Hi I want to open sms app with teat along url I write following code but I facing
error like:Static member 'canSendText' cannot be used on instance of type 'MFMessageComposeViewController'
var controller1 = MFMessageComposeViewController()
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.section == 0
{
if (controller1.canSendText()) {
let urlToShare = "http://www.appzoy.com"
controller1.body = "Hey I just gave an Awesome Assessment on UAssess App you can also try it. I scored , Try to beat my score \(urlToShare)"
controller1.messageComposeDelegate = self as? MFMessageComposeViewControllerDelegate
self.present(controller1, animated: true, completion: nil)
}
}
}
As mentioned into doc you should use:
if MFMessageComposeViewController.canSendText() {
print("SMS services are available")
}
Try This
//MARK:- Send Mail
//MARK:-
func sendMail(emailTitle : String , messageBody : String , toRecipents : [String]){
if (MFMailComposeViewController.canSendMail()) {
let mc: MFMailComposeViewController = MFMailComposeViewController()
let emailTitle = emailTitle //Feedback
let messageBody = messageBody //"Feature request or bug report?"
let toRecipents = toRecipents //["friend#stackoverflow.com"]
mc.mailComposeDelegate = self
mc.setSubject(emailTitle)
mc.setMessageBody(messageBody, isHTML: false)
mc.setToRecipients(toRecipents)
self.present(mc, animated: true, completion: nil)
}else{
//Show alert
}
}
The call sendMail function
let urlToShare = "http://www.appzoy.com"
self.sendMail(emailTitle: "Title of Mail", messageBody: "Hey I just gave an Awesome Assessment on UAssess App you can also try it. I scored , Try to beat my score \(urlToShare)", toRecipents: ["abc#mail.com", "def#mail.com"])
Related
I do not know how to implement the function so that notifications come one by one from the data array. Here is my function that displays only one,last notification :
func addNotificationWithTimeIntervalTrigger(title :String){
let content = UNMutableNotificationContent()
content.title = title
content.subtitle = "Subtitle"
content.body = "Body"
//content.badge = 1
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
let reguest = UNNotificationRequest(identifier: "timeInterval", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(reguest) { (error) in
}
}
Here I just pass the data from my tableView :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.row {
case 0:
UserNotificationManager.shared.addNotificationWithTimeIntervalTrigger(title:"aaa")
default: break
}
My notification :
How to make the notifications go one by one from the array?
Make sure that every scheduled notification has a different identifier , otherwise the new one will replace the old
let reguest = UNNotificationRequest(identifier: "timeInterval", content: content, trigger: trigger)
This could be achieved by using the indexPath.row to get an object from your data model. You have not shared your data model, but an array is a useful way to store your objects for situations like this.
With some changes, your custom function could look like this. You can now pass an integer index to get the correct object from your model.
func addNotificationWithTimeIntervalTrigger(title: String, index: Int) {
guard let thisObject = yourDataModelArray[index] as? YourObjectType else { return }
let content = UNMutableNotificationContent()
content.title = title // This could be taken from data model instead
content.subtitle = thisObject.subtitle
content.body = thisObject.body
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
let reguest = UNNotificationRequest(identifier: "timeInterval", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(reguest) { (error) in
if let error = error {
// Error handling
}
}
}
Then you could call it like this. No switch statement needed as it pulls data from your data model based on the indexPath.row. Note that you could also store the titles in your data model, meaning you would not have to pass this as an argument.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
UserNotificationManager.shared.addNotificationWithTimeIntervalTrigger(title:"Custom title", index: indexPath.row)
}
Try This Separate File created for local Notifications
import Foundation
import UIKit
import UserNotifications
struct NotificationHandlerStruct {
static var notifyTimer : Timer?
}
class LocalNotificationHandler: NSObject, UNUserNotificationCenterDelegate
{
static var shared = LocalNotificationHandler()
//MARK: Schedule Notification
func scheduleNotification(Title title: String, Subtitle subtitle: String, BodyMessage body: String, AlertContent contentRx:[AnyHashable:Any]) {
/// Remove Previous Displayed Notification in case if you need
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["gruveoCall"])
let content = UNMutableNotificationContent()
//adding title, subtitle, body and badge
content.title = title
content.subtitle = subtitle
content.sound = UNNotificationSound.default()
content.body = body
content.badge = 0
content.userInfo = contentRx
//getting the notification trigger
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false)
//getting the notification request
let request = UNNotificationRequest(identifier: "gruveoCall", content: content, trigger: trigger)
//adding the notification to notification center
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
/// Comment Code below if you do not want to repeat same notification again after some interval of time
if NotificationHandlerStruct.notifyTimer == nil {
NotificationHandlerStruct.notifyTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { (timer) in
self.sendNotification(NotificationContent: content)
})
}
else{
NotificationHandlerStruct.notifyTimer?.invalidate()
NotificationHandlerStruct.notifyTimer = nil
}
}
//MARK: Repeat Notification
func sendNotification(NotificationContent content: UNMutableNotificationContent) {
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["gruveoCall"])
//getting the notification trigger
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false)
//getting the notification request
let request = UNNotificationRequest(identifier: "gruveoCall", content: content, trigger: trigger)
//adding the notification to notification center
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
//MARK: Stop Timer
func stopTimer() {
if NotificationHandlerStruct.notifyTimer != nil {
NotificationHandlerStruct.notifyTimer?.invalidate()
NotificationHandlerStruct.notifyTimer = nil
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
//displaying the ios local notification when app is in foreground
completionHandler([.alert, .badge, .sound])
}
}
Usage
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
LocalNotificationHandler.shared.scheduleNotification(Title: self.providerListArray![indexPath.row], Subtitle: "My Subtitle", BodyMessage: "Some Message", AlertContent: ["aps":["data":"your Content"]])
}
I'm trying to make a pull to refresh on WKWebView. When I try to pull and refresh, I get this error:'NSInvalidArgumentException', reason: '-[GoldenVillage.AvailabilityViewController mymethodforref:]: unrecognized selector sent to instance 0x111d18e50'
How to fix it?
My code in viewDidAppear :
self.availabilityWebview = WKWebView(
frame: self.containerView.bounds,
configuration: config
)
self.view = self.availabilityWebview!
refController.bounds = CGRectMake(0, 50, refController.bounds.size.width, refController.bounds.size.height)
refController.addTarget(self, action: Selector(("mymethodforref:")), for: UIControlEvents.valueChanged)
refController.attributedTitle = NSAttributedString(string: "Pull to refresh")
availabilityWebview?.scrollView.addSubview(refController)
self.noNetwork.text! = ""
if let crew = user!["crew"] as? [String:Any], let crewID = crew["crew_id"] as? String {
let url = URL(string: "http://ec2-52-221-231-3.ap-southeast-1.compute.amazonaws.com/gv/available-schedule_3.php?id=\(crewID)")
self.availabilityWebview!.load(URLRequest(url:url!))
func mymethodforref(refresh:UIRefreshControl){
availabilityWebview?.reload()
refController.endRefreshing()
}
func webViewDidFinishLoad(_ webView: UIWebView) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
func webViewDidStartLoad(_ webView: UIWebView) {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
instead of
Selector(("mymethodforref:")
try
#selector(mymethodforref(refresh:))
Hey guys so I'm working on an application where I have imported a contacts list from my device and I am given the option to "add" the contact but it really doesn't do much when it comes to functionality. I'm not the best coder so try to hear me out. what I am trying to do is take the data/ selected table view cell and display it on another page. I "think" that this is what I should do because I have tried to display the data on another page but get an error when I move my OVERRIDE function. that makes me believe that I need to take the data, which I believe is newContact? and set that as a variable and then display it on a new page where I can create a new view controller and add the code without error.
I essentially need to figure out what my JSON data is saved as, then set that equivalent to a string if that is possible, so I can send it to my new view controller or and send it to my database with code I already have created.
I am just not sure where to enter the statements because of errors that I am getting and what the exact code would be.
Sorry for the awful description of what I am trying to perform, I have a grasp of what is needed to be done but I am a beginner.
My Master View Controller that takes the contacts from my phone and accesses them.
import UIKit
import Contacts
import ContactsUI
class MainViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var tableView: UITableView!
var store = CNContactStore()
var contacts: [CNContact] = []
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK: - User Actions
#IBAction func contactListPressed(_ sender: AnyObject) {
let contactPickerViewController = CNContactPickerViewController()
contactPickerViewController.delegate = self
present(contactPickerViewController, animated: true, completion: nil)
}
#IBAction func addContactPressed(_ sender: AnyObject) {
let newContact = CNMutableContact()
newContact.givenName = "Apps"
newContact.familyName = "Foundations"
newContact.nickname = "AF"
if let image = UIImage(named: "logo-apps-foundation.jpg"),
let data = UIImagePNGRepresentation(image){
newContact.imageData = data
}
let phone = CNLabeledValue(label: CNLabelWork, value: CNPhoneNumber(stringValue: "+441234567890"))
newContact.phoneNumbers = [phone]
let email = "" //Your Input goes here
let Email = CNLabeledValue(label:CNLabelWork, value: email as NSString)
newContact.emailAddresses = [Email]
newContact.jobTitle = "Apps Foundation"
newContact.organizationName = "Apps Foundation"
newContact.departmentName = "IT"
let facebookProfile = CNLabeledValue(label: "Facebook", value: CNSocialProfile(urlString: "https://www.facebook.com/appsfoundation", username: "AppsFoundation", userIdentifier: "appsfoundation", service: CNSocialProfileServiceFacebook))
let twitterProfile = CNLabeledValue(label: "Twitter", value: CNSocialProfile(urlString: "https://twitter.com/AppsFoundation", username: "AppsFoundation", userIdentifier: "appsfoundation", service: CNSocialProfileServiceTwitter))
newContact.socialProfiles = [facebookProfile, twitterProfile]
let skypeProfile = CNLabeledValue(label: "Skype", value: CNInstantMessageAddress(username: "AppsFoundation", service: CNInstantMessageServiceSkype))
newContact.instantMessageAddresses = [skypeProfile]
var birthday = DateComponents()
birthday.year = 1991
birthday.month = 1
birthday.day = 1
newContact.birthday = birthday
let request = CNSaveRequest()
request.add(newContact, toContainerWithIdentifier: nil)
do {
try store.execute(request)
let alert = UIAlertController(title: "Contacts iOS 9", message: "New contact has been created", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
} catch let error{
print(error)
}
}
#IBAction func textFieldValueChanged(_ sender: AnyObject) {
if let query = textField.text {
findContactsWithName(query)
}
}
//MARK: - Private Methods
func findContactsWithName(_ name: String) {
AppDelegate.sharedDelegate().checkAccessStatus({ (accessGranted) -> Void in
if accessGranted {
DispatchQueue.main.async(execute: { () -> Void in
do {
let predicate: NSPredicate = CNContact.predicateForContacts(matchingName: name)
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactViewController.descriptorForRequiredKeys()] as [Any]
self.contacts = try self.store.unifiedContacts(matching: predicate, keysToFetch:keysToFetch as! [CNKeyDescriptor])
self.tableView.reloadData()
}
catch {
print("Unable to refetch the selected contact.")
}
})
}
})
}
func updateContact(_ contactIdentifier: String) {
do {
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactPhoneNumbersKey, CNContactViewController.descriptorForRequiredKeys()] as [Any]
let contact = try store.unifiedContact(withIdentifier: contactIdentifier, keysToFetch:keysToFetch as! [CNKeyDescriptor])
let contactToUpdate = contact.mutableCopy() as! CNMutableContact
contactToUpdate.phoneNumbers = [CNLabeledValue(label: CNLabelWork, value: CNPhoneNumber(stringValue: "+440987654321"))]
let saveRequest = CNSaveRequest()
saveRequest.update(contactToUpdate)
try store.execute(saveRequest)
} catch let error{
print(error)
}
}
}
//MARK: - UITableViewDataSource
extension MainViewController: CNContactPickerDelegate {
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
let selectedContactID = contact.identifier
updateContact(selectedContactID)
}
}
//MARK: - UITableViewDataSource
extension MainViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let CellIdentifier = "MyCell"
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier)
cell!.textLabel!.text = contacts[indexPath.row].givenName + " " + contacts[indexPath.row].familyName
if let birthday = contacts[indexPath.row].birthday {
let formatter = DateFormatter()
formatter.dateStyle = DateFormatter.Style.long
formatter.timeStyle = .none
cell!.detailTextLabel?.text = formatter.string(from: ((birthday as NSDateComponents).date)!)
}
return cell!
}
}
//MARK: - UITableViewDelegate
extension MainViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let controller = CNContactViewController(for: contacts[indexPath.row])
controller.contactStore = self.store
controller.allowsEditing = false
self.navigationController?.pushViewController(controller, animated: true)
}
}
I know I need to incorporate something like this but I am not sure where or how to set the JSON data to a variable or the correct type and then incorporate code of this type
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let controller = segue.destination as! ViewControllerB
controller.selectedName = objects[indexPath.row]
}
}
}
sorry for the awful explanation. any help possible would be appreciated, I have been struggling for quite some time.
First of all, you need to have the other view controller that you are trying to pass data to. It can either be on the Interface Builder or done programmatically (I'll assume it's on the IB for now). Then you'll need to setup a segue between the Main VC and the Details VC and give it an identifier e.g. showDetail.
Next would be to determine the data that Details VC needs for it to work properly. You can have individual variables for each data item (e.g. name, age, phone, email, etc) but usually if there is a lot of info, it's best to use a data model. In your case, since you are trying to display contact info, you can simply reuse CNContact.
So you simply need a CNContact in your Details VC that you'll set before transitioning from Main VC in the prepareForSegue function. And to initiate the segue, all you have to do is call performSegue function.
Hope that at least gives you some direction
Originally I wanted to display google map directions in my app but I don't think that is possible to do. So what I'm going to do is have my app open Google Maps app when needed.
I can open Google Maps just fine however I would like to have my app segue to another screen once they have reached their destination.
Is there any way of detecting that? If not what's the best way to segue to another view controller once the user returns to my app?
Here is my code:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
if let cell = tableView.cellForRow(at: indexPath) as? LocationCell {
if(indexPath.row == 0){
cell.selectionStyle = .none
browseVillages(cell.villageBtn)
}
else{
cell.selectionStyle = .none
let googleMaps = URL(string: "comgooglemaps-x-callback://")!
if UIApplication.shared.canOpenURL(googleMaps) {
let directionsRequest = "comgooglemaps-x-callback://" +
"?daddr=\(bars[indexPath.row]["Latitude"]!),\(bars[indexPath.row]["Longitude"]!)&saddr=\(currentLocation!.coordinate.latitude),\(currentLocation!.coordinate.longitude)" +
"&x-success=MYAPP://?resume=true&x-source=AirApp"
let directionsURL = URL(string: directionsRequest)!
UIApplication.shared.open(directionsURL, options: [:], completionHandler: nil)
}
else {
let alert = UIAlertController(title: "Error", message: "MYAPP uses Google Maps to display accurate directions to \(bars[indexPath.row]["Name"]).", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: { })
}
}
}
}
Register the "comeFromMaps" UserDefaults as false at some place like application(_:didFinishLaunchingWithOptions:), then place this just before you open the maps link:
UserDefaults.standard.set(true, forKey: "comeFromMaps")
Then place this in applicationDidBecomeActive(_:) of your AppDelegate:
let comeFromMaps = UserDefaults.standard.bool(forKey: "comeFromMaps")
if comeFromMaps {
UserDefaults.standard.set(false, forKey: "comeFromMaps")
// perform the segue!
}
Also, you can use MapKit to get the directions, using the MKDirections class.
Maybe you can type the next to get the message:
let options = [UIApplicationOpenURLOptionUniversalLinksOnly : false]
UIApplication.shared.open(directionsURL as URL, options: options, completionHandler: { (success) in
print("Open url : \(success)")
})
Do actions just in completionHaldler in UIApplication.shared.open():
UIApplication.shared.open(url, completionHandler: { success in
if success{
DispatchQueue.main.async {
tableView.reloadData()
}
}
})
I am trying to add a send email button to a Sprite Kit game. I can get the email dialog to show up. But if I hit cancel, the app will crash or do nothing. If I hit send, the email will send, but the dialog stays. I cannot get the mailComposeController function to fire...please help!
Code:
import Foundation
import UIKit
import MessageUI
class MailViewController: UIViewController, MFMailComposeViewControllerDelegate {
let systemVersion = UIDevice.currentDevice().systemVersion
let devicemodel = UIDevice.currentDevice().model
let appVersion = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as! String
let appBuild = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as! String
let myrootview2 = UIApplication.sharedApplication().keyWindow?.rootViewController
let mailComposerVC = MFMailComposeViewController()
override func viewDidLoad() {
super.viewDidLoad()
}
func sendEmailButtonTapped(sender: AnyObject) {
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.view.window?.rootViewController = mailComposerVC
print("This is the rootview2: \(myrootview2)")
myrootview2!.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
func configuredMailComposeViewController() -> MFMailComposeViewController {
var msgbody: String
mailComposerVC.mailComposeDelegate = self
msgbody = "\n\nDevice: \(devicemodel)\niOS Version: \(systemVersion)\nApp Version: \(appVersion)\nApp Build Number: \(appBuild)\n"
mailComposerVC.setToRecipients(["test1#test.com"])
mailComposerVC.setSubject("test subject")
mailComposerVC.setMessageBody(msgbody, isHTML: false)
//print(mailComposerVC)
return mailComposerVC
}
func showSendMailErrorAlert() {
let sendMailErrorAlert = UIAlertView(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", delegate: self, cancelButtonTitle: "OK")
sendMailErrorAlert.show()
}
// THIS DOESN'T GET CALLED WHEN SENDING OR CANCELLING EMAIL!
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
let test1 = result.rawValue
print(test1)
print(controller)
print(self)
print(myrootview2)
}
The issue is you are making the mailVC as the root view, you have to present it on your view like given below
#IBAction func sendEmailButtonTapped(sender: AnyObject) {
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
controller.dismissViewControllerAnimated(true, completion: nil)
}