3

I have an app that returns a menu of information (basically menus, menu_headers, and items). I'd like to have something like this:

EKMenu.getMenu(menu_id: Int)

that would return a menu but I think I would need a completion handler in here.

I currently have:

class func getMenu(menu_id: Int){
//class func getMenu(menu_id: Int, completionHandler:(NSArray -> Void)){

  let url="https://www.example.com/arc/v1/api/menus/\(menu_id)/mobile"
  Alamofire.request(.GET, url).responseJSON() {
    (_, _, data, _) in
    println("within menu request")
    var json=JSON(data!)
    var menu=EKMenu()
    menu.name=json["menu"]["name"].stringValue
    for (key, subJson) in json["menu"]["menu_headers"]{
      EKMenu.processMenuHeaders(subJson)
    }
    // how would we return a value here ?????
  }
}

  class func processMenuHeaders(menu_header: JSON){
    let mh_name=menu_header["name"].stringValue
    println("mh_name: \(mh_name)")
    for (key, subJson) in menu_header["menu_headers"]{
      EKMenu.processMenuHeaders(subJson)
    }
  }

but how do I actually return something here? I am 99% sure that it's some type of completion handler but, being new to Swift and Alamofire, I'm a bit lost. I've seen I won't be able to return a value with Alamofire in Swift but know that some of this is going out of date very quickly (ie Swift 1.1)

halfer
  • 19,824
  • 17
  • 99
  • 186
timpone
  • 19,235
  • 36
  • 121
  • 211
  • You can use the completion handler technique explained in the link you give, nothing obsolete there (you just have to adapt a few details for Swift 2 but Xcode will assist you anyway). – Eric Aya Jun 11 '15 at 08:13
  • 1
    looks a lot different to me – timpone Jun 11 '15 at 08:17

1 Answers1

5

An example of a completion handler for your getMenu function, assuming menu is the value you want to "return":

class MenuManager {

    // the handler takes an EKMenu argument
    class func getMenu(menu_id: Int, completionHandler: (menu: EKMenu) -> ()) {

        let url="https://www.domain.com/arc/v1/api/menus/\(menu_id)/mobile"
        Alamofire.request(.GET, url).responseJSON() {
            (_, _, data, _) in
            println("within menu request")
            var json=JSON(data!)
            var menu=EKMenu()
            menu.name=json["menu"]["name"].stringValue
            for (key, subJson) in json["menu"]["menu_headers"]{
                EKMenu.processMenuHeaders(subJson)
            }

            // wrap the resulting EKMenu in the handler
            completionHandler(menu)

        }
    }

    class func processMenuHeaders(menu_header: JSON){
        let mh_name=menu_header["name"].stringValue
        println("mh_name: \(mh_name)")
        for (key, subJson) in menu_header["menu_headers"]{
            EKMenu.processMenuHeaders(subJson)
        }
    }

}

MenuManager.getMenu(42, completionHandler: { menu in
    // here the handler gives you back the value
    println(menu)
})
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • thx! this is really helpful. One quick question. The MenuManager will really be instantining and returning a single menu. I tried to create it in getMenu but need to access it also in processMenuHeaders - what would you suggest as a strategy for this. Traditionally, in a non-async environment, I would assign to menu_headers and return the results but probably not possible here. Can I have a instance variable of menu menu for this class? Sorry, this is the one part of Swift that I feel is hard to grok. In CA so it's 2 in morning and going to sleep soon. Thx again – timpone Jun 11 '15 at 08:42
  • To answer your comment more directly: I've made this `MenuManager` class *just as an example*. You can use a completion handler for your `getMenu` function in any situation you want, with class functions, instance methods, it doesn't matter. – Eric Aya Jun 11 '15 at 08:47
  • 1
    Thx, really appreciate! – timpone Jun 11 '15 at 13:24