Cycling on NSTableView rows - cocoa

I have NSTableview with N rows and two columns (column_A and column_B).
I want cycling on rows, i try so :
IBOutlet id myTableView;
NSTableColumn *column_A = [myTableView tableColumnWithIdentifier:#"A"];
NSTableColumn *column_B = [myTableView tableColumnWithIdentifier:#"B"];
int nr = [myTableView numberOfRows];
for (int i = 0; i<nr; i++) {
NSString *a = [[column_A dataCellForRow:i] stringValue];
NSString *b = [[column_B dataCellForRow:i] stringValue];
... (other code)
a = nil;
b = nil;
}
But I get same values,
for i = 0 I get a = test1 and b= test2
for i = 1 I get a = test1 and b= test2
...
for i = nr -1 I get a = test1 and b = test2
Where is the error ?

-[NSTableColumn dataCellForRow:] returns the prototype cell that is used to show the value at that column and row. This prototype cell can be reused for multiple rows in the same column, so you cannot rely on it having the specific value shown at a given row.
In general, if you want to enumerate the values shown by a table view, you iterate over its data source—an NSTableViewDataSource-conforming instance, which can be obtained via -[NSTableView dataSource], or an NSArrayController instance bound to contents if you are using bindings.
If for some reason you cannot or do not want to use the data source, you should use -[NSTableView preparedCellAtColumn:row:] instead. This method makes sure that the cell is populated with the data source/content value for a given column and row.

Related

Xcode : Passing Data between view controller

I have A Table View Controller containing names (as example A, B, C, etc,,,).
If I pressed on one cell, it should be shifting to another B View Controller with the 2 numbers (a, b).
and on the name cell, it should appear the value of c = (a + b) in the subtitle.
On B class, i create a protocol in order to send to A a NSDictionary.
and from A, i can access these Data without any problem from A
I am just cannot solve how to insert the value of c in the subtitle of the same cell which I clicked.
for example, when i press on A name1, i switch to second view controller, So, i put values for a = 2 and b = 6 and click on save, I got the value c = a + b = 8.
I want to have name1 and under the value of 8.
I tried to reload data for table view, but didn't work.
Where shall I write some codes in order to make the subtitle with the value c appear.
Try this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = #"text";
cell.detailTextLabel.text = #"description text";
}

Add values to NSTableview in a way that lets me reorder them at will

I have an NSTableView and need to add values. I was thinking of doing it with a NSArrayController, but near my table there are four buttons: Move to top, Move up, Move down, Move to bottom. I must be able to reorder the entries in the table with these buttons.
The only thing I can think of is to use an array of dictionaries, where the first entry of the dictionary is the value displayed and the second entry of the dictionary is a double that is used to sort the array. If I move a value up or down, I take the sort value of the entry before and after the destination sum them, and then I divide by two.
I am not sure that the solution I was thinking of is appropriate. What would be the best approach to this scenario?
------EDIT-----
Working on it, and now I am having difficulties writing the updated "order" value into the arraycontroller. Beside that i am having trouble in actually sorting the table with the "order" column once that the value has been updated. Here is my code:
-(IBAction)singleMoveKeywordUp:(id)sender
{
NSInteger selectedRow = [singleKeywordTable selectedRow];
double firstnum;
double secondnum;
double newnum;
NSMutableDictionary *kwmutabledict = [[NSMutableDictionary alloc] init];
if (selectedRow < 2)
{
firstnum = 0;
kwmutabledict = [keywordscontroller.arrangedObjects objectAtIndex:0];
secondnum = [[kwmutabledict valueForKey:#"order"] doubleValue];
}
else
{
kwmutabledict = [keywordscontroller.arrangedObjects objectAtIndex:selectedRow-2];
firstnum = [[kwmutabledict valueForKey:#"order"] doubleValue];
kwmutabledict = [keywordscontroller.arrangedObjects objectAtIndex:selectedRow-1];
secondnum = [[kwmutabledict valueForKey:#"order"] doubleValue];
}
NSMutableDictionary *newkwmutabledict = [[NSMutableDictionary alloc] init];
newnum = (firstnum + secondnum)/2;
[newkwmutabledict setObject:[NSString stringWithFormat:#"%#",[kwmutabledict valueForKey:#"keyword"]] forKey: #"keyword"];
[newkwmutabledict setObject:[NSString stringWithFormat:#"%f",newnum] forKey: #"order"];
[keywordscontroller.arrangedObjects replaceObjectAtIndex:selectedRow withObject:newkwmutabledict] ; //<--------
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"order" ascending:YES];
[singleKeywordTable setSortDescriptors:[NSArray arrayWithObject:sort]];
}
This is failing at the row marked with an Arrow with the error message -[_NSControllerArrayProxy replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance 0x100450520
I can't figure out whats wrong.
keywordscontroller.arrangedObjects returns (NSArray *) which is NOT mutable, and NSArray does not contain selector "replaceObjectAtIndex:withObject:". Hence the exception/error "unrecognized selector".

Replace all keys in an array of dictionary in cocoa

I have a mutable array that consist of array of dictionaries as:
NSArray *myArray
({
    {
        "COL_1" = Jhon;
        "COL_2" = 01/27/13;
        "COL_3" = THAILAND;
        "COL_4" = 5000;
        "COL_5" = No;
    },
    {
        "COL_1" = Peter;
        "COL_2" = 01/27/13;
        "COL_3" = US;
        "COL_4" = 4000;
        "COL_5" = No;
    }
 })
All dictionaries in the array have the same keys. I want to replace the existing keys with a new set of keys that will come from a NSArray. The final array should be like -
NSArray *myArray
({
{
"A" = Jhon;
"B" = 01/27/13;
"C" = THAILAND;
"D" = 5000;
"E" = No;
},
{
"A" = Peter;
"B" = 01/27/13;
"C" = US;
"D" = 4000;
"E" = No;
}
})
I do not want a nested for loop in which i have to iterate overs each elements in the array and again for each dictionary, iterating over each key , to change the keys.
What I did is as follow:
NSArray *myDictFnalKeys = [NSArray arrayWithObjects:#"A",#"B",#"C",#"D",#"E",nil];  // Here we have set our own keys which will replace the existing keys .
NSMutableArray *myNewArray = [[[NSMutableArray alloc] init] autorelease]; //create a new mutable dictionary
for (id myArrayInstance in array) {
            NSDictionary *myNewDict = [[NSDictionary alloc] initWithObjects:[myArrayInstance allObjects] forKeys:myDictFnalKeys]; // copy the object values from old dictionary and keys from the new array.
            [myNewArray addObject:myNewDict];
    }
The problem is the values for the dictionaries are not coming in proper order. [myArrayInstance allObjects] is not returning the proper order so the final array is not in proper order. Its coming like-
NSMutableArray *newArray
({
    {
        A = "01/27/13";
        B = No;
        C = Jhon;
        D = 5000;
        E = THAILAND;
    },
    {
        A = "01/27/13";
        B = No;
        C = Peter;
        D = 4000;
        E = US;
    }
})
You're almost there, the only issue is the call to allObjects which as you found returns the objects in some arbitrary order. Instead define an array of your original keys:
NSArray *originalKeys = #[#"COL_1", #"COL_2", #"COL_3", #"COL_4", #"COL_5"];
where the elements are in the same order as the replacement in your myDictFnalKeys. Now replace the call to allObjects with:
[myDict objectsForKeys:originalKeys notFoundMarker:NSNull.null]
This will return an array of objects matching the keys in order found in originalKeys (if a key is missing then the result array will contain whatever notFoundMarker is - NSNull.null in this case).
Do that and your code will work.
You can use 'objectsForKeys:notFoundMarker:' for getting the values in the requested order. Pass [NSNULL null] as the second argument. (This really does not matter, all the values are present in the dictionary and you are not trying get the values for a undefined key.)

Pre-Select UIPickerView based on previous string in Xcode

I have the following code that populates a UIPickerView with the string value that was previously selected stored in the variable "preValue."
NSUInteger currentIndex = [arrayColour indexOfObject:preValue];
[ColourAndShadePicker selectRow:currentIndex inComponent:0 animated:YES];
The problem is that it doesn't seem to be matching the value exactly when there are spaces involved.
For instance if the 3 options are
Red
Green 1
Green 2
and the user selects Green 2, the Green 2 value is stored but on re-populate it's selecting Green 1 and not Green 2.
I think it has something to do with the spaces, and picking the first similar option?
Any ideas how to solve?
I'm unable to use the row number and need to match the string exactly.
EDIT:
To populate the array in the first place I'm using the following:
arrayColour = [[NSMutableArray alloc] init];
for (int i = 0; i < [substrings count]; i++)
{
//parse out each option (i)
NSString* companyoption = [substrings objectAtIndex:i];
//add as option to component
[arrayColour addObject:companyoption];
}
Thanks!

xcode array access with IBOutletCollections. Mind-boggled.

I have 2 arrays. One is a collection of buttons. The other one should be an array of dictionaries. I am logging the length/size/count of object in the arrays in the console using [arrayListName count]:
2012-07-19 19:56:59.001 ABC[3224:707] lastest_badge_outlet_collection count: 4
2012-07-19 19:56:59.007 ABC[3224:707] badges_array count: 1
ok so when running this loop I want to populate the images with the key value 'name' from each of the dictionaries in existence in the array (that is badges_array). At the moment I have dictionary stored in that array (which is fine). However when I run this through the loop it always populates the third image along
for(int i = 0; i < [lastest_badge_outlet_collection count]; i++){
UIButton *button = [lastest_badge_outlet_collection objectAtIndex:i];
if(i < [badges_array count]){
NSDictionary *badge_d = [badges_array objectAtIndex:i];
NSString *badge_d_image_string = [badge_d objectForKey:#"image"];
UIImage *badge_d_image = [UIImage imageNamed: badge_d_image_string];
[[button imageView] setImage:badge_d_image];
[[button imageView] setContentMode: UIViewContentModeScaleAspectFit];
[button setAlpha:1.0f];
} else {
[button setAlpha:0.5f];
}
}
Theoretically it should be populating the first image. Why is it doing this? How does it decide which order the items are in the outlet collection for example...
Mind boggled.
I tried rewiring them to the collection 1 by 1 by wiring them up in order with no success....
Here is a screenshot.
Thanks!
I don't think there is a way to predict the order of IBOutletCollection.
I guess what you need to do is sort the collection before use it.
You can set tag property for each button and sort them by those number.
Check this answer for more detail.

Resources