iOS难点总结iOS学习小知识点

iOS中的限定符

2017-07-04  本文已影响74人  六度Space

一、变量限定符

ARC为变量提供了四种生命周期限定符

使用这些限定符的基本格式如下:

变量类型 * 限定符类型 变量名

举例说明如下:

    /**
     创建对象后,引用计数为1,并且对象p1在引用期间不会被回收
     */
    Person * __strong p1 = [[Person alloc] init];
    /**
     创建对象后,引用计数为0,对象会被立即释放,且对象p2被置为nil
     */
    Person * __weak p2 = [[Person alloc] init];
    /**
     创建对象后,引用计数为1,对象会被立即释放,但p3不会被置为nil
     */
    Person * __unsafe_unretained p3 = [[Person alloc] init];
    /**
     创建对象后,引用计数为1,当方法返回时,对象会被立即释放
     */
    Person * __autoreleasing p4 = [[Person alloc] init];

二、属性限定符

属性限定符一共有六个:

【注意】 因为assignunsafe_unretained只进行值复制并没有任何实质性的检查,所以他们只应该用于值类型(BOOLNSInteger等),应避免将他们用于引用类型,尤其是指针类型,如(NSString *UIView *等)

限定符在开发中的使用

一、照片模型

创建一个名为YSTPhoto类,里面titleurlcomments等等属性,同时在类.m文件里实现它的dealloc方法,来观察对象从创建到最终释放的生命周期过程。

新建YSTPhoto类,提供3个属性值

@interface YSTPhoto : NSObject

/**
 照片的url地址
 */
@property (nonatomic, strong) NSURL *url;

/**
 照片的名字
 */
@property (nonatomic, copy) NSString *title;

/**
 照片的评论数
 */
@property (nonatomic, strong) NSArray *comments;

@end
@implementation YSTPhoto

- (void)dealloc{
    NSLog(@"YSTPhoto is dealloced!");
}

@end

二、绑定插座变量

Storyboard中添加一个标签resultLabel和四个按钮,然后在ViewController中对按钮进行事件的绑定,每次触发按钮点击事件后,将相应的结果显示在resultLabel上。

故事板

三、方法实现

在每一个方法中做如下事情:

  1. 创建一个YSTPhoto对象,并打印对象;
  2. 设置对象图片的title
  3. resultLabel中显示该对象的引用是否为nil。如果不是nil,则显示title

实现createStrongPhoto方法

- (IBAction)createStrongPhoto:(id)sender {
    //方法一进入的时候打印当前方法名
    NSLog(@"%s enter", __PRETTY_FUNCTION__);
    //__strong 修饰
    YSTPhoto *__strong photo = [[YSTPhoto alloc] init];
    NSLog(@"strong photo: %@", photo);
    photo.title = @"Strong Photo";
    
    NSMutableString *ms = [[NSMutableString alloc] init];
    [ms appendString:(photo == nil? @"Photo is nil" : @"Photo is not nil")];
    [ms appendString:@"\n"];
    if (photo != nil) {
        [ms appendString:photo.title];
    }
    self.resultLabel.text = ms;
    //方法执行结束前打印当前方法名
    NSLog(@"%s exit", __PRETTY_FUNCTION__);
}

/**
打印结果如下:
 2017-07-04 17:28:13.370 变量限定符的使用[8550:287995] -[ViewController createStrongPhoto:] enter
2017-07-04 17:28:13.370 变量限定符的使用[8550:287995] strong photo: <YSTPhoto: 0x608000220540>
2017-07-04 17:28:13.371 变量限定符的使用[8550:287995] -[ViewController createStrongPhoto:] exit
2017-07-04 17:28:13.371 变量限定符的使用[8550:287995] YSTPhoto is dealloced!
 */

实现createWeakPhoto方法

- (IBAction)createWeakPhoto:(id)sender {
    NSLog(@"%s enter", __PRETTY_FUNCTION__);
    YSTPhoto *__weak photo = [[YSTPhoto alloc] init];
    NSLog(@"weak photo: %@", photo);
    photo.title = @"Weak Photo";
    NSMutableString *ms = [[NSMutableString alloc] init];
    [ms appendString:(photo == nil? @"Photo is nil" : @"Photo is not nil")];
    [ms appendString:@"\n"];
    if (photo != nil) {
        [ms appendString:photo.title];
    }
    self.resultLabel.text = ms;
    NSLog(@"%s exit", __PRETTY_FUNCTION__);
}

/**
打印结果如下:
2017-07-04 17:36:20.692 变量限定符的使用[8690:293630] -[ViewController createWeakPhoto:] enter
2017-07-04 17:36:20.693 变量限定符的使用[8690:293630] YSTPhoto is dealloced!
2017-07-04 17:36:20.693 变量限定符的使用[8690:293630] weak photo: (null)
2017-07-04 17:36:20.694 变量限定符的使用[8690:293630] -[ViewController createWeakPhoto:] exit
*/

实现createStrongToWeakPhoto方法

- (IBAction)createStrongToWeakPhoto:(id)sender {
    NSLog(@"%s enter", __PRETTY_FUNCTION__);
    YSTPhoto *__strong sphoto = [[YSTPhoto alloc] init];
    NSLog(@"Strong Photo: %@", sphoto);
    sphoto.title = @"Strong Photo, Assigned to weak";
    YSTPhoto *__weak wphoto = sphoto;
    NSLog(@"Weak Photo: %@", wphoto);
    
    NSMutableString *ms = [[NSMutableString alloc] init];
    [ms appendString:(wphoto == nil? @"Photo is nil" : @"Photo is not nil")];
    [ms appendString:@"\n"];
    if (wphoto != nil) {
        [ms appendString:wphoto.title];
    }
    self.resultLabel.text = ms;
    NSLog(@"%s exit", __PRETTY_FUNCTION__);
}

/**
打印结果如下:
2017-07-04 17:43:49.639 变量限定符的使用[8810:298477] -[ViewController createStrongToWeakPhoto:] enter
2017-07-04 17:43:49.640 变量限定符的使用[8810:298477] Strong Photo: <YSTPhoto: 0x608000031920>
2017-07-04 17:43:49.641 变量限定符的使用[8810:298477] Weak Photo: <YSTPhoto: 0x608000031920>
2017-07-04 17:43:49.641 变量限定符的使用[8810:298477] -[ViewController createStrongToWeakPhoto:] exit
2017-07-04 17:43:49.642 变量限定符的使用[8810:298477] YSTPhoto is dealloced!
*/

实现createUnsafeUnretainedPhoto方法

- (IBAction)createUnsafeUnretainedPhoto:(id)sender {
    NSLog(@"%s enter", __PRETTY_FUNCTION__);
    YSTPhoto *__unsafe_unretained photo = [[YSTPhoto alloc] init];
    NSLog(@"__unsafe_unretained photo: %@", photo);
    photo.title = @"__unsafe_unretained Photo";
    NSMutableString *ms = [[NSMutableString alloc] init];
    [ms appendString:(photo == nil? @"Photo is nil" : @"Photo is not nil")];
    [ms appendString:@"\n"];
    if (photo != nil) {
        [ms appendString:photo.title];
    }
    self.resultLabel.text = ms;
    NSLog(@"%s exit", __PRETTY_FUNCTION__);
}

/**
打印结果如下:
2017-07-04 18:12:05.914 变量限定符的使用[9330:318662] -[ViewController createUnsafeUnretainedPhoto:] enter
2017-07-04 18:12:05.915 变量限定符的使用[9330:318662] YSTPhoto is dealloced!
2017-07-04 18:12:05.915 变量限定符的使用[9330:318662] *** -[YSTPhoto setTitle:]: message sent to deallocated instance 0x60000002bba0
(lldb) 
*/

对以上的测试结果进行分析如下:

  1. __strong引用确保了对象在其作用域内不被销毁,对象只会在方法调用完成后被回收;
  2. __weak引用对引用计数没有贡献,对象会被立即回收,甚至在其被用于紧邻的下一个语句前;
  3. createStrongToWeak方法中,虽然__weak引用不会增加引用计数,但是之前创建的__strong引用确保了对象不会再方法结束前释放;
  4. createUnsafeUnretainedPhoto中,对象会被立即释放,但是由于内存还没有被回收,这个引用还可以使用,不会报错;但是,当再次调用这个对象的时候,内存已经重新分配了,这样就导致了非法访问,程序直接崩溃。在打印结果中,-[YSTPhoto setTitle:]: message sent to deallocated instance 0x60000002bba0这正是因为内存已经被回收了,所以在调用setter方法的时候,就提示找不到。
上一篇 下一篇

猜你喜欢

热点阅读