技术文章分类(180)

技术随笔(11)

ios block回调使用

突然觉得block用来写回调方法,显得非常直观。建议使用.

基本使用如下:

#import "ViewController.h"

typedef void (^done1)(NSString *testString);
typedef int (^done2)(NSString *testString);

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self testBlock1WithDone:^(NSString *testString){
        NSLog(@"%@",testString);
    }];
    
    [self testBlock1_1WithDone:^(NSString *testString){
        if ([testString isEqualToString:@"test1_1"]) {
            return 1;
        }else{
            return 2;
        }
    }];
    
    [self testBlock2WithDone:^(NSString *testString){
        NSLog(@"%@",testString);
    }];
    
    [self testBlock2_1WithDone:^(NSString *testString){
        if ([testString isEqualToString:@"test2_1"]) {
            return 3;
        }else{
            return 4;
        }
    }];
}

-(void)testBlock1WithDone:(void(^)(NSString *testString))completion{
    completion(@"test1");
}

-(void)testBlock1_1WithDone:(int(^)(NSString *testString))completion{
     NSLog(@"%d",completion(@"test1_1"));
}

-(void)testBlock2WithDone:(done1)completion{
    completion(@"test2");
}

-(void)testBlock2_1WithDone:(done2)completion{
    NSLog(@"%d",completion(@"test2_1"));
}
@end

运行打印结果:

2014-11-30 19:44:18.397 BlockDemo[4609:96915] test1
2014-11-30 19:44:18.397 BlockDemo[4609:96915] 1
2014-11-30 19:44:18.397 BlockDemo[4609:96915] test2
2014-11-30 19:44:18.398 BlockDemo[4609:96915] 3

以上我用两种方法实现了有返回值和无返回值的两种block的写法。block的语法跟我们常用语言的语法有蛮大区别,很多程序员并不能很快的适应。

 

block是一个特殊的OC对象, 它建立在栈上, 而不是堆上, 这么做一个是为性能考虑,还有就是方便访问局部变量.
默认情况下block使用到的局部变量都会被复制,而不是保留.
所以它无法改变局部变量的值.
如果在变量面前加上__block, 那么编译器回去不会复制变量, 而是去找变量的地址, 通过地址来访问变量, 实际上就是直接操作变量.
另外块是在栈上分配的, 所以一旦离开作用域, 就会释放, 因此如果你要把快用在别的地方, 必须要复制一份.
所以在属性定义一个快的时候需要使用copy:  @property (nonatomic, copy) void (^onTextEntered)(NSString *enteredText);
块是不能保留的, retain对块没有意义.

 

//
//  MartinLiViewController.m
//  Dispatch_async
//
//  Created by dongway on 14-7-23.
//  Copyright (c) 2014年 dongway. All rights reserved.
//

#import "MartinLiViewController.h"
#import "InteractWithServerOnJSON.h"
#import "SVProgressHUD.h"

@interface MartinLiViewController ()

@end

@implementation MartinLiViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)dispatchLoadData:(id)sender {
    
    NSString *urlString = @"http://old.idongway.com/sohoweb/q?method=store.get&format=json&cat=1";
    //只需要写这么一句代码就可以加载出来网络数据了,包括提交网络请求,或者网络耗时操作。
    [self dispatchLoadDataWithUrlString:urlString complite:^(id result){
        NSArray *stores = [result objectForKey:@"stores"];  //获取网络数据,并可以在这个位置刷新主线程UI
        NSLog(@"%@",[[stores firstObject] valueForKey:@"storeName"]);
    }];
}

-(void)dispatchLoadDataWithUrlString:(NSString *)urlString complite:(void(^)(id dict))compliteAction{
    [SVProgressHUD show];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //InteractWithServerOnJSON interactWithServerOnJSON 这是我自己封装的加载json数据的方法
        NSDictionary *result = [InteractWithServerOnJSON interactWithServerOnJSON:urlString];
        
        dispatch_sync(dispatch_get_main_queue(), ^{
            [SVProgressHUD dismiss];
            compliteAction(result);
        });
    });
}
@end

 

//这里是加载http请求

+(NSDictionary *)interactWithServerOnJSON:(NSString *)urlString
{
    NSError *error;
    NSString *urlStringEncoding = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",urlStringEncoding);
    
    //加载一个NSURL对象
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStringEncoding]];
    //将请求的url数据放到NSData对象中
    NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
    if (response != nil && error == nil) {
        return [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
    } else {
        return  nil;
    }
}

 

 

回调的使用场景:

1,要求必须在某件事情做完后才能做另外一件事情

2,另外一件事情是可以自定义的

 

上面那个例子如果不存在网络加载这样的耗时操作,也可以不用异步加载多线程请求数据。大家明白其中原理就好。

posted @ 2014-08-02 13:37  坤哥MartinLi  阅读(365)  评论(0编辑  收藏  举报