Каков наилучший способ совместного использования методов в классах Objective C? - программирование
Подтвердить что ты не робот

Каков наилучший способ совместного использования методов в классах Objective C?

У меня есть несколько контроллеров представлений и контроллеров табличных представлений, которые я выталкиваю из моего контроллера корневого представления. Во всех этих случаях я бы хотел использовать пользовательскую кнопку возврата в навигационном контроллере. Вместо того, чтобы копировать метод для настройки моей кнопки возврата в каждый класс, файл, я создал вспомогательный класс с методом класса, который выполняет настройку. Ниже приведен код, но мне интересно, не ошибаюсь ли я в этом. Есть ли лучший способ достичь этого? Кроме того, я все еще дублирую метод myCustomBack (void) во всех своих классах и задаюсь вопросом, есть ли способ избежать этого.

@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
4b9b3361

Ответ 1

Благодарим вас за ваши ответы и указывая на меня в правильном направлении. Я закончил создание категории 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

Я думаю, что решение вашей проблемы было бы наследованием.

Вы можете создать подкласс UIViewController и наследовать все пользовательские контроллеры представлений из этого пользовательского подкласса. В "родительском" подклассе есть -(void)myCustomBack, а также код установки, и вам больше не нужно будет его повторять.

Ответ 3

Метод установки не обязательно должен находиться в отдельном классе; Я бы сказал, что вы должны сделать эту функцию.

Метод myCustomBack, если он точно такой же во всех ваших подклассах, можно легко поместить в категорию на UIViewController:

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

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

(Используйте инициализм для префикса, сделанный либо из вашего имени, либо из названия компании или проекта. Несмотря на то, что это некрасиво, вам нужно избегать любой возможности столкновения. Коллизии групп clobber методы и вызовут громоздкие ошибки. )

Пока вы это делаете, вы также можете включить вспомогательный метод в категорию. Поверните его в метод экземпляра и просто используйте self вместо переданного контроллера.

Затем все ваши подклассы наследуют методы, и вы можете использовать их так, как если бы вы их определили. Если какой-либо из классов действительно нужно каким-то образом специализироваться, вы можете переопределить.

Ответ 4

Здесь гораздо лучший способ: используйте протокол UIAppearance. Вы можете настроить все эти свойства и иметь каждую кнопку возврата, которая содержится в пользовательском виде или в любой панели навигации, наследует внешний вид.

Вот скринкаст, который поможет вам. Некоторые из кода оттуда:

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, что приведет к тому, что все обратные кнопки получат этот внешний вид.

Единственное, что вы не можете с этим сделать, это "Назад". Это должно быть во всех ваших контроллерах.

Ответ 5

В большинстве языков упрощенное решение состоит в том, чтобы иметь несколько классов Utils со статическими (классными) методами.

В Obj-C общий способ - использование категорий.

В вашем примере создание категории на UIBarButtonItem, например. UIBarButtonItem (CustomizedButtons) с помощью метода +(UIBarButton*)customBackButton будет намного лучше.

Однако есть более простой способ. Вы можете изменить внешний вид всех ваших задних кнопок в одном месте, чтобы увидеть пример

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];

Обратите внимание, что вам не нужно использовать пользовательские представления и специальный селектор кнопок.