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.
Related
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.
I'm trying to get the split view controller working properly but apparently there's a bug in there or I'm missing something.
First of all, I've started a blank OSX Obj-C application, and in the Storyboard I've dragged the split view controller. Next, I've linked the segues from the main window controller to the split view and added two labels.
http://i.imgur.com/dlFObaF.png
When I build the project, it shows only the second page. Not to mention strange window size in the final build.
http://i.stack.imgur.com/IqRqr.png
I've tried everything.
This occurs in both vertical and horizontal split view.
Any suggestions?
I had the same issue myself today, but it's just the split line wasn't initiated properly.
To see, this, once you run your app, move your mouse toward the edge of the window and drag it, you will now see another view emerging.
To my best knowledge, I do not know how to fix this in IB or in code. Apparently NSSplitViewController does not have a property like UISplitViewControllerAutomaticDimension. Would appreciate if someone can contribute to this.
Edited: Found an answer via another thread. Basically, try to add some constraints to the subviews inside each view and that should prevent the size of a view to be zero. In my toy example, adding margin constraints to my buttons worked out well.
I got a problem with Cocoa and its View redraw hierarchy.
I'm currently testing displaying (audio) levels in a meter style control and I'm using the MeteringView class from MatrixMixerTest example project from apple. This class is drawing the meter and only drawing the difference what got changed which looks like a very efficient class.
My project is splitted into 2 splitviews, in some are NSCollectionViews (Scrollview, Clipview) and in others are only static views. If I add the meter to those "static" views they work fine when these views call setNeedsDisplay:YES. If a meter is added to the view of a CollectionView Item it gets rendered, but loosing its drawn "old level" parts and its corners/background. I think this happens because the CollectionView item gets also called to be redrawn (which has a background image) and everything is gone. It is drawing some parts whats currently changing (the drawing works).
Is there a way to prevent the Item itself to be redrawn? Or, I dont know why it is not happening in those static views, because those views also have background images but do not draw over the meter.
Are there some tricks or whats different in a CollectionView than in a "normal" view?
EDIT: After reading about isOpaque (MeteringView isOpaque = YES) means it should not call the parent views drawRect if set to yes. Well that works for the static views, those MeteringViews do not call parents drawRect, but those in a CollectionView do however. I dont know why.
EDIT 2: I gave this topic another title, because isOpaque=YES in MeteringView is not stopping calling the parents drawRect in a CollectionView, in a normal view it is working. Are there some things to know about? I have to stop redrawing the CollectionView Item because thats the problem.
Thanks in advance guys
Benjamin
isOpaque is just hint to the system. It does not prevent other views from drawing their contents, it only means that it can sometimes skip making other views update their contents.
If your view is opaque, it should draw itself as opaque and completely fill its bounds.
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)
Although I know of a solution to this problem, I am interested if someone can explain this solution to me. I also wanted to get this out there because I could not find any mention of this problem online, and it took me several hours over several days to track down. I have an NSTableView behaving strangely regarding redraws and its selection. The problem looks like this:
Table contents fades in, instead of appearing instantly upon it's appearance on screen. When scrolling through the contents, the newly appearing rows also fade in. When you make a selection (single or multiple), and scroll it off screen, then make another selection (that should replace, not add-to first selection), the first selection does not get cleared properly. If you scroll back to it, it is still there, in addition to your new selection. This is a display-update problem, not selection problem - i.e. your new selection is valid, it is just displayed wrong.
I tracked this through the NSArrayController I was binding to, the underlying Array, sorting, all the connections, and settings, etc., but all that has nothing to do with it.
What solved the problem was:
In the View Effects (right-most) Inspector, uncheck "Core Animation Layer" for the Window's main view.
Can anyone explain what is happening here, and perhaps improve upon the solution ?
It looks like Core Animation and NSTableView aren't getting along so well. The "fading" effect is a by-product of the way core animation works. When you have core animation in one view, it is also enabled in all of that view's subviews.
I don't recommend using core animation on the Mac unless absolutely necessary, because some interface elements (NSTextView and NSTableView, for example) aren't compatible with it. iOS has much better support for table views and such using core animation, mainly because it was designed with core animation in mind.
I know that some more simple UI elements are compatible (NSTextField and NSButton, for example).
If you absolutely need core animation in the rest of the window, put all the other views in a subview of the content view, while leaving the table view directly in the content view. You can then enable Core Animation in the other view.
Commenters, feel free to add to the list of what is and isn't compatible.