如何从 NSURLSessionDataTask 完成处理程序返回 NSData

2023-11-24

我正在尝试创建一个简单的类,我可以用它来调用 post Web 服务。

一切都工作正常,除了我无法退货NSData.

这是我的代码:

+ (NSData *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url{
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    NSMutableArray *pairs = [[NSMutableArray alloc]init];
    for(NSString *key in parameters){
        [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, parameters[key]]];
    }
    NSString *requestParameters = [pairs componentsJoinedByString:@"$"];
    NSURL *nsurl = [NSURL URLWithString:url];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:nsurl];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[requestParameters dataUsingEncoding:NSUTF8StringEncoding]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        //return data;
    }];
    [dataTask resume];

    return nil;
}

请注意我有//return data但它给了我这个错误

 Incompatible block pointer types sending 'NSData *(^)(NSData *__strong, NSURLResponse *__strong, NSError *__strong)' to parameter of type 'void (^)(NSData *__strong, NSURLResponse *__strong, NSError *__strong)'

我的问题是:

  1. 我的方法好还是会给我以后带来麻烦?我没有要下载的图像,也没有要上传的任何内容,我只需发送简单的字符串数据并接收简单的字符串数据。或者在每个函数中独立地编写代码会更好?

  2. 请问如何返回数据?


你不能只返回数据(因为NSURLSessionDataTask异步运行)。您可能想采用自己的完成块模式,类似于completionHandler of the dataTaskWithRequest方法。

因此,您可以将自己的块参数添加到您的方法中,您将从内部调用该块参数dataTaskWithRequest方法completionHandler:

+ (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler {

    // create your request here ...

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (completionHandler)
            completionHandler(data, response, error);
    }];

    [dataTask resume];

    return dataTask;
}

或者,因为这个dataTaskWithRequest在后台线程上运行,有时确保将完成处理程序分派回主队列很有用,例如

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (completionHandler)
        dispatch_async(dispatch_get_main_queue(), ^{
            completionHandler(data, response, error);
        });
}];

请注意,顺便说一句,我认为退回NSURLSessionDataTask引用,如上,因此 (a) 调用者可以确保数据任务已成功创建; (b) 你有NSURLSessionTask您可以使用该引用来取消任务,以防在将来的某个日期您希望能够因某种原因取消请求(例如,用户关闭发出请求的视图控制器)。

无论如何,您可以通过以下方式调用它:

NSURLSessionTask *task = [MyClass postCall:parameters fromURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // put whatever code you want to perform when the asynchronous data task completes
}];

if (!task) {
    // handle failure to create task any way you want
}

You ask:

我的方法好还是会给我以后带来麻烦?我没有[an]图像要下载,也没有任何东西要上传,我只需发送[一些]简单的字符串数据并接收[简单]字符串数据。或者在每个函数中独立地编写代码会更好?

如果您收到返回的简单字符串数据,我建议您以 JSON 格式编写响应,然后将完成块放在postCall use NSJSONSerialization提取响应。使用 JSON 可以让应用程序更轻松地区分成功响应和可能返回字符串响应的各种与服务器相关的问题。

因此,假设您修改了服务器代码以返回如下响应:

{"response":"some text"}

然后你可以修改postCall像这样解析该响应:

+ (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url completionHandler:(void (^)(NSString *responseString, NSError *error))completionHandler {

    // create your request here ...

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (completionHandler) {
            if (error) {
                completionHandler(nil, error);
            } else {
                NSError *parseError = nil;
                NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];

                completionHandler(responseDictionary[@"response"], parseError);
            }
        }
    }];

    [dataTask resume];

    return dataTask;
}

就您的基本问题而言,是否有类似的方法postCall有道理,是的,我认为将创建请求的细节放在一个方法中是非常有意义的。我对您的实现的一个小保留是您决定将其设为类方法而不是实例方法。您当前正在创建一个新的NSURLSession对于每个请求。我建议做postCall实例方法(如果需要,可以是单例方法),然后将会话保存为类属性,设置一次,然后在后续查询中重复使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 NSURLSessionDataTask 完成处理程序返回 NSData 的相关文章

  • 由于无法确认开发者身份而无法打开

    我在 Mac OSX 中开发了一个应用程序和守护进程 并且我已经在 xcode 中与开发者 ID 签署了应用程序和守护进程源代码 在守护进程中 我已经对每个框架进行了签名并打包 并且我使用软件包安装程序对所有框架进行了 pkg 现在我的应用
  • 如何在 iOS 上的视图之间进行展开/收缩转换?

    我正在尝试在 iOS 中制作过渡动画 其中视图或视图控制器似乎扩展以填充整个屏幕 然后在完成后收缩回原来的位置 我不确定这种类型的转换的正式名称是什么 但您可以在 iPad 版 YouTube 应用中查看示例 当您点击网格上的搜索结果缩略图
  • 创建宏来执行默认初始化

    我有很多重复这个简单样板的方法 id myObject if myObject self myObject myObject class new return myObject 所以我想用一个简单的宏来替换它 define default
  • 更新到 Xcode 7.0.1,项目现在有问题

    因此 我将 Xcode 6 1 版本上传到 iTunes Connect 并且该应用程序获得了批准 现在我正在尝试更新应用程序 我更新到 Xcode 7 0 1 Xcode 给我带来了问题 指出 对于应用程序 我使用了故事板和 Object
  • iOS 新手。预期的表达错误?

    这看起来很不寻常 因为该方法与我的 showAnswer 方法完全相同 所以我想我应该在这里问 import QuizViewController h interface QuizViewController end implementat
  • NSMutableData 删除字节?

    我可以使用以下命令轻松地将字节添加到 NSMutableData 实例appendData方法 但是我没有看到任何类似的删除数据的方法 我是否忽略了某些内容 或者我是否需要创建一个新对象并仅复制我需要的字节 请参阅以下方法的文档 void
  • 使用捏合手势;如何放大用户手指实际“捏”的位置?

    我已经在我的应用程序中的 UIImageView 上实现了 UIPinchGestureRecognizer 但是无论我在图像的哪个位置捏合 它似乎都会放大到同一个位置 有谁知道我如何让它放大到用户实际 捏 的地方 请参阅下面的代码 视图控
  • 从 NSString 的第一行删除换行符

    我怎样才能删除第一个 nNSString 中的字符 编辑 只是为了澄清一下 我想做的是 如果字符串的第一行包含 n 字符 请将其删除 否则不执行任何操作 即 如果字符串是这样的 nhello this is the first line n
  • 相机叠加图片

    edit 3 好消息和坏消息 好消息是 在连接检查器中 通过断开覆盖 UIToolbar 并连接 UIImageview 我看到theKing 但是 坏消息 我没有看到我也需要的 UIToolbar 所以现在的问题是 当用户完成这里操作后
  • Apple 推送通知徽章编号

    我开发了服务器端应用程序 以在收到新通知后将徽章编号维护为递增或递减 并在看到通知后删除它工作正常 但是显示徽章时存在一些问题 实际情况是 在设备上收到新通知后 我单击取消按钮 然后徽章编号正确显示 但之后我将打开应用程序并关闭应用程序徽章
  • 在 iPhone 和 Cocos2d 中从类类型(+)方法访问对象?

    我有一个类方法 在其中创建并返回类对象 但我想访问同一类中该对象的某些属性 作为一个类方法 我无法在 h 文件中声明该变量 然后在其他方法中访问它 以下是代码 我如何在下面的实例方法中访问 backsprite 或 hudlayer 对象的
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • UICollectionviewcell 更改背景

    如果我知道部分编号和项目编号 如何更改单元格中的背景 下面的代码显示了我如何尝试做到这一点 UICollectionViewCell collectionView UICollectionView collectionView cellFo
  • 子视图控制器旋转方法未被调用

    Summary 我试图将子视图控制器添加到父视图控制器 并让父视图控制器通知子视图控制器旋转事件 但是 旋转消息不会转发到子视图控制器 这是默认行为 为什么这种默认行为没有发生 环境 iOS 7 XCode 5 OSX 10 9 Detai
  • SDWebImage 显示缓存中图像的占位符

    在 iOS 5 1 项目 iPad 中使用 SDWebImage 3 我们展示相当大的图像 700x500 并且我们有很多图像 1000 我们预取图像并缓存到磁盘 然后允许用户浏览它们 效果很好 除了当您浏览图像时 您总是会看到占位符显示一
  • UINavigationController 在后退按钮单击时向下滚动

    我正在开发一个带有多个导航控制器的 iPhone iPad 应用程序 当我在设备处于横向模式时单击视图的后退按钮时 前一个视图会垂直滚动到屏幕中 而不是像往常一样水平滚动 推送动画始终水平工作 正如它应该的那样 是什么导致了这个奇怪的问题
  • AVAudioMixerNode pan 或 AVAudioUnitSamplerstereoPan 属性无法更改 AVAudioEngine 声音输出的左/右平衡

    我有以下代码 它播放单个 MIDI 音符 但我希望能够调整平衡 平移 以便它仅从左扬声器或右扬声器或某些组合中播放 我认为更改 sampler stereoPan 或 engine mainMixerNode pan 也许可以解决问题 但它
  • 如何在 XCode5 中将部署目标更改为 5.1.1 [重复]

    这个问题在这里已经有答案了 我正在一个项目中工作 我需要支持 iOS 5 1 1 但在 部署目标 的下拉菜单中我没有 5 1 1 作为选项 我的问题是如何将 iOS 5 1 1 添加为部署目标 我将非常感谢你的帮助 如果您愿意 您可以在框中
  • Swift 3 和 Xcode8 - init 的使用不明确

    在我安装 Xcode 8 并将项目转换为 Swift 3 之前 以下行没问题 现在转换后看起来像这样 let valueData Data Data bytes UnsafePointer
  • 如何将 NSAppTransportSecurity 添加到 Cordova 项目

    我正在从事一个 ionic cordova 项目 该应用程序需要配置 iOS 9 版本的应用程序传输安全例外 有谁知道如何将以下配置添加到 cordova 项目配置文件中 配置 xml

随机推荐