天天看點

iOS開發之 各種傳值總結

一、自定義構造函數和屬性傳值

1、首先在需要值的類中自定義構造函數并在.h檔案中聲明

//自定義構造函數傳值

//.m檔案中

- (instancetype)initWithList:(NSArray *)list{

    if (self = [super init]) {

        myList = list;

}

    return self;

}

//.h檔案

- (instancetype)initWithList:(NSArray *)list;

//在哪個類裡面 需要 資料 就可以使用屬性 **向上一個頁面** 要值

//正向傳值

//使用一個對象 裡面的屬性、方法...的時候 必須有這個對象存在

@property (nonatomic, copy) NSString *titleName;

//屬性傳值

1>在聲明檔案中聲明一個屬性

2>在實作檔案中将屬性指派作為标題

//.m檔案

self.title = self.titleName;

2、在傳值的類中初始化被傳值的對象,在初始化時将值賦給被傳值初始化對象。

//Next_ViewController需要一個值 從ViewController傳到 Next_ViewController

//隻要alloc init 就會初始化 一個新的對象

//這個對象 就跟 之前的對象 不是同一個對象 (之前存在的舊對象裡面的資料 就會被清空 (它裡面 沒有被指派))

1>當不同類型(或者類)響應同一個方法時,可以通過 isKindOfClass 判斷這個對象 屬于哪種類型(哪個類)

//判斷手勢

if([sender isKindOfClass:[UITapGestureRecognizer class]] == YES){}

2>初始化一個數組,并将需要傳得值放在初始化的數組

NSArray *list = @[@"自定義", @"構造函數", @“傳值"];

Next_ViewController *next = [[Next_ViewController alloc] initWithList:list];

//屬性傳值

next.titleName = @"傳值";

3> 手勢裡面有一個 狀态屬性 可以通過 手勢觸發的狀态 判斷 手勢觸發的時間段

        if (sender.state == UIGestureRecognizerStateBegan) {

            Next_ViewController *next = [[Next_ViewController alloc] initWithList:@[@"屬性傳值", @"屬性"]];

            next.titleName = @"正向傳值";   

        }

二、KVC與KVO傳值

1、KVC(鍵值編碼)傳值

1>KVC主要通過”key”來進行傳值。通過找到屬性或者全局變量的值

2>“key”是屬性或者全局變量的名字

2、KVO(鍵值觀察者)傳值

1>KVO主要通過觀察“屬性”的狀态的變化做出相應地操作。比如從背景資料庫擷取資料,界面首次初始化時,隻有資料發生變化界面才會發生改變。

2>KVO首先要注冊一個監視中心

//[Model sharManger]建立一個單例

[[Model sharManger] addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

//模拟從背景資料庫擷取資料

[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(updateTitle) userInfo:nil repeats:YES];

//擷取資料

- (void)updateTitle{

     NSArray *list = @[@"K", @"V", @"O"];

    [Model sharManger].title = list[arc4random()%list.count];

}

3>觀察資料是否發生變化

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

    if ([keyPath isEqualToString:@"title"]) {

        //記錄 所有發生的改變

        [all addObject:change[@"old"]];

        label.text = change[@"new"]

        for (NSString *s in all) {

            NSLog(@"%@", s);

        }

    }

4>移除觀察者

[[Model sharManger] removeObserver:self forKeyPath:@"title"];

三、單例傳值

1>建立一個類繼承NSObject

#import "Model.h"

static Model *model = nil;

@implementation Model

+(instancetype)sharManger{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        model = [[Model alloc] init];

    });

    return model;

}

@end  

}

2>聲明兩個屬性

//标題

@property (nonatomic, copy) NSString *title;

//圖檔

@property (nonatomic, retain) UIImage *image;

3>在ViewController.m中導入單例類并給屬性賦初值

[Model sharManger].title = @"風景";

[Model sharManger].image = [UIImage imageNamed:@“begin"];

4>在Next_ViewController類中

UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.view.frame];

    imageView.image = [Model sharManger].image;

    [self.view addSubview:imageView];  

    [Model sharManger].image = [UIImage imageNamed:@"bg"];

5>因為單例隻初始化一次,是以在第一次圖檔傳過去之後,之後圖檔将會一直是@“bg"

四、通知傳值

1、通知是一對多的傳值,通知傳值首先要有觀察者。

2、首先注冊一個消息中心(在這裡模拟請求伺服器擷取使用者賬号資訊)

 1>建一個繼承NSObject的HTTPResquestManager類

//在實作中實作以下方法

+ (void)getRequest{

    NSDictionary *dic = @{@"username":@"通知傳值", @"password":@"123456"};

      sleep(5);

    [[NSNotificationCenter defaultCenter] postNotificationName:@"didResponse" object:nil userInfo:dic];

}

2>在觀察者對象中接收通知

(1)- (instancetype)init

{

    self = [super init];

    if (self) {

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadDataMeassage:) name:@"didResponse" object:nil];

    }

    return self;

}

(2)在reloadDataMeassage方法中實作

- (void)reloadDataMeassage:(NSNotification *)not {

    label.text = [NSString stringWithFormat:@"%@\n%@", not.userInfo[@"userName"], not.userInfo[@"password"]];

}

3>移除觀察者

  [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:@"didResponse"];

五、Block(閉包)傳值(block目的:用于反向傳值)

1、局部變量

1>參數聲明

傳回值類型(^閉包的名字)(參數清單)

2>實作

閉包的名字 =  ^(參數清單){code}

3>調用

閉包的名字();

示例:

聲明

void (^block)(int age, NSString *name);

實作

//如果想修改block外部的變量值 需要添加__block修飾

//__block int age;

block = ^(int age, NSString *name){

//代碼實作

//age = 10;

NSLog(@"%d %@", age, name);

}

調用

block(20, @“小明”);

2、全局變量

1>在延展或.h中聲明一個block全局變量

void (^imageNameBlock)(NSString *imageName);

2>在需要實作Block的方法中實作

***** 由于Block定義全局變量會循環引用 是以需要将該類設定成弱變量

__weak ViewController *vc = self;

__block UIImage *image = nil;

    imageNameBlock = ^(NSString *imageName){

        image = [UIImage imageNamed:imageName];

        vc.view.backgroundColor = [UIColor colorWithPatternImage:image];

    };

3>調用

imageNameBlock(@"logo");

4>為了避免重複初始化控件,需要将控件寫在Block實作的外面

3、屬性傳值

1>在Next_ViewController.h檔案中聲明一個屬性

@property (nonatomic, copy) void (^block)(NSString *title);

2>在Next_ViewController.m檔案中,在傳回上一個頁面時,同時通過Block把這個頁面的值傳到上一個頁面

self.block(@“Block屬性傳值”);

3>在初始化Next_ViewController的地方

next.block = ^(NSString *title){

NSLog(@“%@”, title);

}

4、方法傳值

1>在Next_ViewController.h檔案中聲明一個方法

- (void)passValue:(void^(NSString *))block;

2>在Next_ViewController.m檔案中實作方法

  • (void)passValue:(void^(NSString *))block{

      block(@“方法傳值”);

}

3>在初始化Next_ViewController的地方調用此方法

[next passValue:^(NSString * title){

 NSLog(@“Block方法傳值”);

}];

六、代理傳值

代理:又叫委托 自己不能去辦的事 委托給别人去辦

1、聲明代理方法(不要在@interface裡面 聲明代理方法)

//協定名字一般是類名+delegate

2、聲明代理的屬性 (可以通過這個屬性找到  代理方法)

@property (nonatomic, assign) id<NextDelegate> delegate;

//聲明代理的屬性 用assign 配置設定棧裡面

//id<NextDelegate>  代理的類型 尖括号裡面是代理的名字

3、什麼時候需要觸發這個代理方法

//   respondsToSelector 判斷一個方法 是否可以響應 傳回值是一個BOOL值

4、通過協定的屬性 調用代理的方法 (委托)

5、導入協定

@interface ViewController ()<NextDelegate>

6、在初始化有代理方法的對象地方 挂上代理

 7、寫上代理方法 等待被執行

繼續閱讀