Пользовательская кнопка navigationItem с QLPreviewController в iOS6
Моя цель - использовать QLPreviewController в моем приложении iPad для iOS6, используя мою пользовательскую кнопку "Действие" на верхней панели инструментов.
У меня было решение до iOS5.1. Я использовал класс, который расширяет QLPreviewController, и во время жизненного цикла компонента я сделал что-то вроде
[[self navigationItem] setRightBarButtonItems:[NSArray arrayWithObject:[self buildCustomButton]]];
С iOS6 этот трюк не работает больше, и теперь кажется невозможным изменить конфигурацию navigationItem. Я думаю, что может быть задействовано введение UIActivity и Social Framework, и, возможно, это неэффективно работать с navigationItem, но я могу найти любое решение.
Любое предложение?
Спасибо, пока
Ответы
Ответ 1
Мне действительно нужно было решение, поэтому я сделал это.
Да, это уродливо. Да, это может сломаться в любое время. И да, я поеду в ад, но мой босс прекратил смотреть на меня с сердитыми глазами... пока.
@implementation UINavigationItem (Custom)
void MethodSwizzle(Class c, SEL origSEL, SEL overrideSEL);
- (void) override_setRightBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated{
if (item && [item.target isKindOfClass:[QLPreviewController class]] && item.action == @selector(actionButtonTapped:)){
QLPreviewController* qlpc = (QLPreviewController*)item.target;
[self override_setRightBarButtonItem:qlpc.navigationItem.rightBarButtonItem animated: animated];
}else{
[self override_setRightBarButtonItem:item animated: animated];
}
}
+ (void)load {
MethodSwizzle(self, @selector(setRightBarButtonItem:animated:), @selector(override_setRightBarButtonItem:animated:));
}
void MethodSwizzle(Class c, SEL origSEL, SEL overrideSEL) {
Method origMethod = class_getInstanceMethod(c, origSEL);
Method overrideMethod = class_getInstanceMethod(c, overrideSEL);
if (class_addMethod(c, origSEL, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
class_replaceMethod(c, overrideSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
}else{
method_exchangeImplementations(origMethod, overrideMethod);
}
}
@end
Стив Джобс будет охотиться на меня во сне, пока я не найду правильное решение...
Ответ 2
Он работает, если вы изменяете кнопку элемента действия в верхней панели инструментов, вам придется делать это внутри
-(void)viewDidAppear:(BOOL)animated{
//add code necessarry to change your action buttons of toptoolbar in quicklook
}
После просмотра представления rightBarButtonItems
можно получить доступ.
Ответ 3
Ну, у меня хорошие новости и плохие новости.
Хорошей новостью является то, что я понял, почему это не работает. В iOS6 QLPreviewController navigationItem больше не имеет navigationBar:
(lldb) po [[self navigationItem] navigationBar];
(id) $2 = 0x00000000 <nil>
Теперь панель навигации находится внутри иерархии представлений QLPreviewControllersView:
QLPreviewViewController.view- > UIView- > UIView- > QLRemotePreviewContentController- > NAVBAR- > navItem- > rightBarButtonItems.
Вы можете использовать приведенный ниже метод, чтобы найти файл navigationItem, который вы ищете:
- (void)inspectSubviewsForView:(UIView *)view
{
for (UIView *subview in view.subviews)
{
if ([subview isKindOfClass:[UINavigationBar class]])
{
UINavigationBar *bar = (UINavigationBar *)subview;
if ([[bar items] count] > 0)
{
UINavigationItem *navItem = [[bar items] objectAtIndex:0];
[navItem setRightBarButtonItem:nil];
}
}
if ([subview isKindOfClass:[UIView class]] && [[subview subviews] count] > 0)
{
[self inspectSubviewsForView:subview];
}
}
}
Просто передайте [self view] этому методу, и он будет зацикливаться до тех пор, пока не найдет соответствующую панель вкладок. Затем вы можете удалить или добавить свой собственный.
Плохая новость - это, конечно же, доступ к частным API, и использование этого, скорее всего, приведет к тому, что ваше приложение будет отклонено магазином приложений. Это единственный ответ, который я видел на этом. Хотелось бы увидеть, есть ли неличный способ сделать это, но с учетом того, как он настроен, это кажется маловероятным.
Кроме того, этот метод будет работать, только если он вызывается после того, как панель уже находится в позиции. Лучшим местом для вызова этого является "viewDidAppear", но он не работает в 100% случаев.
Ответ 4
Лучший способ - реализовать свой собственный контроллер и использовать представление QLPreviewController как subview. В этом случае вы можете создать собственную панель навигации с настраиваемыми элементами.
Ответ 5
Я долго пытался заменить эту кнопку. Посмотрел на subviews и т.д. Похоже, что эта кнопка action/share помещается как слой на nav. бар. Я решил решить эту проблему самостоятельно, добавив еще одну кнопку вместо заголовка в подкласс QLPreviewController.
- (void)viewDidLoad
{
[super viewDidLoad];
// Button in center of Navigation Bar
UISegmentedControl *button = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:LS(@"Save"), nil]];
button.frame = CGRectMake(0, 0, 100, 30);
button.center = self.view.center;
button.momentary = YES;
button.segmentedControlStyle = UISegmentedControlStyleBar;
button.tintColor = [UIColor colorWithHue:0.6 saturation:0.33 brightness:0.69 alpha:0];
[button addTarget:self action:@selector(saveToDocumentsClicked) forControlEvents:UIControlEventValueChanged];
self.navigationItem.titleView = button;
}