Subviews added to documentView of NSScrollView not showing up - objective-c

I have a NSView wrapped in a NSScrollView using the IB. In the initialization function of the view (class is NoteView) containing the NSScrollView, I attempt to add subviews to the NSView as follows:
// Initialize custom view with width 802 and height 130, call it initialSubview
// Set initialSubview's frame origin to (20.0, 580.0). documentView of scrollView
// is size (842.0, 740.0)
// Let innerView be the documentView of the scrollView (I have an IBOutlet attaching
// the scrollView's document view to innerView)
[innerView addSubview:initialSubview];
When I do this, nothing shows up. Likewise, trying this:
[[[scrollView] documentView] addSubview:initialSubview];
doesn't work either. However, if I added it to the contentView:
[[[scrollView] contentView] addSubview:initialSubview];
The subview shows up fine. Any ideas?
As an addendum, if I add something like an NSButton to the documentView in the IB, nothing
shows up as well.

I figured out the issue. It seems NSScrollView and Auto-layout fight themselves.
The solution is to remove whatever you're documentView is (in my case innerView)
from their superview, setTranslatesAutoresizingMaskToConstraints to no, and re-add the view.
The code looks something like this:
[innerView removeFromSuperView];
[innerView setTranslatesAutoresizingMaskIntoConstraints:NO];
[scrollView setDocumentView:innerView];
Then you have to set any constraints you'd like manually

I am pretty sure contentView is the correct place to add it. You may also need to update the content size.

Adding views to a NSScrollView from IB adds the view to the NSScrollView's contentView(NSClipView).
According to your setup you have
NoteView is clip view(contentView) of the NSScrollView.
document view of the scroll view is innerview.
inner view(documentView)'s subview which is initialSubView is added from
-initWithFrame: of contentView.
In an NSScrollView a contentView represents the 'clipped' representation of the documentView.
Having the documentView initialized in init of the contentView is why nothing happens.
Do This
Add NoteView from -awakeFromNib or similar entry point as documentView of the NSScrollView.
Add initialSubView as a subview of NoteView.

Related

Necessary to remove ScrollView from Superview before changing and re-adding?

I have a UIScrollView that of course contains information. Based on conditions I make changes to the height of the scrollview as such:
CGRect scrollFrame = self.scrollView.frame;
scrollFrame.size.height = scrollFrame.size.height + adMobBannerView.frame.size.height;
self.scrollView.frame = scrollFrame;
I then add the scrollview back:
[self.view addSubview:self.scrollView];
All of this works as it should. However, should I first be removing the scrollview from the superview before adding it again? While again what I am doing works, I am wondering if I am just layering scrollviews on top of scrollviews unnecessarily?
You don't have to add UIScrollView as subview after you change its height (if it is currently added as subview).
When you try to add view A as a subview of view B and view A has superview it would be removed from its superview so you don't have to call removeFromSuperview method yourself.
From Apple Documentation:
Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview.

Padding around NSTableView

I've a following problem. There is a subclassed NSScrollView with a view based NSTableView in it. I've added a custom background to the scrollview in the -drawRect: method of subclass, and now I would like to add some "padding" around the inner tableview like this:
example http://img.skitch.com/20120117-ktd9g5wy8u9cm37jeebjjxx61u.png
How can I implement this?
If you're targeting Mac OS 10.10 or later, you could use
[scrollView setAutomaticallyAdjustsContentInsets:NO];
[scrollView setContentInsets:NSEdgeInsetsMake(top, right, bottom, left)];
Finally, I've solved the problem. I've created an NSView (let's call it documentContentView), added my NSTableView as a subview of this documentContentView, then I've added the documentContentView to the scrollview's documentView:
NSTableView *docView = (NSTableView *)self.scrollView.documentView;
id newClipView = [[CustomClipView alloc] initWithFrame:[self.scrollView.contentView frame]];
[self.scrollView setContentView:(NSClipView *)newClipView];
[newClipView setDrawsBackground:NO];
NSView *documentContentView = [[NSView alloc] initWithFrame:docView.bounds];
docView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[documentContentView addSubview:docView];
[self.scrollView setDocumentView:documentContentView];
[self.scrollView setDrawsBackground:NO];
I've created my custom NSClipView called CustomClipView (based on this article http://www.cocoadev.com/index.pl?CenteringInsideNSScrollView) and this subclass sets the origin of the documentContentView when the window resized. I've subclassed my tableview as well, and in -reloadData method I can resize the documentContentView when the tableview change it's contents.
The left and right padding can be done inside of the row/cell itself. For the top and bottom padding I suggest to add additional rows with no content and not selectable. This is not sexy, but worked for me.
First of all, don't add backgrounds in drawRect:. Add it in your initWithFrame: if you're subclassing, or change it from the invoker.
Adding the padding is easy: Change the frame of the NSTableView so that it is smaller, and has an origin that isn't at 0,0.

Change background image of UIImage added in UInavigation Controller

I have created a UIView, added the ImageView that UIView as a subview and the add my uiview to navigation controller. here is my code for that:-
UIView* VwTopHdr=[[UIView alloc]initWithFrame:CGRectMake(0,0.3, 1024, 122)];
header_bgimageview =[[UIImageView alloc]initWithFrame:CGRectMake(0,0.3, 1024, 122)];
header_bgimageview.image=[UIImage imageNamed:#"headerBack.png"];
[VwTopHdr addSubview:header_bgimageview];
[header_bgimageview release];
[self.navigationController.view addSubview:VwTopHdr];
Now i want to change the background image of "header_bgimageview" at rune time depending on my code conditions.here i write code to change image:-
header_bgimageview.image=[UIImage imageNamed:#"Differntimage.png"];
But i am not able to change background image using above line of code. What i have to do is removing my UIView from navigation controller create again and the added on navigation controller.
Why i am not able to change image directly instead of creating and added my view again on controller.How can i change image directly?
Expecting for your favourable reply.
Try this, which will basically invalidate the view
[VwTopHdr setNeedsDisplay];
Per class reference documentation on UIView:
setNeedsDisplay
Marks the receiver’s entire bounds rectangle as needing to be redrawn.
- (void)setNeedsDisplay

Resize parent view if subview changes size

I'm new to Cocoa and I'm programming a custom InspectorView.
A parent view (InspectorView) contains several subviews (InspectorCategories).
If I uncollapse a category (subview) I have to resize/relayout my parents view?
I found out that this is not possible through autoresize masks - Is this correct?
I tried it with resizeSubviewsWithOldSize in my parents view but this gets not called while resizing the subview.
How can I achieve this behavior?
There are two parts to accomplish what I think you want:
(a) In the parent view, override the sizeThatFits: method so that it computes a new size that fits around the resized subview.
(b) In the subview, override the setFrame: method and after the frame size is changed, it calls [self.superview sizeToFit] to resize the superview, perhaps like this:
-(void)setFrame:(CGRect)newFrame
{
[super setFrame:newFrame];
[self.superview sizeToFit];
}
No, it is not possible to do through autoresizing masks. Autoresizing mask defines how the view is resized when its superview changes bounds.
The subview should let its superview know what size it needs, for example through a delegate call. The superview then should resize itself and the subview.

UIScrollView.size = view.size - allAdditionalBars.size (like TabBar or NavigationBar) programmatically

UIScrollView is set programmatically, please dont post answers with using .xib file.
My UIScrollView is situated in my model class, so i want the code to be able to be easly imported to another project eg. for iPad or with rotating screen.
I have a view:
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width;, self.view.frame.size.height;)];
And my UIScrollView. I want to set it's size to cover all screen not counting all bars that my controller class will have. But i dont know how ;)
I though about subtracting self.view.frame.size.height - self.navigationController.navigationBar.frame.height and self.tabBarController.tabBar.height if each exists.
Is there any method that automatically sets UIScrollView size..?
Thank you in advance!
In your UIViewController subclass, you don't need to worry about the size of any UINavigationController or UITabBarController chrome. Those controllers will automatically resize your controller's main view to fit the appropriate content area.
If I'm creating the UIView myself in the controller's loadView, I usually just initially size it at [[UIScreen mainScreen] applicationFrame]. If I were to add a UIScrollView as a subview that would fill up the entire area of the main view (rather than just using the UIScrollView directly as the main view), I would use self.view.bounds as its frame and be sure to set autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;.