0

Function

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
    }

}

If I run this code in Xcode, I get the result below:

000000

fid -> 140

fname -> 밀 흑밀

hits -> nil

delegate_image -> ./pic_data/2309/20180423201954alj

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

fid ==== nil
fid ==== nil

I want to return [var foods: Array?] value. But although I made some values of Foods struct and used append function of Array in order to add Foods value into Array, it didn't works. There is no value in Array, only nil.(fid ==== nil) Thus, it is useless to return that Array.

How can I get right results?

I need to get values like below:

fid ==== 140
fid ==== 140

Please help me to solve this problem. I think I used Optional wrongly.

4 Answers 4

1

Main problem is you did not initiate your foods array.

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

You can initiate your array here and return empty list as a result if there is no food for the ID.

And rename your Foods struct with Food and Food class with something like FoodOperations. This would make more sense.

Read this for swift guides.

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

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

print ("fid ==== ", foods.first?.fid ?? 0)
Sign up to request clarification or add additional context in comments.

1 Comment

Right.. I forgot it. Thank you, I changed it, but my code still has a problem with 'return'.
1

Better make a model class to store data. For example:

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

Then after getting result do something like this :

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)

And suggested by Francesco Deliro, use completion handler to return values when your for loop is done. In your case return statement is getting called before for loop ends.

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

1 Comment

Don't make a class inherit from NSObject for no reason, Swift is not Objective-C, classes don't need to inherit from a base class. Moreover, your a struct unless you explicitly need reference type behaviour/inheritance and make the variables immutable unless they need to be mutable.
0

You need to change your function implementation adding a completion handler, because your return is called before the for loop is ended:

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()
}

And you can use it in this way:

//where you have to make the call
self.getFoodsById(yourId) { (foodsArray, error) in
    //here you can manage your foods array
}

2 Comments

Thank you! But I've never used Completion Handler, so I don't know how to call it. Could you show me an example?
@SoonmyunJang I have edited my answer to show how you can use the completion handler ;)
0

Declare Struct

struct AlertModel { var alert:String var title:String }

Create Variable

var alertData = AlertModel

Append data

let alert = AlertModel(alert: "Waring", title: "Over Load") alertData.append(alert)
print(alertData)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.