Mapping NSManagedObject Entity to custom class with RestKit - json

I am able to pull JSON results and map them to the db. However, as soon as I try and map the entity to my subclass, it seems that my mapping breaks.
JSON Sample:
{"Customers":[{"Customer":{"Active":"Y","BranchID":0,"CustomerID":"SMCJIMB00736253","CustomerIdentifier":"","CustomerTypeID":0,"Name":""}}]}
Setup:
// Initialize RestKit
RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:TEST_SERVICES_ROOT];
// Initialize object store
objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:RKDefaultSeedDatabaseFileName];
Mapping:
RKManagedObjectMapping* customerMapping = [RKManagedObjectMapping mappingForClass:[Customer class]];
customerMapping.primaryKeyAttribute = #"customerID";
[customerMapping mapKeyPathsToAttributes:#"Active", #"active", nil];
[customerMapping mapKeyPathsToAttributes:#"BranchID", #"branchID", nil];
[customerMapping mapKeyPathsToAttributes:#"CustomerID", #"customerID", nil];
[customerMapping mapKeyPathsToAttributes:#"CustomerIdentifier", #"customerIdentifier", nil];
[customerMapping mapKeyPathsToAttributes:#"CustomerTypeID", #"customerTypeID", nil];
[customerMapping mapKeyPathsToAttributes:#"Name", #"name", nil];
Add Mapping:
[objectManager.mappingProvider setMapping:customerMapping forKeyPath:#"Customers.Customer"];
Call WS:
// Load the object model via RestKit
RKObjectManager* objectManager = [RKObjectManager sharedManager];
NSString *url = [NSString stringWithFormat:SERVICE_CUSTOMERS,#"0",#"1",#"100"];
[objectManager loadObjectsAtResourcePath:url delegate:self block:^(RKObjectLoader* loader) {
loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[Customer class]];
}];
#interface Customer : NSManagedObject
#property (nonatomic, retain) NSString* active;
#property (nonatomic, retain) NSNumber* branchID;
#property (nonatomic, retain) NSString* customerID;
#property (nonatomic, retain) NSString* customerIdentifier;
#property (nonatomic, retain) NSNumber* customerTypeID;
#property (nonatomic, retain) NSString* name;
//populated via fetch predicate
#property (nonatomic, retain) NSArray* customerAddress;
#end
#implementation Customer
#dynamic active;
#dynamic branchID;
#dynamic customerID;
#dynamic customerIdentifier;
#dynamic customerTypeID;
#dynamic name;
//populated via fetch predicate
#dynamic customerAddress;
#end
This works fine as long as I don't try and map the Customer class to the Entity in the data model. Ultimately, I am trying to use my Customer class as a MKAnnotation, but I can't since I cant provide a concrete implementation class. I'm sure that there is some sort of misunderstanding of RestKit to blame. I see that the RKTwitterCoreData has the RKStatus as a concrete subclass.
#end

Ok,
I figured it out after much trial and error! The issue was that I needed to set my rootKeyPath on my mapping to match the rootkeyPath that I use when I added the mapping to the mapping provider. The RKTwitterCoreData client does not do this, but I needed to for whatever reason.
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
userMapping.rootKeyPath = #"User";
userMapping.primaryKeyAttribute = #"userName";
[userMapping mapKeyPathsToAttributes:#"Authenticated", #"authenticated", nil];
................
[objectManager.mappingProvider setMapping:userMapping forKeyPath:#"User"];

Related

NSString type with index

I have created Author class like this :
#interface Author : NSObject{
NSString *authorID;
NSString *email;
NSString *userName;
NSString *password;
NSString *jenisKelamin;
NSString *alamat;
NSString *kota;
NSString *telepon;
NSString *pekerjaan;
NSString *nama;
NSString *tanggalDaftar;
NSString *status;
NSString *lastLogin;
NSString *publishPhoto;
NSString *komentar;
NSString *balasKomentar;
NSString *newsLetter;
}
#property (nonatomic, retain)NSString *authorID;
#property (nonatomic, retain)NSString *email;
#property (nonatomic, retain)NSString *userName;
#property (nonatomic, retain)NSString *password;
#property (nonatomic, retain)NSString *jenisKelamin;
#property (nonatomic, retain)NSString *alamat;
#property (nonatomic, retain)NSString *kota;
#property (nonatomic, retain)NSString *telepon;
#property (nonatomic, retain)NSString *pekerjaan;
#property (nonatomic, retain)NSString *nama;
#property (nonatomic, retain)NSString *tanggalDaftar;
#property (nonatomic, retain)NSString *status;
#property (nonatomic, retain)NSString *lastLogin;
#property (nonatomic, retain)NSString *publishPhoto;
#property (nonatomic, retain)NSString *komentar;
#property (nonatomic, retain)NSString *balasKomentar;
#property (nonatomic, retain)NSString *newsLetter;
#end
and read json like this :
imageArray = [[NSMutableArray alloc]init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc]initWithContentsOfURL:url];
NSError *jsonParsingError = nil;
id myJson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonParsingError];
NSDictionary *imageList;
for (int i=0; i<[myJson count]; i++) {
imageList=[myJson objectAtIndex:i];
currentImage = [ImageList alloc];
currentImage.imageID=[imageList valueForKey:#"id"];
currentImage.tanggal=[imageList valueForKey:#"tanggal"];
currentImage.judul=[imageList valueForKey:#"judul"];
currentImage.namaFile=[imageList valueForKey:#"nama_file"];
currentImage.deskripsi=[imageList valueForKey:#"deskripsi"];
currentImage.user=[imageList valueForKey:#"user"];
currentImage.status=[imageList valueForKey:#"status"];
currentImage.views=[imageList valueForKey:#"views"];
currentImage.rating=[imageList valueForKey:#"rating"];
currentImage.totalRating=[imageList valueForKey:#"total_rating"];
currentImage.totalPerating=[imageList valueForKey:#"total_perating"];
currentImage.imageThemeID=[imageList valueForKey:#"tema"];
currentImage.bayesianRating=[imageList valueForKey:#"bayesian_rating"];
currentImage.imageURL=[imageList valueForKey:#"img_url"];
NSDictionary *authorDict = [imageList objectForKey:#"author"];
currentImage.author = [[[Author alloc] init] autorelease];
currentImage.author.authorID = [authorDict valueForKey:#"id"];
currentImage.author.email = [authorDict valueForKey:#"email"];
currentImage.author.userName = [authorDict valueForKey:#"username"];
currentImage.author.password = [authorDict valueForKey:#"password"];
currentImage.author.jenisKelamin = [authorDict valueForKey:#"jenis_kelamin"];
currentImage.author.alamat = [authorDict valueForKey:#"alamat"];
currentImage.author.kota = [authorDict valueForKey:#"kota"];
currentImage.author.telepon = [authorDict valueForKey:#"telepon"];
currentImage.author.pekerjaan = [authorDict valueForKey:#"pekerjaan"];
currentImage.author.nama = [authorDict valueForKey:#"nama"];
currentImage.author.tanggalDaftar = [authorDict valueForKey:#"tanggal_daftar"];
currentImage.author.status = [authorDict valueForKey:#"status"];
currentImage.author.lastLogin = [authorDict valueForKey:#"last_login"];
[imageArray addObject:currentImage];
[currentImage release];
return self;
}
But if I try to get the value using :
jsonImage =[[JSONReader alloc]loadImageList:newURL];
ImageList *currentImage;
currentImage = [[jsonImage imageArray]objectAtIndex:0];
[jsonTheme release];
if([jsonImage.imageArray count]>0){
NSLog(#"getting image starting");
NSURL *imageURL=[NSURL URLWithString:currentImage.imageURL];
NSLog(#"image URL from array : %#", currentImage.imageURL);
NSData *imageData=[NSData dataWithContentsOfURL:imageURL];
imgTemp = [UIImage imageWithData:imageData];
self.imgImage.image = imgTemp;
NSLog(#"getting image stop");
lblDate.text = currentImage.tanggal;
lblDescription.text = currentImage.deskripsi;
lblSummary.text = currentImage.judul;
Author *currentAuthor = currentImage.author;
lblUser.text = currentAuthor.userName;
[currentImage release];
}
lblUser.text = currentTheme.author.userName; the result of lblUser is null.
when I tried to debug, the value of userName have index :
currentAuthor Author * 0x071a9a20
NSObject NSObject
authorID NSString * 0x0753e700
[0] id 0x071a4ad0
[0] id
email NSString * 0x075403a0
[0] id 0x071a58e0
userName NSString * 0x0753fef0
[0] id 0x071a5930
can you tell me how to get currentAuthor values ?
I think , while releasing currentImage . value of author also changed.
Please do the following changes and try it
Author *currentAuthor =[ currentImage.author copy];

MapKit annotations imported from MySQL

I've been creating an app that is supposed to show Pins on a Map that are stored in a MySQL Database. I've used JavaScript to convert the Database to JSON then converted the JSON data into NSStrings.
The problem here is I then needed to convert two of these NSStrings into doubles because my Pins need to placed via latitude and longitude, here is my code below that when it builds shows no issues but crashes my simulator and shows up some errors which I shall post directly under my code.
Hazards.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Hazards : NSObject <MKAnnotation>
#property (nonatomic, assign) CLLocationDegrees latitude;
#property (nonatomic, assign) CLLocationDegrees longitude;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, strong) NSString * ID;
#property (nonatomic, strong) NSString * ROUTE;
#property (nonatomic, strong) NSString * ADDRESS;
#property (nonatomic, strong) NSString * LATITUDE;
#property (nonatomic, strong) NSString * LONGITUDE;
#property (nonatomic, strong) NSString * HAZARD;
#property (nonatomic, strong) NSString * RISK;
// Methods
- (id) initWithID: (NSString *) hazardsID andROUTE: (NSString *) hazardsROUTE andADDRESS: (NSString *) hazardsADDRESS andLATITUDE: (NSString *) hazardsLATITUDE andLONGITUDE: (NSString *) hazardsLONGITUDE andHAZARD: (NSString *) hazardsHAZARD andRISK: (NSString *) hazardsRISK;
#end
Hazards.m
#import "Hazards.h"
#implementation Hazards
#synthesize coordinate, title, subtitle, ID, ROUTE, ADDRESS, LATITUDE, LONGITUDE, HAZARD, RISK, latitude, longitude;
- (id) initWithID: (NSString *) hazardsID andROUTE: (NSString *) hazardsROUTE andADDRESS: (NSString *) hazardsADDRESS andLATITUDE: (NSString *) hazardsLATITUDE andLONGITUDE: (NSString *) hazardsLONGITUDE andHAZARD: (NSString *) hazardsHAZARD andRISK: (NSString *) hazardsRISK {
self = [super init];
if (self)
{
ID = hazardsID;
ROUTE = hazardsROUTE;
ADDRESS = hazardsADDRESS;
LATITUDE = hazardsLATITUDE;
LONGITUDE = hazardsLONGITUDE;
HAZARD = hazardsHAZARD;
RISK = hazardsRISK;
latitude = [hazardsLATITUDE doubleValue]; // convert the string hazardsLatitude to a double here
longitude = [hazardsLONGITUDE doubleValue]; // convert the string hazardsLongitude to a double here
}
return self;
}
-(NSString *)title
{
return self.HAZARD;
}
-(NSString *)subtitle
{
return self.ADDRESS;
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "Hazards.h"
#interface ViewController : UIViewController
#property (nonatomic, strong) NSMutableArray *json;
#property (nonatomic, strong) NSMutableArray *hazardsArray;
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#pragma mark - Methods
-(void) retrieveData;
#end
ViewController.m
#import "ViewController.h"
#import "Hazards.h"
#interface ViewController ()
#end
// Railway Street Ballymena Coordinates
#define BALLYMENA_LATITUDE 54.857719;
#define BALLYMENA_LONGITUDE -6.280654;
// Span
#define THE_SPAN 0.01f;
#define getDataURL #"www.ryanball.net/royalmail/json.php"
#implementation ViewController
#synthesize json, hazardsArray, mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Create the region
MKCoordinateRegion myRegion;
// Center
CLLocationCoordinate2D center;
center.latitude = BALLYMENA_LATITUDE;
center.longitude = BALLYMENA_LONGITUDE;
//Span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
myRegion.center = center;
myRegion.span = span;
// Set our mapview
[mapView setRegion:myRegion animated: YES];
// Annotation
NSMutableArray *locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Hazards *myAnn;
// Pin to show Royal Mail Ballymena delivery office
myAnn = [[Hazards alloc] init];
location.latitude = BALLYMENA_LATITUDE;
location.longitude = BALLYMENA_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = #"Royal Mail Ballymena";
myAnn.subtitle = #"111, Railway Street";
[locations addObject:myAnn];
[self.mapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Methods
-(void) retrieveData {
NSURL *url = [NSURL URLWithString:getDataURL];
NSData *data = [NSData dataWithContentsOfURL:url];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Setup our hazards array
hazardsArray = [[NSMutableArray alloc] init];
for (int i =0; i < json.count; i++) {
// Create hazard object
NSString *hazardsID = [[json objectAtIndex:i] objectForKey:#"ID"];
NSString *hazardsROUTE = [[json objectAtIndex:i] objectForKey:#"ROUTE"];
NSString *hazardsADDRESS = [[json objectAtIndex:i] objectForKey:#"ADDRESS"];
NSString *hazardsLATITUDE = [[json objectAtIndex:i] objectForKey:#"LATITUDE"];
NSString *hazardsLONGITUDE = [[json objectAtIndex:i] objectForKey:#"LONGITUDE"];
NSString *hazardsHAZARD = [[json objectAtIndex:i] objectForKey:#"HAZARD"];
NSString *hazardsRISK = [[json objectAtIndex:i] objectForKey:#"RISK"];
Hazards *myHazards = [[Hazards alloc] initWithID:hazardsID andROUTE:hazardsROUTE andADDRESS:hazardsADDRESS andLATITUDE:hazardsLATITUDE andLONGITUDE:hazardsLONGITUDE andHAZARD:hazardsHAZARD andRISK:hazardsRISK];
// Add our hazards object to our hazards array
[hazardsArray addObject:myHazards];
}
[self.mapView addAnnotations:hazardsArray];
}
#end
Here is the error log I get in the console:
2013-04-25 09:04:43.628 RoyalMailApp[6596:c07] -[Hazards setCoordinate:]: unrecognized selector sent to instance 0x8c63a60
2013-04-25 09:04:43.629 RoyalMailApp[6596:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Hazards setCoordinate:]: unrecognized selector sent to instance 0x8c63a60'
*** First throw call stack:
(0x1b3c012 0x1458e7e 0x1bc74bd 0x146c7ea 0x1b2bcf9 0x1b2b94e 0x2698 0x47e1c7 0x47e232 0x3cd3d5 0x3cd76f 0x3cd905 0x3d6917 0x39a96c 0x39b94b 0x3accb5 0x3adbeb 0x39f698 0x1a97df9 0x1a97ad0 0x1ab1bf5 0x1ab1962 0x1ae2bb6 0x1ae1f44 0x1ae1e1b 0x39b17a 0x39cffc 0x215d 0x2085 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)

Calling coordinates from MySQL database with this code causes simulator to display a SIGABRT error. What's wrong?

When I use this code to try and call Lat & Long coordinates from a MySQL database (and display them on a MapView), the app runs fine. Everything appears to work, but for some reason, xcode pauses the simulator before the map loads, and throws me a SIGABRT. Any idea why? See below:
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
#property (nonatomic, retain) NSMutableArray *dispensaries;
#property (nonatomic, retain) NSMutableData *data;
#end
MapViewController.m
#import "MapViewController.h"
#import "MapViewAnnotation.h"
#implementation MapViewController
#synthesize mapView;
#synthesize dispensaries;
#synthesize data;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidUnload];
NSLog(#"Getting Device Locations");
NSString *hostStr = #"http://stylerepublicmagazine.com/dispensaries.php";
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:hostStr]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
NSLog(#"server output: %#", serverOutput);
NSMutableArray *array = (NSMutableArray *)dispensaries;
dispensaries = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
for (NSDictionary *dictionary in array) {
CLLocationCoordinate2D coord = {[[dictionary objectForKey:#"lat"] doubleValue], [[dictionary objectForKey:#"lng"] doubleValue]};
MapViewAnnotation *ann = [[MapViewAnnotation alloc] init];
ann.title = [dictionary objectForKey:#"Name"];
ann.coordinate = coord;
[mapView addAnnotation:ann];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
self.mapView.delegate = self;
}
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"You Are Here";
point.subtitle = #"Your current location";
[self.mapView addAnnotation:point];
}
Ok, so now you have the JSON. You are going to have to decode that using NSXMLParser. Or, if you want to turn that into objects, you could use my open source library on GitHub, which allows you to simply implement NSCoding protocol and instantiate objects (or encode them) as JSON. That's here.

NSMutableDictionary setObject:forKey: fails to add key

I'm sure I'm missing something in a small iPhone program I'm trying to write, but the code is simple and it compiles without any errors and so I fails to see where the error is.
I've set up a NSMutableDictionary to store students' attributes, each with a unique key. In the header file, I declare the NSMutableDictonary studentStore:
#interface School : NSObject
{
#private
NSMutableDictionary* studentStore;
}
#property (nonatomic, retain) NSMutableDictionary *studentStore;
And of course in the implementation file:
#implementation School
#synthesize studentStore;
And I want to add an object into the dictionary:
- (BOOL)addStudent:(Student *)newStudent
{
NSLog(#"adding new student");
[studentStore setObject:newStudent forKey:newStudent.adminNo];
return YES;
}
class Student has the attributes:
#interface Student : NSObject
{
#private
NSString* name; //attributes
NSString* gender;
int age;
NSString* adminNo;
}
where newStudent has the values:
Student *newStudent = [[Student alloc] initWithName:#"jane" gender:#"female" age:16 adminNo:#"123"];
But when I look up the dictionary:
- (void)printStudents
{
Student *student;
for (NSString* key in studentStore)
{
student = [studentStore objectForKey:key];
NSLog(#" Admin No: %#", student.adminNo);
NSLog(#" Name: %#", student.name);
NSLog(#"Gender: %#", student.gender);
}
NSLog(#"printStudents failed");
}
It fails to print the values in the table. Instead, it prints the line "printStudents failed".
I guess this's quite basic, but since I'm new to iOS programming I'm a bit stumped. Any help will be appreciated. Thanks.
Your studentStore instance variable is a pointer to an NSMutableDictionary. By default, it points to nil, meaning it doesn't point to any object. You need to set it to point to an instance of NSMutableDictionary.
- (BOOL)addStudent:(Student *)newStudent
{
NSLog(#"adding new student");
if (studentStore == nil) {
studentStore = [[NSMutableDictionary alloc] init];
}
[studentStore setObject:newStudent forKey:newStudent.adminNo];
return YES;
}

loading image from view controller 1 NSDictionary into detailViewController

I am trying to use an NSMutableDictionary in a view controller to load an image and text into a detail view controller when an image is tapped. I am new to programming and I am trying to understand. Could someone please help.
Here is my code in the view controller 1 .m
- (void) coverflowView:(TKCoverflowView*)coverflowView coverAtIndexWasDoubleTapped:(int)index{
SomeDetailViewController *detailViewController = [[SomeDetailViewController alloc] initWithNibName:#"SomeDetailViewController" bundle:nil];
if ((int)index == 0) {
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"0002.jpg", #"imagekey",
#"This is #1", #"textkey", nil];
NSLog(#"%#", [myDictionary objectForKey:#"imagekey"]);
NSLog(#"%#", [myDictionary objectForKey:#"textkey"]);
}
[self.navigationController pushViewController:detailViewController animated:YES];
}
when I build and run this the image key and text key are called but don't show up in the detail view controller.
my detailViewController.h
#import <QuartzCore/QuartzCore.h>
#interface SomeDetailViewController : UIViewController < UITextViewDelegate, UINavigationControllerDelegate>{
IBOutlet UIImageView *imageView;
IBOutlet UITextView *myText;
NSString *imagekey;
NSMutableDictionary *myDictionary;
NSString *textkey;
}
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
#property (nonatomic, retain) IBOutlet UITextView *myText;
#property (nonatomic, retain) NSString *imagekey;
#property (nonatomic, retain) NSString *textkey;
#property (nonatomic, retain) NSMutableDictionary *myDictionary;
#end
and my detailViewContoller .m
#synthesize myDictionary;
- (void)viewDidLoad
{
[super viewDidLoad];
imageView .image = [[UIImage alloc] init];
self.imageView.image =[UIImage imageNamed:[(NSMutableDictionary *)myDictionary objectForKey:#"imagekey"]];
self.myText.text =[(NSMutableDictionary *)myDictionary objectForKey:#"textkey"];
}
I know this is similar to another post but I was advise not to use NSUsersDefaults so I am trying this.
There are no errors but nothing shows up