GKTurnBasedMatch - Obtaining the End Date - ios

I am currently building an iPhone turn-based game that utilizes Game Center for all network functionality. I created a custom UI to display matches in a UITableView where the local player can enter, create, quit, and delete a game.
My issue is that in my cells, I want to display relevant dates (last turn taken, match created when no turn is taken yet, and match ended date for ended match status). For the life of me, I can't seem to figure out a good way to derive the exact date and time a match ended. The GKTurnBasedMatch object has the creationDate property which is great, but there is no property for when the match ended.
Currently I am just pulling the last turn date of one of the participants, but obviously that is not even close to optimal. I'm thinking the best workaround is to encode the current date in the matchData object sent when endMatchInTurn is called, but I'm hoping I'm missing a better solution somewhere in the API.
Thanks!
Corbin

After much research, there is no valid way to actually obtain the time when a GKTurnBasedMatch ended via the -endMatchInTurnWithMatchData method within the GameKit API. However, I do have a perfectly viable solution which just required a little bit of extra work. For whatever object you use to encode your matchData property, just assign another property and make it an NSDate. Then right before calling the endMatch method, set the new NSDate property to [NSDate date], which returns the current date and time, and archive it before sending as the matchData object. My own code is below:
GameState *stateToSave = [NSKeyedUnarchiver unarchiveObjectWithData:matchToQuit.matchData];
stateToSave.matchEndDate = [NSDate date];
NSData *endGameData = [NSKeyedArchiver archivedDataWithRootObject:stateToSave];
[matchToQuit endMatchInTurnWithMatchData:endGameData completionHandler:^(NSError *error) {
// Code
}

Related

is there any way to identify Unique IDs of UIElements in a view?

I know we can use TAG to identify the elements. But I am creating a dynamic library which gets injected to other app on a jailbroken iPhone and starts scraping data. So using tag is no option for me since I dont have the control.
I see object ID in storyboard is uniques for all elements. but it is not accessible in code and we cant get the element using that.
The problem is when I try to reproduce users recorded action, I dont know which button he clicked (same for all other UIElemetns).
Is there any other way or identifiers for UIElements to access at runtime?
You can use a timestamp to get unique ID's and assign to your view later:
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
NSNumber *timeStampObj = [NSNumber numberWithInt:timeStamp];
myView.tag = timeStampObj;

Cannot use a predicate that compares dates in Magical Record

I am making a method that will remove all of my NSManagedObjects that were not updated in the last sync.
- (void)removeStaleObjects {
// Delete objects that have not been updated in this sync.
NSPredicate *stalePredicate = [NSPredicate predicateWithFormat:#"updated < %#", self.syncStart];
NSArray *staleObjects = [Node MR_findAllWithPredicate:stalePredicate];
for (Node *n in staleObjects) {
[[NSManagedObjectContext MR_defaultContext] deleteObject:n];
}
}
The code keeps failing on the MR_findAll... line with
[__NSDate objCType]: unrecognized selector sent to instance
I have checked my syntax with the apple documentation and I am 99% positive that I am creating the predicate correctly, startDate is just
_startDate = [NSDate date];
that gets run prior to my sync. then after my sync I call
[self removeStaleObjects];
Does anyone know where I am messing up?
Update: I was able to get it to work by storing the update time as a double. However, I am still interested in getting it to work with NSDates so if anyone figures something out, please post it here.
The problem is the name "updated" of your attribute. It conflicts with the isUpdated method of NSManagedObject. (See Core Data NSPredicate "deleted == NO" does not work as expected for a similar issue with a "deleted" attribute.)
If you rename your attribute, everything works as expected.
It also looks to my that your predicate is formatted correctly. Here are a couple things you can do:
1) When debugging this, print out that predicate. You should see something like:
updatedDate < {some integer value}
Dates are stored as integers under the covers, and a predicate converts it properly as well. If your predicate isn't printable in the debugger, you'll know right away
2) Check your updatedDate type. Make sure that's a date (I trust it's already a date, but you didn't specify in your question)
3) Make sure your Node object has the updatedDate attribute on it.

Cancelling NSJSONSerialization - Search as you type, requests overlapping

Similar to the iPhone Facebook app search function, I am implementing search as you type functionality into my application although I have a problem when decoding the data into JSON format.
Basically what happens is because some searches take longer than others, they return at different intervals and this causes some small visual issues when the data is presenting on the screen.
I have set an NSLOG after each decode using NSJSONSerialization for the keyword 'industry'
2013-04-09 23:38:18.941 Project Name [42836:1d03] http://fooWebAddress/json/?method=search&limit=10&q=indus
2013-04-09 23:38:19.776 Project Name [42836:3e07] http://fooWebAddress/json/?method=search&limit=10&q=indu
2013-04-09 23:38:20.352 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=indust
2013-04-09 23:38:21.814 Project Name [42836:4e03] http://fooWebAddress/json/?method=search&limit=10&q=industr
2013-04-09 23:38:23.434 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=ind
2013-04-09 23:38:24.070 Project Name [42836:7503] http://fooWebAddress/json/?method=search&limit=10&q=industry
As you can see it is all out of order.
Does anyone have any way of stopping NSJSONSerialization for the previous connection.
Or possibly any other way to go about this problem?
Steps up to NSJSONSerialization...
NSURLRequest (initwithURL)
NSOperationQueue
NSURLConnection (asynchronous)
NSJSONSerialization
Thanks in advance.
When the user starts typing more text, you could cancel your previous connections and ignore any further delegate callbacks you receive from them. Then make the new request for the current text.
You can do this by maintaining some sort of lastRequest or lastOperation reference. When the user starts typing, call [self.lastRequestOrOperation cancel] and ignore any further notifications from that request with a check like if (request != self.lastRequest) { return; } in whatever callbacks you have.
However this has the problem that if the user keeps typing for a while you are constantly cancelling requests and they may not see any results until they have stopped typing.
A better solution would be to add sequencing so that each request is associated with an increasing sequence ID. You then only parse the result and update the UI when the sequence of the response is higher than the last one you received. If you receive any out-of-band responses from earlier, you just ignore them.
This is a much more complex issue than just being able to cancel the NSJSONSerialization. My suggestion is to use NSFetchedResultsController to populate your table view that shows the search results. Use the search term as one of the predicate variable in the NSFetchRequest attached to NSFetchedResultsController. And then, when you parse the results using NSJSONSerialization, store the results with the search term associated with that request. As soon as the search term changed (which you can detect when the user types more characters), re-create the NSFetchedResultsController and reload your table view. In addition, you can also try to cancel the call to parse the previous results if you launched it using performSelector:withObject:afterDelay. Beware that this cannot be always relied upon as the call may have been initiated by the time you are trying to cancel.
Kinda basic, but you could always maintain an nsdictionary of sub-classed NSURLRequests (sub-classed to provide a tag).
Start request - add request to dicationary with tag = array.count - 1, with key matching tag
Connection returns - is the request the most recent request, if so, parse json
Parse JSON - is the request the most recent request, if so, show results, if not, only display if there are no previous results displayed
Request handling - remove key from dictionary
most recent request = does the dictionary contain an object with a higher key value
Currently what you are doing is, you type each character and calling web-service. Why to call web-service for each letter you type. If user is type continuously, then it will increase the load, so call the web-service only when user stops for a particular interval of time. and then pass that string to call web-service or what ever method you are calling.
[NSObject cancelPerformSelectorsWithTarget:self]; // This will cancel your all req which is going to make when user typing without stopping
[self performSelector:#selector(sendSearchRequest) withObject:searchText afterDelay:0.1f]; // This will pass the string to call a web-service method, on which user hold for some time.

Adding a `lastModified` record to a Core Data managed object

An object needs to be submitted to the server, and I want to indicate to the user that the object needs to be submitted by displaying the lastModified date/time, and lastSubmitted date/time.
(Yes, the record must be manually submitted.)
I'm currently listening for NSManagedObjectContextObjectsDidChangeNotification, checking if the object's entity is RetailLocation, and if so, setting its lastModified date/time (of course, only if lastModified is not the only property being modified). Since this seems to highly confuse the undo manager, I use performSelector:SOMESEL withObject:retailLocation afterDelay:0.0 to set the lastModified property.
Sadly, this is almost even worse: this results in two actions being added to the undo stack!
Can someone recommend a nice way to implement a lastModified attribute in a Core Data-managed record? Alternatively, what am I missing?
If you don't want the modification date to be undoable, you can call disableUndoRegistration on your NSUndoManager before making changes, and enableUndoRegistration when you're done.
If you need one, you can get a pointer to the NSUndoManager by calling undoManager on your NSManagedObjectContext, but if you're working in iOS you should have one already.
Also, note Apple recommends using the NSManagedObjectContextWillSaveNotification notification for this, since changes might not necessarily be saved.

Sorting a NSSet of NSManagedObjects by a NSDate yields error

I am trying to pull in a RSS feed and sort by pubDate. When I examine the 'updated' property, most of the time it is correct and give me a proper date but when I try to convert from a set to a sorted array, I get random results from the sort. I've tracked this down to the fact that when sort is doing it's comparesion, the property (which is an NSDate, see figure1) is coming in and being compared as a __nscfnumber! (also figure2)
Any help or idea would be much appreciated.
figure1
figure2
I assume the comparator block is just for diagnostic purposes? You don't actually need to supply a comparator for NSDate or any of the provided attribute type classes.
If the debugger is reporting that the date1 object is of a NSNumber-cluster class type, then somewhere a NSCFNumber instance is being assigned to to the updated attribute. The debugger ignores factors like a cast and instead simply asked the object what its class is. If the object says it is a NSCFNumber then it is, regardless of how the code treats it otherwise.
Why that happens, I can't say based on the code provided.
You might try logging the value and class of the updated attribute before you attempt the sort to see if it reports properly. I would also recommend decomposing the entire line. Nesting all those method calls will work of course but it is error prone and hard to debug.

Resources