首页 » IOS » Objective-C 个人学习笔记

Objective-C 个人学习笔记

原文 http://blog.csdn.net/weixin_40887549/article/details/79218932

2018-02-01 02:01:10阅读(319)

OC学习笔记 属性(property)和成员变量 属性为了让类外可以访问成员变量 属性就是成员变量的外部接口 在类内调用成员变量而不是属性,属性是给类外使用的 在新版本的iOS SDK中,只要声明了属性系统就会自动生成成员变量。
例如:
@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。

关于id和instancetype

如下代码

@interface NSArray
  + (id) creatAnArray;
@end

当我们用如下方式初始化NSArray时:

[NSArray creatAnArray];

得到的返回类型将和方法声明的返回类型一样,是id;

但当我们将id改为instancetype时:

@interface NSArray
+ (instancetype) creatAnArray;
@end

再用刚同样的方式初始化时:

[NSArray creatAnArray];

得到的返回类型将会和方法所在类的类型相同,是NSArray*;

id和instancetype的区别

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
继承 OC中没有多继承,要实现多继承要通过协议来实现。 父类中的私有成员变量是无法继承使用的,而如果子类继承了父类的方法,方法中有队私有变量的操作以及打印,那我们是可以看到的,但是我们不可以在子类中直接调用私有变量。 如果父类中的方法没有写声明则子类无法继承父类中对应的方法。 多态 OC中不支持方法的重载 注释 使用 /** 文本 **/ 的注释格式(快捷键cmd+alt+/)可以对方法等进行快速注释。 修饰符

在苹果引入ARC之后,修饰符有所增加

存取类型 任何属性都可以声明为readwrite或readonly,且默认设置为readwrite readwrite:程序自动创建setter/getter方法。 readonly:程序之创建getter方法。 自定义setter/getter方法 : @propery(setter=setId,getter=getId) int id; 原子性 atomic:生成的setter/getter操作为原子性的操作,执行性能较低(系统默认)。 noatomic:生成的setter/getter操作为非原子性的操作,执行性能较高。一般推荐手动设置为该属性。 生命周期 MRC assign: 简单赋值,不更改引用计数。一般用于基础类型的数据(NSInteger)和C语言类型数(int,float,double,char,bool)。是MRC模式下的默认值。 copy: 会拷贝传入的对象(即创建一个引用计数为1的新对象,但是内容与传入对象相同),并把新对象赋值给实例变量。常用与NSString,NSArray,NSDictionary,NSSet等。 retain: 释放旧对象,并使传入的新对象引用计数+1。此属性只能用于NSObject及其子类,而不能用于Core Foundation(因为其没有使用引用计数,需要另外使用CFRetain和CFRelease爱进行CF的内存管理)。 ARC

ARC中加入以下修饰符

strong: 强引用,类似于retain。要求保留传入的对象,并放弃原有对象。一个对象只要被至少一个强引用指向,则其不会被释放,而当没有强引用指向时则会被释放。在ARC下是对象类型的默认值。

weak: 弱引用,要求不保留传入的属性(既不会使传入的对象引用计数+1)。类似于assign,但与assign不同的是,当它们指向的对象被释放后,weak会被自动置为nil,而assign则不会,所以assign会导致“野指针”的出现,weak可以避免悬空指针。

unsafe_unretained: 其实质等同于assign。与weak的区别就是指向的对象如果被释放,其不会被置为nil,而导致悬空指针的出现。它是ARC模式下非对象属性的默认值。

属性的默认值 MRC:(atomic, readwrite, assign) ARC下对象类型属性:(atomic, readwrite, strong) ARC下非对象类型:(atomic, readwrite, unsafe_unretained) 关于copy和strong 使用copy修饰immutable类型,使用strong修饰mutable类型

引用一下一句话:

For attributes whose type is an immutable value class that conforms

to the NSCopying protocol, you almost always should specify copy

in your @property declaration. Specifying retain is something you

almost 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/">Objective-C copy那些事儿) mutable属性类型不能用copy修饰,被修饰符copy修饰的属性,默认的setter赋值方式是_iVar = [var copy];而copy方法返回的是immutable类型,将immutable对象赋值给mutable类型指针显然是不对的。 内存管理法则 谁使对象的引用计数+1,不再引用时,谁就负责将该对象的引用计数-1

最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹