swiftasynchronousclosurescompletionhandlerhaneke

How to return values from Haneke's async fetch method


I'm trying to parse some data that I cached using Haneke Swift. I've cached the data and have written the parser to accomplish this. This parser is in a separate class called AssembleCalendar().

Using Haneke's example code for fetching, I've tried with complete and utter failure to actually return a value from the closure.

My attempt

func getScheduledItems() -> [ScheduledItem] {
    
    var scheduledItem = [ScheduledItem]() // initialize array

    let cache = Shared.dataCache
    cache.fetch(key: "CalendarData").onSuccess { data in
        
        scheduledItem = AssembleCalendar().assimilate(data) // update array
        print(scheduledItem) // array returns expected value
        
    }

    print(scheduledItem) // array returns nil
    return scheduledItem // returns nil
}

What I know

I understand that this is an asynchronous issue. My code isn't waiting for my AssembleCalendar() parser to finish. It's just running each line and returns nil long before my scheduledItem receives a value. I've tried many, many solutions and read quite a few examples online but I cannot figure out how to retrieve a value from this closure in this scenario.

My question

How can I get .fetch() to return a value before my function hits nil?


update:

Here's my code in context:

class Schedule {

    var items : [ScheduledItem]
    
    init() {
        items = getScheduledItems() // Schedule.getScheduledItems()
    }
    
    func getScheduledItems(completion: (items: [ScheduledItem]) -> ()) {
        
        var scheduledItem = [ScheduledItem]() // initialize array
        
        let cache = Shared.dataCache
        cache.fetch(key: "CalendarData").onSuccess { data in
            
            scheduledItem = AssembleCalendar().assimilate(data) // update array
            print(scheduledItem) // array returns expected value
            completion(items: scheduledItem)
            
        }
    }
}

Solution

  • Fetch() is using a completion handler, this means that the block of code called in there is actually executing AFTER your return statement has been executed. This is why it is returning nil. To get around this, you can use your own completion handler to return the information:

    class Schedule {
    
        var items = [ScheduledItem]()
    
        init(items: [ScheduledItem]) {
            self.items = items
        }
    
        class func getScheduledItems(completion: (items: [ScheduledItem]) -> ()) {
    
            var scheduledItem = [ScheduledItem]() // initialize array
    
            let cache = Shared.dataCache
            cache.fetch(key: "CalendarData").onSuccess { data in
    
                scheduledItem = AssembleCalendar().assimilate(data) // update array
                print(scheduledItem) // array returns expected value
                completion(items: scheduledItem)
    
            }
        }
    }
    

    Then initialise the class using this:

    Schedule.getScheduledItems { (items) -> () in
        var schedule = Schedule(items: items)
    }