[程序員日記]OC常用傳值方法

在面向?qū)ο箝_發(fā)中,經(jīng)常遇到多個(gè)類間傳值,總結(jié)起來(lái)即正向傳值(A—>B)(屬性傳值),反向傳值(A<—B)(利用對(duì)象,使用TargetAction,使用協(xié)議代理,使用系統(tǒng)自帶的Block,使用自定義Block),雙向傳值(A<—>B)(使用NSUserDefaults進(jìn)行數(shù)據(jù)傳值,使用系統(tǒng)的UIApplication單例進(jìn)行傳值,使用自己的單例類進(jìn)行傳值,使用通知中心NSNotificationCenter進(jìn)行傳值,使用KVC進(jìn)行傳值)。

1.正向傳值

屬性傳值

在B類中定義屬性用于接收A類傳來(lái)的數(shù)據(jù)

2.反向傳值(回調(diào))

1)利用對(duì)象反向傳值

將A類對(duì)象定義成B類的屬性進(jìn)行傳值

如,通過(guò)KGSubViewController(B)修改 KGRootViewController(A)的Label

KGRootViewController

//在KGRootViewController中定義函數(shù)接收返回的數(shù)據(jù)
-(void)backValue:(NSString *)string color:(UIColor *)color
{
    //將參數(shù)的值賦給label
    label.text = string;

    //將顏色賦給賦給lable的字體顏色
    label.textColor = color;
}

界面跳轉(zhuǎn)至KGSubViewController,并將KGRootViewController對(duì)象傳到KGSubViewController中

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  KGSubViewController * svc = [[KGSubViewController alloc]init];

  //讓B持有A
  svc.rvc = self;

  [self presentViewController:svc animated:YES completion:nil];
}

KGSubViewController

//創(chuàng)建一個(gè)Root對(duì)象
@property(nonatomic,retain) KGRootViewController * rvc;


//在銷毀之前,做一些回傳數(shù)據(jù)的事
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.rvc backValue:tf.text color:[UIColor redColor]];

    [self dismissViewControllerAnimated:YES completion:nil];
}

2)使用TargetAction反向傳值

通過(guò)指定回傳方法和回傳對(duì)象進(jìn)行傳值

仍以上例為例,實(shí)現(xiàn)方法為:
KGRootViewController

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    KGSubViewController * svc = [[KGSubViewController alloc]init];
    //將回傳對(duì)象進(jìn)行指定
    svc.target = self;  //這里的self是指rootviewcontrller
    //將回傳方法,進(jìn)行指定
    svc.selector = @selector(backValue:);

    [self presentViewController:svc animated:YES completion:nil];
}

-(void)backValue:(NSString *)string
{
    //回傳數(shù)據(jù)方法
    label.text = string;
}

KGSubViewController

//在這里定義兩個(gè)屬性,用來(lái)接收目標(biāo)和方法,用來(lái)進(jìn)行反向傳值

//接收要回傳的對(duì)象
@property(nonatomic,retain) id target; 

//接收回傳數(shù)據(jù)的方法
@property(nonatomic,assign) SEL selector;

//在銷毀之前,將數(shù)據(jù)回傳回去

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //利用保存的target 和 action 來(lái)進(jìn)行回傳
    if ([self.target respondsToSelector:self.selector]) {
    [self.target performSelector:self.selector withObject:tf.text];
    }

    [self dismissViewControllerAnimated:YES completion:nil];
}

3)使用協(xié)議代理反向傳值

協(xié)議代理是回調(diào)中常用的方法,顧名思義,把某個(gè)對(duì)象要做的事情委托給別的對(duì)象去做。那么別的對(duì)象就是這個(gè)對(duì)象的代理,代理它來(lái)打理要做的事情。使用協(xié)議代理不僅可以正向傳值,亦可反向傳值。在使用中,需要注意哪個(gè)類是委托方,哪個(gè)類是代理方。總之:誰(shuí)傳值誰(shuí)是委托方

如,通過(guò)KGSubViewController改變KGRootViewController中l(wèi)abel值

在KGSubViewController頁(yè)面里,制定一個(gè)協(xié)議

@protocol BackValue <NSObject>
//回傳數(shù)據(jù)的協(xié)議方法
-(void)backValue:(NSString *)string;
@end

@property(nonatomic,retain) id < BackValue > delegate;

在KGSubViewController使代理方實(shí)現(xiàn)方法

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //代理方實(shí)現(xiàn)協(xié)議中的方法
    [self.delegate backValue:tf.text];

    [self dismissViewControllerAnimated:YES completion:nil];
}

在KGRootViewController中實(shí)現(xiàn)協(xié)議 <BackValue>

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    KGSubViewController * svc = [[KGSubViewController alloc]init];

    //讓A同意B所提出的協(xié)議條件
    svc.delegate = self;

    [self presentViewController:svc animated:YES completion:nil];
}

//實(shí)現(xiàn)協(xié)議 方法
-(void)backValue:(NSString *)string
{
    label.text = string;
}

4)使用系統(tǒng)自帶的Block進(jìn)行反向傳值

block是代碼塊的對(duì)象,類似函數(shù)指針,調(diào)用block如同調(diào)用代碼塊中的代碼,利用block可以實(shí)現(xiàn)回調(diào)。

在系統(tǒng)提供方法中,有很多使用block方法,如界面跳轉(zhuǎn)presentViewController時(shí)

將KGRootViewController中l(wèi)abel.text值傳給KGSubViewController textField.text

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    KGSubViewController * svc = [[KGSubViewController alloc]init];

    svc.rvc = self;

    //OC中,block用來(lái)去指向一個(gè)匿名的語(yǔ)句塊,從而可以當(dāng)成函數(shù)還調(diào)用該語(yǔ)句塊
    //這個(gè)方法的第三個(gè)參數(shù)是一個(gè)block,意思說(shuō),當(dāng)彈出來(lái)的svc顯示完成后,執(zhí)行block里的內(nèi)容
    [self presentViewController:svc animated:YES completion:^{
    
         //正向傳值
        svc.textField.text = self.label.text;
    }];
}

將KGSubViewController textField.text值傳給 KGRootViewController中l(wèi)abel.text

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self dismissViewControllerAnimated:YES completion:^{
    
        self.rvc.label.text = self.textField.text;
    
    }];
}

5)使用自定義Block反向傳值

KGSubViewController

//定義一個(gè)block的屬性
@property(nonatomic,copy)void (^block)(NSString *);

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //執(zhí)行block
    self.block(tf.text);

    [self dismissViewControllerAnimated:YES completion:nil];
}

KGRootViewController

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    KGSubViewController * svc = [[KGSubViewController alloc]init];

    //給block賦值,做用是讓svc知道block指向的代碼塊的功能
    svc.block = ^(NSString * string){

        label.text = string;
    
    };
    [self presentViewController:svc animated:YES completion:nil];

}

3.雙向產(chǎn)值
1)使用NSUserDefaults進(jìn)行數(shù)據(jù)傳值

NSUserDefaults紀(jì)錄本地一些輕量級(jí)的數(shù)據(jù),是單例類。其通過(guò)userDefaults對(duì)象來(lái)將選中按鈕的索引給保存到NSUserDefaults的plist文件中。這個(gè)文件實(shí)際上是一個(gè)plist文件,在沙盒中的/Library/Preferences/NSUserDefaults.plist 這個(gè)位置

當(dāng)KGSubViewController調(diào)用viewWillAppear時(shí)讀取沙盒內(nèi)容

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //獲取NSUserDefaults文件,讀取里面內(nèi)容,來(lái)決定讓哪一個(gè)按鈕進(jìn)行選中
    NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
    //通過(guò)存的時(shí)候的key值來(lái)進(jìn)行取值
    NSString * value = (NSString *)[ud objectForKey:@"ButtonIndex"];

    //計(jì)算出按鈕的tag值
    int buttonIndex = 1000 + value.intValue;
    //利用tag值取到按鈕
    UIButton * button = (UIButton *)[self.view viewWithTag:buttonIndex];
    button.selected = YES;
}

KGRootViewController
點(diǎn)擊button將點(diǎn)擊按鈕的索引存入沙盒中

-(void)buttonClick:(UIButton *)button
{
    for (int i = 1;i<6; i++) {
        UIButton * btn = (UIButton *)[self.view viewWithTag:1000+i];
        if (btn.selected == YES) {
            btn.selected = NO;
        }
    }
    button.selected = YES;
    //將每次點(diǎn)擊選中的按鈕索引給存起來(lái)
    NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
    NSLog(@"%@",[NSBundle mainBundle]);
    //通過(guò)userDefaults對(duì)象來(lái)將選中按鈕的索引給保存到NSUserDefaults的plist文件中
    //這個(gè)文件實(shí)際上是一個(gè)plist文件,在沙盒中的/Library/Preferences/NSUserDefaults.plist 這個(gè)位置
    [userDefaults setObject:[NSString stringWithFormat:@"%d",button.tag - 1000] forKey:@"ButtonIndex"];
    //回寫文件
    [userDefaults synchronize]; //synchronize:使同步,同時(shí)發(fā)生
}

KGRootViewController

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //獲取NSUserDefaults文件,讀取里面內(nèi)容,來(lái)決定讓哪一個(gè)按鈕進(jìn)行選中
    NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
    //通過(guò)存的時(shí)候的key值來(lái)進(jìn)行取值
    NSString * value = (NSString *)[ud objectForKey:@"ButtonIndex"];

    label.text = [NSString stringWithFormat:@"上次按下的是第 %@ 個(gè)按鈕",value];
}

2)使用系統(tǒng)的UIApplication單例進(jìn)行傳值

單例類在程序中只創(chuàng)建一次實(shí)例對(duì)象,利用這個(gè)特點(diǎn)可以進(jìn)行傳值。在iOS開發(fā)中,UIApplication就是個(gè)單例類,利用他可實(shí)現(xiàn)傳值。

在UIApplication定義存儲(chǔ)內(nèi)容

//創(chuàng)建一個(gè)公共數(shù)組,用來(lái)存放數(shù)據(jù),
@property(nonatomic,retain) NSMutableArray * array;

在相應(yīng)ViewController中使用

//應(yīng)該去利用系統(tǒng)的UIApplication這個(gè)單例來(lái)獲取系統(tǒng)已經(jīng)創(chuàng)建好的那個(gè)AppDelegate里的對(duì)象

//這是一個(gè)單例 對(duì)象,在整個(gè)程序中,只有一個(gè)唯一的實(shí)例存在
UIApplication * application = [UIApplication sharedApplication];

//通過(guò)這個(gè)單例對(duì)象來(lái)找到它持有的AppDelegate對(duì)象
KGAppDelegate * appDelegate = application.delegate;

//通過(guò)appDelegate對(duì)象拿到他的數(shù)組
[appDelegate.array addObject:self.title];

3)使用自己的單例類進(jìn)行傳值

除了使用系統(tǒng)自帶的單例類外,還可以使用自定義單例類用來(lái)傳值

自定義單例類KGMyApplication

//為application類,添加一個(gè)屬性,用來(lái)接收MyAppDelegate對(duì)象
@property(nonatomic,retain) KGMyAppDelegate * delegate;


//使用這個(gè)方法來(lái)實(shí)例一個(gè)單例對(duì)象
+(KGMyApplication *)sharedMyApplication;

+(KGMyApplication *)sharedMyApplication
{
    static KGMyApplication * obj = nil;
    if (!obj) {
        //給obj創(chuàng)建單例對(duì)象
        obj = [[KGMyApplication alloc]init];
        //給單例對(duì)象的delegate屬性賦值
        obj.delegate = [[KGMyAppDelegate alloc]init];
    }
    return obj;
}

定義KGMyAppDelegate類保存數(shù)據(jù)

//這個(gè)類不是一個(gè)單例類,但是,需要在這里保存數(shù)據(jù)
@property(nonatomic,retain)NSMutableArray * array;

在相應(yīng)ViewController中使用

//首先獲取MyApplication的單例對(duì)象

KGMyApplication * app = [KGMyApplication sharedMyApplication];

//通過(guò)這個(gè)單例對(duì)象里的delegate屬性來(lái)獲取MyAppDelegate對(duì)象

KGMyAppDelegate * appDelegate = app.delegate;

//獲取MyAppDelegate里的數(shù)組
NSMutableArray * array = [appDelegate array];

static int n = 0;
[array addObject:[NSString stringWithFormat:@"VC1-%d",n++]];

4)使用通知中心NSNotificationCenter進(jìn)行傳值

通知由通知中心發(fā)送,通知中心在整個(gè)工程中只有一個(gè)。通知中心可以發(fā)送多條消息,可以在整個(gè)工程中的任何位置接收消息,通過(guò)通知中心的名稱區(qū)分消息。

一個(gè)簡(jiǎn)單的應(yīng)用,從界面2中發(fā)送通知,界面1中接收

KGFirstViewController

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

- (void)doSomeThing:(NSNotification *)noti
{
    NSLog(@"收到了");

    label.text = [noti.userInfo objectForKey:@"key"];
}

KGSecondViewController

NSNotification *noti = [[NSNotification alloc]initWithName:@"xiaoxi" object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%@", btn.titleLabel.text],@"key", nil]];
    // 發(fā)送
    [[NSNotificationCenter defaultCenter] postNotification:noti];

類間傳值是編程時(shí)最常用的方法,也是最基礎(chǔ)的語(yǔ)法。在程序中使用不同的方法可以使的程序編的更加靈活。除以上方法外,還有KVC等方法,將在后續(xù)詳解。

歡迎各位指教

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.正向傳值 屬性傳值在B類中定義屬性用于接收A類傳來(lái)的數(shù)據(jù) 2.反向傳值(回調(diào)) 1)利用對(duì)象反向傳值 將A類對(duì)...
    ScaryMonsterLyn閱讀 1,485評(píng)論 0 0
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,604評(píng)論 30 472
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,537評(píng)論 19 139
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 12,353評(píng)論 6 13
  • 買東西將要付賬時(shí)發(fā)現(xiàn)沒有帶錢或者錢不夠,這也是經(jīng)常遇到的問(wèn)題,面對(duì)身后黑壓壓的排一隊(duì),瞬間尷尬。首先需要明確一點(diǎn):...
    尷尬癌專治閱讀 1,869評(píng)論 0 0

友情鏈接更多精彩內(nèi)容