`
啸笑天
  • 浏览: 3465618 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

NSValue对任何结构体,基本类型,指针的封装

 
阅读更多

 

 

任何结构体:

一个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

 

分享到:
评论

相关推荐

    Lecture 3: Objective-C

    - `NSNumber`, `NSValue`, `NSData`, `NSDate`:用于封装数值、基本数据类型、二进制数据和日期时间。 - `NSArray`, `NSDictionary`, `NSSet`:用于集合操作,分别表示数组、字典和集合。 #### 枚举类型 枚举类型...

    cococa图表算法

    但可以通过 `NSValue` 对象来包装这些结构体,并进行存储和检索。 示例代码如下: ```c NSRect newRect = NSMakeRect(20, 20, 100, 100); NSValue *rectObject = [NSValue valueWithRect:newRect]; NSMutableArray...

    kv0的原理和使用

    - **属性类型**:KVO不支持基本数据类型的属性,只能用于Objective-C对象或者使用`NSValue`封装的基本类型。 ### KVO的例子 在实际应用中,KVO常用于界面的实时更新。例如,一个模型对象的属性值改变时,对应的界面...

    ios开发知识点

    - **NSValue**: 用于封装基本类型值,如指针或结构体。 **5. category、extension、protocol** - **category**: 一种扩展类的方法,可以在不修改原有类源码的情况下添加新的方法或属性。 - **extension**: 在Swift...

    FrameWork +ios

    - **T**: `NSDictionary` 存储的是对象,不支持 C 语言的基本数据类型。 **3.2 NSString** - **T**: `NSString` 是面向对象的字符串类,负责存储 null 结尾的字符数组。 **3.3 分布式通知中心** - **T**: 分布式...

    UIKit 帮助文档

    NSValue用于存储基本数据类型,如浮点数、整数和指针等。UIKit Additions为NSValue提供了额外的方法,使其能够更好地与其他UI元素(如控件和视图)进行交互。 ##### 7. UIAcceleration 和 UIAccelerometer ...

    iOS 给已有类添加属性

    对于基本类型,可以使用NSValue封装。 2. **添加iVar**:使用Runtime的`class_addIvar()`函数向类中添加实例变量。例如,要添加一个名为`age`的整型属性,可以这样写: ```objc Class class = [YourClass class];...

    iOS8-Swift-ObjectiveC混编开发Framework

    然而,可以定义一个Objective-C兼容的类作为桥接,或者使用NSValue和NSManagedObject等Objective-C类来封装Swift值类型。 此外,可能会讲解如何调试和测试混编代码。Xcode提供了强大的调试工具,如断点、变量观察...

    ios kvo kvc 编程

    - 结构体需要通过`NSValue`包装。 - 数字类型的属性需要通过`NSNumber`包装。 - 开发者应该实现`setNilValueForKey:`方法来处理`nil`值的情况。 #### Key-Value Observing (KVO) KVO是一种允许对象观察其他对象...

    UIKit_Framework_Reference

    9. NSValue UIKit Additions Reference:NSValue类用于封装无法直接存储在属性列表中的数据类型。UIKit对其进行了扩展,提供了更多与用户界面相关值的封装方法。 10. UIAcceleration Class Reference和...

    ObjectiveC 最经典最全的基础库

    `NSValue`类用于封装基本数据类型,使其可以存储在`NSArray`或`NSDictionary`中。 以上就是Objective-C基础库中关于字符串、数组和字典操作的基本方法,掌握这些知识对于进行iOS应用开发至关重要。每一种方法都有其...

    iOS动画--基础动画

    Core Animation支持多种类型的动画,包括基本动画(Basic Animation)、关键帧动画(Keyframe Animation)、上下文动画(Contextual Animation)等。其中,基本动画是最常用的类型,它通过设置动画的起点、终点和...

    IOS 开发总结

    - NSValue类:说明了如何使用NSValue类来表示其他值,如结构体或C语言数据类型。 - 判断对象等价性:介绍了如何判断两个对象是否相等。 - nil的操作:解释了在Objective-C中nil的特殊行为和用途。 2. iOS特定...

    ObjectiveC程序设计Foundation框架PPT教案学习.pptx

    Foundation框架还包括了处理几何数据结构的类别,如NSValue,可以封装各种基础数据类型,包括CGGeometry中的点、矩形和大小等。这在进行界面布局和动画计算时非常有用。 在Mac OS X中,Foundation框架与Application...

    iOS 基本动画、关键帧动画、利用缓动函数实现物理动画效果

    在iOS应用开发中,基本动画、关键帧动画以及利用缓动函数实现的物理动画效果是三种常见的动画类型,它们可以帮助开发者实现各种复杂的视觉效果。 首先,我们来看基本动画(CABasicAnimation)。基本动画是最简单的...

    Apparent:愚蠢的 Swift µFramework 用于 Swift 处理愚蠢的 UIAppearance 的愚蠢方式

    4. 使用泛型和类型擦除,确保这些外观设置可以应用于任何遵循`UIAppearance`协议的类。 通过Apparent,开发者可以编写出更清晰、更易读的代码,同时也减少了因为类型转换和错误处理导致的潜在问题。这对于大型项目...

    iOS中的集合该如何弱引用对象示例详解

    前言 本文主要给大家介绍了关于iOS集合弱引用对象的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 1. 使用 NSValue ...以上三个类型的用法分别对应 NSMutableArray,NSMutableDic

    简单的3D动画效果

    首先,`CATransform3D`是Core Animation框架中的一个结构体,用于表示3D变换。它提供了对对象进行旋转、平移、缩放和倾斜等3D操作的能力。`CATransform3D`包含了16个浮点数,按照列优先的顺序排列,这16个值构成了4x...

Global site tag (gtag.js) - Google Analytics