首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

ReactiveCocoa (RAC) 訊號實戰:UI 控件綁定、登入驗證、計時器與 Cell 重用管理

     編輯:Java 相關知識

前言

ReactiveCocoa (RAC) 是 iOS/Mac 函數式回應式編程框架,核心是訊號代表隨時間變化的值。本文透過四大實戰場景展示 RAC 如何簡化 UI 邏輯。

場景一:UISlider 三原色調色板


// 三個 Slider 的值變化訊號
RACSignal *r = [self.redSlider rac_newValueChannelWithNilValue:@0].startWith:@0;
RACSignal *g = [self.greenSlider rac_newValueChannelWithNilValue:@0].startWith:@0;
RACSignal *b = [self.blueSlider rac_newValueChannelWithNilValue:@0].startWith:@0;

// 合併最新值
RACSignal *rgb = [RACSignal combineLatest:@[r, g, b] reduce:^id(NSNumber *r, NSNumber *g, NSNumber *b) {
    return @[r, g, b];
}];

// 訂閱更新 View 背景色
[rgb subscribeNext:^(NSArray *arr) {
    self.colorView.backgroundColor = [UIColor colorWithRed:[arr[0] floatValue]/255.0
                                                      green:[arr[1] floatValue]/255.0
                                                       blue:[arr[2] floatValue]/255.0
                                                      alpha:1.0];
}];

關鍵:startWith:@0 確保初始值存在,否則需三個滑桿都動一下才觸發。

場景二:登入按鈕啟用邏輯(多條件組合)


// 帳號、密碼、同意條款三個訊號
RACSignal *account = self.accountField.rac_textSignal;
RACSignal *password = self.passwordField.rac_textSignal;
RACSignal *agree = self.agreeSwitch.rac_newOnChannel; // UISwitch 專用

// 組合驗證
RAC(self.loginButton, enabled) = [RACSignal combineLatest:@[account, password, agree]
    reduce:^id(NSString *acc, NSString *pwd, NSNumber *on) {
        return @(acc.length > 2 && pwd.length > 2 && [on boolValue]);
    }];

一行程式碼取代傳統多個 addTarget、旗標變數、if-else 判斷。

場景三:計時器標籤自動更新


RAC(self.timeLabel, text) = [[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]]
    startWith:[NSDate date]]
    map:^id(NSDate *date) {
        NSDateComponents *c = [[NSCalendar currentCalendar] components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:date];
        return [NSString stringWithFormat:@"%02ld:%02ld:%02ld", c.hour, c.minute, c.second];
    }];

interval: 每秒發送當前日期,map 轉換為格式化字串,自動綁定 Label 文字。

場景四:UITableViewCell / UICollectionViewCell 重用時訊號清理


// Cell 內部按鈕點擊
[[[cell.replyButton rac_signalForControlEvents:UIControlEventTouchUpInside]
    takeUntil:cell.rac_prepareForReuseSignal] // 關鍵:重用前自動取消訂閱
subscribeNext:^(UIButton *btn) {
    [self.navigationController pushViewController:[ReplyViewController new] animated:YES];
}];

// CollectionView Cell 變色
[[[cell.changeButton rac_signalForControlEvents:UIControlEventTouchUpInside]
    takeUntil:cell.rac_prepareForReuseSignal]
subscribeNext:^(UIButton *btn) {
    cell.backgroundColor = [UIColor grayColor];
}];

takeUntil: 監聽 rac_prepareForReuseSignal,Cell 進入重用池前自動發送 completed 終止訂閱,避免舊訂閱作用於新資料。

常用 UI 控件 RAC 擴充速查

控件訊號屬性/方法說明
UITextField.rac_textSignal文字變化訊號
UISlider.rac_newValueChannelWithNilValue:值變化(含初始 nil 處理)
UISwitch.rac_newOnChannel開關狀態變化
UISegmentedControl.rac_newSelectedSegmentIndexChannelWithNilValue:選中索引變化
UIDatePicker.rac_newDateChannelWithNilValue:日期變化
UIButton.rac_signalForControlEvents:指定事件訊號
UITableViewCell.rac_prepareForReuseSignal即將重用訊號
UIViewController.rac_willDeallocSignal即將銷毀訊號

RAC 訊號建構源碼洞察


// rac_textSignal 簡化實現
- (RACSignal *)rac_textSignal {
    @weakify(self);
    return [[[[RACSignal defer:^{ @strongify(self); return [RACSignal return:self]; }]
        concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]]
        map:^(UITextField *x) { return x.text; }]
        takeUntil:self.rac_willDeallocSignal] // 自動清理
        setNameWithFormat:@"%@ -rac_textSignal", self.rac_description;
}

// rac_signalForControlEvents 核心
- (RACSignal *)rac_signalForControlEvents:(UIControlEvents)events {
    @weakify(self);
    return [[RACSignal createSignal:^(id subscriber) {
        @strongify(self);
        [self addTarget:subscriber action:@selector(sendNext:) forControlEvents:events];
        [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{
            [subscriber sendCompleted];
        }]];
        return [RACDisposable disposableWithBlock:^{
            @strongify(self);
            [self removeTarget:subscriber action:@selector(sendNext:) forControlEvents:events];
        }];
    }] setNameWithFormat:@"%@ -rac_signalForControlEvents: %lx", self.rac_description, (unsigned long)events];
}

可見 RAC 內部自動管理目標釋放、訂閱生命週期,開發者無需手動移除 Target。

結語

RAC 以訊號組合、轉換、綁定三大核心操作,將命令式的「狀態管理 + 事件回調」轉化為宣告式的「資料流描述」。掌握 combineLatest、map、takeUntil、RAC(target, property) 四大招式,即可輕鬆駕馭複雜 UI 互動邏輯。雖 Swift 時代多用 Combine/RxSwift,但 RAC 思想在維護舊專案、理解響應式本質上仍具參考價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved