用UIButton作为CustomView的UIBarButtonItem – 从UIButton,如何访问UIBarButtonItem它的in?

我有一个UIBarButtonItemUIButton作为自定义视图。

UIButton有一个addTarget:action:就可以了。 在行动中,我提出了一个popover。 我目前从sender.frameUIButton的框架),我想从UIBarButtonItem代替。

我如何从UIButton访问UIBarButtonItem

如果您将UIButton设置为customView的自定义视图或自定义视图的子视图,则可以从button向上UIBarButtonItem视图层次结构,直到find包含该button的UIToolbarUINavigationBar ,然后search该栏的项目自定义视图是button(或button的祖先)的那个。

这是我完全未经testing的代码。 你可以调用[[self class] barButtonItemForView:myButton]来获取包含button的项目。

 + (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; } 

首先,你为什么需要访问UIBarButtonItem

然后,要创build一个具有自定义视图的UIBarButtonItem ,我build议您创build一个类似于以下的类别扩展(在这种情况下,自定义视图是一个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:)]; 

select器是在类(目标)内部使用该button项目实现的方法。

现在在doSomething:select器中你可以如下:

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

在这种情况下,类别不重复代码很有用。 希望能帮助到你。

PS我不使用ARC,但同样的考虑也可以应用。

编辑:

访问栏button项目的简单解决scheme可能如下:

  1. 子类UIButton
  2. 在其中创build一个UIBarButtonItemtypes的属性(一个弱的避免保留周期)
  3. 创build它时,注入UIButton的酒吧button项目。

也许它可以工作,但我会更喜欢第一个。

不知道你需要UIButton。 如果你正在做的是调度一个动作,或者甚至定制一个图像的button, UIBarButtonItem应该足够了。

如果你想要从UIButton中获取框架来实现演示,我想你可能会更好地服务于简单地估计UIBarButtonItem的位置。 这应该不是太难,特别是如果它是UINavigationItemleftBarButtonItemrightBarButtonItem的一个或另一个。

我一般为KISS(Keep It Simple,Stupid!)经验法则。 即使苹果也这样做……当你从Springboard启动一个应用程序时,应用程序总是从屏幕的中心扩展,而不是从应用程序的图标扩展。

只是一个build议。

编辑

好的,我只是读了UIPopoverController引用 (我从来没有使用过)。 我想你想要什么presentPopoverFromBarButtonItem:permittedArrowDirections:animated:并传入你的BBI作为第一个参数。 方法存在的原因是为了解决你的问题 – BBI没有框架,因为它们不是NSView的子类。 苹果知道你想要做这种事情,并提供这种方法。 另外,我认为如果你使用这种方法,那么你的自动转换也会起作用。 我可能是错的这个,给它一个镜头。

至于你的自定义布局,我认为如果你复制它在一个UIView和BBI的习惯,你会做得更好。 这当然取决于你。

无论哪种方式,您都可以通过将其作为IBOutlet与您的NIB连接来获取对BBI的引用,或者通过在代码中创build它时保存对其的引用。 然后,只需将该引用传递给上述的popover方法即可。 我认为这可能适合你。

MOAR

BBI只是你的class级的成员 – 一个有很强参考性质的iVar,或许作为一个IBOutlet连接到你的NIB。 然后,您可以从课堂上想要的任何方法访问它。

例如:(不知道我有popover控制器内存pipe理权限)

 @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 

假设您已经将UIButton aButton添加到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 info_button使popup工程:

 - (IBAction)showInfo:(id)sender { [self.flipsidePopoverController presentPopoverFromBarButtonItem:info_Button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } 
 // 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];