iOS:使用代理模式監聽開關狀態改變事件


記一次解決跨控制器監聽開關狀態改變的嘗試。

  為了統一設置UITableViewCell里的內容,自定義了UITableViewCell類的一個基類,命名為SettingCell。SettingCell里顯示的內容由數據模型SettingItem提供:在SettingCell里定義一個屬性即可。

@property (nonatomic, strong) SettingItem *item;

  再定義幾個SettingItem的子類表示顯示不同內容的Cell(如圖1).由於所有開關狀態的歸檔和解檔都一樣,故統一在父類SettingItem里實現。但是點擊“手勢密碼”后跳轉到下一個控制(如圖2)后,需要單獨監聽手勢密碼開關的狀態,這就涉及到了跨控制器監聽開關狀態改變事件的問題。我首先想到了代理模式。

                                       

                                                        圖1                                                             圖2

 

  首先在SettingCell.h里聲明代理方法和屬性:

 1 #import <UIKit/UIKit.h>
 2 
 3 @class SettingItem, SettingCell;
 4 
 5 @protocol SettingCellDelegate <NSObject>
 6 
 7 @optional
 8 
 9 // 監聽開關狀態改變
10 - (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView;
11 
12 @end
13 
14 @interface SettingCell : UITableViewCell
15 
16 // 存放模型數據
17 @property (nonatomic, strong) SettingItem *item;
18 
19 @property (nonatomic, assign, getter = isLastRowInSection) BOOL lastRowInSection;
20 
21 + (instancetype)cellWithTableView:(UITableView *)tableView;
22 
23 // 定義代理屬性
24 @property (nonatomic, weak) id<SettingCellDelegate> delegate;
25 
26 @end

  然后,在SettingCell.m里初始化開關並注冊ValueChanged事件,在switchStateChange:方法里調用代理方法傳遞開關狀態:

 1 - (UISwitch *)switchView
 2 {
 3     if (_switchView == nil) {
 4         _switchView = [[UISwitch alloc] init];
 5         [_switchView addTarget:self action:@selector(switchStateChange:) forControlEvents:UIControlEventValueChanged];
 6     }
 7     return _switchView;
 8 }
 9 
10 /**
11  *  監聽開關狀態改變
12  */
13 - (void)switchStateChange:(UISwitch *)switchView
14 {
15 //    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
16 //    [defaults setBool:self.switchView.isOn forKey:self.item.title];
17 //    [defaults synchronize];
18     if ([self.delegate respondsToSelector:@selector(settingCell:switchChanged:)]) {
19         [self.delegate settingCell:self switchChanged:switchView];
20     }
21     
22     [CoreArchive setBool:self.switchView.isOn key:self.item.title];
23 }

  最后,在圖2的控制器里實現代理方法:

1 - (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView
2 {
3     NSLog(@"手勢密碼開關狀態改變了-------------------");
4 }

  但是發現點擊開關后並沒有發現打印結果,窘迫~

  檢查代理模式的使用方法后發現是沒有設置SettingCell的代理為當前控制器(GestureViewController)。問題又來了,在圖2的控制器里我根本拿不到SettingCell,無奈只好追本溯源,發現這個控制器又是繼承自自定義的一個控制器(BaseSettingViewController),故在父類控制器里的Cell初始化方法里設置代理為當前控制器即可(下面代碼第11行)。於是開心地看到打印結果鳥!

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     // 1.創建cell
 4     SettingCell *cell = [SettingCell cellWithTableView:tableView];
 5     
 6     // 2.給cell傳遞模型數據
 7     SettingGroup *group = self.data[indexPath.section];
 8     cell.item = group.items[indexPath.row];
 9     cell.lastRowInSection =  (group.items.count - 1 == indexPath.row);
10     // 設置代理
11     cell.delegate = self;
12     // 3.返回cell
13     return cell;
14 }

總結思路:

  • 涉及到跨控制器數據訪問時首先考慮代理模式;
  • 當類的繼承關系復雜時一定要縷清關系:什么事在基類里統一做,什么事在子類里單獨做。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM