iOS9のWebView内でTwitterのシェアボタンをクリックしたらiOS標準のダイアログで投稿したい

まえがき

同僚さんがタイトルに書いてあるようなことをやりたいけどできないと言っていたのでちょっと調べてみました。

やってみた

正しいやり方かどうかは別として、こんなやり方になりました。

import UIKit
import Social

class ViewController: UIViewController, UIWebViewDelegate {
    @IBOutlet weak var webView: UIWebView!
    
    let twitterIntentUrl = "https://twitter.com/intent/tweet"
    let initialUrlString = "http://ariarijp.hatenablog.com"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = NSURL(string : initialUrlString)
        let urlRequest = NSURLRequest(URL: url!)
        
        webView.delegate = self;
        
        // WebViewの初期表示
        webView.loadRequest(urlRequest)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        let absUrl = request.URL?.absoluteString
        
        // リクエストされたURLがTwitterのシェアボタンっぽいものだったら、Social.frameworkでダイアログを表示する
        if absUrl!.containsString(twitterIntentUrl) {
            // アカウントの設定が済んでいれば投稿ダイアログ、設定が済んでいなかったらアラートを表示する
            // 参考: http://www.brianjcoleman.com/tutorial-share-facebook-twitter-swift/
            if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter){
                // URLからシェアに使うテキスト、URLを取り出す
                let tweetUrl = getQueryStringParameter(request.URL?.absoluteString, param: "url")
                let tweetText = getQueryStringParameter(request.URL?.absoluteString, param: "text")
                
                let twitterSheet:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
                twitterSheet.setInitialText("\(tweetText!) \(tweetUrl!)")
                self.presentViewController(twitterSheet, animated: true, completion: nil)
            } else {
                let alert = UIAlertController(title: "アカウントエラー", message: "Twitterにログインしてください", preferredStyle: UIAlertControllerStyle.Alert)
                alert.addAction(UIAlertAction(title: "閉じる", style: UIAlertActionStyle.Default, handler: nil))
                self.presentViewController(alert, animated: true, completion: nil)
            }
            
            return false
        }
        
        return true
    }
    
    // URLから指定したパラメータを文字列として取り出す
    // 参考: https://gist.github.com/gillesdemey/509bb8a1a8c576ea215a#gistcomment-1483938
    func getQueryStringParameter(url: String?, param: String) -> String? {
        if let url = url, urlComponents = NSURLComponents(string: url), queryItems = (urlComponents.queryItems) {
            return queryItems.filter({ (item) in item.name == param }).first?.value!
        }
        return nil
    }
}

StoryboardでwebViewを配置して、このViewControllerにOutletを追加してあるのが前提です。

また、はてなブログのURLで動作確認してますが、HTTPSでは無いのでATSの設定をいじったりしてます。

動作確認

動かしてみるとこんな感じです。

Twitterにログインしていない状態でアプリ内WebViewでシェアボタンをタップ

f:id:ariarijp:20160621233518p:plain

Twitterにログインした状態でアプリ内WebViewでシェアボタンをタップ

f:id:ariarijp:20160621233543p:plain

今回のような実装を入れなかった場合(デフォルトの挙動

f:id:ariarijp:20160621233636p:plain

まとめ

雑な感じで「できないことはないでしょう」と言った手前ムキになってやった感がありますが、思ったようなことはできたのでよかったです。

もっと効率が良いやりかたがあれば、Twitterなんかでぜひ教えて下さい。