问题 在iOS6中使用QLPreviewController自定义navigationItem按钮


我的目标是在iOS6的iPad应用程序中使用QLPreviewController,使用顶部工具栏中的自定义操作项按钮。 我有解决方案,直到iOS5.1。我使用了一个扩展QLPreviewController的类,在组件生命周期中我做了类似的事情

[[self navigationItem] setRightBarButtonItems:[NSArray arrayWithObject:[self buildCustomButton]]];

使用iOS6这个技巧不起作用,现在似乎不可能改变navigationItem配置。我认为可能涉及UIActivity和社交框架的介绍,也许在navigationItem上工作并不是更有效,但我可以找到任何解决方案。 有什么建议吗? 谢谢再见


10450
2017-09-24 15:48


起源

类似的问题: stackoverflow.com/questions/12568508/... - Mark
我也有同样的问题。试图解决...... - wzbozon
得到了同样的问题。似乎无法替换或删除标准共享按钮。 - Aron
是的,我曾经能够做到这一点,因为我将QLpreviewController包装在NavigationController中,但现在当我这样做时,文档将不会显示。去图= / - valheru


答案:


我真的需要一个解决方案,所以我做了这个。

是的,这很难看。是的,它可能随时都会破裂。是的,我会陷入困境,但我的老板却生气地闭着眼睛盯着我......现在。

@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

史蒂夫乔布斯将在我的梦中追捕我,直到找到合适的解决方案......


6
2017-10-04 13:54



顺便说一句:我使用的是UIDocumentInteractionController,而不是直接使用QLPreviewController。 - tougher
如果要删除操作按钮,请进行更改 qlpc.navigationItem.rightBarButtonItem 至 零。 - tougher
您不需要道歉只因为Apple没有提供适当的自定义API ... - HyBRiD
大!我发现它很长一段时间了。谢谢! - smart_cai
如何使用您的代码添加新的UIBarButtonItem? - Nam Vu


如果您要更改顶部工具栏中的操作项按钮,则必须在内部执行此操作

-(void)viewDidAppear:(BOOL)animated{
    //add code necessarry to change your action buttons of toptoolbar in quicklook
}

视图出现后 rightBarButtonItems 可以访问。


2
2017-10-10 12:33



加载pdf完成后会出现rightBarButton。所以有时它会失败。 - Steven Jiang


好吧,我有好消息和坏消息。

好消息是我已经弄明白为什么这不起作用。在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%的时间内都不起作用。


2
2017-10-04 02:04



在UIDocumentInteractionController中,QLPreviewController只有 QLPreviewViewController.view->的UIView,所以必须继续使用我的hacky类别解决方案: - / - tougher
是的,我无法在任何子视图中找到任何UINavigationBars。我甚至试过去super.view.subviews(因为我是子类QLPreviewController) - valheru


最好的方法是实现自己的控制器并使用QLPreviewController视图作为子视图。在这种情况下,您可以使用自定义项目创建自己的导航栏。


1
2017-07-16 11:45





我试了很久才更换这个按钮。查看子视图等。看起来此操作/共享按钮作为图层放到导航中。酒吧。我最后通过在QLPreviewController子类中添加一个按钮而不是title来为自己解决这个问题。

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

0
2017-09-27 16:25



我发现一个解决方法是将QLPreviewController作为全屏子视图添加到我的UIViewController,以及UINavigationBar,我可以根据需要进行设置。当用户点击QLPreviewController时,仍然要了解,以隐藏和显示导航栏。我尝试使用stardard uiviewcontroller方法(touchesBegan,touchesMove,touchesMove)以及手势管理器,但是当用户点击该组件时似乎很难拦截。 - bovello