nsstring to nsmutable array - nsmutablearray

I'm making an app in which i want to access the contact's first name and store them in to nsmutable array so that i can get the values of that array like array[0] up to array[i-1] and print them in table view.Here is my code:
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil)
{
contacts_Image_List=[[NSMutableArray alloc]init];
NSLog(#"Succesful.");
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSUInteger i = 0;
for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
person.firstName = firstName;
person.lastName = lastName;
person.fullName = fullName;
// person.userThumb[i]=firstName;
//[person.userThumb[i] addObject:#"firstName"];
//above line gives null
NSLog(#"%#",person.userThumb[i]);
my mutable array is in Person.h class.

On each iteration just do:
[person.yourMutableArray addObject:fullName]
Just ensure that your MutableArray has already been allocated, and that you only allocate it once.

Related

For Loop from Core Data

I have a question, I have 2 arrays (date and descriere), one is keeping a date which I select from a datePicker the other one is an array with strings, Both arrays are fetched from CoreData.
-(void)generateLocalNotification {
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"AddEntrySettings"];
fetchRequest.resultType = NSDictionaryResultType;
NSArray *result = [coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:nil];
NSMutableArray *date = [result valueForKey:#"date"];
NSMutableArray *descriere = [result valueForKey:#"descriere"];`
if (date != nil) {
for (NSString *stringDate in date) {
NSDateFormatter *format = [[NSDateFormatter alloc]init];
[format setDateFormat:#"MM/dd/yyyy h:mm a"];
[format setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
self.date = [format dateFromString:stringDate];
NSLog(#"LOG:%#",date);
localNotification.fireDate = [self.date dateByAddingTimeInterval:0];
localNotification.timeZone = [NSTimeZone timeZoneWithName:#"GMT"];
for (int i = 0; i < descriere.count; i++) {
localNotification.alertBody = descriere[i];
}
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.userInfo = #{#"id" : #42};
UIApplication *app = [UIApplication sharedApplication];
[app scheduleLocalNotification:localNotification];
}
}
}
When I try to fireDate everything is working fine, every time when a date from array is matching with local time I receive a notification till I try to add alertBody, when I make a for loop for alertBody every time is showing just last entry from my NSArray. In CoreData the both entries I adding in the same time. Where is my mistake? How can I make every time to receive a notification with alertBody that matching with date that I insert in CoreData?
The problem is that this for loop:
for (int i = 0; i < descriere.count; i++) {
localNotification.alertBody = descriere[i];
}
will, for every stringDate, iterate to the last item in your descriere array. What you want is to find the index of stringDate in date, and then find the string at the same index in descriere.
But there is an easier way. Don't unpack result into two separate arrays, just access the different values from within the for loop:
if (result != nil) {
for (NSDictionary *dict in result) {
NSString *stringDate = [dict objectForKey:#"date"];
// if necessary, test whether stringDate is nil here
NSDateFormatter *format = [[NSDateFormatter alloc]init];
[format setDateFormat:#"MM/dd/yyyy h:mm a"];
[format setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
self.date = [format dateFromString:stringDate];
NSLog(#"LOG:%#",date);
localNotification.fireDate = [self.date dateByAddingTimeInterval:0];
localNotification.timeZone = [NSTimeZone timeZoneWithName:#"GMT"];
localNotification.alertBody = [dict objectForKey:#"descriere"];
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.userInfo = #{#"id" : #42};
UIApplication *app = [UIApplication sharedApplication];
[app scheduleLocalNotification:localNotification];
}
}

Init NSManagedObject subclass

I would like to know if it's possible to init a subclass of NSManagedObject ?
I have a class "Actualite" which is a subclass of NSManagedObject and when I want to initialize this class, I get this error :
"CoreData: error: Failed to call designated initializer on NSManagedObject class Actualite", and the app crashes after this message "-[Actualite setTitre:]: unrecognized selector sent to instance 0x8433be0"
Here is my code :
-(void) recupererActualites {
listeNouvellesActualites = [[NSMutableArray alloc] init];
// Convert the supplied URL string into a usable URL object
NSURL *url = [NSURL URLWithString:FACE06_RSS];
// Create a new rssParser object based on the TouchXML "CXMLDocument" class, this is the
// object that actually grabs and processes the RSS data
CXMLDocument *rssParser = [[CXMLDocument alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding options:0 error:nil];
// Create a new Array object to be used with the looping of the results from the rssParser
NSArray *resultNodes = NULL;
// Set the resultNodes Array to contain an object for every instance of an node in our RSS feed
resultNodes = [rssParser nodesForXPath:#"//item" error:nil];
NSMutableArray* tmp = [[NSMutableArray alloc] init];
for (CXMLElement* resultElement in resultNodes) {
// Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries
NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];
NSMutableArray* categories = [[NSMutableArray alloc] init];
// Create a counter variable as type "int"
int counter;
// Loop through the children of the current node
for(counter = 0; counter < [resultElement childCount]; counter++) {
// Add each field to the blogItem Dictionary with the node name as key and node value as the value
if([[[resultElement childAtIndex:counter] name] isEqual:#"category"])
[categories addObject:[[resultElement childAtIndex:counter] stringValue]];
else {
if ([[resultElement childAtIndex:counter] stringValue] != nil)
[blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
else
[blogItem setObject:#"" forKey:[[resultElement childAtIndex:counter] name]];
}
}
Actualite* actu = [[Actualite alloc] init];
[blogItem setObject:categories forKey:#"categories"];
[actu initWithDictionnary:blogItem];
[tmp addObject:actu];
//[actu release];
[categories release];
[blogItem release];
}
listeNouvellesActualites = tmp;
[rssParser release];
resultNodes = nil;
// Stockage des actualités en local
[self stockerActualites];
}
And the initWithDictionary method set all the attributes of the Actualite class.
I also tried
Actualite* actu = [[Actualite alloc] initWithEntity:[NSEntityDescription entityForName:#"Actualite" inManagedObjectContext:managedObjectContext] insertIntoManagedObjectContext:managedObjectContext];
and
Actualite* actu = (Actualite*)[NSEntityDescription entityForName:#"Actualite" inManagedObjectContext:managedObjectContext];
instead of
Actualite* actu = [[Actualite alloc] init];
The errors disappear but the app stops at this point. I don't know what can I do...
Is someone already had this problem ?
Thanks a lot !
The idea is that you ask for a new object to be created inside a context and then you use it:
Actualite* actu = [NSEntityDescription insertNewObjectForEntityForName:#"Actualite" inManagedObjectContext:managedObjectContext];

Selecting TableView cell returns incorrect object

I followed a tutorial I found online to create a tableview with sections and an index from an array of custom objects. This code works with the exception that when I select a row in the table I the index path for that section and not for the entire array. I can see why it doesn't work but I can't figure out how to address the fix, this is my cell for tableview code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"NameCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int displayOrder = [defaults integerForKey:#"displayOrder"];
int sortOrder = [defaults integerForKey:#"sortOrder"];
NSString *alphabet = [listIndex objectAtIndex:[indexPath section]];
NSPredicate *sectionPredicate = [[NSPredicate alloc] init];
if (sortOrder == 1) {
//NSLog(#"fName is predicate at cell level");
sectionPredicate = [NSPredicate predicateWithFormat:#"fName beginswith[c] %#", alphabet];
} else {
//NSLog(#"lName is predicate at cell level");
sectionPredicate = [NSPredicate predicateWithFormat:#"lName beginswith[c] %#", alphabet];
}
NSArray *sectionContacts = [filteredList filteredArrayUsingPredicate:sectionPredicate];
if (isSearching) {
current = [filteredList objectAtIndex:indexPath.row];
} else{
current = [sectionContacts objectAtIndex:indexPath.row];
}
if (displayOrder == 1) {
NSString *fullName = [NSString stringWithFormat:#"%# %#",[current valueForKey:#"fName"],[current valueForKey:#"lName"]];
[cell.textLabel setText:fullName];
//NSLog(#"FirstNameFirst");
} else {
NSString *fullName = [NSString stringWithFormat:#"%# %#",[current valueForKey:#"lName"],[current valueForKey:#"fName"]];
[cell.textLabel setText:fullName];
//NSLog(#"LastNameFirst");
}
[cell.detailTextLabel setText:[current valueForKey:#"extension"]];
return cell; }
THen I call the segue with this code.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showContact"]) {
DetailViewController *dvc = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
NSDictionary *c = [filteredList objectAtIndex:path.row];
[dvc setCurrentContact:c];
[searchBar resignFirstResponder];
} }
The problem is that the objectAtIndex:path.row returns the index for that section but it isn't modified for the entire array, so if a name in the "B" section that is at index 4 of that section is tapped it returns the object at index 4 of the primary array. I have been scratching my head to figure out how to get the index for the full array and not for the one that is only local to that section.
I'll buy you a 6 pack of your favorite beverage if you can help!
Thanks!
You do it the same way that they do it in the first function, so change your prepareForSegue to this:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showContact"]) {
DetailViewController *dvc = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
NSDictionary *c;
NSString *alphabet = [listIndex objectAtIndex:[path section]];
NSPredicate *sectionPredicate = [[NSPredicate alloc] init];
if (sortOrder == 1) {
sectionPredicate = [NSPredicate predicateWithFormat:#"fName beginswith[c] %#", alphabet];
} else {
sectionPredicate = [NSPredicate predicateWithFormat:#"lName beginswith[c] %#", alphabet];
}
NSArray *sectionContacts = [filteredList filteredArrayUsingPredicate:sectionPredicate];
if (isSearching) {
c = [filteredList objectAtIndex:path.row];
} else{
c = [sectionContacts objectAtIndex:path.row];
}
[dvc setCurrentContact:c];
[searchBar resignFirstResponder];
}
}
Note that it would probably be best to pull the common code out and make a separate function instead of using it twice like this.

Is it possible to open addContactScreen from native app?

I want to replicate add contact like screen iPhone has. But I don't want to add contact in default phonebook instead I want to use the details in my app. Is it possible to open default add new contact screen and get all the data? If yes then how? A simple code snippet will be very helpful. Here is an image of add contact screen to better understand my question
You can try to add the contact to the address book, pull the data and then delete it from the address book. this is a fairly simple process.
I use this function to save all the person data to core data in my app. and then to delete the person from the addressBook.
+(void)savePersonDetails:(Person*)person{
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef ref = ABAddressBookGetPersonWithRecordID(addressBook,[person.ID intValue]);
ABMutableMultiValueRef multiPhones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(multiPhones); i++) {
NSString *phoneNumber = (NSString*)ABMultiValueCopyValueAtIndex(multiPhones, i);
CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(multiPhones, i);
NSString *phoneNumberLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);
CFRelease(locLabel);
Phone *phone =(Phone*)[NSEntityDescription insertNewObjectForEntityForName:#"Phone" inManagedObjectContext:person.managedObjectContext];
phone.number = phoneNumber;
phone.label = phoneNumberLabel;
phone.person = person;
[person addPhonesObject:phone];
[person release];
CFRelease(phoneNumber);
CFRelease(phoneNumberLabel);
}
CFRelease(multiPhones);
ABMutableMultiValueRef multiEmail = ABRecordCopyValue(ref, kABPersonEmailProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(multiEmail); i++) {
NSString *mail = (NSString*)ABMultiValueCopyValueAtIndex(multiEmail, i);
CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(multiEmail, i);
NSString *mailLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);
Mail *mailEntity =(Mail*)[NSEntityDescription insertNewObjectForEntityForName:#"Mail" inManagedObjectContext:person.managedObjectContext];
mailEntity.mail = mail;
mailEntity.label = mailLabel;
mailEntity.person = person;
[person addMailsObject:mailEntity];
CFRelease(locLabel);
[mail release];
[mailLabel release];
}
CFRelease(multiEmail);
ABMultiValueRef streets = ABRecordCopyValue(ref, kABPersonAddressProperty);
for (CFIndex j = 0; j<ABMultiValueGetCount(streets);j++){
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(streets, j);
CFStringRef typeTmp = ABMultiValueCopyLabelAtIndex(streets, j);
CFStringRef lbl = ABAddressBookCopyLocalizedLabel(typeTmp);
NSString *street = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressStreetKey) copy];
NSString *city = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressCityKey) copy];
NSString *state = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressStateKey) copy];
NSString *zip = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressZIPKey) copy];
NSString *country = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressCountryKey) copy];
Address *addressEntity =(Address*)[NSEntityDescription insertNewObjectForEntityForName:#"Address" inManagedObjectContext:person.managedObjectContext];
addressEntity.label = (NSString*)lbl;
addressEntity.street = street;
addressEntity.city = city;
addressEntity.state = state;
addressEntity.zip = zip;
addressEntity.country = country;
[street release];
[city release];
[state release];
[zip release];
[country release];
CFRelease(dict);
CFRelease(lbl);
CFRelease(typeTmp);
addressEntity.person = person;
[person addAddressesObject:addressEntity];
}
CFRelease(streets);
ABMutableMultiValueRef multiURL = ABRecordCopyValue(ref, kABPersonURLProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(multiURL); i++) {
NSString *url = (NSString*)ABMultiValueCopyValueAtIndex(multiURL, i);
CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(multiPhones, i);
NSString *urlLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel);
Url *urlEntity =(Url*)[NSEntityDescription insertNewObjectForEntityForName:#"Url" inManagedObjectContext:person.managedObjectContext];
urlEntity.url = url;
urlEntity.label = urlLabel;
urlEntity.person = person;
[person addUrlsObject:urlEntity];
CFRelease(locLabel);
[urlLabel release];
[url release];
}
CFRelease(multiURL);
ABAddressBookRemoveRecord(addressBook, ref, nil);
ABAddressBookSave(addressBook, nil);
CFRelease(addressBook);
if (![person.managedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}

Error occurs when I convert NSMutableArray to NSArray

I want to convert NSMutableArray to NSArray to it gives error following is code
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
tempPeoples=[[NSMutableArray alloc]init];
for(int i=0;i<nPeople;i++){
ABRecordRef i1=CFArrayGetValueAtIndex(allPeople, i);
[tempPeoples addObject:i1];
//[peoples addObject:i1];
}// end of the for loop
// Peoples is NSArray
// peoples=[[NSArray alloc] initWithArray: tempPeoples];
peoples=[NSArray arrayWithArray:tempPeoples];
Please help
I found the solution using following code
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *allPeople = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
tempPeoples= [NSMutableArray arrayWithCapacity:0];
for(int i=0;i<nPeople;i++){
ABRecordRef i1=CFArrayGetValueAtIndex(allPeople, i);
NSString* name = (NSString *)ABRecordCopyValue(i1,kABPersonFirstNameProperty);
[tempPeoples addObject:name];
// [peoples addObject:i1];
}// end of the for loop
peoples=[NSArray arrayWithArray:tempPeoples];

Resources