Accessing ParentViewController from UITextFields inside a custom View - iphone

I have a UIScrollView to which I append multiple custom UIView's that contain UITextFields...
In each of these text fields I handle the EditingChanged event so that I do some calculations and append them to a UILabel...
Now... Outside my UIScrollView I have a TextBox who's value I need to access from the TextFields inside my custom View...
Can I scroll up the hierarchy and find that control by it's tag somehow? I've tried using ParentViewController but that's always null.
Any help appreciated

You should be able to use the .superview property to walk up the view hierarchy to the top level UIView
http://developer.apple.com/library/ios/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instp/UIView/superview

Is the TextBox outside the UIScrollView in the same UIViewController? You should be using a controller to manage the communication. Handle the EditingChanged in the lowest level that contains both text boxes. So, if they are in the same UIViewController, have it handle the EditingChanged and have a reference to the text box as well.

Or you can use UIApplicationDelegate.
Declare an instance referring to UISCrollView, and set UIScrollView to the instance.
#interface YourAppDelegate {
YourUIScrollView* yourScrollView;
}
#property (nonatomic, retain) YourUIScrollView* yourScrollView;
#end
Wherever you want to access the scrollview, you can do as below,
YouUIScrollView* yourScrollView = ((YourAppDelegate*)[[UIApplication sharedapplication] delegate]).yourScrollView;

You could go the other way and go down the hierarchy to get the value from the lower UITextField and perform the calculation outside of the UIScrollView. A way you could access the lower UITextField's is as follows:
foreach (scrollView.ViewWithTag(tagNum).SubViews.OfType<UITextField>())
{
// get the value from the textfield then perform the required calculation
}
(this of course assumes that you've given the the UIView's you're adding a Tag.

Related

Can a UIView know when it is on screen

I have a UIView with a lot of components enclosed in it and would like to update some of them if the view is removed or if its parent view controller is popped/pushed. Is it possible for a UIView to get this information
Similar to the method in UIViewController
-(void)viewWillAppear;
Would like something like
-(void)UIViewWillAppear;
Edit for some comments I saw:
I'll explain a bit more
But I have a special case where the UIView needed to add a "floating view" on top of itself (Imagine a zooming/panning/scrolling UISCrollView subclass with floater on top of itself) such that when it scrolled the floating view stayed in place relative to the superview. I tried recalculating the new origin of the "floater" inside of the -(void)layoutSubviews method but the re-placement was very choppy. In order to solve this choppyness problem, the custom UIView added the floating view (which in theory is its subview) as a subview for its superview (a bit of a tongue twister :) ).
Now arises a problem when the custom UIView is removed (or its containing view controller is pushed offscreen). How can the special UISCrollView remove the floating view from its superView.
You can override willMoveToSuperview: to find out when a view is inserted into a hierarchy and when it's removed. That's probably not what you want since the view can be part of a hierarchy and not be inserted by itself.
To find out if it's on screen use willMoveToWindow:. If the argument is non-nil the view just became part of a visible view hierarchy.
If you need to do something after the change use didMoveToWindow:.
UIView do not appear/disappear 'randomly' or when they want - your view controllers (or code) control this. So you should find out when you show them, and call code you need.
The UIView class reference has some kvo observing change.
By implementing -(void)willRemoveSubview:(UIView *)subview you could see the other way round.
UPDATE After reading the explanations:
I hope I understood correctly. I did something similiar time ago, but with a UITableView rather than a UIScrollView (but they are quite the same underneath).
It was like a popup detail view. I solved, as you already did, by adding the detail view to the UITableView superview, and then I added a close UIButton in the detail view, with a corresponding IBOutlet:
#interface CustomUIView : UIView
#property(nonatomic,weak) IBOutlet UIButtonView *closingButton;
-(void)closeDetail:(IBAction)action;
#end
and the action was just:
-(void)closeDetail:(IBAction)action {
// do your cleaning/change to the detail subviews
[self removeFromSuperview]; // <-- clsoe the detail view
}
sdsds

Using UIViewController with a UIView - (Want to use UIScrollView instead) - How to make the switch

I need to implement a scrolling window in order to accommodate all the items on the form I am creating. My current implementation is a UIViewController (that's vcAddCourse) and it has a UIView in it with my current form.
Here is what I have done to add the UIScrollView into the equation.
1) Using IB, I dragged a uiscrollview object 'into' the existing uiview object.
2) Using IB, Ctrl-dragged from file owner to the IBOutlet I created for the new uiscrollview
Here is how I init this controller.
3) I made sure that all the items on my form were now dragged to be under the UIScrollview object.
Finally, over in my .m file, in the ViewdidLoad() function, I added the following line:
theScroller.contentSize=CGSizeMake(328, 680);
No joy. I see the form but it does not scroll.
Note: this on iphone simulator.
What else must I do to swap out the UIView for the new UIScrollView?
Thanks!
To keep things like these clear, I keep the scrollView and the (larger) subview separate in the xib file (as siblings). Your form should be on a UIView, and would be larger than the scrollview. That way you can use IB to layout the form exactly as you want.
To make things work you just have to have the IBOutlets to the UIScrollView and the UIView, and add the view to the scrollview in the viewDidLoad method of your viewController:
[theScroller addSubView:formView];
I'm not exactly sure, but I don't think you have to set the contentSize manually after this, as it should automatically be made big enough to fit your view. If it's not working you might try this:
theScroller.contentSize = formView.frame.size;
Hope this helps

accessing delaycontenttouches property of uiscrollview

Since uitableview inherits from uiscrollview, would i have access to the delayContentTouches property of UIScrollView from my table view controller? I thought I could do something like the following, but it doesn't work(self is the UITableViewController):
self.view.delayContentTouches = YES;
Thanks.
If the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. This value is YES by default. You'd better tell what do you want to do?

Using one IBOutlet with different objects

I was wondering how is it possible that use ONE IBOutlet to several objects , for example I have IBOutlet UITextView *myText; then 3 UItextView on one view , so I want connect all of them with myText !
You can have one NSArray which you declare as an IBOutletCollection (instead of IBOutlet). In order to know what text field you are getting out of the array, you can set a tag on each one in IB and just pull from the array the text fields that match specific tags.
Don't think so. Each UITextView in the one view would be a separate instance of the UITextView class. The myText variable would only be able to point to one instance's memory address at a time.
I'm not sure what you're attempting to accomplish but you might be able to 'fake it' by having all the UITextViews use the controller as their delegate and setting their properties equal to each other when ever changes are detected. (i.e. Every time the controller receives a message about the text property changing it sets all the UITextView objects text properties equal to the changed UITextView's text property).
You can use 1 object and have different tags.
This is inappropriate. However, it's appropriate to hook one IBAction with multiple IBOutlets. So that when different buttons are pressed, they go to the same IBAction. And the IBAction can tell where on earth that triggering is coming from by looking at the (id)sender argument.

How to add UIScrollView to Interface builder?

I have all my controls laid out in interface builder (many labels, buttons etc). How do I put them all in a scroll view in interface builder so that I can have more space and be able to scroll up and down to reveal more controls? Do I have to do this programatically?
Open the view that has all the controls and labels, etc. (in Interface Builder). Select All. Then under the Editor menu, select Embed In, then Scroll View.
Note: in older Xcode versions, this is under the Layout menu, then Embed Objects In... (scroll view).
My preferred solution, where you don't need to hard-code the size of the contentSize:
NB: you might be able to avoid the source-code parts of this using the trick here: https://stackoverflow.com/a/11239123/153422 - although I haven't tried it yet.
The rest of this trick ... you still need to use anyway
Move all controls into a single UIView (in IB: select all, then go Layout > Embed Objects In ... > View)
Hookup that single UIView to your source code using an IBOutlet property (see below)
IN SOURCE CODE, NOT INTERFACE BUILDER (IB is broken here, it has bugs where it sets the origin of the UIScrollView incorrectly - it tries to center the view. Apple never bothered to check it for basic bugs, sigh): Move the single UIView into a UIScrollView (see code below).
Use sizeThatFits to "automatically" set the correct size.
Code (StackOverflow won't let me put code inside a numbered list. Sigh)
Header file:
/** outlet that you hook up to the view created in step 1 */
#property(nonatomic, retain) IBOutlet UIView *masterView;
Class file:
/** inside your viewDidLoad method */
[scrollview addSubview: masterView]; // step 3
scrollView.contentSize = [masterView sizeThatFits:CGSizeZero]; // step 4
...although I haven't checked this recently, IIRC it works on both 2.x and 3.x
Select all the objects you want to put into a scroll view and go to the Layout menu, choose "Embed Objects In" and choose "Scroll View".
Its easy:
First add a scrollview to your view.
Change the size of the scrollview (e.g. make it 700 pixels long).
Start putting your controls
When you want to put/edit controls in the lower (invisble) part, select the scrollview and change the Y-start position to -300.
Voila.
After editing set the Y-start position back to 0 or whatever it was.
I don't know if it's just me, but I tried to follow the instructions in each of the other answers here and none of them worked. None of the answers included everything needed, each one I guess assuming we know to do something so leaving that part out. I finally figured it out with the help of red artisan. So... I am listing here ALL the necessary steps to get this to work:
In InterfaceBuilder, add a View and then add your controls to it (or if your controls already exist in the main view, you can select all your controls and then go to Editor | Embed In | View, then drag that new View so it is all by itself outside the main view). This View can be any size you like.
In InterfaceBuilder, add a Scroll View to your main view, and size it to take up the whole main view.
Add the code listed below to your UIViewController Header and Class files.
In InterfaceBuilder, hook up the View containing your controls to 'contentView' in the File's Owner. Hook up the Scroll View to 'scrollView' in the File's Owner.
Header File:
#interface MyViewController : UIViewController
#property(nonatomic, retain) IBOutlet UIScrollView *scrollView;
#property(nonatomic, retain) IBOutlet UIView *contentView;
Class File:
#synthesize scrollView, contentView;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.scrollView addSubview:self.contentView];
self.scrollView.contentSize = self.contentView.bounds.size;
}
- (void)viewDidUnload
{
self.scrollView = nil;
self.contentView = nil;
[super viewDidUnload];
}
Although this question is very old, I will suggest a workaround I found as I had the same issue and wasn't able to find much help out there:
When in IB, if you want to place objects outside the 420 pixel, just make sure yourself of having selected Unspecified for all of Status Bar, Top Bar, and Bottom Bar for the View that contains the Scroll View with all the objects. This way, you'll be able to manually resize the screen (for the View). Then, you can follow Ximonn's advice on resizing the H value for the Scroll View, having access to all the other objects, working with them and then, undoing changes for H value and then setting the needed Bars.
Important little thing.
To scroll big subview (UIImageView for example) in UIScrollView remember, for this subview, uncheck "User Interaction Enabled" checkbox in InterfaceBuilder -> View window. Or do it programatically.
subview.userInteractionEnabled = NO;
Otherwise this subview will stack on screen without any effect.
I've been looking for this for a few days, and I finally came across this site with a solution that worked for me.
Scrolling with UIScrollView
Basically you have your main view with a UIScrollView object in it. Then another content view with all your content in it. Then you add the content view to the scroll view. And then finally set the size of the scrollview's content size to the size of the content view.
I know, this thread is a bit older... But somebody could find it on google, it's hight ranked.
I wrote this little helper Method to get the job done:
- (void)addSubview:(UIView *)theSubView toScrollView:(UIScrollView *)theScrollView
{
[theScrollView addSubview:theSubView];
theScrollView.contentSize = theSubView.bounds.size;
}
You just have to declare two IBOutlet's in the header (e.g. contentView and scrollView) and call the method like this, whereever you want to load a UIView into a UIScrollView with your sourcecode:
[self addSubview:contentView toScrollView:scrollView];
I called it in viewDidLoad
This method features iOS
The selected answer works well for Xcode 3.
However, for Xcode 4, menus have been re-arranged slightly.
To do the same in Xcode 4 select your views then use:
Editor > Embed In > Scroll View