App sometimes crashes at turnBasedMatchmakerViewController:didFindMatch: delegate method - ios

I have made a game using Game Center. Everything works great except for one thing. Around 1 out of 50 times, when creating a new match, either it is random opponent or by inviting a friend, my app might crash with this error being printed to my console:fatal error: unexpectedly found nil while unwrapping an Optional value. Xcode also redirects me to the "location" of the crash, which is the turnBasedMatchmakerViewController:didFindMatch: delegate method. You can see at which line of code the crash happens down below.
Why it most of the time works, and some rare times crashes, I have no idea.
It is really hard to fix this bug, because I can spend 5 hours straight trying to make the crash happen, without success. I, myself, havenĀ“t had this crash in a very long time, but the apple review team had this crash when reviewing my app.
This is my code:
func turnBasedMatchmakerViewController(viewController: GKTurnBasedMatchmakerViewController, didFindMatch match: GKTurnBasedMatch) {
currentMatch = match
presentingViewController.dismissViewControllerAnimated(true,
completion: nil)
let firstParticipant = match.participants![0] as GKTurnBasedParticipant //This is where my app crashes!
if firstParticipant?.lastTurnDate == nil {
delegate!.enterNewGame(match)
} else {
if match.currentParticipant?.player!.playerID == GKLocalPlayer.localPlayer().playerID {
delegate!.takeTurn(match)
} else {
delegate!.layoutMatch(match)
}
}
}
Fixing this is the only thing standing in my way to have my very first app in the App Store, so all kind of help is greatly appreciated

Change delegate!. to delegate?. everywhere.

Related

EXC_BAD_ACCESS on nil checking optional in Swift

EDIT 2: After changing some completely unrelated code the crash happens again. Even if I try to revert the code changes, it crashes again.
EDIT: After updating to iOS 9.2 (from 9.1) it works without any problem again.
The following code gives me an EXC_BAD_ACCESS on the nil check:
if(self.imageViews != nil){
for (_,element) in self.imageViews!.enumerate(){
element.removeFromSuperview()
}
}
The property is defined as follows:
class ImageAdditionalContent : AdditionalContentView {
var imageViews : [UIImageView]?
Even if I try to first assign an empty array to it, it gives me an EXC_BAD_ACCESS on the assignment:
self.imageViews = []
Even more interesting is, that it worked perfectly a day ago. If I remove the whole code, run the app, quit it, add the code again and run it again, it crashes on the for loop for the first time and afterwards again on the nil check.
I would take advantage of optionals here. As to your EXC_BAD_ACCESS I would check not just the status of the UIImageView array but self. Set a breakpoint before the assignment and see what's going on. If this worked fine a day ago I would also look at what code changes have happen in your project.
if let elements = self.imageViews {
for element in elements {
element.removeFromSuperview()
}
} else {
print("self.imageViews is nil! \(self.imageViews)")
}

iOS/FBSDK - FBSDKProfile is nil on device, works fine on simulator

As per the title, I am getting nil Optional unwrapping errors when testing on my device, but not the simulator - and I have found the cause of this to be calls to FBSDKProfile.currentProfile.name or similar. I remember this causing me pain while developing in the simulator, and I fixed it by adding FBSDKProfile.enableUpdatesOnAccessTokenChange(true) when the user logs in, and if they are already logged in, when the app loads.
Anyone have experience with this issue or have any ideas for a solution? Happy to post code if anyone thinks it would help.
Thanks!
The reason for this problem was that FBSDKProfile takes a few seconds to load and I wasn't giving it the time, and therefore trying to use a nil value.
So the solution was to have placeholder values, and listen for the FBSDK Notification FBSDKProfileDidChangeNotification, updating those values when it was done.
Here's the code:
In the viewDidLoad method:
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("onFBProfileUpdated:"), name: FBSDKProfileDidChangeNotification, object: nil)
And a separate method:
func onFBProfileUpdated(notification: NSNotification) {
nameLabel.text = FBSDKProfile.currentProfile().name
setImage(FBSDKProfile.currentProfile().imageURLForPictureMode(FBSDKProfilePictureMode.Square, size: image.frame.size))
}
Hope this helps anyone who stumbles across the same issue as me.

CloudKit method call hung up

When app starts some preliminary process take place. Sometimes it is done quickly in some second, and sometimes It does not end, but without any error it hung up.
I.e. at launch client always fetch the last serverChangedToken. and sometimes it just hung up it does not complete. I am talking about production environment, developer works well. So this route get called, but some times it does not finishes. Any idea why? I do not get any error, timeout.
let fnco = CKFetchNotificationChangesOperation(previousServerChangeToken: nil)
fnco.fetchNotificationChangesCompletionBlock = {newServerChangeToken, error in
if error == nil {
serverChangeToken = newServerChangeToken
dispatch_sync(dispatch_get_main_queue(), {
(colorCodesInUtility.subviews[10] ).hidden = false
})
} else {
Utility.writeMessageToLog("error 4559: \(error!.localizedDescription)")
}
dispatch_semaphore_signal(sema)
}
defaultContainer.addOperation(fnco)
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
I know it is not recommended to use semaphores to control flow of the CloudKit method calls.
Do you think the last two line can be swapped? First dispatch_semaphore_wait and then addOperation be called?
Strange that app worked for iOS 8, this bug arise only in iOS 9.
Adding the following line of code will probably solve your problem:
queryOperation.qualityOfService = .UserInteractive
In iOS 9 Apple changed the behavior of that setting. Especially when using cellular data you could get the behaviour you described.
The documentation states for the .qualityOfService this:
The default value of this property is NSOperationQualityOfServiceBackground and you should leave that value in place whenever possible.
In my opinion this is more a CloudKit bug than a changed feature. More people have the same issue. I did already report it at https://bugreport.apple.com

how to write Invitehandler for iOS 9 Xcode 7 beta 6

I am trying to develop a simple multiplayer game. As instructed in the Apple doc I am implementing the invite handler "matchforinvite" so that I could accept invite from other players.
https://developer.apple.com/library/ios/documentation/GameKit/Reference/GKMatchmaker_Ref/#//apple_ref/occ/instm/GKMatchmaker/matchForInvite:completionHandler:
I am doing this via the following function
func setUpInviteHandler() {
GKMatchmaker.sharedMatchmaker().matchForInvite(invite: GKInvite, completionHandler: { match, error -> Void in
if invite.playerAttributes != 0 {
print(invite.playerAttributes)
}
})
}
however, no matter how i change it there is always error from Xcode. How could I fix it?
The problem here (i guess) is that the GKInvite object never exist until there is an invite. However, when you do a function like this, the GKInvite thing has to be initialized in order to be called. How could you initialize a runtime object? The worst is i cannot do !(GKInvite) or GKInvite == nil checking because of the class type. Can anyone help?

Why do devices previous to iPhone 5S and iPad Air don't crash when casting a null variable?

I abstracted the code here, since the original is massive:
-(void)something {
// At this point, self.parent is NOT null
[self boom];
SomeClass *variable = (SomeClass*)self.parent;
[variable someMethod];
}
-(void)boom {
self.parent = nil;
}
Surely, if you call something, this will crash, because self.parent is nullified, and then you attempt to cast it and call a method on it.
So the thing is, this never crashed to me. I mean, for several months, this piece of code has been intact, and my app never crashed.
Now it is crashing for two specific configurations
iPhone 5S, latest iOS
iPad Air, latest iOS
All the other previous devices, with the latest iOS too, this didn't crash.
Although the above snippet is not my code, I'm pretty sure it reflects what is happening.
How is this possible? Am I missing something here?
I don't doubt you're getting a crash in the real project, but when you factored out the problem to post here (a very admirable practice, by the way, I wish more people would do it), I think you factored out the real source of your crash.
Messaging nil is perfectly fine. Casting happens at compile time, and casting a variable that might be nil at runtime is perfectly fine.
Casting an object to a Bar when it's really a Foo, then invoking a Bar method on it will cause an NSInvalidArgumentException (unrecognized selector).
But that's not happening in the OP code. It's fine for variable to be a nil instance of SomeClass. No possible method invocation on it will cause a crash.

Resources