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、寫上代理方法 等待被執行

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