1

I have made a simple game using the Game template in Xcode, coded in swift. I created a shapeNode, and when it is touched, I would like this code to run:

        if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook){
            var controller = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
            controller.setInitialText("Testing Posting to Facebook")
            //self.presentViewController(controller, animated:true, completion:nil)
        }

This code is run in the GameViewController.swift file, but gives this error. This error occurs on the commented line.

Could not cast value of type 'UIView' (0x379480d0) to 'SKView' (0x37227ad0).
R_McVities
  • 179
  • 1
  • 9

1 Answers1

4

Update: If you are targeting iOS 9 or above there are some small changes to make this work. You will need to add the correct URL schemes to your info.plist otherwise the check to see if the app is installed will not work.

NOTE: Its is a better idea to now use UIActivityController for sharing. This allows you to only use 1 button and you can share to all sorts of services.

http://useyourloaf.com/blog/querying-url-schemes-with-canopenurl/

To present a viewController in a SKScene you need to use the rootViewController

self.view?.window?.rootViewController?.presentViewController(...

I use a little helper for this using swift 2 protocol extensions, so you can use it anywhere you like in your app. The Facebook part looks like this, twitter is basically the same.

import SpriteKit
import Social

/// URLString
private struct URLString {
    static let iTunesApp = URL(string: "Your iTunes app link")
    static let facebookApp = URL(string: "Your Facebook app link")
    static let facebookWeb = URL(string: "Your Facebook web link")
}

/// Text strings
private struct TextString {
    static let shareSheetText = "Your share sheet text"
    static let error = "Error"
    static let enableSocial = "Please sign in to your account first"
    static let settings = "Settings"
    static let ok = "OK"
}

/// Social
protocol Social {}
extension Social where Self: SKScene {

/// Open facebook
func openFacebook() {
    guard let facebookApp = URLString.facebookApp else { return }
    guard let facebookWeb = URLString.facebookWeb else { return }

    if UIApplication.shared.canOpenURL(facebookApp){     
        UIApplication.shared.openURL(facebookApp)
    } else {
        UIApplication.shared.openURL(facebookWeb)
    }
}

/// Share to facebook
func shareToFacebook() {

    guard SLComposeViewController.isAvailable(forServiceType: SLServiceTypeFacebook) else {
        showAlert()
        return
    }

    guard let facebookSheet = SLComposeViewController(forServiceType: SLServiceTypeFacebook) else { return }
    facebookSheet.completionHandler = { result in

        switch result {

        case .cancelled:
            print("Facebook message cancelled")
            break

        case .done:
            print("Facebook message complete")
            break
        }
    }

    let text = TextString.shareSheetText
    //facebookSheet.setInitialText(text)
    facebookSheet.setInitialText(String.localizedStringWithFormat(text, "add your score property")) // same as line above but with a score property
    facebookSheet.addImage(Your UIImage)
    facebookSheet.add(URLString.iTunesApp)

    self.view?.window?.rootViewController?.present(facebookSheet, animated: true, completion: nil)
}

   // MARK: - Private Methods

   /// Show alert
   private func showAlert() {
    let alertController = UIAlertController(title: TextString.error, message: TextString.enableSocial, preferredStyle: .alert)

    let okAction = UIAlertAction(title: TextString.ok, style: .cancel) { _ in }
    alertController.addAction(okAction)

    let settingsAction = UIAlertAction(title: TextString.settings, style: .default) { _ in

        if let url = URL(string: UIApplicationOpenSettingsURLString) {
            UIApplication.shared.openURL(url)
        }
    }
    alertController.addAction(settingsAction)

    self.view?.window?.rootViewController?.present(alertController, animated: true, completion: nil)
    }
}

To use the helper you simply go to the SKScene you need to call the methods and implement the protocol

 class YourScene: SKScene, Social {....

Now when the Facebook node/button is pressed you can call the methods as if they are part of the scene itself.

openFacebook()    // opens app or safari
shareToFacebook() // opens share sheet textField

all thanks to swift 2 and protocol extensions. The cool bit about this is say you want to use this helper in a regular UIKit app, than all you have to do is import UIKit instead of spriteKit

 import UIKit

and change the protocol extension to this

 extension Social where Self: UIViewController {....

Its quite nice and very flexible I think

Hope this helps.

crashoverride777
  • 10,581
  • 2
  • 32
  • 56