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

相关文章
相关标签/搜索