Game Center - sending and receiving data with Swift
A quick and dirty solution would be something like this:
func encodeGamePacket(packet: GamePacket) -> NSData {
return NSData(bytes: &gamePacket, length: MemoryLayout<GamePacket>.size)
}
func decodeGamePacket(data: NSData) -> GamePacket? {
var tempBuffer:GamePacket? = nil
data.getBytes(&tempBuffer, length: MemoryLayout<GamePacket>.size)
return tempBuffer
}
I have not messed with direct addresses myself under swift yet, so I am not entirely sure whether this is the best approach. Note that I used an optional return type, you can design this differently in your code (maybe add some checks, unwrap the variable and return it or throw an exception when the checks fail).
Alternatively you could design a method that writes your GamePacket
into a String
(for readability, for example), which you can in turn transform into NSData
(String has a data
method) or you turn GamePacket
into an NSCoding
compliant class that offers methods to convert itself into NSData
as well.
Swift - Game Center not available
Assuming that you've enabled Game Center in your app and also added a leaderboard in iTunes Connect then you need to authenticate your player before you can show GC. Also, be sure that you've created a test user in iTunes Connect that you can use to log in to Game Center when the prompt appears.
Your MenuViewController
should authenticate the local player in viewDidLoad like so:
class MenuViewController: UIViewController,
GKGameCenterControllerDelegate
{
var leaderboardIdentifier: String? = nil
var gameCenterEnabled: Bool = false
override func viewDidLoad()
{
super.viewDidLoad()
//Your code that sets up your scene or other set up code
//HERE IS WHERE YOU AUTHENTICATE
authenticateLocalPlayer()
}
func authenticateLocalPlayer()
{
var localPlayer = getLocalPlayer() // see GKLocalPlayerHack.h
localPlayer.authenticateHandler =
{ (viewController : UIViewController!, error : NSError!) -> Void in
if viewController != nil
{
self.presentViewController(viewController, animated:true, completion: nil)
}
else
{
if localPlayer.authenticated
{
self.gameCenterEnabled = true
localPlayer.loadDefaultLeaderboardIdentifierWithCompletionHandler
{ (leaderboardIdentifier, error) -> Void in
if error != nil
{
print("error")
}
else
{
self.leaderboardIdentifier = leaderboardIdentifier
print("\(self.leaderboardIdentifier)") //in your example "VHS" should be returned
}
}
}
else
{
print("not able to authenticate fail")
self.gameCenterEnabled = false
if error
{
print("\(error.description)")
}
else
{
print( "error is nil")
}
}
}
}
}
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController!)
{
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
}
After you've successfully authenticated then you should be able to present Game Center.
Note the line:var localPlayer = getLocalPlayer() // see GKLocalPlayerHack.h
To get that to work you need to do a little hack to get GKLocalPlayer to instantiate correctly in Swift.
Create a new class in Objective-C and name the file GKLocalPlayerHack.h/m
In the header put:
// GKLocalPlayerHack.h
// Issue with GameKit and Swift
// https://stackoverflow.com/questions/24045244/game-center-not-authenticating-using-swift
#import <GameKit/GameKit.h>
@interface GKLocalPlayerHack : NSObject
GKLocalPlayer *getLocalPlayer(void);
@end
In the implementation file put:
// GKLocalPlayerHack.m
// Issue with GameKit and Swift
// https://stackoverflow.com/questions/24045244/game-center-not-authenticating-using-swift
#import "GKLocalPlayerHack.h"
@implementation GKLocalPlayerHack
GKLocalPlayer *getLocalPlayer(void)
{
return [GKLocalPlayer localPlayer];
}
@end
Be sure to add:
#import "GKLocalPlayerHack.h"
To your bridging header.
Credit to @marmph for his answer in this question: Game Center not authenticating using Swift
Unable to Enable Game Center for my App
- Enable Game Center in your App ID. To do this, log into developer.apple.com and go to Member Center -> Certificates,Ids & Devices -> App Ids and select your App id. Then make sure Game Center is enabled
- Make sure Game Center is enabled in Xcode. You can check by going to Project -> Capabilities -> and the check that Game Center is turned on. Once you do that follow to step 3. If it isn't enable it and press fix issues and Xcode should resolve everything by itself.
- Go to iTunes Connect -> My Apps -> Select your app. Under the upper left corner next to App Store you should see Features.
Select it, and you'll be taken to this page:
Press on Game Center and voila, you're ready to set up Leaderboards and Achievements. Congrats.
EDIT:
What appears to have been the problem was the use of production certificates while development, as the OP pointed out that the PN error got fixed in the released build. Another way to try to fix that type of error is to check if the correct and new provisioning profile is installed.
Hope that helps, Julian!
Application is not recognized by Game Center after building with Xcode 6.0.1
Alright I'm able to figure out why. Forgot to mention that I upgraded my test iOS device to 8.0 as well.
It turns out that you need to go to Settings>Game Center and manually enable Sandbox.
I got it working now. Hopefully this helps anyone who face this issue.
why do i not have 'gamecenter' option in my list of capabilities
https://developer.apple.com/documentation/xcode/adding-capabilities-to-your-app
Some capabilities such as 'gamecenter' requires extra configurations first to your app such as paying the yearly fee to be on apple developer program before being allowed to access them.
Game Center not authenticating using Swift
This issue has been resolved by Apple - just call:
GKLocalPlayer.localPlayer()
Previously, the issue was that GKLocalPlayer()
does not return the GKLocalPlayer singleton, but instead returns a new GKLocalPlayer instance.
If you were on the Xcode 6 BETA, you could add a C function or Objective-C method that returns the real GKLocalPlayer singleton, then use this in Swift. This is the gist of my workaround (with bad naming conventions):
In an Objective-C header:
GKLocalPlayer *getLocalPlayer(void);
In an Objective-C implementation:
GKLocalPlayer *getLocalPlayer(void) {
return [GKLocalPlayer localPlayer];
}
In your bridging header:
#import "ThatHeader.h"
Then whenever you need to access the GKLocalPlayer singleton in Swift, you can just use getLocalPlayer()
instead of GKLocalPlayer()
. It's probably a better idea to stick that in an method of a GKLocalPlayer category.
However, this is no longer necessary as detailed above.
GameCenter reporting achievements Swift 3
It would appear that it can take a long time for Apple to set up Game Center achievements, and in the end the code was Ok. Go figure.
Swift Game Center Authentication
This question has to do with a bug in GKLocalPlayer() and Swift. Please see this very detailed answer that I gave from a few weeks ago:
Swift - Game Center not available
Related Topics
Do Not Copy Swift Libraries with Xcode 8
Setadvertisertrackingenabled Is Not Found in Settings Class of Fbsdk
[Core Data]: Threw While Encoding a Value. with Userinfo of (Null)
Swift 3 Custom Extension of Ns Measurement? Ex. Sheeps to Goats
Pass Custom Parameter to UIbutton #Selector Swift 3
Swift Textview Align with English and Arabic Languages
Assigning Values to Tuple in for Loop
Xcode9/Scenekit - .Dae File Not Loading into Scnscene - Returns Nil
Mapview Shows White Overlay on Interaction
Swift Equivalent of Objective-C for Flutter Native Ads
Expressions Are Not Allowed at The Top Level
How to Detect Day Change in Swift
Uitableview Didselectrow Returns Wrong Row Index Value
How to Make UItabbar Image Rounded in Swift Programmatically
User Already Authenticated in App and Firebase Realtime Database Returns Failed: Permission_Denied