I have a WKInterfaceController subclass that shows a 6 row WKInterfaceTable. This class is also initial interface controller. When receiving a notification action via handleActionWithIdentifier:forLocalNotification I am modally presenting a second interface controller. The user takes no action on the modally presented interface controller, but loading it modifies the state of one of the 6 objects used by the row controllers in the initial interface. When the modal controller is dismissed, my intent is to reflect the updated state in the table.
I have no issues retrieving the updated objects since their management is handled by another class that I can simply query for updated data. Since the initial interface controller has already executed awakeWithContext:, I can only rely on willActivate to updating the interface. This seems to be in line with Apple's guidelines since I'm not initializing the interface as part of that method, merely updating it.
TL;DR;
When I update the rows via the row controller, only the value that was updated is displayed properly on the cells. The other cells use the default values assigned to the labels in my cell at design time on the storyboard.
For example
Row 1: Count - 3 Best - 3
Row 2: Count - 42 Best - 99
Row 3: Count - 42 Best - 99
The extremely curious part is that this only happens on subsequent calls to willActivate. When just opening the watch app and updating the interface for the first time in willActivate it behaves as expected. When being activated as a result of the modal dismissing, this behavior creeps up.
Thanks for any ideas.
I can think of two possible issues.
First, the WatchKit interface controllers behave as though they are snapshotted in page sets. After they have been displayed once, the values won't update after being deactivated until they are fully on screen and your willActivate method has been called. Switching images has the same as switching a table row label when the interface isn't visible. It MUST be done in willActivate otherwise it appears to get dropped.
The other problem I've seen related to this is when you setNumberOfRows, you need to update the values in ALL rows. Otherwise you will end up with customized row values for the ones you set, and the default values from the storyboard for all other rows. If you're only updating the values for a particular row in willActivate and not calling the setNumberOfRows on the Table, then I'd say you should file a bug with Apple's Bug Reporting System.
Related
This only happens on iOS 13.. iOS 12.x works fine.
I have a table view with a search controller, and two datasources, one for the regular functionality and one for the search functionality. (the search functionality is unrelated to the content displayed on the main table content).
After cancelling a search, the searchBarCancelButtonClicked: method is triggered, I switch from the search data source to the main datasource and reload the table view but even though the table view details show that the correct datasource is set, the UI still shows the search data source.
I tried triggering the layout refresh, but no luck.
Worth mentioning that the UITableViewDataSource methods are called on the correct data source, it's just the UI that's out of sync so to speak.
Any idea what could cause such a thing?
If I manually set the search controller inactive, it works: [self.searchController setActive:NO];
In my app, I have a very custom UITableView. The cells are all statically defined in Interface Builder, but based on the data structure the table morphs in many various ways. For example, if some data doesn't exist, some cells (or entire sections) are not displayed, custom separator lines are added to account for missing cells, extra views are loaded into the cells, VoiceOver labels change, etc. Because all the cells are static, I set up the table layout in viewDidLoad because I always have the data available at that time. I have always presented this view controller modally, which has worked great. If the user wants to display different data in this table they have to dismiss the view controller and pick a different item to present it again, and it gets rendered appropriately in all cases.
But now I am converting this into a split view controller for iPad, so this UITableViewController never disappears off screen, but I need to set up the table again when the user taps an item. The problem is, because the table is never deallocated, its previous layout still exists when I load more data into it. It would be a lot of work (and an excellent opportunity for many difficult to reproduce bugs to pop up) to test all possible scenarios and try to reset it back to its "pre viewDidLoad state" or undo those previous layout changes if not relevant anymore, if not impossible because I don't have references to the many different custom separator lines generated.
My question is, is it possible to completely reset the table view controller every time a row is selected in the master view controller, therefore allowing it to properly set up the layout because it is not stuck with the previous layout?
I essentially need some way to completely wipe it clean as if it never did any setup, then instantiate it again to cause viewDidLoad get called (or I can move that code to its own method or viewWillAppear). I'm basically looking for a way to reset the tableView back to how it is defined in Interface Builder.
I believe this would result in a flash because the table would completely disappear then reappear in a different format, but that would be acceptable. If that can be animated that'd be nice. If this is really not recommended at all, how do you suggest I proceed to ensure the layout is always appropriate for the data it is presenting?
I was over-thinking this. There's really no need to completely throw away the table and generate a new one. It turned out to be simpler than I had thought to reset the table back to its default state. Just had to be sure to catch every possible thing that could change, including VoiceOver labels, and reset to nil or the default value. Then it can run through the reset code then the layout code every time the data changes and render an appropriate layout. The most difficult part was to remove the custom separator lines, which I solved by adding each one to an array when it's created, then index through it and remove each one from its superview then remove the Autolayout constraints associated with it. One can wrap all of this into a UIView animation block to get a nice fading effect. It's working quite well.
I am currently developing a Core Data application. I have a table view that shows a list of items whose attribute scheduled (which is a date) is nil and a BOOL attribute is NO. There is a button in each of the table view cells that allows the user to set the date in a modal view. There is a date picker in the modal view. The item is passed to that modal view controller.
The date is set when the user taps the Done button in the modal view. The date is set with this line of code:
self.item.scheduled = self.datePicker.date;
Apparently this line of code causes the UI to be blocked for ~1 second (on a 5th generation iPod touch), which is undesired behavior. I used Instruments and discovered that -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] took over 900.0ms.
Can someone please enlighten me as to what is causing the slowness? I am using just one MOC at the moment. Am I supposed to use another to make the change?
Edit: The method that took the longest time I got from Instruments tells me that the table view controller seems to have tried to re-fetch or update the cell, causing the slowness. I have -com.apple.CoreData.SQLDebug 1 passed on launch though, but no message was shown when the date was set.
This is the call tree I got from Instruments.
CoreDataTableViewController is taken from a book about Core Data that I read. It is mostly the same as the one found here.
I finally found the answer. It turns out Auto Layout is extremely slow when offscreen. This is why it can be seen in the call tree that the layout operation took the majority of time.
The solution I chose was to remove the table view controller as the NSFetchedResultsController's delegate in viewWillDisappear:. Then, in viewWillAppear:, I perform a re-fetch and call reloadData on the table view, and set the NSFetchedResultsController's delegate property back to self (which is the table view controller).
EDIT: As amb mentioned in the comments, the solution above is a bad approach. This is the better approach. I should add that my table view only correctly reloaded when I added
if(self.tableView.window == nil)
return;
also to controllerWillChangeContent:.
I have a UITableViewController that comes on to the screen in a popup. Basically it slides in from the left and shows the hierarchy available.
When it comes on screen, I select an item within it to represent the current location. Before today, this all worked.
Today I added a UITextView as a header to the table. Since then, my selection is acting strangely. When the UITableViewController appears, I can see my selected row get selected briefly, but it immediately becomes unselected. Calls to indexPathForSelectedRow return nil.
Is there a way to be alerted whenever the selection changes in UITableView? I know to use tableView:didSelectRowAtIndexPath: to keep track of when the user selects an item, but this problem is happening without user input. I'm assuming I've done something incorrect within the code, but I'm trying to track it down without posting all my code here.
Edit
Apropos of nothing, I did find that the problem goes away if I remove the Navigation Controller that I had added to the UITableViewController. This was because I had not set the property clearsSelectionOnViewWillAppear to NO. By adding the Navigation Controller, the UITableViewController was getting loaded differently, causing the property to actually be used.
However, I still would like to know how to be alerted to table view selection changes.
I have an app that has a containerView that changes its view based on the clicking of one of three different tabs. Each tab contains different pieces of contract data.
It's now come the time for me to get ALL of the data from those tabs but I'm not sure the best method. Delegation is 1:1 and therefore I don't think would work as I can't be sure that each tab has been loaded. Same goes for the NotificationCenter as each has to register as an observer.
I've considered iterating through each and passing the message "view", this will verify each has been loaded, then firing off a Notification or while inside of each view calling a method to get me the data I need so that I'll end up with one large dictionary of values.
Any other ideas or commentary on my possible solution?
Let me know if more details are needed, this was a poor design from the start but I was required to implement it like this as the clients had approved the design BEFORE I started at this company and it took them several weeks to approve anything.
I've solved the issue of every subchild not being visible by calling [subviewName view] to assure that viewDidLoad was fired. Inside viewDidLoad I register for the notification, now I've assured that each view can create a dictionary and pass back it's information to the parent.