NSNotificationCenter 问题:抛出致命错误
NSNotificationCenter issue: Fatal error thrown
我正在开发一个身份验证系统。目前我可以提取 API 数据并对用户进行身份验证。我使用 NSNotificationCenter 字典来存储我的值,我可以打印出字符串消息,但我的布尔值 returns 是可选的。另外,我不确定完成后应该在哪里移除我的观察者。我应该如何实施它?
接收用户输入的代码
import UIKit
class LoginViewController: UIViewController {
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var pwdField: UITextField!
@IBAction func loginBtn(sender: AnyObject) {
let loginobj = Login(userName : self.usernameField.text!, passWord : self.pwdField.text!)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(LoginViewController.handlingAuthentication(_:)), name:"errorPresent", object: nil)
loginobj.getRequest()
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func handlingAuthentication(notification: NSNotification) {
let dict = notification.object as! NSDictionary
let errorFound = dict["error"]
let errorMessage = dict["message"]
print(errorFound)
if((errorFound?.string)! == true){
//initialize Alert Controller
let alertController = UIAlertController(title: "Authentication error", message: errorMessage?.string, preferredStyle: .Alert)
//Initialize Actions
let okAction = UIAlertAction(title: "Ok", style: .Default){
(action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
}
//Add Actions
alertController.addAction(okAction)
//Present Alert Controller
self.presentViewController(alertController, animated: true, completion: nil)
}
else
{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLoggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
self.dismissViewControllerAnimated(true, completion:nil)
}
}
}
LoginViewController 的代码处理数据处理
import Foundation
import Alamofire
import SwiftyJSON
import RealmSwift
class Login {
init(userName: String, passWord: String) {
Data.sharedInstance.userName = userName
Data.sharedInstance.passWord = passWord
}
// call this method to login
func getRequest() {
Alamofire.request(.POST, Data.todoEndpoint, parameters: ["username": Data.sharedInstance.userName!, "password": Data.sharedInstance.passWord!])
.responseJSON { response in
var errorFound = Bool()
var errorMessage = String()
if let result = response.result.value
{
let value = JSON(result)
var outcome = String()
//No username
if value["password"] == nil && value["message"] == nil && value["name"] == nil
{
errorFound = true
outcome = "No username: \(value)"
errorMessage = outcome
}
//No password
else if value["username"] == nil && value["message"] == nil
{
errorFound = true
outcome = "No password: \(value)"
errorMessage = outcome
}
//No password/ username
else if value["username"] == nil && value["password"] == nil && value["message"] != nil
{
outcome = "Incorrect cred: \(value)"
errorFound = true
errorMessage = outcome
}
//success
else if value["username"] != nil && value["password"] == nil && value["message"] == nil
{
errorFound = false
if let api_key = value["api_token"].string
{
print("The token is " + api_key)
}
else
{
print("error parsing api token")
}
//pass data to Users class
_ = Users.init(Name: value["name"].string, Email: value["email"].string, Id: value["id"].int, ProfilePicture: value["profile_picture"].string, Username: value["username"].string)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "errorPresent", object: nil)
}
else
{
errorFound = true
outcome = "No password and username: \(value)"
errorMessage = outcome
}
}
else
{
print("JSON data is nil.")
}
let errorDict = ["error": errorFound, "message": errorMessage]
NSNotificationCenter.defaultCenter().postNotificationName("errorPresent", object:errorDict)
}
}
}
正如 Dan 所指出的,一旦网络请求完成,'in' 之后的代码将 运行 异步。在该代码中触发一个事件(例如 NSNotification),您的其余代码可以使用该事件来知道它已完成。
编辑以回答更改后的问题:
在设置变量之前,您仍在 post 发送通知。将 post 移动到 'in' 块的末尾。
编辑 2:关于 nil 错误,我认为这与您对 .string 的使用有关,请参阅
您没有收到所需的布尔结果的原因有两个:
- 你处理传递的数据的方式是错误的
在您的 handlingAuthentication 方法中,您应该改为这样做:
func handlingAuthentication(notification: NSNotification) {
let dict = notification.object as! NSDictionary
if dict["error"]! as! Bool == true {
let errorMessage = dict["message"] as! String
//initialize Alert Controller
let alertController = UIAlertController(title: "Authentication error", message: errorMessage, preferredStyle: .Alert)
//Initialize Actions
let okAction = UIAlertAction(title: "Ok", style: .Default){
(action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
}
//Add Actions
alertController.addAction(okAction)
//Present Alert Controller
self.presentViewController(alertController, animated: true, completion: nil)
}
else
{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLoggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
self.dismissViewControllerAnimated(true, completion:nil)
}
}
其中 let errorMessage = dict["message"] as! String
和 dict["error"]! as! Bool == true
将从您的输出中删除可选项
- 您处理 JSON 的方式不正确。据我从您的其他帖子中了解到,您要查找的数据是数组形式的。
这是获取密码和用户名错误值的方法:
errorMessage = value["password"][0].string!
errorMessage = value["username"][0].string!
我正在开发一个身份验证系统。目前我可以提取 API 数据并对用户进行身份验证。我使用 NSNotificationCenter 字典来存储我的值,我可以打印出字符串消息,但我的布尔值 returns 是可选的。另外,我不确定完成后应该在哪里移除我的观察者。我应该如何实施它?
接收用户输入的代码
import UIKit
class LoginViewController: UIViewController {
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var pwdField: UITextField!
@IBAction func loginBtn(sender: AnyObject) {
let loginobj = Login(userName : self.usernameField.text!, passWord : self.pwdField.text!)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(LoginViewController.handlingAuthentication(_:)), name:"errorPresent", object: nil)
loginobj.getRequest()
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func handlingAuthentication(notification: NSNotification) {
let dict = notification.object as! NSDictionary
let errorFound = dict["error"]
let errorMessage = dict["message"]
print(errorFound)
if((errorFound?.string)! == true){
//initialize Alert Controller
let alertController = UIAlertController(title: "Authentication error", message: errorMessage?.string, preferredStyle: .Alert)
//Initialize Actions
let okAction = UIAlertAction(title: "Ok", style: .Default){
(action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
}
//Add Actions
alertController.addAction(okAction)
//Present Alert Controller
self.presentViewController(alertController, animated: true, completion: nil)
}
else
{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLoggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
self.dismissViewControllerAnimated(true, completion:nil)
}
}
}
LoginViewController 的代码处理数据处理
import Foundation
import Alamofire
import SwiftyJSON
import RealmSwift
class Login {
init(userName: String, passWord: String) {
Data.sharedInstance.userName = userName
Data.sharedInstance.passWord = passWord
}
// call this method to login
func getRequest() {
Alamofire.request(.POST, Data.todoEndpoint, parameters: ["username": Data.sharedInstance.userName!, "password": Data.sharedInstance.passWord!])
.responseJSON { response in
var errorFound = Bool()
var errorMessage = String()
if let result = response.result.value
{
let value = JSON(result)
var outcome = String()
//No username
if value["password"] == nil && value["message"] == nil && value["name"] == nil
{
errorFound = true
outcome = "No username: \(value)"
errorMessage = outcome
}
//No password
else if value["username"] == nil && value["message"] == nil
{
errorFound = true
outcome = "No password: \(value)"
errorMessage = outcome
}
//No password/ username
else if value["username"] == nil && value["password"] == nil && value["message"] != nil
{
outcome = "Incorrect cred: \(value)"
errorFound = true
errorMessage = outcome
}
//success
else if value["username"] != nil && value["password"] == nil && value["message"] == nil
{
errorFound = false
if let api_key = value["api_token"].string
{
print("The token is " + api_key)
}
else
{
print("error parsing api token")
}
//pass data to Users class
_ = Users.init(Name: value["name"].string, Email: value["email"].string, Id: value["id"].int, ProfilePicture: value["profile_picture"].string, Username: value["username"].string)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "errorPresent", object: nil)
}
else
{
errorFound = true
outcome = "No password and username: \(value)"
errorMessage = outcome
}
}
else
{
print("JSON data is nil.")
}
let errorDict = ["error": errorFound, "message": errorMessage]
NSNotificationCenter.defaultCenter().postNotificationName("errorPresent", object:errorDict)
}
}
}
正如 Dan 所指出的,一旦网络请求完成,'in' 之后的代码将 运行 异步。在该代码中触发一个事件(例如 NSNotification),您的其余代码可以使用该事件来知道它已完成。
编辑以回答更改后的问题: 在设置变量之前,您仍在 post 发送通知。将 post 移动到 'in' 块的末尾。
编辑 2:关于 nil 错误,我认为这与您对 .string 的使用有关,请参阅
您没有收到所需的布尔结果的原因有两个:
- 你处理传递的数据的方式是错误的
在您的 handlingAuthentication 方法中,您应该改为这样做:
func handlingAuthentication(notification: NSNotification) {
let dict = notification.object as! NSDictionary
if dict["error"]! as! Bool == true {
let errorMessage = dict["message"] as! String
//initialize Alert Controller
let alertController = UIAlertController(title: "Authentication error", message: errorMessage, preferredStyle: .Alert)
//Initialize Actions
let okAction = UIAlertAction(title: "Ok", style: .Default){
(action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
}
//Add Actions
alertController.addAction(okAction)
//Present Alert Controller
self.presentViewController(alertController, animated: true, completion: nil)
}
else
{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLoggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
self.dismissViewControllerAnimated(true, completion:nil)
}
}
其中 let errorMessage = dict["message"] as! String
和 dict["error"]! as! Bool == true
将从您的输出中删除可选项
- 您处理 JSON 的方式不正确。据我从您的其他帖子中了解到,您要查找的数据是数组形式的。
这是获取密码和用户名错误值的方法:
errorMessage = value["password"][0].string!
errorMessage = value["username"][0].string!