您可以以一般方式解决此问题,而无需在所有控制器中创建特定的块 iVar。您可以创建一个提供“完成时”块处理的类,然后从它继承,您的视图控制器都将具有“完成时”的能力。您可以只设置属性或提供“方便”方法。
请注意,第一部分的原始代码刚刚损坏,所以我更改了它。——呃。多么尴尬。无论如何,你明白了(如果你是一个厌恶联想的人,我只建议这样做)。
// Use this as a base class for your view controllers...
typedef void(^WhenDoneWithViewControllerBlock)(
UIViewController *viewController,
BOOL canceled);
@interface BlockDismissingViewController : UIViewController
@property (nonatomic, strong) WhenDoneWithViewControllerBlock whenDone;
- (void)done:(BOOL)canceled;
@end
@implementation BlockDismissingViewController
- (void)done:(BOOL)canceled {
if (self.whenDone) {
self.whenDone(self, canceled);
}
}
@end
// The "convenience" method should probably be something like this...
@implementation UIViewController (BlockDismissingViewController)
- (void)presentViewController:(BlockDismissingViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion
whenDone:(WhenDoneWithViewControllerBlock)whenDone {
viewControllerToPresent.whenDone = whenDone;
[self presentViewController:viewControllerToPresent
animated:flag
completion:completion];
}
@end
或者,您可以将其作为 UIViewController 上的一个类别,现在您的所有视图控制器都将获得此功能。您可以使用通知中心来调用适当的块...
@interface UIViewController (WhenDoneWithViewControllerBlock)
- (void)done:(BOOL)canceled;
@end
@implementation UIViewController (WhenDoneWithViewControllerBlock)
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion
whenDone:(WhenDoneWithViewControllerBlock)doneBlock {
if (doneBlock) {
__block id observer = [[NSNotificationCenter defaultCenter]
addObserverForName:@"DoneWithViewControllerNotification"
object:viewControllerToPresent
queue:nil
usingBlock:^(NSNotification *note) {
[[NSNotificationCenter defaultCenter] removeObserver:observer];
doneBlock(viewControllerToPresent, [[note.userInfo objectForKey:@"canceled"] boolValue]);
}];
}
[self presentViewController:viewControllerToPresent
animated:flag
completion:completion];
}
- (void)done:(BOOL)canceled {
[[NSNotificationCenter defaultCenter]
postNotificationName:@"DoneWithViewControllerNotification"
object:self
userInfo:@{ @"canceled" : @(canceled) }];
}
@end
或者,如果您仍然想要一个类别,但想要一个 iVar 并绕过通知中心......
// Using associated objects in a category
@interface UIViewController (WhenDoneWithViewControllerBlock)
@property (nonatomic, strong) WhenDoneWithViewControllerBlock whenDone;
- (void)done:(BOOL)canceled;
@end
@implementation UIViewController (WhenDoneWithViewControllerBlock)
char const kWhenDoneKey[1];
- (WhenDoneWithViewControllerBlock)whenDone {
return objc_getAssociatedObject(self, kWhenDoneKey);
}
- (void)setWhenDone:(WhenDoneWithViewControllerBlock)whenDone {
objc_setAssociatedObject(self, kWhenDoneKey, whenDone, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion
whenDone:(WhenDoneWithViewControllerBlock)whenDone {
viewControllerToPresent.whenDone = whenDone;
[self presentViewController:viewControllerToPresent animated:flag completion:completion];
}
- (void)done:(BOOL)canceled {
if (self.whenDone) {
self.whenDone(self, canceled);
}
}
@end
当然,这些只是示例,但希望您能理解。
当你的视图控制器完成后,它只是调用
[self done:canceledOrSuccess];
并且该块将被调用。
使用最后一个类别是我最喜欢的,尽管关联对象在时间和内存上都有性能成本。您可以获得保存“whenDone”块的“iVar”的便利(您可以显式设置它),并且您可以获得用于呈现的“convenience”方法,并且每个视图控制器都会自动获得此功能,只需添加类别即可。