属性传值,协议传值,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一样,一旦创建,将不能被系统进行回收,所以 这块内存区域会一直存在,直到程序退出,如果大量采用单例的话,会造成大量的内存空间浪费。可以 使用,但不能大量的使用。

时间: 02-07

属性传值,协议传值,block传值,单例传值四种界面传值方式的相关文章

iOS 页面间几种传值方式(属性,代理,block,单例,通知)

第二个视图控制器如何获取第一个视图控制器的部分信息 例如 :第二个界面中的lable显示第一个界面textField中的文本 这就需要用到属性传值.block传值 那么第一个视图控制器如何获的第二个视图控制器的部分信息 例如:第一个界面中的lable显示第二个界面textField中的文本 这就需要使用代理传值 页面间传值有八大传值方式,下面我们就简单介绍下页面间常用的五种传值方式: (一)属性传值 第二个界面中的lable显示第一个界面textField中的文本 首先我们建立一个RootVie

iOS-QQ好友列表 iOS 页面间几种传值方式(属性,代理,block,单例,通知)

主要是 点击按钮实现下拉 刷新数据 页面间传值 // // HMFriendsModel.h // QQ好友列表 // // Created by YaguangZhu on 15/9/1. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import <Foundation/Foundation.h> @interface HMFriendsModel : NSObject @property(nonatomic,cop

iOS页面间传值的五种方式总结(Delegate/NSNotification/Block/NSUserDefault/单例)

iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例) iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notification方式:3.block方式:4.UserDefault或者文件方式:5.单例模式方式:6.通过设置属性,实现页面间传值 在iOS开发中,我们经常会遇到页面间跳转传值的问题,

iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)

iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notification方式:3.block方式:4.UserDefault或者文件方式:5.单例模式方式:6.通过设置属性,实现页面间传值 在iOS开发中,我们经常会遇到页面间跳转传值的问题,现归纳总结一下: 情况1:A页面跳转到B页面 方法: 在B页面的控制器中,编写对应的属性,在A页面跳转到B页面的地方,给

页面之间传值方式的总结,五种方式,通知,block,代理,单例,NSUERDEFALUT,

首先代码拿上 1:单例 2:通知 3:代理 4:block方法 5:NSUSERDEFAULT(沙盒文件) 先是单例类: .h文件 @interface DataSource : NSObject @property (nonatomic, strong) NSString *myName;//单例的属性,用于传值 +(DataSource*)sharedDataSource;//建立单例对象 @end .m文件 #import "DataSource.h" @implementati

[&#128175;原]IOS之Objectic-C的单例的两种安全实现方案

所有转出博客园,请您注明出处:http://www.cnblogs.com/xiaobajiu/p/4122034.html Objectic-C的单例的两种安全实现方案 首先应该知道单例的实现有两大类,一个是懒汉式,一个是饿汉式.所谓的懒汉式就是在我们用到某对象(资源)的时候,去问一个负责提供的方法要那个对象.那个方法发现没有这个资源时就去创建资源,如果是已经有该资源时就直接返回这个资源.而饿汉式就是那个负责提供的方法早已为我们准备好了我们想要的资源问它,它就提供给我们那个它早就准备好了的资源

iOS中创建单例的两种方式

刚刚开始做iOS开发的时候,不知道怎么创建单例,在网上搜的也大多数都不太全,所以总结了一下创建单例的两种方式 首先在.h文件中声明类方法 1 +(instancetype)sharedUtils; 然后在.m文件中实现它,实现的方法有两种 第一种,在创建一个对象时先判断在程序中有没有创建过这个对象 1 static PublicUtils *DefaultManager = nil; 2 3 +(instancetype)sharedUtils 4 { 5 if (!DefaultManager

浅谈单例的三种实现--C#

传统的double check : public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (padlock) { if (i

Swift定义单例的三种方式

第一种:使用GCD. 自定义一个class继承你要继承的类, 定义一个静态可选变量, 声明一个dispatch_once_t,并赋初始值0(0代表还没有被实例过, 如果被实例过了其值始终是1),剩下的和OC定义单例类似 1 class NetWorkTools: AFHTTPSessionManager { 2 3 //MARK: - 单例 4 static var instance: NetWorkTools? 5 static var once_t: dispatch_once_t = 0