I have a problem that I can't quite seem to solve even though I've used resources I've found on Google and on here. I've only started being taught Swift and how to use Xcode about a month ago, hence, I'm very new, and the problem I have is probably very simple to others.
What I'm trying to do is add and save a new contact to the addressbook. I can get from the app to the Contacts app no problem, it's just I can't save the new contact information.
import AddressBookUI
import AddressBook
class ViewController: UIViewController {
#IBOutlet weak var contactLink: UIButton!
#IBAction func contactLink(sender: AnyObject) {
var viewController: ABNewPersonViewController = ABNewPersonViewController()
self.presentViewController(viewController, animated: true, completion: nil)
}
}
Here's the code I'm using that relates to my problem. Any assistance will be appreciated.
Nowadays, you'd use ContactsUI framework. So, in Swift 3, you could do:
import ContactsUI
class ViewController: UIViewController, CNContactViewControllerDelegate {
#IBAction func contactLink(_ sender: AnyObject) {
let controller = CNContactViewController(forNewContact: nil)
controller.delegate = self
let navigationController = UINavigationController(rootViewController: controller)
self.present(navigationController, animated: true)
}
func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
viewController.navigationController?.dismiss(animated: true)
}
}
My original answer, using AddressBookUI framework in Swift 2 is below.
The Swift code is:
import AddressBookUI
class ViewController: UIViewController, ABNewPersonViewControllerDelegate {
#IBAction func contactLink(sender: AnyObject) {
let controller = ABNewPersonViewController()
controller.newPersonViewDelegate = self
let navigationController = UINavigationController(rootViewController: controller)
self.presentViewController(navigationController, animated: true, completion: nil)
}
func newPersonViewController(newPersonView: ABNewPersonViewController!, didCompleteWithNewPerson person: ABRecord!) {
newPersonView.navigationController?.dismissViewControllerAnimated(true, completion: nil);
}
}
See the Prompting the User to Create a New Person Record section of the Address Book Programming Guide: User Interaction: Prompting for and Displaying Data.
Related
Im trying to build a simple app to scan documents, but faced this error when trying to import VisionKit module, how can i solve this error ?
My code:
import UIKit
import VisionKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func openCameraButtonTaped(_ sender: Any) {
configureDocumentView()
}
private func configureDocumentView() {
let scaningDocumentViewController = VNDocumentCameraViewController()
scaningDocumentViewController.delegate = self
self.present(scaningDocumentViewController, animated: true, completion: nil)
}
}
extension ViewController: VNDocumentCameraViewControllerDelegate {
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
for pageNum in 0..<scan.pageCount {
let image = scan.imageOfPage(at: pageNum)
print(image)
}
controller.dismiss(animated: true, completion: nil)
}
}
You are giving a hard time for the compiler, your project name conflicts with Apple's VisionKit. Create a new your project with a different name.
Hi want want to make a refer a friend through SMS I write the following code. If user is pick on that open the SMS with text but it don't cancel again user will unable go back to app.
if indexPath.item == 1
{
//SMS
if MFMessageComposeViewController.canSendText() {
let urlToShare = self.referalmodeldata[0].referralCodeOnly
controller1.body = "Hey I just gave an Awesome Assessment on App you can also try it. I scored , Try to beat my score \(String(describing: urlToShare))"
controller1.messageComposeDelegate = self as? MFMessageComposeViewControllerDelegate
self.present(controller1, animated: true, completion: nil)
}
}
You haven't implemented MFMessageComposeViewControllerDelegate correctly in your code.
First of all you need to confirm MFMessageComposeViewControllerDelegate with your UIViewController as shown below:
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
Next thing is you need add it's delegate method as shown below:
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
self.dismiss(animated: true, completion: nil)
}
Then you need to replace
controller1.messageComposeDelegate = self as? MFMessageComposeViewControllerDelegate
with
controller1.messageComposeDelegate = self
Demo code will be:
import UIKit
import MessageUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
#IBAction func sendText(_ sender: Any) {
if (MFMessageComposeViewController.canSendText()) {
let controller = MFMessageComposeViewController()
controller.body = "Message Body"
controller.messageComposeDelegate = self
self.present(controller, animated: true, completion: nil)
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
self.dismiss(animated: true, completion: nil)
}
}
I'm trying to prompt the user to create a new contact and pass in information. (specifically a phone and email)
I've found numerous examples of using a CNMutableContact and adding an email to it. However, any of the code involving the CNContact gives me a "Use of undeclared type" error.
How can I setup my class to prompt the user to save the contact?
import ContactsUI
//add CNContactViewControllerDelegate to your ViewController
class ViewController: UIViewController , CNContactViewControllerDelegate {
func addPhoneNumber(phNo : String) {
if #available(iOS 9.0, *) {
let store = CNContactStore()
let contact = CNMutableContact()
let homePhone = CNLabeledValue(label: CNLabelHome, value: CNPhoneNumber(stringValue :phNo ))
contact.phoneNumbers = [homePhone]
let controller = CNContactViewController(forUnknownContact : contact)
controller.contactStore = store
controller.delegate = self
self.navigationController?.setNavigationBarHidden(false, animated: true)
self.navigationController!.pushViewController(controller, animated: true)
}
}
You Can Do Something Like This.
extension ViewController: CNContactViewControllerDelegate {
func showNewContactViewController() {
let contactViewController: CNContactViewController = CNContactViewController(forNewContact: nil)
contactViewController.contactStore = CNContactStore()
contactViewController.delegate = self
let navigationController: UINavigationController = UINavigationController(rootViewController: contactViewController)
present(navigationController, animated: false) {
print("Present")
}
}
}
Swift 4
import ContactsUI
implement delegate CNContactViewControllerDelegate
#IBAction func UserTap_Handler(_ sender: Any) {
self.navigationController?.isNavigationBarHidden = false
let con = CNContact()
let vc = CNContactViewController(forNewContact: con)
vc.delegate = self
_ = self.navigationController?.pushViewController(vc, animated: true)
}
//MARK:- contacts delegates
func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
print("dismiss contact")
self.navigationController?.popViewController(animated: true)
}
func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool {
return true
}
I am implementing a seemingly trivial and very popular use case where users select a contact, and send them a precomposed SMS.
However, the SMS ViewController dismisses itself automatically. This is easily reproducible.
How do I fix this?
Here's my code:
import UIKit
import MessageUI
import ContactsUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate, CNContactPickerDelegate{
let contactPickerViewController = CNContactPickerViewController()
let messageVC = MFMessageComposeViewController()
override func viewDidLoad() {
super.viewDidLoad()
contactPickerViewController.delegate = self
messageVC.messageComposeDelegate = self
}
func contactPicker(picker: CNContactPickerViewController, didSelectContact contact: CNContact) {
if let phoneNumberValue = contact.phoneNumbers.first?.value as? CNPhoneNumber {
if let phoneNumber = phoneNumberValue.valueForKey("digits") as? String {
// Configure message ViewController
messageVC.recipients = [phoneNumber]
messageVC.body = "Yoyoyo"
picker.presentViewController(messageVC, animated: true, completion: nil)
}
}
}
func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func invite(sender: AnyObject) {
self.presentViewController(self.contactPickerViewController, animated: true, completion: nil)
}
}
The problem is that you are asking your picker to present the message view controller. When contactPicker:picker:didSelectContact: method is called, the picker view controller is automatically being dismissed by the system. This means that the view controller is going away and you are trying to use that view controller to present your next view controller.
What you need to do is have "ViewController" in this case present the message view controller. Below is an example of the portion of your code i changed. You'll notice i have a timer there. This is because if you try to present the messageVC right away, nothing will happen because the contacts view controller isn't done dismissing itself yet.
func contactPicker(picker: CNContactPickerViewController, didSelectContact contact: CNContact) {
if let phoneNumberValue = contact.phoneNumbers.first?.value as? CNPhoneNumber {
if let phoneNumber = phoneNumberValue.valueForKey("digits") as? String {
// Configure message ViewController
messageVC.recipients = [phoneNumber]
messageVC.body = "Yoyoyo"
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.presentViewController(self.messageVC, animated: true, completion: nil)
})
}
}
}
I have two View Controllers: "DiscoverViewController" and "LocationRequestModalViewController".
The first time a user opens the "DiscoverViewController", I overlay "LocationRequestModalViewController" which contains a little blurb about accessing the users location data and how it can help them.
On the "LocationRequestModalViewController" there are two buttons: "No thanks" and "Use location". I need to send the response from the user back to the "DiscoverViewController"
I have done some research and found that delegates/protocols are the best way to do it, so I followed a guide to get that working, but I'm left with 2 errors and can't figure them out.
The errors are:
On DiscoverViewController
'DiscoverViewController' is not convertible to 'LocationRequestModalViewController'
On LocationRequestModalViewController
'LocationRequestModalViewController' does not have a member name 'sendBackUserLocationDataChoice'
I've marked where the errors are happen in the following files:
DiscoverViewController.swift
class DiscoverViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, LocationRequestModalViewControllerDelegate {
func showLocationRequestModal() {
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var locationRequestVC: AnyObject! = storyboard.instantiateViewControllerWithIdentifier("locationRequestVC")
self.presentingViewController?.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
self.tabBarController?.presentViewController(locationRequestVC as UIViewController, animated: true, completion: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let vc = segue.destinationViewController as LocationRequestModalViewController
vc.delegate = self //This is where error 1 happens
}
func sendBackUserLocationDataChoice(controller: LocationRequestModalViewController, useData: Bool) {
var enableData = useData
controller.navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
showLocationRequestModal()
}
}
LocationRequestModalViewController
protocol LocationRequestModalViewControllerDelegate {
func sendBackUserLocationDataChoice(controller:LocationRequestModalViewController,useData:Bool)
}
class LocationRequestModalViewController: UIViewController {
var delegate:LocationRequestModalViewController? = nil
#IBAction func dontUseLocationData(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func useLocationData(sender: AnyObject) {
delegate?.sendBackUserLocationDataChoice(self, useData: true) // This is where error #2 happens
}
override func viewDidLoad() {
super.viewDidLoad()
//Modal appearance stuff here...
}
}
The answer is in your question itself. Both errors tells the exact reason.
Issue 1
let vc = segue.destinationViewController as LocationRequestModalViewController
vc.delegate = self //This is where error 1 happens
The self is of type DiscoverViewController
But you declared the delegate as:
var delegate:LocationRequestModalViewController? = nil
You need to change that to:
var delegate:DiscoverViewController? = nil
Issue 2
The same reason, LocationRequestModalViewController does not confirm to the LocationRequestModalViewControllerDelegate, change the delegate declaration.
You have defined your delegate as having type LocationRequestModalViewController which does not conform to LocationRequestModalViewControllerDelegate.