I am fetching a String from Parse.com into a UILabel programmatically in my app.
The String is a phone number. So my question is, is it possible to give an action to the UILabel on click to make a Call.. or do I have to fetch the data from a Button, or better yet, is this possible?
If it is possible, how would should I go about? Does anyone have an example or tutorial I could follow?
Any help would be appreciated.
Thanks!
You question is in two part :
Perform any kind on action when a UILabel is taped
Perform a phone call action (action used in the first part)
First, to perform an action when a label is taped, you have to add a tap gesture recognizer to this label :
phoneNumberLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(phoneNumberLabelTap)];
[phoneNumberLabel addGestureRecognizer:tapGesture];
Then you have to implement your phoneNumberLabelTap method :
-(void)phoneNumberLabelTap
{
NSURL *phoneUrl = [NSURL URLWithString:[NSString stringWithFormat:#"telprompt:%#",phoneNumberLabel.text]];
if ([[UIApplication sharedApplication] canOpenURL:phoneUrl]) {
[[UIApplication sharedApplication] openURL:phoneUrl];
} else {
UIAlertView * calert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Call facility is not available!!!" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil, nil];
[calert show];
}
}
In swift 3.0
mobileLabel.isUserInteractionEnabled = true;
let tap = UITapGestureRecognizer(target: self, action:#selector(self.phoneNumberLabelTap))
tap.delegate = self
mobileLabel.addGestureRecognizer(tap)
func phoneNumberLabelTap()
{
let phoneUrl = URL(string: "telprompt:\(mobileLabel.text ?? "")")!
if(UIApplication.shared.canOpenURL(phoneUrl)) {
UIApplication.shared.openURL(phoneUrl)
}
else {
Constants.ShowAlertView(title: "Alert", message: "Cannot place call", viewController: self, isFailed: false)
}
}
Related
Hey there my app is almost ready for release but i want to add a Facebook share button. The thing is i have no idea how the communication between the scene and the viewcontroler works. i did my research but only found code in obj-c like this one
- (void)lkFaceBookShare {
NSString *serviceType = SLServiceTypeFacebook;
if (![SLComposeViewController isAvailableForServiceType:serviceType])
{
[self showUnavailableAlertForServiceType:serviceType];
}
else
{
SLComposeViewController *composeViewController = [SLComposeViewController composeViewControllerForServiceType:serviceType];
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
CGRect rect = [keyWindow bounds];
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.5f);
[self.view drawViewHierarchyInRect:rect afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[composeViewController addImage:viewImage];
NSString *initalTextString = [NSString stringWithFormat:#"Let's join together in the form of underground catch word go along with me!! Link: https://itunes.apple.com/us/app/uoi-hinh-bat-chu-gioi-duoi/id907330926?ls=1&mt=8"];
[composeViewController setInitialText:initalTextString];
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController:composeViewController animated:YES completion:nil];
}
}
- (void)showUnavailableAlertForServiceType:(NSString *)serviceType
{
NSString *serviceName = #"";
if (serviceType == SLServiceTypeFacebook)
{
serviceName = #"Facebook";
}
else if (serviceType == SLServiceTypeSinaWeibo)
{
serviceName = #"Sina Weibo";
}
else if (serviceType == SLServiceTypeTwitter)
{
serviceName = #"Twitter";
}
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Account"
message:[NSString stringWithFormat:#"Please go to the device settings and add a %# account in order to share through that service", serviceName]
delegate:nil
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alertView show];
}
my experience and knowledge is too low to port this too swift so i need some help with this D:
Thanks
This is some code I did for twitter a while ago which still works in swift. I show you how to convert it to Facebook below. Put this your viewController:
func showTweetSheet() {
let tweetSheet = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
tweetSheet.completionHandler = {
result in
switch result {
case SLComposeViewControllerResult.Cancelled:
//Add code to deal with it being cancelled
break
case SLComposeViewControllerResult.Done:
//Add code here to deal with it being completed
//Remember that dimissing the view is done for you, and sending the tweet to social media is automatic too. You could use this to give in game rewards?
break
}
}
tweetSheet.setInitialText("Test Twitter") //The default text in the tweet
tweetSheet.addImage(UIImage(named: "TestImage.png")) //Add an image if you like?
tweetSheet.addURL(NSURL(string: "http://twitter.com")) //A url which takes you into safari if tapped on
self.presentViewController(tweetSheet, animated: false, completion: {
//Optional completion statement
})
}
To convert it to Facebook, simply swap SLServiceTypeTwitter to SLServiceTypeFacebook and rename the variables for readability. If you want to call this method from the SKScene, you have to somehow alert the viewController that you want it to call a method.
My preferred way is to use NSNotificationCenter so that I post an alert from the scene and it is received by the viewController so that it fires a method. This is also incredibly easy to setup. In the scene, you need to put this line of code wherever you want to call the Facebook popup:
NSNotificationCenter.defaultCenter().postNotificationName("WhateverYouWantToCallTheNotification", object: nil)
This sends out a notification with a name. Now, in the viewController you need to subscribe to this alert by putting the following code in either viewDidLoad, viewDidAppear or something similar.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "ThisIsTheMethodName", name: "WhateverYouCalledTheAlertInTheOtherLineOfCode", object: nil)
Now the scene will communicate with the viewController and you will be able to show the Facebook sheet. Remember to replace my strings with ones relative to your project. Hope this helps - sorry it was such a long answer!
func lkFaceBookShare() {
var serviceType: String = SLServiceTypeFacebook
if !SLComposeViewController.isAvailableForServiceType(serviceType) {
self.showUnavailableAlertForServiceType(serviceType)
}
else {
var composeViewController: SLComposeViewController = SLComposeViewController.composeViewControllerForServiceType(serviceType)
var keyWindow: UIWindow = UIApplication.sharedApplication().keyWindow
var rect: CGRect = keyWindow.bounds
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0.5)
self.view!.drawViewHierarchyInRect(rect, afterScreenUpdates: true)
var viewImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
composeViewController.addImage(viewImage)
var initalTextString: String = String(format: "Let's join together in the form of underground catch word go along with me!! Link: https://itunes.apple.com/us/app/uoi-hinh-bat-chu-gioi-duoi/id907330926?ls=1&mt=8")
composeViewController.initialText = initalTextString
var vc: UIViewController = self.view.window.rootViewController
vc.presentViewController(composeViewController, animated: true, completion: { _ in })
}
}
func showUnavailableAlertForServiceType(serviceType: String) {
var serviceName: String = ""
if serviceType == SLServiceTypeFacebook {
serviceName = "Facebook"
}
else if serviceType == SLServiceTypeSinaWeibo {
serviceName = "Sina Weibo"
}
else if serviceType == SLServiceTypeTwitter {
serviceName = "Twitter"
}
var alertView: UIAlertView = UIAlertView(title: "Account", message: "Please go to the device settings and add a \(serviceName) account in order to share through that service", delegate: nil, cancelButtonTitle: "Dismiss", otherButtonTitles: "")
alertView.show()
}
Swift Conversion of Obj-C answer posted by a very helpful user...... original post
I have an IF statement that checks labels to see if a label is empty, if it is show an alert.
if ([_DOBDate.text length] == 0)
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Cannot Proceed"
message:#"Please Submit your DOB and Gender"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
}
later on in the function I have perform segue, like this :
[self performSegueWithIdentifier:#"SetUptoMain" sender:self];
True, the alert does fire when the label is blank, but it also performs the segue. This perform segue line is not in the IF statement. So I would have thought it would have ran the IF statement and stayed there till I pressed OK. OK would be staying on the same view controller.
The segue is performed, is this due to Blocks ? any advice ?
So if the USER pressed Ok from the UIAlert the VC does not move, it stays where it was so the user can enter the details required.
This is my code :
- (IBAction)SettingsSave:(id)sender {
if ([_DOBDate.text length] == 0)
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Cannot Proceed"
message:#"Please Submit your DOB and Gender"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
}
more code...
then at the end
[self performSegueWithIdentifier:#"SetUptoMain" sender:self];
}
thanks
Seems to be an if/else logic issue. Read about it.
-(IBAction)yourAction:(id)sender
{
if ([_DOBDate.text length] == 0)
{
//Show your AlertView as you did
}
else
{
//put the rest of your code, including the performSegue
}
}
UIAlertView doesn't block execution. It runs asynchronously. Therefore the code path will go into your if statement, then continue past it.
If you only want the segue to be performed after the user presses the alert view button then you need to implement UIAlertViewDelegate.
In your header file add something like this:
#interface MyController : UIViewController <UIAlertViewDelegate>
When you create the alert view do it like this:
UIAlertView *message = [[UIAlertView alloc] initWithTitle: #"Cannot Proceed"
message: #"Please Submit your DOB and Gender"
delegate: self
cancelButtonTitle: #"OK"
otherButtonTitles: nil];
[message show];
And add this method to implement the UIAlertViewDelegate.
- (void) alertView: (UIAlertView *) alertView clickedButtonAtIndex: (NSInteger) buttonIndex {
// perform segue here. You can also check what button was pressed based on the button index.
}
EXTRA INFO: I must have asked wrong, I'd like the user to click the button and be redirected to Facebook!
I need to add a visit facebook button called "facebook" as swell in the code below! Right now I just have an ok button.
Also if possible could you help me understand, how I will be able to retrieve user information - e.g I'll ask them to add there email in the textfield, when they press ok then where will I store the email and obtain it, how does that work, and what do I need to read to find out?
Try to add your buttons in otherButtonTitles
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Refresh"
message:#"Are you want to Refresh Data"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Button1",#"Button2",#"Button3",
nil];
As per Duncan's answer you can use delegate and get which button is clicked.so on specific button's tap you can redirect to facebook page using below code.
UIAlertView *info = [[UIAlertView alloc]initWithTitle:#"Yup" message:#"You've won! Like Us on Facebook too" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Facebook", nil];
info.tag = 10;
[info show];
So when the user presses the Facebook button the delegate method alertView:clickedButtonAtIndex will be called so at that time check alert.tag and then check if facebook button is tapped then show another alert.
Your Delegate Method should be
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 10)
{
switch (buttonIndex) {
case 0:
NSLog(#"Cancel");
break;
case 1:
NSLog(#"Facebook");
[self showAlertForRedirect];
break;
default:
break;
}
}
else if (alertView.tag == 20)
{
switch (buttonIndex) {
case 0:
NSLog(#"Cancel");
break;
case 1:
NSLog(#"OK");
[self RedirectNow];
break;
default:
break;
}
}
}
-(void)showAlertForRedirect
{
UIAlertView *info2 = [[UIAlertView alloc]initWithTitle:#"Note" message:#"Would you like to redirect on facebook?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
info2.tag = 20;
[info2 show];
}
-(void)RedirectNow
{
NSURL *fanPageURL = [NSURL URLWithString:#"fb://profile/yourid"];
if (![[UIApplication sharedApplication] openURL: fanPageURL])
{
NSURL *webURL = [NSURL URLWithString:#"https://www.facebook.com/yourpagename"];
[[UIApplication sharedApplication] openURL: webURL];
}
}
As the other poster said, you can add additional buttons by providing button titles in the otherButtonTitles parameter to the initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles: method.
You can set up your alert to have an input field by setting the alertViewStyle property of the button returned by the above method to UIAlertViewStylePlainTextInput
You need to pass in self (your view controller) as the delegate parameter.
Then you need to implement the method alertView:didDismissWithButtonIndex:
In that method, you will get the button index the user selected. You can use the textFieldAtIndex: method to get a pointer to the text field, and get the user-entered text.
Is there a way to achieve this menu easily with the sdk or do I have to make it manually (combining an overlay view and other view with the buttons)?
Thanks in advance!
That's UIActionSheet class from standard UIKit framework
Easy example from Apple's documentation of UIActionSheet extended a bit by me to fire call action.
Delcare in the global scope of the ViewController:
UIActionSheet * actionSheet; and UIView * yourView;
Int the viewDidLoad:
actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Delete Note"
otherButtonTitles:#"Call",#"Add a Contact",nil];
[yourView = self.view]
To fire the menu by some declared button with IBAction you will need:
-(IBAction)viewMapButton:(id) sender
{
[actionSheet showInView:yourView];
}
To take appropriate action depending on user choice declare following method and check what [actionSheet buttonTitleAtIndex:buttonIndex] was equal to:
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString * what_action = [actionSheet buttonTitleAtIndex:buttonIndex];
NSLog(#"The %# button was tapped.", what_action);
if ([what_action isEqualToString:#"Call"])
{
NSString *phoneNumber = [[NSString alloc]
initWithString:#"telprompt:1234567890"];
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:phoneNumber]];
}
}
[NOTE: Firing of call does not work on iOS Simulator]
I have an array of strings that I want to use for button titles on a UIActionSheet. Unfortunately, the otherButtonTitles: argument in the method invocation takes a variable length list of strings, not an array.
So how I can I pass these titles into the UIActionSheet? The workaround I've seen suggested is to pass nil into otherButtonTitles:, then specify the button titles individually by using addButtonWithTitle:. But this has the problem of moving the "Cancel" button to the first position on the UIActionSheet rather than the last; I want it to be the last one.
Is there a way to 1) pass an array in lieu of a variable list of strings, or alternatively 2) move the cancel button to the bottom of the UIActionSheet?
Thanks.
I got this to work (you just need to, be ok with a regular button, and just add it after :
NSArray *array = #[#"1st Button",#"2nd Button",#"3rd Button",#"4th Button"];
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Title Here"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
// ObjC Fast Enumeration
for (NSString *title in array) {
[actionSheet addButtonWithTitle:title];
}
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:#"Cancel"];
[actionSheet showInView:self.view];
One little note: [actionSheet addButtonWithTitle:] returns the index of that button, so to be safe and "clean" you can do this:
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:#"Cancel"];
Taking Jaba's and Nick's answers and extending them a little further. To incorporate a destruction button into this solution:
// Create action sheet
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
// Action Buttons
for (NSString *actionName in actionNames){
[actionSheet addButtonWithTitle: actionName];
}
// Destruction Button
if (destructiveName.length > 0){
[actionSheet setDestructiveButtonIndex:[actionSheet addButtonWithTitle: destructiveName]];
}
// Cancel Button
[actionSheet setCancelButtonIndex: [actionSheet addButtonWithTitle:#"Cancel"]];
// Present Action Sheet
[actionSheet showInView: self.view];
There is the swift version for the response :
//array with button titles
private var values = ["Value 1", "Value 2", "Value 3"]
//create action sheet
let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: nil, destructiveButtonTitle: nil)
//for each value in array
for value in values{
//add a button
actionSheet.addButtonWithTitle(value as String)
}
//display action sheet
actionSheet.showInView(self.view)
To get value selected, add delegate to your ViewController :
class MyViewController: UIViewController, UIActionSheetDelegate
And implement the method "clickedButtonAtIndex"
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
let selectedValue : String = values[buttonIndex]
}