在Objective C中跨类共享方法的最佳方法是什么?

时间:2013-03-30 18:33:23

标签: ios objective-c

我有几个视图控制器和表视图控制器,我从我的根视图控制器推送。在所有这些中,我想在导航控制器中使用自定义后退按钮。我没有复制方法来将我的后退按钮设置到每个类文件中,而是创建了一个带有类方法的辅助类来完成设置。下面的代码有效,但我想知道我是否会以错误的方式解决这个问题。有没有更好的方法来实现这一目标?另外,我仍然在我的所有类中复制 - (void)myCustomBack方法,并且想知道是否有办法避免这种情况。

@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

5 个答案:

答案 0 :(得分:4)

我认为你的问题的解决方案是继承。

您可以创建UIViewController的子类,并使所有自定义视图控制器都继承自此自定义子类。 “父”子类将具有-(void)myCustomBack以及设置代码,您将不再需要重复它。

答案 1 :(得分: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

答案 2 :(得分:2)

设置方法并不需要在一个单独的类中;我说你应该把它变成一个功能。

myCustomBack方法,只要它在所有子类中完全相同,就可以很容易地放在UIViewController上的类别中:

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

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

(使用初始主义作为前缀,由您的名字或公司或项目的名称组成。即使它很难看,您也需要避免任何碰撞的可能性。类别碰撞破坏方法和意志产生粗糙的虫子。)

只要您执行此操作,您也可以将帮助方法放入类别中。将其转换为实例方法,只需使用self而不是传入的控制器。

然后所有子类都将继承这些方法,您可以像在那里定义它们一样使用它们。如果任何类需要以某种方式专门化,你可以覆盖。

答案 3 :(得分:1)

有一个更好的方法:使用UIAppearance协议。您可以设置所有这些属性,并让自定义视图类型或任何导航栏中包含的每个后退按钮都继承该外观。

Here's a screencast that will help you。一些代码来自那里:

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

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

请注意,CustomNavigationBar类只能是UINavigationBar,这会导致所有后退按钮都显示出来。

你可能无法做到的一件事是“后退”标题。那必须在你的所有视图控制器中。

答案 4 :(得分:0)

在大多数语言中,最简单的解决方案是使用静态(类)方法生成多个Utils类。

在Obj-C中,常见的方法是使用类别。

在您的示例中,在UIBarButtonItem上创建一个类别,例如使用方法UIBarButtonItem (CustomizedButtons)的{​​{1}}会好得多。

然而,有一种更简单的方法。 您可以在一个地方修改所有后退按钮的外观,让我们看一个示例

+(UIBarButton*)customBackButton

请注意,您不必使用自定义视图,也不必使用特殊的后退按钮选择器。