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

标签 ios objective-c custom-controls automatic-ref-counting uialertview

我编写了一个类似 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/

相关文章:

ios - 将 [NSFileWrapper initDirectoryWithFileWrappers] 转换为 Swift

objective-c - MPVolumeView 和 iOS 5

php - 发送 POST 数据包含数组 iOS

ios - 自定义 UIAlertView 没有委托(delegate)回调?

c# - 自定义用户控件未在自动生成的代码中初始化

ios - respondsToSelector 无法识别已实现的选择器

objective-c - 如何检测由于没有连接而调用 didFailWithError ?

c# - 无法创建自定义控件的复杂属性

ios - 将 facebook 与 ios5 应用程序集成

ios - 以编程方式创建 UICollectionView