Change the setHighlighted for UIButton - iphone

I am using an UIButton to show and toggle a table-cell-item from read to unread.
I used a blue image as a background to show when an item was unread, and that worked, but figured that it would be better to use the setHighlighted feature, as it saves adding an extra image to the App. The code I use is as follows:
- (void)updateReadButton{
if(article.read.boolValue){
//[readButton setBackgroundImage:nil forState:UIControlStateNormal];
[readButton setHighlighted:FALSE];
[readButton setNeedsLayout];
} else {
[readButton setHighlighted:TRUE];
[readButton setNeedsLayout];
}
}
This works fine for the initial creation of the cell. But when the item is clicked and the detail-view is shown I toggle the 'read' value to 'true' and change the setHighlighted option to false of the UIButton in the cell, but it doesn't change when coming back from the detail view. Only when the cell is scrolling off the screen and recreated is the change reflected. How can I force a redraw of the button once I navigate to the detail view?

You may be able to accomplish the highlight by simply reloading the cell in question. Peek at UITableView's - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation and use it to reload the cell after setting the highlight.

I don't think the method setHighlighted: is the correct one. Here is the documentation:
Specify YES if the control is
highlighted; otherwise NO.
By default, a control is not
highlighted. UIControl automatically
sets and clears this state
automatically when a touch enters and
exits during tracking and when there
is a touch up.

Related

UIButton and UILabel unable to be removed from view

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!

UITableView deselect selected cells after editing

I have multiple cells selected in a UITableView, but they automatically get deselected after editing. I searched a bit and I saw people saying that they called 'reloadData' which has caused the selections to be removed, but I do not call reloadData anywhere except for in 'viewDidAppear'. They get deselected even if the editing has been cancelled without changing anything (when clicking 'edit' button in the toolbar then clicking 'done' button without any editing). I'm not sure where this is happening. Or, if I could detect when the editing has been finished (when 'done' button has been clicked), I could simply reselect all the cells that had been selected, but I'm not sure how I could detect it..
How could I prevent the cells from getting deselected? Or reselect the cells after the edit?
Thanks in advance.
I presume you are trying to achieve selection and deselection on Button press, If you are trying to change the state of selection in a UITableViewCell try using the method in the button action.
-(IBAction) someAction {
if(buttonToggled){
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}else{
//Do something
}
}
for changing the backgroundColor.
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.selectedBackgroundView.backgroundColor=[UIColor blackColor];
for more information on the above please check the link.
UITableView Cell selected Color?
I would suggest the best bet is just to reselect them yourself after every press on your "done" button.
It is quite normal that cells get deselected or buttons get unpressed, since this is their normal state - exept if you write your own code to change this - like in your case.
This is how to select a row:
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
If you have multiple rows that can be selected make sure you have the settings accordingly, otherwise it might always deselect all but the most recent rows.
Nevermind. I found out that - (void)setEditing:(BOOL)editing animated:(BOOL)animated gets called whenever the 'edit' or the 'done' button has been clicked.

iOS: cancel delete event UITAbleViewDelegate

I want to know the delegate method that gets called when the user cancel the delete operation of the UITableViewCell. Now to answer the potential question that "Why do I need this?", following is the scenario:
I have a table view where the item is displayed (which is left aligned to the main view) in a UILabel and its price is displayed in a separate UILabel (which is right aligned to the main view).
Now once the user presses the red (kind of no entry) button to delete any item, the whole cell is indented to the left and half of the price is clipped because of being out of the view. This looks quite ugly and hence I hide the price label upon press of this 'pre-delete' button (which works fine). But I want to display the price tag back when the user dismiss the delete button without deleting the cell. but I am unable to find the cancelDelete kind of event for tableview cell.
Thanx :-)
Here's something that might work instead, it stops the tableview from indenting the cells while editing:
Set UITableView's shouldIndentWhileEditing property to NO.
Implement the delegate-method tableView:editingStyleForRowAtIndexPath: method:
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
Or you can do this when you create your cells:
cell.shouldIndentWhileEditing = NO;
Hopefully this works for you.

How can I detect when the user has swiped an editable UITableViewCell?

I have an editable UITableView. By default the user can swipe and the Delete button will show up. I would like to hide some elements on my UITableView cell when this occurs. How can I do this?
Oh c'mon:
tableView:willBeginEditingRowAtIndexPath:
...
Discussion
This method is called when the user swipes horizontally across a row;
as a consequence, the table view sets its editing property to YES
(thereby entering editing mode) and displays a Delete button in the
row identified by indexPath. In this "swipe to delete" mode the
table view does not display any insertion, deletion, and reordering
controls. This method gives the delegate an opportunity to adjust the
application's user interface to editing mode. When the table exits
editing mode (for example, the user taps the Delete button), the table
view calls tableView:didEndEditingRowAtIndexPath:.
Reference
And then throw some [[cell viewWithTag:<#View's tag number#>] setHidden:YES] for your own views.
Try overriding the willTransitionToState method in your custom UITableViewCell. In particular you would be interested in the UITableViewCellStateShowingDeleteConfirmationMask state.
Couldn't you modify the pertinent elements of the – tableView:willBeginEditingRowAtIndexPath: is called?
As soon as the user wants to editing something in his tableView, this method gets called
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
if(editing){
// Entered Edit mode
// Show the new tableView and reload it.
}
else {
// End of edit mode
// Bring back the tableview and again reload it.
}
[super setEditing:editing animated:animated];
}
Update your UI in tableView:willBeginEditingRowAtIndexPath: and Restore in tableView:didEndEditingRowAtIndexPath:.

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.