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 ...
Related
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
I set up a UIWebView with a cachePolicy of NSURLRequestReloadIgnoringLocalAndRemoteCacheData, and everything was fine: when there was a connection, the UIWebView loaded, and when there wasn't, connection:didFailWithError: was called and I got my UIAlertView.
But when I change the cachePolicy to NSURLRequestReturnCacheDataElseLoad (which is the policy I actually want), in the absence of a connection, the cached page loads and then, when I click on a link...nothing happens. No connection:didFailWithError: called. No UIAlertView.
How do I fix this?
EDIT: Perhaps I have the beginning of an answer.... I can at least identify when a link in the UIWebView is clicked, using the following method:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)req navigationType: (UIWebViewNavigationType)navigationType
{
if (navigationType==UIWebViewNavigationTypeLinkClicked)
{
NSLog(#"Blah!");
}
return YES;
}
Now, instead of NSLogging "Blah!" I just need to get it to call connection:didFailWithError.
So how do I do that?
I did it!
I added this code:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)req navigationType:(UIWebViewNavigationType)navigationType
{
if (navigationType==UIWebViewNavigationTypeLinkClicked)
{
NSURL *scriptUrl = [NSURL URLWithString:#"http://www.homePageOfTheApp.com"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data == nil)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error title." message:#"Error message." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
return YES;
}
Though I might replace http://www.homePageOfTheApp.com" with http://www.google.com since, even though my host has very reliable servers, I'm going to guess that Google's are even better....
I have code setting up a UIAlertView:
-(IBAction)showMessage
{
//NSInteger *buttonIndex = NULL;
UIAlertView *message = [[UIAlertView alloc] initWithTitle:nil
message:nil
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Email",#"SMS",#"Facebook",#"Twitter", nil];
[message show];
}
and code explaining what to do once the user makes a choice:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1){
[self openMail];
}
else if (buttonIndex == 2)
//etc.
}
But what I can't figure out is how to connect the two. The obvious answer is to add a line to the first piece of code calling alertView: clickedButtonAtIndex on UIAlertView *message, but how do you assign buttonIndex? How do you tell alertView whether the user has chosen Facebook, Email, etc?
Add to the header file if you haven't already:
#interface YourClass : UIViewController <UIAlertViewDelegate>
{
}
...etc
and in your AlertView code change delegate:nil to delegate:self
For more information have a look at the Apple Docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIAlertViewDelegate_Protocol/UIAlertViewDelegate/UIAlertViewDelegate.html
From the docs:
The button indices start at 0. If this is the cancel button index, the alert view is canceling. If -1, the cancel button index is not set.
(1) You want to set delegate:self when you initialize the message. Also, in your interface declaration, do something like:
#interface myClass: UIViewController <UIAlertViewDelegate>
This way, your handler function automatically gets called when the user makes a selection.
(2) Buttons are indexed in the order you listed them.
(3) Since you have a lot of options for the user to choose from, it is better to use UIActionSheet instead of UIAlertView. Alerts are generally used for simple Yes/No-type selections.
Hope this helps!
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];
I have two UIAlertViews in same view controller and I want to use the delegate method
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger) buttonIndex
This method will get called when a button in an alert view is pressed. However both alert views will call the same method.
How can I different the two alert views?
Set the tag property to different values when you display the alert. It's just an integer and can be queried in the callback/delegate method.
Here's an example (using an ActionSheet rather than an AlertView, but the principle is exactly the same):
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Title"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Some option", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
actionSheet.tag = 10;
[actionSheet showInView:self.view];
[actionSheet release];
Then in your selector:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (actionSheet.tag) {
case 10:
// do stuff
break;
case 20:
// do other stuff
break;
}
}
Of course, you'd use constants rather than literal values, localised strings, etc, but that's the basic idea.