如何将 PFObject 转换为字符串? - Swift 1.2 Xcode 6.4 和 Parse.com -
How convert PFObject to string? - Swift 1.2 Xcode 6.4 and Parse.com -
这是另一个问题的一部分,但是既然那个原始问题得到了答案,以后如果我在这里遇到这个问题,就更清楚了。
编辑:添加了一个异常断点,在运行时出现了这个:
我收到此消息:从 'String' 转换为无关类型 'PFObject' 总是失败
这里是警告截图
控制台还显示“无法将类型 'PFObject' (0x10980e1e8) 的值转换为 'NSString' (0x10b8e78e0)。
(lldb)“
在我看来,我无法以正确的方式访问数据,但不知道在哪里
提前致谢
//
// TimelineTVC2.swift
// lug15ParseChat
//
//
import UIKit
import Parse
class TimelineTVC2: UITableViewController {
var timelineData : [String] = []
func loadData() {
timelineData.removeAll(keepCapacity: true) //erase previus contents
var findTimeLineDataQuery = PFQuery(className: "Messages")
findTimeLineDataQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) -> Void in
if error == nil {
for singleObject in objects! {
self.timelineData.append(singleObject as! String)
}
let reversedArray : Array = self.timelineData.reverse() //remeber always!
self.timelineData = reversedArray as Array
self.tableView.reloadData()
}
})
}
// MARK: Parse
override func viewDidAppear(animated: Bool) {
self.loadData()
if PFUser.currentUser() == nil {
var loginAlertController = UIAlertController(title: "Sign up / login", message: "please sign up or login", preferredStyle: UIAlertControllerStyle.Alert)
loginAlertController.addTextFieldWithConfigurationHandler({
textfField in
textfField.placeholder = "Your username"
})
loginAlertController.addTextFieldWithConfigurationHandler({
textfField in
textfField.placeholder = "Your password"
textfField.secureTextEntry = true
})
// MARK: login action in the array
loginAlertController.addAction(UIAlertAction(title: "Login Action", style: UIAlertActionStyle.Default, handler: {
alertAction in
let textFields : NSArray = loginAlertController.textFields!
let usernameTextField : UITextField = textFields[0] as! UITextField
let passwordTextField : UITextField = textFields[1] as! UITextField
//MARK: Parse login problem - 15:39
PFUser.logInWithUsernameInBackground(usernameTextField.text, password: passwordTextField.text){
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
println("login success!")
} else {
println("login failed!")
}
}
}))
// MARK: sign up action in the array
loginAlertController.addAction(UIAlertAction(title: "Sign up", style: UIAlertActionStyle.Default, handler: {
alertAction in
let textFields : NSArray = loginAlertController.textFields!
let usernameTextField : UITextField = textFields[0] as! UITextField
let passwordTextField : UITextField = textFields[1] as! UITextField
var messageSender = PFUser() //16:42
messageSender.username = usernameTextField.text
messageSender.password = passwordTextField.text
messageSender.signUpInBackgroundWithBlock({
(success: Bool, error: NSError?) -> Void in
if error == nil {
println("sign up successful")
} else {
// let errorString = error!.userInfo["error"] as! String
let errorString = error!.localizedDescription
println(errorString)
}
})
}))
self.presentViewController(loginAlertController, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return timelineData.count
}
//MARK: WARNING! Cast from 'String' to unrelated type 'PFObject' always fails
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : SweetTableViewCell = tableView.dequeueReusableCellWithIdentifier("cellReuseID", forIndexPath: indexPath) as! SweetTableViewCell
var textMessage : PFObject = self.timelineData[indexPath.row] as! PFObject
cell.sweetTextView.text = textMessage["content"] as! String
return cell
}
}
您想要做的是将整个 PFObject
转换为 String
,正如编译器指出的那样,这将永远行不通。您需要做的是访问 PFObject
中包含您要获取的字符串的字段。因此,例如,在 User
class 上,电子邮件字段是一个字符串。为了从 PFUser
(PFObject
的子class)中获取它,您需要访问该字段,然后分配 that 到字符串。它看起来像这样(假装 singleObject
是 PFUser
因为我不知道你的字段):
for singleObject in objects! {
if let stringData = singleObject["email"] as? String {
timelineData.append(stringData)
}
}
另一种选择,只是语法不同。
for singleObject in objects! {
if let stringData = singleObject.objectForKey("email") as? String {
timelineData.append(stringData)
}
}
两者都会起作用,并为您提供所需的结果。
此外,作为附加点,您可以简单地调用 findTimeLineDataQuery.orderByDescending("createdAt")
,而不是在将对象放入其中后反转数组。这将为您节省一些开销,因为它会在数据返回给您之前完成,而不是在设备上完成。
编辑:修复 cellForRowAtindexPath:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : SweetTableViewCell = tableView.dequeueReusableCellWithIdentifier("cellReuseID", forIndexPath: indexPath) as! SweetTableViewCell
cell.sweetTextView?.text = self.timelineData[indexPath.row]
return cell
}
您试图转换刚从 PFObject
中取出的字符串,然后将它们转回 PFObject
。由于您现在有了要显示的文本,因此在 cellForRowAtindexPath:
中,您所要做的就是访问存储在 timelineData
数组中该位置的值。
您在这里真正想做的是投射 PFObject
的 属性 - 而不是对象本身。在下面的示例中,someProperty
是您希望访问的 Messages
对象上的字段。
它应该看起来像这样:
for singleObject in objects! {
var someProperty = singleObject["somePropertyName"] as String
self.timelineData.append(someProperty)
}
这是另一个问题的一部分,但是既然那个原始问题得到了答案,以后如果我在这里遇到这个问题,就更清楚了。
编辑:添加了一个异常断点,在运行时出现了这个:
我收到此消息:从 'String' 转换为无关类型 'PFObject' 总是失败
这里是警告截图
控制台还显示“无法将类型 'PFObject' (0x10980e1e8) 的值转换为 'NSString' (0x10b8e78e0)。 (lldb)“
在我看来,我无法以正确的方式访问数据,但不知道在哪里
提前致谢
//
// TimelineTVC2.swift
// lug15ParseChat
//
//
import UIKit
import Parse
class TimelineTVC2: UITableViewController {
var timelineData : [String] = []
func loadData() {
timelineData.removeAll(keepCapacity: true) //erase previus contents
var findTimeLineDataQuery = PFQuery(className: "Messages")
findTimeLineDataQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) -> Void in
if error == nil {
for singleObject in objects! {
self.timelineData.append(singleObject as! String)
}
let reversedArray : Array = self.timelineData.reverse() //remeber always!
self.timelineData = reversedArray as Array
self.tableView.reloadData()
}
})
}
// MARK: Parse
override func viewDidAppear(animated: Bool) {
self.loadData()
if PFUser.currentUser() == nil {
var loginAlertController = UIAlertController(title: "Sign up / login", message: "please sign up or login", preferredStyle: UIAlertControllerStyle.Alert)
loginAlertController.addTextFieldWithConfigurationHandler({
textfField in
textfField.placeholder = "Your username"
})
loginAlertController.addTextFieldWithConfigurationHandler({
textfField in
textfField.placeholder = "Your password"
textfField.secureTextEntry = true
})
// MARK: login action in the array
loginAlertController.addAction(UIAlertAction(title: "Login Action", style: UIAlertActionStyle.Default, handler: {
alertAction in
let textFields : NSArray = loginAlertController.textFields!
let usernameTextField : UITextField = textFields[0] as! UITextField
let passwordTextField : UITextField = textFields[1] as! UITextField
//MARK: Parse login problem - 15:39
PFUser.logInWithUsernameInBackground(usernameTextField.text, password: passwordTextField.text){
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
println("login success!")
} else {
println("login failed!")
}
}
}))
// MARK: sign up action in the array
loginAlertController.addAction(UIAlertAction(title: "Sign up", style: UIAlertActionStyle.Default, handler: {
alertAction in
let textFields : NSArray = loginAlertController.textFields!
let usernameTextField : UITextField = textFields[0] as! UITextField
let passwordTextField : UITextField = textFields[1] as! UITextField
var messageSender = PFUser() //16:42
messageSender.username = usernameTextField.text
messageSender.password = passwordTextField.text
messageSender.signUpInBackgroundWithBlock({
(success: Bool, error: NSError?) -> Void in
if error == nil {
println("sign up successful")
} else {
// let errorString = error!.userInfo["error"] as! String
let errorString = error!.localizedDescription
println(errorString)
}
})
}))
self.presentViewController(loginAlertController, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return timelineData.count
}
//MARK: WARNING! Cast from 'String' to unrelated type 'PFObject' always fails
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : SweetTableViewCell = tableView.dequeueReusableCellWithIdentifier("cellReuseID", forIndexPath: indexPath) as! SweetTableViewCell
var textMessage : PFObject = self.timelineData[indexPath.row] as! PFObject
cell.sweetTextView.text = textMessage["content"] as! String
return cell
}
}
您想要做的是将整个 PFObject
转换为 String
,正如编译器指出的那样,这将永远行不通。您需要做的是访问 PFObject
中包含您要获取的字符串的字段。因此,例如,在 User
class 上,电子邮件字段是一个字符串。为了从 PFUser
(PFObject
的子class)中获取它,您需要访问该字段,然后分配 that 到字符串。它看起来像这样(假装 singleObject
是 PFUser
因为我不知道你的字段):
for singleObject in objects! {
if let stringData = singleObject["email"] as? String {
timelineData.append(stringData)
}
}
另一种选择,只是语法不同。
for singleObject in objects! {
if let stringData = singleObject.objectForKey("email") as? String {
timelineData.append(stringData)
}
}
两者都会起作用,并为您提供所需的结果。
此外,作为附加点,您可以简单地调用 findTimeLineDataQuery.orderByDescending("createdAt")
,而不是在将对象放入其中后反转数组。这将为您节省一些开销,因为它会在数据返回给您之前完成,而不是在设备上完成。
编辑:修复 cellForRowAtindexPath:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : SweetTableViewCell = tableView.dequeueReusableCellWithIdentifier("cellReuseID", forIndexPath: indexPath) as! SweetTableViewCell
cell.sweetTextView?.text = self.timelineData[indexPath.row]
return cell
}
您试图转换刚从 PFObject
中取出的字符串,然后将它们转回 PFObject
。由于您现在有了要显示的文本,因此在 cellForRowAtindexPath:
中,您所要做的就是访问存储在 timelineData
数组中该位置的值。
您在这里真正想做的是投射 PFObject
的 属性 - 而不是对象本身。在下面的示例中,someProperty
是您希望访问的 Messages
对象上的字段。
它应该看起来像这样:
for singleObject in objects! {
var someProperty = singleObject["somePropertyName"] as String
self.timelineData.append(someProperty)
}