用UIButton作为CustomView的UIBarButtonItem – 从UIButton,如何访问UIBarButtonItem它的in?
我有一个UIBarButtonItem
与UIButton
作为自定义视图。
UIButton
有一个addTarget:action:
就可以了。 在行动中,我提出了一个popover。 我目前从sender.frame
( UIButton
的框架),我想从UIBarButtonItem
代替。
我如何从UIButton
访问UIBarButtonItem
?
如果您将UIButton
设置为customView
的自定义视图或自定义视图的子视图,则可以从button向上UIBarButtonItem
视图层次结构,直到find包含该button的UIToolbar
或UINavigationBar
,然后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可能如下:
- 子类
UIButton
- 在其中创build一个
UIBarButtonItem
types的属性(一个弱的避免保留周期) - 创build它时,注入
UIButton
的酒吧button项目。
也许它可以工作,但我会更喜欢第一个。
不知道你需要UIButton。 如果你正在做的是调度一个动作,或者甚至定制一个图像的button, UIBarButtonItem
应该足够了。
如果你想要从UIButton
中获取框架来实现演示,我想你可能会更好地服务于简单地估计UIBarButtonItem
的位置。 这应该不是太难,特别是如果它是UINavigationItem
的leftBarButtonItem
或rightBarButtonItem
的一个或另一个。
我一般为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];