gpt4 book ai didi

ios - NSURLSession 和代表

转载 作者:行者123 更新时间:2023-12-03 17:18:55 27 4
gpt4 key购买 nike

在一个小型 iOS 应用程序中,我需要从服务器检索一些 JSON(类似于 DNS 请求),并使用此响应来发起进一步的连接。为此,我有一个使用 NSURLSession 处理 JSON 请求的对象。该对象接收主对象 (MainController) 作为委托(delegate),并在 JSON 数据可用时调用方法。这是 MainController 中的调用:

- (void)serverResolve:(NSString *)serverID withPass:(NSString *)pass {
// Must retrieve the server list from JSON
ServerListRetriever *slCom = [[ServerListRetriever alloc] init];
slCom.delegate = self;
[slCom searchServer:serverID usingPass:pass];
}

我的问题是,一旦completionHandler开始运行,MainController就不会做它应该做的事情。我不知道为什么???

这是 ServerListRetriever 的内容( header ):

#import "ServerListRetrieverDelegate.h"

@interface ServerListRetriever : NSObject
@property (assign, nonatomic) id <ServerListRetrieverDelegate> delegate;

- (void)searchServer:(NSString *)serverID usingPass:(NSString *)pass;
@end

...(和实现)

#import "ServerListRetriever.h"
#define SERVER_LIST @"https://www.example.com/hosts.json"
@implementation ServerListRetriever

- (void)searchServer:(NSString *)serverID usingPass:(NSString *)pass
{
// This will work...
[self.delegate serverConnect:@"https://www.example.net/" withPass:pass];
return;

// And if removing the above two lines, this won't work
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:SERVER_LIST]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// Handle response
if (error) {
[self.delegate serverListFailedWithError:error];
} else {
// NSLog(@"Retrieved JSON: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);

// Extract the server URL
NSError *jsonError = nil;
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];

if (jsonError) {
[self.delegate serverListFailedWithError:jsonError];
return;
}

NSString *serverURL = [parsedObject objectForKey:serverID];
NSLog(@"Resolved server URL: %@", serverURL);

// Continue with connection
[self.delegate serverConnect:serverURL withPass:pass];
}
}] resume];
}

@end

方法serverConnect在这两种情况下都会运行,但是当由completionHandler调用时,很多想法将无法正常工作。我已经通过调试检查了委托(delegate),并且在这两种情况下它具有相同的 ID。

由于我仍在 iOS 上的内存管理方面苦苦挣扎,过早丢失一些对象可能是一个解释。然而,我缺乏定位问题的经验。感谢您的想法和建议!

最佳答案

关于代表是否应该强大一直存在争论。如果它们很弱,那么您保证不会出现保留循环,但这也意味着如果委托(delegate)没有被其他人保留,它可能会在异步操作完成之前消失。

通常处理这种情况的方法是制作委托(delegate)的强大内部副本,例如

@interface ServerListRetriever ()
@property (strong, nonatomic) id <ServerListRetrieverDelegate> strongDelegate;
@end

...

// When an operation is started:
self.strongDelegate = self.delegate;

// When the *last* operation ends (keep an array of operations or something):
self.strongDelegate = nil;

或者,您可以将公共(public)委托(delegate)属性标记为强,但您需要在使用完毕后显式将 ServerListRetriever 的委托(delegate)清空,或者将最后一个引用清空ServerListRetriever 对象本身。

关于ios - NSURLSession 和代表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43798152/

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