2

我正在尝试在项目中使用它:https ://github.com/zakkhoyt/VWWPermissionKit

我不太了解 KVO/通知中心,所以我想发布一个问题。

权限管理器的 init 和 dealloc 基本上是这样的:

- (instancetype)init {
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserverForName:VWWPermissionNotificationsPromptAction object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
            dispatch_async(dispatch_get_main_queue(), ^{
                VWWPermission *permission = note.userInfo[VWWPermissionNotificationsPermissionKey];
                [permission presentSystemPromtWithCompletionBlock:^{
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [permission updatePermissionStatus];

                        if(permission.status == VWWPermissionStatusDenied){
                            [self.permissionsViewController displayDeniedAlertForPermission:permission];
                        }



                        [self checkAllPermissionsSatisfied];    
                    });
                }];
            });
        }];

        [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self readPermissions];
            });
        }];

    }
    return self;
}

-(void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

如果我想读取一组权限,我会称之为:

NSArray *permissionsToRead = @[
                                [VWWCoreLocationWhenInUsePermission permissionWithLabelText:nil],
                                [VWWNotificationsPermission permissionWithLabelText:nil]
                                ];
[VWWPermissionsManager readPermissions:permissionsToRead resultsBlock:^(NSArray *permissions) {
// Do something with the result
    }
}];

这一切都很好。问题是 dealloc 没有被调用,因此通知仍在被调用,例如UIApplicationDidBecomeActiveNotification在 init 方法中创建的。

据我所见,权限管理器已创建且未引用,因此它只是挂起。

readPermssions 的公共方法如下:

+(void)readPermissions:(NSArray*)permissions resultsBlock:(VWWPermissionsManagerResultsBlock)resultsBlock{
    VWWPermissionsManager *permissionsManager = [[self alloc]init];
    [permissionsManager readPermissions:permissions resultsBlock:resultsBlock];
}

创建一个新实例并调用另一个方法,然后将 resultsBlock 传回。据我所知,没有什么可以释放这个。我将如何让 dealloc 被调用?

4

1 回答 1

1

这是因为NSNotificationCenter保留了观察者对象,它保留了向它注册的块,它正在捕获您的视图控制器并防止它被释放。

如果您希望您的视图控制器能够被释放,那么您应该在块外创建一个对它的弱引用 ( __weak typeof(self) weakSelf = self;) 并在块weakSelf内使用。

您也没有正确移除观察者。当您使用通知中心块 api 添加观察者时,它会返回一个对象,该对象实际上是作为观察者添加的,您需要保留对removeObserver:.

我建议不要使用该方法来观察块,因为它增加了比其价值更多的管理麻烦。改用带有选择器的那个。

于 2015-08-06T22:03:16.753 回答