inputAssistantItem和inputAccessoryView停止使用ARC

时间:2016-07-09 18:48:17

标签: ios automatic-ref-counting uitextinput

我正在使用此代码在我的iOS应用中在屏幕键盘上方添加一些按钮。请注意,我在手机和iOS 9之前的设备上使用旧的inputAccessoryView方法,在iOS 9平板电脑上使用较新的inputAssistantItem:

UITextView *textInputMultiline = [[UITextView alloc] initWithFrame:frame];
TextInputToolbar *textInputToolbar = [TextInputToolbar alloc]; // custom class
(void)[textInputToolbar initWithNibName:@"TextInputToolbar" bundle:nil];
textInputToolbar.textView = textInputMultiline;
if ((self.appDelegate.isTablet)&&([[[UIDevice currentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending)) {
    NSMutableArray *barButtonItems = [NSMutableArray array];
    [barButtonItems addObject:[[UIBarButtonItem alloc] initWithTitle:@"button 1" style:UIBarButtonItemStylePlain target:textInputToolbar action:@selector(button1)]];
    [barButtonItems addObject:[[UIBarButtonItem alloc] initWithTitle:@"button 2" style:UIBarButtonItemStylePlain target:textInputToolbar action:@selector(button2)]];
    [barButtonItems addObject:[[UIBarButtonItem alloc] initWithTitle:@"button 3" style:UIBarButtonItemStylePlain target:textInputToolbar action:@selector(button3)]];
    UIBarButtonItem *representativeItem = nil;
    UIBarButtonItemGroup *group = [[UIBarButtonItemGroup alloc] initWithBarButtonItems:barButtonItems representativeItem:representativeItem];
    textInputMultiline.inputAssistantItem.trailingBarButtonGroups = [NSArray arrayWithObject:group];
} else {
    textInputMultiline.inputAccessoryView = textInputToolbar.view;
}

我的自定义工具栏类如下所示:

@interface TextInputToolbar : UIViewController {
    UITextView *textView;

    IBOutlet UIButton *button1;
    IBOutlet UIButton *button2;
    IBOutlet UIButton *button3;
}

@property (nonatomic, strong) UITextView *textView;

- (void)insertText:(NSString *)text;

- (IBAction)button1;
- (IBAction)button2;
- (IBAction)button3;

@end

和...

#import "TextInputToolbar.h"

@implementation TextInputToolbar

@synthesize textView;

- (void)viewDidLoad {
    NSLog(@"viewDidLoad");
    [super viewDidLoad];
}

- (void)insertText:(NSString *)text {
    [self.textView insertText:text];
}

- (IBAction)button1 {
    NSLog(@"button1");
    [self insertText:@"1"];
}

- (IBAction)button2 {
    NSLog(@"button2");
    [self insertText:@"2"];
}

- (IBAction)button3 {
    NSLog(@"button3");
    [self insertText:@"3"];
}

@end

当我的应用不使用ARC时,这可以正常工作。我最近更新到ARC,它只需要对上面的代码进行最小的更改(我之前在UIBarButtonItems上有自动发布,并且在(void)之前没有initWithNibName强制转换),并且现在按钮仍然按预期显示,但不起作用。在iOS 8上,当我点击其中一个按钮([CALayer button1]: unrecognized selector sent to instance,我认为它指示无效的内存指针)时,我遇到了崩溃,而在iOS 9上,当我点击一个按钮时没有任何反应,并且按下按钮方法没有被调用。

在更新到ARC之前,我有一个项目的副本,当我在iOS 8或iOS 9设备上返回并运行它时,工具栏按钮再次工作。因此,ARC似乎是问题的根源或不同问题的触发因素。

如果我将barButtonItem指向self,就像这样......

[barButtonItems addObject:[[UIBarButtonItem alloc] initWithTitle:@"button 3" style:UIBarButtonItemStylePlain target:self action:@selector(test)]];

...按预期收到方法调用。如果我将barButtonItem选择器更改为无效方法,就像这样......

[barButtonItems addObject:[[UIBarButtonItem alloc] initWithTitle:@"button 3" style:UIBarButtonItemStylePlain target:textInputToolbar action:@selector(flkjfd)]];

......没有任何反应。这告诉我,当按钮选择器被调用时,textInputToolbar在某种程度上变为零,因为如果它不是nil,则会产生无法识别的选择器崩溃。

但我知道TextInputToolbar类及其视图正在加载,因为viewDidLoad中的日志记录会发生,并且因为视图显示为inputAccessoryView手机和iOS 8平板电脑。

知道发生了什么,或者我还能做些什么来解决问题?

2 个答案:

答案 0 :(得分:1)

您的代码永远不正确,只是因为泄漏而起作用。你基本上失去了/没有保留视图控制器。它曾经只是继续存在和工作,但在ARC下它被释放,所以没有什么可以响应按钮。 ARC修复了你的记忆问题,让你意识到这是一个问题,虽然不是一个想法。

要修复,请在使用视图时保留视图控制器。

另外,我不知道你在哪里学习:

TextInputToolbar *textInputToolbar = [TextInputToolbar alloc]; // custom class
(void)[textInputToolbar initWithNibName:@"TextInputToolbar" bundle:nil];

但你不应该这样做。在一条线上完成所有这一切。不要忽略init次呼叫返回的对象 - 它可能与您最初呼叫的对象不同。

答案 1 :(得分:1)

调用这些代码时会发生什么:

<div>
            <form> 
                <div class="form-group"> 
                    <label for="kategori">Tambah Kota</label>
                    <br/>
                    @(Html.Kendo().ComboBox()
                      .Name("propinsi")
                      .Placeholder("Pilih Provinsi")
                      .DataTextField("Text")
                      .DataValueField("Value")
                      .HtmlAttributes(new { style = "width:40%;" })
                      .Filter("contains")
                            .DataSource(source => { source.Read(read => read.Action("GetProvinsiByJSON", "Lokasi")); })
                    )
                    <input type="text" class="form-control" id="kota" name="kota" placeholder="Nama Kota">
                    <button type="submit" class="btn btn-default">Simpan</button> 
                </div>
            </form>
        </div>

在iOS 8中,textInputToolbar将是dealloc,但它的视图不会。这就是为什么你可以看到按钮但是当你点击它们时,观察者变成了一个狂野的指针,运行时找不到这个功能,所以它就崩溃了。

在iOS 9中,textInputToolbar也将是dealloc。因为你创建了按钮项并将observe(弱引用)目标设置在InputToolbar之外,所以当textInputToolbar dealloc时,观察变为nil.So函数将不会被调用。