使用iOS快速操作(快捷项),完成处理程序参数的目的是什么?

11
一个 iOS 快速操作 / 快捷方式项目会被 app delegate 实现的 application(_:performActionFor:completionHandler:) 方法接收。
在该实现中,您需要调用 completionHandler,该方法需要传入一个布尔值。
有人知道这个布尔值是用来干什么的吗?无论我传入 true 还是 false,都看不到任何区别。(事实上,即使我忽略调用 completionHandler,也没有任何区别!)

你看过这份文档了吗?application:performActionForShortcutItem:completionHandler - Adil Soomro
2
@AdilSoomro 是的,我有。你呢? - matt
我可能错了,但我认为您负责实现该方法并有条件地调用此类方法,这种情况下,您可以传递一个completionHandler(也是您的责任实现),因此在application(_:performActionFor:completionHandler:)的实现中,您可以传递一个布尔值,该布尔值对于您在completionHandler上实现的逻辑具有意义,并且取决于您想要构建的设计。 - Black Sheep
@BlackSheep 不,你不需要编写完成处理程序,只需调用它即可。 - matt
这个参数是用来让系统知道你的快速操作实现是否成功的,你需要在执行所需操作代码块后调用它。有些操作需要异步请求,如果其中一个请求失败,我假设开发者将不想执行所选操作,因此他可以调用 completionHandler(false)...否则,它几乎总是以布尔值 true 被调用。 - TechSeeko
@TechSeeko 但是问题在于我已经尝试了传递 true 和传递 false,甚至不调用完成处理程序,但是我看不到任何区别。无论如何,我们都会执行所选操作,并且事情看起来或行为上没有任何不同。我要求你以某种方式证明我是错误的。 - matt
1个回答

7

简短回答: 在iOS 10中,块的实现中未使用参数(猜测在iOS 9中也是如此,但无法立即检查)。

详细回答: 让我们看看completion块内部发生了什么:

___50-[UIApplication _handleApplicationShortcutAction:]_block_invoke:
push       rbp                               ; XREF=-[UIApplication _handleApplicationShortcutAction:]+132
mov        rbp, rsp
mov        rax, qword [ds:rdi+0x20]
mov        rdx, qword [ds:rdi+0x28]
mov        rsi, qword [ds:0x1179e88]         ; @selector(_updateSnapshotAndStateRestorationWithAction:)
mov        rdi, rax                          ; argument "instance" for method imp___got__objc_msgSend
pop        rbp
jmp        qword [ds:imp___got__objc_msgSend]
; endp

我在Intel64上运行这个程序,所以第一个参数应该存储在rdi寄存器中(当我们在ARC下调用块时,它是NSMallocBlock的实例)。没有选择器,所以第二个参数(布尔参数)应该存储在rsi寄存器中。但是rsi寄存器在代码中没有被使用 - 它只是向对象ds:rdi+0x20发送消息_updateSnapshotAndStateRestorationWithAction:并带有参数ds:rdi+0x28ds:rdi+0x20ds:rdi+0x28都是块内部捕获的指针。 认为将参数作为快照函数的指示符的猜测是错误的。

这个和你对在生产中捕获UIViewAlertForUnsatisfiableConstraints的回答真是太棒了。我希望自己也能像这样逆向工程UIKit。 - JAL
我想知道如何在快照中使用它。这一定与启动图像有关。我猜如果我们返回 false,并且我们被挂起并现在回到前台,运行时将使用它在后台时间拍摄的快照,因为我们说我们不会更改我们的界面。但是如果我们返回 true,也许运行时会恢复到原始的启动图像。就像那样...?但是如果我正确理解你的话,你是在说它实际上并没有做出那个决定。 - matt
是的,我认为你的假设是正确和合理的:如果我们正在更新我们的UI,我们需要更新启动图像,否则就不需要。默认情况下,我们使用默认的启动图像,因为它是通用的(在iOS 9模拟器中的MobileSafari中就是这样工作的)。确切地说,它没有做出那个决定,因为它没有使用参数。然而,我刚刚尝试了一下不调用“completion”,但什么也没有改变:在使用快捷方式打开应用程序后,我看到了默认的启动故事板。似乎快照更新逻辑发生在调用“appDelegate”方法之前。 - Roman Ermolov
很抱歉,@matt,我现在找不到确切的发生地点(如果我找到了,我会告诉你)。还有一个想法-更新快照逻辑可以类似于application:performFetchWithCompletionHandler:,我稍后会检查一下。 - Roman Ermolov
@matt 我对“预览”更新的假设部分正确:如果我们收到后台获取通知,iOS会将启动图像从快照重置为默认值。然而,完成处理程序结果根本不影响快照。因此,我认为我错了,参数并不是指示UI更新需求的指标。我会更新我的答案,暂时没有其他想法。 - Roman Ermolov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接