custom tablecell valueForSelectedRow problem - iphone

I have created a custom uitablecell which contains several values. When the user selects a row, I want to be able to select that row's content for one of the values in the custom uitablecell. If the cell looks like this:
ba_type varchar2(20) P
source varchar2(20) P
row_qual varhcar2(20)
If the user has selected the 'source varchar2(20) P' row, I want to be able to grab the value of 'source' out for my next query.
thx,
wes

Strictly speaking, you've created a tableview cell that displays several values. Sitting in memory somewhere behind that is an array that contains the actual data. That's how MVC architecture works.
Ideally, you have some data structure in memory that corresponds to the cells. If you had an NSMutableArray in memory, you could retrieve the value by doing
// assumes one section in the table view
NSString* sourceForNextQuery = [dataSourceUsedToPopulate objectAtIndex: indexPath.row];
inside didSelectRowAtIndex
If you insist on retrieving the text from the label in the table view cell, when you create the label that contains it, add a tag (mySourceLabel.tag = 999). Then find that tag again by using searching for the tag, the get the text (UILabel.text)
But really, you want to separate the presentation of the data from the underlying model, and have the controller contain the data.

Related

NSTableVIew bound to NSArrayController doesn't save changes

I have a very simple project containing an NSTableView with 3 columns and buttons for adding new row, removing row and saving the data.
For the purposes of this project I want to save the values into the NSUserDefaults db AND to do all this with no coding, so the IB connections and properties are as follows:
Added Array Controller object via IB. Its Controller content is bound to Shared Users Defaults Controller (Controller Key:values, Model Key Path: myvalues), Handles Content as Compound Value checked.
Added the table view set to have 3 columns and set as view-based.
For the table view itself, its Content is bound to Array Controller (Controller Key arrangedObjects) and its Selection Indexes are bound to Array Controller (Controller Key selectionIndexes)
For each column of the table, the Table View Cell item (third in chain) Value is bound to Table Cell View (Controller Key empty, Model Key Path set to objectValue.xxxx where xxxx is an arbitrary name string for the column); also the Behavior attribute is set to "editable".
The add row and remove row buttons sent actions are connected to the Array Controller add and remove methods and the Save button sent action is linked to the Shared User Defaults save method.
When I run the project I can initially do "add", enter the values for the columns, click on Save, end execution and when I re-run it the data is shown. However, if I then try to change any of that data, the changes won’t be kept. If I add additional rows, and enter data that data is not kept (the rows will be there, just empty). Removing rows works as expected. (NOTE: also if I added several rows on the initial execution, only the first would have data on subsequent executions)
My question is: Why won’t data changes (after the first) work? It seems like there’s a missing layer somewhere.
I created a second project, very similar to first, but specified cell-based table rather than view-based; also the bindings are simpler with NO bindings for table-view but just directly bind table cells Value to Array Controller. This project works perfectly. Cell data can be edited, new row data entered, etc.
Any help would be appreciated
Since the cell-based table works as expected, with no coding, I'm going to use that for now. As for getting the view-based table to work properly, it appears (from Ken's notes and other SO threads) that the managed content is probably being updated properly but the user default controller is not being made aware of these changes. So a simple workaround would be to add a couple of lines of code, for example in AppDelegate applicationWillTerminate method:
let ac : NSArray = arrayController!.arrangedObjects as NSArray
NSUserDefaults.standardUserDefaults().setObject(ac, forKey: "myvalues")
where arrayController is an outlet for IB Array Controller.
(This is a bit of overkill as it would set the object every time the app runs, but you could also connect the SAVE button to a method that would set a Bool and then issue the setObject conditionally on SAVE being requested.)

How to access UITableViewCell that is out of view on a data entry screen to validate content?

I have a UITableView that contains data entry fields whose total height is about 2 screens tall. After entering data in the fields the user taps the Save button in the UINavigationBar then the contents of all the fields is validated.
If field #1 (topmost) is out of view because the user has scrolled to the bottom of the table then the UITableViewCell that contains the UITextField w/ the value is not accessible. Trying to access the cell/field using cellForRowAtIndexPath returns nil.
What would be the best approach to access all the fields in order to validate the field contents?
The best approach would be to store all of the data as it is entered in the fields, and then query your model for the data when you need it, rather than depending on the data being stored in the view.
You have a few options
What I do - store the text from the fields somewhere else and then use that
Store all of your cells in memory all the time so that they never get reused
Temporarily make your table big enough to hold all of your cells when you're doing the validation
Note that you can do number 3 without the change ever being visible.

Mapping a dataset to textfield inside UItableView

In my app, I am using some .net asmx services (as backend) to get some data and populating it on my views. In one of the modules, i need to edit and save the data which am getting from the services.In that am getting several rowkeyvalues and accordingly am creating those many row cells in my tableview, which consists two UItextfields as well, which displays some unique code and comments.
Now if I have to edit and save some fields, I need to map each one of those rowkeys to each row cell and after that am creating object which is basically the wsdl proxy class which I have generated using Sudzc and pass each dataset and serialize it to XML and POST it through SOAP.
The real problem here, am not getting how to map each unique rowkeys to each row cell and create unique dataset(which mainly contains other fields as well including rowkey) for each row and pass it to proxy object (WSDL stubs).
Not sure I understand your problem, but there are 2 ways I can think of to map a row cell to something.
1. Each UITableViewCell is a subclass of UIView, and so it has a "tag" attribute, which is an int.
You can set this and check it's value.
2. When a user taps a row, the tableView:didSelectRowAtIndexPath: is called. IndexPath.row is an int that gives the absolute row postiion within it's section (and if only one section, then in the whole table).
Usually, in cellForRowAtIndexPath: you fetch your backing data corresponding to the IndexPath.row and populate the cell. You could also set the cell's tag at that point.
This ties together the row, the cell and the data.
Hope that helps.
-Mike

Storing unique ID in UITableViewCell

I have a table where there will often be two cells with the same title. I'm zooming in on a map whenever a cell in the table is clicked, so using the title as a unique identifier is out of the question. I already have a unique identifier, but I need to find a way to store it in a UITableViewCell object.
I have been considering two options, both of which are poor, IMO.
1) store the unique ID as the text inside the text of the detailTextLabel property.
2) build a custom UITableViewCell class.
I'm new to objective C, and I would essentially like to know if theres a third option that isnt as inefficient as #1, but not as involved as #2.
Thanks
Use the cell's tag property (works only if your identifier is an integer).
That said, cells already have a unique identifier (albeit not necessarily constant) and that is their indexPath, i.e. their position in the table. You should generally not use the cells to store any data directly. Instead, store the data in a model object and maintain the connection between model data and view via the indexPath.
This is especially important when dealing with table views as cell views get reused or deallocated as soon as a cell is scrolled off the screen.

Is it possible to preload all the cells in a uitableview?

Is there a simple way to preload all the cells in a uitableview?
I need to do this in order to change whether or not all the cells are checked. If I just use cellForRowAtIndexPath, and the user say unchecks all the cells, and then checks a visible cell and starts to scroll again, either the selected cell gets deselected or the newly loading cells are selected.
It seems the easiest way to go would be to preload all the cells if possible.
Thanks!
Don't use the cells as your database.
Your cells are just a narrow window onto your data. The cells just show you a few of the objects in the underlying data. If you try to preload all the cells so you could then select them all, the UITableView could die a slow death, or slow crawl. Especially if we're talking hundreds of entries.
If you want to select all the items in your data, you do so with a direct call to your data to select its objects. Then, you reload the data into your TableView with a reloadData and if everything is set up right, your cells will show the selected state.
Read up on UITableView. Look at Apple's samples. You need to see the separation of data from the view and the controller.
Please re-read the answer I wrote here to your previous, similar question, which explains one solution to your problem.
Again, you should consider keeping an array of on/off settings. You can use NSMutableArray or a C array of int or BOOL values, whatever you want. But it definitely sounds like you need a data model.
Your -tableView:cellForRowAtIndexPath: looks up values of this array. Each value in the array corresponds in some way to a row in the table.
If you only have one section, then you can simply use the ith element of the array to set the checked state of the ith row of the table view. If you use NSMutableArray to store NSNumbers, you can handle resizing quite easily.
If you have more than one section, keep an array of arrays. Each top-level array corresponds to a section. Each inner array corresponds to a section's rows.
If you use NSMutableArray to store NSMutableArrays of NSNumbers, you can handle resizing and section addition and deletion quite easily.
The method -tableView:cellForRowAtIndexPath: then sets up cells with or without checkmarks, depending on the array's value.
Having a data model gives you the freedom to programmatically perform "select all" and "deselect all" button operations.
For example, when you click a button to "select all" cells:
Loop through the array and set each value to YES or 1 or whatever "on" label you chose originally.
Call [tableView reloadData], which is a method that goes back to -tableView:cellForRowAtIndexPath: and which will set a cell's checkmark state based on the state of values in the updated array.
No, you can't do this. You seem to be under the impression that a cell represents a particular piece of data, it doesn't. When the top cell scrolls off the screen it is usually recycled and brought in as the bottom cell. So a list that has hundreds of items you can scolled through may only ever have 8 or 9 cells alloc'ed and initialized.
You need to rethink your application's architecture. When you "uncheck all" it shouldn't change the visual state of the cell, it should change some state in the objects the cell represents, then when you load the cell for the object at that index path you should read that state and set the check mark appropriately.
The changes in the visual state of your cell should always be in response to changes in your underlying model.