handleEventsForBackgroundURLSession 中的 completionHandler 定义:
completionHandler definition inside handleEventsForBackgroundURLSession:
这不是之前在Whosebug
这里问的一个小问题,至少我还没有发现类似的东西,当然我也googled
它并且阅读了大部分排名靠前的结果。
顺便说一句,如果这里有人对 Objective C’
的块语法不满意,请访问此页面
http://fuckingblocksyntax.com ,
在抛出任何与块相关的问题之前。
1st 我的部分问题是:the background of declaration of block-parameter, as well as invoking a method which has a block-parameter ( in many cases, a completionBlock )
MyWorker 中的“calleE-method
”class:
…………
@implementation MyWorker
-(void) aWorkerMethodNeedsABlockInput: ((void)(^)( NSObject *, double )) blockParam
{
NSObject *anObj=[[ NSObject alloc] init];
double *aDouble;
[self retrieveTimeConsumingResults: anObj withNumberOfTry: aDouble ];
blockParam ( anObj, * aDouble );
}
@end
MyManager 中的“calleR-method
”class:
@interface myManager()
@property (nonatomic) MyWorker * mWorker;
@property (nonatomic, copy) (void)(^mBlockProperty)( NSObject *, double );
@end
@implementation MyManager
-(void) aManagerMethodWhoCallsWorkerWithCompletionHandler
{
(void)(^ valBlock )( NSObject *, double ) = ^(void)( NSObject * realObj, double realDouble )
{
[realObj performSelector:@SEL( aSelector) withObject: @(realDouble) afterDelay: aTimeInterval];
} ;
self.mBlockProperty=[valBlock copy];
[self.mWorker aWorkerMethodNeedsABlockInput : self.mBlockProperty];
}
@end
上面的 sudo-code 是在我们的自定义代码中将块存储在 属性 中的正常方式,声明块参数并在 CALLEE 中提供块的参数;提供块定义并在 CALLER 中“使用”块的参数。为了块语法的清晰,我保留了 'void' returnType
的书面形式。写错了请指正!
我问题的第二部分:
的常规用法
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
NSLog(@"Handle events for background url session");
self.backgroundSessionCompletionHandler = completionHandler;
}
然后
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
WebAppDelegate *appDelegate = (WebAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.backgroundSessionCompletionHandler) {
void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
appDelegate.backgroundSessionCompletionHandler = nil;
completionHandler();
}
NSLog(@"All tasks are finished");
}
通过守护进程的后台回调在基于 NSURLSession 框架的上述模式中工作,对吗?我做了很多次,应用这种模式没有问题。
我想了很久的是:
“handleEventsForBackgroundURLSession:”方法的 completionHandler
参数的定义中,当从块属性 存储中调用该方法时,真正的定义是什么? < 在“completionHandler();”的时候被执行 >
我从未见过任何 sample/demo 中 put/copy 任何代码块到 completionHandler
... 或者我想知道太多?
What is really inside the definition of the completionHandler parameter of “handleEventsForBackgroundURLSession:” method, when the method is invoked from a block-property storage? < at the time when “ completionHandler();” is executed > I have never seen any sample/demo which put/copy any block-of-code into completionHandler... or I wish to know too much?
如果我对您的问题的理解正确,那么您是在询问系统传递给 UIApplicationDelegate 方法 application:handleEventsForBackgroundURLSession:completionHandler:
的应用程序实现的块内的实现。
application:handleEventsForBackgroundURLSession:completionHandler:
由外部 service process 调用(间接)。当应用程序使用 NSURLSession
创建后台会话时,该会话由该系统服务管理。该服务执行实际的后台传输并通知 UIKit/Foundation,然后通过称为 XPC 的机制通知您的应用程序。 XPC 被 MacOS 开发人员广泛使用,但目前 iOS 应用程序无法直接使用 - 然而 iOS 上开发人员使用的许多 API 和服务实际上与 XPC 服务通信。
在 application:handleEventsForBackgroundURLSession:completionHandler:
的情况下,传递给 completionHandler
参数的块是一个不透明的回调。后台传输服务需要知道您的应用程序何时完成会话事件处理。调用该块会通知服务应用程序已完全处理这组事件,守护程序可以继续运行。
该块由系统创建和拥有,因此应用程序不应尝试修改或更改它(复制块除外,这是正确的做法!)。应用程序也不应提供自己的完成块 - 开发人员提供的块将无法通知传输服务完成,除非它包装传递给 completionHandler:
本身的块。
后台传输服务和 NSURLSession
已在 iOS 7 中引入。如果您正在编写第三方框架或库,利用该服务可能非常有益,但是框架必须提供一种方法来处理它拥有的任何后台会话的事件。也许正因为如此,似乎只有少数第三方库支持后台传输。支持这一点并不难——库只需要一个方法来指示会话的所有权,以及一个获取完成块和处理事件的方法:
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
if ([someCloudFrameworkObject canHandleEventsForSessionWithIdentifier:identifier]){
[someCloudFrameworkObject handleEventsForBackroundSessionWithIdentifier:identifier completionHandler:completionHandler];
}
}
这不是之前在Whosebug
这里问的一个小问题,至少我还没有发现类似的东西,当然我也googled
它并且阅读了大部分排名靠前的结果。
顺便说一句,如果这里有人对 Objective C’
的块语法不满意,请访问此页面
http://fuckingblocksyntax.com ,
在抛出任何与块相关的问题之前。
1st 我的部分问题是:the background of declaration of block-parameter, as well as invoking a method which has a block-parameter ( in many cases, a completionBlock )
MyWorker 中的“calleE-method
”class:
…………
@implementation MyWorker
-(void) aWorkerMethodNeedsABlockInput: ((void)(^)( NSObject *, double )) blockParam
{
NSObject *anObj=[[ NSObject alloc] init];
double *aDouble;
[self retrieveTimeConsumingResults: anObj withNumberOfTry: aDouble ];
blockParam ( anObj, * aDouble );
}
@end
MyManager 中的“calleR-method
”class:
@interface myManager()
@property (nonatomic) MyWorker * mWorker;
@property (nonatomic, copy) (void)(^mBlockProperty)( NSObject *, double );
@end
@implementation MyManager
-(void) aManagerMethodWhoCallsWorkerWithCompletionHandler
{
(void)(^ valBlock )( NSObject *, double ) = ^(void)( NSObject * realObj, double realDouble )
{
[realObj performSelector:@SEL( aSelector) withObject: @(realDouble) afterDelay: aTimeInterval];
} ;
self.mBlockProperty=[valBlock copy];
[self.mWorker aWorkerMethodNeedsABlockInput : self.mBlockProperty];
}
@end
上面的 sudo-code 是在我们的自定义代码中将块存储在 属性 中的正常方式,声明块参数并在 CALLEE 中提供块的参数;提供块定义并在 CALLER 中“使用”块的参数。为了块语法的清晰,我保留了 'void' returnType
的书面形式。写错了请指正!
我问题的第二部分:
的常规用法 - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
NSLog(@"Handle events for background url session");
self.backgroundSessionCompletionHandler = completionHandler;
}
然后
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
WebAppDelegate *appDelegate = (WebAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.backgroundSessionCompletionHandler) {
void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
appDelegate.backgroundSessionCompletionHandler = nil;
completionHandler();
}
NSLog(@"All tasks are finished");
}
通过守护进程的后台回调在基于 NSURLSession 框架的上述模式中工作,对吗?我做了很多次,应用这种模式没有问题。
我想了很久的是:
“handleEventsForBackgroundURLSession:”方法的 completionHandler
参数的定义中,当从块属性 存储中调用该方法时,真正的定义是什么? < 在“completionHandler();”的时候被执行 >
我从未见过任何 sample/demo 中 put/copy 任何代码块到 completionHandler
... 或者我想知道太多?
What is really inside the definition of the completionHandler parameter of “handleEventsForBackgroundURLSession:” method, when the method is invoked from a block-property storage? < at the time when “ completionHandler();” is executed > I have never seen any sample/demo which put/copy any block-of-code into completionHandler... or I wish to know too much?
如果我对您的问题的理解正确,那么您是在询问系统传递给 UIApplicationDelegate 方法 application:handleEventsForBackgroundURLSession:completionHandler:
的应用程序实现的块内的实现。
application:handleEventsForBackgroundURLSession:completionHandler:
由外部 service process 调用(间接)。当应用程序使用 NSURLSession
创建后台会话时,该会话由该系统服务管理。该服务执行实际的后台传输并通知 UIKit/Foundation,然后通过称为 XPC 的机制通知您的应用程序。 XPC 被 MacOS 开发人员广泛使用,但目前 iOS 应用程序无法直接使用 - 然而 iOS 上开发人员使用的许多 API 和服务实际上与 XPC 服务通信。
在 application:handleEventsForBackgroundURLSession:completionHandler:
的情况下,传递给 completionHandler
参数的块是一个不透明的回调。后台传输服务需要知道您的应用程序何时完成会话事件处理。调用该块会通知服务应用程序已完全处理这组事件,守护程序可以继续运行。
该块由系统创建和拥有,因此应用程序不应尝试修改或更改它(复制块除外,这是正确的做法!)。应用程序也不应提供自己的完成块 - 开发人员提供的块将无法通知传输服务完成,除非它包装传递给 completionHandler:
本身的块。
后台传输服务和 NSURLSession
已在 iOS 7 中引入。如果您正在编写第三方框架或库,利用该服务可能非常有益,但是框架必须提供一种方法来处理它拥有的任何后台会话的事件。也许正因为如此,似乎只有少数第三方库支持后台传输。支持这一点并不难——库只需要一个方法来指示会话的所有权,以及一个获取完成块和处理事件的方法:
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
if ([someCloudFrameworkObject canHandleEventsForSessionWithIdentifier:identifier]){
[someCloudFrameworkObject handleEventsForBackroundSessionWithIdentifier:identifier completionHandler:completionHandler];
}
}