iOS面试问题迅速
目标C中的块
看来找到面试问题及其答案很容易,但我感到困难的是,从这些问题中获得专业知识并在现实生活中使用它,成为成功的iOS开发人员。
我将创建一系列博客,以便每个人都可以一起学习并成长。
第1章:
因此,让我们从“ Objective C中的块 ”开始–
不应将块与中央分发(GCD)混淆:GCD主要是一个队列库, 通常使用块。
让我们细分两种主要的块语法:
- 块文字
- 块指针
块文字是与您的代码内联定义的。 这是一个直接调用方法的示例,将块文字作为参数传递:
NSUInteger foundAtIndex = [someArray indexOfObjectPassingTest:^ BOOL ( id object, NSUInteger idx, BOOL *stop) {
return [object hasPrefix:@"SOME_PREFIX"];
}];
块指针看起来类似于函数指针,但是使用^(脱字符号)而不是*(星号/星号/ splat)。 这是将块文字分配给块指针的示例:
// checkMatch is a block pointer that we assign to.
BOOL (^checkMatch)( id , NSUInteger, BOOL *) = ^ BOOL ( id object, NSUInteger idx, BOOL *stop) {
return [object hasPrefix:@"SOME_PREFIX"];
};
NSUInteger foundPrefixAtIndex = [someArray indexOfObjectPassingTest:checkMatch];
声明块引用
声明单个块的 语法 : return_type(^ block-name)(argument); 声明 块数组的 语法 : return_type(^ block-name [block-count])(参数);
void(^ blockReturningVoidWithVoidArgument)(void);
int(^ blockReturningIntWithIntAndCharArguments)(int,char);
无效(^ arrayOfTenBlocksReturningVoidWithIntArgument [10])(在
注意:-
1.块还支持可变参数(…)参数。
2.您还可以为块创建类型-在多个位置使用具有给定签名的块通常被认为是最佳实践:
typedef float(^ MyBlockType)(float,float);
MyBlockType block1 = // ...;
MyBlockType block2 = // ...;
使用__block变量共享存储
如前所述,尝试在块内为x
分配新值将导致错误:
整数x = 100; //错误, 更正一个__block
int x = 100;
//定义一个块
无效(^ AddXAndY)(int)= ^(int y){
x = x + y; //错误
printf(“%d%d \ n”,x,y);
};
要允许在块内更改变量,请使用__block
存储类型修饰符。
注意 : __block
变量还有两个限制:它们不能是可变长度数组,并且不能是包含C99可变长度数组的结构。
您可以将块作为参数传递给方法或函数
此示例中显示的beginTaskWithCallbackBlock:
方法的声明如下所示:
-(void)beginTaskWithCallbackBlock:(void(^)(void))callbackBlock;
(void (^)(void))
指定参数是一个不接受任何参数或不返回任何值的块。 该方法的实现可以按通常的方式调用该块:
-(void)beginTaskWithCallbackBlock:(void(^)(void))callbackBlock {
callbackBlock();
}
对象使用属性来跟踪块
定义属性以跟踪块的语法类似于块变量:
typedef void(^ XYZSimpleBlock)(void);
@interface XYZObject:NSObject
@property(复制)XYZSimpleBlock blockProperty;
@结束
注意:应该将copy
指定为属性属性,因为需要复制一个块以跟踪其在原始范围之外的捕获状态。 使用自动引用计数时,您不必担心这件事,因为它会自动发生,但是,最好的做法是让property属性显示结果行为。
捕获自身时避免强参考周期
最佳做法是捕获对self
的弱引用,如下所示:
-(void)configureBlock {
XYZBlockKeeper * __weak weakSelf =自我;
self.block = ^ {
[weakSelf doSomething]; //捕获弱引用
//避免引用循环
}
}
通过捕获指向self
的弱指针,该块将不会与XYZBlockKeeper
对象保持牢固的关系。 如果在调用该块之前已释放该对象,则weakSelf
指针将简单地设置为nil
。
块+并发任务
iOS提供了多种并发技术,包括两种任务调度机制:操作队列和Grand Central Dispatch。
这些机制围绕着等待被调用的任务队列的思想。 您可以按照需要调用它们的顺序将它们添加到队列中,并且当处理器时间和资源可用时,系统会将它们从队列中取出来进行调用。 使用NSBlockOperation
使用块创建操作,如下所示:
NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock:^ {
...
}];
可以手动执行操作,但是通常会将操作添加到现有操作队列或您自己创建的队列中,以准备执行:
//在主队列上安排任务:
NSOperationQueue * mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperation:operation];
//在后台队列中安排任务:
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
调试
您可以设置断点并单步执行。 您可以使用invoke-block
在GDB会话中invoke-block
,如以下示例所示:
$ invoke-block myBlock 10 20
这就是封锁! 是时候玩积木了,尝试一下积木。
转到下一部分— KVC和KVO
希望本文对希望获得知识以及清晰面试的人有用,请❤️将此文章推荐给其他人😊。 让我知道您的反馈。 🙂