Object Help Parse iOS SDK? Relational data perhaps? [duplicate] - objective-c

So what I'm trying to do essentially add a button next on each cell in my UITableView. Each cell in my tableView is being populated from my Event Class on parse where each object is displayed in a new cell.
Once a user hits this button it takes whatever Event object from the Event class they've clicked and possibly adds it to a "property" in the Parse User Class I'll create named "watching".
But how would I do something like this to where they're able to have all of these Events under the User Class "watching property"? Would I have to set up some relation of some sort?
Summary:
Basically wanting to have a watch list people are able to watch any of the objects posted by any of the users in the Events Class. These objects that are being watched are added to a property in the User Class so that I can easily create a UITableView pulling the current users watching property list of items and displaying them.

I hope I have understood what you want ... If I understand it you need a form of relationship between the object and the CurrentUser viewing it ...
normally to identify the selected cell within a IBAction you can 'use this method:
- (IBAction) button: (id) sender {
NSIndexPath * indexPath = [self.TableView indexPathForSelectedRow];
PFObject SelectedObject * = [self.YOUR_ARRAY objectAtIndex: indexPath.row];
}
This way you've identified which cell the current user has selected .. From this point on, continue with the PFObject to save the data the way you want
The essential thing is to set the goal of PFObject (in this case the selected cell) then continues to set the data to be set according to what you need

You could create a field on your PFUser class : #"watching"
Then use this as an array, so whenever the user clicks on something to watch ...
[[PFUser currentUser]addObject:objectToWatch.objectId forKey:#"watching"]; // adds it to the array
[[PFUser currentUser]save];
// something about arrays and parse objects, if you're using operations like "addObject" you should save or you'll get errors.
// the other option is to get an NSMutableArray from the array field, edit that, and reassociate it with the #"watching" key ... whichever you prefer
We now have an array of Id's associated with objects to watch. You could query like so
PFQuery * query = [PFQuery queryWithClassName:#"ObjectsToWatch"];
[query whereKey:#"objectId" containedIn:[PFUser currentUser][#"watching"]];
[query findObjectsInBackground]; // use a block method though
This is only one way to do it, hope it helps

Related

Comparing iOS Parse SDK Class with another Class's objects

So what I'm trying to do essentially add a button next on each cell in my UITableView. Each cell in my tableView is being populated from my Event Class on parse where each object is displayed in a new cell.
Once a user hits this button it takes whatever Event object from the Event class they've clicked and possibly adds it to a "property" in the Parse User Class I'll create named "watching".
But how would I do something like this to where they're able to have all of these Events under the User Class "watching property"? Would I have to set up some relation of some sort?
Summary:
Basically wanting to have a watch list people are able to watch any of the objects posted by any of the users in the Events Class. These objects that are being watched are added to a property in the User Class so that I can easily create a UITableView pulling the current users watching property list of items and displaying them.
I hope I have understood what you want ... If I understand it you need a form of relationship between the object and the CurrentUser viewing it ...
normally to identify the selected cell within a IBAction you can 'use this method:
- (IBAction) button: (id) sender {
NSIndexPath * indexPath = [self.TableView indexPathForSelectedRow];
PFObject SelectedObject * = [self.YOUR_ARRAY objectAtIndex: indexPath.row];
}
This way you've identified which cell the current user has selected .. From this point on, continue with the PFObject to save the data the way you want
The essential thing is to set the goal of PFObject (in this case the selected cell) then continues to set the data to be set according to what you need
You could create a field on your PFUser class : #"watching"
Then use this as an array, so whenever the user clicks on something to watch ...
[[PFUser currentUser]addObject:objectToWatch.objectId forKey:#"watching"]; // adds it to the array
[[PFUser currentUser]save];
// something about arrays and parse objects, if you're using operations like "addObject" you should save or you'll get errors.
// the other option is to get an NSMutableArray from the array field, edit that, and reassociate it with the #"watching" key ... whichever you prefer
We now have an array of Id's associated with objects to watch. You could query like so
PFQuery * query = [PFQuery queryWithClassName:#"ObjectsToWatch"];
[query whereKey:#"objectId" containedIn:[PFUser currentUser][#"watching"]];
[query findObjectsInBackground]; // use a block method though
This is only one way to do it, hope it helps

Fastest way to load an NSComboBox from an 8000 item plist

I have a plist that is basically a list of 8000 usernames. I load this into an NSDictionary, then an array of sorted keys (because the list isn't sorted when I get it) then loop through loading into an NSComboBox.
This works, but can take a few seconds to populate the combo box.
Here's my code:
// in my .h
IBOutlet NSComboBox *comboUserList; // which is connected to a combo box in my .xib
// in my .m
// userInfoPlist is an NSString path to the file
NSDictionary *userList = [NSDictionary dictionaryWithContentsOfFile:userInfoPlist];
// sort user info into an array
NSArray* sortedKeys = [userList keysSortedByValueUsingSelector:#selector(caseInsensitiveCompare:)];
// then populate the combo box from userList in the order specified by sortedKeys
for ( NSString *usersKey in sortedKeys) {
[comboUserList addItemWithObjectValue:[userList objectForKey:usersKey]];
}
So this works, but for 8000 odd entries it takes some noticeable time to populate the combo box (only a second or two on a 2011 MAcBook Air, but still noticeable). Is there a faster way to use either the NSDictionary or NSArray as a data source rather than do it in a for loop?
User External Data Source.
[mEmailListBox setUsesDataSource:YES];
[mEmailListBox setDataSource:self];
/*
If you use setDataSource: before setUsesDataSource:, setDataSource: throws an exception.
*/
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox;
{
return [DatSource count];//DatSource NSArray
}
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index;
{
return DatSource[index];
}
Take a look at Combo Box Programming Topics
You can also load data in background with the help of noteNumberOfItemsChanged and reloadData methods
You should use a data source instead of providing the values directly. Use -[NSComboBox setUsesDataSource:] and -[NSComboBox setDataSource:] to set your datasource then implement NSComboBoxDataSource protocol on your controller.
See:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Protocols/NSComboBoxDataSource_Protocol/Reference/Reference.html#//apple_ref/occ/intf/NSComboBoxDataSource
If you do not need eact behavior like this code when you sort keys and put values into NSComboBox you can do it different.
If it is OK to put sorted keys or values you can use one call instead of looping:
[comboUserList addItemsWithObjectValues:sortedKeys];

Binding label's value to the count property of an NSArray

I want to show in a label the current number of elements in an NSArray called pages. Following other guides I did the following:
Created an NSArrayController in IB (called pagesController) and bounded it to the NSArray pages
Bounded the value property of the label to the NSArrayController with Controller Key = arrangedObjects and Model Key Path = #count
The problem is that when the program is running the label always shows "0". To check if the things are working correctly I tried to log a message when the user clicks on another button (the button basically inserts a new element in the pages array): NSLog(#"count = %d", [self.pagesController valueForKeyPath:#"arrangedObjects.#count"]); in this case the output is correct, i.e. the current number of elements in the array printed is correct.
Where am I mistaking?
You many not be using KVC correctly. Your array controller will only be notified with the pages property is redefined, not when objects are added to the array. Try wrapping your code with the appropriate change notifications:
[self willChangeValueForKey:#"pages"];
[pages addObject:someObject];
[self didChangeValueFOrKey:#"pages"];

reloadData in NSTableView but keep current selection

I have anNSTableView showing the contents of a directory. I watch for FSEvents, and each time I get an event I reload my table view.
Unfortunately, the current selection then disappears. Is there a way to avoid that?
Well, you can save selection before calling reloadData and restore it after that.
NSInteger row = [self.tableView selectedRow];
[self.tableView reloadData];
[self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
This worked for me in some cases. But if you insert some items BEFORE the selected row, you should andjust your row variable by adding count of added items to it.
Swift 4.2
Create an extension and add a method which preserves selection.
extension NSTableView {
func reloadDataKeepingSelection() {
let selectedRowIndexes = self.selectedRowIndexes
self.reloadData()
self.selectRowIndexes(selectedRowIndexes, byExtendingSelection: false)
}
}
Do this in case you use the traditional way of populating table views (not NSArrayController).
It depends on how you populate your NSTableView.
If you have the table view bound to an NSArrayController, which in turn contain the items that your table view is displaying, then the NSArrayController has an option to preserve the selection. You can select it (or not) from within Interface Builder as a property on the NSArrayController. Or you can use the setPreservesSelection method in code.
However, if you completely replace the array of items that the NSArrayController manages each time you get your FSEvents, then maybe the preservation of selection cannot work. Unfortunately the Apple docs on this property of NSArrayController are a bit vague as to when it can and cannot preserve the selection.
If you are not using an NSArrayController, but maybe using a dataSource to populate the table view, then I think you'll have to manage the selection yourself.
In the case of using Data Source, Apple Documentation in the header file on reloadData() is that
The selected rows are not maintained.
To get around, you can use reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet). As mentioned in the same header file
For cells that are visible, appropriate dataSource and delegate methods will be called and the cells will be redrawn.
Thus the data will be reloaded, and the selection is kept as well.
A variant on #silvansky's answer.
This one has no need to keep track of count of items inserted/deleted. And it maintains multiple selection.
The idea is to...
1. create an array of selected objects/nodes from the current selection.
2. refresh the table using reloadData
3. for each object obtained in step 1, find/record it's new index
4. tell the table view/outline view to select the updated index set
- (void)refresh {
// initialize some variables
NSIndexSet *selectedIndexes = [self.outlineView selectedRowIndexes];
NSMutableArray *selectedNodes = [NSMutableArray array];
NSMutableIndexSet *updatedSelectedIndex = [NSMutableIndexSet indexSet];
// 1. enumerate all selected indexes and record the nodes/objects
[selectedIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
[selectedNodes addObject:[self.outlineView itemAtRow:idx]];
}];
// 2. refresh the table which may add new objects/nodes
[self.outlineView reloadData];
// 3. for each node in step 1, find the new indexes
for (id selectedNode in selectedNodes) {
[updatedSelectedIndex addIndex:[self.outlineView rowForItem:selectedNode]];
}
// 4. tell the outline view to select the updated index set
[self.outlineView selectRowIndexes:updatedSelectedIndex byExtendingSelection:NO];
}

How to edit data of NSArrayController (or to use something else)

i created a nsarraycontroller to display its data on my nstableview. this is working. but how do i modify this data now?
[arrayController addObject:[...]]
adds an object, how do i get it back?
i tried:
NSMutableArray *data = [arrayController mutableArrayValueForKey:#"column1"];]
but then i get this error
2011-05-29 19:25:50.125 TestApp[1665:903] [<NSArrayController 0x113808500> valueForUndefinedKey:]: this class is not key value coding-compliant for the key column1.
(the objects in my arraycontroller representing the rows in my view are of a class (named FileEntry) consisting of 4 properties and i added these as keys to my nsarraycontroller)
i thought kvc-compilant means every attribute has a getter and setter? (and isnt that what properties do?).
i tested my class if i could use this function:
FileEntry *entry = [[FileEntry alloc] initWithUrl:#"test"]; //(this adds the string "test" to the property "fileurl")
NSLog(#"%#\n", [entry valueForKey:#"fileurl"]);
and it returns:
> 2011-05-29 19:31:54.760 TestApp[1718:903] test
and it works. so how can my class not be kvc-compilant?
anyway, i also tried to use the tableviews datasource instead but cant get those 2 functions to work. would that be of more use than the nsarraycontroller? is it even possible to modify data of the nsarraycontroller?
Usually you need a contend array for the NSArrayController to handle, so you could simply take this array and use the NSMutableArray methods. For example you have in your MyController.h a declaration of an array with its setter and getter methods, and you only have to bind the contend array of the array controller to it. Then you can take two buttons for the add and remove methods of the array controller to add something. Now you must bind the value of the column to e.g. FileEntry.fileurl of your array controller managed objects, Now you should be able to add stuff to the table view. And you can also Edit the names in the table view. If you want to get some stuff out of the array in your program somewhere, you can use an outlet of your table view like this:
NSInteger row = [myTableViewOutlet selectedRow];
FileEntry* myEntry = [myArray objectAtIndex:row];