UIButton and UILabel unable to be removed from view - iphone

I have two UIButtons that I added to my view
[self.view addSubview:button1];
[self.view addSubview:button2];
These buttons have a selector and in the selector is a menu where the user can choose an option and this option can vary in string size for the button so I decided to remove the buttons from the view and reload them again with different string size and button size. I have am getting the information from an API call so there is where I set the buttons up to my view. I tried to do this:
[button1 removeFromSuperview];
Also tried:
[self.button1 removeFromSuperView];
Now, for the UILabel I have it inside a table view cell because the string is long and covers my detailTextLabel. I am using UITableViewCellStyleValue1 for the cells. I have tried to use NSLineBreakByWordWrapping and set the numberOfLines to 0 as well as 5 so I then decided to add the UILabel inside the table view cell so I can control how far the string goes and I can also wrap that around. Since the cell was writing over and over the label every time the cell with the table view was hidden, I decided to create the label inside the if(cell == nil) statement.Like the button, this label also gets refreshed when the buttons are pressed and a menu option is chosen so I have to remove it from the view, the same way i did the buttons. For some reason it isn't working. Anyone have any thoughts/ideas/suggestions?
I also NSLog(#"%#",[button1 superview]) after I removed it to make sure that the button was indeed (null) as well as the label, and they do show up on the terminal as null but the buttons overlap each other, in fact you can still click the old button and you can see it underneath the new button. Same goes with the label. If you need any code let me know, this problem is frustrating me so much!
Also, I am on iOS7 and for some reason my device isn't displaying the status bar. I've tried to change it inside the info.plist -> status bar style. I've tried the 3 options it has but none of them seem to work. I checked all my xib files and checked for any hidden keywords in my .m files. Thanks in advance.

Since you mentioned the button was making an API call I am guessing you may be threading that section of code. If that's the case then the reason its not working is likely because you are not allowed to update the UI in a background thread.
Try replacing:
[button1 removeFromSuperview];
with this:
[button1 performSelectorOnMainThread:#selector(removeFromSuperview) withObject:nil waitUntilDone:NO];

I deeply suggest using storyboards, they make working with the UI a lot easier! They also allow you to play with constraints to see how your UI elements react to longer text or to the screen rotating, etc...
That apple tutorial:
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/SecondiOSAppTutorial/Introduction/Introduction.html
goes through a simple app with storyboards!

Related

iPhone Multi-View Rotation Hell

This is my first post on here and I'm very new to iPhone developing, so please bear with me.
I have an app which has a few view controllers and each view controller has a few nib files that it controls and some of the nibs have more than one view. There is a toolbar throughout the app, controlled by the root view controller.
After lot's of searching, I have got rotation working on every screen, except one. I haven't got them to load in the correct orientation, but I guess that's a different question.
In my nibs that have more than one view, I can select the autosizing options only on the original main view. On the views that I have added, which I load using insertSubview, I can select the fixed margin options, but not the width and height resizing options. I am using Xcode 4.
My 1st Question, is why I am unable to select the resizing options on the additional views?
Sorry, I had to delete the images I put in here, showing what I mean, to be able to post.
Anyway, that is not my main problem, I just want to know, out of curiosity, why I can't select the resize options. I have found a way around it in the code. In the function where I load the subview, I add [viewName setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
E.g to load the view that I have named shiftStart, I use:
- (IBAction)loadShiftStart:(id)sender {
[self clearView];
[self.view insertSubview:shiftStart atIndex:0];
[shiftStart setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
Now here is my problem. I have a nib file that has 3 views, view which is the main view that loads first, rotaStart, which loads as a subview when a button on the first view is pressed and shiftStart, which loads as a subview when a button on the first view is pressed. rotaStart and shiftStart are almost identical, with a title, a text block, a Yes button and a No button. The only difference is the text in the box, and which view is loaded if you click on the Yes or No buttons.
I have all the same resize and margin options selected, in Xcode, for the title, text block and buttons and as far as I can tell, the code that loads them is identical (see code below), but shiftStart rotates correctly and rotaStart does not.
- (IBAction)loadRotaStart:(id)sender {
[self clearView];
[self.view insertSubview:rotaStart atIndex:0];
[rotaStart setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
- (IBAction)loadShiftStart:(id)sender {
[self clearView];
[self.view insertSubview:shiftStart atIndex:0];
[shiftStart setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
Can anyone tell me why rotaStart is not rotating, when the phone is changed to landscape please?
Sorry this explanation has got a bit long winded. I'm not sure how else to explain it.
Thanks
For anyone else looking at this, with a similar problem, #longball solved it for me. Somehow I had managed to add a second view over the top of the base view, complete with Labels & Buttons. Deleting the extra view fixed the problem.

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.

removeFromSuperview only removes view from last cell

I have a UITableView set up with a custom delete button which consists of a UIButton (btnDel) added as a subview to the UITableView's cells. The delete button is added as a subview when my edit button is pressed. This works well but when I try to remove the subview using:
[btnDel removeFromSuperview];
It only removes the button from the last cell and the other cells still retain the now removed button. I've tried this in many different ways and still can't figure it out. I've tried using functions such as turning the opacity of the button to 0 or setting Hidden to YES, but like the removeFromSuperview, it only effects the button in the last cell with the others staying the same.
Any help is greatly appreciated and if anymore of my code is needed let me know.
If you don't keep references you can't tell which button belongs to which cell.
You might want to subclass UITableViewCell so that your cells have a property which points to the button (assign the button to the property right after instantiating the button). You could then use this property to access (enable, disable...) the buttons later on.

Can't touch UITextField on UIScrollView

I know this has been talked about a lot. I think I've gone thru every question on this site, and still have not been able to get this working.
I'm new to developing but I have a good sense of what's going on with all of my code. I definitely don't have a lot of experience though, this is my first iPhone app.
I'm making a data entry field that is comprised of multiple UITextFields within a UIScrollView. I'll avoid explaining the other details for now, as it seems its a very basic problem. Without a scrollview, the textfields work perfectly. I can touch the textfield and the keyboard or picker view show up appropriately. When I add the textfields to a scrollview, the scrollview works, but then the text fields don't receive my touches.
Here's the key: When 'User Interaction' is ENABLED, the scrollview works but the textfield touches are NOT registered. When 'User Interaction' is DISABLED, the scrollview doesn't work, but the textfield touches ARE registered and the keyboard/picker pops up.
From the other posts I have seen people creating subclasses and overriding the touches in a separate implementation. I've seen people using custom content views (subviews?), I've seen some solutions that are now obsolete since the APIs have changed in newer versions of the SDK, and I am just completely stuck.
I will leave out my code for now, because maybe there is a solution that someone has without requiring my code. If someone needs to see my code, I will put it up. My app is being written in the 3.1.3 SDK.
If anyone has ANY information that could help, it would be so greatly appreciated.
Here is what worked for me in Xcode 4.3.3.
In the storyboard, select your scrollview. Select Attribute Inspector on the right side. Uncheck Delays Content Touches.
It sounds like you're using IB to do a lot of your UI layout. If you take a programmatic approach you could set-up the following view hierarchy which should work.
Your view controller object managing your scroll view and your text fields should have a UIScrollView object and a UIView object (in addition to any UITextField objects you need). In the loadView method of the view controller class, allocate and initalize the UIView object and add your text fields to it as subviews. At the end of the method, allocate and initalize the UIScrollView object then add the UIView to the UIScrollView as a subview.
As an example, if your UIScrollView object were called scrollView and your UIView object called mainView the following lines at the end of the view controller's loadView method would properly set up the scroll view with the main view with the text fields on it:
scrollView = [[UIScrollView alloc] initWithFrame: [[UIScreen mainScreen] bounds] ];
scrollView.backgroundColor = [UIColor whiteColor];
scrollView.contentSize = mainView.frame.size;
[scrollView addSubview: mainView];
self.view = scrollView;
You may need to enable / disable user interaction for both the scroll view and text fields as necessary.
If possible you might best using different touch mechanisms for each process (scrolling and textfield input).
Maybe you can check the time differential between touch start and end such that you can detect the difference between a drag (scroll) and a tap (text input).
Having said that if you propagate the touches up from the textfields to the scrollview you should be fine. One thing I use is:
[myObject addTarget:self action:#selector(itemTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside];
which passes the object touched so you can identify it and act accordingly.

UIButton delayed state change

I have a UIButton subview inside of a UITableViewCell.
When this button is touched, the user must hold the button for about a half second for the button's image to change to the UIControlStateHighlighted image.
This means that if the user just taps the button as is usually the case, the highlighted state is never shown.
Why does this occur and how can I fix it?
I just encountered this problem and saw that this issue hadn't been closed. After screwing around for a while I found a fix for it.
Now you can fix this by turning off delaysContentTouches or unchecking the "Delays content touches" box on the tableview.
The only negative side effect is that the user won't be able to tap down on a button and initiate a scrolling gesture. However, if the user tries to scroll starting from anywhere that doesn't itself accept touches, the behavior should be the same as before.
The problem is that your UIButton is inside a UITableView. This means that the table view has to determine whether your tap is going to be a swipe or if it's just a tap intended for the button. The table view has to delay sending a message to the UIButton until it knows that the user doesn't intend to swipe and therefore scroll the view instead of pressing the button.
If you don't need a table view, get rid of the UITableView.
Up for David Hodge's answer.
I just want to add a way to remove that "only negative side effect", already described by David: if you start scrolling inside a UIcontrol in a UIScrollView with delayContentTouches=NO, scrolling doesn't work.
SOLUTION
Subclass UIScrollView (or UITableView as the original question) and override:
-(BOOL) touchesShouldCancelInContentView:(UIView *)view {
return YES;
}
Your UIControls inside UIScrollView/UITableView will change their state immediately on tap and the scrollviews will be able to scroll even if the touch starts on some UIControl. Works like a charm.
I just change the image from within the target action method:
[sender setBackgroundImage:[UIImage imageNamed:#"highlighted-image.png"] forState:UIControlStateNormal];
It changes the background image instantly.
Edit: completely re-written following a misunderstanding of the question
One way of thinking of a UIButton is as a shorthand way of setting up an area of the screen that can respond to various instantaneous touch events the response it makes is defined by UIControl's Target-Action system for delivering messages to other objects.
UIControlEventTouchDown sounds like the one you need to respond to. It will be triggered as soon as someone touches inside your button - this is what the "Contact Info" button in SMS does.
UIButton* myButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect];
// SEt up title, frame etc
[myButton addTarget:self action:#selector(myButtonWasPressed) forControlEvents: UIControlEventTouchDown];
[myMainView addSubView:myButton];
Will send a -(void)myButtonWasPressed message to the object this code runs from (ideally you view controller). In myButtonWasPressed you can then add a new view or take any action you like. The SMS app pushes a view controller to display the contact info using a navigation controller.
If this still doesn't solve your problem, you're going to have to post some code in order to get more insight into what's going wrong.