任何结构体:
一个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"); } @end int 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
相关推荐
前言 本文主要给大家介绍了关于iOS集合弱引用对象的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 1. 使用 NSValue ...以上三个类型的用法分别对应 NSMutableArray,NSMutableDic
OCMock-块测试 ### 特征 [OCMArg invokeBlock] 特定于块参数的约束。... 非Objective-C对象的参数值(例如,基元,结构,指针)必须装在NSValue 。 使用OCMOCK_VALUE可以方便地执行此操作。 在OCMDefault中传递
FastCoder支持比JSON或Plist编码更多的数据类型(包括NSURL,NSValue,NSSet和NSOrderedSet),并且允许将所有受支持的对象类型用作字典中的键,而不仅仅是字符串。 FastCoder还可以使用属性检查自动序列化您的...
CDrawNode-Bezier ... [NSValue valueWithCGPoint:ccp(50,100)], [NSValue valueWithCGPoint:ccp(100,50)], [NSValue valueWithCGPoint:ccp(150,75)], [NSValue valueWithCGPoint:ccp(200,200)], [N
DHS散点图 用于在iOS和OS X上基于属性驱动的简单散点... 要绘制的数据以NSValue对象数组的NSValue提供, NSValue对象包装了包含要绘制的(x,y)坐标的CGPoint结构。 DHScatterGraphView *scatterGraph = [[DHScatterG
NSValue *value = [NSValue valueWithRange:range]; if (range.length > 0) { [rangeArray addObject:value]; } } for (NSValue *value in rangeArray) { NSRange keyRange = [value rangeValue]; ...
教程套件 TutorialKit 是一个用于创建交互式... NSValue *msgPoint = [ NSValue valueWithCGPoint: CGPointMake ( self .window.bounds.size.width * 0.5 , self .window.bounds.size.height * 0.65 )]; NSValue *
FNMatchPull Swift的基于匹配字符和模式刷新控件。 简体中文是这里。 安装 通过安装 。 pod 'FNMatchPull' , '~> 0.2' 演示: ... let matchAnimator = ...matchAnimator.endPoints = [NSValue.init(CG
《Objective-C程序设计》(作者杨正洪、郑齐心、李建国)通过大量的实例系统地介绍了Objective-C语言的基本概念、语法规则、框架、类库及开发环境。读者在阅读本书后,可以掌握Objective-C语言的基本内容,并进行...
然后设置lineData属性: self.graphView.lineData = @[ @[ [NSValue valueWithCGPoint:CGPointMake(1, 20)], [NSValue valueWithCGPoint:CGPointMake(2, 40)], [NSValue valueWithCGPoint:CGPointMake(3, 20)], [N
FDModel是一个Objective-C模型层,旨在极大地简化从远程对象(即NSDictionary,NSString,NSValue)创建模型对象的过程。 用户只需要在其FDModel的子类中重写remoteKeyPathsToLocalKeyPaths方法即可定义哪些远程键...
NSArray points = @[[ NSValue valueWithCGPoint: CGPointMake ( 60 , 40 )], [ NSValue valueWithCGPoint: CGPointMake ( 20 , 35 )], [ NSValue valueWithCGPoint: CGPointMake ( 63 , 67 )] /* ... */ ]; ...
概要 iOS曲线插值包含两个主要组件: UIBezierCurvePath上的类别,UIBezierCurvePath + Interpolation。 演示类别使用情况的小型iOS应用。 例子 ...[array addObject:[NSValue valueWithBytes:& CG
@{@"frame": [NSValue valueWithCGRect:frame1], @"string": @"A beautiful item 1" }, @{@"frame": [NSValue valueWithCGRect:frame3], @"string": @"A beautiful item 2" } ]; } completion:^{ // Some ...
II自动NS编码 没有所有样板代码的情况下,使对象符合NSSecureCoding的要求。 您的对象可序列化,您不必编写繁琐且难以维护的编码/解码代码。...@property ( nonatomic , strong ) NSValue *aValue; @end @inter
Interface Builder,App Store,framework,dot notation,initialization,object typing,introspection,selector,foundation framework,NSString,NSMutableString,NSNumber,NSDictionary,NSValue,NSData...
// pointArray = @[[NSValue valueWithCGPoint:CGPointMake(200, 400)]]; -( void )drawPolygon:( NSArray *)pointArray; //圆形 -( void )drawCircleWithCenter:( CGPoint )center radius:( float )radius; //曲线...
XSpotLight XSportLight *SportLight = [[XSportLight alloc ]init]; SportLight.messageArray = @[ @"这是《简书》 " , @"点这里撰写文章" , ...[ NSValue valueWithCGRect: CGRectMake (SCREEN_WIDTH/ 2 , SCREE