Change Table Data in Function - objective-c

I have a program that changes the data of a table (among other things). In a function (specifically when triggered by a button), I have the code below, but it says, "use of undeclared identifier 'tableView' ". However, outside of this, I have this run when I start the program, and it works.
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {
if ([aTableColumn.identifier isEqualToString:#"row1"]){
return everything2[rowIndex];
}
return everything[rowIndex];
}
I was watching a tutorial and I don't remember everything I did, so do I have to declare, delegate, link the function, or something else?
This is the declaration of everything(2):
NSString *everything[115];
NSString *everything2[115];

Related

Why use Message Forwarding

Why would you use Message Forwarding in Objective-c. Also when using it, you need to call the Surragate method with performSelector? I am thinking you have a lot of knowledge when you are coding this, why would you need Message Forwarding. I am reading that this is Obj-c multiple inheritance - but I don't see it like this, it is just another object attached to an object.
Hope you know and have a pratical example
Thanks
See my discussion at the end of this section: http://www.apeth.com/iOSBook/ch25.html#_uitabbar
Here I have interposed my own object as the data source for one of Apple's table views. I don't know how the table view works (it's Apple's) and I don't know what their data source does (it's Apple's). So I substitute my own data source but I keep Apple's, and any messages that I don't handle that arrive at my data source are passed on to Apple's. Thus in a sense I have made my data source "inherit" from Apple's.
#implementation MyDataSource
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([self.originalDataSource respondsToSelector: aSelector])
return self.originalDataSource;
return [super forwardingTargetForSelector:aSelector];
}
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)sec {
// this is just to quiet the compiler
return [self.originalDataSource tableView:tv numberOfRowsInSection:sec];
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)ip {
// this is why we are here: my tweaks
UITableViewCell* cell = [self.originalDataSource tableView:tv cellForRowAtIndexPath:ip];
cell.textLabel.font = [UIFont fontWithName:#"GillSans-Bold" size:14];
return cell;
}
#end

populating a tableview confusion

Using cocoa on mac osx 10.7 I populated a TableView with some rows, I have some confusions,
names is an NSArray* containing NSString*
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex;
{
return [names objectAtIndex:rowIndex];
}
I checked the protocol reference for the datasource in the apple's documentation
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Protocols/NSTableDataSource_Protocol/Reference/Reference.html
I am returning an NSString* in the above function, the signature of the method only returns id and not NSString* . The documentation gave me no clue about the return type it just says
An item in the data source in the specified tableColumn of the view.
My case was simple NSString* made sense and it worked but I am not sure. I am wondering where is this implicit knowledge coming from as to what type of data has to be returned by this method given there is no mention in the signature and nothing in the method's documentation :/
Any advise ? I am coming from .Net/android/ background the documentations there made more sense probably because those are strongly typed lanuguages ,...
The type of object that you should return is based on how the cells in your NSTableView are defined. By default when you create an NSTableView in Interface Builder, the cells are defined as NSTextFieldCell, so can return an NSString for those cells. However you can define the cells to accept other types of objects in your code (for example NSImageCell, NSButtonCell, etc).

Obtain a stringValue from NSTableView

I have a simple NSTableView which I have loaded with data from a NSMutableArray. When I select a row (entry) in the tableView and modify it, I can find the row index, what I cannot get is the edited entry out as a string so I can modify the array. I can find lots of information on selecting rows, etc., but not on how to get the actual modified string. I keep thinking this should be real simple. Help please.
Part of my code:
- (IBAction)toDoEdit:(id)sender // Accept the edited data
{
NSString *toDoItem = [[toDoTableCell:toDoTableView dataCellFoTableColumn:0 row:rowToBeEdited] stringValue];
// I get the error "dataCellForTableColumn' method cannot be found.
[toDoArray replaceObjectAtIndex:rowToBeDeleted withObject:toDoItem];
[toDoTableView reloadData];
[toDoTableView deselectRow:rowToBeDeleted];
}
~~~~~~~~~~~
// This method should return the cell value of the selected row
- toDoTableCell:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
return toDoTableCell; // No errors here but toDoTableCell is nil.
}
The 'Add' data to tableView works, 'Delete' data from tableView works, I just cannot get the edited data out of tableView so I can reload the data with the corrections.
What you are looking for is an NSTableView Delegate method:
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
This will return the NSCell that is in the row and column that you specify. From the NSCell you should be able to extract the value that you need. Depending on how you are using your NSCell you would either call [cell stringValue] or [cell objectValue].
Try this:
– tableView:setObjectValue:forTableColumn:row:
in - NSTableViewDataSource Protocol Reference
--- Edited based on comment ---
Above method is called whenever user tries to edit a table row, it also provides user with changed value as parameter. If you are trying to edit the row in table itself then it should serve your purpose. You can simply check the objectValue obtained as parameter and verify if it is correct or not. In case it is incorrect you can modify the obtained value and set it in todoArray.
Briefly:
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
// below case is an example, you can add your own
if([anObject isEqualToString:#"Incorrect"])
{
anObject = #"Correct";
}
// Considering todoArray is array of dictionary items containing keys as table-column identifiers
NSMutableDictionary *originalData = [todoArray objectAtIndex:rowIndex];
[originalData setValue:anObject forKey:[aTableColumn identifier]];
[toDoTableView reloadData];
}
To get the value being edited you can simply use this code in above method, before setting the new value:
NSString *editedValue = [[todoArray objectAtIndex:rowIndex] valueForKey:[aTableColumn identifier]];
Hope this helps :)
It is simple. Read up on Cocoa Bindings and NSArrayController.
Take a look at the NSTableView methods selectedColumn, selectedColumnIndexes, selectedRow and selectedRowIndexes. I guess they should provide you with the needed information.
Now you can query the model, i.e. the array, for the data you need.

Objective-C multiple method warning

I'm getting a warning in the following method:
- (void)tableView:(NSTableView *)aTableView
setObjectValue:(id)anObject
forTableColumn:(NSTableColumn *)aTableColumn
row:(int)rowIndex
{
NSString *identifier = [aTableColumn identifier];
Person *person = [employees objectAtIndex:rowIndex];
NSUndoManager *undo = [self undoManager];
[[undo prepareWithInvocationTarget:self] tableView:aTableView setObjectValue:[person valueForKey:identifier] forTableColumn:aTableColumn row:rowIndex];
if(![undo isUndoing])
{
[undo setActionName:#"Edit Person"];
}
[person setValue:anObject forKey:identifier];
[tableView reloadData];
}
I'm trying to implement undo so I figure I would call the same method and just pass the old value. The error I'm getting is "warning: multiple methods named '-tableView:setObjectValue:forTableColumn:row:' found". Any idea why?
The method on NSTableViewDataSource is declared as:
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
Your method uses int as the type of the rowIndex variable. Change that to NSInteger and all will be fine.
The underlying issue is that Objective-C does not support co-variance or contra-variance in method argumentation, leading to the warning.
Note also that you are colluding data model with view layer. Undo in this fashion is going to be very very tricky; if you don't also manage the undo stack in the context of every sort of the table and/or addition/removal of rows, undo is going to apply the value to the wrong row.
You would be far better off reworking your app such that you have a proper separation of model view and controller.
Well, here's what got rid of the warning:
[((MyDocument *)[undo prepareWithInvocationTarget:self]) tableView:aTableView setObjectValue:[person valueForKey:identifier] forTableColumn:aTableColumn row:rowIndex];
Casting to the class that I was in cleared up the ambiguity I suppose.

method syntax in objective-c [duplicate]

This question already has answers here:
Method Syntax in Objective-C
(4 answers)
Closed 3 years ago.
I'm a .NET programmer new to objective-c, and I'm struggling to understand some nuts and bolts syntax. For example, how should I parse this method signature:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
I understand what the "-" char means, and (UITableViewCell *) defines the return type. But the rest has me confused.
(1) (2) (3) (4) (5) (6) (7) (8)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
"-" Defines an instance method
Returns UITableViewCell pointer
First part of the method signature named "tableView"
Takes a UITableView pointer
With the local variable name "tableView"
Second part of the method signature "cellForRowAtIndexPath"
Takes a NSIndexPath pointer
With the local variable name "indexPath".
The actual method signature is: tableView:cellForRowAtIndexPath:.
Read Apple's documentation, like Objective-C: A Primer. It's explained right there. You know, the maker (Apple or Microsoft) has a lot of documentation on their site ...
Objective-C uses named, inline parameters for methods. (As bblum points out in the comment below, this style of parameters are sometimes called "interleaved".) This is a reflection of it's heratage as a mix of C and SmallTalk syntax. The trailing colons denote the names of the parameters to the method. For your method, the full name of the method is referred to as tableView:cellForRowAtIndexPath:. It takes two parameters, a pointer to a UITableView, and pointer to a NSIndexPath. In a java-like language, this method signature would look something like:
public UITableViewCell cellInTableViewForRowAtIndexPath(UITableView tableView, NSIndexPath indexPath);
Every foo:(bar)baz defines a parameter, for example
- (id)initWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ... {
defines a method with five* parameters.
The stuff before the : is part of the name of the method. In this example, the method's name is
initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:
The stuff between the (…) is the type of that argument. Here, we see that the first argument must be an NSString*.
Finally it's the name of the parameter.
(*: Sometimes there is sometimes a , ..., like in here, indicating it's a variadic method.)
The method is called in the syntax
id result = [theAllocedAlertView initWithTitle:#"title"
message:#"message"
delegate:someDelegate
cancelButtonTitle:#"cancel button title"
otherButtonTitles:#"other", #"button", #"titles", nil];
So the name of the method is repeated (in order!), and the parameter names are substituted by the actual arguments.
In C#, the corresponding function signature would look like
object InitWithTitleAndMessageAndDelegateAndCancelButtonTitleAndOtherButtonTitles(
string title,
string message,
object delegate,
string cancelButtonTitle,
params string[] otherButtonTitles);
and called like
object result = theAllocedAlertView.InitWithBlahBlahBlahAndOtherButtonTitles(
"title",
"message",
someDelegate,
"cancel button title",
"other", "button", "titles");
The method selector is:
tableView:cellForRowAtIndexPath:
where each value after the colon is a parameter. The signature is meant to read like an English sentence, i.e. "The TableView's cell for a row at this index".
If this were written in another language it might look like this
// #param (UITableView *) tableView
// #param (NSIndexPath*)indexPath
// #return UITableViewCell
- (UITableViewCell *) someFunctionName(tableView, indexPath) {
}
Thats roughly speaking of course. It would not be written like this in objective-c. However I believe it is possible to write a good chunk of your program in c++