Change the button titles on SLComposeServiceViewController?

試著忘記壹切 提交于 2019-11-30 01:18:08

问题


Is there a way to change the button titles on the SLComposeServiceViewController? I tried to change the bar button items on the navigation item, but those aren't the right buttons.


回答1:


Simply accessing from navigationController!.navigationBar does the charm. The following should help.

self.navigationController!.navigationBar.topItem!.rightBarButtonItem!.title = "Save"



回答2:


I just found a way to do it:

class CustomServiceViewController: SLComposeServiceViewController {
    override func viewDidLoad() {
        let navigationBar = view.subviews.first?.subviews?.last? as? UINavigationBar
        let postButton = navigationBar?.subviews.last? as? UIButton
        let cancelButton = navigationBar?.subviews.last? as? UIButton
        postButton?.setTitle("Done", forState: .Normal)
    }
}

Be warned - it's a fragile solution, based on undocumented internals of SLComposeServiceViewController




回答3:


The answer by Kasztan no longer works with the latest iOS; here is the latest fragile solution..

class CustomServiceViewController: SLComposeServiceViewController { override func viewDidLoad() { let navigationBar = view.subviews.last?.subviews?.last? as? UINavigationBar let postButton = navigationBar?.subviews[3] as? UIButton postButton?.setTitle("Done", forState: .Normal) } }




回答4:


EDIT #3: Solution working on iOS 9 and iOS 10 beta

The previous approach stopped working with iOS 9, but the following seems to work again (tested on iOS 9 and 10 beta 2):

1) First, you need to add a UIFont class extension to check if a button font is bold (this, because the Post button is always bold); here's how.

2) Then, in viewDidAppear:, we need the following code (an updated version of the code I wrote in Edit 2):

if let navigationBar = self.navigationController?.navigationBar {

    // First, let's set backgroundColor and tintColor for our share extension bar buttons
    navigationBar.backgroundColor = UIColor.darkGrayColor()
    navigationBar.tintColor = UIColor.whiteColor()

    if let navBarSubviews = navigationBar.subviews as? [UIView] {

        for eachView in navBarSubviews {

            if let navBarButton = eachView as? UIButton {

                // Second, let's set our custom titles for both buttons (Cancel and Post); checking for the title wouldn't work for localized devices, so we check if the button is bold (Post) or not (Cancel) via the UIFont class extension above.

                let buttonFont : UIFont? = navBarButton.titleLabel?.font

                if buttonFont?.isBold == true {

                    navBarButton.setTitle("Save", forState: .Normal)

                } else {

                    navBarButton.setTitle("Cancel", forState: .Normal)
                }
            }
        }
    }
}

Of course, this works now, but it will probably break again in the future...


EDIT #2: I made it work on a device with iOS 8.4 :)

Turns out I was wrong, after spending an unreasonable amount of time on this I've been able to both change the color of the buttons and their text.

Here's my code, that needs to be put inside ViedDidAppear() (if you place it in viewDidLoad() it won't work!):

    if let navigationBar = self.navigationController?.navigationBar {

        // First, let's set backgroundColor and tintColor for our share extension bar buttons
        navigationBar.backgroundColor = UIColor.darkGrayColor()
        navigationBar.tintColor = UIColor.whiteColor()

        if let navBarSubviews = navigationBar.subviews as? [UIView] {

            for eachView in navBarSubviews {

                if let navBarButton = eachView as? UIButton {

                    // Second, let's set our custom titles for both buttons (Cancel and Post); checking for the title wouldn't work on localized devices, so we check if the current button is emphasized (Post) or not (Cancel) via an UIFontDescriptor.

                    let fontDescriptor : UIFontDescriptor? = navBarButton.titleLabel?.font.fontDescriptor()

                    if let descriptor = fontDescriptor {

                        let fontAttributes : NSDictionary = descriptor.fontAttributes()
                        var buttonFontIsEmphasized : Bool? = fontAttributes["NSCTFontUIUsageAttribute"]?.isEqualToString("CTFontEmphasizedUsage")

                        if buttonFontIsEmphasized == true {
                            navBarButton.setTitle("Save", forState: .Normal)
                        } else {
                            navBarButton.setTitle("Cancel", forState: .Normal)
                        }
                    }
                }
            }
        }
    }

Still, I'm not sure this should be done on a shipping app nor it would pass App Review (it should, though, because it doesn't mess with private APIs). Also, it should be noted that this could break anytime, even though it shouldn't be as easily breakable as the previous solutions (it iterates through the subviews and attempts downcasting them, so a small change in the view hierarchy shouldn't render it useless); my expectations is that, even if in the future it stops working, it shouldn't crash the Share Extension.


Original answer

I believe what you (and I) want to do is not possible anymore, possibly by design. Here's why:

Inspired by @Kasztan and @Paito answers, I tried this in viewDidLoad() of my ShareViewController:

    for eachView in view.subviews {
        println("1")

        for eachSubView in eachView.subviews {
            println("2")

            if let navigationBarView = eachSubView as? UINavigationBar {
                println("3")

                for eachNavBarSubView in navigationBarView.subviews {
                    println("4")

                    if let navBarButton = eachNavBarSubView as? UIButton {
                        println("5")
                        println(navBarButton.titleForState(.Normal))

                        navBarButton.setTitleColor(UIColor.redColor(), forState: .Normal)
                        navBarButton.setTitle("My text", forState: .Normal)
                        navBarButton.tintColor = UIColor.redColor()

                        navBarButton.setNeedsLayout()
                        navBarButton.layoutIfNeeded()
                    }
                }
            }
        }
    }

Not that I believe something like this should ship in an app, but as a proof of concept this should have worked and, in theory, should be a bit less breakable with future releases of the OS.

Except, it didn't work for me on iOS 8.4: I see all the checkpoint messages logged, from 1 to 5, some of them multiple times (as it should be, since the code tries every possible subview).

The "5" message is logged twice, which makes sense since it means that it successfully downcast both the buttons, Cancel and Post, but not the text nor the color is changed from the default.

My conclusion is that something in Apple's code prevents us to change the appearance of those buttons.

Of course, if anyone finds a solution, I'd be glad to downvote my own answer (if it can be done, I'm note sure) ;)

EDIT #1: One last check, I logged the button title too, after the buttons downcast (5), and yes, I got Optional("Cancel") and Optional("Post") in the console, so this solution gets the right buttons, but they can't be edited.



来源:https://stackoverflow.com/questions/25276974/change-the-button-titles-on-slcomposeserviceviewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!