Updating UIAlertView Message dynamically and newline character issue - objective-c

I need to display multiple lines of text in the message of my UIAlertView. I have tried adding a '\n', but it has no effect. It still displays: "This is an examp....".
HOWEVER, if I turn my iPhone to landscape mode it displays the message as I intend it to. And then if I switch BACK to portrait mode it displays correctly there as well.
Update: After further consideration, I suspect it has something to do with the fact that I am updating the current message with a new (and much longer) string. I have already called "show" on the alert view, and am trying to update the message. Perhaps something needs to be redrawn? Like i said before, it displays correctly if I change orientations (doesn't matter which orientation I start in, i still have the same problem). i have already tried "setNeedsDisplay" and "setNeedsLayout".

Although I believe updating the alert view's text while it's being displayed is wrong, the only way I see to change it is this way
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"test" message:#"this is a message\nthis is a new line text" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:#"test button",nil];
[alert show];
//set the new message
NSString *newMessage = [NSString stringWithString:#"Test\nWith a new message with\ncustom new line string\n and a lot\n of new lines\n Yep"];
[alert setMessage:newMessage];
//get the original alert Frame
CGRect alertFrame = alert.frame;
//get the alert view Label
UILabel *alertLabel = [alert.subviews objectAtIndex:2];
//and get the original frame position
CGRect alertLabelFrame = alertLabel.frame;
//see how much space we are needing for the new message and adjust
int heightChange = [newMessage sizeWithFont:[UIFont systemFontOfSize:16] constrainedToSize:CGSizeMake(alertLabelFrame.size.width, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap].height - alertLabelFrame.size.height;
alertFrame.size.height += heightChange;
//adjust the Label height to the new height
alertLabelFrame.size.height += heightChange;
//adjust the frame and elements with an animation for smoothness
[UIView animateWithDuration:0.15 delay:0.4 options:(UIViewAnimationCurveEaseIn) animations:^{
[alert setFrame:alertFrame];
alertLabel.frame = alertLabelFrame;
//move any buttons
for (UIView *subView in alert.subviews) {
if ([subView isKindOfClass:[UIButton class]]) {
//this is a button move it
UIButton *button = (UIButton*)subView;
CGRect alertButtonFrame = button.frame;
//adjust button Y position to the new height
alertButtonFrame.origin.y += heightChange-5;
button.frame = alertButtonFrame;
}
}
} completion:nil];

For newline use the \n newline character in your text like this:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"test" message:#"this is a message\nthis is a new line text" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
Even with setMessage this works:
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setMessage:#"this is\na test"];
[alert show];
[alert release];

Use '\r' symbol. It should break line properly.

Here is some simple code to resize the messages in an alert. Note that the alert's frame needs to be large enough. You can pad the initial alert with a few newlines.
for (UILabel *l in alertView.subviews){
if ([l isKindOfClass:[UILabel class]]){
float w = l.frame.size.width;
[l setNumberOfLines:0];
[l sizeToFit];
CGRect r = l.frame;
r.size.width = w;
l.frame = r;
}
}

Create your own AlertView Category.
AlertWithBlock.h file
#import <UIKit/UIKit.h>
#interface UIAlertView (AlertWithBlock)
- (void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock;
- (void)setDelegateBlock:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegateBlock;
+ (void)alertViewWithTitle:(NSString *)title buttonTitle:(NSString *)buttonTitle message:(NSString *)message;
+ (UIAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles delegate:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))delegate;
#end

Related

textField does not show in the alertView

Here is my code:
UIAlertView *theAlert = [[UIAlertView alloc] initWithTitle:#"Alert" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
UITextField *textField = [[UITextField alloc] initWithFrame: CGRectMake(12, 45, 260, 30)];
[textField setBackgroundColor: [UIColor clearColor]];
textField.borderStyle = UITextBorderStyleRoundedRect;
[theAlert addSubview:textField];
[theAlert show];
[textField release];
[theAlert release];
There is no textFiled in alertView, only a title "Alert" and a button "OK"
I will refer you the Apple Documentation in regards to UIAlertView Class Reference. Specifically
Subclassing Notes
The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified
So what this means is you can't add subviews to an instance of UIAlertView the recent UIAlertView still has the addSubview: method is because UIAlertView is a subclass of UIView which has this method, but as of iOS7 the method addSubview: for UIAlertView no longer calls the super method on UIView it just does nothing.
So basically what you are after is not possible.
There are however alertViewStyles that you can use like UIAlertViewStylePlainTextInput which will add a single UITextField to the UIAlertView which you can then access using the method textFieldAtIndex:. However please be aware that you can't really do anything with this again because it is part of the UIAlertViews hierarchy so again it is made to be used as is.
Messing with the UIAlertView hierarchy will get your app rejected from the Apple Review process under
2.5 - Apps that use non-public APIs will be rejected
your background color is clear so It's not showing
[textField setBackgroundColor: [UIColor redColor]];.
and also show default text field
theAlert.alertViewStyle = UIAlertViewStylePlainTextInput;
//or for username and password
theAlert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
// or for password
theAlert.alertViewStyle = UIAlertViewStyleSecureTextInput;
Try this
You can use the default alertView with textfield.For that you need to set the alertViewStyle
[message setAlertViewStyle:UIAlertViewStylePlainTextInput];
Here message is object of alertView.
You can get the textfield value using the delegate method as shown below
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Login"]) {
UITextField *username = [alertView textFieldAtIndex:0];
UITextField *password = [alertView textFieldAtIndex:1];
NSLog(#"Username: %#\nPassword: %#", username.text, password.text);
}
}
Or you can set alert.alertViewStyle = UIAlertViewStylePlainTextInput;
This will add a text field for you. You can access it in the
UIAlertView delegate callback by using
UITextField *textField = [alertView textFieldAtIndex:0];
If your using ios 7 then add below code to your set of code
theAlert.alertViewStyle=UIAlertViewStylePlainTextInput;
Full code
UIAlertView *theAlert = [[UIAlertView alloc] initWithTitle:#"Alert" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
UITextField *textField = [[UITextField alloc] initWithFrame: CGRectMake(12, 45, 260, 30)];
[textField setBackgroundColor: [UIColor greenColor]];
textField.borderStyle = UITextBorderStyleRoundedRect;
theAlert.alertViewStyle=UIAlertViewStylePlainTextInput;
[theAlert show];

Code breakpoint

Hi I have a code that when I run quits and says there is a breakpoint
- (void)checkCollision{
if(CGRectIntersectsRect(penny.frame, hand.frame))
{
[randomMain invalidate];
[startButton setHidden:NO];
pos= CGPointMake(0.0, 0.0);
CGRect frame = [penny frame];
frame.origin.x=137.0f;
frame.origin.y=326.0;
[penny setFrame:frame]; (the breakpoint is here)
CGRect frame2 = [hand frame];
frame2.origin.x=137.0f;
frame2.origin.y=20.0;
[hand setFrame:frame2];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"You Lose" message:[NSString stringWithFormat:#"He got the penny!"] delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
any ideas?
i apologize for the sloppy format Im new to the website, thanks!
Sometimes a breakpoint gets out of sync with the code presented. Try going to your breakpoint window (Command + 6 or View->Navigators->Show Breakpoint Navigator.
In that navigator, you may see active breakpoints. If you can find the errant breakpoint, delete it from the list. Otherwise, your best bet is to delete all your breakpoints.

Still Dismissing Alert

I am trying to keep this UIAlertView up after the presses either of the buttons (1 & 2).
Once i click on the "+" button or the "-" button, I can see the UILabel text increment, then it closes the UIAlertView.
This is what i currently am using:
#pragma Alert View Methods
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
[self dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
#pragma count functions
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1 || buttonIndex == 2) {
return;
}
else{
[self dismissWithClickedButtonIndex:buttonIndex animated:YES];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
self.currentCountButtonCount++;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",self.countButtonCount + 1]];
}if (buttonIndex == 2) {
self.currentCountButtonCount--;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",self.countButtonCount - 1]];
}
}
- (IBAction)countClick:(id)sender {
// tallies and keeps current count number
if (!self.currentCountButtonCount)
self.currentCountButtonCount = 0;
NSString *alertMessage = [NSString stringWithFormat:#"%d", self.countButtonCount];
self.countAlert = [[UIAlertView alloc]initWithTitle:#"Count" message:alertMessage delegate:self cancelButtonTitle:#"end" otherButtonTitles:#"+",#"-", nil];
[self.countAlert show];
}
On my last question someone told me to do it custom and this is what im trying now and it still dismisses the UIAlert.
How can i keep it up while the label changes until they touch the end button?
What are you using is default button of AlertView and after click on that button it will automatically dismissed the alertview.
So you have to create your buttons programatically and add that buttons in your alertview like:
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[btn setTitle:#"+" forState:UIControlStateNormal];
[countAlert addSubview:btn ];
on this btn call your method.
So you have to create two custom button with "+" and "-". and add that buttons in AlertView.
-(void)setAlertValue:(id)sender{
switch ([sender tag]) {
case 1:
{
// currentCountButtonCount++;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",++countButtonCount]];
}
break;
case 2:
{
//currentCountButtonCount--;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",--countButtonCount]];
}
break;
default:
break;
}
}
- (IBAction)countClick:(id)sender {
// tallies and keeps current count number
if (!currentCountButtonCount)
currentCountButtonCount = 0;
NSString *alertMessage = [NSString stringWithFormat:#"%d", countButtonCount];
self.countAlert = [[UIAlertView alloc]initWithTitle:#"Count" message:alertMessage delegate:self cancelButtonTitle:#"end" otherButtonTitles:nil, nil];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(10, 50, 40, 20)];
[btn addTarget:self action:#selector(setAlertValue:) forControlEvents:UIControlEventTouchUpInside];
[btn setBackgroundColor:[UIColor greenColor]];
btn.tag = 1;
[btn setTitle:#"+" forState:UIControlStateNormal];
UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(230, 50, 40, 20)];
[btn1 addTarget:self action:#selector(setAlertValue:) forControlEvents:UIControlEventTouchUpInside];
[btn1 setBackgroundColor:[UIColor redColor]];
btn1.tag = 2;
[btn1 setTitle:#"-" forState:UIControlStateNormal];
[countAlert addSubview:btn];
[countAlert addSubview:btn1];
[self.countAlert show];
}
I don't want to rain in your parade, but if you think that an alert view is the best way to handle an increment/decrement of a variable, I would suggest you to reconsider your design.
UIAlertViews are meant for transient information and simplified decision making. A simple "Are you sure?" is the text-book example of an alert view usage.
From the user stand point, it's much more comforting being able to modify all the attributes in sliders or any other form of permanent input, and then, when sure, hit the confirm button with an alert view (or confirmation screen). Doing it in an Alert view is not only error prone, but counter-intuitive compared in the way that the rest of iOS works.
If you're having trouble on fitting another form of input in your application, please read on how to perform animations and reveal control as they are needed, hiding the input inside an UIAlertView is simply the easiest solution for you, but not the best for the user.

UIPickerView on UIActionSheet in landscape mode appears blacked out

I have an app the I update a table row through a UIActionSheet. On the sheet I present a UIPickerView. The UIPickerView works and looks great in portrait on the iphone. But when I bring it up in landscape mode, it still works, but the outline area appears black And unselected numbers are black also.
Below is a screenshot and code. Is there anything obviously wrong?
// create enough space for the UIPicker to show up above the selection button
NSString *title = #"\n\n\n\n\n\n\n\n\n\n\n\n";
if ((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) &&
(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)) {
title = #"\n\n\n\n\n\n\n\n\n";
}
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Choose", #"Click to finilize Value - Timer"), nil];
[actionSheet showInView:viewController.view];
UIDatePicker *pickerView = [[UIDatePicker alloc] init];
[pickerView setDatePickerMode: UIDatePickerModeCountDownTimer];
if (timerInterval == 0) timerInterval = 5;
[pickerView setMinuteInterval: timerInterval];
[pickerView setCountDownDuration: [timerRec.timerDuration intValue]];
pickerView.tag = 101;
if ((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) &&
(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)) {
pickerView.frame = CGRectMake(0,0, 50,50);
}
//pickerView.delegate = self;
//pickerView.dataSource = self;
//ickerView.showsSelectionIndicator = YES;
[actionSheet addSubview:pickerView];

Custom AlertView With Background

Everybody, I need to set one image on UIAlertView..
I have attached my UIAlertview with image prob..
i have used this code lines..
UIAlertView *theAlert = [[[UIAlertView alloc] initWithTitle:#"Atention"
message: #"YOUR MESSAGE HERE", nil)
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[theAlert show];
UILabel *theTitle = [theAlert valueForKey:#"_titleLabel"];
[theTitle setTextColor:[UIColor redColor]];
UILabel *theBody = [theAlert valueForKey:#"_bodyTextLabel"];
[theBody setTextColor:[UIColor blueColor]];
UIImage *theImage = [UIImage imageNamed:#"Background.png"];
theImage = [theImage stretchableImageWithLeftCapWidth:16 topCapHeight:16];
CGSize theSize = [theAlert frame].size;
UIGraphicsBeginImageContext(theSize);
[theImage drawInRect:CGRectMake(0, 0, theSize.width, theSize.height)];
theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[theAlert layer] setContents:[theImage CGImage]];
please solve this issue..
i need only image with alert..
Try this...
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlert View" message:#"hello" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Close",nil];
UIImage *alertImage = [UIImage imageNamed:#"plus.png"];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:alertImage];
backgroundImageView.frame = CGRectMake(0, 0, 282, 130);
backgroundImageView.contentMode = UIViewContentModeScaleToFill;
[alert addSubview:backgroundImageView];
[alert sendSubviewToBack:backgroundImageView];
[alert show];
[alert release];
You should consider to not use UIAlertView, but have your own AlertView see TSAlertView for an alternative implementation, that is not derived from UIAlertView.
TSAlertView is allowing you to set your own background image.
Another solution that I am not recommending could be:
You can use introspection: Loop over the UIAlertViews subviews, identify the one that holds the background image set it hidden and place your own backroundimage at an index below/over the original image view.
I found this project: Subclass UIAlertView to customize the look of an alert. It is not working for iOS 4.2+, but with my introspection idea you can make it work again:
change the -layoutSubviews of JKCustomAlert to:
- (void) layoutSubviews {
for (UIView *v in [self subviews]) {
if ([v class] == [UIImageView class]) {
[v setHidden:YES];
}
}
alertTextLabel.transform = CGAffineTransformIdentity;
[alertTextLabel sizeToFit];
CGRect textRect = alertTextLabel.frame;
textRect.origin.x = (CGRectGetWidth(self.bounds) - CGRectGetWidth(textRect)) / 2;
textRect.origin.y = (CGRectGetHeight(self.bounds) - CGRectGetHeight(textRect)) / 2;
textRect.origin.y -= 30.0;
alertTextLabel.frame = textRect;
alertTextLabel.transform = CGAffineTransformMakeRotation(- M_PI * .08);
}
I am NOT promising, that this trick will work in future versions of iOS
A solution I like to use for this is to add a UIView to the ViewController, which mimics the appearance of an alert.
The other property of a UIAlertView is that no other part of the app can be used until the alert is dismissed. This can easily be mimicked by making your UIView a subview of another UIView (with a clear background), which takes up the entire screen.
If you don't want to implement that yourself, here's a Custom Alert View class you could use: https://github.com/shivsak/CustomAlertView