[Swift] SpriteKit,SKScene上でSNS投稿画面を表示し、TwitterやFacebookへ投稿する方法

## 内容

SKScene上でSNS投稿画面を表示し、TwitterやFacebookへ投稿する方法について
![iOS Simulator Screen Shot Jul 15, 27 Heisei, 01.05.47.png](https://qiita-image-store.s3.amazonaws.com/0/30253/9f4be1f3-4322-9fe3-b2bc-8dd13a53094c.png)


UIViewControllerのサブクラスであれば、
`presentViewController()`メソッドが使えるので、簡単にViewControllerを呼び出すことができます。

例:

``` Swift:Swift
var next = NextViewController()
self.presentViewController(next, animated: true, completion: nil)
```

しかし、`SKScene`のサブクラスではUIViewControllerクラスを(多重)継承できないので、  `presentViewController()`メソッドが使えません。`SKScene`からSNSの投稿画面など新しいViewControllerを呼びたい時にどうするべきなのか。

**想定ケース:**

```
(a) FaceBookボタンやTwitterボタンを設置し、ボタンをタップすると、投稿画面が表示され、投稿ができるようにしたい

(b) GameCenterボタンを設置し、ボタンをタップするとGameCenterランキングを表示したい

などなど
```

## 解決方法
`NSNotification` を使います。
(もっと効率的な方法もあるかもしれません）






###  Facebook・Twitterへ投稿する
```html:開発環境
Swift1.2
XCode6.4
```

(1) フレームワークのインポート
事前に`Social.framework`と `Accounts.framework`をProjectにインポートします。
![Screen_Shot_0027-07-14_at_21_16_14.png](https://qiita-image-store.s3.amazonaws.com/0/30253/7afb8369-fb11-e01e-9e6c-454b91e8e3b9.png)

``` Swift:GameViewController.swift
import UIKit
import SpriteKit
import Social // ←記述する!!!!!!!!!!
```

(2) ボタン画像をProjectにインポート

TwitterやFacebookが公式にアイコン画像を配布してるので、
下記名称で`images.xcassets`にdrag and dropしておきます。
(任意の画像でも構いません）

```
twitter_icon
facebooK_icon
```

(3) コードを記述(必要最低限のところのみ書いてます）

``` Swift:GameViewController.swift
import UIKit
import SpriteKit
import Social

class GameViewController: UIViewController{

    override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "showSocialShare:", name: "socialShare", object: nil)
        
        // GameSceneをSKViewに追加しておく
        let scene = GameScene()
        let skView = self.view as! SKView
        scene.scaleMode = .AspectFill
        scene.size = skView.frame.size
        skView.presentScene(scene)

    }
    
    func showSocialShare(notification: NSNotification) {
        
        // (1) オブザーバーから渡ってきたuserInfoから必要なデータを取得する
        let userInfo:Dictionary<String,NSData!> = notification.userInfo as! Dictionary<String,NSData!>
        let message = NSString(data: userInfo["message"]!, encoding: UInt())
        let social = NSString(data: userInfo["social"]!, encoding: UInt())
        
        // (2) userInfoの情報をもとにTwitter/Facebookボタンどちらが押されたのか特定する
        var type = String()
        if social == "twitter" {
            type = SLServiceTypeTwitter
        } else if social == "facebook" {
            type = SLServiceTypeFacebook
        }
        
        // (3) shareViewControllerを作成、表示する
        var shareView = SLComposeViewController(forServiceType: type)
        shareView.setInitialText(message as! String)
        
        shareView.completionHandler = {
            (result:SLComposeViewControllerResult) -> () in
            switch (result) {
            case SLComposeViewControllerResult.Done:
                println("SLComposeViewControllerResult.Done")
            case SLComposeViewControllerResult.Cancelled:
                println("SLComposeViewControllerResult.Cancelled")
            }
        }
        self.presentViewController(shareView, animated: true, completion: nil)
    }
}
```


``` Swift:GameScene.swift
import SpriteKit

class GameScene: SKScene{

    // 変数定義
    let twButton = SKSpriteNode(imageNamed:"twitter_icon")
    let fbButton = SKSpriteNode(imageNamed:"facebook_icon")
    var touchButtonName:String? = ""
    
    // メイン
    override func didMoveToView(view: SKView) {

        twButton.position = CGPoint(x: self.frame.width * 0.45, y: self.frame.size.height * 0.15)
        twButton.name = "twitter_button"
        self.addChild(twButton)
        
        fbButton.position = CGPoint(x: self.frame.width * 0.65, y: self.frame.size.height * 0.15)
        fbButton.name = "facebook_button"
        self.addChild(fbButton)
    }
    
    // Twitter/Facebookボタンがタップされたとき
    func socialButtonTapped(social:String){
        
        // share画面で表示するメッセージを格納
        var message = String()
        if social == "twitter" {
            message = "Twitter Share"
        } else {
            message = "Facebook Share"
        }
        
        // userinfoに情報(socialの種類とmessage)を格納
        let userInfo = ["social": social.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!,"message": message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!]
        
        // userInfoも含めて、"socialShare"という名称の通知をここで飛ばす
        NSNotificationCenter.defaultCenter().postNotificationName("socialShare", object: nil, userInfo: userInfo)
        
    }
    
    // 画面がタップされたとき
    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)
            touchButtonName = nodeAtPoint(location).name
            
            if (touchButtonName == "twitter_button") {
                socialButtonTapped("twitter")
            } else if (touchButtonName == "facebook_button") {
                socialButtonTapped("facebook")
            }
        }
    }
}
```

これでSKScene上でSNS投稿画面を表示し、
TwitterやFacebookへ投稿することができます。