Как добавить структуру в массив? Swift4 - PullRequest
0 голосов
/ 30 апреля 2018

Функция

import Foundation

struct Foods {
    var fid: Int
    var fname: String
    var hits: Int?
    var addr: String?
}

class Food {

    func getFoodsById(_ fid: Int) -> [Foods]? {
        var foods: Array<Foods>?
        let URL_GET_TEAMS:String = "http://jsm0803.iptime.org:81/html/sufoo/getFoodById.php"
        let requestURL = URL(string: URL_GET_TEAMS)

        let request = NSMutableURLRequest(url: requestURL!)

        request.httpMethod = "POST"
        //request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        let postParameters = "Fid=" + String(fid)
           // "name="+teamName!+"&member="+memberCount!;

        request.httpBody = postParameters.data(using: String.Encoding.utf8)


        let task = URLSession.shared.dataTask(with: request as URLRequest){data, response, error in

            if error != nil{
                print("error is \(error)")
                return;
            }
            let dataString = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) // 테스트용
            //print(dataString!)


            do{
                var itemJSON: Dictionary<String, Any>!
                itemJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? Dictionary


                let items:Array<Dictionary<String, Any>> = itemJSON["Food"] as! Array

                for i in 0 ..< items.count{
                    var food: Foods
                    let item = items[i]

                    let fid:Int = item["Fid"] as! Int
                    let fname: String = item["Fname"] as! String
                    let hits: Int? = item["Hits"] as? Int
                    let delegate_image:String? = item["Delegate_Image"]as? String

                    food = Foods(fid: fid, fname: fname, hits: hits, addr: delegate_image)

                    foods?.append(food)



                    print("fid ->", food.fid)
                    print("fname ->", food.fname)
                    if let f = food.hits {
                        print("hits ->", f)
                    }
                    else{
                        print("hits ->", food.hits as Any)
                    }
                    if let f = food.addr {
                        print("delegate_image -> ", f)
                    }
                    else {
                        print("delegate_image -> ", food.addr as Any)
                    }

                    print("==============")
                    print("")

                    print ("fid ==== ", foods?.first?.fid)
                    print ("fid ==== ", foods?.last?.fid)

                }
            }catch {
                print(error)
            }
        }
        task.resume()

        if let result = foods{
            for r in result{
                print ("r.fname")
                print (r.fname)
            }
        }
        print ("000000")
        return foods
    }

}

Если я запускаю этот код в XCode, я получаю результат ниже:

000000

фид -> 140

имя -> 밀 흑밀

попаданий -> ноль

Delegate_image -> ./pic_data/2309/20180423201954alj

==============

fid ==== ноль
FID ==== ноль

Я хочу вернуть значение [var foods: Array?]. Но хотя я сделал некоторые значения структуры Foods и использовал функцию добавления Array для добавления значения Foods в Array, это не сработало. В массиве нет значения, только ноль. (Fid ==== ноль) Таким образом, возвращать этот массив бесполезно.

Как я могу получить правильные результаты?

Мне нужно получить значения, как показано ниже:

fid ==== 140
фид ==== 140

Пожалуйста, помогите мне решить эту проблему. Я думаю, что использовал Optional неправильно.

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

Вам нужно изменить реализацию функции, добавив обработчик завершения, потому что ваш вызов вызывается до завершения цикла for:

func getFoodsById(_ fid: Int, completion: (([Foods]?, Error?) -> Void)?) {

    //your precedent code
    //then when you make the request call the completion

    let task = URLSession.shared.dataTask(with: request as URLRequest){data, response, error in

        guard error == nil else {
            completion?(nil, error)
            return
        }
        let dataString = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) // 테스트용
        //print(dataString!)


        do{
            var itemJSON: Dictionary<String, Any>!
            itemJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? Dictionary


            let items:Array<Dictionary<String, Any>> = itemJSON["Food"] as! Array

            for i in 0 ..< items.count{
                var food: Foods
                let item = items[i]

                let fid:Int = item["Fid"] as! Int
                let fname: String = item["Fname"] as! String
                let hits: Int? = item["Hits"] as? Int
                let delegate_image:String? = item["Delegate_Image"]as? String

                food = Foods(fid: fid, fname: fname, hits: hits, addr: delegate_image)

                foods?.append(food)



                print("fid ->", food.fid)
                print("fname ->", food.fname)
                if let f = food.hits {
                    print("hits ->", f)
                }
                else{
                    print("hits ->", food.hits as Any)
                }
                if let f = food.addr {
                    print("delegate_image -> ", f)
                }
                else {
                    print("delegate_image -> ", food.addr as Any)
                }

                print("==============")
                print("")

                print ("fid ==== ", foods?.first?.fid)
                print ("fid ==== ", foods?.last?.fid)

            }
            completion?(foods, nil)
        }catch {
            print(error)
            completion?(nil, error)
        }
    }
    task.resume()
}

И вы можете использовать его следующим образом:

//where you have to make the call
self.getFoodsById(yourId) { (foodsArray, error) in
    //here you can manage your foods array
}
0 голосов
/ 30 апреля 2018

Основная проблема в том, что вы не инициировали набор продуктов.

//func getFoodsById(_ fid: Int) -> [Foods]? {
func getFoodsById(_ fid: Int) -> [Foods] {
    //var foods: Array<Foods>?
    var foods = [Foods]() // or  var foods: [Foods] = []

Вы можете инициировать свой массив здесь и возвращать пустой список в результате, если для идентификатора нет еды.

И переименуйте свою структуру Foods с помощью класса Food and Food с помощью чего-то вроде FoodOperations. Это имело бы больше смысла.

Считайте это для быстрых направляющих.

struct Food {
    ...
}
class FoodOperations {
    ...
}

if let error = error {
   print("error is \(error)")
   return;
}

print ("fid ==== ", foods.first?.fid ?? 0)
0 голосов
/ 30 апреля 2018

Лучше сделать класс модели для хранения данных. Например:

class Food {
  var fid: Int
  var fname: String
  var hits: Int?
  var addr: String?
}

Затем после получения результата сделайте что-то вроде этого:

var foodArray = [Foods]()
for item in items {
   let food = Food()
   guard let food.fid = item["Fid"] as? Int else {return}
   foodArray.append(food)
}
print(foodArray)

По предложению Франческо Делиро, используйте обработчик завершения, чтобы возвращать значения, когда цикл for выполнен. В вашем случае оператор return вызывается раньше для завершения цикла.

Also don't do force unwrapping, try to use if let/ guard let .
...