2015-06-09 5 views
0

Я только что написал код Swift для доступа к API Riot с помощью Alamofire и SwiftyJSON.Невозможно изменить значение глобальной переменной

Я написал функцию func getIDbyName(SummName: String) -> String, чтобы получить идентификатор summoner.

Как вы можете видеть из приведенного ниже кода, я назначаю идентификатор self.SummID.

После выполнения функции, я могу указать println правильный идентификатор, например "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 
    } 
} 
+0

SummID является свойством класса SummInfo, так что не нужно возвращаться из getIDbyName. Также вам не нужны все эти «я». Ссылки за пределами init - они скрыты в Swift. Но в остальном он выглядит нормально. Где вы проверяете значение SummID и находите его еще «0? Проблема может быть там. –

+0

Большое спасибо. Я просто помещаю println() в разные точки, чтобы проверять, а также точки останова. Возвращение SummID действительно отчаянно пытаюсь получить нужные данные. –

ответ

1

Причина заключается в том, что

Alamofire.request(.GET, fullURL) 
      .responseJSON 

представляет собой асинхронный вызов. Это означает, что вызов getIDbyName немедленно вернется, не дожидаясь завершения ответаJSON. Это точная причина, по которой вы получаете значение «0» для идентификатора, который вы установили изначально.

Сказав, что решение должны иметь обратный вызов замыкание в 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 

} 
+0

Большое вам спасибо. Я прочитал некоторые другие вопросы об асинхронном вызове, но я как-то вроде noob при решении проблемы. У вас есть решение для получения данных. –

+0

I отредактировали мой ответ, который решает проблему. Пожалуйста, взгляните. – Shripada

Смежные вопросы