Couple issues converting game center code from swift 1.2 -> 2.0, any help?

I've managed to fix most of the errors I've received when converting from 1.2 -> 2.0. Most of the time I just added an ! or ? and was able to make most error notifications go away. I have a few issues remaining that I cannot find a way around:


**#1 - My browser glitched when I wrapped this in code format**


playerDict = NSDictionary(objects: [GameKitHelper.sharedGameKitHelper.localPlayer.playerID, NSInteger(ourRandomNumber)], forKeys: [playerIdKey, randomNumberKey])


Error: "Ambiguous reference to member 'Int.Init'


This error is coming up from where it says "NSInteger(ourRandomNumber)"... Not really sure how to fix that.


**#2**


GKPlayer.loadPlayersForIdentifiers(idsArray as [AnyObject], withCompletionHandler: { (players, error) -> Void in


Error: Cannot convert value of type [AnyObject] to expected argument type [String].


Here I've tried adding ? and ! to 'as' as well as changed the value of AnyObject to 'String' and I still get error: NSMutableArray is not convertible to string



**#3**


This one is just a notice and not a compiler error


        if(match != nil){
            for players in match!.players{
                if let player = players as? GKPlayer{
                    idsArray.addObject(player.playerID!)
                }
            }
        }


Here I am getting a notice: 'Conditional cast from GKPlayer to GKPlayer always succeeds'... Do I even need to fix this? I feel like I can get away with the whole if let statement and simple replace it with this


idsArray.addObject(players.playerID!)


That should work, but I'd like someone to confirm with me.

Answered by OOPer in 60614022

Sorry, I cannot reproduce your issue, if your provided data types are correct:

playerID is a string and ourRandomNumber is an Int

I assumed the type of playerID as `String?`, although you described it as `string`.

So, you want another guess game, let's try. Assuming ourRandomNumber is Int32, and I get the same error message:

error: type of expression is ambiguous without more context


Without correct info provided, you cannot get a correct correction.

Try changing `ourRandomNumber` in the line to `Int(ourRandomNumber)`.

**#1**

Too much uncovered. What are the types of playerDict, playerID (this is very probably a `String?`), ourRandomNumber, playerIdKey and randomNumberKey.

Try changing it to:

playerDict = [playerIdKey : GameKitHelper.sharedGameKitHelper.localPlayer.playerID, randomNumberKey : ourRandomNumber]

and report the error message generated, with the types above.


**#2**

Here, too, you are not providing the needed info, what is idsArray?

Anyway, check the latest referece: + loadPlayersForIdentifiers:withCompletionHandler:.

class func loadPlayersForIdentifiers(_ identifiers: [String],
               withCompletionHandler completionHandler: (([GKPlayer]?,
                                              NSError?) -> Void)?)

The method takes [String] as identifers, not [AnyObject]. Thus, you should not cast your idsArray to [AnyObject] .

Assuming idsArray as `NSMutableArray`, you need intermediate NSArray, before you cast it to [String] :

    GKPlayer.loadPlayersForIdentifiers(idsArray as NSArray as! [String], withCompletionHandler: { (players, error) -> Void in

(I recommend you to use [String] rather than NSMutableArray for idsArray.)


**#3**

Check the latest reference: players .

var players: [GKPlayer] { get }

The `players` property of GKMatch is got [GKPlayer] in iOS9 SDK. So you have no need to cast its elements to GKPlayer.

        if match != nil {
            for player in match!.players {
                idsArray.addObject(player.playerID!)
            }
        }

(You'd better not use plural name `players` for a single GKPlayer instance.)

Hi OOPer, seems like questions #2 and #3 were fixed with your adjustments.


I replaced the code for problem #1 and here is the new error: The type of expression is ambiguous without more context.


Replaced this (playerID is a string and ourRandomNumber is an Int):


  let playerIdKey = "PlayerId"
  let randomNumberKey = "randomNumber"
  var playerDict: NSDictionary!

playerDict = NSDictionary(objects: [GameKitHelper.sharedGameKitHelper.localPlayer.playerID, NSInteger(ourRandomNumber)], forKeys: [playerIdKey, randomNumberKey])



With this:


        playerDict = [playerIdKey : GameKitHelper.sharedGameKitHelper.localPlayer.playerID, randomNumberKey : ourRandomNumber]

Thanks, with a little info like such variable data types, we can skip `guess games`.


And for #1, what was bad is the error message or the position inidication that Swift generated, which is quite misleading.

NSInteger is just a typealias of Int, so, you have no need to convert it to NSInteger. But this is not the reason of the error #1. The conversion always succeeds. (Actually it converts nothing.)

If the error message was appropriate like `NSArray cannot contain nil`, you would have tried. It's the time just added an ! .

This should work:

playerDict = NSDictionary(objects: [GameKitHelper.sharedGameKitHelper.localPlayer.playerID!, ourRandomNumber], forKeys: [playerIdKey, randomNumberKey])


Or, dictionary literals in Swift can construct NSDictionary:

playerDict = [playerIdKey : GameKitHelper.sharedGameKitHelper.localPlayer.playerID!, randomNumberKey : ourRandomNumber]


Maybe you know, as you used Swift 1.x, Swift sometime generates messages which are hard to understand or completely mistaking something...

In Swift 2, much improved than former versions, we can find some inappropriate error messages, especially in case of type mismatching.

If you find a type-related error message from Swift, which you cannot fix it easily, take the message as `you have some type mismatching error somewhere in this line`. Rewriting the expression to a combination of simple statements (using intermediate variables) is one way to find out where the actual problem hides.


Removin all compile errors and then you may need test run next. Good luck.


EDIT: Sorry, I mistakenly touched [Save Reply] while editing.

Do you have a correction for my problem #1? I am still getting the error and I do not know how to fix it!

Sorry to keep bothering you with this.. I just used this code


        playerDict = NSDictionary(objects: [GameKitHelper.sharedGameKitHelper.localPlayer.playerID!, ourRandomNumber], forKeys: [playerIdKey, randomNumberKey])


And I am still getting the error "Type of expression is ambiguous without more context". The little red indicator is pointing toward the "GameKitHelper.sharedGamekithelper" variable...


What do you think?

Accepted Answer

Sorry, I cannot reproduce your issue, if your provided data types are correct:

playerID is a string and ourRandomNumber is an Int

I assumed the type of playerID as `String?`, although you described it as `string`.

So, you want another guess game, let's try. Assuming ourRandomNumber is Int32, and I get the same error message:

error: type of expression is ambiguous without more context


Without correct info provided, you cannot get a correct correction.

Try changing `ourRandomNumber` in the line to `Int(ourRandomNumber)`.

I am sorry, you are right. I have it described as the following:


    var ourRandomNumber: UInt32!


I didn't realize it would make such a big difference from Int to UInt32.


So, where do I go from here?



***EDIT**** For some reason I kept rebuilding my project and after a few tries the error just went away without changing any of your code. I'm not sure how that is possible but maybe some glitchiness with xCode 7 I just downloaded.


Thank you for your time OOPer, I appreciate the help.

I didn't realize it would make such a big difference from Int to UInt32.

Not only you, who cannot realize it as such. Swift is the strictest language among all major languages I know, about numeric type conversions.


And about integer types only Int and UInt can be converted to NSNumber, which means you can store them in NSArrays or NSDictionarys.

See the Numbers section in Using Swift with Cocoa and Objective-C (Swift 2).

(This restriction is being kept from the former versions of Swift, your NSInteger(ourRandomNumber) was actually needed (as it's UInt32) in both Swift 1.2.

As noted, `Int(ourRandomNumber)` is exactly the same as `NSInteger(ourRandomNumber)`.)


iOS9 SDK shows many different behaviors than iOS 8 SDKs. You'd better test all your app's functionalities, or you may need to fix runtime errors before testing functionalities...


I don't do much GameKit programming, but I believe many participants of the dev forums would help. Hoping your app works perfectly in iOS9/Xcode7 soon.

Couple issues converting game center code from swift 1.2 -> 2.0, any help?
 
 
Q