IOS項目-通訊錄,ios項目通訊錄
主要是針對極客學院的通訊錄項目,知識點的整理...點擊-> 下載代碼
1,實現登陸和密碼輸入框為空白時,為不可用狀態
實現方案:使用添加觀察者的方式來實現,在viewDidLoad事件當中添加觀察者,來監聽nameField和pwdField文字框內容發生改變的事件,內容改變後觸發當前類的textChange事件
- (void)viewDidLoad { [super viewDidLoad];//添加觀察者 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.pwdField];}
--->textChange方法
- (void)textChange{ //修改按鈕的點擊狀態 self.loginBtn.enabled = (self.nameField.text.length && self.pwdField.text.length);}
2,實現頁面之間的轉跳
自storyboard出來後蘋果公司一直很推薦使用storyboard來實現項目,所以prepareForSegue這個方法一直存在於每一個視圖控制器當中。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
這個方法的意思就是跳轉之前的準備工作,參數是UIStoryboardSegue,UIStoryboardSegue內有三個屬性,1:是identifier(標識),2:sourceViewController(原控制器),3:destinationViewController(目標控制器)
//登陸- (IBAction)loginAction { //點擊後執行跳轉,LoginToContact為storyboard中segue的標識 [self performSegueWithIdentifier:@"LoginToContact" sender:nil];}
跳轉之前調用prepareForSegue方法
/* 一般在這裡給下一個控制器傳值 這個sender是當初performSegueWithIdentifier方法傳入的sender*/- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {//1.取得目標控制器 UIViewController *contactVc = segue.destinationViewController; //2.設定標題(傳值) contactVc.title = [NSString stringWithFormat:@"%@的連絡人清單",self.nameField.text];}
3,使用第三方控制項MBProgressHUD實現進度提示
在使用之前引入標頭檔#import "MBProgressHUD+MJ.h",MBProgressHUD+MJ.h是對MBProgressHUD的再一次封裝,為了方便使用這個+MJ的。
//登陸- (IBAction)loginAction { if (![self.nameField.text isEqualToString:@"jike"]) { [MBProgressHUD showError:@"帳號不存在"]; return; } if (![self.pwdField.text isEqualToString:@"qq"]) { [MBProgressHUD showError:@"密碼錯誤"]; return; } //顯示蒙版(遮蓋) [MBProgressHUD showMessage:@"努力載入中"]; //類比2秒跳轉,以後要發送網路請求 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //移除遮蓋 [MBProgressHUD hideHUD]; [self performSegueWithIdentifier:@"LoginToContact" sender:nil]; });}
4,使用UIAlertController
自IOS8.0後UIActionSheet和UIAlertView被UIAlertController取代
- (IBAction)backAction:(id)sender { //初始化 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"是否登出?" message:@"真的要登出嗎" preferredStyle:UIAlertControllerStyleActionSheet]; //添加按鈕 [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { [self.navigationController popViewControllerAnimated:YES]; }]]; //彈出 [self presentViewController:alert animated:YES completion:NULL];}
5,實現添加頁傳值
要實現的要點有:a,彈出添加頁時彈出小鍵盤,游標定位到輸入框裡。來獲得更好的使用者體驗
- (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; //讓姓名文字框成為第一響應者(叫出鍵盤) [self.nameField becomeFirstResponder];}
b,建立Model檔案夾作為模型層,在該檔案夾下添加需要傳值的模型
#import <Foundation/Foundation.h>@interface JKContactModel : NSObject@property (nonatomic, copy) NSString *name;@property (nonatomic, copy) NSString *phone;@end
c,定義介面AddViewControllerDelegate,介面內有個方法需要傳入AddViewController和JKContactModel
@class 防止相互匯入
@property為assign類型,為了防止循環參考
#import <UIKit/UIKit.h>@class AddViewController,JKContactModel;@protocol AddViewControllerDelegate <NSObject>@optional- (void)addContact:(AddViewController *)addVc didAddContact:(JKContactModel *)contact;@end@interface AddViewController : UIViewController@property (nonatomic, assign) id<AddViewControllerDelegate> delegate;@end
d,在AddViewController下面編寫AddAction添加按鈕點擊事件
respondsToSelector判斷某個對象是否實現了某方法
//添加資料- (IBAction)AddAction { //1.關閉當前視圖控制器 [self.navigationController popViewControllerAnimated:YES]; //代理傳值 //如果它的代理對象響應了我們這個協議方法就進行傳值 if ([self.delegate respondsToSelector:@selector(addContact:didAddContact:)]) { JKContactModel *contactModel = [[JKContactModel alloc] init]; contactModel.name = self.nameField.text; contactModel.phone = self.phoneField.text; [self.delegate addContact:self didAddContact:contactModel]; }}
e,最後回到連絡人清單控制器ContactTableViewController來響應傳值
#pragma mark - AddViewController delagate- (void)addContact:(AddViewController *)addVc didAddContact:(JKContactModel *)contact{ //1.添加資料模型 [self.contactArr addObject:contact]; //2.重新整理表視圖 [self.tableView reloadData];}
f,還有一點要在prepareForSegue方法下設定代理為自己本身
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { AddViewController *addVc = segue.destinationViewController; addVc.delegate = self;}
6,實現修改頁傳值
這個頁基本上本上面添加頁差不多....沒什麼知識點好整理的...
這樣還是有一個問題,這個ContactTableViewController控制器有兩個目標控制器,這樣子需要segeue的目標控制器來判斷轉跳到哪裡
修改prepareForSegue方法
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { id vc = segue.destinationViewController; if ([vc isKindOfClass:[AddViewController class]]) {//如果是跳轉到新增連絡人...控制器 //設定代理 AddViewController *addVc = vc; addVc.delegate = self; }else if ([vc isKindOfClass:[EditViewController class]]){ EditViewController *editVc = vc; //取得選中的那一行 NSIndexPath *path = [self.tableView indexPathForSelectedRow]; editVc.contactModel = self.contactArr[path.row]; editVc.delagate = self; }}
7,UITableView實現滑動刪除
UITableView有一個方法叫commitEditingStyle,通過這個方法實現刪除功能
#pragma mark - UITableView delagate- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ if (editingStyle == UITableViewCellEditingStyleDelete) { //1.刪除資料模型 [self.contactArr removeObjectAtIndex:indexPath.row]; //2.重新整理表視圖 [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop]; }}
8,喜好設定
要實現的要點有:a,在viewDidLoad事件中載入上次配置
- (void)viewDidLoad { [super viewDidLoad]; //讀取上次配置 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; self.nameField.text = [defaults valueForKey:UserNameKey]; self.pwdField.text = [defaults valueForKey:PwdKey]; self.rembSwitch.on = [defaults boolForKey:RmbPwdKey]; if (self.rembSwitch.isOn) { self.pwdField.text = [defaults valueForKey:PwdKey]; self.loginBtn.enabled = YES; } }
b,在使用者登陸成功後儲存配置
//登陸- (IBAction)loginAction { //儲存資料 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:self.nameField.text forKey:UserNameKey]; [defaults setObject:self.pwdField.text forKey:PwdKey]; [defaults setBool:self.rembSwitch.isOn forKey:RmbPwdKey]; //設定同步 [defaults synchronize];}
9,對象歸檔
要實現的要點有:a, NSKeyedArchiver 必須實現NSCoding協議方法
#import "JKContactModel.h"@implementation JKContactModel/* 將某個對象寫入檔案時候會調用 在這個方法中說清楚哪些屬性需要儲存 */- (void)encodeWithCoder:(NSCoder *)encoder{ [encoder encodeObject:self.name forKey:@"name"]; [encoder encodeObject:self.phone forKey:@"phone"];}/* 解析對象會調用這個方法 需要解析哪些屬性 */- (id)initWithCoder:(NSCoder *)decoder{ if (self = [super init]) { self.name = [decoder decodeObjectForKey:@"name"]; self.phone = [decoder decodeObjectForKey:@"phone"]; } return self;}@end
b,然後建立一個歸檔的檔案名稱,使用到的時候將歸檔的檔案載入至記憶體當中
#define ContactFilePath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.data"]@property (nonatomic, strong) NSMutableArray *contactArr;@implementation ContactTableViewController- (NSMutableArray *)contactArr{ if (!_contactArr) { //先重歸檔的檔案中讀取,如果不存在,則建立一個array _contactArr = [NSKeyedUnarchiver unarchiveObjectWithFile:ContactFilePath]; if (_contactArr == nil) { _contactArr = [NSMutableArray array]; } } return _contactArr;}
c,需要在資料添加、更新、刪除後都應該對資料進行歸檔
[NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];