NSValue对任何结构体,基本类型,指针的封装
来源:互联网 发布:excel数据左上角 编辑:程序博客网 时间:2024/06/05 00:16
任何结构体:
一个NSValue对象是用来存储一个C或者Objective-C数据的简单容器。它可以保存任意类型的数据,比如int,float,char,当然也可以是指pointers, structures, and object ids。NSValue类的目标就是允许以上数据类型的数据结构能够被添加到集合里,例如那些需要其元素是对象的数据结构,如NSArray或者NSSet的实例。需要注意的是NSValue对象一直是不可枚举的。
我们可以使用NSValue来辅助我们实现一些简单数据结构的封装。比如我们定义了一个简单的结构体类型
typedef struct{ int id; unsigned char flag;}TestStruct;
TestStruct test;
NSValue *value=[NSValue valueWithBytes:&test objCType:@encode(TestStruct)];//对结构体进行封装,,test是基本数据的值,TestStruct是我们要转化的类型
在我们想取出*value 中的数据时,可以使用如下方式:
TestStruct test2;//声明test2,为了得到test1的值
[value getValue:&test2];//同类型赋值
一些结构体的封装:
@interface NSValue (NSValueUIGeometryExtensions)+ (NSValue *)valueWithCGPoint:(CGPoint)point;+ (NSValue *)valueWithCGVector:(CGVector)vector;+ (NSValue *)valueWithCGSize:(CGSize)size;+ (NSValue *)valueWithCGRect:(CGRect)rect;+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;+ (NSValue *)valueWithUIEdgeInsets:(UIEdgeInsets)insets;+ (NSValue *)valueWithUIOffset:(UIOffset)insets NS_AVAILABLE_IOS(5_0);- (CGPoint)CGPointValue;- (CGVector)CGVectorValue;- (CGSize)CGSizeValue;- (CGRect)CGRectValue;- (CGAffineTransform)CGAffineTransformValue;- (UIEdgeInsets)UIEdgeInsetsValue;- (UIOffset)UIOffsetValue NS_AVAILABLE_IOS(5_0);@end
基本类型:
int count = 10;
NSValue *value = [NSValue valueWithBytes:&count objCType:@encode(int)];
其实基础类型,包括bool,char类型可以有NSValue的子类NSNumber去封装
从字典中取出的NSNumber无法通过isKindOfClass判断具体的数据类型,可以使用@encode来判别
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],@"key1",[NSNumber numberWithDouble:1.00f],@"key2",[NSNumber numberWithInt:1],@"key3",[NSNumber numberWithFloat:33.0f], @"key4", nil]; for(NSString *key in dic){ id value = [dic valueForKey:key]; if([value isKindOfClass:[NSNumber class]]){ const char * pObjCType = [((NSNumber*)value) objCType]; NSLog(@"%s",pObjCType); if (strcmp(pObjCType, @encode(int)) == 0) { NSLog(@"字典中key=%@的值是int类型,值为%d",key,[value intValue]); } if (strcmp(pObjCType, @encode(float)) == 0) { NSLog(@"字典中key=%@的值是float类型,值为%f",key,[value floatValue]); } if (strcmp(pObjCType, @encode(double)) == 0) { NSLog(@"字典中key=%@的值是double类型,值为%f",key,[value doubleValue]); } if (strcmp(pObjCType, @encode(BOOL)) == 0) { NSLog(@"字典中key=%@的值是bool类型,值为%i",key,[value boolValue]); } } }
指针:
@interface NSValue (NSValueExtensionMethods)+ (NSValue *)valueWithNonretainedObject:(id)anObject;@property (nonatomic, readonly) id nonretainedObjectValue;+ (NSValue *)valueWithPointer:(const void *)pointer;- (void *)pointerValue;- (BOOL)isEqualToValue:(NSValue *)value;@end
+ (NSValue *)valueWithPointer:(const void *)pointer;
- (void *)pointerValue;
保存对象指针
NSObject * baseObj = [[NSObject alloc] init];
NSValue * value = [NSValue valueWithPointer:baseObj];
NSObject *base = [value pointerValue];
+ (NSValue *)valueWithNonretainedObject:(id)anObject;
@property (nonatomic, readonly) id nonretainedObjectValue;
NSValue 的valueWithNonretainedObject 和 nonretainedObject 来对弱引用进行封装。
在项目中有某个功能需要用到多个delegate对象,这就需要把delegate放到容器中,但又不想保存强引用导致delegate对象不能被释放。所以希望能在容器中只保存delegate对象的弱引用,就可以用此方法。但是容次必须是弱引用容器,例如:
[NSHashTable weakObjectsHashTable]
[NSPointerArray weakObjectsPointerArray]
[NSPointerArray pointerArrayWithOptions:]
假如使用了NSArray,虽然不会阻止对象的释放,但是对象释放后nonretainedObject 返回的并不是nil。
当然也可以自己实现一个弱引用的封装:
由于我只是想要一个set,没找到支持弱引用的set容器。所以我就使用第二个方法定义了WeakReferenceWrapper 来对弱引用进行封装。上代码:
==============================================
@interface WeakReferenceWrapper : NSObject+(id) wrapNonretainedObject:(id)obj;-(id) init;-(id) initWithNonretainedObject:(id)obj;-(id) get;-(BOOL) isEqual:(id)object;-(NSUInteger)hash;@end@implementation WeakReferenceWrapper { __weak id weakReference;}+(id) wrapNonretainedObject:(id)obj { return [[WeakReferenceWrapper alloc] initWithNonretainedObject:obj];}-(id) init { return [self initWithNonretainedObject:nil];}-(id) initWithNonretainedObject:(id)obj { self = [super init]; if (self) { weakReference = obj; } return self;}-(id) get { return weakReference;}-(BOOL) isEqual:(id)object { if (!object) { return NO; } if (![object isKindOfClass:[self class]]) { return NO; } WeakReferenceWrapper* other = (WeakReferenceWrapper*) object; return ([self get] == [other get]);}-(NSUInteger)hash { if (weakReference) { return [weakReference hash]; } return 0;}@end==============================================测试代码如下: @interface Foo: NSObject-(id) init;-(void) dealloc;@end@implementation Foo-(id) init { self = [super init]; NSLog(@"init"); return self;}-(void) dealloc { NSLog(@"dealloc");}@endint main(int argc, const char * argv[]){ @autoreleasepool { NSMutableSet* foos = [[NSMutableSet alloc] init]; Foo* foo1 = [[Foo alloc] init]; WeakReferenceWrapper* weakFoo1 = [WeakReferenceWrapper wrapNonretainedObject:foo1]; NSLog(@"%d", [foos containsObject:weakFoo1]); [foos addObject:weakFoo1]; NSLog(@"%d", [foos containsObject:weakFoo1]); for (WeakReferenceWrapper* value in foos) { NSLog(@"%p", [value get]); } { Foo* foo2 = [[Foo alloc] init]; [foos addObject:[WeakReferenceWrapper wrapNonretainedObject:foo2]]; for (WeakReferenceWrapper* value in foos) { NSLog(@"%p", [value get]); } } for (WeakReferenceWrapper* value in foos) { NSLog(@"%p", [value get]); } } return 0;}
===========================================================
一定要注意的是:如果WeakReferenceWrapper 指向的对象被析构了。WeakReferenceWrapper 对象本身不会设置为nil,而是get方法返回nil。这是因为容器类中保存的是WeakReferenceWrapper 强引用,WeakReferenceWrapper 保存的是对象的弱引用。
感谢:http://blog.sina.com.cn/s/blog_48d4cf2d0102v1jh.html
http://www.cocoachina.com/industry/20140122/7735.html
- NSValue对任何结构体,基本类型,指针的封装
- nsvalue与结构体,指针和一些基本类型互转
- NSValue封装自定义的结构体
- 用NSNumber和NSValue基本数据类型和结构体的封装
- OC学习:OC_中基本数据类型和结构体的封装(NSNumber继承与NSValue)
- OC-052.NSValue 结构体类型的包装类
- 结构体对函数指针的高级封装应用
- 用NSValue封装C或C++的对象(结构…
- NSValue包装对象指针,CGRect结构体等
- NSValue包装对象指针,CGRect结构体等
- NSValue包装对象指针,CGRect结构体等
- NSValue包装对象指针,CGRect结构体等
- 结构体和NSValue的转换
- 如何使用NSValue 类型包含C结构体
- NSValue包装结构体
- NSValue包装结构体
- NSNumber与NSValue封装非object类型
- 指向结构体类型数据的指针
- bash的配置文件~.profile
- Android跳转系统应用
- 黑幕背后的Autorelease
- Python笔记
- footer至于底部的四种方法
- NSValue对任何结构体,基本类型,指针的封装
- Scala入门到精通——第二十八节 Scala与JAVA互操作
- 访问控制符
- 微信检测工具 微信筛选技巧
- 在Swift中检查API的可用性
- Linux arm tftp 以及nfs 的调试方法使用
- Swift 多范式编程语言(对象,函数,协议)
- sklearn集成方法之一随机森林
- 从VC6升级到vs2010需要修改的部分经验交流