iOS Sharing #04 | 2019-04-13

目錄

一、請用一句話概述分類的概念,並闡述分類的優勢。

二、多個同宿主分類中的都重寫了一個同名方法,哪一個分類的同名方法會生效?爲何?

三、@property(copy)NSMutableArray *array這樣聲明屬性會出現什麼問題?

四、說一說KVO在重寫NSKVONotifying對象的setter方法中,添加了哪兩個關鍵方法?

五、如何實現一個完整的單例?


一、請用一句話概述分類的概念,並闡述分類的優勢。

答:

概述:Objective-C中的分類是修飾模式的一種具體實現,主要做用是在不改變原有類的基礎上,動態的爲類擴展功能(添加方法)。git

分類的優勢github

  • 聲明私有方法
  • 分解龐大的類文件
  • 將Framework私有方法公開化
  • 模擬多繼承

二、多個同宿主分類中的都重寫了一個同名方法,哪一個分類的同名方法會生效?爲何?

答:

運行時在處理分類時會倒序遍歷分類數組,最早訪問最後編譯的類,最後編譯的類的同名方法最終生效。數組

下面咱們來看看源碼解析:app

int mcount = 0; // 記錄方法的數量
int propcount = 0; // 記錄屬性的數量
int protocount = 0; // 記錄協議的數量
int i = cats->count; // 獲取分類個數
bool fromBundle = NO; // 記錄是不是從 bundle 中取的

while (i--) { // 從後往前遍歷,保證先取最後編譯的類
    auto&; 
    entry = cats->list[i]; // 分類,locstamped_category_t 類型
    
    // 取出分類中的方法列表;若是是元類,取得的是類方法列表;不然取得的是實例方法列表
    method_list_t *mlist = entry.cat->methodsForMeta(isMeta);
    if (mlist) {
        mlists[mcount++] = mlist; // 將方法列表放入 mlists 方法列表數組中
        fromBundle |= entry.hi->isBundle(); // 分類的頭部信息中存儲了是不是 bundle,將其記住
    }

    // 取出分類中的屬性列表,若是是元類,取得是nil
    property_list_t *proplist = entry.cat->propertiesForMeta(isMeta);
    if (proplist) {
        proplists[propcount++] = proplist; // 將屬性列表放入 proplists 屬性列表數組中
    }

    // 取出分類中遵循的協議列表
    protocol_list_t *protolist = entry.cat->protocols;
    if (protolist) {
        protolists[protocount++] = protolist; // 將協議列表放入 protolists 協議列表數組中
    }
} 
複製代碼

三、@property(copy)NSMutableArray *array這樣聲明屬性會出現什麼問題?

答:
  • NSMutableArray通過copy修飾後是NSArray(不可變數組)。若是對經copy修飾後的可變數組進行增刪改的操做,其實是在操做不可變數組,從而會引發程序異常,引發Crash。
  • 不寫原子性修飾詞默認使用atomic,而atomic性能比nonatomic差不少。

擴展:

淺拷貝:指針拷貝,不生成新對象

  • 不可變對象的不可變拷貝
NSArray *array = [NSArray array];

//相同地址 
NSLog(@"%p",array);
NSLog(@"%p",[array copy]);

// __NSArray0 (不可變數組) 
NSLog(@"%@",NSStringFromClass([[array copy] class]));
複製代碼

輸出: 性能

在這裏插入圖片描述


深拷貝:生成一個新對象,對象內容相同( 除淺拷貝那種狀況,其餘都是深拷貝)

  • 可變對象的可變拷貝
NSMutableArray *mutArray = [NSMutableArray array];

//輸出不一樣地址 
NSLog(@"%p",mutArray);
NSLog(@"%p",[mutArray mutableCopy]);

// __NSArrayM (可變數組)
NSLog(@"%@",NSStringFromClass([[mutArray mutableCopy] class]));
複製代碼

輸出: ui

在這裏插入圖片描述

  • 可變對象的不可變拷貝
NSMutableArray *mutArray = [NSMutableArray array];
//不一樣地址 
NSLog(@"%p",mutArray);
NSLog(@"%p",[mutArray copy]);

// __NSArray0
NSLog(@"%@",NSStringFromClass([[mutArray copy] class]));
複製代碼

輸出: atom

在這裏插入圖片描述

  • 不可變對象的可變拷貝
NSArray *array = [NSArray array];

//不一樣對象 
NSLog(@"%p",array);
NSLog(@"%p",[array mutableCopy]);
// __NSArrayM 
NSLog(@"%@",NSStringFromClass([[array mutableCopy] class]));
複製代碼

輸出: spa

在這裏插入圖片描述


總結:

除不可變對象的不可變拷貝爲淺拷貝,其他都是深拷貝 3d

在這裏插入圖片描述


四、說一說KVO在重寫NSKVONotifying對象的setter方法中,添加了哪兩個關鍵方法?

答:
-(void)willChangeValueForKey:(NSString *)key;
-(void)didChangeValueForKey:(NSString *)key;
複製代碼

五、如何實現一個完整的單例?

答:
#import "SingletonSample.h"

@interface SingletonSample()<NSCopying>

@end

@implementation SingletonSample
+(instancetype)sharedInstance
{
    static SingletonSample *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    
    return instance;
}

+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    return [self sharedInstance];
}

-(id)copyWithZone:(NSZone *)zone
{
    return self;
}

@end
複製代碼

倉庫

本篇相關代碼指針


聯繫方式

郵箱: adrenine@163.com

郵箱: holaux@gmail.com

郵箱: ledahapple@icloud.com

相關文章
相關標籤/搜索