Swift:从 class 设置 UITextField.text(从 SQLite 检索值)
Swift: Set UITextField.text from class (retrieved value from SQLite)
我正在使用 Swift 和 SQLite.swift。我有以下 UIViewController:
class LoginViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
MySQLite().updateLatestEmailAddressFromUserTable() // breaks here (email is in console, though...)
}
}
然后我尝试从另一个 class:
更新它的值(通过 setEmailAddress 函数)
class MySQLite {
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
LoginViewController().setEmailAddress(user[email]) // breaks here
}
}
}
上面的代码给出了以下错误
fatal error: unexpectedly found nil while unwrapping an Optional value
进一步解释一下:我正在检索 SQLite table 中的最新条目以获取用户的电子邮件地址并更新登录视图控制器中的文本字段。这使得 returning 用户更容易登录。
我已经为此苦苦挣扎了 2 个多小时,并尝试了各种方法。我认为 主要问题 是当我尝试简单地 return 电子邮件地址作为我的第二个函数的字符串并直接从 LoginViewController 设置字段时,它不起作用( SQLite 相关代码还不是 "executed" 但我相信)。
可能相关的线程(Obj-C):
set UITextField.text from another class
问题是当您尝试将文本分配给 textField 时,LoginViewController
的视图未加载。即:emailField
为 nil 并且解包 nil 值会导致运行时崩溃(因为插座尚未连接到它的 storyboard/xib 对端)。
确保具有emailField 的视图已在屏幕上实例化。
@IBOutlet weak var emailField: UITextField!
这是一个可选的,在故事板或 nib 加载之前它将为 nil。我假设 OnBoardingRegistrationFormController 是您的 LoginViewController class?
的一个实例
我看到你已经接受了一个答案,但在这种情况下创建协议可能有点矫枉过正。如果 sqlite 是您的模型,为什么不直接让函数 return 有一个值,然后您可以将该值分配给控制器中的文本字段。例如
class LoginViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
override func viewDidLoad() {
emailField.text = MySQLite().updateLatestEmailAddressFromUserTable()
}
}
class MySQLite {
func updateLatestEmailAddressFromUserTable() -> String{
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
return user[email]
}
}
}
这是怎么回事 LoginViewController().setEmailAddress(user[email])
创建了 LoginViewController
的新实例,它与您当前的 LoginViewController 不同。
为什么不在 MySQLite 中制定协议并定义为委托
并且LoginViewController 将实现update 方法。将委托传递给 MySqlite
在 MySQLite 中,当您从数据库中获取值时调用委托更新方法。
示例
MySQLite
protocol loginDelegate
{
func update(NSString)
}
class MySQLite {
var delegate:loginDelegate?
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
if((delegate) != nil)
{
delegate?.update("example@example.com")
}
}
}
}
class LoginViewController: UIViewController,loginDelegate {
@IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
var mySQLite: MySQLite=LoginClass();
mySQLite.delegate=self;
[mySQLite .updateLatestEmailAddressFromUserTable()];
}
func update(email: NSString) {
println(email);
emailField.text = email
}
}
我正在使用 Swift 和 SQLite.swift。我有以下 UIViewController:
class LoginViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
MySQLite().updateLatestEmailAddressFromUserTable() // breaks here (email is in console, though...)
}
}
然后我尝试从另一个 class:
更新它的值(通过 setEmailAddress 函数)class MySQLite {
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
LoginViewController().setEmailAddress(user[email]) // breaks here
}
}
}
上面的代码给出了以下错误
fatal error: unexpectedly found nil while unwrapping an Optional value
进一步解释一下:我正在检索 SQLite table 中的最新条目以获取用户的电子邮件地址并更新登录视图控制器中的文本字段。这使得 returning 用户更容易登录。
我已经为此苦苦挣扎了 2 个多小时,并尝试了各种方法。我认为 主要问题 是当我尝试简单地 return 电子邮件地址作为我的第二个函数的字符串并直接从 LoginViewController 设置字段时,它不起作用( SQLite 相关代码还不是 "executed" 但我相信)。
可能相关的线程(Obj-C): set UITextField.text from another class
问题是当您尝试将文本分配给 textField 时,LoginViewController
的视图未加载。即:emailField
为 nil 并且解包 nil 值会导致运行时崩溃(因为插座尚未连接到它的 storyboard/xib 对端)。
确保具有emailField 的视图已在屏幕上实例化。
@IBOutlet weak var emailField: UITextField!
这是一个可选的,在故事板或 nib 加载之前它将为 nil。我假设 OnBoardingRegistrationFormController 是您的 LoginViewController class?
的一个实例我看到你已经接受了一个答案,但在这种情况下创建协议可能有点矫枉过正。如果 sqlite 是您的模型,为什么不直接让函数 return 有一个值,然后您可以将该值分配给控制器中的文本字段。例如
class LoginViewController: UIViewController {
@IBOutlet weak var emailField: UITextField!
override func viewDidLoad() {
emailField.text = MySQLite().updateLatestEmailAddressFromUserTable()
}
}
class MySQLite {
func updateLatestEmailAddressFromUserTable() -> String{
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
return user[email]
}
}
}
这是怎么回事 LoginViewController().setEmailAddress(user[email])
创建了 LoginViewController
的新实例,它与您当前的 LoginViewController 不同。
为什么不在 MySQLite 中制定协议并定义为委托
并且LoginViewController 将实现update 方法。将委托传递给 MySqlite
在 MySQLite 中,当您从数据库中获取值时调用委托更新方法。
示例
MySQLite
protocol loginDelegate
{
func update(NSString)
}
class MySQLite {
var delegate:loginDelegate?
func updateLatestEmailAddressFromUserTable(){
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let users = db["users"]
let id = Expression<Int>("id")
let email = Expression<String>("email")
let time = Expression<Int>("time")
for user in users.limit(1).order(time.desc) {
println(user[email]) // this works, correctly outputs in console: email@domain.com
if((delegate) != nil)
{
delegate?.update("example@example.com")
}
}
}
}
class LoginViewController: UIViewController,loginDelegate {
@IBOutlet weak var emailField: UITextField!
func setEmailAddress(email:String){
emailField.text = email
}
override func viewDidLoad() {
var mySQLite: MySQLite=LoginClass();
mySQLite.delegate=self;
[mySQLite .updateLatestEmailAddressFromUserTable()];
}
func update(email: NSString) {
println(email);
emailField.text = email
}
}