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

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

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

@property (nonatomic, strong) SettingItem *item;

  再定義幾個SettingItem的子類表示顯示不一樣內容的Cell(如圖1).因爲全部開關狀態的歸檔和解檔都同樣,故統一在父類SettingItem裏實現。可是點擊「手勢密碼」後跳轉到下一個控制(如圖2)後,須要單獨監聽手勢密碼開關的狀態,這就涉及到了跨控制器監聽開關狀態改變事件的問題。我首先想到了代理模式。spa

                                       

                                                        圖1                                                             圖2代理

 

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

 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:方法裏調用代理方法傳遞開關狀態:blog

 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行)。因而開心地看到打印結果鳥!get

 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 }

總結思路:it

  • 涉及到跨控制器數據訪問時首先考慮代理模式;
  • 當類的繼承關係複雜時必定要縷清關係:什麼事在基類裏統一作,什麼事在子類裏單獨作。
相關文章
相關標籤/搜索