2022-06-20 iOS mvvm及rac的应用总结

viewModel 代码

@interface ZJEditProfileViewModel : NSObject
@property (nonatomic, copy)   NSString *strNickName;
@property (nonatomic, copy)   NSString *strNickNameFlag;
@property (nonatomic, strong) RACSignal *btnEnableSignal;
@property (nonatomic, strong) RACCommand *saveCommand;
@end

@implementation ZJEditProfileViewModel
- (instancetype)init
{
    self = [super init];
    if (self) {
        [self setUp];
    }
    return self;
}

- (void)setUp{
    @weakify(self);
    _btnEnableSignal = [RACSignal combineLatest:@[RACObserve(self,strNickName)] reduce:^id _Nullable(NSString *nickName){
        return @(nickName.length > 1);
    }];

    _saveCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        @strongify(self);
        return [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
            @strongify(self);
            NSString *registerAccount = [[tztUserSaveDataObj getShareInstance] getUserDataValueForKey:zt_key_internetAccount_regcust_id];
            NSDictionary *userInfo = (NSDictionary *)[[tztUserSaveDataObj getShareInstance] getUserDataObjectForKey:zt_key_internetAccount_userinfo] ?: @{};
            NSMutableDictionary *custInfo = userInfo.mutableCopy;
            [custInfo setObject:JTSafeString(self.strNickName) forKey:@"nick_name"];
            NSDictionary *params = @{ @"regcust_id" : JTSafeString(registerAccount),

                                       @"cust_info" : custInfo};
            [[ZJAppService.loginService.api requestForChangeNickName:params] subscribeNext:^(id tuple) {
                RACTupleUnpack(NSNumber *bSuccess, JTResponseModel *response, NSError *error) = tuple;
                if ([bSuccess boolValue]) {
                    if (!error && response.ret == 0) {
                        [subscriber sendNext:@"请求成功"];
                        NSMutableDictionary *dicUserInfo = (NSMutableDictionary *)[[tztUserSaveDataObj getShareInstance] getUserDataObjectForKey:zt_key_internetAccount_userinfo].mutableCopy;
                        [dicUserInfo setTztValue:self.strNickName ?: @"尊敬的客户" forKey:@"nick_name"];
                        [[tztUserSaveDataObj getShareInstance] setUserDataObject:dicUserInfo ForKey:zt_key_internetAccount_userinfo];
                        
                        NSString *strInfo = [[tztUserSaveDataObj getShareInstance] getUserDataValueForKey:zt_key_internetAccount_info];
                        NSArray *arrayInfo = [strInfo mj_JSONObject];
                        if ([arrayInfo isKindOfClass:NSArray.class] && arrayInfo.count) {
                            NSMutableDictionary *dictInfo = [arrayInfo.firstObject mutableCopy];
                            [dictInfo tztSetObject:dicUserInfo forKey:@"user_info"];
                            [[tztUserSaveDataObj getShareInstance] setUserDataObject:[@[dictInfo ?: @{}] mj_JSONString] ForKey:zt_key_internetAccount_info];
                        }
                     
                    } else {
                        JTSHOW_TIPS(response.errorMsg ?: @"网络错误,请重试");
                    }
                } else {
                    JTSHOW_TIPS(@"网络错误,请重试");
                }
                [subscriber sendCompleted];
            }];
            return [RACDisposable disposableWithBlock:^{
            }];
        }];
    }];

}
@end

VC代码

/// Lazy Methods

- (ZJEditProfileViewModel *)viewModel {
    if (!_viewModel) {
        _viewModel = [ZJEditProfileViewModel new];
    }
    return _viewModel;
}

-(UIView *)headerView
{
    if (_headerView == NULL) {
        _headerView = [[UIView alloc] init];
        _headerView.backgroundColor = (g_nSkinType == tztSkin_White) ? [UIColor whiteColor] : [UIColor colorWithTztRGBStr:@"36,40,58"];
    }
    return _headerView;
}

-(UILabel *)labTitle
{
    if (_labTitle == NULL) {
        _labTitle = [[UILabel alloc] init];
        _labTitle.backgroundColor = [UIColor clearColor];
        _labTitle.text = @"昵称";
        _labTitle.font = [UIFont PingFang:regular FontSize:16];
        _labTitle.textColor = (g_nSkinType == tztSkin_White) ? [UIColor blackColor] : [UIColor colorWithTztRGBStr:@"219,219,219"];
    }
    return _labTitle;
}

- (UITextField *)textFieldNickName
{
    if (_textFieldNickName == NULL) {
        _textFieldNickName = [[UITextField alloc] init];
        _textFieldNickName.borderStyle = UITextBorderStyleNone;
        _textFieldNickName.secureTextEntry = NO;
        _textFieldNickName.keyboardType = UIKeyboardTypeDefault;
        _textFieldNickName.textAlignment = NSTextAlignmentRight;
        _textFieldNickName.textColor = (g_nSkinType == tztSkin_White) ? [UIColor blackColor] : [UIColor colorWithTztRGBStr:@"219,219,219"];
        _textFieldNickName.tintColor = [UIColor colorWithRGBULong:0xD9AD77];
        _textFieldNickName.font = [UIFont PingFang:regular FontSize:16];
        _textFieldNickName.keyboardAppearance = (g_nSkinType == tztSkin_White) ?  UIKeyboardAppearanceLight : UIKeyboardAppearanceDark;
        _textFieldNickName.delegate = self;
        if (self.model.title.length >= 8) {
            _textFieldNickName.text = [self.model.title substringToIndex:8];
        }else {
            _textFieldNickName.text = self.model.title;
        }
        self.viewModel.strNickNameFlag = _textFieldNickName.text;
    }
    return _textFieldNickName;
}

-(UILabel *)lbPrompt
{
    if (_lbPrompt == NULL) {
        _lbPrompt = [[UILabel alloc] init];
        _lbPrompt.backgroundColor = [UIColor clearColor];
        _lbPrompt.font = [UIFont PingFang:regular FontSize:14];
        _lbPrompt.text = @"2-8个字符,支持中文、英文或数字";
        _lbPrompt.textColor = (g_nSkinType == tztSkin_White) ? [UIColor colorWithRGBULong:0x999999] : [UIColor colorWithTztRGBStr:@"98,98,98"];
    }
    return _lbPrompt;
}

- (UIButton *)btnSave
{
    if (_btnSave == NULL) {
        _btnSave= [UIButton buttonWithType:UIButtonTypeCustom];
        [_btnSave.titleLabel setFont:[UIFont PingFang:regular FontSize:16]];
        [_btnSave setBackgroundImage:[UIImage imageNamed:@"jt_phonelogin_jg_submit"] forState:UIControlStateNormal];
        [_btnSave setBackgroundImage: (g_nSkinType == tztSkin_White) ? [UIImage imageNamed:@"jt_phonelogin_jg_submit_disable"] : [UIImage imageNamed:@"jt_phonelogin_jg_submit_black_disable"] forState:UIControlStateDisabled];
        [_btnSave setBackgroundImage:[UIImage imageNamed:@"jt_phonelogin_jg_submit_highlighted"] forState:UIControlStateHighlighted];
        [_btnSave setTitleColor:[UIColor colorWithRed:97 / 255.0 green:63 / 255.0 blue:26 / 255.0 alpha:1.0] forState:UIControlStateNormal];
        [_btnSave setTitleColor: (g_nSkinType == tztSkin_White) ? [UIColor colorWithRed:97 / 255.0 green:63 / 255.0 blue:26 / 255.0 alpha:0.3] : [UIColor colorWithRed:97 / 255.0 green:63 / 255.0 blue:26 / 255.0 alpha:1.0]forState:UIControlStateDisabled];
        [_btnSave setTitle:@"保存" forState:UIControlStateNormal];
    }
    return _btnSave;
}


- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self addSubviews];
    [self addConstraints];
    [self loginEvent];
    [self bindData];
}

- (RACSubject *)setData:(ZJAccountManageModel *)data {
    self.model = data;
    return nil;
}

/// 组装视图
- (void)addSubviews {
    [self.view addSubview:self.headerView];
    [self.headerView addSubview:self.labTitle];
    [self.headerView addSubview:self.textFieldNickName];
    [self.view addSubview:self.lbPrompt];
    [self.view addSubview:self.btnSave];
}

/// 添加约束
- (void)addConstraints {
    [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.tztTitleView.mas_bottom).offset(8);
        make.left.right.equalTo(self.view);
        make.height.mas_equalTo(50);
    }];
    
    [self.labTitle mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.headerView).offset(20);
        make.size.mas_equalTo(CGSizeMake(32, 50));
        make.top.equalTo(self.headerView);
    }];
    
    [self.textFieldNickName mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.headerView).offset(-20);
        make.left.equalTo(self.labTitle.mas_right);
        make.top.equalTo(self.headerView);
        make.height.mas_equalTo(50);
    }];
    
    [self.lbPrompt mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view).offset(20);
        make.top.equalTo(self.headerView.mas_bottom).offset(8);
    }];
    
    [self.btnSave mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.lbPrompt.mas_bottom).offset(26);
        make.right.equalTo(self.view).offset(-20);
        make.left.equalTo(self.view).offset(20);
        make.height.mas_equalTo(50);
    }];
}

/// 建立绑定
- (void)bindData {
    RAC(self.viewModel,strNickName) = self.textFieldNickName.rac_textSignal;
    RAC(self.btnSave,enabled)       = self.viewModel.btnEnableSignal;
}

- (void)loginEvent {
    @weakify(self);
    [[self.textFieldNickName.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
        @strongify(self)
        if (self.textFieldNickName.text.length > 8) {
            self.textFieldNickName.text = [self.textFieldNickName.text substringToIndex:8];
        }
        return value.length <= 8;
    }] subscribeNext:^(NSString * _Nullable x) {
   
    }];
    
    [[self.btnSave rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        @strongify(self);
        if([self.viewModel.strNickNameFlag isEqualToString:self.textFieldNickName.text]){
            [self.navigationController popViewControllerAnimated:YES];
        }else {
            [self.viewModel.saveCommand execute:self.textFieldNickName.text];
        }
    }];

    
    [self.viewModel.saveCommand.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
        @strongify(self)
        JTSHOW_TIPS(@"昵称修改成功");
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            @strongify(self)
            [self.navigationController popViewControllerAnimated:YES];
        });
    }];
    
    [self.viewModel.saveCommand.errors subscribeNext:^(id  _Nullable x) {
        JTSHOW_TIPS(@"昵称修改失败");
        
    }];

}

感悟

1、vc代码

1、声明了个viewModel并将它实例化
2、在loginEvent 和 bindData方法使vc的view和viewModel建立了绑定和连接的关系
3、loginEvent用来响应ui事件和viewModel网络请求的发起和回调
4、bindData将view和viewModel绑定
4.1、view的改变影响viewModel. self.textFieldNickName.rac_textSignal 影响着self.viewModel,strNickName
4.2、viewModel的改变也影响view. self.viewModel.btnEnableSignal 影响着self.btnSave,enabled, 按钮能不能点击就看 self.viewModel.btnEnableSignal 了.

2、viewModel代码

1、处理btnEnableSignal的业务逻辑,vc的self.btnSave点击取决于它,可以看到只有strNickName的长度大于1才能点击,否则就不能点击,而strNickName的值是通过self.textFieldNickName.rac_textSignal的信号过来的,刚好就应对了上面所说的view的改变影响viewModel ,viewModel的改变也影响view.
2、处理网络请求发起和通过信号回调.

你可能感兴趣的:(2022-06-20 iOS mvvm及rac的应用总结)