属性的声明以关键字@property开始。该关键字可以出现在类的接口定义@interface中的方法列表中的任何地方。同时,@property还可以在协议或者是类别的声明中出现。
@property(attributes) type name;
其中的@property指令用来声明属性。其后可选的括号中的项是对属性的存储方式和其行为的细节描述。和其他的Objective-C中的类型一样,每一个属性都有一个类型修饰符和名称。
列表5-1展示了简单的属性的声明
@interface MyClass:NSObject { float value; } @proerty float value; @end
我们可以把属性的声明看作等同于声明了两个访问方法。因此
@property float value;
相当于:
-(float) value;
-(void) setValue:(float)newValue;
然而,属性的声明为如何实现对应的访问方法提供了更多的信息。(具体请参见“声明属性的属性”)。
属性的属性(Property Declaration Attributes)
译者注:Property和Attribute直译过来都是“属性”,为了避免混淆,本小节中分别使用Property和Attribute两个英文单词。
我们可以使用下面的形式来对Property进行修饰:
@property( attribute [, attribute2, ...])
和方法一样,Property的作用域局限于声明他的接口中。如果在声明Property时使用了逗号把多个Property的名称分隔开,那么其中的Attribute对所有Property都是适用的。
如果我们使用了@synthesize指令来告诉编译器自动创建访问方法,那么编译器创建的访问方法将是符合Attribute中的描述的。如果我们自己实现这些访问方法,我们必须保证自己的实现和Attribute中的描述是相一致的。(例如,如果我们在Attribute中指定了copy关键字,那么我们必须在实现setter的时候对输入的值进行copy赋值)。
访问方法的名称
和属性相关的getter和setter方法的缺省名称为:属性名称和set属性名称。例如,有属性,其名称为foo,那么缺省的getter方法的名称就是foo;setter方法的名称就为setFoo:。下面的attribute允许我们来自己定义getter和setter方法的名称。这些attribute都是可选的,并且几乎可以和其他的attribute一起出现(例外:readonly和setter=不能同时出现)。
getter=getterName
用于指定属性getter方法的名称。属性的getter方法的返回值必须和属性的类型是一样的,并且不能接收参数。
setter=setterName
由于指定属性的setter方法的名称。书香的setter方法必须接收一个和属性类型相同的参数,并且返回值必须是void的。如果属性被指定为是readonly(只读)的,那么指定其setter方法将会导致编译器报告错误。
可写性
下面的attributes将限定property是否有相关的setter方法。他们是互斥的。
readwrite
表示属性是可读写的。这个也是缺省的attribute。
在实现代码中,getter和setter都是要实现的。如果在实现代码中使用了@synthesize指令,那么编译器会自动生成getter和setter方法。
readonly
表示property是只读的。
如果使用了readonly attribute,那么在@impementation代码块中只需要实现getter方法。如果使用了@synthesize指令,那么也只有getter方法会被自动生成。如果使用点号运算符企图对其进行赋值,编译器会报错。
关于setter下面的attributes表明了setter方法设置值时候的方法。他们是互斥的。
assign
表明只是简单的赋值。这个是缺省的。
通常只用于标量类型。例如,NSInteger和CGRect,或者是位置类型的对象,如delegetes。
retian和assign在支持垃圾回收环境中是等效的。
retain
表明在对象赋值的时候应该持有该对象。
之前的对象会被发送release消息。
在Mac OS X v10.6之前的版本中,这个attribute只是用于Objective-C的对象类型(也就是说不能向一个Core Foundation对象发送retian消息的)。
在Mac OS X v10.6及其之后的版本中,可以使用__attribute__关键字来表明Core Fundation属性应该按照Objective-C的对象来进行内存管理:
@property(retian) __attribute__((NSObject)) CFDictionaryRef myDictionary;
copy
表明应该使用对象的一个副本来进行赋值。
之前的对象会被发送release消息。
副本是通过向对象发送copy消息而得到的。这个attribute只适用于对象类型,并且要求该对象实现了NSCopying协议。更多信息请参见“拷贝”章节。
这些不同限制的使用和是否使用垃圾回收机制有关:
●如果没有使用垃圾回收机制,对于对象属性来说我们必须显示地指明是assign,retian还是copy。否则编译时候会报告错误或者警告(这种限制促使我们谨慎考虑自己到底需要使用什么样的内存管理机制并且显示地指定它)。
为了明确自己到底需要什么样子的内存管理方式,我们需要深入了解Cocoa的内存管理策略(参见《内存管理编程指南》一书)。
●如果使用了垃圾回收机制,使用缺省的attribute(也就是没有指定是assign,retian还是copy)不会导致编译告警。除非属性对应的类型遵守NSCopying协议。
缺省的attribute通常就是我们所需要的;如果属性的类型是可以复制的,为了达到封装的目的,通常我们都是会使用拷贝的副本。
原子性我们可以使用下面的attribute来标明访问方法是非原子的:
nonatomic
该attribute标明访问方法是非原子的。缺省情况下访问方法是原子的。
缺省情况访问方法是原子的可以保证在多线程的环境中对属性的访问具有更好的鲁棒性。也就是说getter方法返回的值或者是setter方法设置值都是充分完好的,而不管多个线程是如何并发执行的。更多详细信息请参阅“性能和线程”章节。
如果我们使用了retain或者copy而没有使用nonatomic,那么在引用计数环境中,自动生成的getter方法中会先上锁,然后在持有原来的对象,再向对象发送autorelease方法,最后解锁并返回其值。这种实现类似如下:
[_internal lock] //使用对象级的锁
id result = [[value retian] autorelease];
[_internal unlock];
return result;
如果使用了nonatomic,自动生成的方法方法仅仅是简单直接地返回其值。
nested push animation can result in corrupted navigation bar
嵌套的navigation动画会造成 navigation bar 错误, 具体表现为上一层的titleview 和这一层重叠, navigationbaritem 维持上一层的左按钮, 右按钮 、、、系统警告提示nested push animation can result in corrupted navigation bar , 大家遇到过这种情况吗?? 嵌套的动画, 是什么意思呢, 为什么会这样, 要怎么解决
结贴~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
有一天,从头到尾分析了整个项目的代码, 最后确认问题根源——自定义UITabbarController引发的血案
项目中使用了自定义的UITabbarController ,修改里面的tabbar视图, 在这个UITabbarController 中实现了viewWillAppear方法, 里面没有加super viewWillAppear , 结果导致了这一连串的问题,
整个软件里面,都会出现弹一次模态窗口,导航视图就会动画乱序,
导航视图前进后退过快, 导致导航栏嵌套, 一个上面覆盖另一个。
此遗憾了结
在iOS开发中为了方便管理资源文件,可以使用bundle的方式来进行管理,我们可以将不同模块用到的资源文件放到不同的包中。目前iOS中只允许使用bundle管理资源文件和国际化信息,不支持代码的打包。
按照下面的步骤创建一个文件包:
1、在磁盘中创建一个根文件夹,这也就是最终的文件包,例如,我们把这个文件夹命名为Resources。
2、在Resources文件夹下创建3个命名为pictures、videos和audios的子文件夹。
3、在上面提到的3个子文件夹内分别放入相应的资源,例如在pictures文件夹中放入一张或者多张图片,在videos文件夹中放入一个或者多个视频文件,在audios文件夹中放入一个或者多个音频文件等。
4、完成以上步骤之后,将Resources文件夹重新命名为Resources.bundle,一旦给文件命名时加上这个扩展名,OS X会要求你确认并弹出一个如图所示的对话框,点击添加以便在文件夹中能够增加.bundle扩展名。
文件包是一个以.bundle为扩展名的文件包,和普通文件夹相比,它有2个主要特点:
1、 Cocoa Touch提供了一个界面,通过这个界面你可以进入相应的文件包简单获取里面的已有资源。
2、如果在Xcode左侧导航窗口增加一个文件包,任何文件增加或者移出文件包,将分别立即出现或者消失在Xcode导航窗口。相反,如果你在Xcode导航中增加了一个文件夹,然后再去删除磁盘中这个文件夹中的文件,在没有Xcode的帮助下,这个文件将会变成红色并且不能立即删除。文件包非常有用,特别是你想在文件夹中通过Finder而非Xcode手动增加文件。
每个iOS应用至少有一个文件包,叫做主文件包。主文件包包含你的应用软件中的二进制代码和其他在应用软件中使用的资源,例如影像、声音、HTML文件和其他相关文件。换言之,主文件包包含了你提交给App Store或者发布到自己组织内部的最终二进制文件中的资源,这些资源可以用NSBundle类的mainBundle类的方法动态加载。
以下代码用来获取Pics包中名为bg-img的png图片:
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"Pics" ofType:@"bundle"]]; NSString *path = [bundle pathForResource:@"bg-img" ofType:@"png"]; UIImage *image = [UIImage imageWithContentsOfFile:path];
更详细的信息请参考:Bundle Programming Guide