Preserving (and loading) table view scroll position for each data source - swift

I am trying to replicate Mail.app behaviours in my app. If you have multiple e-mail accounts and select a random e-mail for each account and switch between each account from the sidebar, the app remembers your scroll position and which e-mail you selected and display them accordingly. That is what I want in my app.
I know how to preserve the row selection, that is easy. tableView.selectedRowIndexes
My tableView has multiple data sources and switches (tableView.reloadData()) accordingly from the sidebar.
I am having a major problem with the scroll position. I tried looking into NSScrollView, NSClipView and NSTableView. It seems to me that there are scrolling mechanism for each view.
I need to remember the scroll position when the user scroll for each data source
I need to load the previous scroll position when the user return to the data source
Also a strange behaviour I noticed is when reloading tableView to a different data source, it seems to persistently remember from the previous data source scroll position. Is that normal? I assumed it would reset to the top.
My data sources are arrays which are my NSViewController subclass properties.
If it matters, I am using storyboard, my app is targeting Big Sur and I am using Swift.

The position to save:
preservedPosition = tableView.visibleRect.origin
Restore:
tableView.scroll(preservedPosition)

Related

Positioning ListViews in WinJS Metro apps using scrollIntoView

I am building a jscript-based Windows 8 Metro app. The main screen of this application is a scrolling "panorama" view with several list views showing various aspects of the app's state. In some cases the user will select something on the page which results in a navigation to another page (using the WinJS.Navigation.navigate method.
When the user hits the back arrow on the other page, it returns to the main screen, and I use "scrollIntoView" on to position the screen to the section that the user was working on before the navigation occurred.
Unfortunately this hardly ever results in correctly positioning the view. It seems random. I suspect that the page isn't finished being built yet and that the scroll values are set based on the state at some snapshot in time.
Now the question:
Is there some what to be notified by WinJS ListView objects that they are completely rendered and layed out? Or is this the job of the page's ready function?
Thanks for any insight!
Putting multiple list views side by side is Not A Good Idea(TM). I would recommend putting one list view, and placing your content in a grouped data source to get the groups. If the items have different templates, then you can use a custom item Template selector to dynamically select a template.
Additionally, to ensure that the list view is scrolled to the right position, you need to use the indexOfFirstVisible to set the items the name suggests.

Need architecture direction

I'm creating an app and I need some help with design.
Launch Screen - I want to show 6-8 "category" buttons with labels loaded from an array ("normal" buttons from interface builder - not tab bar buttons or menu bar buttons).
Table Screen - When one of the category buttons is pushed on the launch screen, I want to show a table view with all of the items in that category.
Detail Screen - When one of the items on the table screen is selected, go to a new screen with details for the item. There will be an action button on this screen which will remove the item from the list if pressed.
My questions are as follows:
1) I don't want to show navigation buttons on the first screen. Can I still use a Navigation-Based application and hide the navigation controls on the first screen, or would it be better (easier) to create a view-based application and put a navigation controller "inside" one of the views? I'm totally open to any basic design approach suggestions you may have.
2) I've figured out how to create a sqlite3 file, add it to the project, query it, and generate the table view from the results, but I'm not sure about how to store the sqlite file in a way that will persist on the device when the user upgrades the app later. Any pointers on that?
Thanks for any help/links/documentation you can point me to. I've watched a million tutorials but none of the ones I've seen really address basic app design.
Now for Q1, both ways work fine but if you have buttons from the first screen, having a uinavigationcontroller might make it slightly easier if you plan to have back buttons on the screens after the first screen.
For Q2, to make the database persist when the user updates their app at some stage, simply keep the original database and include a new database (with a different name) with additional content, then modify your original database and import any additional content to it.
You can also do variations of that also, ie import content from old database to new database and etc. But the key is to keep the database file names different, ie add database_v1.sqlite, database_v2.sqlite and etc.
BTW don't forget to clean up any databases you won't use in future.

My data source is being changed out from under a UITableView

I have an app based on a tab bar and data retrieved from the Internet. The main tab shows a map and one of the other tabs shows incidents around the center point of the map displayed using a UITableView. If the user moves the map and then moves to the incidents page, I need to refresh the list of incidents displayed in the table. To do this I request the incidents in viewWillAppear:animated: and when that completes (asynchronously) I call the table view's reloadData method.
This works beautifully unless the user taps between the tabs quickly (e.g. display incidents, move to map, move map, move back to incidents, move back to map, etc.). At some point the incidents data source (an NSArray) is modified while the table view is trying to access it.
Here is a question that is similar:
UITableView Crashes if Data Source Is Updated During Scrolling
One of the solutions for that question describes a solution at a high level that is exactly what I want: Freeze the data source while the table is being updated. The thing I can't figure out, however, is when to unfreeze the data source. The problem is I can't find any way to be notified when the table is done being updated.
Any ideas? How do I freeze the data source while the table is being updated and then unfreeze it once the table is done being updated?
Although I'd really like to receive a notification when the table view is done accessing the data source, I found that my problem was due to modifying the data container from the work thread. The answer to this question led me to the solution:
Refreshing XML data and updating a UITableView
What I do now is fill a separate array in the worker thread and then perform a selector on the main thread to swap the updated data into the data container used by the table view.
The problem is I can't find any way to
be notified when the table is done
being updated.
I think you can assume that the data is done being loaded by checking in tableView:cellForRowAtIndexPath: to see if the last row has been loaded.
I haven't tested it, just making an assumption based on the API

Prompting user for multiple selections in an iphone app

I'm currently looking for a way to provide the user with being able to select multiple items from a collection of values.
I know this is done in the mail app whereby you can go into the edit mode of a folder and select multiple items by clicking on the circle on the left hand side.
What I'm unsure about is how this is achievable. Is anyone familiar with how to reproduce such functionality?
Thanks,
Matt Delves
The easiest way is this:
Provide a UITableView with all values the user can select.
Keep a mutable array with one object (e.g. an NSNumber) per table row to store each row's selection state.
In tableView:didSelectRowAtIndexPath:, toggle the selection state in your array for the tapped row and set the tapped cell's accessory type to checkmark or none, depending on the selection state.

iPhone Table View Data Edit Pane

I have an application I'm working on, and I need the user to be able to add new "Shows", "Movements" and "Dots." These are all represented by classes. At the root of the application, all the shows are shown, the user can click on the show, see the movement in that show, then tap on a movement and see the dots in the movement. It works beautifully.
Now, I need the user to be able to add and edit these instances of these classes. The way I am thinking this will work is when the user clicks on the "Add Show" button (Or the "Add Movement", etc) a new view will be pushed onto the Navigation Controller. This works. When the button is pressed, a new instance of the show class is created, and passed to the new view controller. This also works. If the user wants to edit the show, then they will hit the edit button for the row, and the instance of the class (which already exists) will be passed to new view controller, and the user will be able to edit it (It should use the same view controller for adding and editing)
My question is, in the examples I have seen, it is always really dirty to create the editing view. The edit view is a table view with each row having some sort of control. Usually it is a UITextField, but it may be a slider, and it may be one where another view is popped, and the user needs to check one value. (This is similar to the address book application when adding and editing a contact)
Is there any way that is cleaner than just manually going in and creating a bunch of arrays to hold what custom table view cells need to be at what row? This gets very messy, very fast. I can do it this way, I just was wondering if there is a better, possibly faster way.
To my knowledge there's no structural solution to solve this. I'm afraid managing the cells with child UITextField or other controls yourself is the only method. This indeed gets dirty and painful very fast, I certainly feel your pain.
Although it doesn't exist, it would be very convenient if Apple added out of the box editing cells to the SDK, similar to the different normal cell styles. I haven't come across an open source project that addresses this issue, but it might exist.
If you do find a better/cleaner method to handle these situations, be sure to ping back.
as far as i know, editing mode is the only way to make the changes you describe (if i understood correctly). I agree that it doesn't seem like the most elegant approach.
http://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW19