I have an up that has 2 uiscrollviews. 1 for vertical and another for horizontal content.
In my viewwillappear function I fetch the data from an API to populate these 2 views. I also have a bool to determine if the data needs to be re-fetched based on users actions from within the app. Initially this bool is set to true (fetch data) and once the information is fetched successfully I set this to false (do not fetch). If a user performs some action that requires a re-fetch, I set the bool back to true so the next time they load the view I get the new data.
The issue I am having is that the horizontal uiscrollview has a dynamic number of pages and if I need to re-fetch (after the first time the view is loaded) all my constraints fail and I am unable to see the new data. The first time the view loads everything works perfectly, it's only if I need to re-fetch is when the issue occurs.
I have tried calling
view.layoutIfNeeded()
on the superview and on the uiscrollview but that does nothing.
Thanks!
Managed to work it out. The structure of the scroll views were slightly incorrect in that I did not put the contents inside a separate container UIView.
Related
I'm having some trouble in my current project. I am trying to replace a view by calling removeFromSuperview() on the old view and then adding the new view using addSubview().
The new view that's coming in is simply a layer-hosting NSView with the contents of the layer set to some image.
This works fine most of time, but when the image happens to be large (42MP loaded from a .arw file in my case), it takes several seconds from execution of the following replacement code to the views actually being visibly replaced.
oldView.removeFromSuperview()
view.addSubview(newView)
Any ideas as to what might be causing this are highly appreciated.
I have a scrollview and table view in one screen. Both of them contain heavy data as its a trading app. So every second I receive and update in the value and call cell update. Meanwhile if the user tries scrolling the scrollview,it doesnt respond, though the scroll delegates are called.
Any help will be appreciated. Thanks
You should try to investigate two things:
When you say you have a table view and a scroll view, I hope you are not putting your table view inside a scroll view, and increasing the content height of scroll view and table view. If you do this, you will be making multiple cells, and loading all the cells in memory. This technique doesn't go well with dequeueReusableCellWithReuseIdentifier.
Only do the UI update on main queue, calling and receiving data should not be done on main queue.
I suspect that you may be doing something wrong in point 1. How many cells would you show at one time on an iPhone/iPad screen, max 10-15 cells. If you reuse cells and have 10-15 cells in memory, your app won't go slow.
I have a UITableView with 6 rows. Each row contains a single UICollectionView. Each collection view contains a single section with 10-15 cells. One view controller is the datasource and delegate for both the table view and the collection view.
I would like to address some performance issues when scrolling the tableview. Whenever a new section comes into view, there is a small pause while the collection view is created and filled. Since I have a fixed number of cells (< 100) and they are almost static (they are initially loaded from a web API but the data will change only a couple of times a week), I would like to pre-build each of the collection view cells in advance. I would prefer the user waits an extra half-second on launch than encounters jerky scrolling.
To accomplish this, I have updated my collectionView: cellForItemAtIndexPath: to check a dictionary of cells I am maintaining. It looks for a key composited from the collection view index and the indexPath for the cell. If the key exists, the corresponding object is returned. If none is found, the cell is built and also added to the dictionary. This step effectively prevents cells from being un-loaded and recycled, at the expense of using more memory.
But on launch, I still need to run this once for each cell to pre-populate the dictionary. I iterate over each table view cell, find the collection view, and call
[self collectionView:collectionView cellForItemAtIndexPath:indexPath];
This is almost enough. The cells are being created and stored in the dictionary, and when I scroll to a new collection view, I see that they are being pulled from the dictionary and are displayed. But all of the cells, and all of their contents, are shoved up in the top-left corner at {0,0}.
Some logging tells me that at the time the cells are created, the frame of the collection view is {{0, 0}, {0, 0}}. I assume this is why none of my layout is being applied?
How can I resolve this?
(Would also be interested in any general comments on my pre-loading implementation).
I resolved this by calling [cell layoutIfNeeded] on the UITableViewCell (not the collection view). A more thorough explanation is welcomed.
I have a problem when reloading views. OSX is not as simple as IOS.
In MainMenu.xib I have an NSBox. As per Hillegrath, several views are stored in an array and when a segmented button is pressed the views are exposed. This works properly. My frustration involves revisiting these views when changes have been made that should cause them to redisplay new values through [self someAction]. Actions in two of the views alter (global)values that should propagate changes in the other views. I am using a window controller w/xib (MainMenu) to hold the box which contains the views. I also title the views in code.
The global ivar values change properly when required and the log shows that. However dependent operations do not occur when the view are revisited, ie, update view specifics.
What appears to happen is that loadView is not called when the various views are displayed, ** **. awakeFromNib and loadView operate correctly when each view is first displayed but not ever on redisplays. This implies that that the view may be hidden but viewDidUnhide has no effect.
The view changing code (from an SO MVC answer and Hillegrath) is
NSViewController *activeVC =
(NSViewController *) self.viewControllers[index];
// [_box setContentView:nil];
[_box setContentView:activeVC.view];
[_box setNeedsDisplay:YES];
From the copied code it can be seen that I have also attempted setting the active content to nil before setting a new view but, to no avail.
Any ideas, recommendations, notifications fail to work either but may not set up correctly.
Thanks
It looks like you’re confusing view loading with display. -awakeFromNib is received by a nib file object only when the nib file is loaded. Similarly, -loadView is received by the view controller only when its corresponding nib file is loaded. Since you are keeping your view controllers in an array, those view controllers do not get deallocated, hence their corresponding nib files are never unloaded whilst the array is alive. This is reasonable behaviour, but you must bear in mind that -awakeFromNib and -loadView are only executed once in this case because nib loading is executed only once.
Since it seems that you are manually populating the view in -loadView, you’ll also have to do that whenever you set that view as the box’s content view (assuming you’re not always updating the view whenever the model changes). For instance, you could have a -reloadData method in your view controller and both -loadView and your box’s content view swapping method would use -reloadData.
Alternatively, you could set your model object as the represented object of your view controller and bind the controls in the corresponding view to properties of that represented object. NSViewController exposes a representedObject property that’s convenient for bindings.
For the record, -[NSBox setContentView:] marks the box for redisplay, so you don’t need to send it -setNeedsDisplay:YES.
(and make sure _box actually points to the NSBox instance)
I have a scroll view full of objects loaded from a json file. Every 3 seconds the data is reloaded, and nothing really changes (unless a user added new data). The reloading is very fast, but the scroll view scrolls back to the top. I want it to remain in the point where it was. How can I do this?
I use this code to delete everything for reloading:
[scrollView.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
And then I repopulate the scroll view. When reloading, the frame of the scroll view vil return to the initial value, and only the addition of the objects will make it expand.
This is under the assumption that you are setting the UIScrollView's contentSize with each object received from the JSON file:
When that first object gets loaded from the JSON file again, it sets the contentSize really low, therefore scrolling to the top.
You really don't want to remove everything from the UIScrollView before adding all of the objects back though. You should instead cache the objects that are in there and only do it if there is a change. Even when there is a change I would look into maybe just appending the changes rather than removing and re-adding objects.