1

我想创建一个与 UIAlertView 类似的类,它不需要强大的 ivar。

例如,使用 UIAlertView,我可以在我的 UIViewController 的方法之一中执行以下操作:

UIAlertView *alertView     = [[UIActionSheet alloc] initWithTitle:nil
                                                          message:@"Foo"
                                                         delegate:nil
                                                cancelButtonTitle:@"Cancel"
                                                otherButtonTitles:nil];
[alertView show];

...并且 actionSheet 将不会被释放,直到它不再可见。

如果我要尝试做同样的事情:

MYAlertView *myAlertView = [[MYAlertView alloc] initWithMessage:@"Foo"];
[myAlertView show];

...myAlertView实例将在我所在的当前方法结束时自动释放(例如,就在该[myAlertView show]行之后)。

什么是防止这种情况发生的正确方法,而不必将 myView 声明为strong我的 UIViewController 上的属性?(即我希望 myView 是一个局部变量,而不是一个实例变量,并且我希望 MYAlertView 实例负责它自己的生命周期,而不是我的 UIViewController 控制它的生命周期。)

更新:MYAlertView 继承自 NSObject,因此无法添加到 Views 层次结构中。

4

4 回答 4

5

UIAlertView创建一个UIWindow,它保留。然后警报视图将自身添加为窗口的子视图,因此窗口保留警报视图。因此,它创建了一个保留周期,使它和它的窗口都保持活动状态。 UIActionSheet以同样的方式工作。

如果您需要您的对象留在周围,并且没有其他东西可以保留它,那么它可以保留自己。您需要确保您有一个明确定义的方法,以便在不再需要它时自行释放。例如,如果它正在管理一个窗口,那么它应该在将窗口从屏幕上移开时释放自己。

于 2013-07-09T23:57:05.677 回答
2

如果您将其添加为另一个视图的子视图,它将被保留。当用户选择并操作或关闭它时,它应该调用 self removeFromSuperview 作为它的最后一幕。

于 2013-07-09T23:03:53.610 回答
2

我用一个小技巧完成了我自己的 AlertView。

只需保留对象本身并在操作时释放它。有了这个,您可以将您的自定义警报视为原生警报。

#import "BubbleAlertView.h"
#import <QuartzCore/QuartzCore.h>

@interface BubbleAlertView ()
...
@property (nonatomic, strong) BubbleAlertView *alertView;
...

@end

@implementation BubbleAlertView

...

- (id)initWithTitle:(NSString*)title message:(NSString*)message delegate:(id)delegate cancelButtonTitle:(NSString*)cancelButtonTitle okButtonTitle:(NSString*) okButtonTitle
{
self = [super init];
if (self)
{
    // Custom initialization
    self.alertView = self; // retain myself

    //More init stuff 
}
return self;
}
...

//SHOW METHOD

- (void)show
{
// We need to add it to the window, which we can get from the delegate
id appDelegate = [[UIApplication sharedApplication] delegate];
UIWindow *window = [appDelegate window];
[window addSubview:self.view];

// Make sure the alert covers the whole window
self.view.frame = window.frame;
self.view.center = window.center;

}

- (IBAction)btPressed:(id)sender
{
//Actions done

[UIView animateWithDuration:0.4f animations:^{
    self.vContent.alpha = 0.f;
} completion:^(BOOL finished) {
    [self.view removeFromSuperview];
    self.alertView = nil; // deallocate myself
}];

}
于 2013-07-10T14:28:20.053 回答
1

您需要以某种方式保留它,直到它被释放。

我真的不明白为什么你不能将它实现为UIView. 然后,您可以使用视图层次结构作为强引用的保持者(保留 +1)。但是您将有充分的理由不这样做。

如果你没有这样的东西,那么我会使用NSMutableArrayas class varialbe(意思是 statc)。只需在@interface块中声明它并用 nil 初始化它:

@interface

static NSMutableArray _allMyAlerts = nil;

提供访问器。

-(NSMutableArray *) allMyAlerts {

  if (_allMyAlerts == nil) {
     _allMyAlerts = [[NSMutableArray alloc] init];
  }
  return _allMyAlerts
}

在 init 方法中执行以下操作:

- (id) init {

  self = [super init];
  if (self) {
    [[self allMyAlerts] addObject:self];
  }

}

当警报被解除时,您将调用一些方法。

- (void) dismissAlert {

  // Do your stuff here an then remove it from the array. 

  [[self allMyAlerts] removeObject:self];
}

您可能想要添加一些东西以使其多线程保存,但事实并非如此。我只想举一个例子来解释这个概念。

allMyAlert 也可以是一个NSMutableSet。据我所知,不需要数组。将对象添加到数组或集合中会将保留计数加 1,删除它会将保留计数减 1。

于 2013-07-09T23:34:29.650 回答