【问题标题】:Custom navigationItem button with QLPreviewController in iOS6iOS6中带有QLPreviewController的自定义navigationItem按钮
【发布时间】:2012-09-24 15:48:39
【问题描述】:

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

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

在 iOS6 中这个技巧不再奏效了,现在改变 navigationItem 配置似乎是不可能的。我认为可能会涉及到 UIActivity 和 Social Framework 的引入,并且在 navigationItem 上工作可能不再有效,但我可以找到任何解决方案。 有什么建议吗? 谢谢,再见

【问题讨论】:

  • 我也有同样的问题。正在尝试解决...
  • 遇到了同样的问题。似乎无法再替换或删除标准分享按钮了。
  • 是的,我以前可以这样做,因为我将 QLpreviewController 包装在 NavigationController 中,但现在当我这样做时,文档将不会显示。走图=/

标签: objective-c ios6 qlpreviewcontroller


【解决方案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

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

【讨论】:

  • 顺便说一句:我使用 UIDocumentInteractionController,而不是直接使用 QLPreviewController。
  • 如果要删除操作按钮,则将 qlpc.navigationItem.rightBarButtonItem 更改为 nil
  • 您无需为 Apple 没有提供适当的自定义 API 而道歉...
  • 如何使用您的代码添加新的 UIBarButtonItem?
【解决方案2】:

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

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

视图出现后rightBarButtonItems就可以访问了。

【讨论】:

  • pdf加载完成后会出现rightBarButton,所以有时候会失败。
  • 不起作用,对导航栏和/或导航项目的任何操作都没有任何效果
【解决方案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,使用此 API 可能会导致您的应用被应用商店拒绝。然而,这是我在这方面看到的唯一答案。很想看看是否有非私人的方式来做到这一点,但考虑到它的设置方式,这似乎不太可能。

此外,此方法仅在杆已就位后调用时才有效。调用它的最佳位置是“viewDidAppear”,但它并非 100% 有效。

【讨论】:

  • 在 UIDocumentInteractionController 中,QLPreviewController 只有 QLPreviewViewController.view->UIView,所以必须继续使用我的 hacky 类别解决方案:-/
  • 是的,我在任何子视图中都找不到任何 UINavigationBars。我什至尝试过 super.view.subviews(因为我是 QLPreviewController 的子类)
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    我尝试了很长时间来更换这个按钮。查看子视图等。看起来此操作/共享按钮作为导航层放置。酒吧。我最终通过在 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;
    }
    

    【讨论】:

    • 我发现的一种解决方法是将 QLPreviewController 作为全屏 subView 添加到我的 UIViewController 中,以及 UINavigationBar,我可以根据需要进行设置。继续了解用户何时点击 QLPreviewController,以便隐藏和显示导航栏。我尝试使用标准的 uiviewcontroller 方法(touchesBegan、touchesMove、touchesMove)以及手势管理器,但是当用户点击该组件时似乎很难拦截。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 2020-09-26
    • 1970-01-01
    相关资源
    最近更新 更多