Пользовательская кнопка 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;
}