UIBarButtonItem с UIButton в качестве CustomView - из UIButton, как получить доступ к UIBarButtonItem его в? - PullRequest
7 голосов
/ 01 марта 2012

У меня есть UIBarButtonItem с UIButton в качестве пользовательского представления.

На UIButton есть addTarget:action:.В действии я представляю поповер.В настоящее время я представляю sender.frame (кадр UIButton), который я хочу вместо UIBarButtonItem представить.

Как получить доступ к UIBarButtonItem из UIButton?

Ответы [ 5 ]

10 голосов
/ 06 марта 2012

Если вы установили UIButton в качестве customView для UIBarButtonItem или дочернего элемента пользовательского представления, то вы можете переходить вверх по иерархии представлений с помощью своей кнопки, пока не найдете UIToolbar или UINavigationBar, который содержит кнопку, затем ищите элементы панели для того, пользовательский вид которого является кнопкой (или предком кнопки).

Вот мой полностью непроверенный код для этого. Вы бы позвонили [[self class] barButtonItemForView:myButton], чтобы получить предмет, содержащий вашу кнопку.

+ (BOOL)ifBarButtonItem:(UIBarButtonItem *)item containsView:(UIView *)view storeItem:(UIBarButtonItem **)outItem {
    UIView *customView = item.customView;
    if (customView && [view isDescendantOfView:customView]) {
        *outItem = item;
        return YES;
    } else {
        return NO;
    }
}

+ (BOOL)searchBarButtonItems:(NSArray *)items forView:(UIView *)view storeItem:(UIBarButtonItem **)outItem {
    for (UIBarButtonItem *item in items) {
        if ([self ifBarButtonItem:item containsView:view storeItem:outItem])
            return YES;
    }
    return NO;
}

+ (UIBarButtonItem *)barButtonItemForView:(UIView *)view {
    id bar = view;
    while (bar && !([bar isKindOfClass:[UIToolbar class]] || [bar isKindOfClass:[UINavigationBar class]])) {
        bar = [bar superview];
    }
    if (!bar)
        return nil;

    UIBarButtonItem *item = nil;

    if ([bar isKindOfClass:[UIToolbar class]]) {
        [self searchBarButtonItems:[bar items] forView:view storeItem:&item];
    }

    else {
        UINavigationItem *navItem = [bar topItem];
        if (!navItem)
            return nil;
        [self ifBarButtonItem:navItem.backBarButtonItem containsView:view storeItem:&item]
        || [self ifBarButtonItem:navItem.leftBarButtonItem containsView:view storeItem:&item]
        || [self ifBarButtonItem:navItem.rightBarButtonItem containsView:view storeItem:&item]
        || ([navItem respondsToSelector:@selector(leftBarButtonItems)]
            && [self searchBarButtonItems:[(id)navItem leftBarButtonItems] forView:view storeItem:&item])
        || ([navItem respondsToSelector:@selector(rightBarButtonItems)]
            && [self searchBarButtonItems:[(id)navItem rightBarButtonItems] forView:view storeItem:&item]);
    }

    return item;
}
6 голосов
/ 01 марта 2012

Прежде всего, зачем вам нужен доступ к UIBarButtonItem?

Затем, чтобы создать UIBarButtonItem с настраиваемым представлением, я предлагаю вам создать расширение категории, как показано ниже (в этом случае настраиваемое представление - UIButton).

//UIBarButtonItem+Extension.h    
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image title:(NSString*)title target:(id)target action:(SEL)action;

//UIBarButtonItem+Extension.m    
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image title:(NSString*)title target:(id)target action:(SEL)action
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
    button.titleLabel.textAlignment = UITextAlignmentCenter;

    [button setBackgroundImage:image forState:UIControlStateNormal];
    [button setTitle:title forState:UIControlStateNormal];
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];

    return [barButtonItem autorelease];    
}

и использовать его вот так (первый импорт UIBarButtonItem+Extension.h):

UIBarButtonItem* backBarButtonItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@"YoutImageName"] title:@"YourTitle" target:self action:@selector(doSomething:)];

где селектор - это метод, который реализован внутри класса (цели), использующего этот элемент кнопки панели.

Теперь внутри селектора doSomething: вы можете сделать следующее:

- (void)doSomething:(id)sender

    UIButton* senderButton = (UIButton*)sender;    
    [popover presentPopoverFromRect:senderButton.bounds inView:senderButton...];
}

Категория, в этом случае полезно не дублировать код. Надеюсь, это поможет.

P.S. Я не использую ARC, но можно применять те же соображения.

Изменить:

Простым решением для доступа к элементу панели кнопок может быть следующее:

  1. Подкласс UIButton
  2. Создайте в нем свойство типа UIBarButtonItem (слабое, чтобы избежать повторного цикла)
  3. Вставить элемент кнопки панели в UIButton при его создании.

Возможно, это может сработать, но я предпочту первый.

0 голосов
/ 11 июня 2013
// get the UIBarButtonItem from the UIButton that is passed in sender
UIToolbar *toolbar = (id)[sender superview];
UIBarButtonItem *ourButtonItem = [toolbar items][2];//pick the right index
[parkingPopOver_ presentPopoverFromBarButtonItem:ourButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
0 голосов
/ 09 ноября 2012

Допустим, вы добавили кнопку UIButton в UIBarButtonItem info_Button следующим образом:

//Add a button on top of the UIBarButtonItem info_button
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[aButton addTarget:self action:@selector(showInfo:) forControlEvents:UIControlEventTouchUpInside];
info_Button.customView = aButton;

Теперь, в showInfo, presentPopoverFromBarButtonItem: info_Button (вместо presentPopoverFromBarButtonItem: sender) это будет передавать информационную кнопку UIBarButtonItem для создания всплывающих окон:

- (IBAction)showInfo:(id)sender
{   
    [self.flipsidePopoverController presentPopoverFromBarButtonItem:info_Button   permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

}
0 голосов
/ 01 марта 2012

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

Если вам нужно взять кадр из UIButton вДля того, чтобы добиться презентации, я думаю, вам лучше всего просто оценить позицию UIBarButtonItem.Это не должно быть слишком сложно, особенно если это один или другой из ваших UINavigationItem * leftBarButtonItem или rightBarButtonItem.

Я обычно за ПОЦЕЛУЙ (Keep It Simple, Stupid!) практическое правило.Даже Apple делает это ... когда вы запускаете приложение из Springboard, оно всегда расширяется от центра экрана, а не от значка приложения.

Просто предложение.

РЕДАКТИРОВАТЬ

ОК, я только что прочитал справку UIPopoverController (я никогда не использовал ее).Я думаю, что вы хотите presentPopoverFromBarButtonItem:permittedArrowDirections:animated: и передать ваш BBI в качестве первого параметра.Причина, по которой метод существует, состоит в том, чтобы решить вашу проблему - у BBI нет фрейма, потому что они не являются подклассами NSView.Apple знает, что вы хотите делать такие вещи, и предоставляет этот метод.Кроме того, я думаю, что если вы используете этот метод, то ваше автоповорот тоже будет работать.Я могу ошибаться по этому поводу, попробуйте.

Что касается вашего настроенного макета, я думаю, что если вы скопируете его в UIView и сделаете BBI-настройку с этим, у вас все получится.Это, конечно, зависит от вас.

В любом случае, вы получаете ссылку на BBI, либо подключая его как IBOutlet к вашему NIB, либо сохраняя ссылку на него при создании в коде.Затем просто передайте эту ссылку методу popover, который я описал выше.Я думаю, что это может сработать для вас.

MOAR

BBI - это просто член вашего класса - iVar с сильным эталонным свойством, возможно, связанный как IBOutlet с вашим NIB.,Затем вы можете получить к нему доступ из любого метода, который вам нужен в классе.

Пример: (не уверен, что у меня есть право на управление памятью контроллера popover)

@interface MyViewController : UIViewController {
   UIBarButtonItem *item;
}

@property (nonatomic, retain) UIBarButtonItem *item;

@end



@implementation MyViewController

@synthesize item;

-(void)viewDidLoad {
   // assuming item isn't in your NIB
   item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlus target:self action:@selector(doit)];
   self.navigationItem.rightBarButtonItem = item;
}

-(void)doit {
   UIPopoverController *popover = [[[UIPopoverController alloc] initWithContentViewController:yourViewController] autorelease];
   [popover presentPopoverFromBarButtonItem:self.item permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
   // or in the line above, replace self.item with self.navigationItem.rightBarButtonItem
}

@end
...