Notification when custom NSView has been added to a NSScrollView - nsview

Following on this question (Custom NSView embedded in NSSscrollView), when my custom view is embedded in a NSScrollView using IB, I can detect this in awakeFromNib method and perform the required initialization (I have to setup some scroll notifications).
My problem is when by custom view is added to a NSScrollView from code, setting the scrollview's documentView property. In this scenario is my custom view notified in any way (some NSView method that is called and I can override) or I have to perform my initialization explicitly after my view has been added to the scroll view?

The documentView of the scroll view is a subview of this scroll view and NSView has lots of usefull methods. In the chapter "Managing the View Hierarchy":
viewDidMoveToSuperview
Informs the view that its superview has changed (possibly to nil).
viewDidMoveToWindow
Informs the view that it has been added to a new view hierarchy.
When the view is added to a superview, viewDidMoveToSuperview is called. But the view could already be inside a view (in a XIB or in code) and this superview could be added to a scroll view. viewDidMoveToWindow is called when the view has been added to or removed from a view hierarchy.

Related

UIViewController inside UIView not getting rotation delegation

I have a UIViewController's view inside my UIScrollView subclass. The problem is my UIViewController is not getting the willRotate delegate called when I rotate the device. This is probably because UIView does not have a rotation delegate implemented in it. What is the best way to solve this?
Basically the structure is I have a MainViewController in which it has a UIScrollView. Inside this UIScrollView I have a subviews, which is the view of a bunch of UIViewControllers. The issue now is, it's not getting rotation calls when I rotate. One way to deal with this is to delegate from the MainViewController to those respective UIViewController. Is there a better/elegant way to solve this?
I am adding it as a subview from my UIScrollView not my MainViewController and you can't do UIViewControllers containment from a UIView. Correct me if I am wrong
I think you're going against the MVC pattern. You can't have a controller inside a view; instead you should have a controller that mediates the communictaion between the view and the user's input. In your case you could set the scrollview as self.view of the MainViewController, and then add the viewcontrollers views as subviews.
Watch the video that I posted in my comment: https://developer.apple.com/videos/wwdc/2011/?id=102
Here is a short summary of view controller containment, which is the design you are looking for, not combining all your logic into one view controller or using delegation for something that is built into the SDK.
A view controller has a view and provides logic for that view and most likely some of it's subviews.
You might have a complex view hierarchy and complex logic for specific views in that hierarchy that warrant the view to have it's own view controller controlling it and it's subviews.
Say you have a MainViewController and it's view is a UIScrollView (or subclass). Inside that scrollview, you might have an assortment of complex views that warrant their own controller, so you have a class, SubViewController that has the subview of the scrollview as it's view.
SubViewController needs to have rotation and appearance method callbacks working correctly in order to implement your logic for the the subview and handle layout changes.
[mainViewControllerInstance addChildViewController:subViewControllerInstance];
But, wait. The subview is still not in the view hierarchy.
[mainViewControllerInstance.view addSubView:subViewControllerInstance.view];
You have successfully created a valid view controller hierarchy of two view controllers and set up the associated view hierarchy of their views.
You will now have the appropriate callbacks functioning, as MainViewController will forward them to SubViewController.
EDIT:
See the documentation for an over view of view controller containment: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

How can i forward objects to separate subviews?

I have a UIView and a ScrollView as 2 separate subviews. How can i drag a UIView(named "a") from my UIView and have the scrollView "take over" that dragged "a" UIView?
It really depends on what you exactly mean by 'take over' the UIView.
If you simply want to change the parent view, when your view is 'dropped' then remove it as a Subview of it's parent view & add the UIView as a Subview of the UIScrollview.
If the original ParentView has a property that holds the UIView, then it will still retain the instance but the view will be one level down the hierarchy.
If you want to past the entire instance of the view to UIScrollView, you'll have to subclass UIScrollView & add a property for the UIView. Then you can either create a custom setter (i.e. don't #synthesize) that will retain the instance & do the above view adding/removing
OR
Create a - (void)provideNewView:(UIView *)newView method that will assign to the local property and do the view adding/removing.

How Can I hide an info button from a subview?

I have a mainViewController and inside its nib file I added an info button, in which action is to flip between two subviews, subview A and subview B.
From mainViewController, under viewDidLoad, I'm inserting subview A. Here I notice that the info button is in front of the subview A, which is fine.
The problem comes that when pressing any buttons that are located within subview A's nib file, in which they add new subviews, the info button remains on front.
So, how can I add these later subviews on front of all parent view stacks, so the info button does not appear? or how can I hide the info button?
If I understand correctly, your mainViewController's view has two superviews: subView A and infoButton. You'd like to add subviews to subviewA that appear over the infoButton view?
The simple answer is that you can't make subviews of subviewA appear over the infoButton view. If you think of the view hierarchy as a tree, the renderer draws the views in a depth-first way. This means it draws subviewA, and all of subviewA's subviews (and so on) before it considers the infoButton view. If you want a view to appear over the infoButton view you need to add it as a sibling of infoButton after infoButton in the main view's subview list.
If you'd like to hide the infoButton, you can simply set the hidden property to YES, and then set it to NO when you want the infoButton view to reappear, of course.
Depending on what you're doing with subviewA, you might consider using a modal view controller or a navigation controller to manage the views that you add when the user interacts with subviewA.

If I have a UIViewController in a UIScrollView how can I programmatically make the UIScrollview zoomToRect?

I have a scrollview that has a page control. The scrollview contains 3 views. Each view contains a view controller. In one of my view controllers I press a button and I want the scrollview to scroll to a specific location. But Im not sure how to accomplish that since the button is not in the UIScrollview but in one of the view controllers. Could anyone point me in the right direction with this? I have spent a lot of time trying to follow the view hierarchy to see if I can send a message to the scrollview for it to scroll. Any help is appreciated.
You can:
Add a delegate in your 3 inner View
Controllers that points to the View
Controller that holds your Scroll
View.
Create a method in the View
Controller that holds the Scroll
View that will call [scrollView
zoomToRect:] when called.
Access it from your 3 inner View
Controllers using the delegate.
If you need more information about delegation. check what is Delegate in iPhone?.

Using navigation controller of superview

I've made a custom view to which I add a custom button. This custom view goes as a subview to yet another view (Kal calendar for iphone) that I push into a navigation controller. Now the button in my custom view is connected to an IBAction in which I am not able to call upon the self.navigationController to pop the current view from.
I've tried the [[sender superview] navigationController] for a hierarchy of superview calls but it doesn't work that way either.
Any ideas please?
Thanks
A view typically has no knowledge of its view controller (and consequently, to its or its superview's view controller's navigation controller) because this would introduce a tight coupling between view and view controller that is usually unwanted and unnecessary.
The easiest way to solve your problem would be to have the view controller instead of the view handle the button's action. If that doesn't work for your design, consider designing a delegate protocol for your custom view and make your view controller the custom view's delegate. The view would then call the delegate method in the button's action method. This latter method is used a lot throughout Cocoa, e.g. by UIScrollView (UIScrollViewDelegate) and UITableView (UITableViewDelegate).