NSURLSession中NSURLSessionDataTask中completionHandler的疑问

先解释一下下面代码的作用:

整个方法是判断是否登陆成功并返回判断结果。

使用JSON格式的数据发送账号密码到后端,并得到一个JSON,里面包括登陆是否成功的信息,LoginState为0成功,其他为失败

其中NSURLSessionDataTask是异步执行的

疑问在注释中

-(NSInteger)postLoginJson:(NSString *)url withStuid:(NSString *)stuid withPwd:(NSString *)pwd{

    NSDictionary *dic = @{@"stuid":stuid,@"pwd":pwd};

    NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];

    NSURL *URL = [NSURL URLWithString:url];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];

    [request setHTTPMethod:@"POST"];

    [request setValue:@"application/jason" forHTTPHeaderField:@"Content-Type"];

    [request setHTTPBody:data];

    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error){

        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

        //其中 setBool bug

        NSLog(@"loginState:%@",dic[@"loginState"]); //这是一个输出,返回状态值。

        if([dic[@"loginState"] integerValue] == 0){

            [userDefaults setInteger:0 forKey:@"tempBool"];

            [userDefaults synchronize];

        }

        else{

            [userDefaults setInteger:1 forKey:@"tempBool"];

            [userDefaults synchronize];

        }

    }];

    [task resume];

    while ([task state] != NSURLSessionTaskStateCompleted) {

        NSLog(@"state %ld",(long)[task state]);//这也是一个输出,当未完成时,一直输出。

    }   //此段代码是为了让任务完成后再往下执行,但无论如何,都是先输出willReturn而不是loginState

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    NSInteger willReturn = [userDefaults integerForKey:@"tempBool"];

    NSLog(@"willReturn %ld",(long)willReturn);//这是函数返回值

    [userDefaults removeObjectForKey:@"tempBool"];

    [userDefaults synchronize];

    //NSLog(willReturn);

    return willReturn;

}

 

最终输出的结果就是:

先是一堆 while中的state

然后willReturn

然后loginState

 

按道理不是应该先loginState先输出吗?

 

3月21日更新

虽然加入了while等待任务完成,但这个任务指的是数据下载任务,也就是当收到登陆状态返回值之后,此任务就为completed状态了,但是complationHandler中的指令这时才开始执行,并且是异步的,所以此while没用,最后的解决办法是把这个函数放在了LoginViewContorller,直接在complationHandler中执行相关UI更新。

目前找不到判定complationHandler运行状态的方法。

 

3月22日更新

从NSURLSessionDataTaskDelegate下手彻底解决了这个问题。仍可以封装网络访问为一个model,为NSURLSessionDataTask传入代理指针,LoginViewController实现代理即可。

代码

VisitWeb.m

-(void)getJson:(NSString *)url withCurrentController:(id)delegate{

    NSURLSessionConfiguration* ephConfiguration=[NSURLSessionConfiguration defaultSessionConfiguration];

    NSURLSession* session=[NSURLSession sessionWithConfiguration:ephConfiguration delegate:delegate delegateQueue:[NSOperationQueue mainQueue]];

    NSURL* URL=[NSURL URLWithString:url];

    NSURLSessionDataTask* dataTask=[session dataTaskWithURL:URL];

    [dataTask resume];

}

在相应文件里新建实例并设置代理即可。

VisitToGetJson *vj = [[VisitToGetJson alloc]init];

[vj getJson:@"http://120.27.120.48/stucard" withCurrentController:self];

转载于:https://www.cnblogs.com/Thkeer/p/5296556.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 iOS 开发,可以使用 AVPlayer 来播放音频,但是默认情况下 AVPlayer 不支持音频下载功能。不过,我们可以通过一些方法来实现音频下载。 一种方法是使用 AVAssetExportSession,将音频文件导出为本地文件。具体步骤如下: 1. 创建 AVURLAsset 对象,用于获取音频资源。 2. 创建 AVAssetExportSession 对象,用于导出音频资源。 3. 设置 AVAssetExportSession 的输出路径和输出格式。 4. 调用 exportAsynchronouslyWithCompletionHandler 方法开始导出音频资源。 5. 在 completion handler 获取导出的本地音频文件路径,然后使用 AVPlayer 播放该文件。 示例代码如下: ```objc // 获取音频资源 AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL URLWithString:@"http://example.com/audio.mp3"]]; // 创建导出会话 AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A]; // 设置输出路径和格式 NSString *outputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"audio.m4a"]; exportSession.outputURL = [NSURL fileURLWithPath:outputPath]; exportSession.outputFileType = AVFileTypeAppleM4A; // 开始导出 [exportSession exportAsynchronouslyWithCompletionHandler:^{ switch (exportSession.status) { case AVAssetExportSessionStatusCompleted: { // 获取导出的本地文件路径 NSString *localPath = exportSession.outputURL.path; // 使用 AVPlayer 播放本地文件 AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:localPath]]; AVPlayer *player = [AVPlayer playerWithPlayerItem:item]; [player play]; break; } case AVAssetExportSessionStatusFailed: NSLog(@"导出失败:%@", exportSession.error); break; default: break; } }]; ``` 另一种方法是使用 AVAssetResourceLoaderDelegate,通过响应 NSURLSessionDataTask 的回调来实现音频下载。具体步骤如下: 1. 创建 AVURLAsset 对象,设置其 resourceLoader 的代理为自定义的 AVAssetResourceLoaderDelegate 对象。 2. 在代理对象实现 resourceLoader:shouldWaitForLoadingOfRequestedResource: 方法,该方法会在播放器请求某个资源时被调用。 3. 在该方法,创建一个 NSURLSessionDataTask 对象,使用该对象下载资源,并将下载完成的数据通过 AVAssetResourceLoadingRequest 的 respondWithData: 方法返回给播放器。 4. 在代理对象实现 resourceLoader:didCancelLoadingRequest: 方法,该方法会在播放器不再需要请求某个资源时被调用,可以在该方法取消 NSURLSessionDataTask 对象。 示例代码如下: ```objc @interface CustomAVAssetResourceLoaderDelegate : NSObject<AVAssetResourceLoaderDelegate> @property (nonatomic, strong) NSURLSession *session; @end @implementation CustomAVAssetResourceLoaderDelegate - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest { // 创建 NSURLSessionDataTask 对象,下载资源 NSURLSessionDataTask *task = [self.session dataTaskWithURL:loadingRequest.request.URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { [loadingRequest finishLoadingWithError:error]; } else { // 将下载完成的数据返回给播放器 [loadingRequest.dataRequest respondWithData:data]; [loadingRequest finishLoading]; } }]; [task resume]; return YES; } - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { // 取消 NSURLSessionDataTask 对象 [self.session invalidateAndCancel]; } @end // 获取音频资源 AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL URLWithString:@"http://example.com/audio.mp3"]]; // 设置 resourceLoader 的代理为自定义的 AVAssetResourceLoaderDelegate 对象 CustomAVAssetResourceLoaderDelegate *delegate = [[CustomAVAssetResourceLoaderDelegate alloc] init]; delegate.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [asset.resourceLoader setDelegate:delegate queue:dispatch_get_main_queue()]; // 使用 AVPlayer 播放音频 AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:asset]; AVPlayer *player = [AVPlayer playerWithPlayerItem:item]; [player play]; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值