fast enumeration and selecting objects - nsarray

I've an array (tempList) populated with records read from a sqlite data source. I want to sort these records based on 'region'. So I've set up the following NSMUtableArrays: _Asia, _Africa, _CentralAmerica, _southAmerica.
The method compiles without any errors. Where the 'if' statements return true, it executes the 'addObject' but the element is not added to the array.
- (void) sortIntoRegions: tempList
{
for (beans *arrayElement in tempList) {
NSLog(#"region: %#", arrayElement.region);
if ([arrayElement.region isEqualToString:#"Africa"]) {
[_africa addObject:arrayElement.name];
} else if ([arrayElement.region isEqualToString: #"Asia & South Pacific"]) {
[_asia addObject:arrayElement.name];
}
else if ([arrayElement.region isEqualToString: #"Central America"]) {
[_centralAmerica addObject:arrayElement];
} else if ([arrayElement.region isEqualToString: #"South America"]) {
[_southAmerica addObject:arrayElement];
}
}
}

I'm going to go out on a limb and guess that you have declared _africa, _asia, _centralAmerica, and _southAmerica to be NSMutableArray *, but you have not initialized them. That is, you have not written any code like this:
_africa = [[NSMutableArray alloc] init];
_asia = [[NSMutableArray alloc] init];
_centralAmerica = [[NSMutableArray alloc] init];
_southAmerica = [[NSMutableArray alloc] init];
Your instance variables are set to nil when your object is created. Sending a message (like addObject:) to nil has no effect (and doesn't print a warning or error message).

Related

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");
}

PKPass files getting replaced on Passbook for files in the same app

My App deals with downloading coupons & save into Passbook. But each time I download a different coupon, file is getting replaced on Passbook.
Below given is my code to add my coupons to Passbook :
Step 1 : Added 'PassKit' framework to the project & imported the same.
Step 2 : Added 'PKAddPassesViewControllerDelegate' on my h file.
Step 3 :
- (void) generatePass {
if (![PKPassLibrary isPassLibraryAvailable]) {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"PassKit not available"
delegate:nil
cancelButtonTitle:#"Pitty"
otherButtonTitles: nil] show];
return;
}
else {
NSData *passData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://(url).pkpass"]];
NSError* error = nil;
PKPass *newPass = [[PKPass alloc] initWithData:passData
error:&error];
if (error!=nil) {
[[[UIAlertView alloc] initWithTitle:#"Passes error"
message:[error
localizedDescription]
delegate:nil
cancelButtonTitle:#"Ooops"
otherButtonTitles: nil] show];
return;
}
PKAddPassesViewController *addController =
[[PKAddPassesViewController alloc] initWithPass:newPass];
addController.delegate = self;
[self presentViewController:addController
animated:YES
completion:nil];
}
}
Passbook indexes passes by serialNumber and passTypeIdentifier. When adding a pass, if a pass with a matching serialNumber and passTypeIdentifier already exists in a user's pass library, that pass will be overwritten by the pass being added.
To add multiple passes for the same passTypeIdentifer you will have to generate a unique serialNumber for each new pass.

issue is running and stopping CFRunLoop

i have situation where i need to wait till one block is get completed and then only move forward with my code for that i use CFRunLooprun and stop this is how do it i will explain more things in comment in my code
[self fatchAllEvent]; // BLOCK IS IN THIS METHOD
NSLog(#"loop will start");
CFRunLoopRun();
NSLog(#"LOOP IS STOOPED");
-(void)fatchAllEvent{
events = [[NSMutableArray alloc]init];
// // Get the appropriate calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
eventStore = [[EKEventStore alloc] init];
if ([eventStore respondsToSelector:#selector(requestAccessToEntityType:completion:)])
{
// __block typeof (self) weakSelf = self; // replace __block with __weak if you are using ARC
dispatch_async(dispatch_get_main_queue(), ^{
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
if (granted)
{
[events removeAllObjects];
NSLog(#" granted");
NSLog(#"User has granted permission!");
// Create the start date components
NSDateComponents *twoYearAgoComponents = [[NSDateComponents alloc] init];
twoYearAgoComponents.year = -2;
NSDate *oneDayAgo = [calendar dateByAddingComponents:twoYearAgoComponents
toDate:[NSDate date]
options:0];
// Create the end date components
NSDateComponents *twoYearFromNowComponents = [[NSDateComponents alloc] init];
twoYearFromNowComponents.year = 2;
NSDate *oneYearFromNow = [calendar dateByAddingComponents:twoYearFromNowComponents
toDate:[NSDate date]
options:0];
// Create the predicate from the event store's instance method
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:oneDayAgo
endDate:oneYearFromNow
calendars:nil];
// Fetch all events that match the predicate
events =(NSMutableArray*) [eventStore eventsMatchingPredicate:predicate];
NSLog(#"The content of array is%#",events);
}
else
{
NSLog(#"Not granted");
}
NSLog(#"LOOP WILL STOP"); // THIS GETS PRINT
CFRunLoopStop(CFRunLoopGetCurrent()); // BUT LOOP IS NOT STOPPING HERE SO MY APP JUST GET HANGED ;
}];
});
}
else
{
[events removeAllObjects];
NSLog(#"Autometiclly granted permission!");
// Create the start date components
NSDateComponents *twoYearAgoComponents = [[NSDateComponents alloc] init];
twoYearAgoComponents.year = -2;
NSDate *oneDayAgo = [calendar dateByAddingComponents:twoYearAgoComponents
toDate:[NSDate date]
options:0];
// Create the end date components
NSDateComponents *twoYearFromNowComponents = [[NSDateComponents alloc] init];
twoYearFromNowComponents.year = 2;
NSDate *oneYearFromNow = [calendar dateByAddingComponents:twoYearFromNowComponents
toDate:[NSDate date]
options:0];
// Create the predicate from the event store's instance method
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:oneDayAgo
endDate:oneYearFromNow
calendars:nil];
// Fetch all events that match the predicate
events =(NSMutableArray*) [eventStore eventsMatchingPredicate:predicate];
NSLog(#"The content of array is%#",events);
}
}
You can't do that this way - you have to call your function, and then in the completion block of the async dispatch, at the end, call a function that continues with what you want to do.
In your above code you mix up asynchronous programming with synchronous execution, that won't work.

Custom objects in array stored in a plist

I've got some custom class objects that i store in an array, this array is then stored in a dictionary with a key. This is then saved and will be loaded when the app is loaded/ reloaded.
Now the issues is that i can't seem to get the custom objects back out, when i load the array it comes back as empty. I must be doing something wrong with either writing or loading the data but i can't figure out what exactly.
Here's the code i have so far:
CustomClass.H file:
#import <Foundation/Foundation.h>
#interface PersonClass : NSObject <NSCoding>
#property (nonatomic,strong) NSString *personName;
#property (nonatomic,strong) NSString *personNo;
#property (nonatomic,strong) NSString *personNotes;
#property (nonatomic) BOOL switchPersonality;
#property (nonatomic) BOOL switchChemistry;
#property (nonatomic) BOOL switchLooks;
#property (nonatomic) BOOL switchHumour;
#property (nonatomic) int personRating;
#property (nonatomic,strong) NSNumber *personRecord;
- (id)initWithName:(NSString *)iPersonName PersonNo:(NSString *)iPersonNo PersonNotes:(NSString *)iPersonNotes SwitchChemistry:(BOOL *)iSwitchChemistry SwitchHumour:(BOOL *)iSwitchHumour SwitchLooks:(BOOL *)iSwitchLooks SwitchPersonality:(BOOL *)iSwitchPersonality PersonRating:(int *)iPersonRating PersonRecord:(NSNumber *)iPersonRecord;
#end
Custom Class.M file:
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:personName forKey:#"pName"];
[aCoder encodeObject:personNo forKey:#"pNo"];
[aCoder encodeObject:personNotes forKey:#"pNotes"];
[aCoder encodeInt:personRating forKey:#"pRating"];
[aCoder encodeObject:personRecord forKey:#"pRecord"];
[aCoder encodeBool:switchChemistry forKey:#"sChemistry"];
[aCoder encodeBool:switchHumour forKey:#"sHumour"];
[aCoder encodeBool:switchLooks forKey:#"sLooks"];
[aCoder encodeBool:switchPersonality forKey:#"sPersonality"];
}
-(id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]){
self.personName = [aDecoder decodeObjectForKey:#"pName"];
self.personNo = [aDecoder decodeObjectForKey:#"pNo"];
self.personNotes = [aDecoder decodeObjectForKey:#"pNotes"];
self.personRating = [aDecoder decodeIntForKey:#"pRating"];
self.personRecord = [aDecoder decodeObjectForKey:#"pRecord"];
self.switchChemistry = [aDecoder decodeBoolForKey:#"sChemistry"];
self.switchHumour = [aDecoder decodeBoolForKey:#"sHumour"];
self.switchLooks = [aDecoder decodeBoolForKey:#"sLooks"];
self.switchPersonality = [aDecoder decodeBoolForKey:#"sPersonality"];
}
return self;
}
The save Method:
- (void)saveData{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"data.plist"];
NSLog(#"PList Path %#",plistPath);
//new array
NSMutableArray *newEntries = [[NSMutableArray alloc]init];
NSLog(#"NEW ENTRIES BEFORE %#",newEntries);
for (PersonClass *person in peopleEntries) {
//encode the object
[NSKeyedArchiver archivedDataWithRootObject:person];
// add the object to the entries
[newEntries addObject:person];
}
NSLog(#"NEW ENTRIES AFTER %#",newEntries);
[newEntries writeToFile:plistPath atomically:YES];
// create dictionary with arrays and their corresponding keys
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSMutableArray arrayWithObjects:newEntries, recordId, nil] forKeys:[NSMutableArray arrayWithObjects: #"peopleEntries",#"recordId", nil]];
NSLog(#"DICTIONARY IS IN SAVE %#",plistDict);
NSString *error = nil;
// check if plistData exists
if(plistDict)
{
// write plistData to our Data.plist file
[plistDict writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
}
NSLog(#"Save RUN");
}
The load Method:
- (void)loadData{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"data.plist"];
NSLog(#"PList Path %#",plistPath);
// check to see if data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// return without loading
NSLog(#"RETURNING");
return;
}
// get saved dictionary
NSDictionary *dictionaryTemp = [[NSDictionary alloc]initWithContentsOfFile:plistPath];
NSLog(#"DICTIONARY IS LOAD %#",dictionaryTemp);
if (!dictionaryTemp)
{
NSLog(#"Error reading plist:");
}
// temporary array
NSMutableArray *holderOne = [dictionaryTemp objectForKey:#"peopleEntries"];
// array to be populated
NSMutableArray *holderTwo = [[NSMutableArray alloc]init];
NSLog(#"HOLDER ONE IS BEFORE %#",holderOne);
NSLog(#"HOLDER TWO IS BEFORE %#",holderTwo);
// go through the array and pull out person classes
for (NSData *person in holderOne) {
// temp array
NSData *entry = [holderOne objectAtIndex:person]; // check the object at index might be an issue???
NSLog(#"ENTRY IS %#",entry);
//deencode the object
[NSKeyedUnarchiver unarchiveObjectWithData:entry];
// add the object to the entries
[holderTwo addObject:entry];
}
NSLog(#"HOLDER ONE IS AFTER %#",holderOne);
NSLog(#"HOLDER TWO IS AFTER %#",holderTwo);
// assign values
peopleEntries = [NSMutableArray arrayWithArray:holderTwo];
NSLog(#"DICTIONARY IS AFTER ADDING %#",dictionaryTemp);
recordId = [NSNumber numberWithInt:[[dictionaryTemp objectForKey:#"recordId"]integerValue]];
NSLog(#"recordId is %#",recordId);
NSLog(#"LOAD RUN");
}
OK i finally discovered the issue, i was extending my class from the NSObject subclass which does not implement the NSCoder protocol so i was encoding and decoding my object in the incorrect way. It should have been done in the following way:
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.personName = [decoder decodeObjectForKey:#"pName"];
self.personNo = [decoder decodeObjectForKey:#"pNo"];
self.personNotes = [decoder decodeObjectForKey:#"pNotes"];
self.personRating = [decoder decodeObjectForKey:#"pRating"];
self.switchChemistry = [decoder decodeBoolForKey:#"sChemistry"];
self.switchHumour = [decoder decodeBoolForKey:#"sHumour"];
self.switchLooks = [decoder decodeBoolForKey:#"sLooks"];
self.switchPersonality = [decoder decodeBoolForKey:#"sPersonality"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:personName forKey:#"pName"];
[encoder encodeObject:personNo forKey:#"pNo"];
[encoder encodeObject:personNotes forKey:#"pNotes"];
[encoder encodeObject:personRating forKey:#"pRating"];
[encoder encodeBool:switchChemistry forKey:#"sChemistry"];
[encoder encodeBool:switchHumour forKey:#"sHumour"];
[encoder encodeBool:switchLooks forKey:#"sLooks"];
[encoder encodeBool:switchPersonality forKey:#"sPersonality"];
}
These objects were then added into an array and i was looping through each object in the array and decoding. This was not correct you can simply encode or decode the entire array with te objects as so:
Decode:
NSData *peopleData;
peopleEntries = [NSKeyedUnarchiver unarchiveObjectWithData:peopleData];
Encode:
NSMutableArray *peopleEntries;
NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:[[GlobalData sharedGlobalData]peopleEntries]];

Passing an NSArray populated with NSDictionaries to a NSAppleScript

So I have an Apple Script that is running one of the functions of my program like so:
[ NSThread detachNewThreadSelector:#selector(runAppleScriptTask)
toTarget:self
withObject:nil];
Using this method:
-(void)runAppleScriptTask
{
mainBundle = [NSBundle bundleForClass:[self class]];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary* errorDict;
NSAppleEventDescriptor* returnDescriptor = NULL;
NSString *scriptPath = [[NSBundle mainBundle] pathForResource: #"AttemptToRepair"
ofType: #"scpt"];
NSLog(#"Found AppleScript Path:%#",scriptPath);
// Run the Apple Script
NSAppleScript *scriptObject = [[NSAppleScript alloc]initWithContentsOfURL:[NSURL fileURLWithPath: scriptPath]
error:&errorDict];
returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
NSLog(#"Return Discriptor,%#",returnDescriptor);
NSString *returnValue = #"User Canceled";
NSMutableDictionary *returnDict = [[NSMutableDictionary alloc] init];
if ([ returnDescriptor stringValue]) {
returnValue = [ returnDescriptor stringValue];
[ returnDict setValue:returnValue forKey:#"returnValue"];
}
else {
if (errorDict) {
returnValue = [ returnDescriptor stringValue];
[ returnDict setValue:errorDict forKey:#"errorDict"];
}
}
NSLog(#"Found Return Value: %#",returnValue);
[scriptObject release];
// Notify
[[NSNotificationCenter defaultCenter]
postNotificationName:AttemptToRepairCompleteNotification
object:self
userInfo:returnDict];
[pool drain];
}
I have a NSArray (Full of Statuses) that I need to pass to the Apple Script. Right now I am dumping the file to a plist:
// File Drop the Global Status Array
BOOL gsaWroteSuccess = [ issueFile writeToFile:#"/private/tmp/gsa.plist" atomically:YES];
if (gsaWroteSuccess) {
NSLog(#"Wrote the current Global Status Array to file");
// Let objects know the Global Status is being updated
NSMutableDictionary *globalStatusUpdate = [[NSMutableDictionary alloc] init];
// Pass the mutated Data to our NSTable
[ globalStatusUpdate setValue:issueFile forKey:#"globalStatusArray"];
[[NSNotificationCenter defaultCenter]
postNotificationName:StatusUpdateNotification
object:self
userInfo:globalStatusUpdate];
}
else {
NSLog(#"Unable to write Global Status Array to file");
}
Which I can easily pick back up in the Apple Script via System Events plist infrastructure , but I would really rather do this all in RAM. Now I think I could use the property syntax mentioned here , http://developer.apple.com/library/mac/#releasenotes/ScriptingAutomation/RN-AppleScriptObjC/_index.html but I need this to work on 10.5,10.6 and 10.7 so I can't use anything that was not released yet. Any thoughts on a slick in memory based way to pass an NSArray full or NSDicitonary objects to my Apple Script (which will become a list in the Apple Script)?
Here is the Apple Script code for the file drop methodology right now if it helps
script AttemptToRepair
property parent : class "NSObject"
activate
set thePListPath to POSIX path of "/tmp/gsa.plist"
tell application "System Events"
set the plist_path to "/tmp/gsa.plist"
set the plist_file to property list file plist_path
set itemNodes to property list items of property list item "globalStatusArray" of plist_file
repeat with i from 1 to number of items in itemNodes
set itemNode to item i of itemNodes
set discription to value of property list item "discription" of itemNode
set metric to value of property list item "metric" of itemNode
set reason to value of property list item "reason" of itemNode
set status to value of property list item "status" of itemNode
display dialog "discription:" & discription & return & ¬
"metric:" & metric & return & ¬
"reason:" & reason & return & ¬
"status:" & status
end repeat
end tell
end script
run AttemptToRepair