核心问题和思想:
在app开发时,经常会使用到单例,普通的app逻辑如果不太复杂,一般不会涉及到多线程问题,比如单例中的某个属性(常用到的如 账户余额 限时抢购的结束时间),会被多个页面使用到,一般属性我们都是给予noatomic,如果是多线程频繁访问可能会导致crash。更多关于atomic和noatomic了解: noatomic atomic
如果使用了atomic能避免crash,但是也会存在数据不一致的情况。
解决方案Objective-C单向数据流,简单来说就是数据驱动视图,数据的改变被视图监听,一旦数据发生改变,监听该数据的视图都会收到消息然后更新UI。
具体代码实现:
第三方库:Reflow
github地址:Reflow下载地址
demo地址:Objective-C单向数据流方案
一、创建一个类,该类可以设成单例,继承自RFStore
该类将替代视图,直接承担修改数据和读取数据的职能,避免了视图对数据进行直接的操作
//.h声明
@interface BinRFStore : RFStore
+ (instancetype)sharedInstance;
#pragma mark - getter 获取数据
- (NSString *)nickname;
#pragma mark - action 修改数据
- (void)actionChangeNickname:(NSString *)nick;
//类扩展添加属性
@interface BinRFStore ()
@property (nonatomic, strong) BinModel *mode;
@end
//.m实现 单例的创建和数据mode的创建赋值 mode为要操作的数据,不过要通过BinRFStore间接实现,而不是直接操作
+ (instancetype)sharedInstance{
static dispatch_once_t onceToken;
static BinRFStore *instance;
dispatch_once(&onceToken, ^{
instance = [[BinRFStore alloc] init];
});
return instance;
}
- (instancetype)init{
if (self = [super init]){
self.mode = [[BinModel alloc] init];
self.mode.nickname = @"昵称";
self.mode.money = 102.f;
}
return self;
}
//第一次获取数据的方法
- (NSString *)nickname{
return self.mode.nickname;
}
//在Reflow里,我们建议所有的数据修改都要生成新的model对象并替换,而不是直接修改原model对象的属性。更改数据的方法要遵循- (void)actionXXXXXX的格式
//Action是定义在store上的普通方法,action的方法名都以action开头。Reflow会对所有以action开头的方法做特殊处理
- (void)actionChangeNickname:(NSString *)nick{
BinModel *newModel = [[BinModel alloc] init];
newModel.nickname = nick;
self.mode = newModel;
}
//视图监听的实现 只要通过 actionChangeNickname 方法改变了 nickname的值,[binRFStore subscribe:^(RFAction *action) {就会执行,我们就可以在这里更新视图UI了
......
@property (nonatomic, strong) RFSubscription *subscription;
......
BinRFStore *binRFStore = [BinRFStore sharedInstance];
self.subscription = [binRFStore subscribe:^(RFAction *action) {
NSLog(@"%@==%@==%@", NSStringFromSelector(action.selector), action.object, action.arguments);
}];
demo地址:Objective-C单向数据流方案