web-dev-qa-db-ja.com

UINavigationControllerのすべてのビューコントローラーに同じボタンを追加する

プログラムで作成したUINavigationController(ウィザードページのように使用する)があり、[キャンセル]ボタンを表示してUIViewControllerのプロセスをキャンセルする必要があります。

UINavigationControllerの作成:

FirstVC *firstVC = [[[FirstVC alloc] initWithNibName:@"FirstPage" bundle:nil] autorelease];
firstVC.delegate = self;

navigationController = [[UINavigationController alloc] initWithRootViewController:firstVC];
[self.view addSubview:navigationController.view];

キャンセルボタンの追加:

UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelRequestNewLeave:)];
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
[cancelButton release];

しかし、2番目のページをUINavigationControllerにプッシュすると、キャンセルボタンがUINavigationBarに表示されません。最初のページに戻ると、キャンセルボタンがあります。つまり、ボタンは最初のビューにのみ追加されます。これは、サブビューで使用する必要があるため、UINavigationControllerをサブクラス化していないためだと思います。しかし、プログラムで作成されたrightBarButtonItemUINavigationControllerを設定する方法がわかりません。

navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;

誰かがこれに光を当てることができますか?

前もって感謝します。

30
Ozay

ナビゲーション項目はビューコントローラごとです。ナビゲーションバーは、現在フレーミングしているビューのビューコントローラーのナビゲーションアイテムからコンテンツを描画します。これは、ナビゲーションコントローラーのスタックの最上部にあるビューコントローラーに対応します。

基本的に、ナビゲーション項目にキャンセルボタンを貼り付けるには、各ビューコントローラーが必要です。次のいずれかを実行できます。

  • コードを関連するすべてのView Controllerにコピーして貼り付けます。
  • コードをユーティリティ関数またはクラスに移動し、それを呼び出します。
  • サブクラスのキャンセルボタンの設定を処理するすべての関連するビューコントローラーに共通のスーパークラスを作成します。
42

UINavigationcontrollerをサブクラス化して、次のようないくつかのメソッドをオーバーライドすることもできます。

- (id)initWithRootViewController:(UIViewController *)rootViewController {
    self = [super initWithRootViewController:rootViewController];
    if (self) {
        [self setCloseButtonToController:rootViewController];
    }
    return self;
}

- (void)dismissController {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)setCloseButtonToController:(UIViewController *)viewController {
    UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(dismissController)];
    [viewController.navigationItem setRightBarButtonItem:closeItem];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [super pushViewController:viewController animated:animated];

    [self setCloseButtonToController:viewController];

}
22
Rafał Wójcik

代わりに、UINavigationControllerDelegateインスタンスを作成するクラスでUINavigationControllerプロトコルを採用できます。事前にcancelButtonを作成してから、次のようにnavigationController:willShowViewController:animated:を実装することもできます。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    viewController.navigationItem.rightBarButtonItem = cancelButton;
}

cancelButtonを作成して保持し、解放しないでください。これは、cancelRequestNewLeave:UINavigationControllerインスタンスを作成するクラスのメソッドである必要があることも意味します。

8
  1. commonViewControllerを作成する
  2. firstViewControllerを作成(CommonViewControllerから拡張
  3. secondeViewControllerを作成(CommonViewControllerから拡張
  4. commonViewControllerに関数common functionsを追加します

そのように

CommonViewController.h

@interface CommonViewController : UIViewController

-(void) initializeCartBarButton;

@end

CommonViewController.m

#import "CommonViewController.h"

@interface CommonViewController ()

@end

@implementation CommonViewController

-(void) initializeCartBarButton {


    UIBarButtonItem *cartBarButton = [[UIBarButtonItem alloc] init];
    cartBarButton.title = @"cart";
    [cartBarButton setTarget: self];
    [cartBarButton setAction: @selector(goToCart:)];

    self.navigationItem.rightBarButtonItem = cartBarButton;
    }

- (IBAction) goToCart:(id)sender {
    NSLog(@"");
  }

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
  }

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
  }

@end

FirstViewController.h

#import <UIKit/UIKit.h>
#import "CommonViewController.h"

@interface FirstViewController : CommonViewController

@end

FirstViewController.m

#import "FirstViewController.h"

@interface FirstViewController ()

@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self initializeCartBarButton];
}
@end

SecondViewController.h

#import <UIKit/UIKit.h>
#import "CommonViewController.h"

@interface SecondViewController : CommonViewController

@end

SecondViewController.m

#import "SecondViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self initializeCartBarButton];
}
@end

注:initializeCartBarButtonのコードをCommonViewControllerのviewDidLoadに追加して、この機能をCommonViewControllerおよび子クラスから削除できます

5
Mohamad Chami

これは、プッシュされたすべてのviewControllerを閉じることができるUINavigationControllerサブクラスを使用して行った方法です。

class CustomNavigationController: UINavigationController, UINavigationControllerDelegate{

    //TODO: Use when we have more right bar button types.
    var rightBarButtonType: RightBarButtonType = .Close

    enum RightBarButtonType{
        case Close
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }

    // MARK: Private Functions
    private func addRightBarButtonTo(viewController: UIViewController){

        let barButtonItem: UIBarButtonItem!
        switch self.rightBarButtonType {
        case .Close:
            barButtonItem = UIBarButtonItem(image: UIImage(named: "ic_close_white"), style: .Done, target: self, action: #selector(CustomNavigationController.dismiss(_:)))

        }
        viewController.navigationItem.rightBarButtonItem = barButtonItem
    }

    // MARK: UINavigationController Delegate
    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        self.addRightBarButtonTo(viewController)
    }

    @objc func dismiss(sender: AnyObject){
        self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
    }
}
3
MadNik

すべてのビューコントローラにボタンを追加する必要があります。一度設定するか、(賢明な方法で)View Controller間で共有することはできません。ボタンを追加する適切な場所は、ビューコントローラのviewDidLoadメソッドです。これが繰り返し発生すると思われる場合は、基本的なUIViewConteollerサブクラスを1つ作成できます。

1
Johan Kool

このコードをルートビューのviewDidLoadメソッドに追加し、ルートビューコントローラーにcancelMethodを実装します。これはすべてのビューコントローラーで使用できます。ボタンフレームを変更することでボタンの位置を調整できます。方向を変更するには、ボタンの位置を手動で調整します。

 UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [btnCancel addTarget:self
                        action:@selector(cancelMethod)
              forControlEvents:UIControlEventTouchDown];
        [btnCancel setBackgroundImage:[UIImage imageNamed:@"image"]  
        forState:UIControlStateNormal];
        btnCancel.frame = CGRectMake(280, 27, 45, 25);

    [self.navigationController.view addSubview: btnCancel];
0
Roshan

UIBarButtonItemを使用する代わりに、カスタム 'キャンセル' UIButtonをNavigationBarのビューに直接追加できます。

UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.imageView = // Some custom image
cancelButton.frame = CGRectMake(...);  // Something far to the right.
[self.navigationController.navigationBar addSubview: cancelButton];

これを行う通常の方法は、そのキャンセルボタンをナビゲーションスタック内のすべての単一のビューコントローラーのnavigationItemに追加することです。上記のアプローチは、より少ないコードを書くことを可能にすることでそれをより単純にすることができますが、それはほんの少しのハックです。

0
hundreth