清楚常量字符串和一般字符串的区别

在Objective-C,经常会用到常量字符串,常量字符串和一般的字符串还是有一定区别的.本节将介绍一些常量字符串的特性,用来加强对常量字符串的理解.请看下面一段代码.

NSSting *sting1 = @"Hello";
NSSting *sting2 = @"Hello";
if (sting1 == sting2) {
    NSLog(@"They are same address");
}

对字符串常量sting1和sting2的地址值进行比较,就会发现二者竟然是相等的,产生这样的结果要归咎于编译器优化的结果.

由于常量会占用一块特殊的代码段,加载到内存是会映射到一块常量存储区,以加快访问速度,编译器在编译时发现sting1和sting2的内容是相同的常量字符串,会把它们都指向一个相同的区域,而不是在开辟出一块额外的空间.因此,它们是相同的地址值.

NSSting *sting1 = @"Hello";
NSSting *sting2 = [NSSting alloc];  NSSting *sting3 = [sting2 initWithSting:sting1];        if (sting1 == sting2) {
    NSLog(@"sting2 are not same to sting3!");
}
    if (sting1 == sting3) {
    NSLog(@"sting1 are not same to sting3!");
}

首先,申明上面这一段代码不是一段合法的代码,因此在第2行alloc之后没有立即init.虽然这种做法是非常不推荐的,但这次为了更加清晰地说明问题,不得而已为之.

通过程序比较分析,就会发现sting2和sting3的地址竟然不相等,而sting1和sting3竟然相等.通过这些可以看出,如果使用一个常量字符串来初始化另一个字符串,另一个字符串会直接通过地址赋值为常量字符串,alloc的内存也会立即释放.再看看下面这段代码:

NSSting *sting1 = [[NSSting alloc]initWithSting:@"Hello"];
[sting1 release];
[sting1 release];
[sting1 release];
NSLog("%@", sting1);

sting1经过多次release竟然还能继续访问,由此说明常量字符串不会release

在Objective-C语言中,集合是最常用的数据类型.而对与集合的访问,要优先考虑使用快速枚举.使用快速枚举,要尽可能使用枚举新的写法.

尽可使用枚举新的写法

使用Objective-C新的枚举写法,编写更简洁的代码,同时避免一些常见的陷阱.更重要的是,这些语法特性是完全向下兼容的,使用新特性编写后形成的二进制程序可以运行之前发布的OS中.

在使用枚举新的写法之前,先梳理一下最近几年来枚举类型几次功能的改进.
枚举在OS X10.5之前的版本中,如何在Objective-C中定义一个枚举类型呢?定义方法如下:

typedef enum {
ObjectiveC,
Java,
Ruby,
Python,
Erlang
}
Language;

这种写法简单明了,用起来也不复杂,但是有一个问题,就是其枚举值得数据范围是模糊的,这个数值可能非常大,可是负数,无法界定.
在OSX 10.5之后 的版本中,就可以这样写:

    enum{
    ObjectiveC,
    Java,
    Ruby,
    Python,
    Erlang
    };
    typedef NSUInteger Language;
    
这种写法的好处是,首先这个枚举的数据类型是确定的,无符号整数;其次,由于采用了NSUInteger,就可以不用考虑32位和64位的问题.但这样写所带来的问题是,数据类型和枚举常量没有显示的关联在Xcode4.4,就可以这样写枚举:

    typedef enum Language:NSUInteger {
    ObjectiveC,
        Java,
        Ruby,
        Python,
        Erlang
        }Language;

在列出枚举内容的同时绑定了枚举数据类型NSUInteger,这样带来的好处是增强了类型检查和更好的代码可读性.

当然,对于普通开发者来说,枚举类型可能不会涉及复杂的数据,使用之前的两种写法也不会用什么大问题,但还是建议使用枚举的写法,以增强现在写的代码在未来中有更强的适用性.

上面介绍了为何尽可能使用枚举新的写法,下面将介绍枚举在集合中的应用.
Objective-C和Cocoa或Cocoa Touch提供了多种方式来枚举集合的内容.虽然它可以使用传统的C循环来遍历内容,像这样:

int count = [array count];
for(int index = 0;index < count; index++) {
    id eachObject = [array objectAtIndex:index];
    ...
}

这时最好的做法是使用本节中描述的其他技术之一.

理解快速枚举

快速枚举是一种语言中用于快速安全的枚举一个集合的表达式,下面将从快速枚举的定义及其应用来分别介绍.
for...in表达式,这种快速枚举表达式是如下定义的:

for(existingItem in expression) {
    statements
}

这两种表达式中,expression 是一个遵守NSFastEnmeration协议的对象.每次循环被迭代的对象都会返回一个对象并赋给一个循环变量,同时statements 中定义的代码被执行一次.当被迭代的对象中已经没有数据可以取出时,循环变量被设为nil,如果循环在这之前被停止,那么循环变量会指向最后一次返回的值.

使用快速枚举可以很容易地枚举集合

许多集合类遵照了NSFastEnumeration协议,如Foundation中的集合类NSArray、NSDictionary和NSSet.显而易见,枚举操作可以遍历NSArray和NSSet的内容.对于其他类,相关文档会说明哪些内容会被枚举.例如,NSDictionary和NSManagedObjectModel也支持快速枚举但是NSDictionary枚举的是它的键值,NSManagedObjectModel枚举的是它的实体.

作为一个例子,可以使用快速枚举,像这样在每一个数组记录每个对象的描述:

for(id eachObject in array){
id object = dictionary[eachKey];
NSLog(@"object:%@for key:%@",object,eachKey);
}

快速枚举的行为很像一个标准C循环,这样就可以使用打破关键字来中断迭代,或继续前进到下一个元素.如果枚举有序的集合,枚举按顺序来进行.对于一个NSArray,这意味着第一次将索引为0,第二个对象在索引1处等等.如果需要跟踪当前索引,只需迭代计数,因为它们发生:

int index = 0;
    for(id eachObject in array) {
    NSLog(@"Object at index %i is:%@",index,eachObject);
    index++
    }

在快速枚举集合期间,不能变异集合,即使集合是可变的.如果从循环内,尝试添加或删除集合的对象,则会生成运行时异常.

大多数集合也支持枚举对象

也可以通过使用NSEnumerator对象枚举Cocoa和Cocoa Touch中的许多集合.例如,对于objectEnmerator 或reverseObjectEnumerator,可以查询NSArray.快速枚举可以使用这些对象,像这样:

for(id eachObject in[array reverseObjectEnumerator]) {
...
}

从此示例中,循环将按照相反的顺序来让变数可以递回取得集合的对象,所以最后一个对象将是第一个,等等.通过反复调用枚举的nextObject的方法,它也可以遍历这些内容,像这样:

id eachObject;
 while ((eachObject = [enumerator nextObject])) {
    NSLog(@"Current object is:%@",eachObject);
 }

在这个例子中,一个 while 循环用于将eachObject变量设置为每次循环的下一给对象.当没有更多的对象保留时间,nextObject方法将返回nil.评估为false的逻辑值,以使循环停止.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 在oc中,经常会用到常量字符串,常量字符串和一般字符串还是有一定区别的。 对字符串常量string1 和strin...
    花生儿阅读 2,180评论 0 3
  • 值相同的2个不同的常量字符串内存地址是相同的。这是编译器优化的结果。常量在内存中被放置在常量存储区。 如果你用字符...
    Stroman阅读 560评论 0 0
  • hh,随便哟西,随便一写。有些时候,突然想把自己的想法表达出来,但当提笔的那一刻却一想,这些又算得了什么,值得去写...
    庄德坤阅读 164评论 0 0
  • 口腔期 唇齿相依 产后抑郁症,孩子从父母眼里读到的是个例,自闭症,孩子的孤独症自闭症,来自于母亲的产后抑郁。口欲期...
    少儿创客阅读 127评论 0 0