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

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

1.正向傳值

屬性傳值

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

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

1)利用對象反向傳值

將A類對象定義成B類的屬性進行傳值

如,通過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對象傳到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)建一個Root對象
@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反向傳值

通過指定回傳方法和回傳對象進行傳值

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

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

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

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

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

KGSubViewController

//在這里定義兩個屬性,用來接收目標和方法,用來進行反向傳值

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

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

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

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

    [self dismissViewControllerAnimated:YES completion:nil];
}

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

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

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

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

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

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

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

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

    [self dismissViewControllerAnimated:YES completion:nil];
}

在KGRootViewController中實現(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];
}

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

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

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

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

將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用來去指向一個匿名的語句塊,從而可以當成函數(shù)還調(diào)用該語句塊
    //這個方法的第三個參數(shù)是一個block,意思說,當彈出來的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

//定義一個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進行數(shù)據(jù)傳值

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

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

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

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

KGRootViewController
點擊button將點擊按鈕的索引存入沙盒中

-(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;
    //將每次點擊選中的按鈕索引給存起來
    NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
    NSLog(@"%@",[NSBundle mainBundle]);
    //通過userDefaults對象來將選中按鈕的索引給保存到NSUserDefaults的plist文件中
    //這個文件實際上是一個plist文件,在沙盒中的/Library/Preferences/NSUserDefaults.plist 這個位置
    [userDefaults setObject:[NSString stringWithFormat:@"%d",button.tag - 1000] forKey:@"ButtonIndex"];
    //回寫文件
    [userDefaults synchronize]; //synchronize:使同步,同時發(fā)生
}

KGRootViewController

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

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

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

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

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

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

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

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

//這是一個單例 對象,在整個程序中,只有一個唯一的實例存在
UIApplication * application = [UIApplication sharedApplication];

//通過這個單例對象來找到它持有的AppDelegate對象
KGAppDelegate * appDelegate = application.delegate;

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

3)使用自己的單例類進行傳值

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

自定義單例類KGMyApplication

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


//使用這個方法來實例一個單例對象
+(KGMyApplication *)sharedMyApplication;

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

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

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

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

//首先獲取MyApplication的單例對象

KGMyApplication * app = [KGMyApplication sharedMyApplication];

//通過這個單例對象里的delegate屬性來獲取MyAppDelegate對象

KGMyAppDelegate * appDelegate = app.delegate;

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

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

4)使用通知中心NSNotificationCenter進行傳值

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

一個簡單的應(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];

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

歡迎各位指教

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

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

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

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