一、自定義構造函數和屬性傳值
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、寫上代理方法 等待被執行