UiActionSheet bug in iOS - ios

i wanted to change buttons color in action sheet so i wrote this code
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet {
for (UIView *_currentView in actionSheet.subviews) {
if ([_currentView isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)_currentView;
button.titleLabel.textColor = [UIColor darkGrayColor];
NSLog(#"%#",#"ahmed");
}
}
}
but nothing happen although i made delegate to self and called UIActionSheetDelegate .
although i have 6 buttons ,i see as this function wasn't be called at all
what is the problem?????

Related

How to set UIActionSheet button color

I've been searching the internet and trying different thing but cannot seem to change the button title colour on my action sheet.
Here is the action sheet code.
- (void)showActionSheet
{
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Select Country"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (NSString *listCountry in resultSet) [actionSheet addButtonWithTitle:listCountry];
[actionSheet showInView:[self.view window]];
}
I've tried this delegate but it does not work.
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{
for (UIView *subview in actionSheet.subviews) {
if ([subview isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)subview;
button.titleLabel.textColor = [UIColor greenColor];
}
}
}
Make sure you set, UIActionSheet delegate and set breakpoint on this method,
willPresentActionSheet,
check whether this method getting called .
If you have set delegate means, try this one
- (void) changeTextColorForUIActionSheet:(UIActionSheet*)actionSheet {
UIColor *tintColor = [UIColor redColor];
NSArray *actionSheetButtons = actionSheet.subviews;
for (int i = 0; [actionSheetButtons count] > i; i++) {
UIView *view = (UIView*)[actionSheetButtons objectAtIndex:i];
if([view isKindOfClass:[UIButton class]]){
UIButton *btn = (UIButton*)view;
[btn setTitleColor:tintColor forState:UIControlStateNormal];
}
}
}
Update:
https://github.com/seivan/SHActionSheetBlocks
https://github.com/ianb821/IBActionSheet
You must implement UIActionSheetDelegate and then you can use willPresentActionSheet delegate method
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{
for (UIView *subview in actionSheet.subviews) {
if ([subview isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)subview;
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
}
}
}

Customising UISearchBar in iOS 7

I have a UISearchBar whose appearance I want to customise. The suggestion in this post worked before the update to iOS 7. But now I'm not sure how to do it. I mainly want to customise the Cancel button. Does anybody know how?
You need to search for the button recursively. This should be a fail-safe way to do it:
- (void)viewDidLoad
{
[super viewDidLoad];
[self convertButtonTitle:#"Cancel" toTitle:#"Annuller" inView:self.searchBar];
}
- (void)convertButtonTitle:(NSString *)from toTitle:(NSString *)to inView:(UIView *)view
{
if ([view isKindOfClass:[UIButton class]])
{
UIButton *button = (UIButton *)view;
if ([[button titleForState:UIControlStateNormal] isEqualToString:from])
{
[button setTitle:to forState:UIControlStateNormal];
}
}
for (UIView *subview in view.subviews)
{
[self convertButtonTitle:from toTitle:to inView:subview];
}
}
I've tested this on iOS 7 only, but it works and should do so for iOS 6 too.

UIActionSheet Selected background Color in iOS

In my app , i have a lot of value to choice , So i used UIActionSheet to show.
So the following pic is appear.
As you see , the selected row Color is Blue.
I want to change that color to Gray.
How can i change it?
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{
//Gets an array af all of the subviews of our actionSheet
NSArray *subviews = [actionSheet subviews];
for (UIView *v in subviews)
{
if ([v isKindOfClass:[UIButton class]])
{
UIButton *b = (UIButton*)v;
[b setBackgroundImageByColor:[UIColor gray] forState:UIControlStateHighlighted ];
}
}
}
try this code..

Clear button at uisearchbar not working at all

I created a search bar programmatically and added to my view using the codes below:
- (void)viewDidLoad
{
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(xPositionForSearchBar, yPositionForSearchBar, widthForSearchBar, heightForSearchBar)];
UIView *bg = [[searchBar subviews] objectAtIndex:0];
searchBar.delegate = self;
searchBar.placeholder = #"Search record";
for(UIView *view in searchBar.subviews){
if([view isKindOfClass:[UITextField class]]){
UITextField *tf = (UITextField *)view;
tf.delegate = self;
break;
}
}
[bg removeFromSuperview];
[self.view addSubview: searchBar];
}
The code is implemented with UISearchBarDelegate and UITextFieldDelegate.
I have tried using
- (void)searchBarCancelButtonClicked:(UISearchBar *)aSearchBar
{
NSLog(#"cancel clicked");
searchBar.text = #"";
[aSearchBar resignFirstResponder];
}
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
NSLog(#"clear");
[self performSelector:#selector(searchBarCancelButtonClicked:) withObject:searchBar afterDelay: 0.1];
return YES;
}
and yet, the text inside the searchBar is not cleared at all when i click on the "clear button" - a circle with a "X" inside.
The clear button works when I implemented it in IB. Wonder why?
Kindly advice, many thanks.
This might happen if you position your search bar out of the bounds of a parent view. Then, the touches aren't delivered to your searchBar properly. This also affects text editing controls like copy & paste.
I have checked your code it work fine on device as well as on simulator.

How to change the default text of Cancel Button which appears in the UISearchBar +iPhone

I am developing an Application where I wanted to change the text of Search String in the SearchBar. I wanted to change the text of Cancel Button Also which appears next to the SearchBar. Before entering any string in the search bar we wil get the Search String as the default string. I wanted to change the text of that string and when we click on that searchbar we get a cancel button next to searchbar and I wanted to change the text of that cancel button.
Use the appearance proxy:
id barButtonAppearanceInSearchBar = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
[barButtonAppearanceInSearchBar setBackgroundImage:grayBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[barButtonAppearanceInSearchBar setTitleTextAttributes:#{
NSFontAttributeName : [UIFont fontWithName:#"HelveticaNeue-CondensedBold" size:20],
NSForegroundColorAttributeName : [UIColor blackColor]
} forState:UIControlStateNormal];
[barButtonAppearanceInSearchBar setTitle:#"X"];
You also need to have the "searchBar setShowsCancelButton" before the procedure.
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[theSearchBar setShowsCancelButton:YES animated:NO];
for (UIView *subView in theSearchBar.subviews){
if([subView isKindOfClass:[UIButton class]]){
[(UIButton*)subView setTitle:#"Done" forState:UIControlStateNormal];
}
}
}
Note also: use UIButton to avoid problems with Apple!
Solution for iOS 7. All credits for this go to Mr. Jesper Nielsen - he wrote the code.
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
UIButton *cancelButton;
UIView *topView = theSearchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
if (cancelButton) {
[cancelButton setTitle:#"YourTitle" forState:UIControlStateNormal];
}
}
If by "Search String", you mean the placeholder, then this should do it:
[searchBar setPlaceholder:#"Whatever you want"];
As for changing the text of the cancel button, that may be a bit more difficult. Apple does not use a standard UIBarButtonItem for this, or even a non-standard UIButton. Instead they use a UINavigationButton for the cancel button in the search bar. Since this is not a documented public class, attempting to modify it could very well get your app rejected from the App Store. If you do want to risk rejection, then you could search through the subviews of searchBar:
for(UIView *view in [searchBar subviews]) {
if([view isKindOfClass:[NSClassFromString(#"UINavigationButton") class]]) {
[(UIBarItem *)view setTitle:#"Whatever you want"];
}
}
Note that the cancel button is loaded lazily, so you will have to do this modification when the search bar is activated by the user.
In iOS 7 if you are using UISearchBar just write this code in searchBarTextDidBeginEditing: method
searchBar.showsCancelButton = YES;UIView* view=searchBar.subviews[0];
for (UIView *subView in view.subviews) {
if ([subView isKindOfClass:[UIButton class]]) {
UIButton *cancelButton = (UIButton*)subView;
[cancelButton setTitle:#"إلغاء" forState:UIControlStateNormal];
}
}
I would like to fix the UIAppearance technique, as yar1vn code won't work with Xcode 5. With the following you will have code that works perfectly for both iOS 6 and iOS 7.
First, you need to understand that the cancel button is a private UINavigationButton:UIButton. Hence, it is not an UIBarButtonItem. After some inspection, it appears that UINavigationButton will respond to those UIAppearance selectors:
// inherited from UINavigationButton
#selector(setTintColor:)
#selector(setBackgroundImage:forState:style:barMetrics:)
#selector(setBackgroundImage:forState:barMetrics:)
#selector(setTitleTextAttributes:forState:)
#selector(setBackgroundVerticalPositionAdjustment:forBarMetrics:)
#selector(setTitlePositionAdjustment:forBarMetrics:)
#selector(setBackButtonBackgroundImage:forState:barMetrics:)
#selector(setBackButtonTitlePositionAdjustment:forBarMetrics:)
#selector(setBackButtonBackgroundVerticalPositionAdjustment:forBarMetrics:)
// inherited from UIButton
#selector(setTitle:forState:)
Coincidentally, those selectors match those of a UIBarButtonItem. Meaning the trick is to use two separate UIAppearance to handle the private class UINavigationButton.
/* dual appearance technique by Cœur to customize a UINavigationButton */
Class barClass = [UISearchBar self];
UIBarButtonItem<UIAppearance> *barButtonItemAppearanceInBar = [UIBarButtonItem appearanceWhenContainedIn:barClass, nil];
[barButtonItemAppearanceInBar setTintColor:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... style:... barMetrics:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setTitleTextAttributes:... forState:...];
[barButtonItemAppearanceInBar setBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setTitlePositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil];
[buttonAppearanceInBar setTitle:... forState:...];
Now, this technique works for the Cancel button, but it also works for the Back button if you change the barClass to [UINavigationBar self].
This solution work for me - iOs7 and iOs8:
#interface ... : ...
#property (strong, nonatomic) IBOutlet UISearchBar *search;
#end
and
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
NSArray *searchBarSubViews = [[self.search.subviews objectAtIndex:0] subviews];
UIButton *cancelButton;
for (UIView *subView in searchBarSubViews) {
if ([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
break;
}
}
if (cancelButton) {
[cancelButton setTitle:#"New cancel" forState:UIControlStateNormal];
}
//insert this two lines below if you have a button appearance like this "Ne...cel"
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar setShowsCancelButton:YES animated:YES];
}
On iOS 7, if you've set displaysSearchBarInNavigationBar = YES on UISearchDisplayController, replacing the cancel button title via subview recursion or the appearance proxy will not work.
Instead, use your own bar button in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"A Custom Title", nil)
style:UIBarButtonItemStyleBordered
target:self
action:#selector(cancelButtonTapped:)];
// NB: Order is important here.
// Only do this *after* setting displaysSearchBarInNavigationBar to YES
// as that's when UISearchDisplayController creates it's navigationItem
self.searchDisplayController.navigationItem.rightBarButtonItem = barItem;
}
Jeremytripp 's working Code in Swift
I couldn't find the same code in Swift so I "translated" it myself:
func searchDisplayControllerWillBeginSearch(controller: UISearchDisplayController) {
self.searchDisplayController?.searchBar.showsCancelButton = true
var cancelButton: UIButton
var topView: UIView = self.searchDisplayController?.searchBar.subviews[0] as UIView
for subView in topView.subviews {
if subView.isKindOfClass(NSClassFromString("UINavigationButton")) {
cancelButton = subView as UIButton
cancelButton.setTitle("My Custom Title", forState: UIControlState.Normal)
}
}
}
If you just want to localized the default "Cancel" title for cancel button, I prefer to change the value of CFBundleDevelopmentRegion key from en to your localized region in Info.plist file in project.
Here is my change,
<key>CFBundleDevelopmentRegion</key>
<string>zh_CN</string>
after that, the default "Cancel" title will show as Chinese "取消". This change will also affect all the default region values, for example, the pasteboard operations' action titles on UITextField/UITextView will be localized, "Select" -> "选择", "Paste" -> "粘贴"...
By the way, the Info.plist file could be localized perfectly.
Enjoy!
Instead of referencing the non-public UINavigationButton class, I did the following. I'm hoping that it will make it through App Store review!
for (id subview in searchBar.subviews) {
if ([subview respondsToSelector:#selector(setTitle:)]) {
[subview setTitle:#"Map"];
}
}
If you're still having trouble with changing the Cancel button in iOS7, this is currently working for me:
-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
self.searchDisplayController.searchBar.showsCancelButton = YES;
UIButton *cancelButton;
UIView *topView = self.searchDisplayController.searchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
if (cancelButton) {
//Set the new title of the cancel button
[cancelButton setTitle:#"Hi" forState:UIControlStateNormal];
}
}
if the SearchBar is in the navigationBar, the code will be different than the usual answer; You need to search for NavigationBar's subviews instead.
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{
UINavigationBar * navigationBar = self.navigationController.navigationBar;
for (UIView *subView in navigationBar.subviews){
if([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]){
[(UIButton*)subView setTitle:#"İptal" forState:UIControlStateNormal];
}
}}
and This work in iOS7+ , if you still can't set the title you should learn view debugging - This is how I solved this problem of mine.
This brief tutorial outlines the key points of View-Debugging very well:
http://www.raywenderlich.com/98356/view-debugging-in-xcode-6
if #available(iOS 13.0, *) {
controller.searchBar.setValue("Done", forKey:"cancelButtonText")
} else {
controller.searchBar.setValue("Done", forKey:"_cancelButtonText")
}
🤦‍♂️
Actually controller.searchBar.setValue("Done", forKey:"cancelButtonText") works for all iOS versions
Working short code in Swift 2.1 (iOS7-9 tested)
#IBOutlet weak var searchBar: UISearchBar!
func enableSearchBarCancelButton(enable: Bool, title: String? = nil) {
searchBar?.showsCancelButton = enable
if enable {
if let _cancelButton = searchBar?.valueForKey("_cancelButton"),
let cancelButton = _cancelButton as? UIButton {
cancelButton.enabled = enable //comment out if you want this button disabled when keyboard is not visible
if title != nil {
cancelButton.setTitle(title, forState: UIControlState.Normal)
}
}
}
}

Resources