Dismissing GameCenter View in Swift - swift

After showing a Game Center view it doesn't dismiss after tapping done. Here's my code to show it:
let gameCenterController = GKGameCenterViewController()
self.presentViewController(gameCenterController, animated:true, completion: nil)
What am I missing?

There is some good Q&A on this over at Ray Wenderlich. See the last method in the code below. Source:
http://www.raywenderlich.com/forums/viewtopic.php?f=2&t=18671
class GameViewController: UIViewController, GKGameCenterControllerDelegate {
var skView: SKView!
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
// View
//------
skView = self.view as SKView
skView.ignoresSiblingOrder = true
scene = GameScene.sceneWithSize(skView.bounds.size)
scene.scaleMode = .AspectFill
scene.view?.window?.rootViewController = self
skView.presentScene(scene)
authenticateLocalPlayer()
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
var touch:UITouch = touches.anyObject() as UITouch
var location:CGPoint = touch.locationInNode(scene)
if (scene.gameCenterRect.contains(location) && GKLocalPlayer.localPlayer().authenticated) {
self.openGameCenter()
}
}
func openGameCenter() {
var gameCenter = GKGameCenterViewController()
gameCenter.gameCenterDelegate = self
self.presentViewController(gameCenter, animated: true, completion: nil)
}
func authenticateLocalPlayer(){
var localPlayer = GKLocalPlayer()
localPlayer.authenticateHandler = {(viewController, error) -> Void in
if ((viewController) != nil) {
self.presentViewController(viewController, animated: true, completion: nil)
}else{
println("(GameCenter) Player authenticated: \(GKLocalPlayer.localPlayer().authenticated)")
}
}
}
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController!) {
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
[...] // standard methods
}

Related

Problem with delegates removing annotation

I have two screens. The first one (firstViewController) has a mapView with a UITapGestureRecognizer. When the user taps the screen, an annotations is added to the map and the second screen (secondViewController) is presented.
When the user dismisses the secondViewController and comes back to the first one, the annotation should be removed. I know I have to use delegation, but I just can't make it to work.
This is the code I have now:
class firstViewController: UIViewController, AnnotationDelegate {
let mapView = MKMapView()
var temporaryPinArray = [MKPointAnnotation]()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(mapView
let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
mapView.addGestureRecognizer(gesture)
secondVC.annotationDelegate = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
mapView.frame = view.bounds
}
#objc func handleTap(_ gestureReconizer: UILongPressGestureRecognizer) {
let location = gestureReconizer.location(in: mapView)
let coordinates = mapView.convert(location, toCoordinateFrom: mapView)
mapView.removeAnnotations(mapView.annotations)
let pin = MKPointAnnotation()
pin.coordinate = coordinates
temporaryPinArray.removeAll()
temporaryPinArray.append(pin)
mapView.addAnnotations(temporaryPinArray)
// Present secondViewController
let secondVC = SecondViewController()
panel.set(contentViewController: secondVC)
panel.addPanel(toParent: self)
}
func didRemoveAnnotation(annotation: MKPointAnnotation) {
mapView.removeAnnotation(annotation)
}
}
Second View Controller
protocol AnnotationDelegate {
func didRemoveAnnotation(annotation: [MKPointAnnotation])
}
class SecondViewController: UIViewController {
var annotationDelegate: AnnotationDelegate!
let mainVC = firstViewController()
let closeButton: UIButton = {
let button = UIButton()
button.backgroundColor = .grey
button.layer.cornerRadius = 15
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(closeButton)
closeButton.addTarget(self, action: #selector(dismissPanel), for: .touchUpInside)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
closeButton.frame = CGRect(x: view.frame.width-50, y: 10, width: 30, height: 30)
}
#objc func dismissPanel() {
self.dismiss(animated: true, completion: nil)
annotationDelegate.didRemoveAnnotation(annotation: mainVC.temporaryPinArray)
}
}
Thank you so much for your help!
You created a new instance of firstViewController inside SecondViewController. This instance is unrelated to the actual first one:
let mainVC = firstViewController()
This means that temporaryPinArray is different as well. So instead of passing in this unrelated array...
#objc func dismissPanel() {
self.dismiss(animated: true, completion: nil)
annotationDelegate.didRemoveAnnotation(annotation: mainVC.temporaryPinArray)
}
Just change the function to take no parameters instead:
protocol AnnotationDelegate {
func didRemoveAnnotation() /// no parameters
}
#objc func dismissPanel() {
self.dismiss(animated: true, completion: nil)
annotationDelegate.didRemoveAnnotation() /// no parameters
}
And inside firstViewController's didRemoveAnnotation, reference the actual temporaryPinArray.
func didRemoveAnnotation() {
mapView.removeAnnotations(temporaryPinArray) /// the current array
}

Could not cast value of type 'Pong.MenuVC' (0x1072ea808) to 'Pong.GameViewController'

I have built an app using Xcode and swift 5.
Every time I click the "Easy", "Medium", "Hard" or "2 Player" button I get an error:
Could not cast value of type 'Pong.MenuVC' (0x1072ea808) to
'Pong.GameViewController'
Does anyone know how to fix it?
Thank you for your help.
Code of MenuVC:
enum gameType {
case easy
case medium
case hard
case player2
}
class MenuVC : UIViewController {
#IBAction func Player2(_ sender: Any) {
moveToGame(game: .player2)
}
#IBAction func Easy(_ sender: Any) {
moveToGame(game: .easy)
}
#IBAction func Medium(_ sender: Any) {
moveToGame(game: .medium)
}
#IBAction func Hard(_ sender: Any) {
moveToGame(game: .hard)
}
```
**Code with Thread 1: signal SIGABRT:**
```swift
func moveToGame(game : gameType) {
let gameVC = self.storyboard?.instantiateViewController(withIdentifier: "gameVC") as! GameViewController
currentGameType = game
self.navigationController?.pushViewController(gameVC, animated: true)
}
}
Code of GameViewController:
import UIKit
import SpriteKit
import GameplayKit
var currentGameType = gameType.medium
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
scene.size = view.bounds.size
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override var prefersStatusBarHidden: Bool {
return true
}
}
In your storyboard the id gameVC is of type MenuVC not GameViewController so change class name of the vc
let gameVC = self.storyboard?.instantiateViewController(withIdentifier: "gameVC") as! GameViewController

How to pass the variable from a ViewController Class to other Struct?

I have no idea how to pass the data from the class to another struct. This is my ViewController.swift file. And I have another file called Meme.swift which is used to save the struct. I tried to put the struct in ViewController.swift file as well as Meme.swift file but I cannot access the value like topTextField.text and lowTextField.text and use them in the struct. Can anyone help me with this?
ViewController:
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate {
#IBOutlet weak var cameraButton: UIBarButtonItem!
#IBOutlet weak var bottomTextField: UITextField!
#IBOutlet weak var topTextField: UITextField!
#IBOutlet weak var imagePickerView: UIImageView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var actionButton: UIBarButtonItem!
let bottomTextFieldDelegate = BottomTextFieldDelegate()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
topTextField.text = "TOP"
bottomTextField.text = "BOTTOM"
topTextField.delegate = self
bottomTextField.delegate = self.bottomTextFieldDelegate
}
func textFieldDidBeginEditing(_ textField: UITextField) {
topTextField.text = ""
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
textField.resignFirstResponder()
actionButton.isEnabled = true
return true
}
#IBAction func shareAction(_ sender: Any) {
let image = generateMemedImage()
let controller = UIActivityViewController(activityItems: [image as Any], applicationActivities: nil)
self.present(controller, animated: true, completion: nil)
controller.completionWithItemsHandler = {(activityType: UIActivityType?, completed:Bool, returnedItems:[Any]?, error: Error?) in
if !completed {
debugPrint("cancelled")
return
}else{
self.save()
self.dismiss(animated: true, completion: nil)
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
cameraButton.isEnabled = UIImagePickerController.isSourceTypeAvailable(.camera)
configureTextField(textField: topTextField)
configureTextField(textField: bottomTextField)
topTextField.textAlignment = .center
bottomTextField.textAlignment = .center
subscribeToKeyboardNotifications()
actionButton.isEnabled = false
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
unsubscribeFromKeyboardNotifications()
}
func configureTextField(textField: UITextField) {
textField.defaultTextAttributes = memeTextAttributes
}
func save() -> Meme {
// Create the meme
let memedImage = generateMemedImage()
let meme = Meme(topText: topTextField.text!, bottomText: bottomTextField.text!, originalImage: imageView.image!, memedImage: memedImage)
return meme
}
func generateMemedImage() -> UIImage {
// TODO: Hide toolbar and navbar
navigationController?.setToolbarHidden(true, animated: true)
self.navigationController?.isNavigationBarHidden = true
// Render view to an image
UIGraphicsBeginImageContext(self.view.frame.size)
view.drawHierarchy(in: self.view.frame, afterScreenUpdates: true)
let memedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
// TODO: Show toolbar and navbar
navigationController?.setToolbarHidden(false, animated: false)
self.navigationController?.isNavigationBarHidden = false
return memedImage
}
func keyboardWillShow(_ notification:Notification) {
view.frame.origin.y = 0 - getKeyboardHeight(notification)
}
func keyboardWillHide(_ notification:Notification) {
view.frame.origin.y = 0
}
func getKeyboardHeight(_ notification:Notification) -> CGFloat { //getting the height of keyboard and use it for func keyboardWillShow to relocate
//the keyboard using keyboardWillShow function
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect
return keyboardSize.cgRectValue.height
}
func subscribeToKeyboardNotifications() { //setting up the obeserver to be notified when keyboard is shown or not, then execute keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: .UIKeyboardWillHide, object: nil)
}
func unsubscribeFromKeyboardNotifications() { //unsubscribe the notification
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
//setting the arributes of the text
let memeTextAttributes:[String:Any] = [
NSStrokeColorAttributeName: UIColor.black,
NSForegroundColorAttributeName: UIColor.white,
NSFontAttributeName: UIFont(name: "HelveticaNeue-CondensedBlack", size: 40)!,
NSStrokeWidthAttributeName: 3,]
#IBAction func pickAnImageFromAlbum(_ sender: Any) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
present(imagePicker, animated: true, completion: nil)
}
#IBAction func pickAnImageFromCamera(_ sender: Any) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imagePickerView.image = image
imagePickerView.contentMode = .scaleAspectFit
dismiss(animated: true, completion: nil)
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController){
dismiss(animated: true, completion: nil)
}
}
BottomFieldDelegate:
import Foundation
import UIKit
class BottomTextFieldDelegate: NSObject, UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.text = ""
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let viewController = ViewController()
textField.resignFirstResponder()
viewController.view.endEditing(true)
let actionButton = viewController.actionButton
actionButton?.isEnabled = true
return true
}
}
First u need to move this function like save() and generateMemedImage() into your ViewController class and then you can access topTextField.text and lowTextField.text
Modify your struct like below, and do not put nsobject in struct
struct Meme {
var topText: String
var bottomText: String
var memedImage: UIImage
var originalImage: UIImage
init(topText: String, bottomText: String, originalImage: UIImage, memedImage: UIImage) {
self.topText = topText
self.bottomText = bottomText
self.originalImage = originalImage
self.memedImage = memedImage
}
}
Remove save() from Meme struct and put that code in your Viewcontroller file.
Modify your function which return Meme struct object.
func save() -> Meme {
// Create the meme
let meme = Meme(topText: topTextField.text!, bottomText: bottomTextField.text!, originalImage: imageView.image!, memedImage: memedImage)
return meme
}
And you can store in Array like below.
let array:[Meme] = []
array.append(save())

SpriteKit - Pause screen doesn't show when didBecomeActive

My pause system works perfectly from inside the game, and also when the app moves to the background and then becomes active again the game stays paused, but my problem now is when it becomes active my pause screen doesn't show.
AppDelegate:
func applicationDidBecomeActive(application: UIApplication) {
NSNotificationCenter.defaultCenter().postNotificationName("Pause", object: nil)
}
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene()
// Configure the view.
let skView = self.view as! MainView
NSNotificationCenter.defaultCenter().addObserver(skView, selector: "setStayPaused", name: "Pause", object: nil)
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
scene.size = skView.bounds.size
skView.presentScene(scene)
}
MainView (My custom skView):
class MainView: SKView {
var stayPaused = false as Bool
override var paused: Bool {
get {
return super.paused
}
set {
if (!stayPaused) {
super.paused = newValue
}
stayPaused = false
}
}
func setStayPaused() {
if (super.paused) {
self.stayPaused = true
}
}
}
GameScene:
override func didMoveToView(view: SKView) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseGame", name: "Pause", object: nil)
}
func pauseGame() {
if isFirstTime == false { // to make sure that the app did not just get launched
pauseScreen.hidden = false // doesn't show
pauseButton.hidden = false // doesn't show
view?.paused = true
scene?.paused = true
}
}
Setting the pause screen's and button's hidden property has no effect because the view and/or scene is paused. You will need to temporarily un-pause the view, set the hidden properties to false, return the main loop, and then re-pause the view. Here's an example of how to do that.
AppDelegate:
func applicationWillResignActive(application: UIApplication) {
NSNotificationCenter.defaultCenter().postNotificationName("PauseViewNotification", object:nil)
}
func applicationDidBecomeActive(application: UIApplication) {
NSNotificationCenter.defaultCenter().postNotificationName("ShowPauseScreenNotification", object:nil)
}
MainVew (SKView subclass):
class MainView: SKView {
override var paused: Bool {
get {
return super.paused
}
set {
}
}
func pause() {
super.paused = true
}
func resume() {
super.paused = false
}
func togglePause() {
super.paused = !super.paused
}
}
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! MainView
NSNotificationCenter.defaultCenter().addObserver(skView, selector:Selector("pause"), name: "PauseViewNotification", object: nil)
}
}
GameScene:
override func didMoveToView(view: SKView) {
NSNotificationCenter.defaultCenter().addObserver(self, selector:Selector("pauseGame"), name: "ShowPauseScreenNotification", object: nil)
}
func pauseGame() {
if (!isFirstTime) {
pauseScreen.hidden = false
pauseButton.hidden = false
// Un-pause the view so the screen and button appear
if let customView = self.view as? MainView {
customView.resume()
}
// Re-pause the view after returning to the main loop
let pauseAction = SKAction.runBlock({
[weak self] in
if let customView = self?.view as? MainView {
customView.pause()
}
})
runAction(pauseAction)
}
isFirstTime = false
}
You can toggle between the pause states with
if let customView = self.view as? MyView {
customView.togglePause()
}

Parse PFGeoPoint save location getting started

Im trying to create an app with two user types...one sends a location and the other user type (on a different device) searches an area and finds the closest user.
I have been on parse's website and stack overflow...they all seem to start in the middle. I would like to have somebody explain the first steps
Heres my code
import UIKit
import MapKit
import CoreLocation
import Parse
class ViewController: UIViewController, MKMapViewDelegate,
CLLocationManagerDelegate, UISearchBarDelegate,
UIGestureRecognizerDelegate
{
#IBOutlet weak var photographer1: UIButton!
#IBOutlet weak var buyer1: UIButton!
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var searchBar: UISearchBar!
let locationManager = CLLocationManager()
var searchController:UISearchController!
var annotation:MKAnnotation!
var localSearchRequest:MKLocalSearchRequest!
var localSearch:MKLocalSearch!
var localSearchResponse:MKLocalSearchResponse!
var error:NSError!
var pointAnnotation:MKPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
override func viewDidLoad()
{
super.viewDidLoad()
self.locationManager.delegate = self
self.mapView.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
// to run the animation this sec of code checks if the region was changed
var mapChangedFromUserInteraction = false
func mapViewRegionDidChangeFromUserInteraction() -> Bool {
let view = self.mapView.subviews[0]
// Look through gesture recognizers to determine whether this region change is from user interaction
if let gestureRecognizers = view.gestureRecognizers {
for recognizer in gestureRecognizers {
if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
return true
}
}
}
return false
}
func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
if (mapChangedFromUserInteraction) {
// user changed map region
}
}
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if (mapChangedFromUserInteraction) {
hobo()
//
buyer1.center = CGPointMake(188.0, 513.0)
photographer1.center = CGPointMake(188.0, 581.0)
}
}
// your boy
// MARK: - Location Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Error: " + error.localizedDescription)
}
func searchBarSearchButtonClicked(searchBar: UISearchBar){
//1
searchBar.resignFirstResponder()
dismissViewControllerAnimated(true, completion: nil)
if self.mapView.annotations.count != 0{
annotation = self.mapView.annotations[0]
self.mapView.removeAnnotation(annotation)
}
//2
localSearchRequest = MKLocalSearchRequest()
localSearchRequest.naturalLanguageQuery = searchBar.text
localSearch = MKLocalSearch(request: localSearchRequest)
localSearch.startWithCompletionHandler { (localSearchResponse, error) -> Void in
if localSearchResponse == nil{
let alertController = UIAlertController(title: nil, message: "Place Not Found", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
return
}
//3
self.pointAnnotation = MKPointAnnotation()
self.pointAnnotation.title = searchBar.text
self.pointAnnotation.coordinate = CLLocationCoordinate2D(latitude: localSearchResponse!.boundingRegion.center.latitude, longitude: localSearchResponse!.boundingRegion.center.longitude)
self.pinAnnotationView = MKPinAnnotationView(annotation: self.pointAnnotation, reuseIdentifier: nil)
self.mapView.centerCoordinate = self.pointAnnotation.coordinate
self.mapView.addAnnotation(self.pinAnnotationView.annotation!)
}
}
func hobo(){
print("testing")
}
#IBAction func showSearchBar(sender: AnyObject) {
searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.delegate = self
presentViewController(searchController, animated: true, completion: nil)
}
#IBAction func locateMe(sender: AnyObject) {
self.mapView.showsUserLocation = true
self.locationManager.startUpdatingLocation()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
buyer1.center = CGPointMake(188.0, 581.0)
photographer1.center = CGPointMake(188.0, 513.0)
}
#IBAction func photographer(sender: AnyObject) {
}
#IBAction func buyer(sender: AnyObject) {
}
}