Argument of '#selector' does not refer - swift3

Anyone can help me?
This is my code:
fileprivate func datapicker(sender : UITextField){
let datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(datePickerValueChanged(sender: datePickerView, myText: sender)), for: UIControlEvents.valueChanged)
}
#objc func datePickerValueChanged(sender:UIDatePicker , myText : UITextField) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = DateFormatter.Style.medium
dateFormatter.timeStyle = DateFormatter.Style.none
myText.text = dateFormatter.string(from: sender.date)
}
#IBAction func fromdateAction(_ sender: UITextField) {
datapicker(sender: sender)
}

Selectors can't be called like that. You don't get to pass the arguments for a selector, the API does.
You have to pass in:
#selector(datePickerValueChanged)
This means that your datePickerValueChanged method can't take 2 arguments, because the API expects only one.
This means that you need a way to know which text field's date picker changed. One simple way to do this is to create a property called focusedTextField:
var focusedTextField: UITextField!
Set this to sender in your dataPicker method:
focusedTextField = sender
And set it to nil when the user ends editing
// in another method that is called when the text field ends editing
focusedTextField = nil
Now, you can remove the second argument from datePickerValueChanged and use focusedTextField instead.

Related

Swift2 to Swift3 error - Cannot assign value of type 'NSDictionary?' to type 'AddressModel'

Moving an app from Swift2 to Swift3 and I've hit an error that I've been unable to fix after trying several different suggestions.
lazy var address: AddressModel? = {
[unowned self] in
var dict = self.getpayloadDict()
var model: AddressModel
model = dict
return model
}()
model = dict throws Cannot assign value of type 'NSDictionary?' to type 'AddressModel'
The AddressModel . . .
class AddressModel: Deserializable {
var City: String?
var State: String?
var PostalCode: String?
required init(data: [String: AnyObject]) {
City = data["City"] as! String?
State = data["State"] as! String?
PostalCode = data["PostalCode"] as! String?
}
}
Any help appreciated.
The error is supposed to occur also in Swift 2. It's pretty clear: getpayloadDict() returns a dictionary which doesn't match AddressModel.
You might create an AddressModel instance from the dictionary
lazy var address: AddressModel? = { // this closure does not cause a retain cycle
let dict = self.getpayloadDict()
return AddressModel(data: dict)
}()
Side note:
as! String? (force unwrap an optional to an optional) is horrible syntax. Use regular conditional downcast as? String. And please conform to the naming convention that variable names start with a lowercase letter.

Getting nil response while passing string to another view controller - Swift3

In FirstViewController i'm fetching the response from JSON and want to pass that fetched response to another view controller.Below is the code which i have used so far for parsing and passing the response.
FirstViewController
var fn:String! //globally declared variable
code i have tried for parsing in FirstViewController
do {
let detailsDictionary:NSDictionary = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! Dictionary<String, AnyObject> as NSDictionary
print(detailsDictionary)
let details = detailsDictionary["Data"] as! [[String:AnyObject]]
print(details)
for dtl in details
{
self.fn = dtl["Father_Name"] as? String ?? "NA"
print(self.fn) //here i'm getting the exact value from JSON
}
}
}
SecondViewController
In SecondViewController there is a Label called profile_name and want to set that parsed string(fn) as Label's text. for that i declared another variable as global.
var pname:String!
below is the code i have used to fetch the value from FirstViewController.
viewDidLoad()
{
let othervc = FirstViewController()
self.pname = othervc.fn
self.profile_name.text = self.pname
}
Problem : I tried my best efforts to get the desired output but i'm getting nil response.
Please Help.
In Second ViewController
let strName:String!
In First ViewController
let strOne = "This is for testing"
let objstory = self.storyboard?.instantiateViewController(withIdentifier: "yout Secoond ViewController Storybord ID") as! YourSecondViewControllerName
objstory.strNam = strOne
self.navigationController?.pushViewController(objstory, animated: true)
Your updated code just won't work.
let othervc = FirstViewController()
creates a new instance of FirstViewController (not the one that got the JSON).
You should be handling it something like this:
In FirstViewController
let fn = dtl["Father_Name"] as? String ?? "NA"
let svc = SecondViewController() // Or maybe instantiate from Storyboard, or maybe you already have a reference to it
svc.pname = fn
present(svc, animated: true, completion: nil)
Then in SecondViewController
override func viewDidLoad() {
super.viewDidLoad()
profile_name.text = pname
}
I'd suggest you take some time out and re-read Apple's View Controller programming guide.
Original Answer
The problem you have here…
vcvalue.profile_name.text = fn
is that profile_name is nil as the view for the view controller hasn't been loaded at this point.
You should handle this by creating a property in LeftSideMenuViewController
var name: String?
Then set
vcvalue.name = fn
And then in LeftSideMenuViewController
override func viewDidLoad() {
super.viewDidLoad()
profile_name.text = name
}
Also, some basic tips…
Don't force unwrap (!) apart from IBOutlets. You may have to write a bit more code, but you will reduce crashes.
Make #IBOutlets private - this will prevent you accidentally assigning to them as you are now
If you're overriding any viewWill/DidDis/Appear methods, you must call super at some point.
You need to re-read the section on switch/case
So this…
let a = indexPath.row
switch(a)
{
case 0 :
if(a == 0)
{
return 45
}
break
etc
could just be…
switch indexPath.row {
case 0...4:
return 45
case 5:
return 50
default:
break
}

how to get selected text of textfield on button click? pickerview is set as an inputview to the textfield. Swift

currently my output is displaying selected values from pickerview inside textfields.
now my question is i want to access all these values on submit button and want to display in another view controller how to do this?. let me explain my scenario my first vc is set as collectionview from one of the collectionviewcell m redirecting to this page.
Note: i already know that how to pass data between two view controller. but its not working in my case.Please Help.
Code
#IBAction func StaffAtten_Action(_ sender: Any) {
// let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "StaffAttendence_SecondPage") as! StaffAttendence_SecondPage
//
// secondVC.a = active_text.text!
// secondVC.b = active_text.text!
// secondVC.c = active_text.text!
// secondVC.savedata.append(year.text!)
// secondVC.savedata.append(month.text!)
// secondVC.savedata.append(institute.text!)
}
}
The problem that you are having is that you are instantiating a brand new VC and passing data to it. The VC that is actually presented is not the one you created.
Since you have a segue connecting the two VCs, override prepare(for:sender:)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? StaffAttendence_SecondPage {
vc.a = ...
vc.b = ...
// pass the rest of the data here...
}
}

Retrieving value from database

Hi I have a problem and would be grateful to any advice or answer.
func getUserProfileMDP(){
// set attributes to textField
var ref: DatabaseReference!
ref = Database.database().reference()
let user = Auth.auth().currentUser
print(user!.uid)
ref.child("users").child((user?.uid)!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
guard let value = snapshot.value as? [String: String] else { return }
print(value)
let passwordValue = value["password"]!as! String
print(passwordValue)
self.MDP = passwordValue // prints the right value from database
}){ (error) in
print(error.localizedDescription)
}
print(self.MDP) // prints the value innitialised in class(nope)
}
Here is the function that gets the value from database. It works (the first print gets the right value)
#IBAction func register(_ sender: Any) {
print(self.MDP)// prints the value innitialised in class(nope)
getUserProfileMDP()
print(self.MDP) // prints the value innitialised in class(nope)
let MDP = self.MDP
That is were I need the password to compare it. It doesn't get me the value of the database but the value initialized in class above:
var MDP = "nope"
Have a nice day
Given your last comment, I'd say that you're almost there, but here's an example. I did not fix the other parts of your code, I only added the completion handler in the method signature, and passed the password value to the handler, to show you how this works. The handler must be called inside the async closure.
func getUserProfileMDP(completion: #escaping (String)->()) {
// set attributes to textField
var ref: DatabaseReference!
ref = Database.database().reference()
let user = Auth.auth().currentUser
print(user!.uid)
ref.child("users").child((user?.uid)!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
guard let value = snapshot.value as? [String: String] else { return }
print(value)
let passwordValue = value["password"]!as! String
completion(passwordValue)
}){ (error) in
print(error.localizedDescription)
}
}
And you call it like that:
getUserProfileMDP() { pass in
print(pass)
self.MDP = pass
}

set alarm using DatePicker (swift3

My code below works that if you manually use to datePicker to match the date and time with the users date and time it will print cool. However the code does not work as a alarm. I can set the date picker ahead of the user time and when the user time matches the date pickers timer nothing prints. I just want to be able to select a date/time using date picker and when the users eventually matches the datePickers time just print cool.
import UIKit
var dateFormatter : DateFormatter!
let datePicker2 = UIDatePicker();
let date = Date()
class ViewController: UIViewController {
#IBOutlet var dateLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let datePicker : UIDatePicker = UIDatePicker(frame: CGRect(x: 0,y: 330,width: self.view.frame.size.width,height: 220))
datePicker.datePickerMode = UIDatePickerMode.dateAndTime
self.view.addSubview(datePicker)
datePicker.addTarget(self, action: #selector(ViewController.change(_:)), for: UIControlEvents.valueChanged)
dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd hh:mm"
}
#IBAction func change(_ sender : UIDatePicker)
{
let pickerString = dateFormatter.string(from: sender.date)
let nowString = dateFormatter.string(from: Date())
dateLabel.text = pickerString
if pickerString == nowString {
print("cool")
}
}}
This is happening because your if statement is only being called when the picker moves. You need a timer that fires every second looking to see if they match. To use the method below you just need to move the pickerString and nowString up to global variables. If you don't like that you can refactor and use as you want.
var pickerString: String?
var nowString: String?
override func viewDidLoad() {
super.viewDidLoad()
let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
if pickerString == nowString {
print("cool")
}
}
#buildSucceeded