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

iOS 内存管理求职学习资料

本文介绍了iOS 内存管理求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

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

一、Objective-C 使用引用计数来管理内存。

每个对象都有一个计数器,来表示引用该对象的个数;每次引用就加1,用完就减1;当计数为0时表示不再使用该对象,于是就销毁该对象。
多个对象之间的引用形成闭环会导致循环引用,从而不能够相互释放,造成内存泄漏。

二、ARC 自动引用计数

ARC 自动引用计数,把内存管理事宜交由编译器来处理。
使用 ARC 时,实际上引用计数还是在执行的,只不过保留操作和释放操作由 ARC 在编译时自动为你添加。
ARC 环境下特殊情况处理。

- (void)dealloc {     // 移除通知中心的监听者     // 移除 KVO 监听者     // 关闭 NSTimer,并将定时器置空(nil)     // 释放非 Objective-C 对象的内存,如 CFRelease(...), free(...) }

三、自动释放池

@autoreleasepool {} 自动释放池。
当向一个对象发送autorelease消息时,系统会将该对象放入到最新的自动释放池。
在自动释放池的作用域内,池子内的对象依然可以正常使用。
当自动释放池的作用域结束时,再释放池子内的对象———每个对象收到几个autorelease就进行几次release操作。
常见用途:循环内部创建大量临时对象时,没有及时释放导致内存使用急剧增加,可以使用自动释放池在每次循环结束时释放对象。

for (NSInteger i = 0; i < 100000; i++) {     @autoreleasepool {         NSString *str = @"Hello World";         str = [str stringByAppendingFormat:@"- %ld", i];         str = [str uppercaseString];     } }

四、@property 属性修饰符

原子性(多线程管理):atomic、nonatomic
读写属性:readwrite、readonly
setter 语意:assign、retain、copy
强弱引用:strong、weak
1、NSNumber、NSString、Block 使用 copy。
2、IBOutlet 属性、引用“引用对象”的属性(控制器引用view的子视图)、代理属性使用 weak。
3、Class、id 类型的属性使用 retain。
4、NSString 属性使用 retain 时,可能赋值一个 NSMutableString,导致值为 NSMutableString 类型。
5、NSMutableString 属性使用 copy 时,导致属性值为 NSString 类型,有可能出现未识别方法调用的异常。
atomic 只是保证了读写的线程安全,但是在多线程环境访问对象属性时,访问结果不一定符合我们的预期。

- (void)setAtomicObj:(NSObject *)atomicObj{     @synchronized(self) {         if (_atomicObj != atomicObj) {             [_atomicObj release];             _atomicObj = [atomicObj retain];         }     } } - (NSObject *)atomicObj{     @synchronized(self) {         return _atomicObj;     } }

ARC下同时重写getter、setter方法时,需使用关键字@synthesize 声明变量和属性的关系。
@synthesize name = _name;
注意:@property = ivar + getter + setter;

五、定时器使用时的内存管理

通常控制器会拥有一个定时器,如果把控制器设置为定时器的 target,定时器会引用控制器,导致定时器不关闭销毁时不能释放控制器。因此,想办法不要定时器直接或者间接引用控制器即可。
定时器解决循环引用思路:
1、iOS10 以后系统提供了block 方法执行定时器操作。

    [NSTimer timerWithTimeInterval:(NSTimeInterval) repeats:(BOOL) block:^(NSTimer * _Nonnull timer) {      }];     [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval) repeats:(BOOL) block:^(NSTimer * _Nonnull timer) {      }];

2、给 NSTimer 提供一个分类,实现自定义的 block 方法。

@interface NSTimer (BBBlocksSupport)  + (NSTimer *)bb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval                                          block:(void(^)(void))block                                        repeats:(BOOL)repeats;  @end
@implementation NSTimer (BBBlocksSupport)  + (NSTimer *)bb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval                                          block:(void(^)(void))block                                        repeats:(BOOL)repeats {     return [self scheduledTimerWithTimeInterval:interval                                           target:self                                         selector:@selector(bb_blockInvoke:)                                         userInfo:[block copy]                                          repeats:repeats]; }  + (void)bb_blockInvoke:(NSTimer *)timer {     void (^block)(void) = timer.userInfo;     if (block) {         block();     } }  @end

3、中间件模式。
设计思路:给中间对象动态添加定时器需要执行的方法。

#import <Foundation/Foundation.h>  @interface BBTimerManager : NSObject  @property (weak, nonatomic) NSTimer *bb_timer;  + (instancetype)bb_timerManagerWithTimeInterval:(NSTimeInterval)interval                                          target:(id)aTarget                                        selector:(SEL)aSelector                                        userInfo:(id)userInfo                                         repeats:(BOOL)repeats;  @end
#import "BBTimerManager.h" #import <objc/runtime.h>  @implementation BBTimerManager  + (instancetype)bb_timerManagerWithTimeInterval:(NSTimeInterval)interval                                          target:(id)aTarget                                        selector:(SEL)aSelector                                        userInfo:(id)userInfo                                         repeats:(BOOL)repeats {     Method targetMethod = class_getInstanceMethod([aTarget class], aSelector);     if (!class_addMethod([BBTimerManager class], aSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod))) {         class_replaceMethod([BBTimerManager class], aSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod));     }     BBTimerManager *manager = [BBTimerManager new];     manager.bb_timer = [NSTimer scheduledTimerWithTimeInterval:interval target:manager selector:aSelector userInfo:userInfo repeats:repeats];     return manager; }  @end
- (void)dealloc {     [_timerManager.bb_timer invalidate];     _timerManager.bb_timer = nil; }

六、优雅使用 KVO

在需要处理属性变化事件的对象中添加观察者,并在该对象销毁时移除观察者。

@interface RootViewController () @property (retain, nonatomic) Focus *focus; @end
@implementation RootViewController  - (void)viewDidLoad {     [super viewDidLoad];     self.focus = [[Focus alloc] init];     [self.focus addObserver:self                  forKeyPath:@"number"                     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld                     context:nil];     self.focus.number = @2; }  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {     if ([keyPath isEqualToString:@"number"]) {         NSLog(@"%@", change);     } }  - (void)dealloc {     [self.focus removeObserver:self forKeyPath:@"number"]; }

七、copy 操作

对于不可变对象 NSString、NSArray、NSDictionary 表示引用加1。
对于可变对象 NSMutableString、NSMutableArray、NSMutableDictionary 表示复制对象,返回不可变对象。
mutableCopy 操作:
对于不可变对象、可变对象都是表示复制对象,返回可变对象。
自定义对象使用 copy 和 mutableCopy 需要遵守 NSCopying 和 NSMutableCopying 协议。

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

一、Objective-C 使用引用计数来管理内存。

每个对象都有一个计数器,来表示引用该对象的个数;每次引用就加1,用完就减1;当计数为0时表示不再使用该对象,于是就销毁该对象。
多个对象之间的引用形成闭环会导致循环引用,从而不能够相互释放,造成内存泄漏。

二、ARC 自动引用计数

ARC 自动引用计数,把内存管理事宜交由编译器来处理。
使用 ARC 时,实际上引用计数还是在执行的,只不过保留操作和释放操作由 ARC 在编译时自动为你添加。
ARC 环境下特殊情况处理。

- (void)dealloc {     // 移除通知中心的监听者     // 移除 KVO 监听者     // 关闭 NSTimer,并将定时器置空(nil)     // 释放非 Objective-C 对象的内存,如 CFRelease(...), free(...) }

三、自动释放池

@autoreleasepool {} 自动释放池。
当向一个对象发送autorelease消息时,系统会将该对象放入到最新的自动释放池。
在自动释放池的作用域内,池子内的对象依然可以正常使用。
当自动释放池的作用域结束时,再释放池子内的对象———每个对象收到几个autorelease就进行几次release操作。
常见用途:循环内部创建大量临时对象时,没有及时释放导致内存使用急剧增加,可以使用自动释放池在每次循环结束时释放对象。

for (NSInteger i = 0; i < 100000; i++) {     @autoreleasepool {         NSString *str = @"Hello World";         str = [str stringByAppendingFormat:@"- %ld", i];         str = [str uppercaseString];     } }

四、@property 属性修饰符

原子性(多线程管理):atomic、nonatomic
读写属性:readwrite、readonly
setter 语意:assign、retain、copy
强弱引用:strong、weak
1、NSNumber、NSString、Block 使用 copy。
2、IBOutlet 属性、引用“引用对象”的属性(控制器引用view的子视图)、代理属性使用 weak。
3、Class、id 类型的属性使用 retain。
4、NSString 属性使用 retain 时,可能赋值一个 NSMutableString,导致值为 NSMutableString 类型。
5、NSMutableString 属性使用 copy 时,导致属性值为 NSString 类型,有可能出现未识别方法调用的异常。
atomic 只是保证了读写的线程安全,但是在多线程环境访问对象属性时,访问结果不一定符合我们的预期。

- (void)setAtomicObj:(NSObject *)atomicObj{     @synchronized(self) {         if (_atomicObj != atomicObj) {             [_atomicObj release];             _atomicObj = [atomicObj retain];         }     } } - (NSObject *)atomicObj{     @synchronized(self) {         return _atomicObj;     } }

ARC下同时重写getter、setter方法时,需使用关键字@synthesize 声明变量和属性的关系。
@synthesize name = _name;
注意:@property = ivar + getter + setter;

五、定时器使用时的内存管理

通常控制器会拥有一个定时器,如果把控制器设置为定时器的 target,定时器会引用控制器,导致定时器不关闭销毁时不能释放控制器。因此,想办法不要定时器直接或者间接引用控制器即可。
定时器解决循环引用思路:
1、iOS10 以后系统提供了block 方法执行定时器操作。

    [NSTimer timerWithTimeInterval:(NSTimeInterval) repeats:(BOOL) block:^(NSTimer * _Nonnull timer) {      }];     [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval) repeats:(BOOL) block:^(NSTimer * _Nonnull timer) {      }];

2、给 NSTimer 提供一个分类,实现自定义的 block 方法。

@interface NSTimer (BBBlocksSupport)  + (NSTimer *)bb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval                                          block:(void(^)(void))block                                        repeats:(BOOL)repeats;  @end
@implementation NSTimer (BBBlocksSupport)  + (NSTimer *)bb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval                                          block:(void(^)(void))block                                        repeats:(BOOL)repeats {     return [self scheduledTimerWithTimeInterval:interval                                           target:self                                         selector:@selector(bb_blockInvoke:)                                         userInfo:[block copy]                                          repeats:repeats]; }  + (void)bb_blockInvoke:(NSTimer *)timer {     void (^block)(void) = timer.userInfo;     if (block) {         block();     } }  @end

3、中间件模式。
设计思路:给中间对象动态添加定时器需要执行的方法。

#import <Foundation/Foundation.h>  @interface BBTimerManager : NSObject  @property (weak, nonatomic) NSTimer *bb_timer;  + (instancetype)bb_timerManagerWithTimeInterval:(NSTimeInterval)interval                                          target:(id)aTarget                                        selector:(SEL)aSelector                                        userInfo:(id)userInfo                                         repeats:(BOOL)repeats;  @end
#import "BBTimerManager.h" #import <objc/runtime.h>  @implementation BBTimerManager  + (instancetype)bb_timerManagerWithTimeInterval:(NSTimeInterval)interval                                          target:(id)aTarget                                        selector:(SEL)aSelector                                        userInfo:(id)userInfo                                         repeats:(BOOL)repeats {     Method targetMethod = class_getInstanceMethod([aTarget class], aSelector);     if (!class_addMethod([BBTimerManager class], aSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod))) {         class_replaceMethod([BBTimerManager class], aSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod));     }     BBTimerManager *manager = [BBTimerManager new];     manager.bb_timer = [NSTimer scheduledTimerWithTimeInterval:interval target:manager selector:aSelector userInfo:userInfo repeats:repeats];     return manager; }  @end
- (void)dealloc {     [_timerManager.bb_timer invalidate];     _timerManager.bb_timer = nil; }

六、优雅使用 KVO

在需要处理属性变化事件的对象中添加观察者,并在该对象销毁时移除观察者。

@interface RootViewController () @property (retain, nonatomic) Focus *focus; @end
@implementation RootViewController  - (void)viewDidLoad {     [super viewDidLoad];     self.focus = [[Focus alloc] init];     [self.focus addObserver:self                  forKeyPath:@"number"                     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld                     context:nil];     self.focus.number = @2; }  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {     if ([keyPath isEqualToString:@"number"]) {         NSLog(@"%@", change);     } }  - (void)dealloc {     [self.focus removeObserver:self forKeyPath:@"number"]; }

七、copy 操作

对于不可变对象 NSString、NSArray、NSDictionary 表示引用加1。
对于可变对象 NSMutableString、NSMutableArray、NSMutableDictionary 表示复制对象,返回不可变对象。
mutableCopy 操作:
对于不可变对象、可变对象都是表示复制对象,返回可变对象。
自定义对象使用 copy 和 mutableCopy 需要遵守 NSCopying 和 NSMutableCopying 协议。

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

一、Objective-C 使用引用计数来管理内存。

每个对象都有一个计数器,来表示引用该对象的个数;每次引用就加1,用完就减1;当计数为0时表示不再使用该对象,于是就销毁该对象。
多个对象之间的引用形成闭环会导致循环引用,从而不能够相互释放,造成内存泄漏。

二、ARC 自动引用计数

ARC 自动引用计数,把内存管理事宜交由编译器来处理。
使用 ARC 时,实际上引用计数还是在执行的,只不过保留操作和释放操作由 ARC 在编译时自动为你添加。
ARC 环境下特殊情况处理。

- (void)dealloc {     // 移除通知中心的监听者     // 移除 KVO 监听者     // 关闭 NSTimer,并将定时器置空(nil)     // 释放非 Objective-C 对象的内存,如 CFRelease(...), free(...) }

三、自动释放池

@autoreleasepool {} 自动释放池。
当向一个对象发送autorelease消息时,系统会将该对象放入到最新的自动释放池。
在自动释放池的作用域内,池子内的对象依然可以正常使用。
当自动释放池的作用域结束时,再释放池子内的对象———每个对象收到几个autorelease就进行几次release操作。
常见用途:循环内部创建大量临时对象时,没有及时释放导致内存使用急剧增加,可以使用自动释放池在每次循环结束时释放对象。

for (NSInteger i = 0; i < 100000; i++) {     @autoreleasepool {         NSString *str = @"Hello World";         str = [str stringByAppendingFormat:@"- %ld", i];         str = [str uppercaseString];     } }

四、@property 属性修饰符

原子性(多线程管理):atomic、nonatomic
读写属性:readwrite、readonly
setter 语意:assign、retain、copy
强弱引用:strong、weak
1、NSNumber、NSString、Block 使用 copy。
2、IBOutlet 属性、引用“引用对象”的属性(控制器引用view的子视图)、代理属性使用 weak。
3、Class、id 类型的属性使用 retain。
4、NSString 属性使用 retain 时,可能赋值一个 NSMutableString,导致值为 NSMutableString 类型。
5、NSMutableString 属性使用 copy 时,导致属性值为 NSString 类型,有可能出现未识别方法调用的异常。
atomic 只是保证了读写的线程安全,但是在多线程环境访问对象属性时,访问结果不一定符合我们的预期。

- (void)setAtomicObj:(NSObject *)atomicObj{     @synchronized(self) {         if (_atomicObj != atomicObj) {             [_atomicObj release];             _atomicObj = [atomicObj retain];         }     } } - (NSObject *)atomicObj{     @synchronized(self) {         return _atomicObj;     } }

ARC下同时重写getter、setter方法时,需使用关键字@synthesize 声明变量和属性的关系。
@synthesize name = _name;
注意:@property = ivar + getter + setter;

五、定时器使用时的内存管理

通常控制器会拥有一个定时器,如果把控制器设置为定时器的 target,定时器会引用控制器,导致定时器不关闭销毁时不能释放控制器。因此,想办法不要定时器直接或者间接引用控制器即可。
定时器解决循环引用思路:
1、iOS10 以后系统提供了block 方法执行定时器操作。

    [NSTimer timerWithTimeInterval:(NSTimeInterval) repeats:(BOOL) block:^(NSTimer * _Nonnull timer) {      }];     [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval) repeats:(BOOL) block:^(NSTimer * _Nonnull timer) {      }];

2、给 NSTimer 提供一个分类,实现自定义的 block 方法。

@interface NSTimer (BBBlocksSupport)  + (NSTimer *)bb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval                                          block:(void(^)(void))block                                        repeats:(BOOL)repeats;  @end
@implementation NSTimer (BBBlocksSupport)  + (NSTimer *)bb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval                                          block:(void(^)(void))block                                        repeats:(BOOL)repeats {     return [self scheduledTimerWithTimeInterval:interval                                           target:self                                         selector:@selector(bb_blockInvoke:)                                         userInfo:[block copy]                                          repeats:repeats]; }  + (void)bb_blockInvoke:(NSTimer *)timer {     void (^block)(void) = timer.userInfo;     if (block) {         block();     } }  @end

3、中间件模式。
设计思路:给中间对象动态添加定时器需要执行的方法。

#import <Foundation/Foundation.h>  @interface BBTimerManager : NSObject  @property (weak, nonatomic) NSTimer *bb_timer;  + (instancetype)bb_timerManagerWithTimeInterval:(NSTimeInterval)interval                                          target:(id)aTarget                                        selector:(SEL)aSelector                                        userInfo:(id)userInfo                                         repeats:(BOOL)repeats;  @end
#import "BBTimerManager.h" #import <objc/runtime.h>  @implementation BBTimerManager  + (instancetype)bb_timerManagerWithTimeInterval:(NSTimeInterval)interval                                          target:(id)aTarget                                        selector:(SEL)aSelector                                        userInfo:(id)userInfo                                         repeats:(BOOL)repeats {     Method targetMethod = class_getInstanceMethod([aTarget class], aSelector);     if (!class_addMethod([BBTimerManager class], aSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod))) {         class_replaceMethod([BBTimerManager class], aSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod));     }     BBTimerManager *manager = [BBTimerManager new];     manager.bb_timer = [NSTimer scheduledTimerWithTimeInterval:interval target:manager selector:aSelector userInfo:userInfo repeats:repeats];     return manager; }  @end
- (void)dealloc {     [_timerManager.bb_timer invalidate];     _timerManager.bb_timer = nil; }

六、优雅使用 KVO

在需要处理属性变化事件的对象中添加观察者,并在该对象销毁时移除观察者。

@interface RootViewController () @property (retain, nonatomic) Focus *focus; @end
@implementation RootViewController  - (void)viewDidLoad {     [super viewDidLoad];     self.focus = [[Focus alloc] init];     [self.focus addObserver:self                  forKeyPath:@"number"                     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld                     context:nil];     self.focus.number = @2; }  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {     if ([keyPath isEqualToString:@"number"]) {         NSLog(@"%@", change);     } }  - (void)dealloc {     [self.focus removeObserver:self forKeyPath:@"number"]; }

七、copy 操作

对于不可变对象 NSString、NSArray、NSDictionary 表示引用加1。
对于可变对象 NSMutableString、NSMutableArray、NSMutableDictionary 表示复制对象,返回不可变对象。
mutableCopy 操作:
对于不可变对象、可变对象都是表示复制对象,返回可变对象。
自定义对象使用 copy 和 mutableCopy 需要遵守 NSCopying 和 NSMutableCopying 协议。

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

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

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

评论 抢沙发

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

b2b链

联系我们联系我们