Updating SwiftyJSON object created from an Alamofire request

时间:2015-07-28 17:03:17

标签: swift alamofire swifty-json

I'm trying to display some JSON data pulled from a website in a table view. Initially, everything works great. I declare my JSON data as an instance varable:

var tableData:JSON!
{
    didSet
    {
        tableView.reloadData()
    }
}

And then I make my request somewhere-- viewDidLoad or viewWillAppear or via the user pulling down on the tableView to refresh or whatever, doesn't really matter-- set the data, and the table gets reloaded. Everything works great.

request(method, url, parameters: parameters, encoding: ParameterEncoding.URL).responseJSON(options: NSJSONReadingOptions.AllowFragments) { (request, response, json, error) -> Void in
            self.tableData = JSON(json!)
        }

However, sometimes I don't just want to display the data, but I want to let the user update the data, for example, in a textField. And here's where I'm running into problems.

So I've created a table view cell with a text field, filled it with some text pulled from my tableData JSON, so far so good. My user can then change the text field, and I want to update the tableData via the text field's delegate methods. This is not working for me.

func textFieldDidEndEditing(textField: UITextField)
{
    let key = "anExampleKey"
    tableData[key] = JSON(textField.text)
    println(tableData[key]) // the original value, not textField.text
}

Nothing seems to happen, the tableData value for "anExampleKey" remains unchanged. So, if that cell scrolls off the screen for example and then comes back into view, any changes my user has made are lost and it reverts back to the original value.

This seems to be an issue solely with a JSON value created from an Alamofire request however. For example, if I do this:

func textFieldDidEndEditing(textField: UITextField)
{
    let key = "anExampleKey"
    var json = JSON([key:tableData[key].stringValue])
    tableData[key] = JSON(textField.text)
    json[key] = JSON(textField.text)
    println(tableData[key]) // the original value, not textField.text
    println(json[key]) // textField.text
}

The json variable will be updated to reflect the textField, while the tableData will still have its original value, not what's in the textField. Does anyone know why the JSON object made via the Alamofire request is immutable, whereas one created directly from a dictionary is not?

1 个答案:

答案 0 :(得分:1)

好的,我明白了。它与SwiftyJSON或Alamofire无关,而是我将我的实例变量声明为可选的unwrapped。我仍然不完全确定可选和隐式解包变量的所有规则,但使用常规JSON变量而不是JSON!允许我更新它。

var tableData:JSON! /* won't update */
var tableData:JSON = JSON([:]) /* will update */ 

我不知道为什么会这样。我以为我现在已经围绕Swift可选和隐式解开的规则,但我猜不是。它几乎就像我每次隐式打开JSON一样!变量,它创建一个新副本并更新它,保持实例变量不变。我启动了一个游乐场,看看对于所有隐式展开的结构是否都是真的,但事实并非如此,我可以在那里更新一个隐式展开的结构的实例值。有趣的,可选的JSON?值会更新。

struct Test
{
    var myVar = 0
}

var myTest:Test!

myTest = Test() /* myVar = 0 */
myTest.myVar = 7 /* myVar = 7 */
myTest.myVar /* myVar = 7 still */

var implicitlyUnwrappedJSON:JSON!
implicitlyUnwrappedJSON = JSON(["Test":"This is one"])
implicitlyUnwrappedJSON["Test"] = "This is another one"
implicitlyUnwrappedJSON["Test"].string /* This is one */
implicitlyUnwrappedJSON?["Test"] = "This is another one"
implicitlyUnwrappedJSON["Test"].string /* This is another one */
implicitlyUnwrappedJSON!["Test"] = "This is another one yet"
implicitlyUnwrappedJSON["Test"].string /* This is another one yet */

var optionalJSON:JSON?
optionalJSON = JSON(["Test":"This is one"])
optionalJSON?["Test"] = "This is another one"
optionalJSON?["Test"].string /* This is another one */
optionalJSON!["Test"] = "This is another one yet"
optionalJSON!["Test"].string /* This is another one yet */

var json:JSON = JSON(["Test":"This is one"])
json["Test"] = "This is another one"
json["Test"].string /* This is another one */

所以我不知道这里发生了什么,但我有它的工作。