How to Add Checkbox Cell to NSTableView with Cocoa Bindings? - objective-c

I'm new in Cocoa. I have a table that stores Contacts. I'm not using NSTableView Protocol. I'm using Cocoa Bindings , and Mutable Array for storing in it. The question is , I want to be able to have checkbox on each row, and select contacts that I want, and be able to get selected rows. How can I do it? When I try to put Check box cell in column of Table, nothing works. Here my code how I'm filling my NSTableView for contacts. So what should be done to be able add checkboxes and handle them? Thanks.
NSMutableDictionary *dict =[NSMutableDictionary dictionaryWithObjectsAndKeys:
Name, #"Name",
Surname, #"Surname",
Education,#"Education",
nil];
//controller for binding data to NSTableView
[controllerContacts addObject:dict];
//Table for viewing data.
[viewTableOfContacts reloadData];

If you want to use checkbox at each row via bindings, you need to define a key in dict corresponding to your binding for check box.
In your case, it can be like this-
NSMutableDictionary *dict =[NSMutableDictionary dictionaryWithObjectsAndKeys:
Name, #"Name",
Surname, #"Surname",
Education,#"Education",
[NSNumber numberWithInt:0],#"selectedStudent",
nil];
Then bind that column for "selectedStudent" key.
Also if you want to retrieve only selected rows, you can use NSPredicate like this-
NSPredicate *selectedStudentPredicate = [NSPredicate predicateWithFormat:#"selectedStudent == 1"];
NSArray *selectedStudents = [controllerContacts filteredArrayUsingPredicate:selectedStudentPredicate];
Hope this helps !

Related

NSMutableArray add data to NSTableView creating an empty row?

I've create a function below which will call when a button is pressed:
- (IBAction)setData:(id)sender{
[_myArrayController addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"James", #"Name",
#"Smith",#"Surname", nil]];
}
On My NSTableView I have two columns both NSTableViewColumns have been binded to the keys above Name for the first and Surname for the second for the arrangedObjects controller key.
When I press the button a new row is created however both column fields are blank rather than saying James Smith.
Any ideas what I could be doing wrong?

How to use predicate with nsdictionary?

I have a dictionary within another dictionary in my plist as below:
<dict1>Root
<dict2>A
<dict3>Apple
<string>"About Apple..."
<dict3>Arrow
<string>"About Arrow..."
<dict2>B
<dict3>Ball
<string>"About Ball..."
<dict2>C
etc...
The user is currently using a search bar to search for a string. How can I look with the third level and compare each string using a predicate and return results and pass these to table view cells?
I tried following this video tutorial but I fail on the predicate.
https://www.youtube.com/watch?v=UE4h_Td6W6U
He has written his dictionary to an array from what I can see. Mine seems a little more complicated.
I am new to this so any help will be appreciated.
You need to traverse down your dictionary list until you get to the Dictionary that you're looking for. It looks something like this:
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"YOURPLIST" ofType:#"plist"];
NSMutableDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath]; //This puts you into the root directory
NSMutableDictionary *secondLevel = [NSMutableDictionary dictionaryWithDictionary:[dictionary objectForKey:[NSString stringWithFormat:#"A"]]]; //or B or C etc
NSMutableDictionary *thirdLevel = [NSMutableDictionary dictionaryWithDictionary:[dictionary objectForKey:[NSString stringWithFormat:#"Apple"]]];
This will put you in the Apple dictionary, however to be able to fetch the string you need a key attached to it. Your dictionary should look like
<key>Some key name</key>
<string>About Apple...</string>
And then you could fetch the string using the key through:
NSString *string = [thirdLevel objectForKey:#"Some key name"];
If you're strictly searching for strings, you could do something like this Search String in NSDictionary store in NSMutableArray

Get data from a PList into UITableView?

I want to maintain a list of records, for each one I maintain the same type of data. I want to use this data in 2 different places:
UITableView that takes from each record the "Name" value
UIViewController that takes all the data to use in different fields.
I assume I should be using a plist to store the data; I also assume that the object that should be receiving the data for the UITableView is NSArray so I can use the cellForRowAtIndexPath method to create the table automatically.
So i created the plist "PLForArr.plist":
It seems that i can only get a NSDictionary when calling the plist using
NSString *path = [[NSBundle mainBundle] pathForResource:#"PLForArr" ofType:#"plist"];
NSArray * myArr = [[NSArray alloc] initWithContentsOfFile:path]; //doesn't work...
NSDictionary * myDict = [[NSDictionary alloc] initWithContentsOfFile:path]; //does work, but who to I make a NSArray out of it / or get the data from here to the UITableView?
I understand that i don't understand something basic here... Can someone take me step by step on:
How to keep the data - should I use plist or something else? Should I have a main record of type array (as I did on the example plist here) or can I just keep it as these Dictionaries without the unnecessary MyArr that I used considering the UITableView end target?
How to call the data - Is there a way to get it into a NSArray or must it get into a NSDictionary?
How to call it into the the UITableView - Can I fill in the lines using a NSDictionary?
Storing the data is an Array or a Dictionary is up to you. But if you want to make changes to it over time you can't store it in the main bundle.
Your pList file is a dictionary that contains an array. See code example below.
You will have to store the dictionary in an array for the data source for your table. See code example below.
Assuming that your UITableView's data source is called tableArray. You can use tableArray to fill in the information in the table and your view. Oh yeah,
NSString *path = [[NSBundle mainBundle] pathForResource:#"PLForArr" ofType:#"plist"];
NSDictionary *myDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *myArray = [myDict objectForKey:#"MyArray"];
self.tableArray = [myArray copy];
[myArray release];
[myDict release];
This goes in tableView: cellForRowAtIndexPath:
cell.text = [[tableArray objectAtIndex:row]objectForKey:#"Obj Name"];
Storing your data either in a dictionary, or in an array is up to you. Depending on the kind of data you have, you will consider storing unordered collection of objects (dictionary), accessing the entries with keys; or rather in ordered collection (array), using numeric indexes.
It's fine to get arrays from property list files, but the root (top level) object is a dictionary (in the screenshot, "MyArr" isn't the top-level object, it is the key for accessing your array in the top-level dictionary). To get your array from it, simply alloc/init the plist dictionary the way you did, and access the array entry using its key ([myDict objectForKey:#"MyArr"]). Otherwise make sure you set the root object of the property list to be an array, and retry NSArray's initWithContentsOfFile:
The real question seems to be How can I fill the cells with my data ? The table views ask its delegate and dataSource about how many sections, rows in a section, to display. Based on these numbers, it will ask the dataSource for cells. Once again depending on the storage type you've chosen, you will implements these methods a little bit differently, but the concepts remain.
You will probably want to read documentation about :
Property List
Table views

Objective-C identifier from NSString

I want to pass an NSString to a method and have that particular NSString name a new NSSMutableArray. Confusing? Programmatically looks like this:
+ (void)newMutableArrayWithName:(NSString*)theArrayName
{
NSLog(#"Creating an array that is named: %#",theArrayName);
NSMutableArray* theArrayName = [[NSMutableArray alloc] init];
}
Unfortunately, "theArrayName" is not affiliated with the argument passed to the method. Is there any way this is achievable?
The name of a variable is used by the compiler, and is set at compile-time, not at run time.
If you need to be able to associate a label with an array, I suggest that you use an NSDictionary to do something like this
NSString *theArrayName = #"My Cool Array";
NSMutableArray *theArray = [NSMutableArray array];
NSDictionary *theDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
theArray, theArrayName, nil];
You could have multiple "named" arrays in the dictionary, if you wanted, and could access them by the names that you gave them
[theDictionary objectForKey:#"My Cool Array"];
Look into key-value coding for setting the values of existing properties by the property's name, but it appears it can't create a new property. For that, you should just use a dictionary.

objective-c how to create an enumeration array with its string values as keys?

i have an enumeration say gender, now i want to associate it to string values to use in the view inside a picker view. It's cocoa-touch framework and objective-c as language.
So i don't know of a way to set the data source of the picker view as the enumeration, as could have been done in other frameworks. So i've been told i have to make array of enum values. and then i tried to add thos into an NSMutableDictionary with their respective string values.
So i ended up with
NSArray* genderKeys = [NSArray arrayWithObjects:#"Male",#"Female",nil] ;
NSArray* genderValues = [NSArray arrayWithObjects:[NSNumber numberWithInt:male],[NSNumber numberWithInt:female],nil];
for(int i =0;i<[genderKeys count];i++)
[_genderDictionary setValue:[genderValues objectAtIndex:i] forKey:[genderKeys objectAtIndex:i]];
and it's not working saying it's not a valid key, and i've read the key-coding article and i know now what's key and whats keypath, but still how can i solve that. It's ruining my life, Please help.
Sorry guys, i was using NSDictionary for _genderDictionary.But i had in my mind that it was nsmutable. Thank you all.
Be careful using UI text as keys into your database. What amount when you need to localise your application to french, chinese, arabic etc?
That works for me. Running this (your code, with the first line added so it would compile) seems to work fine.
NSMutableDictionary *_genderDictionary = [NSMutableDictionary dictionary];
NSArray* genderKeys = [NSArray arrayWithObjects:#"Male",#"Female",nil] ;
NSArray* genderValues = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2],nil];
for(int i =0;i<[genderKeys count];i++)
[_genderDictionary setValue:[genderValues objectAtIndex:i] forKey:[genderKeys objectAtIndex:i]];
NSLog()-ing _genderDictionary outputs this
{
Female = 2;
Male = 1;
}
edit: re-reading your question, makes me think what you are looking for is the delegate methods of UIPickerView... implementing –pickerView:titleForRow:forComponent: is where you set the text that appears in the picker. If you have an NSArray of genders, you would do something like return [_genderArray objectAtIndex:row]; That way you don't need to fuss around with a dictionary and keys.
edit 2: a picker's datasource can't be an NSArray or NSDictionary directly. It has to be an object that implements UIPickerView's datasource/delegate protocol (which I suppose you could do with a subclass of NSArray, but that'd be cah-ray-zay!).
If I understand you correctly, you try to create a pre-populated dictionary.
You could use [NSDictionary dictionaryWithObjectsAndKeys:] for that.
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt:0], #"Male",
[NSNumberWithUnsignedInt:1], #"Female", nil]