iOS转场及传值

作者: 小鬼的世界 | 来源:发表于2016-04-12 17:47 被阅读639次

    作为初学者, 有错误的地方还请大神们挑出, 本人接受批评, 多谢各位大神了

    iOS转场: (RootViewController, SecondViewController)

    <#(nonnull UIViewController *)#>: 目标viewController
    

    animated: 是否存在动画

    //Show: 选择Show,目的地视图会被压入导航栈顶部. 导航条会提供一个后退按钮,用以返回源视图. 这是最常用的方式.
    //Show detail:与Show相似, 但会替换源视图. 将没有导航条和后退按钮.
    [self.navigationController pushViewController:delita animated:YES];
    
    [self.navigationController showViewController:delita sender:<#(nullable id)#>
    

    completion: 转场之后做什么, 是一个block函数

    //Present Modally: 模态显示内容.目的地视图会从底向上弹出, 通常用于显示跟页面连贯性不强的视图, 比如 添加餐馆, 添加用户(无论在哪个页面,都可能会调用此功能)
    self.navigationController presentViewController:<#(nonnull UIViewController *)#> animated:<#(BOOL)#> completion:<#^(void)completion#>
    

    Present as popover:iPad中常用,模态显示一个带箭头指向圆角矩形弹窗. 类似一个弹出菜单.

    转场传值:

    1. 属性传值

    //转场方法
    - (void)btnAction:(UIButton *)btn{
        SecondViewController *sec = [[SecondViewController alloc] init];//获取目标场景
        sec.string = self.label.text;//string为目标场景中的属性(NSString)
        [self.navigationController pushViewController:sec animated:YES];//转场
    }
    

    2. 代理传值(反向转场)

    1. 设置代理

    @protocol SecondViewControllerDelegate <NSObject>
    @optional
    - (void)changeTitle:(NSString *)title;
    @end
    

    2. 在SecondViewController.h定义代理

    @property (nonatomic, assign) id<SecondViewControllerDelegate>delegate;
    

    3. 在SecondViewController.m使用代理传值

    - (void)backAction:(UIButton *)btn{
        if (self.delegate && [self.delegate respondsToSelector:@selector(changeTitle:)]) {//判断是必须的
            [self.delegate changeTitle:self.textField.text];
        }
        [self.navigationController popToRootViewControllerAnimated:YES];
    }
    

    4. 在RootViewController.m中遵循代理并且实现代理方法

    记得让SecondViewController指定代理人为RootViewController.m

    - (void)changeTitle:(NSString *)title{
        self.navigationItem.title = title;
    }
    

    3. block 传值

    block定义

    /**
         *    //定义一个参无返回值的block函数
         *    void 无返回值
         *
         *    @param ^ block名称
         *
         *    @^() 无参数
         */
        void (^voidFunc)() = ^(){
            NSLog(@"我是一个代码块");
        };
        //使用block
        voidFunc();
    /**
         *    定义一个实现输出两个整数之和的block函数
         *    void 无返回值
         *    @param (int , int )类型说明
         *    @param a 参数
         *    @param b 参数
         */
        void (^addBlock)(int , int ) = ^(int a, int b){
            NSLog(@"a + b = %d", a + b);
        };
        addBlock(4, 6);
    /**
         *    block命别称
         *
         *    @param void (^)(int , int) 函数类型
         *    @param Block 别名
         */
        typedef void (^Block)(int ,int );
        //给一个参数为两个整数, 返回值为整形的block类型命别称
        typedef int (^addTwo)(int ,int );
        //block使用
        addTwo subBlock = ^(int a, int b){
            return a-b;
        };
        //block中没有使用局部变量, block存储在全局区,
        //block中如果有使用全局变量, 则存储在栈区
        subBlock(10, 5);
    

    block传值步骤

    1. 在SecondViewController.h给block命别称(一般不省略)
    typedef void(^titleBlock)(NSString *title);
    
    2. 在SecondViewController.h中定义一个block属性
    @property (nonatomic, copy) titleBlock myBlock;
    //注意: block属性必须用copy
    //block使用全局变量, 存在栈区, 使用copy是把block复制一份到堆区
    
    3. 在跳转页面方法中给block属性赋值(RootViewController的btnAction:)
        //在block中使用局部变量
        //__block(MRC)/__weak(ARC)
        __weak RootViewController *temp = self;//复制指针(引用计数不变)
        //不使用temp而用self, 在下个界面会持有self, 引用计数会+1
        //使用self容易造成循环引用(MRC下)
        sec.myBlock = ^(NSString *title){
            temp.navigationItem.title = title;
        };
    
    4. 调用block属性传入参数
    - (void)backAction:(UIButton *)btn{
        self.myBlock(self.textField.text);
        [self.navigationController popToRootViewControllerAnimated:YES];
    }
    

    单例模式传值

    1. 新建一个单例模式, 这里新建一个类白包含单例模式(User)

    //在User.h中定义一些属性, 这些属性作为存取值的对象
    @property (nonatomic, strong) NSString *userName;
    @property (nonatomic, strong) NSString *passworld;
    //设计一个单例模式初始化
    //获取唯一的用户
    + (User *)defaultUser;
    

    2. 实例化初始化

    + (User *)defaultUser{
        //static修饰的对象只会在第一次调用函数时初始化, 之后不再初始化
        static User *user = nil;
       if(user == nil){//判断user是否为空, 空则初始化
           user =[ [User alloc] init];
       }
       return user;
    }
    

    2. 在RootViewController.m中导入User.h, 同时在viewWillAppear(界面即将显示)中获取单例模式的值

    - (void)viewWillAppear:(BOOL)animated{
        self.textField.text = [User defaultString].string;
    }
    

    3. 在转场按钮函数中将值存入User中

    - (void)btnAction:(UIButton *)btn{
        SecondViewController *sec = [[SecondViewController alloc] init];
        //获取单例
        User *u = [User defaultString];
        //赋值
        u.string = self.textField.text;
        [self.navigationController pushViewController:sec animated:YES];
    }
    
    注: 如果需要让RootViewController一开始就显示, 比如让textField一开始就显示"单例模式"
    //在viewDidLoad中直接初始化User并存值
    self.textField.text = @"单例模式";
    [User defaultString].string = self.textField.text;
    

    4. 在SecondViewController中使用User中的string给self.textField.text赋值

    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(50, 200, 200, 50)];
        self.textField.borderStyle = UITextBorderStyleRoundedRect;
        self.textField.text = [User defaultString].string;
        self.textField.delegate = self;
        self.textField.textAlignment = NSTextAlignmentCenter;
        self.textField.clearButtonMode = UITextFieldViewModeAlways;
        [self.view addSubview:self.textField];
    

    5. 在按钮返回函数中存储数据

    - (void)btnAction:(UIButton *)btn{
        User *u = [User defaultString];
        u.string = self.textField.text;
        [self.navigationController popViewControllerAnimated:YES];//返回上层界面
    }
    

    相关文章

      网友评论

        本文标题:iOS转场及传值

        本文链接:https://www.haomeiwen.com/subject/wvailttx.html