iOS常用知识点总结一

2018-03-30  本文已影响126人  小强简书

1.理解内存中的区域

(1)栈区:由系统自动分配和释放,存放局部变量的值,容量小,速度快,有序

(2)堆区:自己分配和释放,不释放会出现内存泄漏,容量大,速度慢,无需

(3)静态储存区:全局变量和静态变量储存,程序结束,系统自动回收

(4)常量区:储存常量,程序结束,系统自动回收

(5)代码区:储存代码

2.copy关键字

(1)NSString,NSArray,NSDictionary 使用关键字

如果使用strong,可能会导致这个属性指向一个可变对象,如果这个对象在外部被修改了,则这个对象也会受到影响,虽然copy和strong类似,但是copy的设置方法并不会保留新值,而是将其拷贝,来确保NSString等不会受到影响

如果在NSMutableArray等中使用copy,可能会导致崩溃,因为copy会复制出一份不可变的NSArray的对象,在进行插入,删除的时候会发生崩溃


 NSArray *array = @[ @1, @2, @3, @4 ];

 NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];

 self.array = mutableArray;

 [mutableArray removeAllObjects];;

 NSLog(@"%@",self.array);

 [mutableArray addObjectsFromArray:array];

 self.array = [mutableArray copy];

 [mutableArray removeAllObjects];;

 NSLog(@"%@",self.array);

打印结果


2015-09-27  19:10:32.523 CYLArrayCopyDmo[10681:713670] (

)

2015-09-27  19:10:32.524 CYLArrayCopyDmo[10681:713670] (

  1,

  2,

  3,

  4

)

1. 对非集合类对象的****copy****操作

所以可以看出,对immutable对象进行copy,是指针复制,mutableCopy是内容复制,深复制,对mutable对象copy和mutableCopy都是深复制

2.集合类对象的copy操作

集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象

[immutableObject copy] // 浅复制

[immutableObject mutableCopy] //单层深复制

[mutableObject copy] //单层深复制

[mutableObject mutableCopy] //单层深复制

2 block中的copy

block中的copy是MVC留下来的传统,是为了将创建在栈区的block拷贝到堆区,如果不拷贝的话,一旦在作用域之外来调用就会崩溃,另外,block在栈区里,但是很可能会用到一些变量,只要将其拷贝到堆区,才可以使用这些变量。

但是在ARC里写不写都行,strong和copy都可以的

3.类用copy关键字,重写copy关键字的setter方法

若想令自己所写的对象具有拷贝功能,则需实现 NSCopying 协议。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopying 与 NSMutableCopying 协议。


- (id)copyWithZone:(NSZone *)zone;

浅复制和深复制


- (id)copyWithZone:(NSZone *)zone {

 CYLUser *copy = [[[self  class] allocWithZone:zone]

  initWithName:_name

  age:_age

  sex:_sex];

 copy->_friends = [_friends mutableCopy];

  return copy;

}

- (id)deepCopy {

 CYLUser *copy = [[[self  class] alloc]

  initWithName:_name

  age:_age

  sex:_sex];

 copy->_friends = [[NSMutableSet  alloc] initWithSet:_friends

  copyItems:YES];

  return copy;

}

重写copy关键字的setter方法


- (void)setName:(NSString *)name {

 _name = [name copy];

}

3.@property中的属性关键字解析和原理(ivar,getter,setter)等

(1)原子性和非原子性 atomicity,nonatomic

atomicity,是默认的,原子的,使用了同步锁,大量使用会影响性能,几乎所有的属性都是nonatomic,因为atomic并不能保证线程安全,例如如果一个线程在不断读取一个属性值,但是另外一个线程在同时修改,就算有同步锁,也还是会读取到不同的属性值的。而且考虑到性能问题,不应该大量使用原子性。

(2)读/写 readwrite,readonly

使用读写属性的时候一般是这个样子的

.h文件


@property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode;

.m文件


@property (readwrite, nonatomic, assign) AFSSLPinningMode SSLPinningMode;

(3)assign,unsafe_unretained,strong,weak,copy

assign:assign是一个property的默认属性,可以用于非oc对象比如CGFloat 或 NSlnteger 等


@property (nonatomic) NSNumber *count;

等价于

@property (nonatomic, assign) NSNumber *count;

unsafe_unretained,声明一个弱应用,但是不会自动nil化,也就是说,如果所指向的内存区域被释放了,这个指针就是一个野指针了。与assign几乎等价

strong:标识一中拥有关系

weak:标识一种非拥有关系,weak 必须用于 OC 对象

(4) getter=<name>,setter=<name>

setter方法不常用,如果一个以init为开头的属性,重写其setter方法的时候,系统会把init开头的方法当成初始化方法,所以要使用setter方法

(5)nonnull,null_resettable,nullable

__nullable指代对象可以为NULL或者为NIL

__nonnull指代对象不能为null

NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END 在这两个宏之间的代码,所有简单指针对象都被假定为nonnull

@property **的本质是 **

```@property = ivar + getter + setter;

(“属性” (property)有两大概念:ivar(实例变量)、存取方法(access method = getter + setter)。

)```

property在runtime中是objc_property_t定义是一个结构体


struct  property_t {

  const  char *name;

  const  char *attributes;

};

而attributes本质是objc_property_attribute_t,定义了property的一些属性,定义如下:


/// Defines a property attribute

typedef  struct {

  const  char *name; /**< The name of the attribute */

  const  char *value; /**< The value of the attribute (usually empty) */

} objc_property_attribute_t;

我们定义一个string的property@property (nonatomic, copy) NSString *string;,通过 property_getAttributes(property)获取到attributes并打印出来之后的结果为T@"NSString",C,N,V_string

其中T就代表类型,可参阅Type Encodings,C就代表Copy,N代表nonatomic,V就代表对于的实例变量。


@interface  Person : NSObject

@property  NSString *firstName;

@end

等价于

@implementation  Person

@synthesize firstName = _myFirstName;

@end

属性实现

  1. OBJC_IVAR_$类名$属性名称 :该属性的“偏移量” (offset),这个偏移量是“硬编码” (hardcode),表示该变量距离存放对象的内存区域的起始地址有多远。
  2. setter 与 getter 方法对应的实现函数
  3. ivar_list :成员变量列表
  4. method_list :方法列表
  5. prop_list :属性列表

当我们增加一个属性的时候,系统会在成员变量列表中增加一个实例变量,然后在方法列表里增加setter和getter方法,在属性列表里增加属性描述,在偏移量里增加偏移量

@synthesize****和****@dynamic

本质上:都是 var = _var

@syntheszie 如果没有实现setter和getter方法或者没有实现其中一个,编译器会自动给加上

@synthesize 合成实例变量的规则,有以下几点:

  1. 如果指定了成员变量的名称,会生成一个指定的名称的成员变量,
  2. 如果这个成员已经存在了就不再生成了.
  3. 如果是 @synthesize foo; 还会生成一个名称为foo的成员变量,也就是说:

如果没有指定成员变量的名称会自动生成一个属性同名的成员变量,

  1. 如果是 @synthesize foo = _foo; 就不会生成成员变量了.

@dynamic****则不会,需要手动加上****setter****和****getter****方法。

@protocol category 中如何使用 @property

  1. 在 protocol 中使用 property 只会生成 setter 和 getter 方法声明,我们使用属性的目的,是希望遵守我协议的对象能实现该属性
  2. category 使用 @property 也是只会生成 setter 和 getter 方法的声明,如果我们真的需要给 category 增加属性的实现,需要借助于运行时的两个函数:
  3. objc_setAssociatedObject
  4. objc_getAssociatedObject
上一篇下一篇

猜你喜欢

热点阅读