@property(nonatomic,strong)NSString *people;
则在类内可以直接调用成员变量_people。
@interface People : NSObject
/*
声明方法
- 、+ 是方法的类型,(-代表对象方法(用对象名来调用),+代表类方法(用类名来调用)),
(加号方法和减号方法可以互相调用,但是需要类名和实例化变量,加号方法不能调用成员变量。)
*/
- (void)report;
+ (void)report;
@end
在对象方法中调用类方法,和在类方法中调用对象方法
/* .m文件对方法的实现 */
- (void)report
{
NSLog(@"- 号: report");
[People report1];
}
+ (void)report1
{
NSLog(@"+ 号:report1");
[[People alloc] report];
}
//初始化方法
- (id)init;
/* id类型是万能类型,可以返回各种类型对象 */
-(instancetype)init;
/* instancetype代表当前类的类型 */
对于选择哪个,在初始化方法中都行,对于其他的一些方法,填id会导致错误,一般填写instancetype。
如下代码
@interface NSArray
+ (id) creatAnArray;
@end
当我们用如下方式初始化NSArray时:
[NSArray creatAnArray];
得到的返回类型将和方法声明的返回类型一样,是id;
但当我们将id改为instancetype时:
@interface NSArray
+ (instancetype) creatAnArray;
@end
再用刚同样的方式初始化时:
[NSArray creatAnArray];
得到的返回类型将会和方法所在类的类型相同,是NSArray*;
id在编译的时候不能判断对象的真实类型
instancetype在编译的时候可以判断对象的真实类型
如果init方法的返回值是instancetype,那么将返回值赋值给一个其它的对象会报一个警告
如果是在以前, init的返回值是id,那么将init返回的对象地址赋值给其它对象是不会报错的
id可以用来定义变量, 可以作为返回值, 可以作为形参
instancetype只能用于作为返回值,例如:
//err,expected a type
- (void)setValue:(instancetype)value
{
//do something
}
就是错的,应该写成:
- (void)setValue:(id)value
{
//do something
}
参考自iOS instancetype 和 id 区别详解
@interface MyClass : NSObject
{
//成员变量访问修饰符的问题
//默认 - 受保护
//公有 - 在类内类外都可以使用
@public
int _classInt; /*声明为公有成员类型,则在类外也可以被调用,但是要用指向(->)调用*/
//私有 - 在类内可以使用,类外无法调用并且不能被继承
@private
//受保护 - 在类内可以使用,类外无法调用并且可以被继承
@protected
//框架权限 - 在框架内相当于受保护,在框架外相当于私有
@package
}
@property(nonatomic,strong)NSString *className;
//方法是没有访问修饰符的同C语言一样
- (void)report;
@end
在苹果引入ARC之后,修饰符有所增加
ARC中加入以下修饰符
strong: 强引用,类似于retain。要求保留传入的对象,并放弃原有对象。一个对象只要被至少一个强引用指向,则其不会被释放,而当没有强引用指向时则会被释放。在ARC下是对象类型的默认值。
weak: 弱引用,要求不保留传入的属性(既不会使传入的对象引用计数+1)。类似于assign,但与assign不同的是,当它们指向的对象被释放后,weak会被自动置为nil,而assign则不会,所以assign会导致“野指针”的出现,weak可以避免悬空指针。
unsafe_unretained: 其实质等同于assign。与weak的区别就是指向的对象如果被释放,其不会被置为nil,而导致悬空指针的出现。它是ARC模式下非对象属性的默认值。
copy
修饰immutable类型,使用strong
修饰mutable类型引用一下一句话:
For attributes whose type is an immutable value class that conforms
to the
NSCopying
protocol, you almost always should specifycopy
in your
@property
declaration. Specifying retain is something youalmost never want in such a situation.
举个例子:
@interface UserInfo : NSObject <NSCopying>
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@end
//main 函数中
NSMutableString *mutableFirstName = [NSMutableString stringWithFormat:@"张"];
NSMutableString *mutableLastName = [NSMutableString stringWithFormat:@"全蛋"];
UserInfo *my = [[UserInfo alloc] init];
my.firstName = mutableFirstName;
my.lastName = mutableLastName;
NSLog(@"全名:%@%@", my.firstName, my.lastName);
// print: 全名:张全蛋
// 改mutableFirstName 张 为 李
[mutableFirstName deleteCharactersInRange:NSMakeRange(0, 1)];
[mutableFirstName appendString:@"李"];
// 改mutableLastName 全蛋 为 没蛋
[mutableLastName appendString:@"没蛋"];
NSLog(@"全名:%@%@", my.firstName, my.lastName);
// print: 全名:张没蛋
对于immutable对象类型属性,假设该类型存在mutable版本,若使用strong
修饰该属性,则将会是不安全的。比如在上述例子中,my.firstName
被copy
修饰,而my.lastName
被strong
修饰,当把mutable类型赋给了immutable类型(即NSMutableString
赋给NSString
),之后又修改mutable类型变量的值(将张改为李,全蛋改为没蛋),copy
修饰的firstName
不会改变,而strong
修饰的lastName
会随之改变。这是不希望发生的。
对于两者的setter方法的定义如下:
- (void) setFirstName:(NSString*)firstName{
_firstName = [firstName copy];
}
- (void) setLastName:(NSString*)lastName{
_lastName = lastName;
}
如果去掉copy,写成下面这个样子,则copy的好处将不复存在。
- (void) setFirstName:(NSString*)firstName{
_firstName = [firstName copy];
}
NSCopying
类型属性都应该使用copy
修饰,而是对于NSString
、NSDictionary
等属性才需要使用copy
修饰,因为它们存在mutable版本,在为属性赋值时,右值很可能是它们的mutable类型对象,若使用strong
修饰则会带来不稳定因子;另外一个方面,如果属性类型不存在对应的mutable版本,则完全不用担心这点,反正你也无法在外部修改它,不稳定因子自然不存在了。(参考Objective-C copy那些事儿)copy
修饰,被修饰符copy
修饰的属性,默认的setter赋值方式是_iVar = [var copy];
而copy
方法返回的是immutable类型,将immutable对象赋值给mutable类型指针显然是不对的。