iOS 拷贝面试题

没有比这里更全的了,看我就好了!

面试官😃 :请简单介绍一下iOS的浅拷贝和深拷贝?

浅拷贝:指针的拷贝,实际上拷贝了指向原来对象的指针,不会创建新的对象!

深拷贝:拷贝对象的具体内容,创建新的对象。拷贝结束后,两个对象存的值是相同的,但是内存地址不一样!(至少有一层是深拷贝)

面试官😃 :请问NSString属性用什么修饰符修饰,为什么用这个修饰符修饰?

开发中NSString属性用copy修饰符修饰。之所以用copy来修饰NSString属性,是因为可以避免赋值来源是NSMutableString的时候,改变可变字符串的值不会影响不可变字符串的值。之所以不会影响其原有值,是因为用copy修饰不可变字符串,在赋值的时候,在setter方法中会对赋值来源执行一次copy操作,当对可变类型执行copy操作,返回新的不可变对象,即使改变了来源数据,也不会影响copy修饰的不可变属性!所以用copy修饰NSString属性,也可以保证数据安全,不受污染!

面试官😃 :你了解iOS中的完全拷贝吗?简单说一下。

完全拷贝的概念是相对于深拷贝来说的。在深拷贝的理解中有一种说法是至少是一层深拷贝,比如,我们对容器类型的对象执行一次mutableCopy操作时,就进行了深拷贝,但这次深拷贝是单层深拷贝,也就是说容器内存地址发生了变化,但容器元素的内存地址没有发生变化,我们称它为单层深拷贝,并不是理论上的完全生拷贝!(容器类型的内容拷贝,仅限于对象本身,对象元素仍然是指针拷贝)

面试官😃 :如何实现自定义类的深浅拷贝?

系统提供的一些类,比如NSString,NSArray,NSDictionry都遵循了NSCopying和NSMutableCopying协议,所以我们可以直接调用copy/mutableCopy方法。我们自定义的类也想要实现深浅拷贝的功能,我们自定义的类也需要遵循NSCopying和NSMutableCopying协议,并实现对应的协议方法!

自定义的类实现浅拷贝:遵循NSCopying协议,实现copyWithZone方法,方法内返回self!

自定义的类实现深拷贝:遵循NSMutableCopying协议,实现mutableCopyWithZone方法,方法内创建新对象,并把当前类的属性依次赋值给新对象的属性,最后返回这个新的对象!

实现自定义A类的深拷贝的时候,如果A类中嵌套B类,那么B类也要实现NSMutableCopying协议,现mutableCopyWithZone方法,方法内创建新对象,并把当前类的属性依次赋值给新对象的属性,最后返回这个新的B对象!并且,在A类的mutableCopyWithZone方法中,  newA.b = [self.b mutableCopy] 。

这种实现方式只针对简单的单层的类!

上述是基本的实现方式!下面介绍一种使用Runtime+KVC方式给新对象进行赋值!参考代码实现!

CustomModel *m1 = [CustomModel new];
m1.name = @"Shaw";
m1.age = 27;
CustomModel *m2 = [m1 copy];
m2.name = @"CTT";
m2.age = 28;
    
NSLog(@"%@&%@", m1.name, m2.name);
// 打印结果:Shaw&CTT

@interface CustomModel : NSObject <NSCopying>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end

@implementation CustomModel

- (id)copyWithZone:(NSZone *)zone {
    CustomModel *copy = [[[self class] alloc] init];
    unsigned int propertyCount = 0;
    objc_property_t *propertyList = class_copyPropertyList([self class], &propertyCount);
    for (int i = 0; i < propertyCount; i++ ) {
        objc_property_t thisProperty = propertyList[i];
        const char* propertyCName = property_getName(thisProperty);
        NSString *propertyName = [NSString stringWithCString:propertyCName encoding:NSUTF8StringEncoding];
        id value = [self valueForKey:propertyName];
        [copy setValue:value forKey:propertyName];
    }
    return copy;
}
// 注意此处需要实现这个函数,因为在通过Runtime获取属性列表时,会获取到一个名字为hash的属性名,这个是系统帮你生成的一个属性
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {}

面试官😃 :如何自定义的类有多层嵌套,有没有方法实现自定义类的深拷贝?

如果问到这一步,那表明面试官对我们回答的如何实现自定义类的深浅拷贝的问题不是很满意,在提示我们针对上一个问题还有没有更好的解决办法。

当然,我们是有的,请看下面!

我们可以使用归档/解当的方法来实现自定义对象的深拷贝。

1,自定义类包括嵌套的类都要实现NSCoding协议,并实现encodeWithCoder/initWithCoder协议方法,

举例说明:

 DDPerson嵌套了Car,并且有个Car数组,继续看下每个类的实现,

DDPerson.m

 Car.m

 ViewController中

 我们打断点来看下最终每个对象的属性值

 通过对比,我们实现了一个自定义对象的完全拷贝!

到这里,可以说关于iOS中的拷贝的一些知识点就算结束了!

但是!!!

官😃 :怎么解决自定义对象完全拷贝的循环引用?

如果在实际工作工作中,没有遇到过这歌问题,那么一时间是很难搞懂这个的。

举例说明:

 是不是眼熟,A租借了一辆车,但是这辆车的车主也是A。现在就出现了循环引用。

解决办法 weak修饰owner属性,打断car对perosn的强引用。

@property (nonatomic, weak) DDPerson *owner;//车的拥有者

看到这,脑瓜子嗡嗡的😃 😃 😃 ,感觉这道题目和自定义对象的完全拷贝没关系。考察的是互相强引用,构成循环饮用的解决办法!

最后附上经典记忆图:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值