iOS_四大傳值

一、目錄

二、掌握四大傳值前提

1.掌握push跳轉 相關文章鏈接:http://www.jianshu.com/p/46f693f761a1
2.掌握單例模式
3.掌握block
4.掌握代理

三、介紹

1、屬性傳值

(1)、介紹:

比如A視圖要給B視圖傳值字符“abc”
1,B視圖就聲明一個屬性NSSTring來接受字符abc
2,A視圖中new一個B控制器,B.NSString = “abc”
3,這樣就賦值過去了

(2)、代碼:
// B視圖的.h文件
@property (nonatomic,copy) NSString *propertySendString; 
// 用來接受A視圖傳遞過來的數據
// A視圖的.m文件
 Delegate *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"delegateVC"];
    vc.propertySendString = @"屬性傳值";
    [self.navigationController pushViewController:vc animated:YES];
(3)、注意:

在A視圖裏面new了B視圖,這時候跳轉到B視圖,一定一定一定要把這個new的視圖push過去,不然如果是故事版脫線跳轉的話,跳轉過來的就不是這個new的B控制器了,那麼傳遞肯定是失敗的

2、單例傳值

(1)、介紹:

單例就是整個APP只有一個對象,比如我把A類設爲單例,那麼我new的A類對象都是同一樣,不會出現第二個的,這樣我給A類中的一個變量賦值,那麼我在其他視圖想要用的時候,我就只需要new這個單例對象去拿這個變量的值就可以了

(2)、代碼
// 創建一個單例類 這個類的.h文件
#import <Foundation/Foundation.h>

@interface SingleTon : NSObject

// 傳值的屬性
@property (nonatomic,copy) NSString *passValue;

// 創建單例 (單例的命名,shared+類名)
+ (SingleTon *)sharedSingleTom;

@end
// 這個類的.m文件
#import "SingleTon.h"

@implementation SingleTon
// 以下是創建單例的方法,這是嚴格的單例,所以代碼偏多
// 嚴格是創建單例步驟
static SingleTon *singleTon;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleTon = [super allocWithZone:zone];
    });
    return singleTon;
}

+ (SingleTon *)sharedSingleTom {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleTon = [[SingleTon alloc] init];
    });
    return singleTon;
}

-(id)copyWithZone:(NSZone *)zone{
    return singleTon;
}

@end
// 比如我A界面想把abc傳到B界面,
// 那麼我這個單例類就是傳值的中間介質
// 以下代碼就是給單例的變量賦值(賦我要傳的值)
// 比如我在A界面裏給單例變量賦值,那麼接下來我在B界面裏,創建這個單例,然後直接調用這個單例變量,這個變量就是abc的值了
 SingleTon *singleTon = [SingleTon sharedSingleTom];
    singleTon.passValue = @"單例傳值";

3、block傳值

(1)、介紹

可以向任何方向傳值
比如我A類中有個值要傳出來,那麼我就在A類寫一個類方法,類方法的參數是block,然後這個block的參數是我要傳的值
這樣我在B類就可以用直接用A類調用這個類方法,然後這個類方法的block回調裏就會帶一個參數,這個參數是帶有值的,值就是從A類block參數帶出來的

(2)、代碼

// A類的.h文件

#import <Foundation/Foundation.h>
// 定義一個閉包(block),然後參數是字符串
typedef void (^sentValue)(NSString *str);
@interface Block : NSObject

// 定義一個類方法,參數是這個閉包
+ (void)sentValueClick:(sentValue)_sentBlock ;


@end
// A類的.m文件
#import "Block.h"

@implementation Block

// 實現.h文件中定義的類方法
+ (void)sentValueClick:(sentValue)_sentBlock {

    // 這個給這個閉包傳的參數“block傳值”就是你要傳的值了
    _sentBlock(@"block傳值");

}

@end
// 你想在哪裏拿到這個值,就在哪裏調用這個方法,這個str參數就是傳出來的值
 [Block sentValueClick:^(NSString *str) {
        NSLog(@"block:%@",str);
    }];

4、代理傳值

(1)、介紹:

代理傳值一般用於後向前傳值
比如我A點擊跳轉到B界面,然後想把B界面的值傳遞到A界面,並且跳轉回A界面
那麼我就在B界面寫一個代理和代理方法,然後再B界面視圖消失的方法裏面調用這個代理方法,這時候由於你已經設置A界面爲B的代理對象了,所以在B界面快消失的時候調用代理方法,其實是A界面調用了代理方法,所以這時候就可以把我要傳遞的值傳遞過去(有點難理解,具體看下代碼)

(2)、代碼
// B界面.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>


@protocol SentValueDelegate <NSObject>

@optional
- (void)sentValueClicked:(NSString *)str;

@end

@interface Delegate : UIViewController

@property (nonatomic,weak) id <SentValueDelegate> delegate;

@property (nonatomic,copy) NSString *propertySendString;

@end
//B界面.m文件
// 視圖即將消失會自動調用的方法
- (void)viewWillDisappear:(BOOL)animated {
    if ([_delegate respondsToSelector:@selector(sentValueClicked:)]) {
        [self.delegate sentValueClicked:@"代理傳值"];
    }
}
// A界面的.m文件

// 點擊按鈕跳轉到第二個頁面 代理傳值(後向前傳值)
- (IBAction)pushClicked:(UIButton *)sender {

    Delegate *delegateVC = [self.storyboard instantiateViewControllerWithIdentifier:@"delegateVC"];
    delegateVC.delegate = self;

    [self.navigationController pushViewController:delegateVC animated:YES];
}


// 實現代理的方法(這個方法包含着一個參數,這個參數就是從B頁面傳遞過來的值)
- (void)sentValueClicked:(NSString *)str {
    NSLog(@"%@",str);
}
(3)、補充說明

對於這個代理,確實有點難理解,這裏我說下執行的順序
首先是A類的.m文件
我點擊按鈕,跳轉到B界面,這時候我點擊按鈕就會來到按鈕的監聽方法,在這個方法裏面new一個B控制器,然後這時候就要設置B的代理爲A類,因爲這時候要先設置好,等下B類調用代理方法纔會來到這裏

// A界面的.m文件

// 點擊按鈕跳轉到第二個頁面 代理傳值(後向前傳值)
- (IBAction)pushClicked:(UIButton *)sender {

    Delegate *delegateVC = [self.storyboard instantiateViewControllerWithIdentifier:@"delegateVC"];
    delegateVC.delegate = self;

    [self.navigationController pushViewController:delegateVC animated:YES];
}


// 實現代理的方法(這個方法包含着一個參數,這個參數就是從B頁面傳遞過來的值)
- (void)sentValueClicked:(NSString *)str {
    NSLog(@"%@",str);
}

跳轉到B類後,在B類快要消失的方法寫以下代碼
代碼的說明:如果delegate這個代理屬性響應了這個方法
if ([_delegate respondsToSelector:@selector(sentValueClicked:)]) {
如果響應了就執行以下代碼,那麼這裏就是關鍵了
我剛纔是A類實現代理方法,就是響應就這個方法
剛纔我在A類把delegate = A類控制器(設置了代理),
所以這時候self.delegate是等於A類控制器的self
那麼以下的代碼就相當於[A類的self 調用sentValueClicked]
[self.delegate sentValueClicked:@"代理傳值"];
那麼這時候,程序就會來到A類實現的代理方法,
看以下代碼,這時候,這個方法的參數str就是
[self.delegate sentValueClicked:@"代理傳值"];裏面的”代理傳值”

// 實現代理的方法(這個方法包含着一個參數,這個參數就是從B頁面傳遞過來的值)
- (void)sentValueClicked:(NSString *)str {
    NSLog(@"%@",str);
}

以上就是代理傳值理解的關鍵地方,如果這個可以理解好,那麼代理是怎麼執行的也就可以理解好了

- (void)viewWillDisappear:(BOOL)animated {
    if ([_delegate respondsToSelector:@selector(sentValueClicked:)]) {
        [self.delegate sentValueClicked:@"代理傳值"];
    }
}

四、總結

  • 屬性 傳值 : 前向後

  • 單例 傳值 : 任何方向
    主要思想:單例做爲一箇中介

  • block傳值: 任何方向
    主要思想:哪個類要把值傳出來,哪個類就寫閉包(block),然後自動類方法+閉包參數的方法,把參數傳出來

  • 單例 傳值: 後向前
    主要思想:哪個類需要把值傳出來,就在哪個類寫一個代理,然後想要獲取到這個值的話,那麼就設置自己爲這個類的代理對象,然後去實現它的代理方法,通過這個方法的參數拿到值

五、個人使用心得

最簡單的方式:

屬性傳值,但是侷限在前向後,爲什麼呢?
因爲我A類傳值給B類,這裏最主要的關鍵實現是,在A類中new一個B類,並且把我要傳的值賦值給B類的接受變量,然後把B類的對象push到B界面,這時候在B類用self.接受變量就可以拿到值了
其實,這裏實現的關鍵,就是B類的對象
在A類中new B類的對象,進行賦值,在B界面調用self也是這個B類對象,也就是說這是同一個對象,同一塊內存空間的,所以,理所當然可以賦值,然後傳值過去
所以大概知道爲什麼只能前向後了把,因爲這個實現的關鍵就是要控制同一個B類對象,如果我是後向前,那麼我B類裏面,我就得new一個A類對象,但是如果我是用pop是沒辦法把A對象傳遞過去的,也就是說我這時候回到A界面又重新new 了一個A對象,所以傳值失敗的

最喜歡的方式:

block傳值:因爲這個block可以向任何地方傳值,步驟又少

#使用最多的方式:

block傳值和屬性傳值,如果是前向後我會用屬性傳值,其他情況大多是用block

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章