Load and save NSMutableArray won't work - objective-c

first of all, I have a class which mamages an NSMutableArray.
When the class is instantiated, it should look if there is already a saved array and load it, or otherwise made a new one.
everytime an item is added it should be saved. but: nothing happens.
#import "NEList.h"
#interface NEList()
#end
#implementation NEList
#synthesize theInternArray;
-(id) initWithArray {
self = [super init];
if(self != nil) {
NSLog(#"build");
theInternArray = [[NSMutableArray alloc] initWithCapacity:20];
return self;
}
return nil;
}
-(id) initWithContent {
self = [super init];
if(self != nil) {
NSLog(#"load");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"theFiles"];
theInternArray = [NSMutableArray arrayWithContentsOfFile:filePath];
if(theInternArray == nil) {
theInternArray = [[NSMutableArray alloc] initWithCapacity:200];
}
NSLog(#"second %#", theInternArray);
return self;
}
return nil;
}
-(BOOL) save {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"theFiles"];
return [self.theInternArray writeToFile:filePath atomically:NO];
}
-(BOOL) addObject:(NEListItem *)theItem {
[theInternArray addObject:theItem]; [self save];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
localNotif.fireDate = theItem.theBestBeforeDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = [theItem.theName stringByAppendingString:#" expires!"];
localNotif.alertAction = NSLocalizedString(#"View Details", nil);
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
return true;
}
-(NEListItem *) getElementAtIndex:(NSUInteger)theIndex {
return [theInternArray objectAtIndex:theIndex];
}
-(BOOL)removeObjectByName:(NSString *)theName {
for (NEListItem *tempItem in theInternArray) {
if([tempItem.theName isEqualToString:theName]) {
[theInternArray removeObject:tempItem];
break;
return true;
}
}
NSLog(#"Nicht gefunden");
return false;
}
#end
the save method is called in another class which owns an instance of NEList

Ok, all I changed was the "initWithContent" Method and the save method. I've commented out your code and under it made the changes to use NSUserDefaults. NSUserDefaults should save a binary file of your Array and later get it back and convert it back to a NSArray. If this doesn't work just let me know what error your getting.
-(id) initWithContent {
self = [super init];
if(self != nil) {
NSLog(#"load");
/*
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"theFiles"];
theInternArray = [NSMutableArray arrayWithContentsOfFile:filePath];
if(theInternArray == nil) {
theInternArray = [[NSMutableArray alloc] initWithCapacity:200];
}
NSLog(#"second %#", theInternArray);*/
NSUserDefaults *uDefaults = [NSUserDefaults standardUserDefaults];
theInternArray = [uDefaults objectForKey:#"internArray"];
if (!theInternArray)
{
theInternArray = [[NSMutableArray alloc] initWithCapacity:200];
}
NSLog(#"%#", theInternArray);
return self;
}
return nil;
}
-(BOOL) save {
/*NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"theFiles"];*/
NSUserDefaults *uDefaults = [NSUserDefaults standardUserDefaults];
[uDefaults setObject:theInternArray forKey:#"internArray"];
//return [self.theInternArray writeToFile:filePath atomically:NO];
return [uDefaults objectForKey:#"internArray"];
}
Oh, and the reason why your way didn't work is because it's not that simple to save a file then get it back. You would need to print out your data from the array (like "item1,item2,item3, etc." to the file, then parse it and create a NSArray with that data later.

So, this is the solution worked for me.
First of all, this is my custom class which is stored in the arrays:
#import <Foundation/Foundation.h>
#interface NEListItem : NSObject <NSCoding>
#property (nonatomic, strong) NSString *theName;
#property (nonatomic, strong) NSString *theBestBeforeDate;
#property (nonatomic, strong) NSDate *theInternDate;
-(id) initWithName:(NSString *) theInitName;
#end
and the implementation
#import "NEListItem.h"
#implementation NEListItem
#synthesize theName = _theName;
#synthesize theBestBeforeDate = _theBestBeforeDate;
#synthesize theInternDate = _theInternDate;
-(id)initWithName:(NSString *)theInitName {
self = [super init];
if(self != nil) {
self.theName = theInitName;
return self;
}
return nil;
}
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeObject:self.theName forKey:#"theName"];
[coder encodeObject:self.theBestBeforeDate forKey:#"theBBDate"];
[coder encodeObject:self.theInternDate forKey:#"theInternDate"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[NEListItem alloc] init];
if (self != nil)
{
self.theName = [coder decodeObjectForKey:#"theName"];
self.theInternDate = [coder decodeObjectForKey:#"theInternDate"];
self.theBestBeforeDate = [coder decodeObjectForKey:#"theBBDate"];
}
return self;
}
#end
so, this is needed for saving custom values.
the save method:
-(BOOL) save {
NSLog(#"save called");
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:theInternArray] forKey:#"savedArray"];
return true;
}
and the loading which is part of a init method
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:#"savedArray"];
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil) {
theInternArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
return self;
}
else
theInternArray = [[NSMutableArray alloc] initWithCapacity:200];
return self;
}
many thanks to ManOx which helped me a lot

Related

Error message is saying my data is NULL - NSKeyedUnArchiver - I've followed all the steps - still won't work

I want to save an NSMutableArray *allRedItems to a file. It contains custom objects, Itemz :
#interface Itemz : NSObject <NSCoding>
#property double price;
#property double quality;
#property double style;
#property double overallAverage;
I've done all the right steps so far:
#implementation Itemz
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeDouble:self.price forKey:#"price"];
[encoder encodeDouble:self.style forKey:#"style"];
[encoder encodeDouble:self.quality forKey:#"quality"];
[encoder encodeDouble:self.overallAverage forKey:#"overallAverage"];
[encoder encodeBool: self.isClicked forKey:#"isClicked"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
//decode properties, other class vars
self.price = [decoder decodeDoubleForKey:#"price"];
self.style = [decoder decodeDoubleForKey:#"style"];
self.quality = [decoder decodeDoubleForKey:#"quality"];
self.overallAverage = [decoder decodeDoubleForKey:#"overallAverage"];
self.isClicked = [decoder decodeBoolForKey:#"isClicked"];
}
return self;
}
#end
Here is where I saved my array *allRedItems
#implementation AllRedItems
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.allRedItems];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *allItemsRed = [documentsDirectory stringByAppendingPathComponent:#"allItemsRed"];
[data writeToFile:allItemsRed atomically:YES];
#end
When I retrieve it, it gives me this error - [NSKeyedUnarchiver initForReadingWithData:]: data is NULL
#implementation ItemSuggestion
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:#"allItemsRed"];
NSData * data = [NSData dataWithContentsOfFile:path];
NSMutableArray *allRedItems = [NSKeyedUnarchiver unarchiveObjectWithData:data];
#end
Am I missing something? Or do I need to add something?
You save it in NSDocumentationDirectory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
But retrieve it from NSDocumentDirectory, so you can't get it.
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Use NSDocumentDirectory in the two methods.

issues reading from plist file

I have created a simple plist file with some user preferences for a card game I'm writing.
I have also created a controller that reads and writes to this plist file which is a singelton.
everything works fine, but then after a couple of tries it stops working.
Logging the values to the console it shows the list returning a value of 0 which causes my app to crash
I have deleted the plist and created a new one and then the same story, works fine for 2 or three time and then boom zero.
here is a copy of the controller singelton code:
#implementation userOptionsController
static userOptionsController* _sharedOptionsController = nil;
#synthesize backgroundSound=_backgroundSound;
#synthesize soundEffects = _soundEffects;
#synthesize coach = _coach;
#synthesize numberOfDecks = _numberOfDecks ;
+(userOptionsController*)sharedOptionsController{
#synchronized([userOptionsController class])
{
if(!_sharedOptionsController)
[[self alloc]init];
return _sharedOptionsController;
}
return nil;
}
+(id)alloc
{
#synchronized ([userOptionsController class])
{
NSAssert(_sharedOptionsController == nil, #"Attempted to allocate a second instance of userOptionsController singleton");
_sharedOptionsController = [super alloc];
return _sharedOptionsController;
}
return nil;
}
- (id) init {
self = [super init];
if (self) {
}
return self;
}
-(void)readPlistFile
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"playerPrefOptions" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
NSMutableDictionary *temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
self.backgroundSound = [[temp objectForKey:#"backgroundSounds"]boolValue];
self.soundEffects = [[temp objectForKey:#"soundEffects"]boolValue];
self.coach =[[temp objectForKey:#"coach"]boolValue];
self.numberOfDecks = [[temp objectForKey:#"numberOfDecks"]intValue];
}
-(void)writeOptionsToFile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSMutableDictionary *infoDict = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSNumber *moshe = [NSNumber numberWithInt:self.numberOfDecks];
[infoDict setObject: moshe forKey:#"numberOfDecks"];
[infoDict setObject:[NSNumber numberWithBool:self.coach] forKey:#"coach"];
[infoDict setObject:[NSNumber numberWithBool:self.backgroundSound] forKey:#"backgroundSounds"];
[infoDict setObject:[NSNumber numberWithBool:self.soundEffects] forKey:#"soundEffects"];
[infoDict writeToFile:path atomically:YES];
}
#end
so the property :
int numberOfDecks =[userOptionsController sharedOptionsController].numberOfDecks;
will return zero.
any ideas?
thanks.
Rather than use a plist for this content, it looks like NSUserDefaults is a more appropriate location.
Instead of shipping the app with a default plist file, instead just registerDefaults: with NSUserDefaults (often done in your app delegate application:didFinishLaunchingWithOptions:).
Then, whenever any changes are made just update NSUserDefaults and call synchronize to save the changes.
Try this and see what it does (what logs are output):
#implementation userOptionsController
+ (userOptionsController*)sharedOptionsController
{
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
- (id) init {
self = [super init];
if (self) {
}
return self;
}
-(void)readPlistFile
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"playerPrefOptions" ofType:#"plist"];
if (![fileManager copyItemAtPath:bundle toPath: path error:&error]) {
NSLog(#"ERROR - file couldn't be copied: %#", error);
}
}
NSMutableDictionary *temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
if (temp == nil) {
NSLog(#"ERROR - file couldn't be read");
}
self.backgroundSound = [[temp objectForKey:#"backgroundSounds"]boolValue];
self.soundEffects = [[temp objectForKey:#"soundEffects"]boolValue];
self.coach =[[temp objectForKey:#"coach"]boolValue];
self.numberOfDecks = [[temp objectForKey:#"numberOfDecks"]intValue];
}
-(void)writeOptionsToFile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSMutableDictionary *infoDict = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSNumber *moshe = [NSNumber numberWithInt:self.numberOfDecks];
[infoDict setObject: moshe forKey:#"numberOfDecks"];
[infoDict setObject:[NSNumber numberWithBool:self.coach] forKey:#"coach"];
[infoDict setObject:[NSNumber numberWithBool:self.backgroundSound] forKey:#"backgroundSounds"];
[infoDict setObject:[NSNumber numberWithBool:self.soundEffects] forKey:#"soundEffects"];
if (![infoDict writeToFile:path atomically:YES]) {
NSLog(#"ERROR - failed to write the new file (%#)", path);
} else {
NSLog(#"Completed write of:\n%#", infoDict);
}
}
#end

Saving to plist file issue

I can't save my new data to plist file for some reason. This is code I have been using for saving data:
-(void)saveData:(NSMutableDictionary *)dictionaryData toFile:(NSString *)filename {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *path = [docDir stringByAppendingPathComponent:filename];
NSMutableArray *data = [[NSMutableArray alloc] initWithContentsOfFile:path];
[data addObject:dictionaryData];
[data writeToFile:filename atomically:YES];
}
this is code I used to copy file from bundle to app directory in case if it is not there :
-(NSMutableArray *)loadFromFile:(NSString *)filename {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *path = [docDir stringByAppendingPathComponent:filename];
NSFileManager *fileMgr = [NSFileManager defaultManager];
if(![fileMgr fileExistsAtPath:path]) {
NSArray *fileArray = [filename componentsSeparatedByString:#"."];
NSString *name = [fileArray objectAtIndex:0];
NSString *ext = [fileArray objectAtIndex:1];
NSString *bundle = [[NSBundle mainBundle] pathForResource:name ofType:ext];
[fileMgr copyItemAtPath:bundle toPath:path error:&error];
}
NSMutableArray *data = [[NSMutableArray alloc] initWithContentsOfFile:path];
return data;
}
For some reason I can't save new data to plist file. When I try to add new NSMutableDictionary object to my plist file (with saveData:toFile: method) and than reload my array variable with the plist file data - new object is not there. Am I doing something wrong?
this is how I load plist file :
#property (nonatomic, strong) NSMutableArray *modules;
#property (nonatomic, strong) NSMutableDictionary *module;
- (void)viewDidLoad {
[super viewDidLoad];
self.modules = [self loadFromFile:#"ModulesList.plist"];
self.module = [self.modules objectAtIndex:0];
for (int i = 0; i < self.modules.count; i++ ) {
NSLog(#"Modules array from plist file, module at index %i : %#",i, [self.modules objectAtIndex:i]);
}
than for testing purpose I have this code to add new module object:
- (IBAction)leftButton:(id)sender {
NSString *mytitle = [[NSString alloc] initWithFormat:#"my title"];
NSString *myauthor = [[NSString alloc] initWithFormat:#"my author2"];
NSUInteger myean = 22023423;
NSString *mytitle2 = [[NSString alloc] initWithFormat:#"my title 2"];
NSString *myauthor2 = [[NSString alloc] initWithFormat:#"my author2"];
NSUInteger myean2 = 29032432;
NSString *mytitle3 = [[NSString alloc] initWithFormat:#"my title 3"];
NSString *myauthor3 = [[NSString alloc] initWithFormat:#"my author 3"];
NSUInteger myean3 = 21023423;
NSMutableDictionary *mybook = [[NSMutableDictionary alloc] init];
NSMutableDictionary *mybook2 = [[NSMutableDictionary alloc] init];
NSMutableDictionary *mybook3 = [[NSMutableDictionary alloc] init];
[mybook setObject:mytitle forKey:#"title"];
[mybook setObject:myauthor forKey:#"author"];
[mybook setObject:[NSNumber numberWithInteger:myean] forKey:#"ean"];
[mybook2 setObject:mytitle2 forKey:#"title"];
[mybook2 setObject:myauthor2 forKey:#"author"];
[mybook2 setObject:[NSNumber numberWithInteger:myean2] forKey:#"ean"];
[mybook3 setObject:mytitle3 forKey:#"title"];
[mybook3 setObject:myauthor3 forKey:#"author"];
[mybook3 setObject:[NSNumber numberWithInteger:myean3] forKey:#"ean"];
NSMutableArray *mybooks = [[NSMutableArray alloc] init];
[mybooks addObject:mybook];
[mybooks addObject:mybook2];
[mybooks addObject:mybook3];
[self.module setObject:mybooks forKey:#"books"];
[self.modules addObject:self.module];
for (int i = 0; i < self.modules.count; i++ ) {
NSLog(#"Modules array after add operation, module at index: %i: %#",i, [self.modules objectAtIndex:i]);
}
[self saveData:self.module toFile:#"ModulesList.plist"];
}
than when I will reload my self.modules array from plist with button action, my new data is not there:
- (IBAction)reload:(id)sender {
self.modules = [self loadFromFile:#"ModulesList.plist"];
for (int i = 0; i < self.modules.count; i++ ) {
NSLog(#"RELOAD: Modules array from plist file, module at index %i : %#",i,[self.modules objectAtIndex:i]);
}
}
this is screenshot of my plist file : http://dl.dropbox.com/u/49076351/Screen%20Shot%202013-02-27%20at%2016.27.45.png

iOS: Saving A Picture In UIImageView

I have an app that allows the user to choose a picture from their camera roll, and display it in a UIImageView. I usually use this method to save text in text fields, and I assumed that it would work for an image as well, but I'm having some issues with it. There are no errors, but it simply does not save the image.
This is the relevant code I'm using:
.h:
#define kFilename9 #"PGdata.plist"
...
- (NSString *)dataFilePath;
.m:
- (NSString *)dataFilePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename9];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification {
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:image.image];
[array writeToFile:[self dataFilePath] atomically:YES];
}
- (void)viewDidLoad
{
...
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
image.image = [array objectAtIndex:0];
}
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app];
[super viewDidLoad];
}
You have to convert the UIImage to a PNG or JPG first, using UImagePNGRepresentation or UIImageJPEGRepresentation. Those function return NSData which you can then write to a file.
You can save by following this way。
UIImage * image;//the image you want to save
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir=[paths objectAtIndex:0];
NSFileManager *filemanager=[NSFileManager defaultManager];
NSData * imagedata=UIImageJPEGRepresentation(image,1);
NSString *savePath= [docDir stringByAppendingPathComponent:#"imageName.jpg"];
BOOL isdic=NO;
BOOL isHave=[filemanager fileExistsAtPath:savePath isDirectory:&isdic];
if (isHave==YES&&isdic==NO) {
[filemanager removeItemAtPath:savePath error:nil];
}
BOOL result= [imagedata writeToFile:savePath atomically:YES];

How to Add Multiple Placemarks and Annotations to Map

I have a class that loads a map, get my current location, then does a search on my database for companies in an area based on a zip code radius. I am doing a for loop to loop through each address, forward geocode, now I want to put a placemark and annotation for each location. How can I accomplish this. Here is my code:
- (void)locationUpdate:(CLLocation *)location {
locationLabel.text = [location description];
NSNumber *lat = [[NSString alloc] initWithFormat:#"%g", location.coordinate.latitude];
float latValue = [lat floatValue];
NSNumber *lng = [[NSString alloc] initWithFormat:#"%g", location.coordinate.longitude];
float lngValue = [lng floatValue];
mapView=[[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.showsUserLocation=TRUE;
mapView.mapType=MKMapTypeStandard;
mapView.delegate=self;
/*Region and Zoom*/
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.2;
span.longitudeDelta=0.2;
CLLocationCoordinate2D location1=mapView.userLocation.coordinate;
location1.latitude=latValue;
location1.longitude=lngValue;
region.span=span;
region.center=location1;
/*Geocoder Stuff*/
geoCoder=[[MKReverseGeocoder alloc] initWithCoordinate:location1];
geoCoder.delegate=self;
[geoCoder start];
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
[self.view insertSubview:mapView atIndex:0];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geoCoder didFindPlacemark:(MKPlacemark *)placemark
{
NSDictionary *zipDic = [placemark addressDictionary];
NSString *zipCode = [zipDic objectForKey:#"ZIP"];
NSString *post = [NSString stringWithFormat:#"zip=%#", zipCode];
NSString *hostString = #"https://www.mysite.com/searchzip.php?";
// Append string and add percent escapes
hostString = [[hostString stringByAppendingString:post] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *hostURL = [NSURL URLWithString:hostString];
NSString *jsonString = [[NSString alloc] initWithContentsOfURL:hostURL];
self.zipArray = [jsonString JSONValue];
NSLog(#"%#", zipArray);
for (NSString *sZip in zipArray) {
NSString *lblAddress = [sZip objectForKey:#"address"];
NSString *hostStr = [[#"http://maps.google.com/maps/geo?q=" stringByAppendingString:lblAddress]stringByAppendingString:#"&key=ABQIAAAA1KqXKe5yJPkX6ii6Ud K-0RSIvIZDM4KnjydqrehqKK56hFf_fxQc0uyCKoh-4i77-5B0Qfc8Gs223Q&sensor=false&output=json"];
hostStr = [hostStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *hostURL = [NSURL URLWithString:hostStr];
NSString *jsonString = [[NSString alloc] initWithContentsOfURL:hostURL];
SBJSON *parser = [[SBJSON alloc] init];
// parse the JSON string into an object - assuming json_string is a NSString of JSON data
NSArray *object = [parser objectWithString:jsonString error:nil];
NSArray *placemarks = [object objectForKey:#"Placemark"];
NSDictionary *mark = [placemarks objectAtIndex:0];
NSDictionary *point = [mark objectForKey:#"Point"];
NSArray *coordinates = [point objectForKey:#"coordinates"];
NSNumber *lat = (NSNumber*)[coordinates objectAtIndex:0];
float latValue = [lat floatValue];
NSNumber *lon = (NSNumber*)[coordinates objectAtIndex:1];
float lonValue = [lon floatValue];
//Here is where I would put placemarks and annotations
}
}
- (void)locationError:(NSError *)error {
locationLabel.text = [error description];
}
#end
I tried...
CLLocationCoordinate2D location = {latitude: latValue, longitude: lonValue};
return location;
But obviously its wrong.
I tried creating a seperate MapAnnotation class to handle the annotations like so:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "AgencyViewController.h"
#interface MapAnnotation : NSObject<MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *subtitletext;
NSString *titletext;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (readwrite, retain) NSString *titletext;
#property (readwrite, retain) NSString *subtitletext;
-(id)initWithCoordinate:(CLLocationCoordinate2D) coordinate;
- (NSString *)subtitle;
- (NSString *)title;
-(void)setTitle:(NSString*)strTitle;
-(void)setSubTitle:(NSString*)strSubTitle;
and implement it like so:
CLLocationCoordinate2D newCoord = {latitude: latValue, longitude: lonValue};
MapAnnotation *addAnnotation = [[MapAnnotation alloc] initWithCoordinate:newCoord];
[addAnnotation setTitle:#"The Pin Title"];
[addAnnotation setSubTitle:#"The pin subtitle goes here"];
[mapView addAnnotation:addAnnotation];
And that didnt work either...
Figured it out, needed to add
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"Prospects"];
if(pinView == nil) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Prospects"];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
} else {
pinView.annotation = annotation;
}
return pinView;
}
Now I need to figure out how to change the color of my location pin.