Add one button (as subview) to multiple UIViews - iphone

I have a UIButton and I want to add it to multiple UIViews. Later on - I want to remove it from one of the superviews. I am trying it the following way but when I pass the removeFromSuperview message to the button, it gets removed from both the views:
[viewOverlay addSubview:myButton];
[viewButtons addSubview:myButton];
Afterwards I want it to be removed from the viewOverlay only.
[myButton removeFromSuperview];
and this causes the button removed from both the views. Any idea how can I achieve this???
Obaid

when I pass the removeFromSuperview message to the button, it gets
removed from both the views
It might look that way, but myButton was removed from viewOverlay when you added it to viewButtons. From the documentation for -addSubview::
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.
The only correct solution here is to create two buttons and add one to each of viewOverlay and viewButtons. The two buttons can look the same, have the same target, and perform the same action, so they'll look like the "same" button from the user's perspective. But a view can only have one superview at a time. I mean that literally: every view has a superview pointer that points to the view that contains it, and that point can obviously only point to one object at a time.

You can't add one view to multiple views at the same time. In this case firstly added view will be removed and added for second. To achieve this you need to create one more instance or copy existed.
From here -
A parent view may contain any number of subviews but each subview has
only one superview, which is responsible for positioning its subviews
appropriately.

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

Is it possible to avoid SuperViews when hitTesting?

Basically, I want to be able to click all the Subviews in the Image below...
I want to be able to tap the Subviews of View B but View A is in the way even though View A Subviews are not blocking the views below. Is this possible? In other words I want to be able to tap through the transparent parts of a view even though its frame/bounds cover that area. View B is under View A in a ScrollView.
thanks,
austin
The solution is to subclass View A (if it's not a custom view already) and override pointInside:withEvent.
Return YES if the specified point is inside one of View A's sub-views, or NO otherwise. When pointInside:withEvent returns NO the system will continue to try other views until it finds one that claims the point is inside it, then it will call hitTest:withEvent to see which inner-view to send the touches to (the default behaviour).

Re-add a UIButton

I'm creating a simple matching game for kids for iPad. All images are drawn on buttons.
When a matching pair is found,
[matchedBtn1 removeFromSuperview];1
[matchedBtn2 removeFromSuperview];
Now, I'm creating a reset function which allows player to reset the once he/she is done.
Question is how do I re-add the UIButtons</code>?
Tried this,
[self addSubview:matchBtn1];
But the program crashes once reset button is clicked and gives this warning for every button I addSubview to
"viewController" may not respond to "-addSubview".
Many thanks in advance for your help. :)
try :
[self.view addSubview:matchBtn1];
I think you should be trying to add them to the view of the controller, not the view controller itself.
[[viewController view] addSubView:matchBtn1]; 
Also make sure you have kept a retained copy of matchBtn1 somewhere in your classes as it will have been released when you removed the subviews.
Instead of adding and removing them, create a set of transparent views over the buttons and when you want to remove them, change the color of those views so that the buttons are hidden. That way if you want to reset the screen, you just have to reset all those views to transparent. You may have to set the cover views to intercept touches too, so the user doesn't click hidden buttons.

determine if uiview is displayed

is there a possibility to determine if an uiview obj is going to be displayed. imagine: you have 2 uiviews in an uiscrollview. now you are going to switch per gesture from the first view to the second. the first view now is NOT in the viewport. now you are going to go back to the first view. and now I want to be notified that this view is in viewport, or is redisplayed. the same has to be for the second view. I have not found any callback or something like this.
You make sure your UiViewController overrides viewWillAppear: (before it appears this method is called) or viewDidAppear: (after this method is called).
See: http://developer.apple.com/iphone/library/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/viewWillAppear:
That depends what you mean by "switch". If one view is just scrolled out of the visible area of the scrollview, but still remains attached as a subview to it, then you may want to check if the bounds of your view overlap those of the scrollviews visible area.
You could do this by using UIScrollView Delegate's scrollViewDidScroll: method to implement a check for overlaps while the user is scrolling.
If however your view is actually removed from the viewstack, then you may want to subclass UIView and implement willMoveToSuperview: to check if the view has been added to the scrollview again.

How to resize other subviews and parent view when one subview size changes

I have a view which is similar to mail app. I have a scroll view and in that many other subviews. When the user clicks on any textview, it expands to show the text in it. e.g. "to" field in mail. I would want to resize the other subviews such that it starts below the expanded region. How can I do that.
I created the view through IB and I marked it for flexible top margin to facilitate this. But nothing happens automatically and hence I was wondering if I need to call sizethatFits/setneedsLayout.
When the subview resizes, call [[self superview] setNeedsLayout]. In your superview, implement -layoutSubviews to do the actual layout. You'll have to calculate everything yourself. Fixed/flexible margins are relevant to resizing the superview, not on peer views. The default -layoutSubviews does nothing at all; it just gets called at appropriate times.
If you need to force layout to happen at a particular point, then you can call -layoutIfNeeded on yourself or your superview. Read the docs on how this method works. Generally speaking you don't need to call this, though. It will usually get called at the appropriate time if you just use -setNeedsLayout.