gpt4 book ai didi

ios - 如何将值从Helper类返回到 View Controller ?

转载 作者:行者123 更新时间:2023-11-28 18:36:45 24 4
gpt4 key购买 nike

我有一个viewcontroller,在其viewDidLoad中调用HelperClass类方法,如下所示:

- (void)viewDidLoad{
[super viewDidLoad];

self.usersArray = [SantiappsHelper fetchUsers];
}


该类方法如下所示:

+(NSArray *)fetchUsers{

NSString *urlString = [NSString stringWithFormat:@"http://www.myserver.com/myApp/getusers.php"];
NSURL *url = [NSURL URLWithString:urlString];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];

[request setHTTPMethod: @"GET"];

__block NSArray *usersArray = [[NSArray alloc] init];


dispatch_async(dispatch_get_main_queue(), ^{
// Peform the request
NSURLResponse *response;
NSError *error = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
// Deal with your error
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(@"HTTP Error: %d %@", httpResponse.statusCode, error);
return;
}
NSLog(@"Error %@", error);
return;
}

NSString *responseString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(@"responseString fetchUsers %@", responseString);

NSLog(@"inside of block");

usersArray = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSASCIIStringEncoding] options:0 error:nil];

});
NSLog(@"outside of block");
return usersArray;


}

responseString打印出来就好了。但是,如何将该值返回给视图控制器?因为它的一个tableview控制器已经在获取任何数据之前加载了其tableview。

最佳答案

实际的问题是“如何从异步方法返回结果?”

假设您有一个异步任务“ doSomethingAsync”(它是一个类方法,实例方法或函数,但这并不重要)。

熟悉的同步形式“ doSomething”将简单地返回结果,并可以如下声明:

- (Result*) doSomething;

等效异步任务“ doSomethingAsync”可以使用完成处理程序声明:

typedef void (^completion_block_t)(Result* result)
- (void) doSomethingAsync:(completion_block_t)completionHandler;


例:

假设类“ MyClass”定义了一个属性“结果”,该结果将从异步类方法(类Foo)的结果中初始化。您在方法“ fetchResult”中检索结果:

- (void) fetchResult {
[Foo doSomethingAsync:^(Result* result){
self.result = result;
}];
}


可能需要一段时间来了解这里发生的事情,并且需要您“思考异步”;)

要实现的重要一点是,完成处理程序是一个块-内联定义,并被视为正常对象。该块由调用站点创建,并作为参数completedHandler的参数传递给 doSomethingAsync:方法。该块本身定义了异步任务完成时要采取的动作。

另一方面,异步方法内部必须保留对该块的引用,直到完成为止。然后,它必须调用该块并将其结果作为参数提供给完成块的参数结果。



还有其他形式可以“返回”异步函数的结果。一种常见的模式是使用未来或承诺。 Future或Promise仅表示异步功能的最终结果。它是一个可以立即从异步函数返回的对象-但其值(异步任务的结果)仅在异步任务完成时才可用。任务必须在完成时最终为诺言设置一个值。这称为“解决”。这意味着,该任务必须保留对返回的promise对象的引用,并最终使用表示成功或失败的值来“解析”它。

假设有一个这样的“ Promise”类,这将允许您声明如下异步方法:

- (Promise*) doSomethingAsync;

Promise的实现可能完全支持“异步模型”。为了检索结果,您只需定义结果可用时的操作。 Promise的特定实现可以完成此任务,例如:

- (void) fetchResult {
Promise* promise = [Foo doSomethingAsync];
promise.then(^(Result* result){
self.result = result;
});
}


注意“ then”,它实际上是Promise类的一个属性,该属性返回一个块:

@property then_block_t then;


通过以下方式立即调用此返回的类型为“ then_block_t”的块:

promise.then(...)  


很像:

then_block_t block = promise.then;
block( ... );


但更短。

类型为“ then_block_t”的块具有一个参数,它是一个完成块,当结果最终可用时,promise将调用该块。内联定义完成块:

^(Result* result){ ... }


如您所见,完成块具有参数结果,该结果是异步方法的实际结果。

好,现在您的头可能会旋转;)

但是现在,回到例子

    Promise* promise = [Foo doSomethingAsync];
promise.then(^(Result* result){
self.result = result;
});


它的内容为:


“启动异步方法[Foo doSomethingAsync]并返回一个
诺言。
完成后,执行任务结果所在的块
“ doSomethingAsync”与参数结果一起传递。”


您可以写得更短:

[Foo doSomethingAsync]
.then(^(Result* result) {
self.result = result;
};


这类似于带有完成处理程序的表单:

[Foo doSomethingAsync:^(Result* result){
self.result = result;
}];




不过,Promise的最重要特征是,它允许我们将两个或多个异步任务“链接”在一起。这是因为从属性 then_block_t返回的类型为 then的块具有类型为 Promise的返回值。

typedef Promise* (^then_block_t)(completion_block_t onSuccess);

我很确定您的头部现在正在以高频率旋转;)-因此,一个示例将使您清楚(希望如此):

假设您有两种异步方法:asyncA和asyncB。第一个需要输入,异步处理它并产生结果。第二种方法asyncB应该获取此结果,对其进行异步处理,最后输出@“ OK”或NSError-如果出了问题:

[self asyncA:input]
.then(^(OutputA* outA) {
return [self asyncB:outA];
})
.then(^(OutputB* outB){
NSLog(@"end result: %@", outB);
return nil;
});


内容为:


“异步执行任务“ asyncA”。
完成后,异步执行任务“ asyncB”。
如果完成,则打印出结果。”


您可能会注意到处理程序将在语句中返回Promise对象

return [self asyncB:outA];

这将建立“链”形式的任务“ asyncA”到“ asyncB”。然后,返回的Promise的最终“值”将作为结果参数出现在下一个处理程序中。

处理程序还可以返回立即结果,该结果恰好也作为下一个处理程序中的result参数结束。



Objective-C中的实际实现略有不同,因为* then_block_t *具有两个参数:一个用于成功案例,一个用于失败案例:

typedef Promise* (^then_block_t)(completion_block_t onSuccess, failure_block_t onFailure);

为了简洁起见,我在以前的示例中将其省略。实际的实现如下所示:

[self asyncA:input]
.then(^(OutputA* out) {
return [self asyncB:out];
}, nil)
.then(^(id result){
NSLog(@"result: %@", result);
return nil;
}, ^id(NSError*error){
NSLog(@"ERROR: %@", error);
return nil;
});




许诺的另一个很酷的功能是,错误将通过许诺链转发。这意味着,一个人可以有多个“链接”任务,例如A,B,C,D,其中仅定义了成功处理程序。最后一个处理程序(对)定义一个错误处理程序。如果在第一个异步任务中发生错误-该错误将通过所有promise转发,直到错误处理程序最终对其进行处理为止。仅当任务成功时才调用成功处理程序,而仅当任务失败时才调用错误处理程序:

[self A]
.then(^(id result) {
return [self B:result];
}, nil)
.then(^(id result) {
return [self C:result];
}, nil)
.then(^(id result) {
return [self D:result];
}, nil)

.then(^(id result) {
NSLog(@"Success");
return nil;
}, ^id(NSError*error){
NSLog(@"ERROR: %@", error);
return nil;
});


关于承诺的更多内容,但远远超出了答案。

可以在此处找到实现的示例: RXPromise

关于ios - 如何将值从Helper类返回到 View Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17416683/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com