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

希望本文对希望获得知识以及清晰面试的人有用,请❤️将此文章推荐给其他人😊。 让我知道您的反馈。 🙂