Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective-C异步工作流中任务序列的维护_Objective C_Xcode_Asynchronous - Fatal编程技术网

Objective-C异步工作流中任务序列的维护

Objective-C异步工作流中任务序列的维护,objective-c,xcode,asynchronous,Objective C,Xcode,Asynchronous,我正在尝试做一个简单的下载,之后我会收到一个JSON文件。然后,我想将此对象转换为NSDictionary,并在返回格式化对象之前进行一些格式化。我在一个单独的班级里做这件事是为了保持整洁。其思想是初始化类并调用类中的一个函数,该函数将启动下载,并在最后吐回一个NSDictionary(如果过程中出现错误,则进行错误处理) 下面是一个流程图,以说明我想要实现的目标: 问题是,当下载是一个异步任务时,我无法思考如何将这些任务排序在一起,并且在下载完成之前我无法解析JSON: 我知道下载任务有一

我正在尝试做一个简单的下载,之后我会收到一个JSON文件。然后,我想将此对象转换为NSDictionary,并在返回格式化对象之前进行一些格式化。我在一个单独的班级里做这件事是为了保持整洁。其思想是初始化类并调用类中的一个函数,该函数将启动下载,并在最后吐回一个NSDictionary(如果过程中出现错误,则进行错误处理)

下面是一个流程图,以说明我想要实现的目标:

问题是,当下载是一个异步任务时,我无法思考如何将这些任务排序在一起,并且在下载完成之前我无法解析JSON:

我知道下载任务有一个完成处理程序,我可以在它启动时调用下一步,但这样我就失去了在最后返回NSDictionary的能力。类似地,如果我将NSDictionary设置为可以从外部访问并存储其中每个步骤的属性,那么我如何知道它何时包含最终结果(初始化时,字典为空;我需要等待序列完成)

因此,我正在寻找一种处理这个看似简单的下载任务的好方法。我希望我清楚地解释了我的问题,但如果你需要任何澄清,请让我知道

最后,这里是一些最相关步骤的代码片段。这是我要处理下载的地方:

- (void) initiateDownload {
// Initialize variables for URL request
NSURL *nasaAPI           = [NSURL URLWithString:@"https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"];
NSURLRequest *urlRequest    = [NSURLRequest requestWithURL:nasaAPI];
NSURLSession *urlSession    = [NSURLSession sharedSession];

// Setup session to timeout after a specific time interval
NSURLSessionConfiguration *sessionConfig    = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest     = 10.0;
sessionConfig.timeoutIntervalForResource    = 30.0;

// Initialize the download task
downloadTask    = [urlSession dataTaskWithRequest:urlRequest
                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *downloadError) {
                                    if (downloadError) {
                                        // Error occured, put it into errorMessage dictionary
                                        [self errorReceived:downloadError];
                                    } else if (data) {
                                        [self dataReceived:data];
                                    }
                                }];

// Fire download task
[downloadTask resume];
}
这就是我处理解析我下载的JSON的地方:

- (void) parseWeatherJSON:(NSData *)data {
/* ---------- ---------- ---------- ---------- ----------
 Returns with an NSDictionary with either
 1) the parsed JSON data or 2) an error message.
 ---------- ---------- ---------- ---------- ---------- */

// Create temporary variables
NSError *jsonError;
NSDictionary *parsedJSON;

// Insiate JSON parsing
parsedJSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];

// Handle any possible errors
if (jsonError) {
    // JSON parsing did not complete, return error message instead
    errorDictionary = [NSDictionary dictionaryWithObjectsAndKeys:jsonError, @"error", nil];
    [self errorReceived:jsonError];
} else {
    // JSON parsing was complete, return parsed NSDictionary
    [self dictionaryReceived:parsedJSON];
}
}
更新1.:如果上面的逻辑不适合处理下载/解析序列,我非常愿意接受其他想法。这正是我要做的,但我不是一个训练有素的程序员。也许有更好的办法

  • 添加带有dictionary参数的完成块
  • i从会话中提示将数据下载并解析到completionHandler中的字典中
  • 使用已解析的字典作为参数调用完成块
  • 这里有一个例子

    // declare in .h
    typedef void(^ResponseCallback)(NSError *error, id result);
    
    
    - (void) initiateDownloadWithCompletion:(ResponseCallback)completion {
        ...
    
        downloadTask = [urlSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *downloadError) {
            if (downloadError) {
                completion(downloadError, nil);
            } else if (data) {
                [self parseWeatherJSON: data completion: completion];
            }
        }];
    
        ...
    }
    
    
    - (void) parseWeatherJSON:(NSData *)data completion:(ResponseCallback)completion {
        ...
    
        if (jsonError) {
            ...
            completion(jsonError, nil);
        } else {
            ...
            completion(nil, parsedJSON);
        }
    }
    

    为什么不在
    initialedownload
    方法中添加一个完成块作为参数?我不知道如何添加。:)我忘了提到我是一个初学者/中级开发人员(只是在业余时间做这件事)。我可以自己做很多事情,但有时我需要提前完成任务的帮助。这是其中一种情况。:)嗨,海森堡,你介意在代码中显示这个吗?我还不知道怎么做。当然,我可以提供一些代码。顺便说一句,如果你是从iOS开始的,为什么不使用Swift?我不是从iOS开始的,我已经做了4-6年了;因此,我不愿意开始一种全新的语言。顺便说一句,我给了斯威夫特一个机会,但没能成功。Obj C对我来说似乎更符合逻辑,更容易理解。