I am making a turnbased game for iOS with game center, 2 participants per match. I would like to implement a time limit on every turn, so that a player don't have to wait forever for the other player to finish its turn. I have tried:
currentMatch endTurnWithNextParticipants:[[NSArray alloc] initWithObjects:nextParticipant,nil] turnTimeout:GKTurnTimeoutDefault matchData:data completionHandler:^(NSError *error)
but nothing happens, the player still has forever to do their turn, so I am obviously missing something here.
What happens when the time limit is reached? How does gamecenter handle this, and where should I handle this?
That method updates the data stored on Game Center for the current match.
According to Apple Docs:
If the next player to act does not take their turn in the specified interval, the next player in the array receives a notification to act. This process continues until a player takes a turn or the last player in the list is notified.
When this method is called, it creates a new background task to handle the request. The method then returns control to your game. Later, when the task is complete, Game Kit calls your completion handler. Keep in mind that the completion handler may be called on a thread other than the one originally used to invoke the method. This means that the code in your block needs to be thread-safe.
I think you need to also end the players go on their end programatically.
Related
After I create a new session data task with URLSession.dataTask(with:completionHandler:) and start the task by calling its resume() method, given that the app doesn't crash while the request is running, is it safe for me to assume that completionHandler (passed to URLSession.dataTask(with:completionHandler:) above) will always eventually get called only once, even if something weird happens with the network request (like if the connection drops) or with the app (like if it goes into the background)?
Note: I'm not explicitly calling cancel() or suspend() on the task. Just resume().
I want to know the answer to this question because (from my app's main thread) I'm creating and starting (one after the other) multiple asynchronous network requests and want to know when the last one has finished.
Specifically, I'm working on an app that has a custom class called Account. On launch, the app (assuming it finds an account access token stored in UserDefaults) creates only one instance of that class and stores it to a global variable (across the entire app) called account, which represents the app's currently-logged-in account.
I've added a stored var (instance) property to Account called pendingGetFooRequestCount (for example) and set it to 0 by default. Every time I make a call to Account.getFoo() (an instance method), I add 1 to pendingGetFooRequestCount (right before calling resume()). Inside completionHandler (passed to URLSession.dataTask(with:completionHandler:) and (to be safe) inside a closure passed to DispatchQueue.main.async(), I first subtract 1 from pendingGetFooRequestCount and then check if pendingGetFooRequestCount is equal to 0. If so, I know the last get-foo request has finished, and I can call another method to continue the flow.
How's my logic? Will this work as expected? Should I be doing this another way? Also, do I even need to decrement pendingGetFooRequestCount on the main thread?
URLRequest has a timeoutInterval property, its default value is 60 seconds. If there is no response by then, the completion is called with non-nil error.
So I want to get the timings of the cellular call that I place from my app. I get call's start time as soon as call gets connected, but i also get start time block executed when calls ends which overwrites my callStartTime property. Same thing happens with incoming calls as well (as you can see from the console log screenshot attached). I am using telprompt:// to place calls and return back to app. Is this a bug?
The CXCallObserver delegate method is invoked whenever calls changed, and is invoked once when a call connects and then later if/when that call ends. The hasConnected and hasEnded properties should be interpreted as "has ever connected" and "has ever ended", respectively.
Thus, I recommend using logic such as this:
if (call.hasConnected) {
if (!call.hasEnded) {
// record start time (unless start time has already been recorded)
} else {
// record end time (unless end time has already been recorded)
}
}
I am able to observe the CNContactStoreDidChangeNotification when the contact database is changed while the app is in background state. I am pretty sure that only one observer was added to NSNotificationCenter.
The problem is NSNotificationCenter posts MULTIPLE times (2, 3, 5, and even more times) even if I only add one new contact.
Where is the problem?
Make certain you aren't adding the observer multiple times. This can happen without you realizing it if (for example) you call -addObserver from -viewDidLoad or -viewDidAppear in your view controller (as these might get called more than once throughout the life of your application), or from any of the application state callbacks in your app delegate (-applicationDidBecomeActive, -applicationWillResignActive, -applicationDidEnterBackground, -applicationWillEnterForeground, etc).
Wrap the call to -addObserver in a conditional that ensures it can only be called once (set a flag), and put NSLog statements around it so you can see in the debug console if you are getting there more than once. Search your code for other calls to -addObserver that you might have forgotten about.
Call -removeObserver before adding it, just to be sure (making sure to pass the same name and object as when you added it). Calling -removeObserver on an observer that doesn't exist is okay. Note that this is more of a band-aid than a fix - your code should be smart enough to know whether or not you've already added it - but this might help you diagnose the problem).
I just wrote a quick minimal test program that adds an observer (once!) on CNContactStoreDidChangeNotification and I only get the notification once when I add or change a contact. Write a similar test program for yourself and see if you get the same result. If your test program works correctly, then it is likely that your app is doing something you don't expect (and calling -addObserver multiple times).
I had the same problem, the number of times it fired varied between 2 & 3. The solution that worked for me was to set a semaphore variable, set in the handler and reset the semaphore when finished. Wrap the address book processing in an if statement on the semaphore to ignore further calls.
addressBkSemphore is reset to false in buildFrendsAndContacts
- (void)addressBkChange:(NSNotification *)note
{
if (addressBkSemphore == false)
{
addressBkSemphore = TRUE;
[self buildFrendsAndContacts];
}
}
Hope it helps.
You can start a one time execution timer or a dispatch after few seconds and cancel it in case there's a new contacts update within those seconds, thus ensuring that only the timer or dispatch_after triggered by the last update will actually execute (taking into account that all update calls come one after the other within under a sec. difference, as far as I tested)
And btw, I could reproduce the issue only when making change to contacts on the same device with my app. If I change the contacts on another device linked to the same apple account, there was only one update.
First, I am not asking internet reachability.
I have a lot internet requests in different places in my App. I want to show the ActivityIndicator on status bar, but I don't want to set
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES/NO
every time.
Is there a way I can detect my App is using the Internet?(Hook Methods or something?)
Thanks a lot!
Sadly — unless I'm behind the times — it's your own responsibility to keep track of this; there's no getter for quantity of network communications in flight and neither is there a notification or object you could observe to watch for changes.
Supposing you were just using NSURLSession, you might implement a function, YAURLCompletionForCompletion that takes a block of the form void (^)(NSURL *location, NSURLResponse *response, NSError *error) as a parameter and that increments a global activity count and returns another block of the same form which calls the original and then decrements the counter.
Display the spinner whenever the counter is non-zero. Always use YAURLCompletionForCompletion to wrap whatever completion handlers you pass when creating NSURLSessionDataTasks.
If you use AFNetworking, then AFNetworkActivityIndicatorManager is a good choice. You can implement similar function like that.
I am registering to receive updates from a CMMotionManager like so:
motionManager.startDeviceMotionUpdatesToQueue(deviceMotionQueue) {
[unowned self] (deviceMotion, error) -> Void in
// ... handle data ...
}
where deviceMotionQueue is an NSOperationQueue with the highest quality of service, i.e. the highest possible update rate:
self.deviceMotionQueue.qualityOfService = NSQualityOfService.UserInteractive
This means that I am getting updates often. Like really often. So I was wondering: what happens if I don't handle one update fast enough? If the update interval is shorter than the execution time of 'handle data'? Will the motion manager drop some information? Or will it queue up and after a while become run out of memory? Or is this not feasable at all?
It's hard to know what the internal CoreMotion implementation will do, and given that what it does is an "implementation detail", even if you could discern its current behavior, you wouldn't want to rely on that behavior moving forward.
I think the common solution to this is to do the minimum amount of work in the motion update handler, and then manage the work/rate-limiting/etc yourself. So, for instance, if you wanted to drop interstitial updates that arrived while you were processing the last update, you could have the update handler that you pass into CoreMotion do nothing but (safely) add a copy of deviceMotion to a mutable array, and then enqueue the "real" handler on a different queue. The real handler might then have a decision tree like:
if the array is empty, return immediately
otherwise (safely) take the last element, clear all elements from the array, and do the work based on the last element
This would have the effect of letting you take only the most recent reading, but also to have knowledge of how many updates were missed, and, if it's useful, what those missed updates were. Depending on your app, it might be useful to batch process the missed events as a group.
But the takeaway is this: if you want to be sure about how a system like this behaves, you have to manage it yourself.