iOS開發系列--基於MJExtension的Runtime簡單使用

首先了解兩個概念:深拷貝和淺拷貝
簡單來講,深拷貝就是內容拷貝,淺拷貝就是指針拷貝。更具體的用法,就不做過多解釋,自行百度吧。數組

// 字符串是直接賦值的,右側若是是copy,那麼就是淺拷貝;右側若是是mutableCopy,那麼就是深拷貝。  
   NSString *string1 = @"helloworld";  
   NSString *string2 = [string1 copy]; // 淺拷貝  
   NSString *string3 = [string1 mutableCopy]; // 深拷貝  
   NSMutableString *string4 = [string1 copy]; // 淺拷貝  
   NSMutableString *string5 = [string1 mutableCopy]; // 深拷貝  
  
   NSLog(@"string1 = %d;string2 = %d",string1,string2);  
   NSLog(@"string1 = %d;string3 = %d",string1,string3);  
   NSLog(@"string1 = %d;string4 = %d",string1,string4);  
   NSLog(@"string1 = %d;string5 = %d",string1,string5);

打印結果:this

使用場景:

在某些時候,須要複製一份相同的Model數據,可是又不影響原Model,相似上述的深拷貝,又或者在大量相同字段中須要改變其中一個字段的值。因爲Model數據的複雜性或者沒有實現NSCopy協議,簡單的使用Copy來拷貝可能沒法達到預期效果,由此就有了MJExtension的衍生使用。spa

核心代碼:

//
//  NSObject+TMCopy.h
//  LJDY
//
//  Created by TIM on 16/8/23.
//  Copyright © 2016年 mimi. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSObject (TMCopy)

/**
 實現類的copy
 */
- (id)tm_copy;

@end
//
//  NSObject+TMCopy.m
//  LJDY
//
//  Created by TIM on 16/8/23.
//  Copyright © 2016年 mimi. All rights reserved.
//

#import "NSObject+TMCopy.h"

@implementation NSObject (TMCopy)

- (id)tm_copy
{
    Class clazz = [self class];;
    __strong Class newClass = [[clazz alloc] init];
    Class superClass = self.superclass;
    while (superClass && ![NSStringFromClass(superClass) isEqualToString:@"NSObject"]) {
        [self setupValueWithNewClass:newClass Class:superClass];
        superClass = superClass.superclass;
    }
    [self setupValueWithNewClass:newClass Class:clazz];
    return newClass;
}

- (void)setupValueWithNewClass:(Class)newClass
                         Class:(Class)clazz
{
    int i;
    unsigned int propertyCount = 0;
    //runtime 獲取類的全部屬性
    objc_property_t *propertyList = class_copyPropertyList(clazz, &propertyCount);
    NSDictionary *dic;
    //獲取數組中須要轉換的模型類
    if ([clazz respondsToSelector:@selector(mj_objectClassInArray)]) {
        dic = [clazz mj_objectClassInArray];
    }
    for (i = 0; i < propertyCount; i++) {
        objc_property_t *thisProperty = propertyList + i;
        const char *propertyName = property_getName(*thisProperty);
        //屬性名
        NSString *property = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
        id value = [self valueForKey:property];
        //若是對象是模型類,則再次遍歷模型類中的屬性
        if (dic && [[dic allKeys] containsObject:property]) {
            //特殊處理模型中包含模型數組
            if ([value isKindOfClass:[NSArray class]]) {
                NSMutableArray *modelArray = [NSMutableArray array];
                for (Class _arrayClass in value) {
                    [modelArray addObject:[_arrayClass tm_copy]];
                }
                [newClass setValue:modelArray forKey:property];
            }
            else {
                id _class = [value tm_copy];
                [newClass setValue:_class forKey:property];
            }
        }
        else {
            [newClass setValue:value forKey:property];
        }
    }
    free(propertyList);
}

@end

使用方法:

FriendItem *_item = [item tm_copy];

結果:

相關文章
相關標籤/搜索