新聞顯示頁面的設定,主要實現以下功能:
1.一個UITableView頁作為總的設定頁,點擊新聞顯示,進入新聞詳情設定頁面,詳情頁麵包含以下設定:是否顯示圖片,是否顯示作者,是否顯示日期,是否顯示簡介,調整圖片位置(左或右)。
2.使用者的設定被儲存到plist檔案,每次都先從plist設定檔中讀取。
3.只有在使用者選擇了顯示圖片時才可對圖片位置進行設定,否則“圖片設定”開關被隱藏。
直接上代碼,第一個.h檔案:
#import <UIKit/UIKit.h>#import "detailSettingViewController.h"//注意一定在標頭檔添加要跳轉到的頁面@interface settingViewController : UITableViewController{ }//這裡並不需要添加UITableViewDelegate和UITableViewDataSource,因為本身就繼承自UITableView。@property(nonatomic,retain)IBOutlet UITableView *settingTableView;@end
第一個.m檔案
#import "settingViewController.h"#import <QuartzCore/QuartzCore.h>@interface settingViewController ()@end@implementation settingViewController@synthesize settingTableView=_settingTableView;- (void)viewDidLoad{ [super viewDidLoad];}- (void)viewDidUnload{ [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil;}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ return (interfaceOrientation == UIInterfaceOrientationPortrait);}#pragma mark - Table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ // Return the number of sections. return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ // Return the number of rows in the section. return 1;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell==nil) { cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.imageView.layer.cornerRadius=12.0; cell.imageView.layer.masksToBounds=YES; cell.imageView.image=[UIImage imageNamed:@"Icon.png"]; cell.textLabel.text=@"新聞顯示"; return cell;}@end
第二個.h檔案:
#import <UIKit/UIKit.h>@interface detailSettingViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>{ NSMutableArray *sectionArray; NSMutableArray *rowArray; NSMutableDictionary *newsUserDefault; BOOL showImage;//是否顯示圖片 BOOL imageLocation;//圖片的位置,左或右 BOOL showAuthor;//是否顯示作者 BOOL showDate;//是否顯示日期 BOOL showIntro;//是否顯示簡介 NSString *plistPath;//檔案儲存體位置 }@property(nonatomic,retain)IBOutlet UITableView *detailSettingTableView;@end
這裡有一個特別需要注意的地方,我之前直接繼承自UITableViewController,出現了以下錯誤提示:
[UITableViewControllerloadView] loaded the "2-view-3" nib but didn't get a UITableView.'
原因:項目中存在多個ViewController,每個ViewController 都有UITableView,點擊前一個ViewController 的UITableView 的cell跳轉到第二個ViewController 的UITableView。第一個ViewController直接繼承自UITableViewController,而第二個ViewController也繼承自UITableViewController
,這樣就導致了歧義,系統在loadView的時候就不知道該給哪一個ViewController loadView了。
解決辦法:將第二個ViewController繼承自UIViewController。
補充說明:第一個ViewController繼承自UITableViewController,所以不再需要實現UITableViewDelegate和UITableViewDataSource。而第二個ViewController則需要實現這兩個協議。可參見:http://stackoverflow.com/questions/10549337/uisearchbar-and-uitableview。
接下來是.m檔案:
#import "detailSettingViewController.h"@interface detailSettingViewController ()@end@implementation detailSettingViewController@synthesize detailSettingTableView=_detailSettingTableView;-(void)ArrayInit{ sectionArray=[[NSMutableArray alloc] initWithObjects:@"顯示設定",@"圖片位置" ,nil]; rowArray=[[NSMutableArray alloc] initWithObjects:@"圖片",@"日期",@"作者",@"簡介", nil];}-(void)readThePlist{ plistPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"userDefaults.plist"]; if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath]) { newsUserDefault=[[NSMutableDictionary alloc]initWithContentsOfFile:plistPath]; imageLocation=[[newsUserDefault valueForKey:@"imageLoaction"] boolValue]; showImage=[[newsUserDefault valueForKey:@"showImage"] boolValue]; showDate=[[newsUserDefault valueForKey:@"showDate"] boolValue]; showAuthor=[[newsUserDefault valueForKey:@"showAuthor"] boolValue]; showIntro=[[newsUserDefault valueForKey:@"showIntroduction"] boolValue]; } else //建立檔案 { NSLog(@"create"); newsUserDefault=[[NSMutableDictionary alloc] initWithCapacity:12]; [newsUserDefault writeToFile:plistPath atomically:YES]; }}- (void)viewDidLoad{ [super viewDidLoad]; [self ArrayInit]; [self readThePlist];}- (void)viewDidUnload{ [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil;}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ return (interfaceOrientation == UIInterfaceOrientationPortrait);}#pragma mark - Table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ // Return the number of sections. return [sectionArray count];}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ // Return the number of rows in the section. if (section==0) { return [rowArray count]; }else { return 1; }}-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ //section header tittle NSString *sectionHeader=[[NSString alloc] init]; sectionHeader=[sectionArray objectAtIndex:section]; return sectionHeader;}-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{ //section footer NSString *sectionFooter=[[NSString alloc]init]; if (section==0) { sectionFooter=@"是否顯示"; }else { sectionFooter=@"圖片顯示在左或右"; } return sectionFooter;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSInteger section=indexPath.section; NSInteger row=indexPath.row;//@我本想幹掉cell重用機制,後面發現這樣很傻,但請注意,總有不得已的時候。// NSString *CellIdentifier =[NSString stringWithFormat:@"cell%d%d",section,row];// UITableViewCell *cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; static NSString *CellIdentifier=@"Cell"; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell==nil) { cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } UISwitch *Switch=[[UISwitch alloc] initWithFrame:CGRectMake(220, 6, 79, 27)]; [Switch addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged]; if (section==0) { Switch.tag=101+row; cell.textLabel.text=[rowArray objectAtIndex:row]; switch (Switch.tag) { case 101: Switch.on=showImage; break; case 102: Switch.on=showDate; break; case 103: Switch.on=showAuthor; break; case 104: Switch.on=showIntro; break; default: break; } [cell.contentView addSubview:Switch]; }else if(section==1){ Switch.tag=100; Switch.hidden=YES; if (showImage) { Switch.hidden=NO; Switch.on=imageLocation; if (imageLocation==0) { NSLog(@"圖片顯示在左邊"); }else { NSLog(@"圖片顯示在右邊"); } } cell.textLabel.text=@"Left/Right"; [cell.contentView addSubview:Switch]; } return cell;}-(void)switchAction:(UISwitch *)sender{ NSInteger switchTag=sender.tag; BOOL switchStatus=sender.on;//Switch的狀態 NSNumber *convertSwitchStatus=[[NSNumber alloc] initWithBool:switchStatus]; UISwitch *imageSwitch=(UISwitch *)[self.view viewWithTag:100];//圖片可顯示時才能調整圖片的位置 switch (switchTag) { case 101: [newsUserDefault setValue:convertSwitchStatus forKey:@"showImage"]; if (switchStatus==YES) { imageSwitch.hidden=NO; }else { imageSwitch.hidden=YES; } break; case 102: [newsUserDefault setValue:convertSwitchStatus forKey:@"showDate"]; break; case 103: [newsUserDefault setValue:convertSwitchStatus forKey:@"showAuthor"]; break; case 104: [newsUserDefault setValue:convertSwitchStatus forKey:@"showIntroduction"]; break; case 100: [newsUserDefault setValue:convertSwitchStatus forKey:@"imageLoaction"]; break; default: break; }// NSLog(@"-----plist-----%@,count=%i",newsUserDefault,[newsUserDefault count]); [self saveToPlistFile]; }-(void)saveToPlistFile{ NSString *localPath=[[NSBundle mainBundle] pathForResource:@"userDefaults" ofType:@"plist"]; plistPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]stringByAppendingPathComponent:@"userDefaults.plist"]; if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) { [[NSFileManager defaultManager] copyItemAtPath:localPath toPath:plistPath error:nil]; } [newsUserDefault writeToFile:plistPath atomically:YES];}@end
程式啟動並執行效果如下:
點擊之後進入詳情設定頁面:
ps:一定要養成好的編程習慣啊,就是上面那個switch:case語句裡的一個break忘了寫,調試我一下午,多麼苦逼的錯誤啊,希望各位以此為戒。
另外,也許有的人會精益求精的覺得在圖片位置那個UISwitch中是否可以顯示“左/右”來標識使用者的選擇。當然,這樣做的確是做到了更好的使用者體驗。我也嘗試了一些方法,大致思路就是利用Objective C的特性之一的Category,對UISwitch進行擴充,這一點可參考:http://bj007.blog.51cto.com/1701577/541736和http://www.flyblog.info/catprogramming/258.html。但是後面一位朋友的實現方法會卡死在下面這一句,網上說這種方法在新的SDK中不能再用了,請各位大俠指點。我用的是最新的SDK。
return [[[self slider] subviews] objectAtIndex:2];