为 objective-c 制造一个 属性 强的非原子

making one property strong,nonatomic for objective-c

我有一个多视图应用程序并使用一个对象来跟踪我的登录用户。我的 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 正在发布它。如果我错了,请纠正我。

我有两个问题:

  1. 使用此设置,数据为 strong,其余属性为 weak,这是否存在潜在风险?

  2. 我应该把数据做成ivar,其余的保持原样吗?

这些属性的存在没有实际原因(除了我糟糕的 class 设计技巧)。我只是觉得它很有趣,想了解这是怎么回事。

你问过:

  1. With this setup, the data being strong and the rest of the properties being weak, is there any potential risk to this?

是的,如果您 nil dictionary,您的所有属性都可能会变成 nil,假设您在别处没有对它们的其他强引用。

  1. Should I make the data an ivar and keep the rest as is?

我什至不会将其设为 ivar(除非您还没有与我们分享的其他保存要求)。它应该只是一个局部变量,并使您的属性 copy (或 strong)。


我建议 (a) 摆脱 NSDictionary 属性 和 (b) 使 NSString 属性成为 copy(或 strong), 而不是 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 public 接口、声明可空性、字典上的轻量级泛型等),但以上内容可能是一个很好的起点。


顺便说一句,如果你想知道为什么我使用这些 copy 而不是 strong,我们只是想保护自己,以防调用者传递 NSMutableString(这是一个NSString 子类),后来不小心变异了。这只是更安全一点,更具防御性的模式。