2013-03-30 6 views
14

私はルートビューコントローラからプッシュするいくつかのビューコントローラとテーブルビューコントローラを持っています。これらのすべてで、ナビゲーションコントローラでカスタムの戻るボタンを使用したいと思います。私の戻るボタンを各クラスファイルに設定するメソッドをコピーする代わりに、セットアップを行うクラスメソッドでヘルパークラスを作成しました。下のコードはうまくいきますが、私はこれを間違った方法で行っているのだろうかと思います。これを達成するより良い方法はありますか?また、私はまだすべてのクラスで - (void)myCustomBackメソッドを複製していますが、それを回避する方法があるかどうか疑問に思っていました。Objective Cのクラス間でメソッドを共有する最適な方法は何ですか?

@interface NavBarBackButtonSetterUpper : NSObject 
+ (UIButton *)navbarSetup:(UIViewController *)callingViewController; 
@end 

@implementation NavBarBackButtonSetterUpper 

+ (UIButton *)navbarSetup:(UIViewController *)callingViewController 
{ 
    callingViewController.navigationItem.hidesBackButton = YES; 

    UIImage *backButtonImage = [[UIImage imageNamed:@"back_button_textured_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; 

    UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 30)]; 

    [backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal]; 

    [backButton setTitle:@"Back" forState:UIControlStateNormal]; 
    backButton.titleLabel.font = [UIFont fontWithName:@"AmericanTypewriter-Bold" size:12]; 
    backButton.titleLabel.shadowOffset = CGSizeMake(0,-1); 

    UIView *customBackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 30)]; 
    [customBackView addSubview:backButton]; 

    callingViewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customBackView]; 

    return backButton; 
} 
@end 



@interface MyCustomTableViewController : UITableViewController 
@end 

@implementation MyCustomTableViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIButton *backButton = [NavBarBackButtonSetterUpper navbarSetup:self]; 

    [backButton addTarget:self action:@selector(myCustomBack) forControlEvents:UIControlEventTouchUpInside]; 
} 

- (void)myCustomBack 
{ 
    [self.navigationController popViewControllerAnimated:YES]; 
} 
@end 


@interface MyCustomViewController : UIViewController 
@end 

@implementation MyCustomViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIButton *backButton = [NavBarBackButtonSetterUpper navbarSetup:self]; 

    [backButton addTarget:self action:@selector(myCustomBack) forControlEvents:UIControlEventTouchUpInside]; 
} 

- (void)myCustomBack 
{ 
    [self.navigationController popViewControllerAnimated:YES]; 
} 
@end 

答えて

4

ありがとう、あなたの応答と正しい方向に私を指しています。私は、他のクラスで使用したいメソッドを含むUIViewControllerのカテゴリを作成しました。これを行うもっとエレガントな方法があるなら、私は提案を聞いてうれしいです。これは私が一緒に行ったものです:

// UIViewController+BackButtonSetup.h 

@interface UIViewController (BackButtonSetup) 
- (void)backButtonSetup; 
- (void)myCustomBack; 
@end 


// UIViewController+BackButtonSetup.m 

@implementation UIViewController (BackButtonSetup) 

- (void)backButtonSetup 
{ 
    self.navigationItem.hidesBackButton = YES; 

    // A Bunch of code to set up the custom back button 

    [backButton addTarget:self action:@selector(myCustomBack) forControlEvents:UIControlEventTouchUpInside]; 

} 

- (void)myCustomBack 
{ 
    [self.navigationController popViewControllerAnimated:YES]; 
} 

@end 


// MyCustomTableViewController.m 

#import "UIViewController+BackButtonSetup.h" 

@implementation MyCustomTableViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [self backButtonSetup]; 
} 
@end 


//MyCustomViewController.m 

#import "UIViewController+BackButtonSetup.h" 

@implementation MyCustomViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [self backButtonSetup]; 
} 
@end 
+0

良い選択。このパターンは私に非常によく役立っており、私はそれを使用して後悔したことはありません。これがあなたの最初の質問であることに気がついたので、チェックマークをクリックすることで、答えとしてマークする必要があります。ジョシュ・カズウェルや自分の答えが私の見解では良い選択をするだろうが、明らかにあなたの決定だけである。良い最初の質問、あなたが貢献し続けていることを願って、運の最高。 –

+0

@CarlVeazey - ありがとう!これが私の最初の質問であるので、答えを記入するための適切な礼儀はまだ少し不明です。私はすべての答えを読んで、それらをすべて考慮して行きました、そして、私は行くとカテゴリを作成する方法を研究しました。さらに、私は応答とその問題に対するより良い解決策を待っていました。しかし、この時点で私は自分の仕事がうまくいくと思います。 – Dylan

4

私はあなたの問題に対する解決策は継承であると考えています。

UIViewControllerのサブクラスを作成し、すべてのカスタムView Controllerにこのカスタムサブクラスを継承させることができます。 "親"サブクラスには-(void)myCustomBackとセットアップコードがあり、これをもう一度繰り返す必要はありません。

+0

これはこれです。カテゴリやプロトコルも使用できますが、サブクラス化はこのインスタンスでは最も簡単な方法のようです。オブジェクトに応じて実装が変更された場合にのみ、メソッドをオーバーライドする必要があります。 – user2000809

+2

これは、ビューコントローラとテーブルビューコントローラの両方をサブクラス化しなければならないので、重複したコードが残っている可能性があります。 – Andreas

+0

'UIViewController'と' UITableViewController'の両方のサブクラスを作成する必要がありますか?私はまだ2つの場所でコードを複製しています。 – Dylan

2

セットアップ方法は実際には別のクラスにする必要はありません。私はそれを機能させるべきだと言いたい。

myCustomBack方法、限り、それはすべてあなたのサブクラスでまったく同じだとして、簡単UIViewController上のカテゴリーに入れることができます。

@interface UIViewController (DylanBack) 
- (void)DylanCustomBack; 
@end 

@implementation UIViewController (DylanBack) 
- (void)DylanCustomBack 
{ 
    [self.navigationController popViewControllerAnimated:YES]; 
} 
@end 

は(自分の名前のいずれかから作られた、接頭辞のためinitialismを使用します、または会社やプロジェクトの名前ですが、醜い場合でも、衝突の可能性を避ける必要があります。カテゴリの衝突はぎこちない方法を作り、ぎこちないバグが発生します)。

これを実行している限り、ヘルパーメソッドもカテゴリに入れてください。それをインスタンスメソッドに変換し、渡されたコントローラの代わりにselfを使用します。

あなたのすべてのサブクラスはメソッドを継承し、そこに定義したのと同じようにメソッドを継承します。何らかの専門化が必要なクラスがあれば、オーバーライドすることができます。

1

これについては、より良い方法があります。UIAppearanceプロトコルを使用してください。これらのプロパティをすべて設定し、カスタムビュータイプまたはナビゲーションバーに含まれるすべての戻るボタンにルックを継承させることができます。

Here's a screencast that will help you。そこからコードの一部:それCustomNavigationBarクラスがちょうどその外観を取得するためにすべてのバックボタンを引き起こすであろう、UINavigationBarできること

UIImage *back = [UIImage imageNamed:@"nav-backbutton.png"]; 
back = [back stretchableImageWithLeftCapWidth:ArrowLeftCap topCapHeight:0]; 

[[UIBarButtonItem appearanceWhenContainedIn:[CustomNavigationBar class], nil] 
       setBackButtonBackgroundImage:back 
            forState:UIControlStateNormal 
           barMetrics:UIBarMetricsDefault]; 

注意。

これではできないことの1つは、「戻る」というタイトルです。それはあなたのすべてのビューコントローラになければならないでしょう。

+0

ああ、私の答えが終わる前にあなたは答えました。 – Sulthan

+0

私がこの道を下った理由は、戻るボタンのタイトルを変更したり、ラベルを付ける代わりに「ホーム」イメージに変更することができたからです。残念ながら、 'UIBarButtonItem'ではそれができません。私はカスタムビューを使用することでしかできませんでした。私は他のすべてのボタンとナビゲーションバー自体に 'UIAppearance'プロトコルを使用しています。 – Dylan

0

ほとんどの言語で、簡単な解決策は、静的(クラス)メソッドを持つ複数のUtilsクラスを持つことです。

Obj-Cでは、一般的な方法はカテゴリを使用しています。

あなたの例では、UIBarButtonItemにカテゴリを作成します。方法+(UIBarButton*)customBackButtonUIBarButtonItem (CustomizedButtons)がはるかに良いでしょう。

しかし、もっと簡単な方法があります。 あなたはのは

NSDictionary* titleAttributes = [NSDictionary dictionaryWithObjectsAndKeys: 
            [UIFont titilliumBoldWithSize:14.0f], UITextAttributeFont, 
            [UIColor colorWithIntegerRed:181 green:201 blue:210], UITextAttributeTextColor, 
            [UIColor clearColor], UITextAttributeTextShadowColor, 
            [NSValue valueWithUIOffset:UIOffsetMake(1.0f, 1.0f)], UITextAttributeTextShadowOffset, 
            nil]; 

NSDictionary* titleAttributesHighlighted = [NSDictionary dictionaryWithObjectsAndKeys: 
               [UIFont titilliumBoldWithSize:14.0f], UITextAttributeFont, 
               [UIColor whiteColor], UITextAttributeTextColor, 
               [UIColor clearColor], UITextAttributeTextShadowColor, 
               [NSValue valueWithUIOffset:UIOffsetMake(1.0f, 1.0f)], UITextAttributeTextShadowOffset, 
               nil]; 

[[UIBarButtonItem appearance] setTitleTextAttributes:titleAttributes forState:UIControlStateNormal];  
[[UIBarButtonItem appearance] setTitleTextAttributes:titleAttributesHighlighted forState:UIControlStateHighlighted]; 

[[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0.0f, 1.0f) forBarMetrics:UIBarMetricsDefault]; 

UIImage* backButtonImage = [UIImage imageNamed:@"navigation_button_back_bg"]; 
UIImage* backButtonImageHighlighted = [UIImage imageNamed:@"navigation_button_back_bg_highlighted"]; 

UIEdgeInsets backButtonCapInsets; 
backButtonCapInsets.top = 0.0f; 
backButtonCapInsets.bottom = backButtonImage.size.height; 
backButtonCapInsets.left = 14.0f; 
backButtonCapInsets.right = 5.0f; 

backButtonImage = [backButtonImage resizableImageWithCapInsets:backButtonCapInsets]; 
backButtonImageHighlighted = [backButtonImageHighlighted resizableImageWithCapInsets:backButtonCapInsets];  

[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage 
                forState:UIControlStateNormal 
               barMetrics:UIBarMetricsDefault]; 

[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImageHighlighted 
                forState:UIControlStateHighlighted 
               barMetrics:UIBarMetricsDefault]; 

の例を見てみましょう、一つの場所にあなたのバックボタンのすべての外観を変更することができますが、カスタムビューと特別なバックボタンセレクターを使用する必要はありません。

+0

ありがとうございます - 私は他のすべての 'UIBarButtonItem'に' UIAppearance'プロトコルを使用しています。他のビューコントローラのバックボタンに使用しています。問題は、カスタム表示を使用せずに戻るボタンのタイトルを変更できないことです。 – Dylan

+0

タイトルをアイコンに変更することはできませんが、タイトルを変更することはできます。タイトルはスタック上の前のコントローラの 'title'プロパティです。 – Sulthan

+0

私は、 'viewDidDisappear'でルートビューコントローラのタイトルを変更し、' viewWillAppear'でそれをリセットすることができますが、これはちょっと "ハッキー"ですが、私の現在のアプローチも "ハッキー"だと思います。しかし、タイトルの代わりにイメージを使用すると、カスタムビューを使用する必要があります。 – Dylan

関連する問題