使一个属性变强,对于目标c非原子性

时间:2019-02-27 00:06:23

标签: ios objective-c automatic-ref-counting

我有一个多视图应用程序,并使用一个对象来跟踪我的登录用户。我的User.h看起来像这样

@interface User : NSObject

@property (strong, nonatomic) NSDictionary *data;

@property (weak, nonatomic) NSString *uid;
@property (weak, nonatomic) NSString *firstName;
@property (weak, nonatomic) NSString *lastName;
@property (weak, nonatomic) NSString *dob;
@property (weak, nonatomic) NSString *gender;
@property (weak, nonatomic) NSString *avatarURL;
@property (assign, nonatomic) NSInteger status;

- (void)setPropertiesWith:(NSDictionary *)data;

User.m看起来像这样

#import "User.h"

@implementation User
/*
 * set properties
 */
- (void)setPropertiesWith:(NSDictionary *)data{
    self.data = data;

    self.uid = self.data[@"uid"];
    self.firstName = self.data[@"firstName"];
    self.lastName = self.data[@"lastName"];
    self.dob = self.data[@"dob"];
    self.gender = self.data[@"gender"];
    self.status = [[self.data valueForKeyPath:@"status"] intValue];
    self.avatarURL = self.data[@"avatarURL"];
}

@end

我的数据很弱,但是在其中一种观点中,它可能会变成空值-我相信ARC正在发布它。如果我错了,请纠正我。

我有2个问题:

  1. 使用此设置,数据为strong,其余属性为weak,这样做有潜在的风险吗?

  2. 我应该将数据设为ivar,其余数据保持原样吗?

没有任何实际原因(除了我的课堂设计技能差)之外。我只是觉得它很有趣,并想了解发生了什么。

1 个答案:

答案 0 :(得分:2)

您问:

  
      
  1. 通过此设置,数据为strong,其余属性为weak,这有潜在的风险吗?
  2.   

是的,如果您nil dictionary,假设您在其他地方没有其他强引用,那么您所有的财产都可能成为nil

  
      
  1. 我应该将数据设为一个ivar,其余数据保持不变吗?
  2.   

我什至都不会将它设为ivar(除非您还没有与我们共享此存储条件,否则还有其他要求)。它应该只是一个局部变量,并让您的属性为copy(或strong)。


我建议(a)放弃NSDictionary属性,并且(b)使NSString属性为copy(或strong),而不是{{ 1}}。另外,我没有定义weak方法,而是定义了一个初始化程序:

setPropertiesWith

// User.h

@interface User : NSObject

@property (copy, nonatomic) NSString *uid;
@property (copy, nonatomic) NSString *firstName;
@property (copy, nonatomic) NSString *lastName;
@property (copy, nonatomic) NSString *dob;
@property (copy, nonatomic) NSString *gender;
@property (copy, nonatomic) NSString *avatarURL;
@property (assign, nonatomic) NSInteger status;

- (instancetype)initWithDictionary:(NSDictionary *)dictionary;

@end

然后,呼叫者会这样做:

// User.m

@implementation User

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if ((self = [super init])) {
        self.uid       = dictionary[@"uid"];
        self.firstName = dictionary[@"firstName"];
        self.lastName  = dictionary[@"lastName"];
        self.dob       = dictionary[@"dob"];
        self.gender    = dictionary[@"gender"];
        self.status    = [dictionary[@"status"] intValue];
        self.avatarURL = dictionary[@"avatarURL"];
    }

    return self;
}

@end

您还可以在这里考虑其他改进(例如User *user = [[User alloc] initWithDictionary:someDictionary]; 公共接口,声明可空性,字典中的轻量级泛型等),但是以上可能是一个很好的起点。


顺便说一句,如果您想知道为什么我制作这些readonly而不是copy,我们只是想保护自己,以防呼叫者通过strong(这是{{ 1}}子类),并在以后意外地对其进行了变异。这只是一个更安全,更防御的模式。