how to split out reverse geocoding components? - geocoding

anyone know how to split out like city, state and address from this code? It returns the entire address, but i only want city and state.
//Geocoding Block
[_geoCoder2 reverseGeocodeLocation: _currentLocation2.location completionHandler:
^(NSArray *placemarks, NSError *error) {
//Get nearby address
CLPlacemark *placemark = [placemarks objectAtIndex:0];
//String to hold address
NSString *locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
//Print the location to console
NSLog(#"I am currently at %#",locatedAt);
//Set the label text to current location
[_cityLabel setText:locatedAt];
}];

CLPlacemark has properties such as locality and administrativeArea. See the docs to learn what they are, but you'll want to experiment to see how they parse out the address into its components. Also, the addressDictionary is in address book format, so there are keys for city and state inside it; your mistake is turning it into a string rather than examining the structure of the dictionary.

// Reverse Geocoding
NSLog(#"Resolving the Address");
[_geoCoder2 reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
_cityLabel.text = [NSString stringWithFormat:#"%#\n%#\n",
placemark.locality,
placemark.administrativeArea];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];

Related

CloudKit - exception on CKRecord setObject: forKey:

I'm trying to add iCloud syncing to my game, by storing save data filename as a key, and the file in a CKAsset. However, the program always crashes when it tries to setObject: forKey: on the CKRecord, even if I use a simple dummy string instead of the file asset.
If I don't assign any objects to the CKRecord, the record successfully saves to iCloud, as I can see the record with the correct name in the iCloud Dashboard.
Nothing is logged to the debugger output when the exception is thrown. What could cause this crash?
bool iCloudSync::UploadToCloud( SaveDataManager::CloudOperationComplete Callback, void *UserData, std::vector< const char * > *PathsToUpload )
{
m_UploadCallback = Callback;
m_UploadCallbackUserData = UserData;
if (PathsToUpload == NULL) return false;
// TODO: [[CKContainer defaultContainer] accountStatusWithCompletionHandler] to check if there is a signed-in icloud user
CKDatabase *db = [[CKContainer defaultContainer] privateCloudDatabase];
CKRecord *record = [[CKRecord alloc] initWithRecordType:#"SaveDataFiles"];
for (int i = 0; i < PathsToUpload->size(); i++) {
NSString *filenameString = [NSString stringWithCString:(*PathsToUpload)[i] encoding:NSASCIIStringEncoding];
NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *fullPathURL = [documentsURL URLByAppendingPathComponent:filenameString];
NSError *error = nil;
bool reachable = [fullPathURL checkResourceIsReachableAndReturnError:&error];
if (reachable) {
CKAsset *fileAsset = [[CKAsset alloc] initWithFileURL:fullPathURL];
// CRASH HERE Trying to assign any value to a key
// record[filenameString] = fileAsset;
[record setObject:#"Dummy test string" forKey:filenameString];
}
}
// TODO: completion handler
// TODO: always overwrite remote
[db saveRecord:record completionHandler:nil];
// CKModifyRecordsOperation *modify = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:[NSArray arrayWithObject:record] recordIDsToDelete:nil];
// Success!
return true;
}
The error that was logged was:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'recordKey (gamestate1.dat) contains invalid characters'
The reason nothing was being logged was because my exception breakpoint was getting triggered several times in a row before the logging actually happened. I just needed to keep pressing continue before it logged the exception output.
So, I just need to find some other key I can use that doesn't include a dot, which is frustratingly an invalid character.
For reference, the valid characters are that the first character must be alphabetical, subsequent characters are alphanumeric or underscores. Here is Apple's phrasing:
Key names consist of one or more alphanumeric characters and start with a letter. You may also include underscore characters if you do not use an underscore as the first character in the name. Spaces are not allowed in key names. The names of your keys must not match the names of any properties of this class.

How do I get element from NSArray of NSDictionary

This is NSLog of my NSArray
[{"id":16,"venueId":16,"street":"171 - 3401 Dufferin St","city":"Toronto","zipcode":"M6A 2T9","province":"ON","country":"Canada"}]
NSDictionary *dict = [myarray objectAtIndex:i]
//myarray is your array of dictionary
//if the array has just one element like in your example, i will be 0
NSNumber *venueId = [dict objectForKey:#"venueId"];
finally I found solution
NSError *error;
NSArray* jsonArray = [NSJSONSerialization JSONObjectWithData:[[venue objectForKey:#"address"] dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error] ;
NSDictionary *dict = [jsonArray objectAtIndex:0];
//myarray is your array of dictionary
NSString *street = [dict objectForKey:#"street"];
NSLog(#"street: %#", street);
Note: I used below code to check data type to make sure it returns valid kind of class.
if ([[venue objectForKey:#"address"] isKindOfClass:[NSArray class]]) {
NSLog(#"%#", #"It is NSArray");
} else if ([[venue objectForKey:#"address"] isKindOfClass:[NSString class]]) {
NSLog(#"%#", #"It is NSString");
}

Decoded response in Java ME (Nokia Asha)

I am implementing small Java ME app. This app gets some data from 3rd patty resource and needs to be authenticated before. I do first call for get cookies (it was easy), and the second call with this cookies for get data. I googled a little how to do it, and found next solution - Deal with cookie with J2ME
I have changed this code to next for my purpose:
public void getData(String url,String cookie) {
HttpConnection hpc = null;
InputStream is = null;
try {
hpc = (HttpConnection) Connector.open(url);
hpc.setRequestProperty("cookie", cookie);
hpc.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
hpc.setRequestProperty("Accept-Encoding", "gzip, deflate");
hpc.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
is = hpc.openInputStream();
int length = (int) hpc.getLength();
byte[] response = new byte[length];
is.read(response);
String strResponse = new String(response);
} catch (Exception e) {
System.out.println(e.getMessage() + " " + e.toString());
} finally {
try {
if (is != null)
is.close();
if (hpc != null)
hpc.close();
} catch (Exception e) {}
}
}
I get something like to the next
??ÑÁNÃ0à;O±(²§M}A-?#
.?PYS¨Ôe¥Í#\üìde??XÊo}Vâ]hk?­6ëµóA|µvÞz'Íà?wAúêmw4í0?ÐÆ?ÚMW=?òêz CÛUa:6Ö7¼T?<oF?nh6[_0?l4?äê&)?çó³?ÅÕúf¨ä(.? ªDÙ??§?ÊP+??(:?Á,Si¾ïA¥ã-jJÅÄ8ÊbBçL)gs.S.þG5ÌÀÆéX}CÁíÑ-þ?BDK`²?\¶?ó3I÷ô±e]°6¬c?q?Ó?¼?Y.¯??Y?%?ÏP1è?ìw;?È Ò??e
|ôh0?
How can I decode this?
Stupid me. I didn't take to consideration next code: hpc.setRequestProperty("Accept-Encoding", "gzip, deflate"); I get coded in ZIP response and everything that I need it decode it.

Synchronize IOS core data with web service?

Here is my problem:
I want to use core data - speed and connectivity issues to build my IOS app. The data stored in core data is coming from a SQLServer database which I can access through a yet-to-be-defined web service.
Any changes to the data stored in core data needs to be synchronized with the SQLServer via a web service. In addition, I need to buffer changes that don't get synchronized because of connectivity issues.
I also need to update core data with any changes that have occured on the server. This could happen on a schedule set in user preferences.
Solutions I've Explored:
Using NSIncrementalStore class (new in IOS 5). I'm very confused on what this does exactly but it sounds promising. From what I can tell, you subclass NSIncrementalStore which allows you to intercept the regular core data API calls. I could then pass on the the information to core data as well as sync it with the external database via a web service. I could be completely wrong. But assuming I'm right, how would I sync deltas if the connection to the internet is down?
AFIncrementalStore - This is a subclass off of NSIncrementalStore using AFNetworking to do the web services piece.
RestKit - I'm a little concerned on how active this API is and it seems to be going through a transition to block functionality. Has anyone used this extensively?
I'm leaning towards AFIncrementalStore since this is using (what seems to be) a more standard approach. The problem is, I could be completely off on what NSIncrementalStore really is.
A link to some sample code or tutorial would be great!
My solution to this was to store two copies of the data set in a CoreData database. One represents the last-known server state and is immutable. The other is edited by the user.
When it is time to sync changes, the app creates a diff between the edited and immutable copies of the data. The app sends the diff to a web service which applies the diff to its own copy of the data. It replies with a full copy of the data set, which the app overwrites onto both of its copies of the data.
The advantages are:
If there is no network connectivity, no changes are lost: the diff is calculated each time the data set needs to be sent, and the immutable copy is only changed on a successful sync.
Only the minimum amount of information that needs to be sent is transmitted.
Multiple people can edit the same data at the same time without using locking strategies with a minimum opportunity for data loss via overwrites.
The disadvantages are:
Writing the diffing code is complex.
Writing the merging service is complex.
Unless you are a metaprogramming guru, you'll find that your diff/merge code is brittle and has to change whenever you change your object model.
Here are some of the considerations I had when coming up with the strategy:
If you allow changes to be made offline, checkin/checkout locking won't work (how can you establish a lock with no connection?).
What happens if two people edit the same data at the same time?
What happens if one person edits data on one iOS device when connectionless, switches it off, edits on another device and then turns the original device back on?
Multithreading with CoreData is an entire problem class in itself.
The closest thing I've heard of to out-of-the-box support to do anything remotely like this is the new iCloud/CoreData syncing system in iOS6, which automatically transmits entities from a CoreData database to iCloud when they change. However, that means you have to use iCloud.
EDIT: This is very late, I know, but here's a class that is capable of producing a diff between two NSManagedObject instances.
// SZManagedObjectDiff.h
#interface SZManagedObjectDiff
- (NSDictionary *)diffNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject
#end
// SZManagedObjectDiff.m
#import "SZManagedObjectDiff.h"
#implementation SZManagedObjectDiff
- (NSDictionary *)diffNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject {
NSDictionary *attributeDiff = [self diffAttributesOfNewObject:newObject withOldObject:oldObject];
NSDictionary *relationshipsDiff = [self diffRelationshipsOfNewObject:newObject withOldObject:oldObject];
NSMutableDictionary *diff = [NSMutableDictionary dictionary];
if (attributeDiff.count > 0) {
diff[#"attributes"] = attributeDiff;
}
if (relationshipsDiff.count > 0) {
diff[#"relationships"] = relationshipsDiff;
}
if (diff.count > 0) {
diff[#"entityName"] = newObject ? newObject.entity.name : oldObject.entity.name;
NSString *idAttributeName = newObject ? newObject.entity.userInfo[#"id"] : oldObject.entity.userInfo[#"id"];
if (idAttributeName) {
id itemId = newObject ? [newObject valueForKey:idAttributeName] : [oldObject valueForKey:idAttributeName];
if (itemId) {
diff[idAttributeName] = itemId;
}
}
}
return diff;
}
- (NSDictionary *)diffRelationshipsOfNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject {
NSMutableDictionary *diff = [NSMutableDictionary dictionary];
NSDictionary *relationships = newObject == nil ? [[oldObject entity] relationshipsByName] : [[newObject entity] relationshipsByName];
for (NSString *name in relationships) {
NSRelationshipDescription *relationship = relationships[name];
if (relationship.deleteRule != NSCascadeDeleteRule) continue;
SEL selector = NSSelectorFromString(name);
id newValue = nil;
id oldValue = nil;
if (newObject != nil && [newObject respondsToSelector:selector]) newValue = [newObject performSelector:selector];
if (oldObject != nil && [oldObject respondsToSelector:selector]) oldValue = [oldObject performSelector:selector];
if (relationship.isToMany) {
NSArray *changes = [self diffNewSet:newValue withOldSet:oldValue];
if (changes.count > 0) {
diff[name] = changes;
}
} else {
NSDictionary *relationshipDiff = [self diffNewObject:newValue withOldObject:oldValue];
if (relationshipDiff.count > 0) {
diff[name] = relationshipDiff;
}
}
}
return diff;
}
- (NSDictionary *)diffAttributesOfNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject {
NSMutableDictionary *diff = [NSMutableDictionary dictionary];
NSArray *attributeNames = newObject == nil ? [[[oldObject entity] attributesByName] allKeys] : [[[newObject entity] attributesByName] allKeys];
for (NSString *name in attributeNames) {
SEL selector = NSSelectorFromString(name);
id newValue = nil;
id oldValue = nil;
if (newObject != nil && [newObject respondsToSelector:selector]) newValue = [newObject performSelector:selector];
if (oldObject != nil && [oldObject respondsToSelector:selector]) oldValue = [oldObject performSelector:selector];
newValue = newValue ? newValue : [NSNull null];
oldValue = oldValue ? oldValue : [NSNull null];
if (![newValue isEqual:oldValue]) {
diff[name] = #{ #"new": newValue, #"old": oldValue };
}
}
return diff;
}
- (NSArray *)diffNewSet:(NSSet *)newSet withOldSet:(NSSet *)oldSet {
NSMutableArray *changes = [NSMutableArray array];
// Find all items that have been newly created or updated.
for (NSManagedObject *newItem in newSet) {
NSString *idAttributeName = newItem.entity.userInfo[#"id"];
NSAssert(idAttributeName, #"Entities must have an id property set in their user info.");
id newItemId = [newItem valueForKey:idAttributeName];
NSManagedObject *oldItem = nil;
for (NSManagedObject *setItem in oldSet) {
id setItemId = [setItem valueForKey:idAttributeName];
if ([setItemId isEqual:newItemId]) {
oldItem = setItem;
break;
}
}
NSDictionary *diff = [self diffNewObject:newItem withOldObject:oldItem];
if (diff.count > 0) {
[changes addObject:diff];
}
}
// Find all items that have been deleted.
for (NSManagedObject *oldItem in oldSet) {
NSString *idAttributeName = oldItem.entity.userInfo[#"id"];
NSAssert(idAttributeName, #"Entities must have an id property set in their user info.");
id oldItemId = [oldItem valueForKey:idAttributeName];
NSManagedObject *newItem = nil;
for (NSManagedObject *setItem in newSet) {
id setItemId = [setItem valueForKey:idAttributeName];
if ([setItemId isEqual:oldItemId]) {
newItem = setItem;
break;
}
}
if (!newItem) {
NSDictionary *diff = [self diffNewObject:newItem withOldObject:oldItem];
if (diff.count > 0) {
[changes addObject:diff];
}
}
}
return changes;
}
#end
There's more information about what it does, how it does it and its limitations/assumptions here:
http://simianzombie.com/?p=2379
Use the Parse platform and its IOS SDK to structure and store info. It can cache data locally so you can retrieve it quickly and when there is no connectivity.

Exception when parsing an array in JSON

When I try to parse an array returned from my web-service I got this exception:
2011-05-03 23:28:10.021 -JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=11 \"Unexpected end of string\" UserInfo=0x803d8b0 {NSLocalizedDescription=Unexpected end of string}"
)
Here is my code:
-(void)requestFinished:(ASIHTTPRequest *)request
{
if(request.responseStatusCode==200)
{
//parse the response
NSArray *array=[[request responseString]JSONValue];
listeTypesDesCarburants=[array objectAtIndex:0];
listeDesEnseignes=[array objectAtIndex:1];
}
}
listeTypesDesCarburants and listeDesEnseignes are both a NSArray
the web-services returned me an array which is composed of two arrays:
$finalArray=array($array1,$array2);
sendResponse(200,json_encode($finalArray));
Edit:
Here is my method to parse the response :
-(void)requestFinished:(ASIHTTPRequest *)request
{
if(request.responseStatusCode==200)
{
//parse the response
NSArray *array=[[request responseString]JSONValue];
listeTypesDesCarburants=[array objectAtIndex:0];
listeDesEnseignes=[array objectAtIndex:1];
}
else
{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"TopStation"
message:#"Unexpected error"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
If I try to do this:
NSLog(#"%d",[array count]);
It gives me 0, what means that the array doesn't even received the objects, am I right?