区块链技术博客
www.b2bchain.cn

iOS面试题目解析08 – iOS 内存管理策略求职学习资料

本文介绍了iOS面试题目解析08 – iOS 内存管理策略求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

1. iOS 内存管理有哪些关键字,说一下对这些关键字的理解?

  • strong: 表示指向并持有该对象,对象的引用计数会加1。该对象只要引用计数不为0就不会被销毁。当然可以通过将变量强制赋值 nil 来进行销毁。

  • weak: 表示指向但是并不持有该对象,引用计数也不会加1,是一种弱引用。在 Runtime 中对该属性进行了相关操作,无需处理,可以自动销毁,即置为 nil。weak 用来修饰对象,多用于避免循环引用的地方。weak 不可以修饰基本数据类型。

  • assign: 主要用于修饰基本数据类型, 例如 NSIntegerCGFloat,存储在栈中,内存不用程序员管理。assign 是可以修饰对象的,但是会出现问题。如果用assign修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

  • copy: copystrong 类似,但会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰 NSString 等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用 strong 修饰,如果对象在外部被修改了,会影响到属性。

2. assign 修饰对象会有什么问题?

如果用 assign 修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为 nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

3. weakassign 的区别?

  • weak: weak 是用来修饰对象的,是一种弱引用,并在对象被释放的时候,会自动置为 nil。

  • assign: assign 用来修饰基础数据类型,这些基础数据类型在栈上分配,不需要程序员手动管理生命周期。如果用 assign 修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

4. weak 的实现原理?

  • weak的作用:weak 关键字的作用是弱引用,所引用对象的计数器不会加1,并在引用对象被释放的时候自动被设置为 nil。

  • weak的原理:底层维护了一张weak_table_t结构的hash表,key是所指对象的地址,value是weak指针的地址数组。

比如下面的代码:

#import "Person.h" #import "Dog.h"  @interface Person()  @property (nonatomic, weak) Dog *a;  @end

waek表中的key就是 a 指向 Dog 对象的地址,value就是 a 这个指针的地址。

5. delegate 为何要用 weak 修饰?

在 ARC 环境下,为避免循环引用,往往会把 delegate 属性用 weak 修饰;在 MRC 下使用 assign 修饰。

6. block 属性为什么需要用 copy 来修饰?

因为在 MRC 下,block 在创建的时候,它的内存是分配在栈(stack)上的,而不是在堆(heap)上,可能被随时回收。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。通过 copy 可以把 block 从栈上拷贝到堆上,保证 block 的声明域外使用。在 ARC 下写不写都行,编译器会自动对 block 进行 copy 操作

7. 内存管理默认的关键字是什么?

  • 对象类型为:strong
  • 基础数据类型为: assign

8. nil 和 release 的区别?

nil是将一个对象的指针置为空,只是切断了指针和内存中对象的联系,并没有释放对象内存;而release才是真正释放对象内存的操作。

9. 为什么不要在初始化方法和 dealloc 中使用访问器方法(setter 和 getter)?

在初始化方法和dealloc中,对象的存在与否还不确定,它可能还未初始化完毕,所以给对象发消息可能不会成功,或者导致一些问题的发生。

  • 假如我们在init中使用setter方法初始化实例变量。在init中,我们会调用self = [super init]对父类的东西先进行初始化,即子类先调用父类的init方法(注意: 调用的父类的init方法中的self还是子类对象)。如果父类的init中使用setter方法初始化实例变量,且子类重写了该setter方法,那么在初始化父类的时候就会调用子类的setter方法。而此时只是在进行父类的初始化,子类初始化还未完成,所以可能会发生错误。

  • 在销毁子类对象时,首先是调用子类的dealloc,最后调用[super dealloc](这与init相反)。如果在父类的dealloc中调用了setter方法且该方法被子类重写,就会调用到子类的setter方法,但此时子类已经被销毁,所以这也可能会发生错误。

10.ObjC 对象在 dealloc 中会做些什么事情?

  1. 判断销毁对象前有没有需要处理的东西(如弱引用、关联对象、C++的析构函数、SideTabel的引用计数表等等);

  2. 如果没有就直接调用free函数销毁对象;

  3. 如果有就先调用 object_dispose 做一些释放对象前的处理(置弱引用指针置为nil、移除关联对象、object_cxxDestruct、在SideTabel的引用计数表中擦出引用计数等等),再用free函数销毁对象。

11. NSString 使用 strong 可以吗?NSArray 呢?

copystrong 类似,但会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰 NSString 等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用 strong 修饰,如果对象在外部被修改了,会影响到属性。

比如:

@interface ViewController ()  @property (nonatomic, strong) NSString *name;  @end  - (void)viewDidLoad {     [super viewDidLoad];      NSMutableString *anotherName = [NSMutableString string];     [anotherName appendString:@"Swift"];      self.name = anotherName;     NSLog(@"self.name: %@", self.name); // self.name: Swift      [anotherName appendString:@" Java"];     NSLog(@"self.name: %@", self.name); // self.name: Swift Java     NSLog(@"anotherName: %@", anotherName); // self.name: Swift Java }

可见将 NSMutableString 赋值给 NSString 后,它们就是同一个对象了,后续对 NSMutableString 的操作,也就是对 NSString 的操作。
使用 copy 后就就没有问题。

1. iOS 内存管理有哪些关键字,说一下对这些关键字的理解?

  • strong: 表示指向并持有该对象,对象的引用计数会加1。该对象只要引用计数不为0就不会被销毁。当然可以通过将变量强制赋值 nil 来进行销毁。

  • weak: 表示指向但是并不持有该对象,引用计数也不会加1,是一种弱引用。在 Runtime 中对该属性进行了相关操作,无需处理,可以自动销毁,即置为 nil。weak 用来修饰对象,多用于避免循环引用的地方。weak 不可以修饰基本数据类型。

  • assign: 主要用于修饰基本数据类型, 例如 NSIntegerCGFloat,存储在栈中,内存不用程序员管理。assign 是可以修饰对象的,但是会出现问题。如果用assign修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

  • copy: copystrong 类似,但会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰 NSString 等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用 strong 修饰,如果对象在外部被修改了,会影响到属性。

2. assign 修饰对象会有什么问题?

如果用 assign 修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为 nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

3. weakassign 的区别?

  • weak: weak 是用来修饰对象的,是一种弱引用,并在对象被释放的时候,会自动置为 nil。

  • assign: assign 用来修饰基础数据类型,这些基础数据类型在栈上分配,不需要程序员手动管理生命周期。如果用 assign 修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

4. weak 的实现原理?

  • weak的作用:weak 关键字的作用是弱引用,所引用对象的计数器不会加1,并在引用对象被释放的时候自动被设置为 nil。

  • weak的原理:底层维护了一张weak_table_t结构的hash表,key是所指对象的地址,value是weak指针的地址数组。

比如下面的代码:

#import "Person.h" #import "Dog.h"  @interface Person()  @property (nonatomic, weak) Dog *a;  @end

waek表中的key就是 a 指向 Dog 对象的地址,value就是 a 这个指针的地址。

5. delegate 为何要用 weak 修饰?

在 ARC 环境下,为避免循环引用,往往会把 delegate 属性用 weak 修饰;在 MRC 下使用 assign 修饰。

6. block 属性为什么需要用 copy 来修饰?

因为在 MRC 下,block 在创建的时候,它的内存是分配在栈(stack)上的,而不是在堆(heap)上,可能被随时回收。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。通过 copy 可以把 block 从栈上拷贝到堆上,保证 block 的声明域外使用。在 ARC 下写不写都行,编译器会自动对 block 进行 copy 操作

7. 内存管理默认的关键字是什么?

  • 对象类型为:strong
  • 基础数据类型为: assign

8. nil 和 release 的区别?

nil是将一个对象的指针置为空,只是切断了指针和内存中对象的联系,并没有释放对象内存;而release才是真正释放对象内存的操作。

9. 为什么不要在初始化方法和 dealloc 中使用访问器方法(setter 和 getter)?

在初始化方法和dealloc中,对象的存在与否还不确定,它可能还未初始化完毕,所以给对象发消息可能不会成功,或者导致一些问题的发生。

  • 假如我们在init中使用setter方法初始化实例变量。在init中,我们会调用self = [super init]对父类的东西先进行初始化,即子类先调用父类的init方法(注意: 调用的父类的init方法中的self还是子类对象)。如果父类的init中使用setter方法初始化实例变量,且子类重写了该setter方法,那么在初始化父类的时候就会调用子类的setter方法。而此时只是在进行父类的初始化,子类初始化还未完成,所以可能会发生错误。

  • 在销毁子类对象时,首先是调用子类的dealloc,最后调用[super dealloc](这与init相反)。如果在父类的dealloc中调用了setter方法且该方法被子类重写,就会调用到子类的setter方法,但此时子类已经被销毁,所以这也可能会发生错误。

10.ObjC 对象在 dealloc 中会做些什么事情?

  1. 判断销毁对象前有没有需要处理的东西(如弱引用、关联对象、C++的析构函数、SideTabel的引用计数表等等);

  2. 如果没有就直接调用free函数销毁对象;

  3. 如果有就先调用 object_dispose 做一些释放对象前的处理(置弱引用指针置为nil、移除关联对象、object_cxxDestruct、在SideTabel的引用计数表中擦出引用计数等等),再用free函数销毁对象。

11. NSString 使用 strong 可以吗?NSArray 呢?

copystrong 类似,但会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰 NSString 等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用 strong 修饰,如果对象在外部被修改了,会影响到属性。

比如:

@interface ViewController ()  @property (nonatomic, strong) NSString *name;  @end  - (void)viewDidLoad {     [super viewDidLoad];      NSMutableString *anotherName = [NSMutableString string];     [anotherName appendString:@"Swift"];      self.name = anotherName;     NSLog(@"self.name: %@", self.name); // self.name: Swift      [anotherName appendString:@" Java"];     NSLog(@"self.name: %@", self.name); // self.name: Swift Java     NSLog(@"anotherName: %@", anotherName); // self.name: Swift Java }

可见将 NSMutableString 赋值给 NSString 后,它们就是同一个对象了,后续对 NSMutableString 的操作,也就是对 NSString 的操作。
使用 copy 后就就没有问题。

1. iOS 内存管理有哪些关键字,说一下对这些关键字的理解?

  • strong: 表示指向并持有该对象,对象的引用计数会加1。该对象只要引用计数不为0就不会被销毁。当然可以通过将变量强制赋值 nil 来进行销毁。

  • weak: 表示指向但是并不持有该对象,引用计数也不会加1,是一种弱引用。在 Runtime 中对该属性进行了相关操作,无需处理,可以自动销毁,即置为 nil。weak 用来修饰对象,多用于避免循环引用的地方。weak 不可以修饰基本数据类型。

  • assign: 主要用于修饰基本数据类型, 例如 NSIntegerCGFloat,存储在栈中,内存不用程序员管理。assign 是可以修饰对象的,但是会出现问题。如果用assign修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

  • copy: copystrong 类似,但会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰 NSString 等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用 strong 修饰,如果对象在外部被修改了,会影响到属性。

2. assign 修饰对象会有什么问题?

如果用 assign 修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为 nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

3. weakassign 的区别?

  • weak: weak 是用来修饰对象的,是一种弱引用,并在对象被释放的时候,会自动置为 nil。

  • assign: assign 用来修饰基础数据类型,这些基础数据类型在栈上分配,不需要程序员手动管理生命周期。如果用 assign 修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。

4. weak 的实现原理?

  • weak的作用:weak 关键字的作用是弱引用,所引用对象的计数器不会加1,并在引用对象被释放的时候自动被设置为 nil。

  • weak的原理:底层维护了一张weak_table_t结构的hash表,key是所指对象的地址,value是weak指针的地址数组。

比如下面的代码:

#import "Person.h" #import "Dog.h"  @interface Person()  @property (nonatomic, weak) Dog *a;  @end

waek表中的key就是 a 指向 Dog 对象的地址,value就是 a 这个指针的地址。

5. delegate 为何要用 weak 修饰?

在 ARC 环境下,为避免循环引用,往往会把 delegate 属性用 weak 修饰;在 MRC 下使用 assign 修饰。

6. block 属性为什么需要用 copy 来修饰?

因为在 MRC 下,block 在创建的时候,它的内存是分配在栈(stack)上的,而不是在堆(heap)上,可能被随时回收。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。通过 copy 可以把 block 从栈上拷贝到堆上,保证 block 的声明域外使用。在 ARC 下写不写都行,编译器会自动对 block 进行 copy 操作

7. 内存管理默认的关键字是什么?

  • 对象类型为:strong
  • 基础数据类型为: assign

8. nil 和 release 的区别?

nil是将一个对象的指针置为空,只是切断了指针和内存中对象的联系,并没有释放对象内存;而release才是真正释放对象内存的操作。

9. 为什么不要在初始化方法和 dealloc 中使用访问器方法(setter 和 getter)?

在初始化方法和dealloc中,对象的存在与否还不确定,它可能还未初始化完毕,所以给对象发消息可能不会成功,或者导致一些问题的发生。

  • 假如我们在init中使用setter方法初始化实例变量。在init中,我们会调用self = [super init]对父类的东西先进行初始化,即子类先调用父类的init方法(注意: 调用的父类的init方法中的self还是子类对象)。如果父类的init中使用setter方法初始化实例变量,且子类重写了该setter方法,那么在初始化父类的时候就会调用子类的setter方法。而此时只是在进行父类的初始化,子类初始化还未完成,所以可能会发生错误。

  • 在销毁子类对象时,首先是调用子类的dealloc,最后调用[super dealloc](这与init相反)。如果在父类的dealloc中调用了setter方法且该方法被子类重写,就会调用到子类的setter方法,但此时子类已经被销毁,所以这也可能会发生错误。

10.ObjC 对象在 dealloc 中会做些什么事情?

  1. 判断销毁对象前有没有需要处理的东西(如弱引用、关联对象、C++的析构函数、SideTabel的引用计数表等等);

  2. 如果没有就直接调用free函数销毁对象;

  3. 如果有就先调用 object_dispose 做一些释放对象前的处理(置弱引用指针置为nil、移除关联对象、object_cxxDestruct、在SideTabel的引用计数表中擦出引用计数等等),再用free函数销毁对象。

11. NSString 使用 strong 可以吗?NSArray 呢?

copystrong 类似,但会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰 NSString 等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用 strong 修饰,如果对象在外部被修改了,会影响到属性。

比如:

@interface ViewController ()  @property (nonatomic, strong) NSString *name;  @end  - (void)viewDidLoad {     [super viewDidLoad];      NSMutableString *anotherName = [NSMutableString string];     [anotherName appendString:@"Swift"];      self.name = anotherName;     NSLog(@"self.name: %@", self.name); // self.name: Swift      [anotherName appendString:@" Java"];     NSLog(@"self.name: %@", self.name); // self.name: Swift Java     NSLog(@"anotherName: %@", anotherName); // self.name: Swift Java }

可见将 NSMutableString 赋值给 NSString 后,它们就是同一个对象了,后续对 NSMutableString 的操作,也就是对 NSString 的操作。
使用 copy 后就就没有问题。

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » iOS面试题目解析08 – iOS 内存管理策略求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们