• 属性传值,协议传值,block传值,单例传值四种界面传值方式


    一、属性传值

    对于属性传值而言,相对于其它的三种 方法来说,是最基础,最简单的一种 方法,但,属性传值 有很大的局限性,因为是适用于第一个界面向第二个界面传 值,第二个向第三个界面传值等等。N界面向N + 1界面传值。而在此基础上,必须知道跳转界面的明确位置及所要传的值的具体类型。在第二个界面中声明所要传值 类型的属性。

    @interface SecondViewController : UIViewController
    
    //声明一个字符串属性来保存第一个界面传过来的字符串内容
    @property (nonatomic, copy)NSString *string;
    @property (nonatomic, copy)UIColor *color;
    @property (nonatomic, retain)UILabel *label;

    当然,在第二个界面中使用所声明的属性

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.view.backgroundColor = _color;
        UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
        button.frame = CGRectMake(100, 200, 200, 50);
        [button setTitle:self.string forState:UIControlStateNormal];

    在属性传值 的时候,需要知道明确跳转的位置及所要传的值的类型。

    @implementation FirstViewController
    
    - (void)right{
        SecondViewController *secondVC = [[SecondViewController alloc] init];
        secondVC.string = self.textField.text;
        secondVC.color = self.view.backgroundColor;
        [self.navigationController pushViewController:secondVC animated:YES];
    }

    二、协议传值

    通常,协议传值可以和属性传值一起使用,属性传值是从前往后依次传值,而协议 是从后往前来传值。

    协议传值可以简单的分为六步来实现。

    1.声明协议 2.声明代理  3.执行协议方法  4.接收协议  5.设置协议 代理对象 6.实现协议方法

    //1.声明协议
    @protocol FourViewControllerDelegate <NSObject>
    - (void)change:(NSString *)string;
    - (void)changeColor:(UIColor *)color;
    
    @end
    
    @interface FourViewController : UIViewController
    
    @property (nonatomic, retain)UITextField *textField;
    //2.声明代理
    @property (nonatomic,  assign)id<FourViewControllerDelegate>fouDelegate;
    
    @end
    @implementation FourViewController
    
    - (void)back{
        //3.执行协议方法
        if (self.fouDelegate != nil && [self.fouDelegate respondsToSelector:@selector(change:)]) {
            [self.fouDelegate change:self.textField.text];
            [self.fouDelegate changeColor:self.view.backgroundColor];
        }
        
        [self.navigationController popViewControllerAnimated:YES];
    
    }

    而如果想要使用协议,而必须要接收协议

    //5.接收协议
    @interface ThreeViewController : UIViewController<FourViewControllerDelegate>
    
    @property (nonatomic, retain)UILabel *label;
    
    @end
     1 @implementation ThreeViewController
     2 
     3 //6.实现协议方法
     4 - (void)change:(NSString *)string{
     5     self.label.text = string;
     6 }
     7 - (void)changeColor:(UIColor *)color{
     8     self.view.backgroundColor = color;
     9 }
    10 -(void)button{
    11     FourViewController *fourVC = [[FourViewController alloc] init];
    12     //4.指定第二个界面的代理对象为第一个视图控制器
    13     fourVC.fouDelegate = self;
    14     [self.navigationController pushViewController:fourVC animated:YES];
    15 }

    三、block传值

    相比于前两种来说,应该知道,block是匿名函数。既然是函数,也就会有那四种 表现形式,无参无返回值,有参无返回值,有参无返回值,有参有返回值这四种 形式。所以 block相对于前两种来说,表现方式 多样。

     1     __block int a = 0;
     2     void (^block1)(void) = ^(void){
     3         a ++;
     4         NSLog(@"%d",a);
     5     };
     6     block1();
     7     
     8     void (^block2)(int age, NSString *string) = ^(int age, NSString *string){
     9         NSLog(@"age is %d, text is %@", age, string);
    10     };
    11     block2(20, @"xiaoming");

    12 NSString *(^block3)(void) = ^(void){ 13 return @"有参wu返回值"; 14 }; 15 NSLog(@"block3 is %@", block3()); 16 NSString *(^block4)(NSString *text) = ^(NSString *string){ 17 return [string stringByAppendingString:@"有返回值"]; 18 }; 19 NSLog(@"block4 is %@",block4(@"有参有返回值"));

    block和协议传值的作用类似,但不同于协议传值的繁琐,block有很好的操作性。

    在第二个界面声明block

    #import <UIKit/UIKit.h>
    
    typedef void (^BaDaBlock)(NSString *);
    
    typedef void (^colorBlock)(UIColor *);
    
    
    @interface SecondViewController : UIViewController
    
    @property (nonatomic, retain)UITextField *textField;
    
    
    @property (nonatomic, copy)BaDaBlock bada;
    @property (nonatomic, copy)colorBlock cBlock;
    
    @end

    Block声明成属性,一定要用copy
    因为Block存储的内容在栈区,用copy复制一份到堆区,不能用retain的原因是,retain只能使堆区中的引用计数加1,而不能使栈区的引用计数加1

    在第二个界面执行所声明的blcok方法

    @implementation SecondViewController
    - (void)back{
        //执行Block
        
        if (self.bada != nil ) {
            self.bada(self.textField.text);
        }
        
        if (self.cBlock != nil) {
            self.cBlock(self.view.backgroundColor);
        }
        [self.navigationController popViewControllerAnimated:YES];
    }

    Block专门释放的方法  Block_release(_bada);

    Block_release(_cBlock);

    使用在第一个界面使用block

    @implementation FirstViewController
    
    - (void)button{
        SecondViewController *secondVC = [[SecondViewController alloc] init];
        secondVC.bada = ^(NSString *str){
            self.label.text = str;
        };
        secondVC.cBlock = ^(UIColor *color){
            self.view.backgroundColor = color;
        };
        [self.navigationController pushViewController:secondVC animated:YES];
        [secondVC release];
    }

    四、单例传值

    单例,简单的来说,就是单个的实例对象,不管被创建多少次,都具有唯一性,只有惟一的一个。

    单例的使用范围不限定,但需要知道明确跳转的位置,和所需传值 的类型。

    而单例 ,系统内部也有定义,像UIScreen, UIDevice都是系统内部定义 的单例,而通常使用的则是用户自定义的单例

    #import <Foundation/Foundation.h>
    
    @interface Handler : NSObject
    
    @property (nonatomic, copy)NSString *string;
    
    //单例方法是类方法,返回值类型为instancetype
    //自己定义的单例类,方法名通常都以share开头
    +(instancetype)shareInstance;
    
    @end

    实现所声明的单例方法

    #import "Handler.h"
    
    static Handler *handler = nil;
    @implementation Handler
    
    +(instancetype)shareInstance{
        //加锁,保证创建过程在同一时间内只能允许一个线程对象访问
        @synchronized(self){
        if (nil == handler) {
            handler = [[Handler alloc]init];
           }
        }
        return handler;
    }
    
    @end

    在实现的声明的单例方法时,一定要确保所创建的单例是唯一的。

    在实现跳转的地方创建单例,将值赋给单例类声明的属性。

    - (void)getAction{
        TwoViewController *twoVC = [[TwoViewController alloc] init];
        
        //创建单例
        Handler *handler = [Handler shareInstance];
        handler.string = _textField.text;
        
        [self.navigationController pushViewController:twoVC animated:YES];
    }

    使用传过来的单例值

    @implementation ThreeViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
          
        
        Handler *handler = [Handler shareInstance];
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 50)];
        label.text = handler.string;

    注意:

    因为单例可以全局使用,非常方便,并且唯一性。那怎么不大量使用呢?当然不能大量使用,因为是全局可以使用,相当于static一样,一旦创建,将不能被系统进行回收,所以 这块内存区域会一直存在,直到程序退出,如果大量采用单例的话,会造成大量的内存空间浪费。可以 使用,但不能大量的使用。

  • 相关阅读:
    将Jquery序列化后的表单值转换成Json
    sql 2008 修改链接服务器 Rpc &Rpc Out
    JavaScript中双等的使用情况
    从一张搞笑图看JavaScript的语法和特性
    dom元素的增删查改
    前端解决跨域问题(转)
    盒子模型以及css3指定盒子模型种类的box-sizing
    如何居中浮动元素
    CSS水平垂直居中常见方法总结(转)
    JS基础-连续赋值(转)
  • 原文地址:https://www.cnblogs.com/xueyao/p/5185824.html
Copyright © 2020-2023  润新知