NSMutableArray addObject Isn't Working - ios

I am trying to create a NSMutableArray which will become the dataSource for a UIPickerView, but nothing is getting added to the array, the console just shows (. What am I doing wrong?
NSMutableArray *arr = [[NSMutableArray alloc] init];
PFQuery *rejectedNumber = [PFQuery queryWithClassName:#"Group"];
[rejectedNumber findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!objects) {
// Did not find any UserStats for the current user
NSLog(#"NotFound");
} else {
for (int i=0;i<[objects count];i++)
{
PFObject * obj = [objects objectAtIndex:i];
self.theObject = obj;
NSString *string = obj[#"GroupName"];
[arr addObject:string];
NSLog(#"GOGOGO%#", arr);
}

Related

Combind parse queries and add to seperate arrays

How can I combine multiple Parse Queries?
I want to query the column sclink and songTitle from parse.com then add each to its own array.
Also how to save query locally and call it? IF else statment or something:
NSMutableArray *trackList = [[NSMutableArray alloc] init];
PFQuery *queryTracks = [PFQuery queryWithClassName:#"liveRadioPL"];
NSArray *objects = [queryTracks findObjects]; // Online PFQuery results
[PFObject pinAllInBackground:objects];
[queryTracks selectKeys:#[#"scLink"]];
[queryTracks findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
totalTracks = (int)objects.count;
NSLog(#"Successfully retrieved %lu Tracks.", (unsigned long)objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
[trackList addObject:[NSString stringWithFormat:#"%#", [object objectForKey:#"scLink"]]];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
trackListArray = trackList;
NSMutableArray *trackTitles = [[NSMutableArray alloc] init];
PFQuery *queryTitles = [PFQuery queryWithClassName:#"liveRadioPL"];
NSArray *objectsTitle = [queryTitles findObjects]; // Online PFQuery results
[PFObject pinAllInBackground:objects];
[queryTracks selectKeys:#[#"songTitle"]];
[queryTracks findObjectsInBackgroundWithBlock:^(NSArray *objectsTitle, NSError *error) {
if (!error) {
// The find succeeded.
totalTitles = (int)objectsTitle.count;
NSLog(#"Successfully retrieved %lu Titles.", (unsigned long)objectsTitle.count);
// Do something with the found objects
for (PFObject *object in objects) {
[trackTitles addObject:[NSString stringWithFormat:#"%#", [object objectForKey:#"songTitle"]]];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I'm not sure your logic really makes sense - you're using 4 API requests when all you need is 1 API request. Also, Jacob is right, you're filling an array from a background thread and as a result the main thread will see it as empty.
I think I understand what you're trying to do - try this
PFQuery *queryTracks = [PFQuery queryWithClassName:#"liveRadioPL"];
// use includeKey if slink and songTitle are pointers to other Parse classes
// from the context of your question you probably don't need to use includeKey
[queryTracks includeKey:"scLink"];
[queryTracks includeKey:"songTitle"];
NSArray *objects = [queryTracks findObjects];
NSMutableArray* scLinks = [[NSMutableArray alloc] init];
NSMutableArray* songTitles = [[NSMutableArray alloc] init];
for (PFObject* object in objects) {
[scLinks addObject:object[#"scLink"]];
[songTitles addObject:object[#"songTitles"]];
}
I hope this helps, good luck!

Calling specific method after another method

I'm retrieving data from my parse database and looping it into an NSMutableArray. This is in my getHomes method, which is being called in viewDidLoad. The NSMutableArray contain various UIImages, which CGSize' i'm looping through. This method is called getCellHeights. I want to call this method right after the getHomes method, but stacking them like this in viewdidLoad does not do the trick. The getCellHeights method is not running since there is no objects in the NSMutableArray, cause its not completed with the retrieving of data.
How can i make sure that the getCellHeights is not running before the getHomes method is completed?
getCellHeights
-(void)getcellHeights {
for (int i = 0; i < homesDic.count; i++) {
UIImage *image = [[homesDic objectAtIndex:i] objectForKey:#"image"];
CGFloat divider = image.size.width/145;
CGFloat wantedWidth = 145;
CGFloat wantedHeight = image.size.height/divider;
NSLog(#"width: %f height: %f", wantedWidth, wantedHeight);
CGSize size = CGSizeMake(wantedWidth, wantedHeight);
[_cellSizes addObject:[NSValue valueWithCGSize:size]];
}
}
getHomes
-(void)getHomes {
PFQuery *query = [PFQuery queryWithClassName:#"Homes"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects1, NSError *error) {
if (!error) {
for (PFObject *object in objects1) {
PFQuery *userQ = [PFUser query];
[userQ getObjectInBackgroundWithId:[object objectForKey:#"userId"] block:^(PFObject *userName, NSError *error) {
NSLog(#"%#", userName);
[[userName objectForKey:#"file"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
UIImage *profileImage = [UIImage imageWithData:data];
PFQuery *homeQ = [PFQuery queryWithClassName:#"homeImages"];
[homeQ whereKey:#"homeId" equalTo:object.objectId];
[homeQ whereKey:#"number" equalTo:#(0)];
[homeQ findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
PFQuery *cityQ = [PFQuery queryWithClassName:#"City"];
id zip = [NSNumber numberWithInteger: [[object objectForKey:#"zip"] intValue]];
[cityQ whereKey:#"fra" greaterThanOrEqualTo:zip];
[cityQ whereKey:#"fra" lessThanOrEqualTo:zip];
[cityQ findObjectsInBackgroundWithBlock:^(NSArray *cObject, NSError *error) {
if (!error) {
PFObject *cityObject = [cObject lastObject];
PFObject *image = [objects lastObject];
[[image objectForKey:#"Image"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
UIImage *image = [UIImage imageWithData:data];
NSMutableDictionary *flagDict = [[NSMutableDictionary alloc] init];
[flagDict setObject:[object objectForKey:#"title"] forKey:#"title"];
[flagDict setObject:image forKey:#"image"];
[flagDict setObject:[cityObject objectForKey:#"navn"] forKey:#"city"];
[flagDict setObject:[userName objectForKey:#"name"] forKey:#"name"];
[flagDict setObject:profileImage forKey:#"profileImage"];
[homesDic addObject:flagDict];
[self.collectionView reloadData];
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
}];
}
}];
}];
}];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
The Blocks that you're passing to the Parse framework query methods are completion/callback Blocks; when the fetch has completed, they are run. Do whatever you need to do after the fetch -- including calling cellHeights -- in the appropriate completion Block.

Returning a single key value from an array with multiple identical values?

I have an array of objects(images) with key values of #"titleLabel" stored on a backend server(parse). What I am trying to do is display the list of titles in a pickerView but I only want to display ONE title for every group of #"titleLabels" whose keys match. For example: if I have five objects(images) with titleLabel key: 'Spring Break' I only want to display one instance of the title 'Spring Break' and not all five. The code I have written is my best amateur shot at solving it but my NSLog for 'titles array count' is returning a value of 1 and when I log the value I get all of the titles again.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Images"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:obj forKey:key];
}
}
for (id key in dict) {
NSLog(#"key: %#, value: %# \n", key, [dict objectForKey:key]);
NSLog(#"Objects array is %d", [self.objectsArray count]);
NSLog(#"Titles array is %d", [self.titlesArray count]);
}
[self.pickerView reloadComponent:0];
}
}];
And here is where I define my keys in a separate controller:
PFObject *image = [PFObject objectWithClassName:#"Images"];
[image setObject:self.releaseDate forKey:#"releaseDate"];
[image setObject:file forKey:#"file"];
[image setObject:fileType forKey:#"fileType"];
[image setObject:title forKey:#"titleLabel"];
[image setObject:deadline forKey:#"deadline"];
[image setObject:self.recipients forKey:#"recipientIds"];
[image setObject:[[PFUser currentUser] objectId] forKey:#"senderId"];
[image setObject:[[PFUser currentUser] username] forKey:#"senderName"];
[image saveInBackground];
PFObject *object = [self.objectsArray valueForKey:#"titleLabel"];
if(object != [self.objectsArray valueForKey:#"titleLabel"]){
self.titlesArray = [self.titlesArray arrayByAddingObject:object];
}
you are checking if the object is equal to what you just assigned. Also, you should be using a NSMutableArray but if you dont care, i dont care too. :) Saying that, i guess your else loop should look like this
self.objectsArray = objects;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:obj forKey:key];
}
}
for (id key in dict) {
NSLog(#"key: %#, value: %# \n", key, [dict objectForKey:key]);
}

pulling a value from NSMutableDictionary

Here's my code for returning a unique value for identical keys in a dictionary. Right now, in my log, my "objects array:" is 6 (3 sets of (2 objects with identical keys)), and my "dictionary:" returns values for 1 object from each set (3 unique values). In my 'for' statement:
for (id key in dict)
{
self.titlesArray = [NSMutableArray arrayWithObject:dict];
NSLog(#"titles: %#", self.titlesArray);
self.titlesArray = [[NSMutableArray alloc] initWithObjects:[dict valueForKey:key] ,nil];
NSLog(#"titles: %#", self.titlesArray);
}
The first log prints out the three unique values AND keys. The second prints only a single value for a single key (which is what I want.. but I need all three key values) So my problem now is that I am unable to pull a key for each unique value from the dictionary and add it to my titlesArray.
for (id key in dict)
{
self.titlesArray = [NSMutableArray arrayWithObject:dict];
self.titlesArray = [[NSMutableArray alloc] initWithObjects:[dict valueForKey:key] ,nil];
code isn't quite right.
PFQuery *query = [PFQuery queryWithClassName:#"Images"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
// found messages!
self.objectsArray = objects;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [obj valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:key forKey:[obj valueForKey:#"titleLabel"]];
}
}
for (id key in dict) {
self.titlesArray = [NSMutableArray arrayWithObject:dict];
NSLog(#"titles: %#", self.titlesArray);
self.titlesArray = [[NSMutableArray alloc] initWithObjects:[dict valueForKey:key] ,nil];
NSLog(#"titles: %#", self.titlesArray);
}
NSLog(#"dictionary: %#", dict);
NSLog(#"Objects array is %d", [self.objectsArray count]);
[self.pickerView reloadComponent:0];
it looks like there is some type error in line
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
it should be
PFObject *key = [obj valueForKey:#"titleLabel"];
It's happening in this line, isn't it:
if(![dict objectForKey:#"titleLabel"]){
[dict setValue:obj forKey:key];
}
}
You are setting "obj" as a value, no problem there, but then you are using "key" which is a PFObject, but NSDictionary requires a NSString for the key.
If PFObject contains a NSString property that you want to use, you can pass that in. For example, if PFObject has an NSString property called "name" you could call this:
if(![dict objectForKey:#"titleLabel"]) {
[dict setValue:obj forKey:key.name];
}
}
The relevant thing to notice is the types of the parameters when NSMutableDictionary defines this method, namely the (NSString*):
- (void)setValue:(id)value forKey:(NSString *)key
How does your PFObject look like. Does it have strings in it?. According to your question you already know that you can't pass a PFObject as key for dictionary. If your object is some what like this
interface PFObject : NSObject
{
NSString *keyString;
......
.Some other variables
}
Then you should be using it like this to set it as key
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
if(![dict objectForKey:#"titleLabel"]){
[dict setValue:obj forKey:[key valueForKey#"titleLabel"]];
}
Here is the code I found to work. It takes the array and sorts through the keys to return only unique values for a specific key:
PFQuery *query = [PFQuery queryWithClassName:#"Images"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
// found messages!
self.objectsArray = objects;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [obj valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:key forKey:[obj valueForKey:#"titleLabel"]];
}
}
for (id key in dict) {
self.titlesArray = [NSMutableArray arrayWithObject:dict];
[self.titlesArray addObject:dict.allKeys];
self.titlesArray = [self.titlesArray objectAtIndex:1];
}
NSLog(#"titles: %#", self.titlesArray);
[self.pickerView reloadComponent:0];

iOS FMDB Sqlite wrapper. Out of memory

The following code :
-(NSArray *)getContentsWithContextTypes:(NSArray *)contextTypes
contextData:(NSArray *)contextData
{
__block NSString *query = #"SELECT * FROM Texts_original1 WHERE ";
[contextData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *attributeName = [self.contextTypeToDBQueryTexts
objectForKey:contextTypes[idx]];
query = [query stringByAppendingFormat:#"%# = \"%#\"", attributeName, obj];
if(idx != contextData.count - 1)
{
query = [query stringByAppendingString:#" AND "];
}
}];
[self.db open];
FMResultSet *results = [self.db executeQuery:query];
NSMutableArray *array = [NSMutableArray array];
while([results next])
{
Content *content = [[TextualContent alloc] initWithResults:results];
[array addObject:content];
}
[self.db close];
return array;
}
Generates the following error when I run it :
Error calling sqlite3_step (21: out of memory) rs
It happens half way through the loop. There should be 33 results. After 17 I get that error and the loop exits. Any Ideas? Thanks.
It's important to know that you close the FMResultSet object, as it will cause memory problems.
Do it as follows, [resultSet close]
I am not getting into your code logic but, I will make some modifications in database code.
Try the following:
-(NSArray *)getContentsWithContextTypes:(NSArray *)contextTypes
contextData:(NSArray *)contextData
{
__block NSString *query = #"SELECT * FROM Texts_original1 WHERE ";
[contextData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSString *attributeName = [self.contextTypeToDBQueryTexts
objectForKey:contextTypes[idx]];
query = [query stringByAppendingFormat:#"%# = \"%#\"", attributeName, obj];
if(idx != contextData.count - 1)
{
query = [query stringByAppendingString:#" AND "];
}
}];
self.db = [FMDatabase databaseWithPath:[self getDBPath]];
if(![db open])
{
NSLog(#"Could not open DB");
return nil;
}
FMResultSet *results = [self.db executeQuery:query];
NSMutableArray *array = [NSMutableArray array];
while([results next])
{
Content *content = [[TextualContent alloc] initWithResults:results];
[array addObject:content];
}
[results close]; //VERY IMPORTANT!
[self.db close];
return array;
}

Resources