I'm trying to display a custom UIAlertView and I'm using AHAlertView:
https://github.com/warrenm/AHAlertView
I added both AHAlertView.m and .h to my project and add the following to the viewDidLoad method:
NSString *title = #"Alert View Title";
NSString *message = #"This is a message that might prompt you to do something.";
AHAlertView *alert = [[AHAlertView alloc] initWithTitle:title message:message];
__weak AHAlertView *weakAlert = alert;
[alert setCancelButtonTitle:#"Cancel" block:^{
weakAlert.dismissalStyle = AHAlertViewDismissalStyleTumble;
}];
[alert addButtonWithTitle:#"OK" block:^{
weakAlert.dismissalStyle = AHAlertViewDismissalStyleZoomDown;
}];
[alert show];
The problem is when I'm tapping either one of the buttons, the app crashes with:
"Application windows are expected to have a root view controller at the end of application launch"
I don't know what I did wrong, I looked at the sample project and this is the way the alert is being used.
How can I implement it correctly?
Did you activate -fno-objc-arc option ? If you did, deactivate it, AHAlertView support ARC
Related
I have several view controllers that need to make Parse services calls, which is therefore handled in a class for every "Parse" related work.
Now I have a case where the parse response will (if no errors comes up obviously) instantiate the MFMessageComposeViewController with certain parameters.
The text body comes from parse, the recipients comes from the class.
My problem is : I have copy/pasted code that I can't get rid off because I don't know what to do
In my controller class, I do this :
- (void)showSMS:(NSString*)reciever { //This is the phone number
if(![MFMessageComposeViewController canSendText]) {
UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"ALERT_ERROR_Title", nil) message:NSLocalizedString(#"ALERT_ERROR_NOSMS", nil) delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[warningAlert show];
return;
}
[[ParseService sharedInstance]sendSMSOfType:SMS_TYPE_INSIST toRecipient:reciever andBlock:^(NSError *error, NSString *body) {
if (!error){
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
NSArray *recipents = [[NSArray alloc]initWithObjects:reciever, nil];
[messageController setRecipients:recipents];
[messageController setBody:body];
[self presentViewController:messageController animated:YES completion:nil];
}else{
UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:#"Error getting sms" message:#"Couldn't get the text online" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[warningAlert show];
return;
}
}];
}
and I have this exact same block of code in 3 different places, except for ONE difference, the SMS_TYPE parameter.
How should I tweak this so I don't have to create and assign the parameters in every controller, have one neat line that would look like this [??? setUpMessageControllerWithParam:recipients:body];
Pretty much the whole completion block here troubles me, but I can't really put it somewhere else because I'll have trouble presenting a view on self if self isn't a VC, same goes for delegates and alerts.
This is probably simple for most of you, I'm just OOP-retarded. Any help is much appreciated :)
There are several ways to do the this ... like creating a base view controller with this method passing the custom parameters and inheriting your other view controllers from it, or you can make a Category with this method and import this category and use wherever you need ...
Let's say that when the user presses a button a message needs to be shown and then a modal view controller is displayed.
I would write something like that :
- (void)pickImageButtonPressed:(id)button {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert"
message:#"Some alert"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[[UIApplication sharedApplication].keyWindow.rootViewController
presentModalViewController:picker animated:YES];
[picker release];
}
With this code, the modal view controller is simply not displayed !
However, if I switch the two blocks of code (show modal first, then show the alert), the view controller is displayed modally and the alert shows up above it, exactly as I want.
My question is: why the alert prevents the modal view controller from being displayed ?
Please note that I do not want to wait for alert to be dismissed before calling presentModalViewController.
Update :
I figured out that my production code was a bit more complicated than what I first put. I updated the example code and then finally found a simple example to reproduce the problem.
Note that in my production code, the popup is displayed from a place where I don't have any reference to a view controller, that's why I use [UIApplication sharedApplication].keyWindow.rootViewController instead of a direct reference to a view controller
I finally found the answer. The issue really was on this line:
[[UIApplication sharedApplication].keyWindow.rootViewController
presentModalViewController:picker animated:YES];
When an alert is displayed, [UIApplication sharedApplication].keyWindow.rootViewController is nil !. That's why the picker was never displayed. And that's why it worked when I switched the two blocks.
Now I need to find a way to get the most relevant view controller to present the picker modally...
I have an action sheet which works like this:
- (void)Method1 {
UIActionSheet *photoSourceSheet=[[UIActionSheet alloc]
initWithTitle:#"Options"
delegate:self
cancelButtonTitle:#"Exit"
destructiveButtonTitle:nil
otherButtonTitles:#"opt1",#"opt2", #"opt3", nil];
photoSourceSheet.tag=1;
photoSourceSheet.delegate=self;
[photoSourceSheet showInView:self.view];
}
- (void)Method2 {
UIActionSheet *photoSourceSheet1=[[UIActionSheet alloc]
initWithTitle:#"Select Video"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Take New Video", #"Choose Existing Video", nil];
// photoSourceSheet.delegate=self;
photoSourceSheet1.tag=2;
photoSourceSheet1.delegate=self;
[photoSourceSheet1 showInView:self.view];
}
then in my delegate i have:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex: NSInteger)buttonIndex {
if (actionSheet.tag==1) {
if (buttonindex==2) {
[self method2];
}
} else if (actionSheet.tag==2) {
// some code
}
}
My delegate method gets called for the first action sheet i.e. photoSourceSheet but not for photoSourceSheet1.
Is there something special I need to do, like manually dismissing the sheet?
My second UIActionSheet (photoSourceSheet1) appears but it crashes the app as soon as I select an option on the sheet.
It throws EXEC_BAD_ACCESS
There is nothing wrong with the above code.
EXEC_BAD_ACCESS is basically due to ill Memory Management.Sometimes you unintentionally remove the object that is being used.
Try enable Zombies it will tell you the exact problem area.
Steps: Go to Edit Scheme
Memory Management
Check the option enable Zombie Objects
I am getting a really weird error MFMailCompseViewController. The error is "error: address doesn't contain a section that points to a section in a object file". The app crashes after MFMailCompseViewController dismisses and the email actually get sent.
This is specific to MFMailComposeViewController as I have tried to present a plain view controller modally and it dismisses fine.
Here is the code I wrote to calland present mail composer:
- (void) emailImage:(UIImage *)img {
//verified that the image is being returned correctly
UIImage *img1 = [[_delegate photoBrowser:self photoAtIndex:0] underlyingImage];
MFMailComposeViewController *mfViewController = [[MFMailComposeViewController alloc] init];
mfViewController.mailComposeDelegate = self;
NSString *subject = #"Check out this photo I took - Cap That App";
[mfViewController setSubject:subject];
NSData *imgData = UIImageJPEGRepresentation(img1, 1.0);
[mfViewController addAttachmentData:imgData mimeType:#"image/jpg" fileName:#"photo.jpg"];
NSString *contactMessage = #"\n\nSent via Cap That - Available in the Apple App Store";
[mfViewController setMessageBody:contactMessage isHTML:YES];
[self presentViewController:mfViewController animated:YES completion:nil];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Status:" message:#"" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil] autorelease];
switch (result) {
case MFMailComposeResultCancelled:
alert.message = #"You chose not to send the email.";
break;
case MFMailComposeResultSaved:
alert.message = #"Your email was saved as a draft. It has not been sent yet.";
break;
case MFMailComposeResultSent:
alert.message = #"Your email has been sent!";
break;
case MFMailComposeResultFailed:
alert.message = #"There was an error sending the email. Please verify your email is working and try again.";
break;
default:
alert.message = #"You chose not to send the email.";
break;
}
[self dismissViewControllerAnimated:YES completion:^(void) {
[alert show];
}];
}
Thanks in advance for anyone's help on this.
I'm getting the same error in my app, acting on a tap gesture on a HUD. My gesture recognizer method is using a block property on the HUD to perform the needful actions, and there's where it's crashing (the code within the block never gets to run). Apparently the program cannot access that code, and since you also have a completion block that might be a clue to what's happening.
I don't see that I'm doing anything wrong in my code, and you don't seem to be doing that either, so maybe it's a bug. Are you by any chance running a developer preview of Xcode (4.4 or 4.5)?
Edit: it turns out my problem was that the code block property was being released before it got the chance to run. I think a similar thing might happend in your case, with the alert var. Can you try moving the alert init within the completion block?
Edit 2: As an alternative, try prefixing the alert init with __weak (or __unsafe_unretained if you're targetting iOS 4.3), that should do it. If you're not using ARC, use __block instead.
I'm new to Cocoa Touch and I'm just messing around trying to get a feel for the language and framework. So I'm just trying to create a simple app that takes text from a UITextField and just shows it in a UIAlertView here is the action method:
- (IBAction)showNotifAction:(id)sender {
putVal = _TextToDisplay.text;
_alertOne.title = #"Message";
_alertOne.message = putVal;
[_alertOne show];
}
For some reason it breaks on line 3 with a SIGART. Is there something I'm doing wrong? Oh, BTW, here is my AppDelegate implementation:
#interface LearnAppDelegate : NSObject <UIApplicationDelegate> {
UITextField *_TextToDisplay;
UIButton *_ShowNotif;
UIAlertView *_alertOne;
NSString *putVal;
}
You need to define your UIAlertVIew. Pointer that you are trying to use points to nothing or to garbaged memory.
Try something like the following code:
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:"My title"
message:putVal
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] autorelease];
[alert show];