Why is my array returning null? - ios

I am calling getBoardingCards once here:
BRPBoardingCards *boardingCards = [[BRPBoardingCards alloc] init];
boardingCardsArray = [boardingCards getBoardingCards];
The array is returning null though (in the NSLog shown). What am I doing wrong?
- (NSArray*)getBoardingCards
{
NSMutableArray *storedArray = [[NSMutableArray alloc] init];
Utils *utils = [[Utils alloc] init];
NSUserDefaults *properties = [utils getUserDefaults];
// check if its the first time we are running the app.
if(![[properties objectForKey:#"first_run"] isEqualToString:#"no"]){
//I decided it is for american tourists and every booking office allows payment in dollars because I dont have a euros key on my keyboard.
//Car also has lots of seats. 1337 of them to be precise.
[self setNewBoardingCardWithCardType:#"car" WithPrice:#"$1.50" AndStartLocation:#"airport" AndEndLocation:#"restaurant" WithSeat:#"1337" andExtraInformation:#"We dont like you so we are giving you the back seat by yourself."];
[self setNewBoardingCardWithCardType:#"helicopter" WithPrice:#"$500" AndStartLocation:#"restaurant" AndEndLocation:#"hospital" WithSeat:#"1" andExtraInformation:#"You are driving."];
[self setNewBoardingCardWithCardType:#"train" WithPrice:#"$100" AndStartLocation:#"restaurant" AndEndLocation:#"ditch" WithSeat:#"STANDONHEAD" andExtraInformation:#"No Seats on this train. Gotta stand on your head. Dont forget your white lightning for the ditch."];
[self setNewBoardingCardWithCardType:#"Fire Engine" WithPrice:#"$10" AndStartLocation:#"restaurant" AndEndLocation:#"burning house" WithSeat:#"HOSE" andExtraInformation:#"Take the hose to put out this fire we are heading to. "];
[self setNewBoardingCardWithCardType:#"Nimbus" WithPrice:#"$300" AndStartLocation:#"burning house" AndEndLocation:#"popo floating island" WithSeat:#"LEVITATION" andExtraInformation:#"Dont forget to turn super saiyan on your way up there. "];
[self setNewBoardingCardWithCardType:#"Sky Dive" WithPrice:#"$1020" AndStartLocation:#"popo floating island" AndEndLocation:#"home" WithSeat:#"GRAVITY" andExtraInformation:#"Ohh! that Adrenalines pumping. "];
[self setNewBoardingCardWithCardType:#"Legs" WithPrice:#"$50" AndStartLocation:#"ditch" AndEndLocation:#"park bench hotel" WithSeat:#"VODKA" andExtraInformation:#"Time to get a good nights rest and sobre up. "];
[self setNewBoardingCardWithCardType:#"Bicycle" WithPrice:#"$5" AndStartLocation:#"park bench hotel" AndEndLocation:#"home" WithSeat:#"BIKESEAT1" andExtraInformation:#"What a terrible hangover. Time to head home. "];
[self setNewBoardingCardWithCardType:#"ambulance" WithPrice:#"$40" AndStartLocation:#"hospital" AndEndLocation:#"home" WithSeat:#"LEVITATION" andExtraInformation:#"Well that was a bad idea! "];
[properties setObject:#"no" forKey:#"first_run"];
[properties synchronize];
NSLog(#"did set first run to no");
}
storedArray = [[properties objectForKey:#"cards"] mutableCopy];
NSLog(#"getBoardingCards storedArray: %#", storedArray);
return storedArray;
}
- (NSArray*)getBoardingCardsByType:(NSString*)cardType
{
// at this point i would create a for loop and iterate through the array checking if (type isEqualToString:cardType).
// But this is just an idea for later. To go by only a certain type of route.
return nil;
}
- (void)setNewBoardingCardWithCardType:(NSString*)cardType WithPrice:(NSString*)price AndStartLocation:(NSString*)startLocation AndEndLocation:(NSString*)endLocation WithSeat:(NSString*)seatCode andExtraInformation:(NSString*)extraInfo{
// populate the dictionary with data.
NSMutableDictionary *card = [[NSMutableDictionary alloc] init];
[card setObject:cardType forKey:#"type"];
[card setObject:price forKey:#"price"];
[card setObject:startLocation forKey:#"startLocation"];
[card setObject:endLocation forKey:#"endLocation"];
[card setObject:seatCode forKey:#"seat"];
[card setObject:extraInfo forKey:#"info"];
// get our stored array.
Utils *utils = [[Utils alloc] init];
NSUserDefaults *properties = [utils getUserDefaults];
NSMutableArray *storedArray = [[properties objectForKey:#"cards"] mutableCopy];
[storedArray addObject:card];
// set the stored array.
[properties setObject:storedArray forKey:#"cards"];
[properties synchronize];
}

You're not creating the cards mutable array in the NSUserDefaults.
This line (in setNewBoardingCardWithCardType:):
NSMutableArray *storedArray = [[properties objectForKey:#"cards"] mutableCopy];
is essentially
NSMutableArray *storedArray = [nil mutableCopy];
which is the same as
NSMutableArray *storedArray = nil;
Check if the object for this key exist, if not - create it and then use it.

Related

One method to add/remove/edit dictionaries from memory

Right now, if i have a list , NSMutableArry of NSDictionaries, and i would like to edit / remove/ add object to, and save to the user defaults . (obj-c/swift)
So i would have a function for each operation , for example to add one to the list :
-(void)addMedicineToArray:(NSDictionary*)medicine
{
NSMutableArray *medicines=[[NSMutableArray alloc] init];
medicines=[[[NSUserDefaults standardUserDefaults] objectForKey:#"Medicines"] mutableCopy];
if(!medicines)
medicines=[[NSMutableArray alloc] init];
[medicines addObject:medicine];
[[NSUserDefaults standardUserDefaults] setObject:medicines forKey:#"Medicines"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Then another method to remove, and another one to edit. I am pretty sure this is not that clever solution, although i coudn't think of a simple solution to do that in one clear method.
is there some better implementation of this instead of writing 3/4 methods ?
//
// MYCustomViewControllerClass.m
// Fro StackOverFlow
//
// Created by Naresh Reddy M on 16/03/16.
// Copyright © 2016 Naresh Reddy M. All rights reserved.
//
#import "MYCustomViewControllerClass.h"
typedef NS_ENUM(NSInteger, EditingType)
{
kEditingTypeDeleteObj = 1,
kEditingTypeUpdateObj = 2,
kEditingTypeAddObj = 3,
// if needed,Add few More as per your requirement .
};
#implementation MYCustomViewControllerClass
- (void)viewDidLoad
{
[super viewDidLoad];
// Forming Medicine Data Dict & Array
NSMutableArray <NSDictionary *>*medicinesArray;
if([[[NSUserDefaults standardUserDefaults] objectForKey:#"MYMeds"] mutableCopy])
medicinesArray = [[[NSUserDefaults standardUserDefaults] objectForKey:#"MYMeds"] mutableCopy];
else
{
medicinesArray = [NSMutableArray new];
for(int i = 0; i < 10 ; ++i)
{
NSMutableDictionary *medicineDetailsDict = [NSMutableDictionary new];
[medicineDetailsDict setValue:[NSString stringWithFormat:#"Medicine : %d",1+i] forKey:[NSString stringWithFormat:#"Name"]];
[medicineDetailsDict setValue:[NSString stringWithFormat:#"D%d",1+i] forKey:[NSString stringWithFormat:#"DrugID"]]; // Please do maintain a UNIQUE ID for Your Drug
// You can have other info about drug with appropriate keys
[medicinesArray addObject:medicineDetailsDict];
}
}
// 1 - Deleting your medicine with DrugID D1 from aray & saving updated medicines Array into userdefaults
// Name will be changed for Medicine With DrugID - D1 from #"Medicine : 1" to #"Updated Data for Name Key"
NSMutableDictionary *medicine1 = [medicinesArray[0] mutableCopy];
[medicine1 setValue:#"Updated Data for Name Key" forKey:#"Name"]; // Im updating its name here
[self updateMedicine:medicine1 inToArray:medicinesArray withUpdateType:kEditingTypeUpdateObj];
// Name of Medicine With D1 Id Has been Updated
// 2 - Adding New Medicince To your Array & saving updated Array In user defaults
NSMutableDictionary *myNewMed = [NSMutableDictionary new];
[myNewMed setValue:#"D150" forKey:#"DrugID"];
[myNewMed setValue:#"New Named Drug" forKey:[NSString stringWithFormat:#"Name"]];
NSLog(#"%#",[medicinesArray description]); // D150 will be Added
[self updateMedicine:myNewMed inToArray:medicinesArray withUpdateType:kEditingTypeAddObj];
NSLog(#"%#",[medicinesArray description]); // D150 Has been Added
// 3 - Deleting A Medicine From DB
// D150 Will be Deleted
[self updateMedicine:myNewMed inToArray:medicinesArray withUpdateType:kEditingTypeDeleteObj];
medicinesArray = [[[NSUserDefaults standardUserDefaults] objectForKey:#"MYMeds"] mutableCopy];
NSLog(#"%#",[medicinesArray description]); // D150 Was deleted
}
-(void)updateMedicine:(NSMutableDictionary *)updatedMedicine inToArray:(NSMutableArray <NSDictionary *>*)arrayOfMedicines withUpdateType:(EditingType)editType
{
switch (editType)
{
case kEditingTypeDeleteObj:
{
NSString *idOfRecivedDrug = updatedMedicine[#"DrugID"];
for(NSDictionary *med in arrayOfMedicines)
{
if([med[#"DrugID"] isEqualToString:idOfRecivedDrug])
{
NSInteger index = [arrayOfMedicines indexOfObject:med];
[arrayOfMedicines removeObjectAtIndex:index];
[[NSUserDefaults standardUserDefaults] setObject:arrayOfMedicines forKey:#"MYMeds"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
}
break;
case kEditingTypeAddObj:
{
NSString *idOfRecivedDrug = updatedMedicine[#"DrugID"];
bool bIsDrugFound = false;
for(NSDictionary *med in arrayOfMedicines)
{
if([med[#"DrugID"] isEqualToString:idOfRecivedDrug])
{
bIsDrugFound = true;
break;
}
}
if(bIsDrugFound)
NSLog(#"Seems you are trying to add drug to existing UNIQUE ID,Try Updating Other than adding it as a new");
else
{
[arrayOfMedicines addObject:updatedMedicine];
[[NSUserDefaults standardUserDefaults] setObject:arrayOfMedicines forKey:#"MYMeds"];
[[NSUserDefaults standardUserDefaults] synchronize]; }
}
break;
case kEditingTypeUpdateObj:
{
NSString *idOfRecivedDrug = updatedMedicine[#"DrugID"];
for(NSDictionary *med in arrayOfMedicines)
{
if([med[#"DrugID"] isEqualToString:idOfRecivedDrug])
{
// Found Your Drug now Need to edit it's data
NSInteger index = [arrayOfMedicines indexOfObject:med];
[arrayOfMedicines replaceObjectAtIndex:index withObject:updatedMedicine];
[[NSUserDefaults standardUserDefaults] setObject:arrayOfMedicines forKey:#"MYMeds"];
[[NSUserDefaults standardUserDefaults] synchronize];
break;
}
else
NSLog(#"Your medicine was new,probably need to add it into the dictionary");
}
}
break;
default:
break;
}
}
#end
Happy To Help :)
Have Fun
whenever you save anything to NSUserDefaults then it get saved as Immutable i.e. whenever you fetch data from NSUserDefault it will be Immutable. So you need first to downcast it to Mutable object and then you can perform operations on that object. Each class whether its NSMutableArray or NSMutableDictionary have methods defined to add, remove & update the records.
To update any existing data you need first to check its availability in the data source & then perform further operation required. You can even perform all tasks in a single function by having a Enum structure define for each operation.

Create Events for MBCalendarKit in iOS

I imported MBCalendar Kit into my project, and I don't know how to add an event or array of events in calendar. I found this code:
NSMutableDictionary *eventsDict = [[NSMutableDictionary alloc] init];
for (int i =0; i< eventsArray.count ;i++)
{
// Create events
eventsDict = eventsArray[i];
CKCalendarEvent* aCKCalendarEvent = [[CKCalendarEvent alloc] init];
aCKCalendarEvent.title = [eventsDict objectForKey:#"email"];
aCKCalendarEvent.date = date; //[eventsArray objectForKey:#"phone"];
aCKCalendarEvent.address = [eventsDict objectForKey:#"addrLine1"];
aCKCalendarEvent.image = [eventsDict objectForKey:#"pPic"];
aCKCalendarEvent.name = [eventsDict objectForKey:#"fname"];
aCKCalendarEvent.appDate = [eventsDict objectForKey:#"apntDt"];
aCKCalendarEvent.notes = [eventsDict objectForKey:#"notes"];
aCKCalendarEvent.phone = [eventsDict objectForKey:#"phone"];
[myeventsArray addObject: aCKCalendarEvent];
}
[_data setObject:myeventsArray forKey:date];
but I don't know where to write it, or how to use it. Can anyone help me?
Thank you.
I'm working with this Framework and I've had the same issues.
What worked for me was to use the NSDate+Components category, specifically the dayWithDay:month:year method to create the dates for the events, then create as many events as you want the way you're doing it, encapsulate all the events that are on the same day in an array and lastly setting that array as an object for the NSDictionary data with the previously created as the key to that array. Here's an example:
NSDate *eventDate1 = [NSDate dateWithDay:8 month:8 year:2014];
NSDate *eventDate2 = [NSDate dateWithDay:9 month:8 year:2014];
CKCalendarEvent *event1 = [CKCalendarEvent eventWithTitle:#"Event 1" andDate:eventDate1 andInfo:nil];
CKCalendarEvent *event2 = [CKCalendarEvent eventWithTitle:#"Event 2" andDate:eventDate2 andInfo:nil];
NSArray *today = [NSArray arrayWithObjects:event1, nil];
NSArray *tomorrow = [NSArray arrayWithObjects:event2, nil];
[[self data] setObject:today forKey:eventDate1];
[[self data] setObject:tomorrow forKey:eventDate2];
Hope this helps :D
I'm working on my own framework based on this but with an iOS7 native feel, it's not finished yet but here is the repo:
https://github.com/AndoniV/CalendarBar_iOS7_Style.git

Class Object is always null

This is the method when my app complete the downloading with contact which is coming from server. In for loop I am using AIContactParsarModal class and using dictionary I am setting the objects, but every time object value is null.
Thanks for the help and any help will be appreciable. Here is my code.
- (void)donewithContact {
self.allPersonDetailsDict = [[NSMutableDictionary alloc]initWithCapacity:1];
NSMutableArray *allKeysArray = [[NSMutableArray alloc] init];
NSString *prefix;
NSString *searchContactString = [[NSUserDefaults standardUserDefaults] objectForKey:#"AdvanceSearch"];
if ([searchContactString isEqualToString:#"SpecialSearch"]) {
[self.allPersonDetailsDict removeAllObjects];
}
if (getContactArray.count == 0 ){
[noContactLabel setHidden:NO];
} else {
for (AIContactParsarModal *contact in getContactArray) {
NSLog(#"contact LAST NAMES ARE %#",contact.lastName);
prefix = [[contact.lastName substringWithRange:NSMakeRange(0, 1)] uppercaseString];
if ([allKeysArray containsObject:prefix]) {
NSMutableArray *conatctsWithPrefix = [_allPersonDetailsDict objectForKey:prefix];
[conatctsWithPrefix addObject:contact];
} else {
[allKeysArray addObject:prefix];
NSMutableArray *conatctsWithPrefix = [[NSMutableArray alloc] initWithObjects:contact,nil];
[self.allPersonDetailsDict setObject:conatctsWithPrefix forKey:prefix];
NSLog(#"conatctsWithPrefix %#",conatctsWithPrefix);
}
}
[noContactLabel setHidden:YES];
}
NSLog(#"All Names First characters are:%#", allKeysArray);
[self.contactTableView reloadData];
[HUD hide:YES];
}
May be you are getting null value in contact by which you are getting null in conatctsWithPrefix
first print values stored in contact.

Saving Hebrew text to NSUserDefaults return strange encoding

I'm saving Hebrew text to NAMutableArray, then I save it to NSUserDefalts, this way:
numOfWallPosts++;
NSString *tempKeyToStore = [NSString stringWithFormat:#"wall_post_%d", numOfWallPosts]; // wall_post_%d
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray addObject:currentOwner];
[tempArray addObject:currentTitle];
[tempArray addObject:currentText];
[tempArray addObject:currentDate];
[tempArray addObject:currentTime];
[tempArray addObject:currentImageURL];
[tempArray addObject:currentWallID];
[self.sharedPrefs setObject:tempArray forKey:tempKeyToStore];
[self.sharedPrefs synchronize];
When I want to get the Hebrew text back I get text like this:
Wall messages: (
"\U05de\U05e2\U05e8\U05db\U05ea",
"\U05ea\U05e8\U05d2\U05d9\U05dc \U05e4\U05d9\U05e7\U05d5\U05d3 \U05d4\U05e2\U05d5\U05e8\U05e3",
"\U05d0\U05d6\U05e2\U05e7\U05ea \U05ea\U05e8\U05d2\U05d5\U05dc \U05d1\U05e9\U05e2\U05d4 19:05",
"27/05/13",
"13:16",
"http://blabla......",
9
)
I tried to format the text in UTF8String, and with NSUTF8StringEncoding and I still get the text this way.
Can I save the text in proper way or encode it back to proper Hebrew?
EDIT:
This is so strange, although the text saved strange, I pull it back and I get the text correctly.
But when I save them to NSUserDefaults, it show me this strange encoding.
NSString *tempKeyToStore = [NSString stringWithFormat:#"wall_post_%d", indexPath.row];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
NSLog(#"\n\nWall messages: %#", [self.sharedPrefs objectForKey:tempKeyToStore]);
tempArray = [self.sharedPrefs objectForKey:tempKeyToStore];
NSString *tempOwner = [tempArray objectAtIndex:0];
NSLog(#"\n\nOWNER: %#", tempOwner);
If you use NSLog(#"%#", ...) to print the description of an array or dictionary, all non-ASCII characters are printed using a \Unnnn escape sequence:
NSArray *a = [NSArray arrayWithObject:#"מערכת"];
NSLog(#"%#", a);
Output:
(
"\U05de\U05e2\U05e8\U05db\U05ea"
)
(The reason is that the description method of NSArray and NSDictionary
uses the Old-Style ASCII Property Lists format,
which, as the name indicates, allows only ASCII characters.)
If you print the description of a string, all characters are properly displayed:
NSLog(#"%#", [a objectAtIndex:0]);
Output:
מערכת
So this is only a display issue.
Try doing something like this:
NSString *someObject = //your object that needs decode
NSString *decodedObject = [NSString
stringWithCString:[someObject cStringUsingEncoding:NSUTF8StringEncoding]
encoding:NSNonLossyASCIIStringEncoding];
NSLog(#"decodedObject = %#", decodedObject);
Edit: There's probably something wrong in your code someplace else because this:
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray addObject:#"בדיקה"];
[[NSUserDefaults standardUserDefaults] setObject:tempArray forKey:#"test"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSMutableArray *test2=[[NSUserDefaults standardUserDefaults] objectForKey:#"test"];
NSLog(#"test2: %#",[test2 objectAtIndex:0]);
works fine.
Well, can you post the code behind sharedPrefs?
When i tried to save a simple hebrew to userdefault it worked just fine.
NSString *tempKeyToStore = #"KEY";
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray addObject:#"שלום שלום"];
[[NSUserDefaults standardUserDefaults] setObject:tempArray forKey:tempKeyToStore];
[[NSUserDefaults standardUserDefaults] synchronize];
Read it later -
//
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *tempArray = [defaults objectForKey:#"KEY"];
for (NSString* str in tempArray)
{
NSLog(#"%#", str);
}
Hope i helped..

Setting up a plist to store application data (not settings) for an iPhone game

I am writing an iPhone game and have it working well with my level data hard coded but I would like to store the level data in a plist a load it at launch. I have never used plists and am having trouble understanding how I should set the plist up based on my data model.
Here is how I have it hard coded now:
(in my appDelegate)
- (void)loadLevels {
//setup NSNumber objects to load into sequences
NSNumber * rID = [[[NSNumber alloc] initWithInt:0] autorelease];
NSNumber * bID = [[[NSNumber alloc] initWithInt:1] autorelease];
NSNumber * gID = [[[NSNumber alloc] initWithInt:2] autorelease];
NSNumber * yID = [[[NSNumber alloc] initWithInt:3] autorelease];
NSNumber * rbID = [[[NSNumber alloc] initWithInt:4] autorelease];
NSNumber * rgID = [[[NSNumber alloc] initWithInt:5] autorelease];
NSNumber * ryID = [[[NSNumber alloc] initWithInt:6] autorelease];
NSNumber * bgID = [[[NSNumber alloc] initWithInt:7] autorelease];
NSNumber * byID = [[[NSNumber alloc] initWithInt:8] autorelease];
NSNumber * gyID = [[[NSNumber alloc] initWithInt:9] autorelease];
//Level One's Sequence
NSMutableArray * aSequence = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
[aSequence addObject: rID];
[aSequence addObject: bID];
[aSequence addObject: gID];
[aSequence addObject: yID];
[aSequence addObject: rbID];
[aSequence addObject: rgID];
[aSequence addObject: ryID];
[aSequence addObject: bgID];
[aSequence addObject: byID];
[aSequence addObject: gyID];
// Load level One
_levels = [[[NSMutableArray alloc] init] autorelease];
Level *level1 = [[[Level alloc] initWithLevelNum:1 levelSpeed:1.0 levelSequence:aSequence] autorelease];
[_levels addObject:level1];
//do the same thing for subsequent levels//
}
(this is how I have my Level Class implemented)
#import "Level.h"
#implementation Level
#synthesize levelNum = _levelNum;
#synthesize levelSpeed = _levelSpeed;
#synthesize levelSequence = _levelSequence;
- (id)initWithLevelNum:(int)levelNum levelSpeed:(float)levelSpeed levelSequence:(NSMutableArray *)levelSequence {
if ((self = [super init])) {
self.levelNum = levelNum;
self.levelSpeed = levelSpeed;
self.levelSequence = [[[NSMutableArray alloc] initWithArray:levelSequence] autorelease];
}
return self;
}
- (void)dealloc {
[_levelSequence release];
_levelSequence = nil;
[super dealloc];
}
#end
I'm just not getting how to set up a plist to store my data to match my model. Can anyone give me some advise please?
ADDITION:
(here is how I think I need to setup the plist - the data model is simply the three variables initializing my level (above). If you look at my current plist it might be more clear how it is setup, but each level is comprised of: a level number, a level speed, and an array of numbers denoting the required sequence for that level.)
Now, if I do have this setup correctly how do I load the values into my program?
Add your plist file as a resource file in your project. Say, it's name is config.plist
Get the path for the resource file. (Though, be careful of [NSBundle mainBundle] as it will not return the unit test bundle in a unit test.)
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"config" ofType:#"plist"];
Your root object is an array of levels. Load it in a NSArray.
// this is autoreleased. you can retain it if needed
NSArray *levelArray = [NSArray arrayWithContentsOfFile:plistPath];
Now you have the array of levels. Each level is a dictionary. Load the level i (counting from 0).
NSDictionary *level = [levelArray objectAtIndex:i];
Now you can get the objects from level dictionary by using objectForKey method. For example, to get the sequence array:
NSArray *seq = [level objectForKey:#"levelSequence"];
You can loop through the levelArray to alloc, init and add to levels array for all your levels.
Hope it helps. Please note that I have not compiled the code, so there might be some typos.
What you should do is create an NSDictionary with all of the applicable data that you want, and read it from and write it to NSUserDefaults.

Resources