一个objective c基础教程-c的基本问题 为什么这个赋值不了

Posts - 69,
Articles - 0,
Comments - 969
CODING 完美世界...
17:10 by KenshinCui, ... 阅读,
概述 我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是由系统自己管理的,放在栈上)。如果一个对象创建并使用后没有得到及时释放那么就会占用大量内存。其他高级语言如C#、Java都是通过垃圾回收来(GC)解决这个问题的,但在OjbC中并没有类似的垃圾回收机制,因此它的内存管理就需要由开发人员手动维护。今天将着重介绍ObjC内存管理:
引用计数器 在Xcode4.2及之后的版本中由于引入了ARC(Automatic Reference Counting)机制,程序编译时Xcode可以自动给你的代码添加内存释放代码,如果编写手动释放代码Xcode会报错,因此在今天的内容中如果你使用的是Xcode4.2之后的版本(相信现在大部分朋友用的版本都比这个要高),必须手动关闭ARC,这样才有助于你理解ObjC的内存回收机制。
ObjC中的内存管理机制跟C语言中指针的内容是同样重要的,要开发一个程序并不难,但是优秀的程序则更测重于内存管理,它们往往占用内存更少,运行更加流畅。虽然在新版Xcode引入了ARC,但是很多时候它并不能完全解决你的问题。在Xcode中关闭ARC:项目属性—Build Settings--搜索“garbage”找到Objective-C Automatic Reference Counting设置为No即可。 内存管理原理 我们都知道在C#、Java中都有GC在自动管理内存,当我们实例化一个对象之后通常会有一个变量来引用这个对象(变量中存储对象地址),当这个引用变量不再使用之后(也就是不再引用这个对象)此时GC就会自动回收这个对象,简单的说就是:当一个对象没有任何变量引用的时候就会被回收。 例如下面的C#代码片段using S
namespace GC
class Program
private static void Test()
object o=new object();
static void Main(string[] args)
上面是一段C#代码,在Test()方法中,通过new Object()创建了一个对象,o是一个对象的引用(存储了对象的地址),它是一个局部变量,作用范围就是Test()方法内部。
当执行完Test()方法之后o就会被释放,此时由于没有变量在引用new Object()这个对象,因此GC会自动回收这个对象所占用的空间。
但是在ObjC中没有垃圾回收机制,那么ObjC中内存又是如何管理的呢?其实在ObjC中内存的管理是依赖对象引用计数器来进行的:在ObjC中每个对象内部都有一个与之对应的整数(retainCount),叫“引用计数器”,当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1(ObjC中调用一个对象的方法就是给这个对象发送一个消息),当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。
下面通过一个简单的例子看一下引用计数器的知识:
Person.h//
MemoryManage
Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@interface Person : NSObject
#pragma mark - 属性
@property (nonatomic,copy) NSString *
@property (nonatomic,assign) int
Person.m//
MemoryManage
Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "Person.h"
@implementation Person
#pragma mark - 覆盖方法
#pragma mark 重写dealloc方法,在这个方法中通常进行对象释放操作
-(void)dealloc{
NSLog(@"Invoke Person's dealloc method.");
[super dealloc];//注意最后一定要调用父类的dealloc方法(两个目的:一是父类可能有其他引用对象需要释放;二是:当前对象真正的释放操作是在super的dealloc中完成的)
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "Person.h"
void Test1(){
Person *p=[[Person alloc]init]; //调用alloc,引用计数器+1
p.name=@"Kenshin";
NSLog(@"retainCount=%lu",[p retainCount]);
//结果:retainCount=1
[p release];
//结果:Invoke Person's dealloc method.
//上面调用过release方法,p指向的对象就会被销毁,但是此时变量p中还存放着Person对象的地址,
//如果不设置p=nil,则p就是一个野指针,它指向的内存已经不属于这个程序,因此是很危险的
//如果不设置p=nil,此时如果再调用对象release会报错,但是如果此时p已经是空指针了,
//则在ObjC中给空指针发送消息是不会报错的
[p release];
void Test2(){
Person *p=[[Person alloc]init];
p.name=@"Kenshin";
NSLog(@"retainCount=%lu",[p retainCount]);
//结果:retainCount=1
[p retain];//引用计数器+1
NSLog(@"retainCount=%lu",[p retainCount]);
//结果:retainCount=2
[p release];//调用1次release引用计数器-1
NSLog(@"retainCount=%lu",[p retainCount]);
//结果:retainCount=1
[p release];
//结果:Invoke Person's dealloc method.
int main(int argc, const char * argv[]) {
@autoreleasepool {
在上面的代码中我们可以通过dealloc方法来查看是否一个对象已经被回收,如果没有被回收则有可能造成内存泄露。如果一个对象被释放之后,那么最后引用它的变量我们手动设置为nil,否则可能造成野指针错误,而且需要注意在ObjC中给空对象发送消息是不会引起错误的。
野指针错误形式在Xcode中通常表现为:Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)错误。因为你访问了一块已经不属于你的内存。
内存释放的原则
手动管理内存有时候并不容易,因为对象的引用有时候是错综复杂的,对象之间可能互相交叉引用,此时需要遵循一个法则:谁创建,谁释放。
假设现在有一个人员Person类,每个Person可能会购买一辆汽车Car,通常情况下购买汽车这个活动我们可能会单独抽取到一个方法中,同时买车的过程中我们可能会多看几辆来最终确定理想的车,现在我们的代码如下:
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@interface Car : NSObject
#pragma mark - 属性
#pragma mark 车牌号
@property (nonatomic,copy) NSString *
#pragma mark - 公共方法
#pragma mark 运行方法
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "Car.h"
@implementation Car
#pragma mark - 公共方法
#pragma mark 运行方法
-(void)run{
NSLog(@"Car(%@) run.",self.no);
#pragma mark - 覆盖方法
#pragma mark 重写dealloc方法
-(void)dealloc{
NSLog(@"Invoke Car(%@) dealloc method.",self.no);
[super dealloc];
Person.h//
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@interface Person : NSObject{
#pragma mark - 属性
#pragma mark 姓名
@property (nonatomic,copy) NSString *
#pragma mark - 公共方法
#pragma mark Car属性的set方法
-(void)setCar:(Car *)
#pragma mark
Car属性的get方法
Person.m//
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "Person.h"
#import "Car.h"
@implementation Person
#pragma mark - 公共方法
#pragma mark Car属性的set方法
-(void)setCar:(Car *)car{
if (_car!=car) { //首先判断要赋值的变量和当前成员变量是不是同一个变量
[_car release]; //释放之前的对象
_car=[car retain];//赋值时重新retain
#pragma mark
Car属性的get方法
-(Car *)car{
#pragma mark - 覆盖方法
#pragma mark 重写dealloc方法
-(void)dealloc{
NSLog(@"Invoke Person(%@) dealloc method.",self.name);
[_car release];//在此释放对象,即使没有赋值过由于空指针也不会出错
[super dealloc];
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "Person.h"
#import "Car.h"
void getCar(Person *p){
Car *car1=[[Car alloc]init];
car1.no=@"888888";
p.car=car1;
NSLog(@"retainCount(p)=%lu",[p retainCount]);
Car *car2=[[Car alloc]init];
car2.no=@"666666";
[car1 release];
[car2 release];
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p=[[Person alloc]init];
p.name=@"Kenshin";
getCar(p);
[p.car run];
[p release];
程序运行结果:
从运行结果来看创建的三个对象p、car1、car2都被回收了,而且[p.car run]也能顺利运行,已经达到了我们的需求。但是这里需要重点解释一下setCar方法的实现,setCar方法中为什么没有写成如下形式:-(void)setCar:(Car *)car{
前面在我们说到属性的定义时不是都采用的这种方式吗?
根据前面说到的内存释放原则,getCar方法完全符合,在这个方法中定义的两个对象car1、car2也都是在这个方法中释放的,包括main函数中的p对象也是在main函数中定义和释放的。但是如果发现调用完getCar方法之后紧接着调用了汽车的run方法,当然这在程序设计和开发过程中应该是再普通不过的设计了。如果setCar写成“_car=car”的形式,当调用完getCar方法后,人员的car属性被释放了,此时调用run方法是会报错的(大家自己可以试试)。但是如下的方式却不会有问题:-(void)setCar:(Car *)car{
if (_car!=car) { //首先判断要赋值的变量和当前成员变量是不是同一个变量
[_car release]; //释放之前的对象
_car=[car retain];//赋值时重新retain
因为在这个方法中我们通过[car retain]保证每次属性赋值的时候对象引用计数器+1,这样一来调用过getCar方法可以保证人员的car属性不会被释放,其次为了保证上一次的赋值对象(car1)能够正常释放,我们在赋新值之前对原有的值进行release操作。最后在Person的dealloc方法中对_car进行一次release操作(因为setCar中做了一次retain操作)保证_car能正常回收。
像上面这样编写setCar方法的情况是比较多的,那么如何使用@property进行自动实现呢?答案就是使用属性参数,例如上面car属性的setter方法,可以通过@property定义如下:@property (nonatomic,retain) Car *
你会发现此刻我们不必手动实现car的getter、setter方法程序仍然没有内存泄露。其实大家也应该都已经看到前面Person的name属性定义的时候我们同样加上了(nonatomic,copy)参数,这些参数到底是什么意思呢?
@property的参数分为三类,也就是说参数最多可以有三个,中间用逗号分隔,每类参数可以从上表三类参数中人选一个。如果不进行设置或者只设置其中一类参数,程序会使用三类中的各个默认参数,默认参数:(atomic,readwrite,assign)
一般情况下如果在多线程开发中一个属性可能会被两个及两个以上的线程同时访问,此时可以考虑atomic属性,否则建议使用nonatomic,不加锁,效率较高;readwirte方法会生成getter、setter两个方法,如果使用readonly则只生成getter方法;关于set方法处理需要特别说明,假设我们定义一个属性a,这里列出三种方式的生成代码:
assign,用于基本数据类型-(void)setA:(int)a{
retain,通常用于非字符串对象-(void)setA:(Car *)a{
if(_a!=a){
[_a release];
_a=[a retain];
copy,通常用于字符串对象-(void)setA:(NSString *)a{
if(_a!=a){
[_a release];
_a=[a copy];
自动释放池
在ObjC中也有一种内存自动释放的机制叫做“自动引用计数”(或“自动释放池”),与C#、Java不同的是,这只是一种半自动的机制,有些操作还是需要我们手动设置的。自动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelase方法,那么当代码块执行完之后,在块中调用过autorelease方法的对象都会自动调用一次release方法。这样一来就起到了自动释放的作用,同时对象的销毁过程也得到了延迟(统一调用release方法)。看下面的代码:
Person.h//
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
@interface Person : NSObject
#pragma mark - 属性
#pragma mark 姓名
@property (nonatomic,copy) NSString *
#pragma mark - 公共方法
#pragma mark 带参数的构造函数
-(Person *)initWithName:(NSString *)
#pragma mark 取得一个对象(静态方法)
+(Person *)personWithName:(NSString *)
Person.m//
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import "Person.h"
@implementation Person
#pragma mark - 公共方法
#pragma mark 带参数的构造函数
-(Person *)initWithName:(NSString *)name{
if(self=[super init]){
self.name=
#pragma mark 取得一个对象(静态方法)
+(Person *)personWithName:(NSString *)name{
Person *p=[[[Person alloc]initWithName:name] autorelease];//注意这里调用了autorelease
#pragma mark - 覆盖方法
#pragma mark 重写dealloc方法
-(void)dealloc{
NSLog(@"Invoke Person(%@) dealloc method.",self.name);
[super dealloc];
MemoryManage
Created by Kenshin Cui on 14-2-15.
Copyright (c) 2014年 Kenshin Cui. All rights reserved.
#import &Foundation/Foundation.h&
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person1=[[Person alloc]init];
[person1 autorelease];//调用了autorelease方法后面就不需要手动调用release方法了
person1.name=@"Kenshin";//由于autorelease是延迟释放,所以这里仍然可以使用person1
Person *person2=[[[Person alloc]initWithName:@"Kaoru"] autorelease];//调用了autorelease方法
Person *person3=[Person personWithName:@"rosa"];//内部已经调用了autorelease,所以不需要手动释放,这也符合内存管理原则,因为这里并没有alloc所以不需要release或者autorelease
Person *person4=[Person personWithName:@"jack"];
[person4 retain];
Invoke Person(rosa) dealloc method.
Invoke Person(Kaoru) dealloc method.
Invoke Person(Kenshin) dealloc method.
当上面@autoreleaespool代码块执行完之后,三个对象都得到了释放,但是person4并没有释放,原因很简单,由于我们手动retain了一次,当自动释放池释放后调用四个对的release方法,当调用完person4的release之后它的引用计数器为1,所有它并没有释放(这是一个反例,会造成内存泄露);autorelase方法将一个对象的内存释放延迟到了自动释放池销毁的时候,因此上面person1,调用完autorelase之后它还存在,因此给name赋值不会有任何问题;在ObjC中通常如果一个静态方法返回一个对象本身的话,在静态方法中我们需要调用autorelease方法,因为按照内存释放原则,在外部使用时不会进行alloc操作也就不需要再调用release或者autorelase,所以这个操作需要放到静态方法内部完成。
对于自动内存释放简单总结一下:
autorelease方法不会改变对象的引用计数器,只是将这个对象放到自动释放池中;
自动释放池实质是当自动释放池销毁后调用对象的release方法,不一定就能销毁对象(例如如果一个对象的引用计数器&1则此时就无法销毁);
由于自动释放池最后统一销毁对象,因此如果一个操作比较占用内存(对象比较多或者对象占用资源比较多),最好不要放到自动释放池或者考虑放到多个自动释放池;
ObjC中类库中的静态方法一般都不需要手动释放,内部已经调用了autorelease方法;快速让你入门Objective-C语言_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
快速让你入门Objective-C语言
入​门​O​b​j​e​c​t​i​v​e​-​C​语​言
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢用objective-c编一个程序输入任意数,输出每位对照的英文,但遇到问题_百度知道
提问者采纳
int main(做个循环;eight\:
NSLog(@&nine\seven\ i ++) {&#47。switch ([str intValue]) {
case 7;/n&quot,又是你;将C语言格式的字符串转化为OC格式的字符串
NSString *oc_tmp_str = oc_Foundation/
&#47:),str],次数上限为字符串长度
NSRange range = {1.h&gt.location];);n&six\
break,str):
NSString *str = [oc_tmp_str substringToI
n&, const char * argv[]){@autoreleasepool {char str[1000];
return 0;); i &n&two&#92,2};three\one\%s&/&#47:
case 1,如此循环到结束即可;
&#47。C语言我语法记不清楚了;/n&
/four\five&#92:
NSLog(@&%s&):
n&quot。上次的问题忘了给你写了;&#47:
NSLog(@&quot:);
case 8;),赋值给str
oc_tmp_str = [oc_tmp_str substringFromIndex:
);//将第二位到最后以为重新赋值给oc_tmp_zero&#92:
NSLog(@&quot。这次写一下,用作下次循环种截取第一位。别忘了采纳哦~另外的问题也要采纳哦亲~~~#import &/
break.location];将转化完的字符串复制一份for (int i = 0;n&quot。既然你说你是学oc的;n&/
Fn&quot,这个使用控制台写的,我就用oc写; oc_string.
case 9;n&取字符串第一位,直接复制代码就行;);接收键盘输入的内容
NSString *oc_string = [NSString stringWithF申明一个char类型数组;):
NSLog(@&quot,也就是字符串
scanf(&quot:
提问者评价
其他类似问题
为您推荐:
其他1条回答
浮点数精度问题,换个思路把各数位上的数字分开再判断就可以了
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁Objective-C 拾遗 - 做个不善的人 - 博客园
关于Method&
这里引入method specification的概念(我自己弄的,因为不了解官方的名称是什么,如果有人知道,请告诉我)。在C中,一个函数的方法名(区分大小写),也就是说,如果两个函数的方法名相同,即使参数个数或者参数类型不同,那么也认为这两个方法是一样的,从而产生错误(在C语言中是编译时错误),比如下面的代码:
void foo() //valid
int foo() //Error
error C2371: 'foo' : different basic types
void Foo() //valid
void foo(int a) //Error
error C2084: function 'void foo()' already has a body
C++引入了重载的概念,所以method specification包含方法名、参数个数及其类型。这里就不举例了。下面看Objective-C中method specification。
用习惯了C/C++,理解Objective-C的method specification着实费劲。因为Objective-C中method specification是由方法名加参数名构成的,举例来说:
#import &Foundation/Foundation.h&
@interface Tester : NSObject
- (void) test:(NSString *)msg:(Tester *)sec:(int)
- (void) test:(NSString *)msg secondAr0:(Tester *)sec ThirdArg0:(int)
- (void) test:(NSString *)msg secondAr:(Tester *)sec ThirdArg: (int)
- (void) test:(NSString *)
- (void) test:(NSString *)msg2;
- (void) test0;
//- (void) test:(int *) //Duplicate declaration of method 'test:'
-(void) notI
#import "Tester.h"
@implementation Tester
- (void) test:(NSString *)msg :(Tester *)sec :(int)third
NSLog(@"current method is %@",NSStringFromSelector(_cmd));
- (void) test:(NSString *)msg secondAr0:(Tester *)sec ThirdArg0:(int)third
NSLog(@"current method is %@",NSStringFromSelector(_cmd));
- (void) test:(NSString *)msg secondAr:(Tester *)sec ThirdArg: (int)third
NSLog(@"current method is %@",NSStringFromSelector(_cmd));
-(void)test:(NSString *)msg
NSLog(@"current method is %@",NSStringFromSelector(_cmd));
-(void)test0
NSLog(@"current method is %@",NSStringFromSelector(_cmd));
//- (void) test:(NSString *)msg2 //Duplicate declaration of method 'test:'
NSLog(@"current method is %@",NSStringFromSelector(_cmd));
-(void)notImp
NSLog(@"test notImp");
int main(int argc, const char * argv[])
@autoreleasepool {
id tester = [[Tester alloc] init];
[tester test:@"" :tester :1];
[tester test:@""
secondAr0:tester
ThirdArg0:1];
[tester test:@""
secondAr:tester
ThirdArg:1];
[tester test:@""];
[tester test0];
[tester test:@"" :tester :1];
将错误的部分注释后,输出结果如下:
2013-03-01 18:16:03.119 TestSelector[12056:403] current method is test:::
2013-03-01 18:16:03.121 TestSelector[12056:403] current method is test:secondAr0:ThirdArg0:
2013-03-01 18:16:03.122 TestSelector[12056:403] current method is test:secondAr:ThirdArg:
2013-03-01 18:16:03.122 TestSelector[12056:403] current method is test:
2013-03-01 18:16:03.123 TestSelector[12056:403] current method is test0
2013-03-01 18:16:03.123 TestSelector[12056:403] current method is test:::
2013-03-01 18:16:03.124 TestSelector[12056:403] current method is test:
&可以看到,如果给某个参数起名字,那会把这个名字加一个':'作为那方法的specification的一部分,如果不给参数命名,那就只加一个':'。如果参数被命名,那之后调用时也必须指明这个名字。
attribute, to-one relationship , to-many relationship
attribute: 比如学生的姓名、年龄等;attribute往往是NSString, NSDate, NSData的实例;
to-one relationship: 比较像attribute,不过其类型要复杂一些,比如每个学生有个学校与之关联。to-one relationship往往使用指针实现;
sorted to-many relationship: 比如每个playlist都包含若干歌曲,其要么按加入时间排序、要么按名字排序,或者其他的排序方式。其典型的使用NSMutableArray来实现。
unsorted to-manay relationship: 比如每个部门都有一些员工,这种情况是没有顺序的。往往使用NSMutableSet实现;
== 和 isEqual 的关系
Imagine you have a pair of one dollar bills. Both bills are &equal&, because you could use either bill to pay for a one dollar item.
They are however not identical. Each bill has a unique serial number that indicates when and where it was made. No two dollar bills have the same serial number. If you told me the serial number of one of the bills, you could put in in a pile with thousands of other bills and I would still be able to uniquely identify that particular bill.
Now imagine the same test with coins instead of dollar bills. While coins do have some slight variation (the year and pressing facility may vary), I can easily aquire a bag of 1000 quarters, all of which are not only equal but identical. There is no way to identity a particular quarter once it has been thrown in a pile of identical quarters.
Objects (NSObject, NSView, etc) are like dollar bills, each one is unique but may be equal to others,but not identical. Primitives (int,float,char) are like coins, if they are equal then they are identical.
在Objecitve C中,a==b意思是问,这两个对象是否identical, 而[a isEqual:b]意思是问,这两个对象是否equal。对于object来说,如果a==b为真,那么[a isEqual:b]也为真,但反之就不一定成立。而对于primitive类型而言,则反之也是成立的。
再来看看isEqual和hash的关系,Apple的文档中说hash是返回一个整形,用来在hash table中作为table address。如果两个对象是equal的(用isEqual判断),那么他们就应该具有相同的hash值。如果一个mutable的对象被加入到一个collection中,在此期间,其hash值不能变化。因此 hash值的计算要么就不依赖对象的内部状态,要么就是依赖内部状态,但内部状态在被加入到hash table期间不能被改变。
Objective C中支持两种字符串:C字符串和NSString字符串。NSString字符串常量前面带有@符号,而C字符串则没有。
// C string
// NSString
NSString *
foo = "this is a C string";
bar = @"this is an NSString";
NSString会被更经常地用到,它们之间可以进行转换,下面是转换的例子:
const char *foo = "Blah blah";
NSString *
//Create an NSString from a C string
bar = [NSString stringWithUTF8String:foo];
//Create a C string from a NSString
foo = [bar UTF8String];
因为NSString可以是Unicode的字符串,所以你要正确的处理C字符串的多字节的字符,通常这有些难且废时。(处理多字节字符问题,你可能还会遇到有些语言是从右向左读这样的问题) 不管怎么样,尽量用NSString代替C字符串
property和synthesize
这是在Objective C 2.0中引入的新关键字。其目的是为了简化Property的实现。以前的时候,要实现一个Property,我们需要声明一个instance variable,然后定义并实现两个accesser,比如下面的代码:
@class Test {
-(void)setCount:(int)newC
- (int)count
-(void)setCount:(int)newCount
count = newC
使用新的关键字后,就可以使用property代替.h文件中的代码,使用synthesize代替.m中的代码了。新代码如下所示:
@property int
@synthesize
property的使用语法是:@property (参数1,参数2,参数3) 类型 名字;其中()中的参数个数是可选的,其参数有以下3种类型:
读写属性: (readwrite/readonly)setter语意:(assign/retain/copy)原子性: (【atomicity】/nonatomic)
被加粗的参数是默认值,也就是这个类别中任何值都没有被指定时使用的值,对于原子性,只有nonatomic关键字,表示不是原子访问的,但它不是默认值。下面对这些值分别介绍一下:
readonly此标记说明属性是只读的,默认的标记是读写,如果你指定了只读,在@implementation中只需要一个读取器。或者如果你使用@synthesize关键字,也是有读取器方法被解析。而且如果你试图使用点操作符为属性赋值,你将得到一个编译错误。 readwrite此标记说明属性会被当成读写的,这也是默认属性。设置器和读取器都需要在@implementation中实现。如果使用@synthesize关键字,读取器和设置器都会被解析。 assign此标记说明设置器直接进行赋值,这也是默认值。在使用垃圾收集的应用程序中,如果你要一个属性使用assign,且这个类符合NSCopying协议,你就要明确指出这个标记,而不是简单地使用默认值,否则的话,你将得到一个编译警告。这再次向编译器说明你确实需要赋值,即使它是可拷贝的。 retain指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数&&译者注)。 copy它指出,在赋值时使用传入值的一份拷贝。拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。更深入的讨论,请参考&复制&部分。 nonatomic指出访问器不是原子操作,而默认地,访问器是原子操作。这也就是说,在多线程环境下,解析的访问器提供一个对属性的安全访问,从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行访问。如果你不指定nonatomic,在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic,那么访问器只是简单地返回这个值。
IBAction and IBOutlet&
IBAction and IBOutlet are macros defined to denote variables and methods that can be referred to in Interface Builder.其定义如下:
#ifndef IBOutlet
#define IBOutlet
#ifndef IBAction
#define IBAction void
IBAction resolves to "void" and IBOutlet resolves to nothing, but they signify to Xcode and Interface builder that these variables and methods can be used in Interface builder to link UI elements to your code.
If you're not going to be used Interface Builder at all, then you don't need them in your code, but if you are going to use it, then you need to specify IBAction for methods that will be used in IB and IBOutlet for objects that will be used in IB.
看看什么地方可以有IBAction和IBOutlet,在IB中可以将UI上的元素跟File's Owner, Application, First Responder(?), Shared User Defaults(?) , Object, Object Controller, Managed Object Context. 所以这这些类中是可以是使用IBAction和IBOutlet的,其他地方,即使用了,也无法跟UI上的元素进行link。
关于new和alloc init&
&nil, NSNull
阅读(...) 评论()
随笔: 335

我要回帖

更多关于 objective c基础教程 的文章

 

随机推荐