无法更改全局变量的值

时间:2015-06-09 01:36:53

标签: ios swift scope

我刚刚使用Alamofire和SwiftyJSON编写了一些用于访问Riot API的Swift代码。

我写了一个函数func getIDbyName(SummName: String) -> String来获取召唤者的身份。

从下面的代码中可以看出,我将ID分配给self.SummID

执行该功能后,我可以println正确的ID,例如"1234567"。但是,return self.SummID会返回"0",与开头分配的相同。

我试图弄乱代码,但我无法在self.SummID闭包之外得到Alamofire.request的正确值。它总是在"0"外的任何地方。

我认为它与变量的范围有关。有谁知道这里发生了什么?

import Foundation

import Alamofire
import SwiftyJSON

class SummInfo {
    var SummName = "ThreeSmokingGuns"
    var SummID = "0"

    var SummChamp = "akali"
    var SummS1 = "flash"
    var SummS2 = "ignite"
    var SummRank = "Unranked"
    var SummWR = "-"        //summoner's winrate

    let api_key = "key"
    let URLinsert = "?api_key="

    init(SummName: String, SummChamp: String, SummS1: String, SummS2: String, SummRank: String, SummWR: String) {

        self.SummName = SummName
        self.SummChamp = SummChamp
        self.SummS1 = SummS1
        self.SummS2 = SummS2
        self.SummRank = SummRank
        self.SummWR = SummWR


    }

    init(SummName: String) {
        self.SummName = SummName
    }

    func getIDbyName(SummName: String) -> String
    {
        let SummURL = "https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/"

        var fullURL = "\(SummURL)\(SummName)\(URLinsert)\(api_key)"

        Alamofire.request(.GET, fullURL)
            .responseJSON { (request, response, data, error) in
                if let anError = error
                {
                    // got an error in getting the data, need to handle it
                    println("error calling GET on /posts/1")
                    println(error)
                }
                else if let data: AnyObject = data // hate this but responseJSON gives us AnyObject? while JSON() expects AnyObject
                    // JSON(data!) will crash if we get back empty data, so we keep the one ugly unwrapping line

                {
                    // handle the results as JSON, without a bunch of nested if loops
                    let post = JSON(data)
                    self.tempJ = post
                    var key = post.dictionaryValue.keys.array //not necessary
                    var key2 = post[SummName.lowercaseString].dictionaryValue.keys.array
                    self.SummID = post[key[0],key2[2]].stringValue  //[profileIconId, revisionDate, id, summonerLevel, name]


                    //test console output

                    println("The post is: \(post.description)")
                    println(SummName.lowercaseString)
                    println(key)
                    println(key2)
                    println(self.SummID)


                }


        }
      return self.SummID
    }
}

1 个答案:

答案 0 :(得分:1)

原因是

Alamofire.request(.GET, fullURL)
            .responseJSON

是异步调用。这意味着对getIDbyName的调用将立即返回,而无需等待responseJSON完成。这就是为什么你得到一个' 0'您最初设置的ID的值。

话虽如此,解决方案是在 getIDbyName 方法中进行回调关闭:

 func getIDbyName(SummName: String, callback: (id:String?) ->() ) -> ()
{
        let SummURL = "https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/"

        var fullURL = "\(SummURL)\(SummName)\(URLinsert)\(api_key)"

        Alamofire.request(.GET, fullURL)
            .responseJSON { (request, response, data, error) in
                if let anError = error
                {
                    // got an error in getting the data, need to handle it
                    println("error calling GET on /posts/1")
                    println(error)
                    //Call back closure with nil value  
                    callback(nil)  //Can additionally think of passing actual error also here


                }
                else if let data: AnyObject = data // hate this but responseJSON gives us AnyObject? while JSON() expects AnyObject
                    // JSON(data!) will crash if we get back empty data, so we keep the one ugly unwrapping line

                {
                    // handle the results as JSON, without a bunch of nested if loops
                    let post = JSON(data)
                    self.tempJ = post
                    var key = post.dictionaryValue.keys.array //not necessary
                    var key2 = post[SummName.lowercaseString].dictionaryValue.keys.array
                    self.SummID = post[key[0],key2[2]].stringValue  //[profileIconId, revisionDate, id, summonerLevel, name]


                    //test console output

                    println("The post is: \(post.description)")
                    println(SummName.lowercaseString)
                    println(key)
                    println(key2)
                    println(self.SummID)
                    //Pass the actual ID got.
                    callback(self.SummID)
                }


        }
      return self.SummID
    }

客户端应始终使用此API来获取最新的ID,并且可以直接引用该属性以获取SummID成员中到目前为止缓存的任何内容。

以下是如何调用此方法 -

object.getIDbyName(sumName){ (idString :String) in

      //Do whatever with the idString

}