ActionSheetPicker Invalid target/action combination used for ActionSheetPicker' - ios

Hi I'm trying to use ActionSheetPicker to let the user select a time for a reminder but I get the error described in the title. Here is my Code:
SelectTime(sender: validCell) // called when tapping a date
// Time Picker
func SelectTime(sender: UIView){
//let timePicker = ActionSheetDatePicker.show(withTitle: "Enter time for reminder", datePickerMode: .time, selectedDate: userDate, target: self, action: , origin: sender.superview!.superview)
let timePicker = ActionSheetDatePicker.show(withTitle: "Enter time for reminder", datePickerMode: .time, selectedDate: userDate, target: self, action: Selector(("timePicked")), origin: sender.superview!.superview, cancelAction: Selector(("timeCanceled")))
timePicker?.minuteInterval = 5
timePicker?.locale = Calendar.current.locale
timePicker?.show()
}
func timePicked(time: Date){
dateSelected.text = formatter.string(for: time)
}
func timeCanceled(){
print("Canceled")
dismiss(animated: true, completion: nil)
}
The cancel code is never called and when I press cancel on the timePicker it shows another time picker underneath it without any buttons.
Gif when canceling
http://www.giphy.com/gifs/l1J3zMQWJ23GpHEaY
The dateSelected is also never called. I'm I doing the selectors wrong?

Change this code
func SelectTime(sender: UIView){
let timePicker = ActionSheetDatePicker.show(withTitle: "Enter time for reminder", datePickerMode: .time, selectedDate: userDate, target: self, action: , origin: sender.superview!.superview)
let timePicker = ActionSheetDatePicker.show(withTitle: "Enter time for reminder", datePickerMode: .time, selectedDate: userDate, target: self, action: Selector(("timePicked")), origin: sender.superview!.superview, cancelAction: Selector(("timeCanceled")))
timePicker?.minuteInterval = 5
timePicker?.locale = Calendar.current.locale
timePicker?.show()
}
func timePicked(time: Date){
dateSelected.text = formatter.string(for: time)
}
func timeCanceled(){
print("Canceled")
dismiss(animated: true, completion: nil)
}
in this code....
let timePicker = ActionSheetDatePicker(title: "Date:", datePickerMode: UIDatePickerMode.date, selectedDate: Date(), doneBlock: {
picker, value, index in
dateSelected.text = formatter.string(for: time)
print("value = \(value)")
print("index = \(index)")
print("picker = \(picker)")
return
}, cancel: { ActionStringCancelBlock in
print("cancel")
return }, origin: sender.superview!.superview)
timePicker?.minuteInterval = 5
timePicker?.locale = Calendar.current.locale

Related

In Swift, how to get a UIAlertAction button to stay in the enclosure when pressed

I have a UIAlertController that has a series of buttons. When I press the button, I want a variable to be set with a certain value which will in turn populate one of the textfields and the CoreData upon hitting the save button within the alert.
I am close but not quite there - when I press the button it will set the variable to what I want, but it immediately closes the alert. What I want to do is use keyboard to enter the information in the 2 textfields, press the button for 'vaccination' for example to set the entryType = "vaccination" and then the user should hit save to save the record.
#IBAction func buttonAddEntry(_ sender: Any) {
var typeField = ""
let newEntry = Vaccination(context: context)
print ("Create New VAX ENTRY")
let alert = UIAlertController(title: "New Entry", message: "Enter Entry Details", preferredStyle: .alert)
alert.addTextField()
alert.addTextField()
let dateField = alert.textFields![0]
dateFieldMain = dateField
//let typeField = alert.textFields![1]
//let commentField = alert.textFields![2]
let datePicker = UIDatePicker()
datePicker.datePickerMode = UIDatePicker.Mode.date
datePicker.addTarget(self, action: #selector(VaxViewController.datePickerValueChanged(sender:)), for: UIControl.Event.valueChanged)
dateFieldMain!.inputView = datePicker
print ("textfield set to datepicker")
let bt1 = UIAlertAction(title: "Vaccination", style: UIAlertAction.Style.default) {
(action) in
print ("Vaccination")
typeField = "Vaccination"
}
alert.addAction(bt1)
let bt2 = UIAlertAction(title: "Wormer", style: UIAlertAction.Style.default){
(action) in
print ("Wormer")
typeField = "Wormer"
}
alert.addAction(bt2)
let bt3 = UIAlertAction(title: "Medication", style: UIAlertAction.Style.default){
(action) in
print ("Medication")
typeField = "Medication"
}
alert.addAction(bt3)
let cancelButton = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.destructive) {
(action) in return }
alert.addAction(cancelButton)
let alertButton = UIAlertAction(title: "Save", style: .default) { (action) in
let dateField = alert.textFields![0]
//let typeField = alert.textFields![1]
let commentField = alert.textFields![2]
//convert date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM, dd, yyyy"
let dateConverted = dateFormatter.date(from: dateField.text!)
//set the properties of the new entry
newEntry.vaxDate1 = dateConverted
newEntry.vaxType = typeField
newEntry.comment = commentField.text
newEntry.animal = self.animal
try! self.context.save()
self.fetchVaccinations()
//self.tableView.reloadData()
}
alert.addAction(alertButton)
self.present(alert, animated: true, completion: nil)
}

How do I display contacts when UITextField is clicked?

I have tried multiple times to create a UITextField that when clicked should show the contacts available on the device and retrieve the phone number and display it in the textfield. However I have been unable to do that. The best that I could do is to use a button to receive and display the number on a textfield. This works! How do I do the same for when the UITextField is clicked?
I'm running it on Xcode 10
private let contactPicker = CNContactPickerViewController()
override func viewDidLoad() {
super.viewDidLoad()
configureTextFields()
configureTapGesture()
phonenumber.textContentType = .telephoneNumber
}
private func configureTextFields() {
phonenumber.delegate = self
}
private func configureTapGesture(){
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SelfTestTimer.handleTap))
viewcontact.addGestureRecognizer(tapGesture)
}
#objc private func handleTap(){
viewcontact.endEditing(true)
}
#IBAction func pbbbbb(_ sender: Any) {
contactPicker.delegate = self
self.present(contactPicker, animated: true, completion: nil)
}
}
extension SelfTestTimer: CNContactPickerDelegate {
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
let phoneNumberCount = contact.phoneNumbers.count
guard phoneNumberCount > 0 else {
dismiss(animated: true)
return
}
if phoneNumberCount == 1 {
setNumberFromContact(contactNumber: contact.phoneNumbers[0].value.stringValue)
}else{
let alertController = UIAlertController(title: "Select one of the numbers", message: nil, preferredStyle: .alert)
for i in 0...phoneNumberCount-1 {
let phoneAction = UIAlertAction(title: contact.phoneNumbers[i].value.stringValue, style: .default, handler: {
alert -> Void in
self.setNumberFromContact(contactNumber: contact.phoneNumbers[i].value.stringValue)
})
alertController.addAction(phoneAction)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: {
alert -> Void in
})
alertController.addAction(cancelAction)
dismiss(animated: true)
self.present(alertController, animated: true, completion: nil)
}
}
func setNumberFromContact(contactNumber: String) {
var contactNumber = contactNumber.replacingOccurrences(of: "-", with: "")
contactNumber = contactNumber.replacingOccurrences(of: "(", with: "")
contactNumber = contactNumber.replacingOccurrences(of: ")", with: "")
guard contactNumber.count >= 10 else {
dismiss(animated: true) {
self.presentAlert(alertTitle: "", alertMessage: "A maximum of 10 contacts allowed per session", lastAction: nil)
}
return
}
phonenumber.text = String(contactNumber.suffix(10))
}
func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
}
}
extension SelfTestTimer: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
I want it so that when the UITextField is clicked, the contacts will appear and when one contact is selected, the number should appear in the textfield
You should use textFieldShouldBeginEditing method. Open the contacts controller in this method and return false, no need to add a gesture recogniser.

How do I fix this code to allow for the timer to begin as a result of the user clicking on the UIAlert?

Trying to make a timer start as a result of the UIAlert being clicked on. But I keep getting this error indicating the instances isTimerRunning and runTimer cannot be used on the thirdViewController.
We have been trying to move it around, thinking it is a scope issue, but cannot seem to get it to be ok with those functions.
When we adjusted it to use alert.copyAction, rather than let.. the error changes to "expected declaration".
var seconds = 60
var timer = Timer()
var isTimerRunning = false
var resumeTapped = false
let alert = UIAlertController(title: "Your wing was damaged! There is also a dust storm incoming! You need to repair the wing and escape to the next planet.", message: nil, preferredStyle: .alert)
let copyAction = UIAlertAction(title: "Copy that mission control!", style: .default, handler: { action in
if isTimerRunning == false {
runTimer()
}
})
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(thirdViewController.updateTimer)), userInfo: nil, repeats: true)
}
#objc func updateTimer() {
if seconds < 1 {
timer.invalidate()
} else {
seconds -= 1
timeLabel.text = timeString(time: TimeInterval(seconds))
}
}
func timeString(time:TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i”, hours, minutes, seconds")
}
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(withTimeInterval: 0.0, repeats: false) { (timer) in
self.alert.addAction(self.copyAction)
self.present(self.alert,animated: true, completion: nil)
}
}
//use run timer method in alert controller).so you can start timer with open alert
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(withTimeInterval: 0.0, repeats: false) { (timer) in
runtimer()
self.alert.addAction(self.copyAction)
self.present(self.alert,animated: true, completion: nil)
}
}

Countdown timer shown inside of button in UIAlertController then enable button swift update

This is a previous post. As I am new I can not comment.
Thanks to Muhammad Zeeshan as his aswer worked for me until...
Since the latest swift the code changed. Now you click the cancel button and get the error Unexpectedly found nil while unwrapping an Optional value on line
let alertController = presentedViewController as! UIAlertController
Actual updated code
var timer = Timer()
var timerCount: Int = 5
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func okButton(_ sender: Any) {
showAlertView()
}
func showAlertView() {
let alertController = UIAlertController(title: "Title", message: "Message of alert", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
okAction.isEnabled = false
alertController.addAction(okAction)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alertController, animated: true) {
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.countDownTimer), userInfo: nil, repeats: true)
}
}
#objc func countDownTimer() {
timerCount -= 1
let alertController = presentedViewController as! UIAlertController
let okAction = alertController.actions.first
if timerCount == 0 {
timer.invalidate()
okAction?.setValue("Ok", forKey: "title")
okAction?.isEnabled = true
} else {
okAction?.setValue("Ok \(timerCount)", forKey: "title")
}
}}
So I am wondering how to kill it without the error.
Once I figured out unwrapping an optional it was easy.
Just before
let alertController = presentedViewController as! UIAlertController
Do
if presentedViewController == nil {
timer.invalidate()
return
}
Also I had to add
timerCount = 5
before
showAlertView()
To reset the counter.

notification firing 6 times a minute (swift4)

Every time my notification timer goes off it repeats 6 times via in the minute. I only want the notification to fire once per minute. How can I write the code so the notification only goes off once per minute.
import UIKit
class ViewController: UIViewController {
var timer = Timer()
var passingDate : Date?
#IBOutlet var dptext: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
createDatePicker()
timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(ViewController.testDate), userInfo: nil, repeats: true)
}
func createDatePicker() {
datePicker.datePickerMode = .dateAndTime
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneButton], animated: false)
dptext.inputAccessoryView = toolbar
dptext.inputView = datePicker
}
#objc func testDate() {
if Calendar.current.isDate(datePicker.date, equalTo: Date(), toGranularity: .minute) {
print("success")
if let passingDate = passingDate, Calendar.current.isDate(datePicker.date, equalTo: passingDate, toGranularity: .minute) {
// Previous date existing, and is in the same minute as the current date : do nothing
return
}
passingDate = datePicker.date
print("success")
}
}
#objc func donePressed() {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
dptext.text = dateFormatter.string(from: datePicker.date)
self.view.endEditing(true)
}
}
Change the timeInterval from 10 to 60 :
timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(ViewController.testDate), userInfo: nil, repeats: true)

Resources