0

このコードを使用して、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がありませんでした)。ボタンは期待どおりに表示されますが、機能しません。iOS 8 では、ボタンの 1 つをタップするとクラッシュします (無効なメモリ ポインターを示していると思います)。iOS 9 では、ボタンをタップしても何も起こらず、ボタン メソッドのログが呼び出されません。(void)initWithNibName[CALayer button1]: unrecognized selector sent to instance

ARC にアップデートする前に自分のプロジェクトのコピーを持っていて、戻って iOS 8 または iOS 9 デバイスでそれを実行すると、ツールバー ボタンが再び機能します。したがって、ARC が問題の原因であるか、別の問題の引き金になっているようです。

このように、barButtonItem を自分自身に向けると...

[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 になったことを示唆しています。これは、nil でない場合、認識されないセレクターのクラッシュが発生するためです。

しかし、viewDidLoad でのログインが発生し、ビューが携帯電話と iOS 8 タブレットの inputAccessoryView として表示されるため、TextInputToolbar クラスとそのビューが読み込まれていることがわかります。

何が起こっているのか、またはトラブルシューティングのために他にできることはありますか?

4

2 に答える 2

1

これらのコードを呼び出すと、次のことが起こります。

UITextView *textInputMultiline = [[UITextView alloc] initWithFrame:frame];

//alloc textInputToolbar (textInputToolbar.retaincount = 1)
TextInputToolbar *textInputToolbar = [TextInputToolbar alloc];
textInputToolbar.textView = textInputMultiline;

if ((self.appDelegate.isTablet)&&([[[UIDevice currentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending)) {
    NSMutableArray *barButtonItems = [NSMutableArray array];
    //add button items....
    UIBarButtonItem *representativeItem = nil;

    //alloc UIBarButtonItemGroup (group.retaincount = 1)
    UIBarButtonItemGroup *group = [[UIBarButtonItemGroup alloc] initWithBarButtonItems:barButtonItems representativeItem:representativeItem];

    //strong reference group (group.retaincount = 2)
    textInputMultiline.inputAssistantItem.trailingBarButtonGroups = [NSArray arrayWithObject:group];
    //autorelease group 

} else {
    //strong reference textInputToolbar.view (textInputToolbar.view.retaincount = 2)
    textInputMultiline.inputAccessoryView = textInputToolbar.view;
}

//autorelease textInputToolbar (textInputToolbar.retaincount = 0, textInputToolbar.view.retaincount = 1)

iOS 8 では、textInputToolbar は dealloc になりますが、ビューはそうではありません。そのため、ボタンは表示されますが、クリックすると、オブザーバーがワイルド ポインターになり、ランタイムが関数を見つけられず、クラッシュしました。

iOS 9 では、textInputToolbar も dealloc になります。ボタンアイテムを作成し、inputToolbar の外にobserve(weak reference) ターゲットを設定したため、textInputToolbar が dealloc すると、observe が nil になり、関数が呼び出されませんでした。

于 2016-07-15T08:20:25.180 に答える