組模型的封裝ios
SettingGroup數組
// // SettingGroup.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 模型,一組(Section,Group),包含 組的header,組的footer,中間的條目(cell數組) #import <Foundation/Foundation.h> @interface SettingGroup : NSObject // 頭部標題 @property (nonatomic, copy) NSString *header; // 中間的條目(SettingItem對象數組) @property (nonatomic, strong) NSArray *items; // 尾部標題 @property (nonatomic, copy) NSString *footer; @end
父類SettingItem緩存
// // SettingItem.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 一個SettingItem模型 相應一個Cell需要的數據源 // 父類,用來描寫敘述當前cell裏面要顯示的內容。描寫敘述點擊cell後作什麼事情 #import <Foundation/Foundation.h> @interface SettingItem : NSObject // 爲一行(cell)提供 圖標名 @property (nonatomic, copy) NSString *icon; // 爲一行(cell)提供 標題 @property (nonatomic, copy) NSString *title; // 爲一行(cell)提供 子標題 @property (nonatomic, copy) NSString *subtitle; // 爲一行(cell)提供 點擊後,要運行的操做 @property (nonatomic, copy) void (^operation)() ; // 點擊cell後要運行的操做 #pragma mark - 類方法,生成模型實例 // 有標題 有圖片的模型 + (id)itemWithIcon:(NSString *)icon title:(NSString *)title; // 僅僅有標題的模型 + (id)itemWithTitle:(NSString *)title; @end
// // SettingItem.m // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 一個SettingItem模型 相應一個Cell需要的數據源 // 父類,用來描寫敘述當前cell裏面要顯示的內容,描寫敘述點擊cell後作什麼事情 #import "SettingItem.h" @implementation SettingItem // 有標題 有圖片的模型 + (id)itemWithIcon:(NSString *)icon title:(NSString *)title { SettingItem *item = [[self alloc] init]; item.icon = icon; item.title = title; return item; } // 僅僅有標題的模型 + (id)itemWithTitle:(NSString *)title { return [self itemWithIcon:nil title:title]; } @end
// // SettingItemArchive.h // 25_彩票 // // Created by beyond on 14-8-29. // Copyright (c) 2014年 com.beyond. All rights reserved. // 中間父類,僅一個成員,key,所有需要歸檔的settingItem的子類(如開關等) 都可以繼承本模型 #import "SettingItem.h" @interface SettingItemArchive : SettingItem // 存儲數據時用的key,取數據時也是用該key @property (nonatomic, copy) NSString *key; @end
// // SettingItemArrow.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 子類 最右邊是箭頭的item數據模型,專業提供數據源,給右邊是箭頭的cell #import "SettingItem.h" @interface SettingItemArrow : SettingItem // 通常帶箭頭的cell,被點擊時候,是要跳到還有一個界面(控制器) @property (nonatomic, assign) Class showVCClass; // 即將顯示的控制器的類名 @end
// // SettingItemSwitch.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 子類 最右邊是【開關】的item數據模型,專業提供數據源,給右邊是開關的cell // 繼承自SettingItemArchive,而SettingItemArchive又繼承自SettingItem #import "SettingItemArchive.h" @interface SettingItemSwitch : SettingItemArchive // 開關需要保存的是狀態,在設置時,就歸檔 @property (nonatomic, assign) BOOL off; @end
// // SettingItemSwitch.m // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // #import "SettingItemSwitch.h" @implementation SettingItemSwitch // 開關需要保存的是狀態,在設置時,就歸檔 - (void)setOff:(BOOL)off { _off = off; [SettingTool setBool:off forKey:self.key]; } - (void)setKey:(NSString *)key { [super setKey:key]; _off = [SettingTool boolForKey:key]; } @end
子類SettingItemLabel
app
// // SettingItemLabel.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 子類 最右邊是【文字】的item數據模型,專業提供數據源,給右邊是Label的cell #import "SettingItemArchive.h" @interface SettingItemLabel : SettingItemArchive // cell右邊顯示的文字,在設置時就要歸檔 @property (nonatomic, copy) NSString *text; @end
// // SettingItemLabel.m // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 子類 最右邊是【文字】的item數據模型,專業提供數據源,給右邊是Label的cell #import "SettingItemLabel.h" @implementation SettingItemLabel // 攔截,cell右邊顯示的文字,賦值時,就必須歸檔 - (void)setText:(NSString *)text { _text = text; // 歸檔 [SettingTool setObject:text forKey:self.key]; } // 爲key賦值的時候,就必須解檔 - (void)setKey:(NSString *)key { [super setKey:key]; _text = [SettingTool objectForKey:key]; } @end
本身定義cell視圖View的封裝 SettingCellide
// // SettingCell.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // view,本身定義cell,接收數據源爲其內部子控件提供數據 #import <UIKit/UIKit.h> // 模型,數據源,爲view cell 提供數據 @class SettingItem; @interface SettingCell : UITableViewCell // 模型,數據源,爲view cell 提供數據 @property (nonatomic, strong) SettingItem *item; // cell所在的組和行號 @property (nonatomic, strong) NSIndexPath *indexPath; // 類方法建立cell實例對象,使用instancetype優勢多多,更加嚴謹,讓編譯器更智能提示錯誤 + (instancetype)settingCellWithTableView:(UITableView *)tableView; @end
// // SettingCell.m // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // view,本身定義cell,接收數據源爲其內部子控件提供數據 #import "SettingCell.h" // 數據源 #import "SettingItem.h" #import "SettingItemSwitch.h" #import "SettingItemArrow.h" #import "SettingItemLabel.h" // 在ios6中,cell的contentView的x是10,所以,要想讓cell全屏寬,必須使用cell左移10,寬度+20 const int MakeCellToLeftBy = 10; @interface SettingCell() { // 每一個進入視野的cell 都循環利用(共用)一個arrow,switch,label UIImageView *_arrowImgView; UISwitch *_switch; UILabel *_label; UIView *_divider; } @end @implementation SettingCell #pragma mark - 生命週期 // 類方法建立cell實例對象,使用instancetype優勢多多,更加嚴謹,讓編譯器更智能提示錯誤 // 先從參數tableView的緩存池中取,取不到,纔要建立 + (instancetype)settingCellWithTableView:(UITableView *)tableView { // 0.用static修飾的局部變量,僅僅會初始化一次 static NSString *ID = @"SettingCell"; // 1.拿到一個標識先去緩存池中查找相應的Cell SettingCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; // 2.假設緩存池中沒有,才需要傳入一個標識建立新的Cell if (cell == nil) { cell = [[SettingCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ID]; } return cell; } // 重寫父類的方法,建立cell實例 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { // 先調用父類的方法 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // 1.設置全局統一的cell背景view [self setupCellBgView]; // 2.設置子控件屬性 [self setupCellLabelBgColor]; // 3.加入cell底部的分隔線(爲了統一,先移除系統自帶的separateLine) [self setupCellUnderLine]; } return self; } #pragma mark - 初始化 屬性設置 #pragma mark 1.設置cell背景view - (void)setupCellBgView { // 1.默認 cell背景view (白色) UIView *bgView = [[UIView alloc] init]; bgView.backgroundColor = [UIColor whiteColor]; self.backgroundView = bgView; // 2.選中 cell背景view (灰色) UIView *selectedBgView = [[UIView alloc] init]; selectedBgView.backgroundColor = kColor(237, 233, 218); self.selectedBackgroundView = selectedBgView; } #pragma mark 2.設置cell內子控件label背景 - (void)setupCellLabelBgColor { // 標題 去其默認的背景 self.textLabel.backgroundColor = [UIColor clearColor]; self.textLabel.font = [UIFont systemFontOfSize:14]; // 子標題 去其默認的背景 self.detailTextLabel.backgroundColor = [UIColor clearColor]; self.detailTextLabel.font = [UIFont systemFontOfSize:12]; } #pragma mark 3.設置分隔線 // 3.加入cell底部的分隔線(爲了統一,先移除系統自帶的separateLine) - (void)setupCellUnderLine { UIView *divider = [[UIView alloc] init]; divider.backgroundColor = kColor(200, 200, 200); // 不能在這裏設置分隔線的x值(緣由:cell沒有詳細的數據,裏面的label就不知道終於的位置) // divider.frame = CGRectMake(0, 0, self.contentView.frame.size.width, 1.5); [self.contentView addSubview:divider]; _divider = divider; } #pragma mark - 攔截setter方法 // 依據所在的組,所在的行號,設置切割線的顯示狀態 - (void)setIndexPath:(NSIndexPath *)indexPath { _indexPath = indexPath; // 設置underLine的可見性,依據該cell所在的indexPath _divider.hidden = indexPath.row == 0; } // 攔截數據源,爲子控件們賦值 - (void)setItem:(SettingItem *)item { _item = item; // 設置數據 self.imageView.image = [UIImage imageNamed:item.icon]; self.textLabel.text = item.title; self.detailTextLabel.text = item.subtitle; // 依據數據源模型的不一樣,建立不一樣的最右邊的accessoryView if ([item isKindOfClass:[SettingItemArrow class]]) { // 1.設置箭頭 [self setAccessoryViewArrow]; } else if ([item isKindOfClass:[SettingItemSwitch class]]) { // 2.設置開關 [self setAccessoryViewSwitch]; } else if ([item isKindOfClass:[SettingItemLabel class]]) { // 3.設置文本 [self setAccessoryViewLabel]; } else { // 什麼也沒有。必須清空右邊顯示的view。因爲cell循環使用 self.accessoryView = nil; // 並且要,還原,使用默認的選中樣式(即可以產生選中效果) self.selectionStyle = UITableViewCellSelectionStyleDefault; } } #pragma mark 設置右邊的箭頭 // 每一個進入視野的cell 都循環利用(共用)一個arrow,switch,label - (void)setAccessoryViewArrow { if (_arrowImgView == nil) { _arrowImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellArrow"]]; } // 右邊顯示箭頭 self.accessoryView = _arrowImgView; // 用默認的選中樣式 self.selectionStyle = UITableViewCellSelectionStyleDefault; } #pragma mark 設置右邊的文本標籤 // 每一個進入視野的cell 都循環利用(共用)一個arrow,switch,label - (void)setAccessoryViewLabel { if (_label == nil) { _label = [[UILabel alloc] init]; _label.bounds = CGRectMake(0, 0, 100, self.frame.size.height); _label.textAlignment = NSTextAlignmentRight; _label.backgroundColor = [UIColor clearColor]; _label.textColor = kColor(173, 69, 14); _label.font = [UIFont systemFontOfSize:13]; } // 設置右邊label的值 SettingItemLabel *labelItem = (SettingItemLabel *)_item; _label.text = labelItem.text; // 右邊顯示子文本 self.accessoryView = _label; // 贊成選中本行 self.selectionStyle = UITableViewCellSelectionStyleDefault; } #pragma mark 設置右邊的開關 // 每一個進入視野的cell 都循環利用(共用)一個arrow,switch,label - (void)setAccessoryViewSwitch { if (_switch == nil) { _switch = [[UISwitch alloc] init]; [_switch addTarget:self action:@selector(switchChange) forControlEvents:UIControlEventValueChanged]; } // 設置開關的狀態 SettingItemSwitch *switchItem = (SettingItemSwitch *)_item; _switch.on = !switchItem.off; // 右邊顯示開關 self.accessoryView = _switch; // 因爲是開關,因此要禁止選中本行 self.selectionStyle = UITableViewCellSelectionStyleNone; } #pragma mark 開關狀態改變 - (void)switchChange { SettingItemSwitch *switchItem = (SettingItemSwitch *)_item; switchItem.off = !_switch.on; } #pragma mark - 當cell的寬高改變了就會調用 // 父類方法,需要調節cell內部子控件的frame,僅僅有在layoutSubviews方法中,才最可靠\最有效 - (void)layoutSubviews { // 必須先調用父類的方法 [super layoutSubviews]; // 0.設置cell分隔線的位置 (從文字處開始) _divider.frame = CGRectMake(self.textLabel.frame.origin.x, 0, self.contentView.frame.size.width + 100, 1.2); if (iOS7) return; // 下面是iOS6,設置cell佔整個屏幕的寬度 [self makeCellFullWidth]; } // 下面是iOS6,設置cell佔整個屏幕的寬度 - (void)makeCellFullWidth { // 在ios6中,cell的contentView的x默認是10,所以,要想讓cell全屏寬,必須使用cell的x左移10,寬度+20,至關於把整個cell,先左平移,再扯寬 // 1.將cell的frame拉寬 CGRect cellF = self.frame; // cell整體先左平移10 cellF.origin.x = -MakeCellToLeftBy; // cell整體寬度再+20,這樣cell的contentView就全屏寬了 CGFloat deltaW = MakeCellToLeftBy * 2; cellF.size.width = [UIScreen mainScreen].bounds.size.width + deltaW; self.frame = cellF; // 2.右邊控件的frame (左移) // accessoryView不屬於contentView, 屬於cell CGRect accessF = self.accessoryView.frame; accessF.origin.x = cellF.size.width - accessF.size.width - deltaW; self.accessoryView.frame = accessF; } @end
BaseSettingControllerpost
// // BaseSettingController.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 父類,內部維護了一個tableView,子類提供數據源數組(GroupsArr) #import <UIKit/UIKit.h> #import "SettingGroup.h" #import "SettingItem.h" // 導入數據模型 // 右側是箭頭的數據模型 #import "SettingItemArrow.h" // 右側是開關的數據模型 #import "SettingItemSwitch.h" // 右邊是子文本 #import "SettingItemLabel.h" // 所有聲明的將要被存儲到沙盒中的key #import "SettingArchiveKeys.h" @interface BaseSettingController : UIViewController<UITableViewDataSource, UITableViewDelegate> { // 開放給子類用,父類僅僅負責初始化,子類負責加入一個個Group對象,一個group模型相應一個section NSMutableArray *_allGroups; // 所有的組模型 } @property (nonatomic, weak, readonly) UITableView *tableView; @end
// // BaseSettingController.m // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 父類,內部維護了一個tableView,子類提供數據源數組(GroupsArr) #import "BaseSettingController.h" #import "SettingCell.h" // 每一個section之間的頂部間距 const int SectionHeaderMargin = 20; @interface BaseSettingController () @end @implementation BaseSettingController // 直接讓tableView就是控制器的view - (void)loadView { // 父類的組數組 初始化放在LoadView方法中,優勢是,子類在viewDidLoad時,就已經擁有初始化的_allGroups,而再也不需要先調用父類的viewDidLoad,而後纔可向數組加入成員 _allGroups = [NSMutableArray array]; // 建立並維護本身的tableView,子類僅需提供數據源 groupsArr 就能夠 [self createTableView]; } // 建立並維護本身的tableView,子類僅需提供數據源 groupsArr 就能夠 - (void)createTableView { UITableView *tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame style:UITableViewStyleGrouped]; // 設置數據源和代理 爲當前父控制器 tableView.delegate = self; tableView.dataSource = self; // 設置全局統一的表格背景 // 假設是分組,則要先清空背景view,纔可設置表格背景顏色(colorWithPattern平鋪) tableView.backgroundView = nil; tableView.backgroundColor = kGlobalBg; // group狀態下。sectionFooterHeight和sectionHeaderHeight是有值的 tableView.sectionFooterHeight = 0; tableView.sectionHeaderHeight = SectionHeaderMargin; // 在tableView初始化的時候設置contentInset // 在tableView展現完數據的時候給contentInset.top添加(20+44)的值 // 重要~~ ????? if (iOS7) { tableView.contentInset = UIEdgeInsetsMake(SectionHeaderMargin - 35, 0, 0, 0); } // 先隱藏表格默認的分隔線,cell內部在依據所在的indexPath繪製underLine tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.view = tableView; _tableView = tableView; } #pragma mark - 數據源 // 多少組 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // 返回組 數組的長度 return _allGroups.count; } // 各個組有多少行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // 取出組模型 SettingGroup *group = _allGroups[section]; // 返回組模型中成員---settingItems數組的長度 return group.items.count; } // 每當有一個cell進入視野範圍內就會調用。返回當前這行顯示的cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.建立一個SettingCell 本身定義的view SettingCell *cell = [SettingCell settingCellWithTableView:tableView]; // 2.取出組模型 SettingGroup *group = _allGroups[indexPath.section]; // 3.取出組中的被點的cell模型,並賦值給本身定義的view,供其內部子控件使用 cell.item = group.items[indexPath.row]; // 依據所在的組,所在的行號,設置切割線的顯示狀態 cell.indexPath = indexPath; return cell; } #pragma mark - 代理 // 點擊了cell後的操做 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // 1.去除選中時的背景 [tableView deselectRowAtIndexPath:indexPath animated:YES]; // 2.取出這行相應的模型 SettingGroup *group = _allGroups[indexPath.section]; // 取出相應的cell數據源模型 SettingItem *item = group.items[indexPath.row]; // 3.取出這行相應模型中有block代碼 if (item.operation) { // 運行block item.operation(); return; } // 4.檢測有沒有要跳轉的控制器 if ([item isKindOfClass:[SettingItemArrow class]]) { // 將cell相應的數據源模型 轉成詳細的子類 SettingItemArrow *arrowItem = (SettingItemArrow *)item; // 建立並跳轉到指定的控制器 if (arrowItem.showVCClass) { UIViewController *vc = [[arrowItem.showVCClass alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } } } #pragma mark 返回每一組的header標題 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { // 取得組模型 SettingGroup *group = _allGroups[section]; // 返回組的頭部標題 return group.header; } #pragma mark 返回每一組的footer標題 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { // 取得組模型 SettingGroup *group = _allGroups[section]; // 返回組的尾部標題 return group.footer; } @end atom
子類設置控制器spa
// // SettingController.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // 點擊【設置】button跳轉到本控制器,本控制器繼承自BaseSettingController #import "BaseSettingController.h" @interface SettingController : BaseSettingController @end
// // SettingController.m // 25_彩票 // // Created by beyond on 14-8-28. // Copyright (c) 2014年 com.beyond. All rights reserved. // #import "SettingController.h" #import "PushNoticeController.h" #import "ShareController.h" #import "AboutController.h" #import "HelpController.h" #import "ProductController.h" @interface SettingController () @end @implementation SettingController - (void)viewDidLoad { [super viewDidLoad]; // 1.第0組:3個 [self add0SectionItems]; // 2.第1組:6個 [self add1SectionItems]; } #pragma mark 加入第0組的模型數據 - (void)add0SectionItems { // 1.1.推送和提醒 SettingItemArrow *push = [SettingItemArrow itemWithIcon:@"MorePush" title:@"推送和提醒"]; push.showVCClass = [PushNoticeController class]; // copy狀態下的block(堆裏面的block)會對裏面所使用的外界變量 產生 強引用 // __weak SettingController *setting = self; // __unsafe_unretained // 1.2.搖一搖機選 SettingItemSwitch *shake = [SettingItemSwitch itemWithIcon:@"handShake" title:@"搖一搖機選"]; shake.key = ILSettingShakeChoose; // 1.3.聲音效果 SettingItemSwitch *sound = [SettingItemSwitch itemWithIcon:@"sound_Effect" title:@"聲音效果"]; sound.key = ILSettingSoundEffect; SettingGroup *group = [[SettingGroup alloc] init]; group.items = @[push, shake, sound]; [_allGroups addObject:group]; } #pragma mark 加入第1組的模型數據 - (void)add1SectionItems { // 2.1.檢查新版本號 SettingItemArrow *update = [SettingItemArrow itemWithIcon:@"MoreUpdate" title:@"檢查新版本號"]; update.operation = ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"眼下已經是最新版本號了" delegate:nil cancelButtonTitle:@"肯定" otherButtonTitles:nil, nil]; [alert show]; }; // 2.2.幫助 SettingItemArrow *help = [SettingItemArrow itemWithIcon:@"MoreHelp" title:@"幫助"]; help.showVCClass = [HelpController class]; // 2.3.分享 SettingItemArrow *share = [SettingItemArrow itemWithIcon:@"MoreShare" title:@"分享"]; share.showVCClass = [ShareController class]; // 2.4.查看消息 SettingItemArrow *msg = [SettingItemArrow itemWithIcon:@"MoreMessage" title:@"查看消息"]; // 2.5.產品推薦 SettingItemArrow *product = [SettingItemArrow itemWithIcon:@"MoreNetease" title:@"產品推薦"]; product.showVCClass = [ProductController class]; // 2.6.關於 SettingItemArrow *about = [SettingItemArrow itemWithIcon:@"MoreAbout" title:@"關於"]; about.showVCClass = [AboutController class]; SettingGroup *group = [[SettingGroup alloc] init]; group.items = @[update, help, share, msg, product, about]; [_allGroups addObject:group]; } @end