iOS autoreleasepool 动态添加属性

内存管理模型基于持有关系的概念。如果一个对象正处于被持有状态,
那它占用的内存就不会被回收。而这种持有关系计数被正式成为引用计数。
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 
#import 

#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 

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


你可能感兴趣的:(iOS autoreleasepool 动态添加属性)