在 objective-c 中保留块内分配的值
retain assigned values from within block in objective-c
我正在尝试创建一个实现自定义隧道协议的应用程序。
并且在为块中的变量赋值时遇到问题,请参见以下代码
@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[=25 有任何建议=]?
首先,代码中对 __block
限定符的用途存在误解。
此限定符仅适用于局部变量(参见 块的语言规范 中的 The __block
Storage Qualifier),因为它的目的是延长局部变量的生命周期,如果它们可以被块修改,一旦method/function/language-block它们在退出时被定义,它们通常会消失。
在代码中 vpnProfiles
是一个 实例变量 ,其生命周期与其拥有的对象实例的生命周期相关联,因此 __block
具有没有意义——不幸的是,编译器没有警告你,只是忽略了它。实例变量可以被块捕获和修改,因为这样做也会捕获拥有的对象实例,因此通常(†)在块引用时保持它的活动。
现在是主要问题和评论:
my understanding is that this issue is due to async threads
完全正确。
您的 loadAllFromPreferencesWithCompletionHandler:
方法接受一个完成处理程序,它可能 运行 在将来的某个时间 在 它返回的方法之后...
因此块内的 NSLog
在 之后执行 NSLog
在调用 loadAllFromPreferencesWithCompletionHandler:
之后 – 正如可以看到的问题中显示的输出。
anyone has suggestions on how to get newManagers
to local instance variable vpnProfiles
?
它已经被语句 vpnProfiles = newManagers;
赋值 – 问题是代码正在检查赋值 在 它发生之前。
but i can't seem to find a solution
线索在您的方法名称中,该块是一个 完成处理程序 ,它将在将来 newManagers
可用时调用。您需要在 这个完成处理程序中安排工作在 之后完成。
因此,例如,您可以对 vpnProfiles
进行赋值,然后使用 dispatch_async()
安排一个块,该块调用 ProfileTableViewController
实例上的方法,该实例读取 vpnProfiles
并做任何需要的事情。
I'm trying to create an app that implements customized tunnel protocols.
是时候进一步研究异步设计方法了,因为它对于此类代码至关重要。玩得开心!
HTH
备注
(†) 如果捕获的对象引用 弱 则对象不会保持活动状态。要了解有关此研究的更多信息 "reference cycles" 和 "weak self".
我正在尝试创建一个实现自定义隧道协议的应用程序。 并且在为块中的变量赋值时遇到问题,请参见以下代码
@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[=25 有任何建议=]?
首先,代码中对 __block
限定符的用途存在误解。
此限定符仅适用于局部变量(参见 块的语言规范 中的 The __block
Storage Qualifier),因为它的目的是延长局部变量的生命周期,如果它们可以被块修改,一旦method/function/language-block它们在退出时被定义,它们通常会消失。
在代码中 vpnProfiles
是一个 实例变量 ,其生命周期与其拥有的对象实例的生命周期相关联,因此 __block
具有没有意义——不幸的是,编译器没有警告你,只是忽略了它。实例变量可以被块捕获和修改,因为这样做也会捕获拥有的对象实例,因此通常(†)在块引用时保持它的活动。
现在是主要问题和评论:
my understanding is that this issue is due to async threads
完全正确。
您的 loadAllFromPreferencesWithCompletionHandler:
方法接受一个完成处理程序,它可能 运行 在将来的某个时间 在 它返回的方法之后...
因此块内的 NSLog
在 之后执行 NSLog
在调用 loadAllFromPreferencesWithCompletionHandler:
之后 – 正如可以看到的问题中显示的输出。
anyone has suggestions on how to get
newManagers
tolocalinstance variablevpnProfiles
?
它已经被语句 vpnProfiles = newManagers;
赋值 – 问题是代码正在检查赋值 在 它发生之前。
but i can't seem to find a solution
线索在您的方法名称中,该块是一个 完成处理程序 ,它将在将来 newManagers
可用时调用。您需要在 这个完成处理程序中安排工作在 之后完成。
因此,例如,您可以对 vpnProfiles
进行赋值,然后使用 dispatch_async()
安排一个块,该块调用 ProfileTableViewController
实例上的方法,该实例读取 vpnProfiles
并做任何需要的事情。
I'm trying to create an app that implements customized tunnel protocols.
是时候进一步研究异步设计方法了,因为它对于此类代码至关重要。玩得开心!
HTH
备注
(†) 如果捕获的对象引用 弱 则对象不会保持活动状态。要了解有关此研究的更多信息 "reference cycles" 和 "weak self".