2

我编写了一个 UIAlertView 类(GOAlertView),只是为了具有与 iOS7 beta 4 的众所周知的属性“contentView”相同的功能,该属性已在 iOS7 beta 5 中删除,换句话说,我正在尝试创建一个自定义的 AlertView。但是使用 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; 

相反,我正在即时使用它。不仅如此,我也可以委托消息。

问题:但是使用我自己的 GOAlertView(它不是 UIAlertView 的子类)我可以显示我的 AlertView,因为它已被立即解除分配。但是,如果我像上面提到的那样持有强参考,它就可以工作。但我不能即时使用它。

我看过一个例子:https ://github.com/TomSwift/TSAlertView/blob/master/TSAlertView/TSAlertView.m

程序员在方法'- show'中说“$important - 仅当用户单击警报视图按钮时才释放窗口”并且他自己释放“窗口”对象。但我不能这样做,因为我在启用 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];

目前,我可以在屏幕上看到一个紫色方块。

4

1 回答 1

2

一种方法是,在您的 GOAlertView 类中,当您初始化实例时,(ab)使用关联存储让对象保留自身,直到它被添加到视图层次结构中(之后,视图层次结构将保留它。)像这样:

#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从不调用,您的对象将有效地泄漏自身以及它保留的整个对象图。

于 2013-09-24T12:49:04.203 回答