我正在尝试创建一个实现自定义隧道协议的应用。 并在从块向变量分配值时遇到问题,请参见以下代码
@implementation ProfileTableViewController{
__block NSArray *vpnProfiles;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.allowsMultipleSelectionDuringEditing = NO;
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray* newManagers, NSError *error)
{
if(error != nil){
NSLog(@"Load Preferences error: %@", error);
}else{
if([newManagers count] > 0)
{
vpnProfiles = newManagers;
NSLog(@"vpnProfiles 1st: %ld", [vpnProfiles count]);
}
}
}];
NSLog(@"vpnProfiles 2nd: %ld", [vpnProfiles count]);
}
上面将打印
vpnProfiles 2nd: 0
vpnProfiles 1st: 1
我的理解是此问题是由于异步线程引起的,但是在搜索并尝试后似乎找不到解决方案。
有人对如何获取 newManagers 到本地变量 vpnProfiles 的建议吗?
答案 0 :(得分:1)
首先,代码中对Y
限定词的用途有误解。
此限定符仅适用于局部变量(请参见块语言规范中的The __block
Storage Qualifier),因为其目的是延长局部变量的寿命(如果它们可以被块修改),一旦在出口中定义了方法/功能/语言块,它们就会消失。
在代码aidl
中是一个实例变量,其生存期与其拥有的对象实例的生存期相关,因此__block
没有任何意义-不幸的是,编译器不会警告您,而只会忽略它。实例变量可以被一个块捕获和修改,因为这样做也可以捕获拥有的对象实例,因此通常(†)在该块引用它时保持其活动状态。
现在要问的主要问题和评论:
我的理解是此问题是由于异步线程引起的
完全正确。
您的vpnProfiles
方法接受一个完成处理程序,它可能会在返回的方法后的 之后的某个时间运行。
因此,在调用__block
之后的loadAllFromPreferencesWithCompletionHandler:
之后的之后执行该块中的NSLog
–如问题所示的输出所示
有人对如何获取
NSLog
到localinstance 变量loadAllFromPreferencesWithCompletionHandler:
的建议吗?
它已经由语句newManagers
分配了-问题是代码在 发生之前正在检查分配。
但是我似乎找不到解决方法
线索就在您的方法名称中,该块是一个补全处理程序,它将在将来的vpnProfiles
可用时被调用。您需要在此完成处理程序内 安排在该点之后 要做的工作。
例如,您可以对vpnProfiles = newManagers;
进行赋值,然后使用newManagers
安排一个块,该块在您的vpnProfiles
实例上调用读取dispatch_async()
的方法并做任何需要的事情。
我正在尝试创建一个实现自定义隧道协议的应用。
是时候进一步研究异步设计方法了,因为这对于此类代码至关重要。玩得开心!
HTH
注意
(†)如果捕获的对象引用是 weak ,则该对象不会保持活动状态。要了解有关此研究的更多信息,请参见“参考周期”和“弱自我”。