View Parse Data on WatchKit Table - ios

I am trying to get my app working on WatchKit. I use Parse, and want to simply show the value of "Request" in my PFObject as a row in a WatchKit Table. I have the table and row set up and the row NSObject class simply has 1 label in it, where the "Request" field will populate. Here is what I have in my InterfaceController for the Watch.
#import "InterfaceController.h"
#import "TheTable.h"
#import <Parse/Parse.h>
#import "BlogView.h"
#interface InterfaceController()
#property (nonatomic, retain) PFObject *theObject;
#property (nonatomic, retain) NSMutableArray *rowTypesList;
#end
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[Parse setApplicationId:#"MYID"
clientKey:#"MYKEY"];
[super awakeWithContext:context];
// Configure interface objects here.
}
- (void)willActivate
{
PFQuery *query = [PFQuery queryWithClassName:#"Prayers"];
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSArray *array = [objects objectAtIndex:0];//Selects the first "object" from all the "objects"
array = [array valueForKey:#"Request"];//Makes a NSArray from the "pairs" values
_rowTypesList = [array mutableCopy];//Converts the array to a NSMutableArray
NSLog(#"%#", _rowTypesList);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}]; [self setupTable];
}
- (void)setupTable
{
NSLog(#"%#", _rowTypesList);
[_theActualTable setRowTypes:_rowTypesList];
for (NSInteger i = 0;_theActualTable.numberOfRows; i++)
{
NSObject *row = [_theActualTable rowControllerAtIndex:i];
TheTable *importantRow = (TheTable *) row;
[importantRow.textRowLabel setText:???]; //THIS IS PROBLEM AREA, HOW DO I GET TEXT HERE FROM THE MUTABLEARRAY
}
}
#end
How do I get the value from the array for that row into the label?

I don't understand Objective C that much, but I get an idea.
You need to either call setupTable from the ParseQuery callback and pass it the results array, or either iterate that array in the callback and in each iteration call mytable.label.setText(array[i]["property"])
Hope it makes sense.

Related

Objective-C class object not mapping to array

How can I pass the event to the toDoArray? I'm not sure what I'm missing. Any help appreciated.
SDEventModel.h
#interface SDEventModel : AWSDynamoDBObjectModel <AWSDynamoDBModeling>
ViewController.h
#property (nonatomic, strong) NSArray *toDoArray;
ViewController.m
if (task.result) {
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
for (SDEventModel *event in paginatedOutput.items) {
//Do something with event.
NSLog(#"Task results: %#", event);
[self.toDoArray arrayByAddingObject:event];
NSLog(#"To do array results: %#", self.toDoArray);
[self.tableview reloadData];
}
}
Here is the output of the NSLog.
Task results: <SDEventModel: 0x7faa88d81430> {
city = "New York";
image = "photo-22.jpg";
title = "Hang with friends";
}
To do array results: (null)
The arrayByAddingObject method returns another array with the added object, and does not append the same.
This is how the method is intended to be used:
self.toDoArray = [self.toDoArray arrayByAddingObject:event];
However, in your case, it seems that the array is not even initialized. So you need to do something like this as well:
-(void) viewDidLoad {
[super viewDidLoad];
self.toDoArray = #[];
}
Define toDoArray as NSMutableArray like this in ViewController.h
#property (nonatomic, strong) NSMutableArray *toDoArray;
Now in ViewController.m initialise that array and add objects of event into it
if (task.result) {
self.toDoArray = [NSMutableArray new];
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
for (SDEventModel *event in paginatedOutput.items) {
//Do something with event.
NSLog(#"Task results: %#", event);
[self.toDoArray addObject:event];
}
NSLog(#"To do array results: %#", self.toDoArray);
[self.tableview reloadData];
}
Please check Whether the Array in which you are adding object is Mutable or not?
if it is not mutable, you can create a new array or convert existing array to Mutable Array using mutableCopy

Querying a column in Parse

I have an iOS app that allows users to save GeoPoints to a Parse.com database table. Its a Google Maps app that lets users submit Lat/Long coordinates that will be displayed on the map once the Points have been approved by an admin type person.
I created a table called Point on Parse.com to save this information and the table has the following fields in addition the default ones that are created for you:
approved (String)
point (GeoPoints)
When a new row in the table is created (new Point is submitted by a user), "approved" is always set to "0" and "point" will contain the Lat/Long of a point that has been uploaded.
Once the "point" has been approved by an admin, "approved" is set to "1".
I query the table to display all the GeoPoints that have been approved (set to "1").
I can get all the rows that has been set to "1" but I dont know how to access the "point" field. I need to get the "point" for each row to display it to a map.
Here is what I have to query the table for all Points where "approved" is set to "1"
// Query the Database to get Points
PFQuery *query = [PFQuery queryWithClassName:#"Point"];
[query whereKey:#"approved" equalTo:#"0"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (!error)
{
// The find was successful
NSLog(#"Successfully Retrieved %d Number of Points", objects.count);
// Display the found Points as Markers
for (PFObject *object in objects)
{
NSLog(#"%#", object.objectId);
// Tried to do this but does not work
NSLog(#"%#", object.point);
}
}
else
{
// Show errors
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I tried the following once I had an array of the objects but this does not work.
// Tried to do this but does not work
NSLog(#"%#", object.point);
Can anyone please help?
I think what you want is:
PFGeoPoint *point = object[#"point"];
Refer to the PFGeoPoint class reference for more information.
You can also go with subclassing for ease of use. Refer to iOS Guide Subclassing. Don't forget to register the subclass in your AppDelegate.
//Point.h
#import "Parse/Parse.h"
#interface Point : PFObject <PFSubclassing>
#property (nonatomic) BOOL approved;
#property (nonatomic, strong) PFGeoPoint *geoPoint;
+ (void)findApprovedPointsWithBlock:(PFArrayResultBlock)resultBlock;
#end
//Point.m
#import "Point.h"
#import <Parse/PFObject+Subclass.h>
#implementation Point
#dynamic approved;
#dynamic geoPoint;
+ (NSString *)parseClassName {
return #"Point";
}
+ (void)findApprovedPointsWithBlock:(PFArrayResultBlock)resultBlock {
PFQuery *query = [PFQuery queryWithClassName:#"Point"];
[query whereKey:#"approved" equalTo:#YES];
[query findObjectsInBackgroundWithBlock:^(NSArray *points, NSError *error) {
resultBlock(points, error);
}];
}
#end
// Somewhere in your code
[Point findApprovedPointsWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (Point *object in objects) {
NSLog(#"%#", object.objectId);
NSLog(#"%#", object.geoPoint);
}
}
else {
}
}];

Empty array error - can't pass data from an existing NSMutableArray to a NSString

UPDATE
The problem was inside the findObjectsInBackgroundWithBlock: with the following line:
NSLog(#"Successfully retrieved %# .", objects[0]);
the new version:
NSLog(#"Successfully retrieved %# .", firstObject);
Passing the data to the mutable array was correct, i only changed the objectAtIndex to firstObject. But this block still not works properly.
Old question:
I have an NSMutableArray called searchResult, i would like to use it's first object for a PFQuery query, but the app is crashing when i'm trying to convert it to an NSString.
This is the error from the log:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
I know it's because an empty array, but don't understand why is the array empty. It should contain one username, because I have a search form where users can search for other users, if the search was successful i store the result in the searchResult mutable array. The result is listed in a table view cell, that contains the "Add Friend" button. If the user taps it, the other user should be added to it's friends. So the point is that i really really don't understand why can't i pass the existing data to the NSString?
- (void)viewDidLoad
{
[super viewDidLoad];
self.currentUser = [PFUser currentUser];
searchResult = [[NSMutableArray alloc] initWithObjects:#"User", nil];
}
- (void)didTapButton:(id)sender {
UIButton *button = (UIButton *)sender;
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:tableView];
NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:pointInSuperview];
NSString * contactRecipient = [searchResult objectAtIndex:0];
PFQuery *query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"username" equalTo:contactRecipient];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %# .", objects[0]);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
.h file
#interface TestViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
IBOutlet UITableView *tableView;
NSMutableArray *searchResult;
NSString *searchRes;
}
#property (weak, nonatomic) IBOutlet UITextField *searchField;
#property (nonatomic, strong) PFUser *currentUser;
#end
Sounds like you're getting an empty response (which may be valid). Use objects.firstObject instead and make the rest of your code nil safe.

IOS set and get property on load

I'm trying to initialize a couple properties fetched from parse.com when the view is loaded so I can do calculation with them. For instance, I declare the following in my header file:
TaskViewController.h
#property (nonatomic, assign) int taskTotalCount;
#property (nonatomic, assign) int taskCompletedCount;
#property (nonatomic, assign) int progressCount;
- (void)CountAndSetTotalTask;
- (void)CountAndSetCompletedCount;
- (void)CalculateProgress;
Then in the implementation, assuming all the other initialization are setup properly and they are called in viewdidload, below are the method implementations:
TaskViewController.m
- (void)CountAndSetCompletedCount {
// Query the tasks objects that are marked completed and count them
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:#"Goal" equalTo:self.tasks];
[query whereKey:#"completed" equalTo:[NSNumber numberWithBool:YES]];
[query countObjectsInBackgroundWithBlock:^(int count, NSError *error) {
if (!error) {
// The count request succeeded. Assign it to taskCompletedCount
self.taskCompletedCount = count;
NSLog(#"total completed tasks for this goal = %d", self.taskCompletedCount);
} else {
NSLog(#"Fail to retrieve task count");
}
}];
}
- (void)CountAndSetTotalTask {
// Count the number of total tasks for this goal
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:#"Goal" equalTo:self.tasks];
[query countObjectsInBackgroundWithBlock:^(int count, NSError *error) {
if (!error) {
// The count request succeeded. Assign it to taskTotalCount
self.taskTotalCount = count;
NSLog(#"total tasks for this goal = %d", self.taskTotalCount);
} else {
NSLog(#"Fail to retrieve task count");
}
}];
}
- (void)CalculateProgress {
int x = self.taskCompletedCount;
int y = self.taskTotalCount;
NSLog(#"the x value is %d", self.taskCompletedCount);
NSLog(#"the y value is %d", self.taskTotalCount);
if (!y==0) {
self.progressCount = ceil(x/y);
} else {
NSLog(#"one number is 0");
}
NSLog(#"The progress count is = %d", self.progressCount);
}
The issue I am encountering is that the taskTotalCount and taskCompletedCount are set correctly and returns different numbers in the first two methods while the NSLog returns 0 for both x and y. Therefore I'm not sure if the third method somehow got loaded before the two properties are set or it's some other issues. Thank you in advance for any pointers.
Assuming you call these three methods like this:
- (void)viewDidLoad {
[super viewDidLoad];
[self CountAndSetCompletedCount];
[self CountAndSetTotalTask];
[self CalculateProgress];
}
then the problem is that the first two methods return immediately while the calls to Parse occur in the background. This means that CalculateProgress is called long before you get back the results from the calls to Parse.
One solution is to just call CountAndSetCompletedCount from viewDidLoad. In its completion handler you then call CountAndSetTotalTask. In its completion handler you finally call CalculateProgress.

Parse specific, how to save query results on an NSArray

Im very new to iOS and PFQuery and I need your help please
IM trying to store the array of objects obtained form PFQuery into a local NSArray, Im trying to do it inside if (!error) but it does not leave the block, once the block terminates so does the values for it on my array.
//InstallersDirectory.m
#interface InstallersDirectoryTVC ()
#property (nonatomic, strong) NSArray *supervisors;
#end
//more code goes here
- (void)viewDidLoad
{
[super viewDidLoad];
PFQuery *query = [PFQuery queryWithClassName:#"InstallersInfo"];
[query whereKey:#"supervisor" equalTo:#"yes"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
self.supervisors = [objects valueForKey:#"supervisor"];
}
}else {
NSLog(#"Error, %# %#",error,[error userInfo]);
}
}];
Everything works inside the block, like self.supervisors.count or NSLog, but it doesn't leave the block at all. Could you please tell me how I can get those values store definitely to self.supervisors?
Thanks !!
edit | comment
If you still need help on this issue, here is a suggestion or two:
first, self.supervisors is a NSArray. As a NSArray it has to be fully initialized and populated at creation time. So, even though you are iterating through your results, you are creating a new array each time which means only the last iteration would likely be stored in self.supervisors.
try this instead,
#property (nonatomic,strong) NSMutableArray *supervisors;
in your block:
[self.supervisors addObject:object];
//note: this will put the entire returned object in your mutable array
then later outside your block:
to list all the supervisors:
for (PFObject *supervisor in self.supervisors) {
NSLog(#"supervisor info:%#",supervisor);
}
To get the 4th supervisor in the list:
PFObject *superVisorNumber4 = [self.supervisors objectAtIndex:4];
To get the phone number from that supervisor (making this up :)
NSString *phone = [superVisorNumber4 objectForKey:#"phone"];
hope that helps

Resources