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 :)
Related
I use Parse.com and have a PFObject that I use to populate a TableView. The PFObject contains several NSStrings and one NSArray. The array will contain days of week, some of which occur multiple times. I just need a way to determine which object has the most of each day of the week in that Array. I have had some success with finding the most popular one, but it gives numbers for the title of array.
[super viewWillAppear:animated];
PFQuery *query = [self queryForTable];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSLog(#"this should be all of the objects %#", objects];
// now just run the code I suggest, adapting objects as the array of arrays
NSArray *maxOccurrenceArray = nil;
NSInteger maxOccurrences = -LONG_MAX;
for (PFObject *pfObject in objects) {
NSArray *array = [pfObject objectForKey:#"THE_NAME_OF_THE_ARRAY_PROPERTY"];
NSInteger occurrences = [self occurrencesOf:#"Sunday" inArray:array];
if (occurrences > maxOccurrences) {
maxOccurrences = occurrences;
maxOccurrenceArray = array;
}
}
NSLog(#"The array with the most occurrences is %#", maxOccurrenceArray);
}];
NSArray *maxOccurrenceArray = nil;
NSInteger maxOccurrences = -LONG_MAX;
for (NSArray *array in arrays) {
NSInteger occurrences = [self occurrencesOf:#"Sunday" inArray:array];
if (occurrences > maxOccurrences) {
maxOccurrences = occurrences;
maxOccurrenceArray = array;
}
}
NSLog(#"The array with the most occurrences is %#", maxOccurrenceArray);
I don't understand how this is possible or why this is happening. Can anyone give me an idea?
I added more code to help you figure it out, however, i'm not sure how the extra code will help.
NSMutableArray *messages = [[NSMutableArray alloc] init];
PFUser *currentUser = [PFUser currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"message"];
[query whereKey:#"receiver" equalTo:currentUser.objectId];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error && objects !=NULL) {
NSMutableArray *listOfLastMsgs = [[NSMutableArray alloc] init];
for (PFObject *object in objects) {
Boolean *tester = false;
for(int i = 0;i<listOfLastMsgs.count;i++){
if([[object objectForKey:#"sender"] isEqualToString:[[listOfLastMsgs objectAtIndex:i] objectForKey:#"sender"]]){
tester = true;
}
}
if(!tester){
[listOfLastMsgs addObject:object];
}
}
for(int i = 0;i<listOfLastMsgs.count;i++){
NSString *s = [[listOfLastMsgs objectAtIndex:i] objectForKey:#"message"];
if(s.length > 80){
s = [s substringToIndex:80];
}
[messages addObject:s];
}
NSLog(#"in did load %lu", (unsigned long)messages.count);
[self.tableView reloadData];
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"in number of rows %lu", (unsigned long)messages.count);
return messages.count;
}
Here is my output log
2014-07-25 18:15:32.980 myapp[5696:60b] in number of rows 0
2014-07-25 18:15:35.990 myapp[5696:60b] in did load 2
2014-07-25 18:15:35.991 myapp[5696:60b] in number of rows 0
Assuming that big hunk of code is in your viewDidLoad the problem is simple - you have a local messages variable that you setup in viewDidLoad and your numberOfRowsInSection is referencing an uninitialized messages instance variable.
Assuming you really do have an ivar named messages, in viewDidLoad, change:
NSMutableArray *messages = [[NSMutableArray alloc] init];
to:
messages = [[NSMutableArray alloc] init];
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
So what I have is a pop being activated that has its own ViewController and XIB file. It has a label called #property (strong, nonatomic) IBOutlet UILabel *addressLabel; the issue is I am trying to call that label in the first VC (where the pop up is called) since that is where I query the database to populate the label with a name from the DB. Can I make *addressLabel global so it is recongnized in the main VC?
Here is the main VC where the pop is called
- (void)receivedSighting:(FYXVisit *)visit updateTime:(NSDate *)updateTime RSSI:(NSNumber *)RSSI;
{
NSLog(#"Gimbal Beacon!!! %#", visit.transmitter.name);
// this will be invoked when an authorized transmitter is sighted during an on-going visit
[self showTransmittersView];
//This gets the popup
SamplePopupViewController *samplePopupViewController = [[SamplePopupViewController alloc] initWithNibName:#"SamplePopupViewController" bundle:nil];
[self presentPopupViewController:samplePopupViewController animated:YES completion:nil];
PFQuery *query = [PFQuery queryWithClassName:#"houses"];
[query whereKey:#"name" equalTo:[NSString stringWithFormat:#"%#",visit.transmitter.name]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
NSLog(#"address: %#", [object objectForKey:#"address"]);
NSLog(#"url:: %#", [object objectForKey:#"url"]);
NSString *displayAddress = [NSString stringWithFormat:#"%#", [object objectForKey:#"address"]];
NSString *displayDescription = [NSString stringWithFormat:#"%#", [object objectForKey:#"description"]];
NSString *displayUrl = [NSString stringWithFormat:#"%#", [object objectForKey:#"url"]];
//This is where I was getting the info to put in the pop up label
self.addressLabel.text = displayAddress;
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
I am showing an several images using an UIScrollView. however I would want it to refresh automatically.
I want to refresh it every time I show the view controller.
Using my code I have to push the refresh button every time which is just nonsense.
Here is the code : How can i do this ?
- (IBAction)refresh:(id)sender
{
NSLog(#"Showing Refresh HUD");
refreshHUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:refreshHUD];
// Register for HUD callbacks so we can remove it from the window at the right time
refreshHUD.delegate = self;
// Show the HUD while the provided method executes in a new thread
[refreshHUD show:YES];
PFQuery *query = [PFQuery queryWithClassName:#"TPhoto"];
PFUser *user = [PFUser currentUser];
[query whereKey:#"user" equalTo:user];
[query orderByAscending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
if (refreshHUD) {
[refreshHUD hide:YES];
refreshHUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:refreshHUD];
// The sample image is based on the work by http://www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/
// Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators)
refreshHUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
// Set custom view mode
refreshHUD.mode = MBProgressHUDModeCustomView;
refreshHUD.delegate = self;
}
NSLog(#"Successfully retrieved %d photos.", objects.count);
// Retrieve existing objectIDs
NSMutableArray *oldCompareObjectIDArray = [NSMutableArray array];
for (UIView *view in [photoScrollView subviews]) {
if ([view isKindOfClass:[UIButton class]]) {
UIButton *eachButton = (UIButton *)view;
[oldCompareObjectIDArray addObject:[eachButton titleForState:UIControlStateReserved]];
}
}
NSMutableArray *oldCompareObjectIDArray2 = [NSMutableArray arrayWithArray:oldCompareObjectIDArray];
// If there are photos, we start extracting the data
// Save a list of object IDs while extracting this data
NSMutableArray *newObjectIDArray = [NSMutableArray array];
if (objects.count > 0) {
for (PFObject *eachObject in objects) {
[newObjectIDArray addObject:[eachObject objectId]];
}
}
// Compare the old and new object IDs
NSMutableArray *newCompareObjectIDArray = [NSMutableArray arrayWithArray:newObjectIDArray];
NSMutableArray *newCompareObjectIDArray2 = [NSMutableArray arrayWithArray:newObjectIDArray];
if (oldCompareObjectIDArray.count > 0) {
// New objects
[newCompareObjectIDArray removeObjectsInArray:oldCompareObjectIDArray];
// Remove old objects if you delete them using the web browser
[oldCompareObjectIDArray removeObjectsInArray:newCompareObjectIDArray2];
if (oldCompareObjectIDArray.count > 0) {
// Check the position in the objectIDArray and remove
NSMutableArray *listOfToRemove = [[NSMutableArray alloc] init];
for (NSString *objectID in oldCompareObjectIDArray){
int i = 0;
for (NSString *oldObjectID in oldCompareObjectIDArray2){
if ([objectID isEqualToString:oldObjectID]) {
// Make list of all that you want to remove and remove at the end
[listOfToRemove addObject:[NSNumber numberWithInt:i]];
}
i++;
}
}
// Remove from the back
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:NO];
[listOfToRemove sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
for (NSNumber *index in listOfToRemove){
[allImages removeObjectAtIndex:[index intValue]];
}
}
}
// Add new objects
for (NSString *objectID in newCompareObjectIDArray){
for (PFObject *eachObject in objects){
if ([[eachObject objectId] isEqualToString:objectID]) {
NSMutableArray *selectedPhotoArray = [[NSMutableArray alloc] init];
[selectedPhotoArray addObject:eachObject];
if (selectedPhotoArray.count > 0) {
[allImages addObjectsFromArray:selectedPhotoArray];
}
}
}
}
// Remove and add from objects before this
[self setUpImages:allImages];
} else {
[refreshHUD hide:YES];
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
Call the refresh method from viewDidAppear in your view controller.
However, if that can happen often, you should consider keeping the images in a local cache and only refresh them if there is something new to show on the server.