我编写了一个类似 UIAlertView 的类(GOAlertView),只是为了具有与 iOS7 beta 4 众所周知的属性“contentView”相同的功能,该属性已在 iOS7 beta 5 中删除,换句话说,我正在尝试创建一个自定义警报 View 。但是使用 Apple 的 UIAlertView 可以有这样的代码:
[[[UIAlertView alloc] initWithTitle:@"Hello" message:@"Are you good programmer" delegate:self cancelButtonTitle:@"No comments" otherButtonTitles:@"Ya", @"Hee :)", nil] show];
重要:这里我没有像
那样持有任何 UIAlertView 的强引用@property (strong, nonatomic) UIAlertView *alertView;
我是在即时使用它。不仅如此,我还可以发送委托(delegate)消息。
问题:但是使用我自己的 GOAlertView(它不是 UIAlertView 的子类),我可以显示我的 AlertView,因为它已立即被释放。但如果我像上面提到的那样持有强引用,它就有效。但我无法即时使用它。
我看到了一个例子:https://github.com/TomSwift/TSAlertView/blob/master/TSAlertView/TSAlertView.m
程序员在方法“-show”中说“$important - 仅当用户单击警报 View 按钮时才会释放窗口”,并且他自己释放“window”对象。但我不能这样做,因为我正在启用 ARC 的环境中工作,我什至不想禁用它(我只适用于 GOAlertView)。
任何人都可以给出解释或者可能是具有类似 contentView 的属性的相同示例...?
模拟代码:
GOAlertView.m 是:
#import "GOAlertView.h"
@interface GOAlertView ()
@property (strong, nonatomic) UIWindow *window;
@end
@implementation GOAlertView
- (void)show {
UIViewController *vc = [UIViewController new];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
[self.window setWindowLevel:UIWindowLevelStatusBar];
[self.window setRootViewController:vc];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(60, 100, 200, 160)];
[view setBackgroundColor:[UIColor purpleColor]];
[vc.view addSubview:view];
[self.window setHidden:NO];
}
和GOViewController.m是:
#import "GOViewController.h"
#import "GOAlertView.h"
@interface GOViewController ()
@property (strong, nonatomic) GOAlertView *alertView;
@end
@implementation GOViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// [self setAlertView:[[GOAlertView alloc] init]];
// [self.alertView show];
[[[GOAlertView alloc] init] show];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
这里,如果我使用
[self setAlertView:[[GOAlertView alloc] init]];
[self.alertView show];
相反
[[[GOAlertView alloc] init] show];
目前,我可以在屏幕上看到一个紫色方 block 。
最佳答案
实现此目的的一种方法是,在您的 GOAlertView 类中,当您初始化实例时,(ab)使用关联的存储来让对象保留自身,直到将其添加到 View 层次结构中(之后, View 层次结构将保留它。)像这样:
#import <objc/runtime.h>
static void * const AssociatedStorageKey = (void*)&AssociatedStorageKey;
- (id)init
{
if (self = [super init])
{
// Hacky retain self...
objc_setAssociatedObject(self, AssociatedStorageKey, self, OBJC_ASSOCIATION_RETAIN);
}
return self;
}
- (void)show
{
[super show];
// Should be in the view hierarchy now and retained by that, so we'll release our hacky retain
objc_setAssociatedObject(self, AssociatedStorageKey, nil, OBJC_ASSOCIATION_RETAIN);
}
请注意,这会创建一个保留周期,因此如果从未调用 -show
,您的对象将有效地泄漏自身及其保留的整个对象图。
关于ios - 自定义 UIAlertView : How to prevent an Objective-C object to be released automatically by ARC or How to retain an object manually in an ARC environment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18981326/