从C#到Objective-C,循序渐进学习苹果开发(4)--代码块(block)和错误异常处理的理解

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验。本文继续上一篇随笔《从C#到Objective-C,循序渐进学习苹果开发(3)--分类(category)和协议Protocal的理解》,继续对比介绍它们两者之间的差异,以便我们从C#阵营过来的人员加深印象,深入了解Objective-C语言的特性。本篇随笔主要针对Objective-C里面的代码块(block)和异常处理概念的理解进行介绍。

1、Object C的代码块(block)

Objective-C的代码块从刚刚学习的时候,感觉有点奇怪,慢慢感觉它在C#里面也有点熟悉,它在Objective-C里面的引入,好像是主要用来解决代码回调和同步调用的问题的,说到这里,如果熟悉C#的特性的,可能会联想到了C#里的Action<T>和Func<T>的概念了吧,没错,他们就是一丘之貉,哈哈。

代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值,字符(^)是代码块的语法标记。

如下面的例子就是一个代码块的定义

void (^simpleBlock)(void) = ^{
        NSLog(@"This is a block");
    };

定义后,你就可以通过类似函数的方式进行使用了,看了下面的代码是不是感觉很熟悉的样子呢。

simpleBlock();

当然,对于这样的东西,它也是可以接受参数的,即使是多个参数也没问题,这个如果是带参数的,应该就是和C#的Func<T>很相似了,下面是一个两个参数的代码块例子。

double (^multiplyTwoValues)(double, double) =
                              ^(double firstValue, double secondValue) {
                                  return firstValue * secondValue;
                              };

    double result = multiplyTwoValues(2,4);

这样的代码块,它还可以获取类里面定义的局部变量,但是由于它的特殊性,好像如果不加特殊处理,它获取到的变量或者属性的值,是在它出现的那瞬间的快照。

下面一个例子,很好介绍代码块里面获取内容是快照的现实。

int anInteger = 42;

    void (^testBlock)(void) = ^{
        NSLog(@"Integer is: %i", anInteger);
    };

    anInteger = 84;

    testBlock();

上面代码块里面,打印出来的值,是42,而非84,因为它在代码块出现的那瞬间,就拿到了局部变量,之后就没有跟随大部队变化了。

那这种方式有无变通的方法,让它可以根据变量的变化而自动变化呢?当然有了,需要特殊处理即可,答案就是使用__block进行标识,它就可以跟随大部队的步伐了。

如果上面的代码块里面变量的定义使用了这个关键字,那么值就似乎84了,如下代码块所示。

 __block int anInteger = 42;

    void (^testBlock)(void) = ^{
        NSLog(@"Integer is: %i", anInteger);
    };

    anInteger = 84;

    testBlock();

这个__block功能很强大,告诉编译器,它可以获取变量的最新值,也可以在代码块里面对值进行修改(危险吗?反正你知道就好)

前面说道了,Objective-C里面的代码块类似c#里面lambda的Action 和 Func 那么举个例子来大致介绍下把。

对比一下下面两组代码,其一是Objective-C的代码块

typedef void (^MethodBlock)(int); 

- (void) fooWithBlock:(MethodBlock)block
{
    int a = 5;
    block(a);
}

- (void) regularFoo
{
    [self fooWithBlock:^(int val)
    {
        NSLog(@"%d", val);
    }];
}

接着是C#里面的代码例子,感觉它们很接近吧。在这里,你可能会感叹,编程语言这个世界里,很小,世界都趋向于大同了。

void Foo(Action<int> m)
{
    int a = 5;
    m(a);
}

void RegularFoo()
{
    Foo(val => // Or: Foo(delegate(int val)
    {
        Console.WriteLine(val);
    });
}

不过代码块的使用,你会慢慢感觉它虽然很强大,但是很多地方也不是很容易理解,毕竟对于我们这些入门没有很深根基的人来说,要慢慢消化。

再来看看下面这个例子代码,这个方法里面的代码块定义,很有意思。

- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock {
    ...
    callbackBlock();
}

再来看看下面这个代码块,你可能会更晕,没事,晕了就对了,说明你是一个正常的人。

void (^(^complexBlock)(void (^)(void)))(void) = ^ (void (^aBlock)(void)) {
    ...
    return ^{
        ...
    };
};

最后记得,如果是一个方法有多个参数,记得把代码块的参数放到最后来定义。

- (void)beginTaskWithName:(NSString *)name completion:(void(^)(void))callback;

至于代码块如何简化同步调用的问题,让给读者自己去了解研究了,我感觉也有点头晕了。哈哈。

2、Object C的错误及异常处理

我们知道,在开发各种应用程序或者系统的时候,错误肯定难以避免,有效处理错误异常就是你一个很有必要的内容。在C#里面,我们如果需要抛出异常,我们使用throw方法进行,所有的错误都以异常对象Exception作为基类进行扩展,包括各种各样的异常对象,而对错误异常的捕捉是通过try {} catch(Exception ex) finally {}这样的代码或者类似处理进行的,对于Objective-C来说,它又是如何处理错误异常的呢?

其实Objective-C对错误处理的机制也差不多,它对异常的支持包括四个编译器指令: @try@catch@throw 以及 @finally。是不是又一次感觉到语言的大同了,这个东西和C#的处理几乎没有什么差别。

另外Objective-C还引入了一个NSError的东西,这个东西和NSException有什么关系呢?这个东西有点类似于我们在C#开发的时候,增加一个out的输入参数,用来把程序内部的错误信息传递出去,然后交给调用者,让它们爱怎么用就怎么用,反正我处理完成了,有无错误我都告诉你了。由于NSError可以传递的信息比较丰富,一般来说这样对程序的处理也很方便。

如网络连接的异常,你可以通过下面的代码把它传递出来。

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

下面我们来看看一个写文件的错误如何处理的,首先定义一个函数,包含了NSError的参数的,注意一般这个参数是放到最后的,这点好像和我们有些这样处理的C#约定也是一样的。

- (BOOL)writeToURL:(NSURL *)aURL
           options:(NSDataWritingOptions)mask
             error:(NSError **)errorPtr;

那我们调用这个writeToURL的函数的时候,有错误发生就应该处理,错误发生的时候,它执行完毕了,并且返回一个NO的值

    NSError *anyError;
    BOOL success = [receivedData writeToURL:someLocalFileURL
                                    options:0
                                      error:&anyError];
    if (!success) {
        NSLog(@"Write failed with error: %@", anyError);
        // present error to user
    }

为了表示错误的了来源,NSError有一个domain的属性,约定一般以公司的名称(或特别的名称)来进行区分。

com.iqidi.appOrFrameworkName.ErrorDomain

如构造一个NSError的代码大概如下所示。

NSString *domain = @"com.iqidi.MyApplication.ErrorDomain";
NSString *desc = NSLocalizedString(@"Unable to…", @"");
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };

NSError *error = [NSError errorWithDomain:domain
                                         code:-101
                                     userInfo:userInfo];

而常规的异常,我们一般还是通过NSException进行处理,异常就是发生问题的时候,停下来第一时间请示如何处理,如果有处理的线路就按照处理的线路进行,否则就一级级往上推了。

它的处理和C#差不多,我们都很熟悉了,代码结构如下所示。

@try {
    // code that throws an exception
    ...
}
@catch (CustomException *ce) { // most specific type
    // handle exception ce
    ...
}
@catch (NSException *ne) { // less specific type
    // do whatever recovery is necessary at his level
    ...
    // rethrow the exception so it's handled at a higher level
    @throw;
}
@catch (id ue) { // least specific type
    // code that handles this exception
    ...
}
@finally {
    // perform tasks necessary whether exception occurred or not
    ...
}

异常的构造和抛出代码和C#的也很类似

NSException* myException = [NSException
        exceptionWithName:@"FileNotFoundException"
        reason:@"File Not Found on System"
        userInfo:nil];
@throw myException;

如果在处理异常的时候,需要处理一些对象的内存释放,那么一般是把它放到@finally包含的代码块里面。

这个和C#类似,虽然C#不会需要处理内存的释放问题,但是对于一些耗时的操作对象,如Connection,一般最好也放到finally里面确保关闭,处理类似。

- (void)doSomething {
    NSMutableArray *anArray = nil;
    array = [[NSMutableArray alloc] initWithCapacity:0];
    @try {
        [self doSomethingElse:anArray];
    }
    @finally {
        [anArray release];
    }
}

如果要抛出原汁原味的异常,这点也和C#相似,通过@throw;方法即可。

@try {
    NSException *e = [NSException
        exceptionWithName:@"FileNotFoundException"
        reason:@"File Not Found on System"
        userInfo:nil];
    @throw e;
}
@catch(NSException *e) {
    @throw; // rethrows e implicitly
}

本文转自博客园伍华聪的博客,原文链接:从C#到Objective-C,循序渐进学习苹果开发(4)--代码块(block)和错误异常处理的理解,如需转载请自行联系原博主。

时间: 2024-11-05 21:59:11

从C#到Objective-C,循序渐进学习苹果开发(4)--代码块(block)和错误异常处理的理解的相关文章

从C#到Objective-C,循序渐进学习苹果开发(7)--使用FMDB对Sqlite数据库进行操作

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本篇主要开始介绍基于XCode进行IOS程序的开发,介绍使用FMDB对Sqlite数据库进行操作,以及对数据库操作类进行抽象设计,以期达到重用.简化.高效开发的目的. 在.NET领域开发了很多年,一般常见的项目都需要操作数据库,包括有Oracle.SqlServer.Mysql.Sqlite.Access等数据库,这些数据库是

从C#到Objective-C,循序渐进学习苹果开发(5)--利用XCode来进行IOS的程序开发

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.前面几篇随笔主要介绍C#和Objective-C之间的差异,本片开始介绍利用XCode来进行IOS的程序开发,对比和C#利用VS进行开发的差异,以便我们更快的融入到IOS开发的阵营. 在介绍利用XCode来开发项目前,我自己消化了几本IOS开发的书籍,以及苹果开发网站的一些自认为重要文章介绍,学习了一些视频的内容,包括网易里面

从C#到Objective-C,循序渐进学习苹果开发(1)--准备开发账号和开发环境

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验,因为一旦方方面面都精通了,也就可能没太大的动力继续写这系列的文章了,文章中可能有一些地方说的不对或者不够完善的地方,希望大家多多指正,共同提高. 由于本人起步Objective-C的苹果开发比较晚,但是因为自己有着比较深厚的C#开发背景,因此在很多方面都会和我之前的经验做比较,因此本系列文章对于从C#转向Objective-C

从C#到Objective-C,循序渐进学习苹果开发(2)--Objective-C和C#的差异

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台开发苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验. 在上篇<从C#到Objective-C,循序渐进学习苹果开发(1)--准备开发账号和开发环境>介绍了一些基本的转换感悟和一些基础的准备工作,还没有正式真实的介绍Objective-C和C#的之前差异,我们知道,从一种环境或者一种语言转换过去另外一种,我们都会做一些对比和理解,这样可以很容易把我们头脑的知识进行对接,在这

从C#到Objective-C,循序渐进学习苹果开发(3)--分类(category)和协议Protocal的理解

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本文继续上一篇随笔<从C#到Object C,循序渐进学习苹果开发(2)--Objective-C和C#的差异>,继续对比介绍它们两者之间的差异,以便我们从C#阵营过来的人员加深印象,深入了解Objective-C语言的特性.本篇随笔主要针对Objective-C里面的分类(category)和协议Protocal概念的理解

从C#到Objective-C,循序渐进学习苹果开发(6)--视图控制器的使用

本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本篇主要开始介绍基于XCode进行IOS程序的开发,介绍其中视图控制器的理解和使用过程. 1.视图控制器(导航视图控制器和选项卡视图控制器) 我们知道,在.net里面开发Winform程序或者Webform程序,我们只需要绘制一个个界面,然后在后台添加相应的处理,如果设计比较好的话,把业务逻辑.数据库访问等不同的层包装起来,本

15个快速学习苹果Swift编程语言的入门教程

要说今年最火的编程语言是什么.那就非Swift莫属了.当然最主要还是市场炒的比较热,加上官方Swift教程<The Swift Programming Language>在北航的大三学生发起在github上进行协同翻译获得了很高的人气,短短几天时间内<Swift中文版>第一版就发布.这真是不火不行了. Swift是苹果公司在WWDC2014上发布的全新开发语言.从演示视频及随后在appstore上线的标准文档看来,语法内容混合了OC,JS,Python,语法简单,使用方便,并可与O

美有线电视商康卡斯特CEO:学习苹果好榜样

康卡斯特CEO布莱恩·罗伯茨 北京时间12月17日消息,据国外媒体报道,美国最大的有线服务公司康卡斯特首席执行官布莱恩·罗伯茨在接受采访时表示,康卡斯特在发展的过程中学习苹果的模式,把复杂的产品组合简约化和易用化. 美国最大的媒体公司并非你想像中的那个.康卡斯特公司的收入和市场影响力比迪斯尼.新闻集团.时代华纳的都要高.就连康卡斯特CEO布莱恩·罗伯茨对公司崛起的速度也感到吃惊.康卡斯特由布莱恩·罗伯茨的父亲创立于美国密西西比州图珀洛市,最初只是一家小小的有线电视公司,如今却是NBC环球的主要持

[翻译] 学习iOS开发的建议:如何从菜鸟到专家

[文章原地址] http://mobile.tutsplus.com/tutorials/iphone/ios-quick-tip-from-novice-to-expert/ 翻译有误之处请勿见笑,本人将在文章的部分地方添加注释,并根据需求增减文章内容,在此对原作者辛勤劳作表示感谢  iOS Quick Tip: From Novice to Expert Bart Jacobs on Jul 29th 2013 with 5 comments Even though it's possibl