Parse PFObject save results to NSMutableArray - ios

I'm looking to save values within from the PFObjet and save them to multiple NSMutableArrays. Let me explain. I'm download information from the Partisipants class within Parse. The Partisipants class contains multiple NSString values, such as name, phoneNumber, etc. I'm looking to scrape that information from the return value of the query, and add each instance of a new objectID to the NSMutableArray. Assume there are multiple rows, or userIDs to scrape into the NSMutableArray.
PFQuery *query = [PFQuery queryWithClassName:#"Partisipants"];
[query setLimit: 600];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded. The first 600 objects are available in objects
self.objectsFromParse = objects;
NSLog(#"%#", self.objectsFromParse);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
Edit
This is my return result for executing this query (personal information was modified):
(
"<Partisipants:S420zHiNFT:(null)> {\n additionalDonation = \"100.00\";\n emailAddress = \"somewhere#email.com\";\n emergencyPhone = 12345678901;\n hasArrived = NO;\n name = \"James\";\n phoneNumber = 12345678901;\n}",
"<Partisipants:9BpoFxO1zx:(null)> {\n additionalDonation = \"500.00\";\n emailAddress = \"someguy#email.com\";\n emergencyPhone = 12345678901;\n hasArrived = NO;\n name = \"Michael\";\n phoneNumber = 12345678901;\n}"
)

If you want to store emails, names, objectId's etc. each in new mutableArrays, you could do:
NSMutableArray * usernames = [NSMutableArray array];
NSMutableArray * emails = [NSMutableArray array];
NSMutableArray * objectIds = [NSMutableArray array];
for (PFObject * participant in objects) {
if (participant[#"name"]) [usernames addObject:participant[#"name"]];
if (participant[#"emailAddress"]) [emails addObject:participant[#"emailAddress"]];
[objectIds addObject:participant.objectId];
}

Create your array of participants. Then loop over them and build your mutable arrays(nameArray, email array, etc). Note that this is a very bad approach if some of the participants data is optional. How would you signify no email address for instance? You can't use nil in arrays so you'd have to represent it using NSNull or an empty string...

You may need help from KVC.
#import <Foundation/Foundation.h>
#interface Object : NSObject
#property (nonatomic, strong, readonly) NSString *name;
#property (nonatomic, strong, readonly) NSString *objectId;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
#end
#interface Object ()
#property (nonatomic, strong) NSDictionary *dictionary;
#end
#implementation Object
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
if (self = [super init]) {
self.dictionary = dictionary;
}
return self;
}
- (NSString *)name
{
return self.dictionary[#"name"];
}
- (NSString *)objectId
{
return self.dictionary[#"objectId"];
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Object *object0 = [[Object alloc] initWithDictionary:#{#"name": #"victor", #"objectId": #"001"}];
Object *object1 = [[Object alloc] initWithDictionary:#{#"name": #"evan", #"objectId": #"002"}];
Object *object2 = [[Object alloc] initWithDictionary:#{#"name": #"gerry"}];
Object *object3 = [[Object alloc] initWithDictionary:#{#"name": #"tony", #"objectId": #"004"}];
NSArray *array = #[object0, object1, object2, object3];
NSArray *objectIds = [array valueForKey:#"objectId"];
NSLog(#"%#", objectIds);
NSArray *names = [array valueForKey:#"name"];
NSLog(#"%#", names);
NSArray *filteredObjectIds = [objectIds filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF != nil"]];
NSLog(#"%#", filteredObjectIds);
NSMutableArray *mutableArray = [filteredObjectIds mutableCopy];
NSLog(#"%#", mutableArray);
}
return 0;
}
Console log:
2017-11-03 16:33:29.092837+0800 Test[50097:3891576] (
001,
002,
"<null>",
004
)
2017-11-03 16:33:29.093079+0800 Test[50097:3891576] (
victor,
evan,
gerry,
tony
)
2017-11-03 16:33:29.093317+0800 Test[50097:3891576] (
001,
002,
004
)
2017-11-03 16:33:29.093401+0800 Test[50097:3891576] (
001,
002,
004
)
Program ended with exit code: 0

Related

object is not saved in array

I have the following code that parses json into custom objects, parsing works fine i have a problem with saving the objects.
-(void)handleCities:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"_getInitialData" object:nil];
if(![notification object])
{
NSLog(#"Something went wrong");
return;
}
// Convert data to a dictionary
NSMutableDictionary * data = [NSJSONSerialization JSONObjectWithData:(NSMutableData *) [notification object] options:NSJSONReadingMutableContainers error:nil];
// Loop over all the data
if([data objectForKey:#"data"] != (id)kCFBooleanFalse)
{
for(int i = 0; i < [[[data objectForKey:#"data"] objectForKey:#"cities"] count]; i++)
{
CityObject * object = [[CityObject alloc] init];
// Loop over all the properties
for(NSString * key in [[[data objectForKey:#"data"] objectForKey:#"cities" ] objectAtIndex:i])
{
NSString * _key = key;
if([object._remap objectForKey:key])
{
NSString * value = [object._remap objectForKey:_key];
NSLog(#"Notice [%#] Remapping \"%#\" to \"%#\"", self.class, _key, value);
_key = value;
}
// Save the value for easy access
NSString * value = [[[[data objectForKey:#"data"] objectForKey:#"cities" ] objectAtIndex:i] objectForKey:_key];
// Does the value have a value
if((id)value == [NSNull null])
{
value = #"";
}
// Set the value for key
[object setValue:value forKey:_key];
}
NSMutableDictionary * set = [[[data objectForKey:#"data"] objectForKey:#"cities"] objectAtIndex:i];
int count = (int)[[set objectForKey:#"categories"] count];
for(int b = 0; b < count; b++)
{
CategoryObject * category = [[CategoryObject alloc] init];
for(NSString * key in [[set objectForKey:#"categories"] objectAtIndex:b])
{
NSString * value = [[[set objectForKey:#"categories"] objectAtIndex:b] objectForKey:key];
if((id)value == [NSNull null])
{
value = #"";
}
[category setValue:value forKey:key];
}
NSLog(#"Category %#",category.class);
NSLog(#"Object : %#",object.class);
NSLog(#"Object Categories : %#",object.categories.class);
// i can print the category object fine here
[object.categories addObject:(CategoryObject *)category];
}
[self.cities addObject:object];
}
}
CityObject * city = [self.cities objectAtIndex:0];
CategoryObject * category = [city.categories objectAtIndex:0];
NSLog(#"Category Name : %#", category.name);
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"_getInitialData" object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"getInitialData" object:nil];
}
CityObject.h
#import <Foundation/Foundation.h>
#import "Object.h"
#interface CityObject : Object
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSString * id;
#property (nonatomic, strong) NSString * state;
#property (nonatomic, strong) NSString * image;
#property (nonatomic, strong) NSString * term_order;
#property (nonatomic, strong) NSMutableArray * categories;
#property (nonatomic, strong) NSMutableDictionary * _remap;
#end
CityObject.m
#import "CityObject.h"
#implementation CityObject
-(id)init
{
if(self = [super init])
{
self._remap = [[NSMutableDictionary alloc] init];
self.categories = [[NSMutableArray alloc] init];
[self._remap setObject:#"state" forKey:#"new_city"];
}
return self;
}
#end
CategoryObject.h
#import <Foundation/Foundation.h>
#import "Object.h"
#interface CategoryObject : Object
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSString * icon;
#property (nonatomic, strong) NSString * id;
#end
Before i add the CategoryObject to my array i can retrieve the values without a problem it is when i NSLog at the end i cannot get the values / objects out of the array's.
What am i doing wrong since it works great when i add the CityObjects but not when i "parse" the categories. I can read them fine before i add them to the object.categories
Error / Output
-[__NSDictionaryM name]: unrecognized selector sent to instance 0x7a482760
2015-03-24 09:21:05.649 10things[16968:337325] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryM name]: unrecognized selector sent to instance 0x7a482760'
Problem solved, i did not have a strong pointer to the model, the Dictionary was magically being replaced to a NSMutableDictionary Once i had a strong handle everything worked properly. (thanks for the code feedback)

NSInternalInconsistencyException for NSMutableArray

I'm trying to add objects to an NSMutableArray but it keeps giving me this error.:
NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object
I have researched this problem, and I'm not doing anything wrong that past people have done, so I have no idea what's wrong. Here is my code:
Group.h
#property (strong, nonatomic) NSString *custom_desc;
#property (strong, nonatomic) NSMutableArray *attributes; //I define the array as mutable
Group.m
#import "Group.h"
#implementation Group
-(id)init
{
self = [super init];
if(self)
{
//do your object initialization here
self.attributes = [NSMutableArray array]; //I initialize the array to be a NSMutableArray
}
return self;
}
#end
GroupBuilder.m
#import "GroupBuilder.h"
#import "Group.h"
#implementation GroupBuilder
+ (NSArray *)groupsFromJSON:(NSData *)objectNotation error:(NSError **)error
{
NSError *localError = nil;
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
if (localError != nil) {
*error = localError;
return nil;
}
NSMutableArray *groups = [[NSMutableArray alloc] init];
NSDictionary *results = [parsedObject objectForKey:#"result"];
NSArray *items = results[#"items" ];
for (NSDictionary *groupDic in items) {
Group *group = [[Group alloc] init];
for (NSString *key in groupDic) {
if ([group respondsToSelector:NSSelectorFromString(key)]) {
[group setValue:[groupDic valueForKey:key] forKey:key];
}
}
[groups addObject:group];
}
for(NSInteger i = 0; i < items.count; i++) {
//NSLog(#"%#", [[items objectAtIndex:i] objectForKey:#"attributes"]);
NSMutableArray *att = [[items objectAtIndex:i] objectForKey:#"attributes"]; //this returns a NSArray object understandable
Group *g = [groups objectAtIndex:i];
[g.attributes addObjectsFromArray:[att mutableCopy]]; //I use mutable copy here so that i'm adding objects from a NSMutableArray and not an NSArray
}
return groups;
}
#end
Use options:NSJSONReadingMutableContainers on your NSJSONSerialization call.
Then all the dictionaries and arrays it creates will be mutable.
According to the error message you are trying to insert an object into an instance of NSArray, not NSMutableArray.
I think it is here:
NSMutableArray *att = [[items objectAtIndex:i] objectForKey:#"attrib`enter code here`utes"]; //this returns a NSArray object understandable
Items is fetched from JSON and therefore not mutable. You can configure JSONSerialization in a way that it creates mutable objects, but how exactly I don't know out of the top of my head. Check the references on how to do that or make a mutable copy:
NSMutableArray *att = [[items objectAtIndex:i] objectForKey:#"attributes"] mutableCopy];
Next try, considering your replies to the first attempt:
#import "Group.h"
#implementation Group
-(NSMutableArray*)attributes
{
return [[super attributes] mutableCopy];
}
#end

How to initialize a dictionary from NSString to NSArray

I am trying to create a dictionary (Not sure whether it should be NSDictionary or NSMutableDictionary) from NSString to an array (Not sure whether it should be NSArray or NSMutableArray).
property:
#property(nonatomic, readonly) NSMutableDictionary * categories;
implementation:
#synthesize categories = _categories;
- (NSMutableDictionary *)categories{
if(! _categories) {
for(PFObject * each in self.products) {
NSString * currentcategory = [each valueForKey:#"subtitle"];
NSArray * currentlist = [_categories objectForKey:currentcategory];
if(! currentlist) {
currentlist = [[NSArray alloc] init];
}
NSMutableArray * newArray = [currentlist mutableCopy];
[newArray addObject:each];
NSArray * newlist = [NSArray arrayWithArray:newArray];
[_categories setObject:newlist forKey:currentcategory];
}
}
NSLog(#"After constructor the value of the dictionary is %d", [_categories count]);
return _categories;
}
From the debug NSLog I realize that the dictionary is empty after the construction. What is wrong here and how shall I change it?
After code line
if(! _categories) {
add
_categories = [NSMutableDictionary new];
If you did not initialize _category array somewhere in code then.
you must instantiate it inside
if(!_categories)
Your NSMutableArray _categories instance is not allocated and initialized yet.
To create instance of NSMutableArray just add
_categories = [NSMutableArray arrayWithCapacity:0];

Trouble accessing Mutable array

Im having trouble reassigning data in an array where I am trying to index user names. I am able to separate my original array into individual objects but am not able to send the value to a new array that I need to reference later on. The value and count for userNames in my self.userNamesArray = userNames; line is correct. But right after that when I log self.userNamesArray, I get (null). Any tips cause I'm not completely sure I'm cheers!
.h
#property (nonatomic, copy) NSMutableArray *userNamesArray;
.m
- (void)viewWillAppear:(BOOL)animated {
self.friendsRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
PFQuery *query = [self.friendsRelation query];
[query orderByAscending:#"username"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
self.friends = objects;
NSArray *users = [self.friends valueForKey:#"username"];
NSLog(#"username:%#", users);
//Create an array of name wrappers and pass to the root view controller.
NSMutableArray *userNames = [[NSMutableArray alloc] initWithCapacity:[self.friends count]];
for (NSString *user in users) {
componentsSeparatedByCharactersInSet:charSet];
NSArray *nameComponents = [user componentsSeparatedByString:#" "];
UserNameWrapper *userNameWrapper = [[UserNameWrapper alloc] initWithUserName:nil nameComponents:nameComponents];
[userNames addObject:userNameWrapper];
}
self.userNamesArray = userNames;
NSLog(#"userNamesArray:%#",self.userNamesArray);
[self.tableView reloadData];
}
Here's the code where I need to reference the self.userNamesArray where again, it is comping up nil.
- (void)setUserNamesArray:(NSMutableArray *)newDataArray {
if (newDataArray != self.userNamesArray) {
self.userNamesArray = [newDataArray mutableCopy];
if (self.userNamesArray == nil) {
self.sectionsArray = nil;
NSLog(#"user names empty");
}
else {
[self configureSections];
}
}
}
Change your property method of mutable array to below:-
#property (nonatomic, retain)
NSMutableArray *userNamesArray;
Is this code calling itself recursively?
self.userNamesArray = [newDataArray mutableCopy];
is equivilent to:
[self setUserNamesArray: [newDataArray mutableCopy]];
If you need to override what happens during assignment, you can do as you're doing here but use _userNamesArray to reference the underlying member field.
First of all, I don't you need NSMutableArray for "userNamesArray". You could simply use NSArray. Now, try with below piece of code and you should be good to go:
self.userNamesArray = [NSMutableArray arrayWithArray:userNames];
You might get null because of this line:
NSArray *users = [self.friends valueForKey:#"username"];
Change it to:
NSArray *users = [self.friends objectForKey:#"username"];
In addition, follow #Abhinav suggestion to have more cleaner code :)

Trying to filter NSMutableArray with NSPredicate and getting error

I'm trying to filter the results of a list of employee contacts that I keep in my app but am getting the following error : 'Can't use in/contains operator with collection LAST (not a collection)'
I've tried several variations with the NSPredicate command, self, self.last, employee.last, last == 'smith' (this one doesn't generate an error but doesn't return any results).
NSMutableArray *employeesList = [[NSMutableArray alloc] init];
Person2 *employee = [[Person2 alloc] init];
employee.first = #"bob";
employee.last = #"black";
[employeesList addObject:employee];
employee = [[Person2 alloc] init];
employee.first = #"jack";
employee.last = #"brown";
[employeesList addObject:employee];
employee = [[Person2 alloc] init];
employee.first = #"george";
employee.last = #"smith";
[employeesList addObject:employee];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"last contains[cd] %#", #"black"];
NSArray *filteredKeys = [employeesList filteredArrayUsingPredicate:predicate];
NSLog(#"filtered : %#",filteredKeys);
[person2.h]
#interface Person2 : NSObject
{
#private
}
#property (nonatomic, retain) NSString *first;
#property (nonatomic, retain) NSString *last;
+ (Person2 *)personWithFirst:(NSString *)first andLast:(NSString *)last;
#end
[person2.m]
#import "Person2.h"
#implementation Person2
#synthesize first, last;
- (id)init {
self = [super init];
if (self) {
}
return self;
}
+ (Person2 *)personWithFirst:(NSString *)first andLast:(NSString *)last {
Person2 *person = [[Person2 alloc] init];
[person setFirst:first];
[person setLast:last];
return person;
}
- (NSString *)description {
return [NSString stringWithFormat:#"%# %#", [self first], [self last]];
}
#end
I've got an NSArray category that does this sort of thing easily:
#interface NSArray (FilterAdditions)
- (NSArray *)filterObjectsUsingBlock:(BOOL (^)(id obj, NSUInteger idx))block;
#end
#implementation NSArray (FilterAdditions)
- (NSArray *)filterObjectsUsingBlock:(BOOL (^)(id, NSUInteger))block {
NSMutableArray *result = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (block(obj, idx)) {
[result addObject:obj];
}
}];
return result;
}
So you would call it like this:
NSArray *filteredEmployees =
[employeeList filterObjectsUsingBlock:^BOOL(id obj, NSUInteger idx){
return [(Person2 *)obj.last isEqualToString:#"black"];
}];
So I found the answer and now I feel very dumb!! The use of "first" and "last" are reserved names and cannot be used. I changed the variables to firstName and lastName and it works perfectly.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html.
Thank you all for your comments and assistance.

Resources