iOS頁面間傳值的一些方式總結,ios頁面總結
廢話不多說,直接進入主題:
這裡要說的方式有6種:1、屬性傳值 2、block 3、delegate 4、UserDefault 5、單例 6、通知(篇幅原因我唯寫核心代碼,如果看不懂可以直接在最下面去github 看demo)
1、block(個人覺得最常用的情境下最好用的)
先說我最常用的block吧,屬性傳值就很簡單了,主要用於順傳,我們在這裡包括下面都主要講逆傳。屬性傳值放在block裡一起寫了。
下面上代碼:
1 //secondVc.h2 typedef void (^TestBlock) (NSString *str);3 4 @interface ATNextViewController : UIViewController5 //定義block6 @property (nonatomic, copy) TestBlock testBlock;7 @end
1 //secondVc.m2 - (void)btnClick:(UIButton *)btn {3 if(self.testBlock) { //block傳值4 self.testBlock(@"綠色");5 }6 7 [self.navigationController popViewControllerAnimated:YES];8 }
下面是第一個VC代碼:
//Vc.m- (void)btnClick:(UIButton *)btn { ATNextViewController *nextVc = [[ATNextViewController alloc] init]; nextVc.inStr = @"紅色"; //屬性傳值,用於順傳,直接傳就好了 //這裡是block回傳的值 nextVc.testBlock = ^(NSString *str) { NSLog(@"%@",str); }; [self.navigationController pushViewController:nextVc animated:YES];}
2、delegate
代理要首先搞清楚誰傳值給誰,我這裡主要寫的都是逆傳,內層控制器傳向外層控制器,那也就是secondVc傳值給Vc,所以應該是Vc作為secondVc的代理,在代理方法接收secondVc傳過來的值。
secondVc的代碼:
1 //secondVc.h 2 3 //聲明代理 4 @protocol ATNextVcDelegate <NSObject> 5 6 @optional 7 - (void)inStr:(NSString *)inStr; 8 @end 9 @interface ATNextViewController : UIViewController10 @property (nonatomic, weak) id<ATNextVcDelegate> delegate;11 @end
1 //secondVc.m2 //代理傳值3 4 - (void)btnClick:(UIButton *)btn {5 if ([self.delegate respondsToSelector:@selector(inStr:)]) {6 [self.delegate inStr:@"紅色"];7 }8 [self.navigationController popViewControllerAnimated:YES];9 }
Vc代碼:
1 //Vc.m 2 //代理方法接收值 3 4 - (void)btnClick:(UIButton *)btn { 5 ATNextViewController *nextVc = [[ATNextViewController alloc] init]; 6 nextVc.delegate = self; 7 [self.navigationController pushViewController:nextVc animated:YES]; 8 } 9 #pragma mark - ATNextVcDelegate10 - (void)inStr:(NSString *)inStr {11 NSLog(@"%@========", inStr);12 }
3、UserDefault
這種方式會在本地存下檔案,屬於資料持久化(關於資料持久化有時間會另開一篇詳細講解)的一種。再次開啟程式依然會有上一次儲存留下的值。
這裡只有存和取兩個動作:
1 //secondVc.m 2 - (void)btnClick:(UIButton *)btn { 3 //存 4 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 5 [defaults setObject:@"黃色" forKey:@"btnColor"]; 6 [defaults setObject:@"100x100" forKey:@"btnSize"]; 7 [defaults synchronize]; 8 9 [self.navigationController popViewControllerAnimated:YES];10 11 }
1 //Vc.m 2 3 - (void)viewWillAppear:(BOOL)animated { 4 [super viewWillAppear:animated]; 5 //取 6 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 7 NSString *btnColor = [defaults objectForKey:@"btnColor"]; 8 NSString *btnSize = [defaults objectForKey:@"btnSize"]; 9 NSLog(@"%@ %@",btnColor,btnSize);10 }
和之前不同的是,這種方式只要進入這個介面就會取值,而不一定只是從上一個介面返回才傳值。
4、單例
單例一般直接做成宏,用的時候拿過來直接用就好了,所以單例宏檔案這裡就不寫了,感興趣可以去demo看一下,直接上代碼:
這裡我定義了一個單例類,用它存使用者登入狀態的資訊,之後是控制器中的使用:
//ATLoginStatus.h#import <Foundation/Foundation.h>#import "ATSingleton.h"@interface ATLoginStatus : NSObject@property (nonatomic, assign) BOOL isLogin;@property (nonatomic, copy) NSString *phoneNumStr;SingletonH(LoginStatus)@end
// ATLoginStatus.m#import "ATLoginStatus.h"@implementation ATLoginStatusSingletonM(LoginStatus)@end
//secondVc.m- (void)btnClick:(UIButton *)btn { //存 ATLoginStatus *status = [ATLoginStatus sharedLoginStatus]; status.phoneNumStr = @"12345"; status.isLogin = YES; [self.navigationController popViewControllerAnimated:YES]; }
//Vc.m- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //取 ATLoginStatus *status = [ATLoginStatus sharedLoginStatus]; NSLog(@"%@ %d",status.phoneNumStr,status.isLogin);}
5、通知
通知主要是發通知和收通知兩部:
發通知:
1 //secondVc.m2 3 - (void)btnClick:(UIButton *)btn {4 //發出通知5 [[NSNotificationCenter defaultCenter] postNotificationName:@"btnColorNoti" object:self userInfo:@{@"btnColor": @"黃色"}];6 [self.navigationController popViewControllerAnimated:NO];7 }
收通知:
//Vc.m- (void)viewDidLoad { [super viewDidLoad]; //... //註冊通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(btnColorNoti:) name:@"btnColorNoti" object:nil];}//收到通知的時候調用這個方法接受到通知訊息- (void)btnColorNoti:(NSNotification *)noti { NSDictionary *dict = noti.userInfo; NSLog(@"%@",dict[@"btnColor"]);}//控制器銷毀的時候登出通知監聽- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self];}
OK,就是這些了,雖然這些方式都能用於控制器之間傳值,但是其實有些方式是沒有必要用在我舉例的這種普通情境(跑一下我的demo就明白這是什麼情境了)下的(當然屬性傳值只能用於順傳),在我所舉例的這種情境下,用block是最簡潔的,delegate也可以,但是個人感覺對於傳值來說過於麻煩了,通知也還可以,但還是不如block。但是單例和UserDefaults其實是不需要在這種情境下用的,他們可以用在兩個控制器隔很遠的情況下,或者兩個控制器沒有關聯的情況下。就像我舉的單例的例子中,存一下全域都可能用到的如使用者資訊,這樣全域都能隨時取得這個資訊。
下面是demo:
my github:https://github.com/alan12138/somethingInteresting