首页 > 编程知识 正文

pp助手苹果下载(ios13.3更新了什么功能)

时间:2023-05-03 15:02:26 阅读:100714 作者:9

00-1010我相信@property已经在iOS开发中使用了,@property翻译为property。定义一个类时,通常有多个@属性。使用@property,我们可以保存类的一些信息或状态。例如,定义一个学生类:

@学生界面:对象

@property(非原子,副本)NSString * name

@property(非原子,复制)NSString * sex

@end

学生类有两个属性,名字和性别。

在程序中使用时,您可以使用

self.name=@ ' xxx

self.sex=@ ' x

那么,为什么可以这样使用呢?属性中的copy和nonatomic分别代表什么?让我们一起来看看这些问题。

00-1010实际上@property=实例变量get方法set方法。也就是说,属性

@property(非原子,副本)NSString * name

表示实例变量、获取方法和设置方法。get方法用于获取变量的值,set方法用于设置变量的值。由@property生成的实例变量、get方法和set方法的命名是严格规定的。实例变量、get方法和set方法的名称将在后面介绍。

这里需要注意的是,实例变量、get方法和set方法不会真正出现在我们的编辑器中。通过使用属性生成的实例变量、get方法和set方法都是在编译过程中生成的。下面介绍set方法、get方法和自动生成的实例变量。

@property介绍

set方法也可以称为setter方法,然后可以看到setter方法可以直接理解为set方法。同样,get方法也被称为getter方法。

或者具有上述属性:

@property(非原子,副本)NSString * name

例如,由属性名生成的setter方法是

- (void)setName:(NSString *)名称;

命名方式固定,同意捆绑。如果属性名是名字,那么setter方法是:

-(void)setfirst name :(NSString *)first name;

在项目中,经常需要重写setter方法,只需重写相应的方法即可。例如,重写name属性的setter方法:

- (void)setName:(NSString *)名称

{

NSLog(@ '重写setter ');

_ name=name

}

什么是_name将在后面介绍。

00-1010带属性

@property(非原子,副本)NSString * name

例如,编译器自动生成的getter方法是

- (NSString *)名称;

getter方法的命名也是固定的。如果属性名是名字,那么getter方法是:

- (NSString *)名字;

重写getter方法:

- (NSString *)名称

{

NSLog(@ '重写getter ');

return _ name

}

如果我们如上所述定义name属性并重写getter方法和setter方法,Xcode将提示以下错误:

使用未声明的标识符“_ name”;做

you mean 'name'?

稍后我们再解释为何会有该错误,以及如何解决。先来看一下_name到底是什么。

实例变量

既然@property = 实例变量 + getter + setter,那么属性所生成的实例变量名是什么呢?根据上面的例子,也很容易猜到,项目中也经常使用,实例变量的名称就是_name。实例变量的命名也是有固定格式的,下划线+属性名。如果属性是@property firstName,那么生成的实例变量就是_firstName。这也是为何我们在setter方法和getter方法,以及其他的方法中可以使用_name的原因。

这里再提一下,无论是实例变量,还是setter、getter方法,命名都是有严格规范的。正是因为有了这种规范,编译器才能够自动生成方法,这也要求我们在项目中,对变量的命名,方法的命名遵循一定的规范。

自动合成

定义一个@property,在编译期间,编译器会生成实例变量、getter方法、setter方法,这些方法、变量是通过自动合成(autosynthesize)的方式生成并添加到类中。实际上,一个类经过编译后,会生成变量列表ivar_list,方法列表method_list,每添加一个属性,在变量列表ivar_list会添加对应的变量,如_name,方法列表method_list中会添加对应的setter方法和getter方法。

动态合成

既然有自动合成,那么相对应的就要有非自动合成,非自动合成又称为动态合成。定义一个属性,默认是自动合成的,默认会生成getter方法和setter方法,这也是为何我们可以直接使用self.属性名的原因。实际上,自动合成对应的代码是:

@synthesize name = _name;

这行代码是编译器自动生成的,无需我们来写。相应的,如果我们想要动态合成,需要自己写如下代码:

@dynamic sex;

这样代码就告诉编译器,sex属性的变量名、getter方法、setter方法由开发者自己来添加,编译器无需处理。

那么这样写和自动合成有什么区别呢?来看下面的代码:

Student *stu = [[Student alloc] init]; stu.sex = @"male";

如上编译,不会有任何问题。运行,也没问题。但是当代码执行到这一行的时候,程序崩溃了,崩溃信息是:

[Student setSex:]: unrecognized selector sent to instance 0x60000217f1a0

即:Student没有setSex方法,没有属性sex的setter方法。这就是动态合成和自动合成的区别。动态合成,需要开发者自己来写属性的setter方法和getter方法。添加上setter方法:

- (void)setSex:(NSString *)sex { _sex = sex; }

由于使用@dynamic,编译器不会自动生成变量,因此除此之外,还需要手动定义_sex变量,如下:

@interface Student : NSObject { NSString *_sex; } @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *sex; @end

现在再编译,运行,执行没有错误和崩溃。

重写setter、getter方法的注意事项

上面的例子中,重写了属性name的getter方法和setter方法,如下:

- (void)setName:(NSString *)name { NSLog(@"rewrite setter"); _name = name; } - (NSString *)name { NSLog(@"rewrite getter"); return _name; }

但是编译器会提示错误,错误信息如下:

Use of undeclared identifier '_name'; did you mean 'name'?

提示没有_name变量。为什么呢?我们没有声明@dynamic,那默认就是@autosynthesize,为何没有_name变量呢?奇怪的是,倘若我们把getter方法,或者setter方法注释掉,gettter、setter方法只留下一个,不会有错误,为什么呢?

还是编译器做了些处理。对于一个可读写的属性来说,当我们重写了其setter、getter方法时,编译器会认为开发者想手动管理@property,此时会将@property作为@dynamic来处理,因此也就不会自动生成变量。解决方法,显示的将属性和一个变量绑定:

@synthesize name = _name;

这样就没问题了。如果一个属性是只读的,重写了其getter方法时,编译器也会认为该属性是@dynamic,关于可读写、只读,下面会介绍。这里提醒一下,当项目中重写了属性的getter方法和setter方法时,注意下是否有编译的问题。

修改实例变量的名称

使用自动合成时,针对

@property (nonatomic, copy) NSString *name;

属性,生成的变量名是_name。倘若,不习惯使用下划线开头的变量名,能否指定属性对应的变量名呢?答案是可以的,使用的是上面介绍过的@synthesize关键字。如下:

@synthesize name = stuName;

这样,name属性生成的变量名就是stuName,后续使用时需要写stuName,而不是_name。如getter、setter方法:

- (void)setName:(NSString *)name { NSLog(@"rewrite setter"); stuName = name; } - (NSString *)name { NSLog(@"rewrite getter"); return stuName; }

注意:虽然可以使用@synthesize关键字修改变量名,但是如无特殊需求,不建议这样做。因为默认情况下编译器已经为我们生成了变量名,大多数的项目、开发者也都会遵循这样的规范,既然苹果已经定义了一个好的规范,为什么不遵守呢?

getter方法中为何不能用self

有经验的开发者应该都知道这一点,在getter方法中是不能使用self.的,比如:

- (NSString *)name { NSLog(@"rewrite getter"); return self.name; // 错误的写法,会造成死循环 }

原因代码注释中已经写了,这样会造成死循环。这里需要注意的是:self.name实际上就是执行了属性name的getter方法,getter方法中又调用了self.name, 会一直递归调用,直到程序崩溃。通常程序中使用:

self.name = @"aaa";

这样的方式,setter方法会被调用。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。