2016-07-09 16 views
0

我正在使用此代碼在iOS應用中的屏幕鍵盤上方添加一些按鈕。請注意,我用的手機和預先的iOS 9器件,老inputAccessoryView方法和iOS 9片的新inputAssistantItem:inputAssistantItem和inputAccessoryView停止使用ARC

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上有自動釋放,並且在initWithNibName之前沒有(void)),現在按鈕仍然按預期顯示,但不顯示工作。在iOS 8上,當點擊其中一個按鈕([CALayer button1]: unrecognized selector sent to instance,我認爲這表示無效的內存指針)時,我會崩潰,並且在iOS 9上,當我點擊按鈕時沒有任何反應,並且不調用按鈕方法中的日誌記錄。

在更新到ARC之前,我有一個項目的副本,當我回到iOS 8或iOS 9設備上運行該項目時,工具欄按鈕再次工作。所以看起來ARC不是問題的根源就是引發了另一個問題。

如果我點barButtonItem自我,像這樣...

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

...如預期的那樣收到方法調用。如果我將barButtonItem選擇器更改爲無效方法,就像這樣...

......沒有任何反應。這向我暗示textInputToolbar在調用按鈕選擇器時會以某種方式變爲零,因爲如果它不爲零,則會產生無法識別的選擇器崩潰。

但我知道TextInputToolbar類及其視圖正在加載,因爲在viewDidLoad中進行了日誌記錄,並且因爲該視圖顯示爲inputAccessoryView,因此手機和iOS 8平板電腦都是這樣。

任何想法發生了什麼,或者我能做些什麼來排除故障?

回答

1

你的代碼從來不是正確的,只是因爲泄漏才起作用。你基本上失去/不保留視圖控制器。它過去只是繼續存在和工作,但在ARC下它已經發布,所以沒有任何響應按鈕。 ARC已經解決了你的記憶問題,並且讓你意識到存在一個問題,儘管這不是一個好主意。

要修復,保留視圖控制器,同時其視圖正在使用。

而且,我不知道你在哪裏學會了做:

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

,但你不應該。這一切都在一條線上。不要忽略從init調用中返回的對象 - 它可能與您最初調用它的對象不同。

+0

你說得對,我應該在textInputToolbar上有一個autorelease,我剛剛確認會打破非ARC的功能。你能告訴我如何在這種情況下正確保留和釋放te​​xtInputToolbar嗎?我是否需要使用父視圖控制器的實例變量而不是本地變量,或者我可以以某種方式執行此代碼塊中的所有操作? – arlomedia

+0

您需要將屬性添加到包含視圖控制器,實例變量,是。 – Wain

+0

謝謝,解決了它。 – arlomedia

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之外,因此當textInputToolbar dealloc時,觀察變爲零,因此不會調用該函數。