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