【问题标题】:How convert PFObject to string? - Swift 1.2 Xcode 6.4 and Parse.com -如何将 PFObject 转换为字符串? - Swift 1.2 Xcode 6.4 和 Parse.com -
【发布时间】:2015-07-30 17:23:49
【问题描述】:

这是另一个问题的一部分,但由于最初的问题得到了答案,如果我在这里单方面面对这个问题,将来会更清楚。

编辑:添加了一个异常断点,在运行时出现了这个:

我收到此消息:从“字符串”转换为不相关类型“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
    }
}

【问题讨论】:

    标签: ios xcode swift parse-platform optional


    【解决方案1】:

    您要做的是将整个PFObject 转换为String,正如编译器指出的那样,这永远不会起作用。您需要做的是访问 PFObject 中包含您要获取的字符串的字段。例如,在User 类中,电子邮件字段是一个字符串。为了从PFUserPFObject 的子类)中获取它,您需要访问该字段,然后将 that 分配给字符串。它看起来像这样(假设singleObjectPFUser,因为我不知道你的领域):

    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 中取出的字符串转换回PFObjects。由于您现在有了要显示的文本,因此您只需在 cellForRowAtindexPath: 中访问存储在 timelineData 数组中该位置的值即可。

    【讨论】:

    • 添加了您的第一个解决方案,并解决了第一个问题!,现在仍然是来自 cellFromRowAtIndexPath 的第二条消息“从 'String' 转换为不相关类型 'PFObject' 总是失败”我有 Messages 类,上面有一个消息列解析。我应该“瞄准”该专栏,但如何?
    • 我更新了我的答案以解决您的第二个问题@biggreentree。
    • 太棒了!解决了!有没有办法让我更好地理解这种访问?例如 .sweetTextView?。如果可选项为零怎么办?在这种情况下我应该介意吗?
    • 在这种情况下,它被称为可选链。这意味着如果对象的任何部分(在本例中为 textLabel)为 nil,则在运行时它不会尝试在此之后执行任何代码,因此您不必担心 nil 的情况。在访问图像方面,我们在添加到数组之前进行了检查,所以timelineData[indexPath.row] 永远不会返回 nil。
    【解决方案2】:

    您在这里真正想要做的是投射PFObject属性 - 而不是对象本身。在下面的示例中,someProperty 是您希望访问的 Messages 对象上的字段。

    它应该看起来像这样:

    for singleObject in objects! {
        var someProperty = singleObject["somePropertyName"] as String
        self.timelineData.append(someProperty)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-23
      • 2016-08-17
      • 1970-01-01
      • 2022-11-02
      • 2019-09-29
      • 1970-01-01
      相关资源
      最近更新 更多