Autoreleasepool: 实际是一个双向链表。
1.自动释放池开始,创建page结果,插入哨兵对象。
2.在自动释放池内部调用autorelease方法的对象被依次插入当前page栈中。
3.如果当前page栈已满,则创建新的page结构,组成双向链表,继续插入自动释放对象。
4.如果创建了新的内部自动释放池,在当前位置再次插入一个哨兵对象。
5.当内部的自动释放池结束时,根据对应的哨兵对象将其内的所有自动释放对象释放。
6.外部自动释放池结束时,根据对应的哨兵对象将其内所有的自动释放对象释放。
内存管理模型基于持有关系的概念。如果一个对象正处于被持有状态,
那它占用的内存就不会被回收。而这种持有关系计数被正式成为引用计数。
ARC是一种编译器特性,它评估了对象在代码中的生命周期,并在编译是自动注入适合的内存管理调用。
参考:https://zhuanlan.zhihu.com/p/37463055
一、创建过多线程不会直接导致watchdog强杀,但过多线程可能导致主线程得不到及时处理,而因为
其他原因被kill。
二、CPU长时间过载并不会导致强杀,但系统会生成一个report来警告开发者:‘this is not a crash’的
crash日志。
三、避免创建过多线程。
一、autoreleasepool
在一些特定情况下,需要创建自己的autoreleasepool块
1.当有一个创建了很多临时对象的循环时:
在循环中使用autoreleasepool块可以为每个迭代释放内存,虽然迭代前后最终的内存使用相同,但是应用的最大内存需求可以大大降低。
for (NSDictionary * item in items) {
@autoreleasepool {//确保在每次循环迭代完成后,清理内存从而导致更少的内存需求
Sku * sku = [Sku mj_objectWithKeyValues:item];
if ([item objectForKey:@"deleted_at"] && ![[item objectForKey:@"deleted_at"] isKindOfClass:[NSNull class]] && [[item objectForKey:@"deleted_at"] length]) {
[delSku addObject:sku];
}
else {
[addSku addObject:sku];
}
if (sku.productId && ![itemIds containsObject:[NSNumber numberWithInteger:sku.productId]]) {
[itemIds addObject:[NSNumber numberWithInteger:sku.productId]];
}
}
}
2.当创建一个线程时:
每个线程都将有它自己的autoreleasepool块栈。主线程用自己的autoreleasepool启动。对于任何
自定义的线程,必须创建自己的autoreleasepool。
二、使用RunTime动态添加属性
参考文章:https://www.jianshu.com/p/0f9b990e8b0a
.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "UserName.h"
@interface NSObject (Clothing)
@property (nonatomic, copy) NSString *clothingName;
@property (nonatomic, copy) NSString *titleName;
//根据不同状态设置UserName
- (void)gm_setUserName:(UserName *)userName forState:(UIControlState)state;
//根据不同状态值获取UserName
- (UserName *)userNameForState:(UIControlState)state;
@end
.m文件
#import "NSObject+Clothing.h"
#import <objc/runtime.h>
static NSString *_clothingName;
static const void *TitleNameKey = &TitleNameKey;
static char TitleNameCharKey;
static char NameKeyNormal;//默认
static char NameKeySelected;//选中
static char NameKeyDisabled;//禁止
static const char *gm_NameKeyForState(UIControlState state) {
switch (state) {
case UIControlStateNormal:
return &NameKeyNormal;
case UIControlStateSelected:
return &NameKeySelected;
case UIControlStateDisabled:
return &NameKeyDisabled;
default:
return &NameKeyNormal;
}
}
@implementation NSObject (Clothing)
//一、通过使用静态全局变量给分类添加属性
//但是这样_titleName静态全局变量与类并没有关联,无论对象创建与销毁,只要程序在运行_titleName变量就存在,并不是真正意义上的属性
- (void)setClothingName:(NSString *)clothingName {
_clothingName = clothingName;
}
- (NSString *)clothingName {
return _clothingName;
}
//方法二:使用RunTime动态添加属性
/**
总结:1.一个实例对象就对应一个ObjectAssociationMap,而ObjectAssociationMap中存储多个此实例对象的关联对象的key以及ObjectAssociation,为ObjcAssionation中存储着关联对象的value和policy策略
2.关联对象并不是放在原来的对象里面,而是自己维护了一个全局的map用来存放每一个对象以及对应关联属性表格。
3.如果设置关联对象为nil, 就相当于是移除关联对象
*/
- (void)setTitleName:(NSString *)titleName {
//动态添加属性
//第一种
objc_setAssociatedObject(self, TitleNameKey, titleName, OBJC_ASSOCIATION_COPY_NONATOMIC);
//第二种
objc_setAssociatedObject(self, @selector(setTitleName:), titleName, OBJC_ASSOCIATION_COPY_NONATOMIC);
//第三种
objc_setAssociatedObject(self, &TitleNameCharKey, titleName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)titleName {
//获取属性
return objc_getAssociatedObject(self, TitleNameKey);
}
- (UserName *)userNameForState:(UIControlState)state {
//获取属性
return (UserName *)objc_getAssociatedObject(self, gm_NameKeyForState(state));
}
- (void)gm_setUserName:(UserName *)userName forState:(UIControlState)state {
//设置属性
objc_setAssociatedObject(self, gm_NameKeyForState(state), userName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)removeAssocatedObjects {
//移除所有关联对象
objc_removeAssociatedObjects(self);
}
@end