object-c 经典实用面试题+自己总结的答案(2)

6. key 和 keypath 的区别

在iOS开发中经常碰到重载方法有传key和keypath两种,但是一直搞不清楚他们两的区别,最近研究了一下官网KVC编程对key和keypath的区别有了具体的认识:

例如:

KVC编程时setValue(value: AnyObject?, key: String)和setValue(value: AnyObject?, keypath: String)

key:只能接受当前类所具有的属性,不管是自己的,还是从父类继承过来的,如view.setValue(CGRectZero(), key: “frame”);

keypath: 除了能接受当前类的属性,还能接受当前类属性的属性,即可以接受关系链,如view.setValue(5, keypath: “layer.cornerRadius”)

7. 类别 与 拓展的区别。

  • 类扩展 (Class Extension也有人称为匿名分类)

作用:
能为某个类附加额外的属性,成员变量,方法声明
一般的类扩展写到.m文件中
一般的私有属性写到类扩展
使用格式:

@interface Mitchell()
//属性
//方法
@end
  • 与分类的区别

分类的小括号中必须有名字

@interface 类名(分类名字)
/*方法声明*/
@end
@implementation类名(分类名字)
/*方法实现*/
@end

分类只能扩充方法,不能扩展属性和成员变量(如果包含成员变量会直接报错)。
如果分类中声明了一个属性,那么分类只会生成这个属性的set、get方法声明,也就是不会有实现。
举例说明:如果我们分别在,类扩展与分类中添加了两个属性,

image
接下来在初始化方法中分别赋值,

image
大家会看到在为在分类中所声明的属性textOne赋值的时候,崩溃了,那么我们来查看一下崩溃的原因:

类扩展与类别1.3.png
意思是说,我们所创建的对象中并没有textOne这个属性。也就是说虽然我们再类别中声明属性不会报错,但是@property并没有自动为我们设置的属性生成set、get方法。

再说一下我们为什么不能包含类的.m文件,因为这样会重复包含另一个类的实现文件。

8. block 和 函数指针 有什么区别。

  • 函数指针是对一个函数地址的引用,这个函数在编译的时候就已经确定了。而block是一个函数对象,是在程序运行过程中产生的。在一个作用域中生成的block对象分配在栈(stack)上,和其他所有分配在栈上的对象一样,离开这个作用域,就不存在了。
    Block允许开发者在两个对象之间将任意的语句当做数据进行传递,往往这要比引用定义在别处的函数直观。

9. 如何向 NSArray 中加入结构体,是深拷贝还是浅拷贝?*

  • 比较常见的结构体:CGPoint ,CGSize,CGRect。。。。。。我们如何存放到数组中呢?因为是结构体不是对象,不能添加到数组中,解决方法:把这些常见的结构装换成对象,让后放进去,取出来在装换成结构体使用。我们想到了NSValue使用方法如下:
  CGPoint point = CGPointMake(0, 0);  
  NSMutableArray *array = [[NSMutableArray alloc]initWithCapacity:0];  
  NSValue *value = [NSValue valueWithCGPoint:point];  
  [array addObject:value];  

取出数组之后的对象的使用:

NSValue *tmpValue = array[0];   
CGPoint tmpPoint = [tmpValue CGPointValue];

下面是一些常见的结构体使用方法是一样的

@interface NSValue (NSValueUIGeometryExtensions)  
  
+ (NSValue *)valueWithCGPoint:(CGPoint)point;  
+ (NSValue *)valueWithCGVector:(CGVector)vector;  
+ (NSValue *)valueWithCGSize:(CGSize)size;  
+ (NSValue *)valueWithCGRect:(CGRect)rect;  
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;  
+ (NSValue *)valueWithUIEdgeInsets:(UIEdgeInsets)insets;  
+ (NSValue *)valueWithUIOffset:(UIOffset)insets NS_AVAILABLE_IOS(5_0);  
  
- (CGPoint)CGPointValue;  
- (CGVector)CGVectorValue;  
- (CGSize)CGSizeValue;  
- (CGRect)CGRectValue;  
- (CGAffineTransform)CGAffineTransformValue;  
- (UIEdgeInsets)UIEdgeInsetsValue;  
- (UIOffset)UIOffsetValue NS_AVAILABLE_IOS(5_0);  
  
@end 
  • 2、自定义结构体的存储
    同样是先转换NSValue对象再加入数组中,代码如下:
//   自定义的结构体  
    struct Test {  
        int ID;  
        CGFloat  height;  
    };  
    typedef struct Test Test;  
      
//    封装数据  
    Test tmpTest;  
    tmpTest.height = 80.0;  
    tmpTest.ID = 100;  
    NSLog(@"id==%d,height==%f",tmpTest.ID,tmpTest.height);  
      
    NSValue *customValue = [NSValue valueWithBytes:&tmpTest objCType:@encode(struct Test)];  
//    取出数据  
    Test tmpTest1;  
    [customValue getValue:&tmpTest1];  
    NSLog(@"id==%d,height==%f",tmpTest1.ID,tmpTest1.height); 

10. 通知是同步还是异步

与JavaScript中的事件机制不同,iOS里的事件广播机制是同步的,默认情况下,广播一个通知,会阻塞后面的代码:

-(void) clicked  
{  
    NSNotificationCenter *center =  [NSNotificationCenter defaultCenter];  
    [center postNotificationName:@"event_happend" object:self];  
      
    NSLog(@"all handler done");  
}  

按下按钮后,发送一个广播,此前已经注册了2个此事件的侦听者

-(id) init  
{  
    self = [super init];  
    if(self){  
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(whenReceive:) name:@"event_happend" object:nil];  
    }  
    return self;  
}  
  
  
-(void) whenReceive:(NSNotification*) notification  
{  
    NSLog(@"im1111");  
}  
-(id) init  
{  
    self = [super init];  
    if(self){  
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(whenReceive:) name:@"event_happend" object:nil];  
    }  
    return self;  
}  
  
  
-(void) whenReceive:(NSNotification*) notification  
{  
    NSLog(@"im22222");  
}  

执行这段代码,首先会输出im1111,然后是im22222,最后才是all handler done。调试发现,代码始终是跑在同一个线程中(广播事件的线程),广播事件之后的代码被阻塞,直到所有的侦听者都执行完响应
所以,由于NotificationCenter的这个特性,如果希望广播的事件异步处理,则需要在侦听者的方法里开启新线程。应该把Notification作为组件间解耦的方式,而不是利用它来实现异步处理.

发生事件,通知中心广播,有可能有多个监听者,设计上使用同步的方式,能够保证所有的监听者都对通知作出响应!不会产生遗漏.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Army_Ma

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值