Ios 向UINavigationBar的子类添加按钮

Ios 向UINavigationBar的子类添加按钮,ios,objective-c,uinavigationcontroller,uinavigationbar,subclassing,Ios,Objective C,Uinavigationcontroller,Uinavigationbar,Subclassing,我正在子类化UINavigationBar。在我的导航栏中,我想添加一个后退按钮。最终,我希望有一个标题,自定义按钮和uicollectionview如下所示: 在我的UINavigationBar AppDelegate: NFVDContentTableViewController *contentTVC = [[NFVDContentTableViewController alloc] initWithNibName:nil bundle:nil]; UINavigationCont

我正在子类化
UINavigationBar
。在我的导航栏中,我想添加一个后退按钮。最终,我希望有一个标题,自定义按钮和uicollectionview如下所示:

在我的
UINavigationBar

AppDelegate:

 NFVDContentTableViewController *contentTVC = [[NFVDContentTableViewController alloc] initWithNibName:nil bundle:nil];
 UINavigationController *contentNavCtr = [[UINavigationController alloc] initWithNavigationBarClass:[NFVDContentNavigationBar class] toolbarClass:[UIToolbar class]];
 contentNavCtr.viewControllers = @[contentTVC];
在我的子类UINavigation头文件中:

@interface NFVDContentNavigationBar : UINavigationBar <UINavigationBarDelegate>

@end

这很难做到,因为UIViewController自带了自己的UINavigationItems,请参阅UIViewController头文件中的文档:

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIViewController : UIResponder <NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer> {
    @package
    UIView           *_view;
    UITabBarItem     *_tabBarItem;
    UINavigationItem *_navigationItem;
- (void)viewDidLoad
{
    [super viewDidLoad];
    UIBarButtonItem * tester = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"reveal-icon"] style:UIBarButtonItemStylePlain target:self action:@selector(menuItemPressed:)];
    [[self navigationItem] setRightBarButtonItem:tester];
}
您仍然可以对UINavigationBar进行子类化,但不要将其作为子类来尝试覆盖已经连接到UIKit默认的UIViewController的BarButtonims,如果您想对此有兴趣,那么下面是如何对UIViewController进行子类化的开始,代码很多:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self == nil)
        return nil;

    if (self) {
        _showsNotifications = false;
        _showsAddFriends = false;
    }
    _notificationsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage resizeImage:[UIImage imageNamed:@"YOUR IMAGE NAME"] height:27] style:UIBarButtonItemStylePlain target:nil action:nil];
    _addFriendsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"YOUR IMAGE NAME"] style:UIBarButtonItemStylePlain target:self action:@selector(addFriendsPressed)];
}
您可以看到,将更改UIViewController中UINavigationItems内部的属性添加到自定义视图控制器Bool中。然后,使用此方法需要在作为此自定义viewcontroller子类的viewcontroller的INIT中调用并设置这些bool值,请执行以下操作:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        [self setShowsAddFriends:false];
        [self setShowsNotifications:false];
    }
    return self;
}
然后在子类UIViewController中,使bool开关能够实际切换

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (_showsNotifications) {
        [[self navigationItem] setRightBarButtonItem:_notificationsBarButtonItem];
    }
    if (_showsAddFriends) {
        [[self navigationItem] setRightBarButtonItem:_addFriendsBarButtonItem];
    }
}
做了又做,复杂?有点像,但这就是你如何用你想要的任意多的自定义导航项按钮来模板项目,完整的代码大约是1k行代码,但这是它的核心,子类UIViewController,在header中设置bool属性,在子类中设置这些bool属性,以便使用此子类作为父类的UIViewController可以在“init”中调用这些bool setter属性,然后您将能够切换并选择您喜欢的导航项。此外,要确保视图控制器维护设置给它们的项目,请确保在视图中声明这些项目设置将显示在将UIViewController的自定义子类用作父视图的视图控制器中。祝你好运,并有一个好的一天

事实上,我只是给你看代码,为什么?因为我对下周发布的两个应用程序感到厌烦,而且有太多的事情要做。因此,以下是您需要查看的文件,请记住这些文件非常简单:

CCUSTViewController.m

//******CCUSTViewController.m****
//this is the implementation file for the subclass of UIViewController

#import "CCUSTViewController.h"
#import "CCUSTFriendsViewController.h"
#import "CCUSTActivitiesViewController.h"

@interface CCUSTViewController ()
@end

@implementation CCUSTViewController
{
    UIBarButtonItem * _notificationsBarButtonItem;
    UIBarButtonItem * _addFriendsBarButtonItem;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self == nil)
        return nil;
    if (self) {
        _showsNotifications = false;
        _showsAddFriends = false;
    }
    _notificationsBarButtonItem = [[UIBarButtonItem alloc] initWithImage::[UIImage imageNamed:@"your imate"] style:UIBarButtonItemStylePlain target:self action:@selector(showNotificationsPressed)];
    _addFriendsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"your imate"] style:UIBarButtonItemStylePlain target:self action:@selector(addFriendsPressed)];
    return self;
}
- (void)showNotificationsPressed
{
    CCUSTActivitiesViewController * tobePushed = [CCUSTActivitiesViewController new];
    [self navigationController] pushViewController:tobePushed animated:true];
}

- (void)addFriendsPressed
{
    CCUSTFriendsViewController * tobePushed = [CCUSTFriendsViewController new];
    [self navigationController] pushViewController:tobePushed animated:true];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    if (_showsNotifications) {
        [[self navigationItem] setRightBarButtonItem:_notificationsBarButtonItem];
    }
    if (_showsAddFriends) {
        [[self navigationItem] setRightBarButtonItem:_addFriendsBarButtonItem];
    }
}

@end
// CCCUSTHomeViewController.m
#import "CCCUSTHomeViewController.h"
#import "CCCUSTHomeView.h"

@interface CCCUSTHomeViewController () 
@end

@implementation CCCUSTHomeViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        [self setShowsAddFriends:TRUE];
        [self setShowsNotifications:TRUE];
    }
    return self;
}

-(void)loadView 
{
    [self setView:[CCCUSTHomeView new]];
}

-(CCCUSTHomeView*)contentView 
{
    return (id)[self view];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setTitle:@"HOME"];
}

-(void)viewWillAppear:(BOOL)animated 
{
    [super viewWillAppear:animated];
    [self setShowsAddFriends:TRUE];
    [self setShowsNotifications:TRUE];
}
@end
CCUSTViewController.h

#import <UIKit/UIKit.h>

@interface CCUSTViewController : UIViewController

@property (nonatomic) BOOL showsNotifications;
@property (nonatomic) BOOL showsAddFriends;

@end
#import "CCUSTViewController.h"

@interface CCCUSTHomeViewController : CCUSTViewController
@end
CCCUSTHomeViewController.m

//******CCUSTViewController.m****
//this is the implementation file for the subclass of UIViewController

#import "CCUSTViewController.h"
#import "CCUSTFriendsViewController.h"
#import "CCUSTActivitiesViewController.h"

@interface CCUSTViewController ()
@end

@implementation CCUSTViewController
{
    UIBarButtonItem * _notificationsBarButtonItem;
    UIBarButtonItem * _addFriendsBarButtonItem;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self == nil)
        return nil;
    if (self) {
        _showsNotifications = false;
        _showsAddFriends = false;
    }
    _notificationsBarButtonItem = [[UIBarButtonItem alloc] initWithImage::[UIImage imageNamed:@"your imate"] style:UIBarButtonItemStylePlain target:self action:@selector(showNotificationsPressed)];
    _addFriendsBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"your imate"] style:UIBarButtonItemStylePlain target:self action:@selector(addFriendsPressed)];
    return self;
}
- (void)showNotificationsPressed
{
    CCUSTActivitiesViewController * tobePushed = [CCUSTActivitiesViewController new];
    [self navigationController] pushViewController:tobePushed animated:true];
}

- (void)addFriendsPressed
{
    CCUSTFriendsViewController * tobePushed = [CCUSTFriendsViewController new];
    [self navigationController] pushViewController:tobePushed animated:true];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    if (_showsNotifications) {
        [[self navigationItem] setRightBarButtonItem:_notificationsBarButtonItem];
    }
    if (_showsAddFriends) {
        [[self navigationItem] setRightBarButtonItem:_addFriendsBarButtonItem];
    }
}

@end
// CCCUSTHomeViewController.m
#import "CCCUSTHomeViewController.h"
#import "CCCUSTHomeView.h"

@interface CCCUSTHomeViewController () 
@end

@implementation CCCUSTHomeViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        [self setShowsAddFriends:TRUE];
        [self setShowsNotifications:TRUE];
    }
    return self;
}

-(void)loadView 
{
    [self setView:[CCCUSTHomeView new]];
}

-(CCCUSTHomeView*)contentView 
{
    return (id)[self view];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setTitle:@"HOME"];
}

-(void)viewWillAppear:(BOOL)animated 
{
    [super viewWillAppear:animated];
    [self setShowsAddFriends:TRUE];
    [self setShowsNotifications:TRUE];
}
@end
哦,是的,您需要将相同的代码从init添加到ViewWillDisplay,因为当您在堆栈上弹出推送的视图控制器时,您甚至需要在CCCUSTHomeViewController中拦截该代码,以便UINavigationItems在堆栈顶部的viewcontroller中重新出现。您还可以使用相同的方法对UICollectionViewController和UITableViewController中的所有内容进行子类化,这意味着使用此结构作为模板,您可以在Xcode中拥有一个空项目,并将所有这些子类添加到该项目中,然后您将对所有视图控制器拥有更多的控制权。实现这种方法,你可以做的还有很多,但有些事情,我必须保密,但我只想说,很多大型应用程序都使用同样的技术和你在野外看不到的其他高级技术。最妙的是你不需要授权,也不需要操纵任何事情。祝你好运,祝你有一个美好的一天

因为我在乎:


我真的觉得有必要感谢你的回答。细节是非同寻常的。如果我可以问一下,你是从哪里学到这种高级技术的?我能说的是,这种方法是出于某种原因被保密的。我对所有内容都进行了子类化,这是我自己的封装方法,它避免了几乎所有的委托和所有的B。如果您考虑如何将这种类型的东西应用于您制作的所有应用程序和创建的所有视图,那么开发只需要很少代码的高级代码将变得简单。一些库试图复制这10多行代码,而同样的事情是通过使用苹果提供给我们的东西来完成的:子类化的方式不会在UIKit上乱来,而是利用它。