NSDictionary returning null value for key - objective-c

Im having trouble understanding why the following code displays "The First Key = (null)" in the console/terminal:
Here is the Interface:
#import <UIKit/UIKit.h>
#interface TestingViewController : UIViewController
#property (nonatomic, strong) NSMutableArray *namesArray;
#property (nonatomic, strong) NSDictionary *myDictionary;
#end
This is the implementation:
#import "DictionaryTestViewController.h"
#implementation DictionaryTestViewController
#synthesize namesArray;
#synthesize myDictionary;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.myDictionary initWithObjectsAndKeys:#"value1", #"key1", #"value2", #"key2", nil];
NSLog(#"The First Key = %#", [self.myDictionary objectForKey:#"key1"]);
}
#end
Thanks in advance!

You haven't allocated your dictionary yet. It's nil at the moment, and sending message to nil does nothing.
Change it to this instead if you're using ARC
self.myDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:#"value1", #"key1", #"value2", #"key2", nil];
or this if not
self.myDictionary = [[[NSDictionary alloc] initWithObjectsAndKeys:#"value1", #"key1", #"value2", #"key2", nil] autorelease];

Related

Unable to POST to Server using RestKit

I have been trying this for quite sometime now, but I just couldn't be able to post successfully to my server. I have read this, github object mapping overview for the Restkit and, the Gist restKit tutorial.
My Problem
I am trying to post sign in information(nickname,hardwareId,phone model) and get the AccountId from my server. But I am getting this response from the console:
GuessTheImage[6832:70b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AccountsClass 0x8c5cba0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key AccountInfo.'
What I think is the problem
I believe I am messing up the way I store the data right before the mapping part. But I am not sure where exactly.
The JSON that I am trying post should look like this
{
"DeviceType": "sample string 1",
"HardwareId": "sample string 2",
"NickName": "sample string 3",
"AccountId": 4
}
Overview of the program
I created the variables for mapping in the AccountClass. From loginviewcontroller, I get the device type, hardwareId and nickname after the user clicks login button and assign those variables to the variables in AccountClass and map it POST if afterwards.
AccountClass.h
#import <Foundation/Foundation.h>
#interface AccountsClass : NSObject
#property (nonatomic, strong,retain)NSString *DeviceType;
#property (nonatomic,strong)NSNumber *AccountId;
#property (nonatomic,strong) NSString *NickName;
#property (nonatomic,strong) NSNumber *HardwareId;
#end
LoginViewController.h
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController<UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *usernameTextField;
#property (strong, nonatomic) IBOutlet UIButton *submitButton;
#property (nonatomic,readonly) NSUUID *identifierForVendor;
#property(nonatomic, readonly, retain) NSString *model;
#property (nonatomic,readonly,retain)NSString *StoreIdentifierForVendor;
#property (nonatomic,readonly,retain)NSString *StoreTheModel;
- (IBAction)submit:(id)sender;
#property (nonatomic,strong)NSString *nickname;
#end
LoginViewController.m
#import "LoginViewController.h"
#import <RestKit/RestKit.h>
#import "AccountsClass.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize usernameTextField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(dissmissKeyboard)];
[self.view addGestureRecognizer:tap];
[usernameTextField setDelegate:self];
}
-(void)loadPostRequest
{
_StoreIdentifierForVendor = [[[UIDevice currentDevice]identifierForVendor]UUIDString];
_StoreTheModel = [UIDevice currentDevice].model;
_nickname = usernameTextField.text;
AccountsClass *AccountInfo = [[AccountsClass alloc] init];
AccountInfo.NickName = _nickname;
NSNumberFormatter *hardwareIdentification = [[NSNumberFormatter alloc]init];
[hardwareIdentification setNumberStyle:NSNumberFormatterScientificStyle];
NSNumber *hwreID =[hardwareIdentification numberFromString:_StoreIdentifierForVendor];
AccountInfo.HardwareId = hwreID;
AccountInfo.DeviceType =_StoreTheModel;
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[AccountsClass class]];
[responseMapping addAttributeMappingsFromArray:#[#"NickName", #"HardwareId", #"DeviceType",#"AccountId"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *AccountDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:statusCodes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping]; // objectClass == NSMutableDictionary
[requestMapping addAttributeMappingsFromArray:#[#"AccountInfo.NickName", #"AccountInfo.HardwareId", #"AccountInfo.DeviceType",#"AccountInfo.AccountId"]];
// For any object of class Article, serialize into an NSMutableDictionary using the given mapping and nest
// under the 'article' key path
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[AccountInfo class] rootKeyPath:nil method:RKRequestMethodAny];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"https://picquiz.azurewebsites.net"]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:AccountDescriptor];
// POST to create
[manager postObject:AccountInfo path:#"/Accounts" parameters:nil success:nil failure:nil];
}
-(void)dissmissKeyboard
{
[usernameTextField resignFirstResponder];
}
- (IBAction)submit:(id)sender {
[self loadPostRequest];
}
#end
I will appreciate your help.
Your problem appears to be:
[requestMapping addAttributeMappingsFromArray:#[#"AccountInfo.NickName", #"AccountInfo.HardwareId", #"AccountInfo.DeviceType",#"AccountInfo.AccountId"]];
because the data that you are trying to POST doesn't have nested data like that. It looks like it should be:
[requestMapping addAttributeMappingsFromArray:#[#"NickName", #"HardwareId", #"DeviceType",#"AccountId"]];

Pulling coordinates for MapView annotations from MySQL database, but annotations aren't showing?

I'm trying to pull coordinates for my MapView from a MySQL database, but for some reason my coordinates just aren't showing up on the MapView?
See below my code.
MapViewController.h file
#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"
#import "JSONKit.h"
#implementation MapViewController
#synthesize mapView;
#synthesize dispensaries;
#synthesize data;
#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 = [[[serverOutput objectFromJSONString] mutableCopy] autorelease];
dispensaries = [serverOutput objectFromJSONString];
NSLog(#"%#", [serverOutput objectFromJSONString]);
for (NSDictionary *dictionary in array) {
assert([dictionary respondsToSelector:#selector(objectForKey:)]);
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];
}
MapViewAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MKAnnotation.h>
#import <CoreLocation/CoreLocation.h>
#interface MapViewAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
MapViewAnnotation.m
#import "MapViewAnnotation.h"
#implementation MapViewAnnotation
#synthesize title, coordinate, subtitle;
-(void)dealloc{
[title release];
[super dealloc];
}
#end
this seems to be an issue with you expecting the wrong JSON:
You wrap the serverOutput in an array:
NSMutableArray *array = [NSMutableArray arrayWithObject:[serverOutput objectFromJSONString]];
You try to access a JKDictionary (Json Kit dictionary) WITCH is infact an array and therefore doesn't answer to objectForKey:
try to make sure:
for (NSDictionary *dictionary in array) {
assert([dictionary respondsToSelector:#selector(objectForKey:)]);
--
potential Solution
I believe your extra wrapping makes it bad. try:
NSMutableArray *array = [[[serverOutput objectFromJSONString] mutableCopy] autorelease];

How to reference a singleton?

I am trying to use singleton in my app. I want to share 8 strings using a singleton.
This is the tutorial I referred to -> http://www.galloway.me.uk/tutorials/singleton-classes/
My code:
- MyManager.h
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSString *someProperty1;
NSString *someProperty2;
NSString *someProperty3;
NSString *someProperty4;
NSString *someProperty5;
NSString *someProperty6;
NSString *someProperty7;
NSString *someProperty8;
}
#property (nonatomic, retain) NSString *someProperty1;
#property (nonatomic, retain) NSString *someProperty2;
#property (nonatomic, retain) NSString *someProperty3;
#property (nonatomic, retain) NSString *someProperty4;
#property (nonatomic, retain) NSString *someProperty5;
#property (nonatomic, retain) NSString *someProperty6;
#property (nonatomic, retain) NSString *someProperty7;
#property (nonatomic, retain) NSString *someProperty8;
+ (id)sharedManager;
#end
MyManager.m
#import "MyManager.h"
#implementation MyManager
#synthesize someProperty;
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
someProperty1 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty2 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty3 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty4 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty5 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty6 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty7 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty8 = [[NSString alloc] initWithString:#"Default Property Value"];
}
return self;
}
- (void)dealloc {
// Should never be called, but just here for clarity really.
}
#end
I want to use this singleton to use these string variables to add string in one other view and then use it to store in database in another third view.
Can someone please tell me how to reference them and store string in these variables and again access them in the third different view?
import MyManager.h where you use singleton.
[[MyManager sharedManager] setSomeProperty1:#abc"]; //for setting
[[MyManager sharedManager] someProperty1]; // for getting
or you can use like this also
MyManager *manager = [MyManager sharedManager];
manager.someProperty1 = #"abc";
NSString *str = manager.someProperty1;

NSMutableArray initWithObjects Not Working

Ey guys, I am having some problems adding NSURLs to an array and looping through them. Here are the relevant portions of my code:
RSS_ReaderAppDelegate.h:
#interface RSS_ReaderAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
NSDictionary *RSSFeeds;
NSMutableArray *RSSFeedURLs;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) NSDictionary *RSSFeeds;
#property (nonatomic, retain) NSMutableArray *RSSFeedURLs;
RSS_ReaderAppDelegate.m:
#implementation RSS_ReaderAppDelegate
#synthesize window;
#synthesize navigationController;
#synthesize RSSFeeds, RSSFeedURLs;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSURL *url1 = [[NSURL alloc] initWithString:#"http://<some url>"]; //real URL has been hidden
NSURL *url2 = [[NSURL alloc] initWithString:#"http://<some other url>"]; //real URL has been hidden
[RSSFeedURLs initWithObjects: url1, url2, nil];
[url1 release];
[url2 release];
for (NSURL *url in RSSFeedURLs) { //jumps right over this for loop
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] init];
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error(s) encountered");
}//for
// Add the navigation controller's view to the window and display.
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
So [RSSFeedURLs initWithObjects: url1, url2, nil]; doesn't seem to actually do anything as when I run the debugger and type "po RSSFeedsURLs" it reports: "Cannot access memory at address 0x0", and thus the for loop is never entered. I have no idea why this is so, can anyone shed some light on this situation for me? Thanks in advance.
you want:
RSSFeedURLs = [[NSMutableArray alloc] initWithObjects: url1, url2, nil];
but you should want:
rssFeedURLs = [[NSMutableArray alloc] initWithObjects: url1, url2, nil];
Variables starting with capital letters lead to much confusion.

Share NSArray Contents between multiple methods in a single class

What am I doing wrong? My code crashes when I try to log the array. Here is my class:
#interface ArrayTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
NSArray *array;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) NSArray *array;
-(IBAction)buttonPressed;
#end
#implementation ArrayTestAppDelegate
#synthesize window, array;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
array = [NSArray arrayWithObjects:#"Banana", #"Apple", #"Orange", #"Pear", #"Plum", nil];
[window makeKeyAndVisible];
}
-(IBAction)buttonPressed {
NSLog(#"%#", array);
}
- (void)dealloc {
[window release];
[array release];
[super dealloc];
}
#end
This is a common memory management error in Cocoa. The arrayWithObjects method of the NSArray class returns an autoreleased object. By the time you try to log the array in the buttonPressed method, the array has already been released and you get a crash. The fix is easy:
array = [[NSArray alloc] initWithObjects:#"Banana", #"Plum", nil];
Or:
array = [[NSArray arrayWithObjects:#"Banana", #"Plum", nil] retain];
I guess the first one is better, the retain on the end of the second example is easy to miss. I would suggest that you read some more on memory management in Cocoa.