1

I created this basic architecture to handle my networking stuff,

i wanted to keep it modular and structured:

public class NetworkManager {

    public private(set) var queue: DispatchQueue = DispatchQueue(label: "com.example.app.dispatchgroups", attributes: .concurrent, target: .main)
    public private(set) var dispatchGroup: DispatchGroup = DispatchGroup()

    private static var sharedNetworkManager: NetworkManager = {
        let networkManager = NetworkManager()
        return networkManager
    }()

    private init() {}

    class func shared() -> NetworkManager {
        return sharedNetworkManager
    }

    public func getData() {
        dispatchGroup.enter()

        queue.async(group: dispatchGroup) {
            Alamofire.request(Content.url).responseJSON { response in
                switch response.result {
                case .success(let value):
                    let json = JSON(value)
                    // do some stuff and save to Content struct
                    Content.annotations += [Station(...)]

                case .failure(let error):
                    print("error: ",error)
                }
            }

            self.dispatchGroup.leave()
        }
    }

}

struct Content {

    static var url = "url"

    static var annotations = [Station]()

}

So when i call this in my seperate class:

class MainViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // some stuff ...

        NetworkManager.shared().getData()

        NetworkManager.shared().dispatchGroup.notify(queue: DispatchQueue.main) {
            self.mapView.removeAnnotations(Content.annotations)
            self.mapView.addAnnotations(Content.annotations)
        }
    }

}

Buuut, it seems like DispatchGroup().notify() is executed before all requests finished... because no annotations are added to mapview.

I already checked and annotations are loaded.

Anybody could help me with this architecture?

Thanks and Greetings!

Creative crypter
  • 1,348
  • 6
  • 30
  • 67
  • i changed it to: networkManager.getDispatchGroup().notify(queue: DispatchQueue.main) { .. } but its still the same.. any suggestion? – Creative crypter Jan 14 '17 at 21:10
  • 1
    @Creativecrypter You should declare your dispatchGroup as: `public private(set) var dispatchGroup: DispatchGroup`. There's no point making a computed property to return a property. Just use the property directly, and set its setter to private. – Alexander Jan 14 '17 at 21:34
  • hi, i changed my code to a singleton and included your change, still the same result :/ can you check? – Creative crypter Jan 14 '17 at 21:42
  • 1
    Unrelated to your problem (which seems to be answered now), but you can simplify your shared property to `private static var sharedNetworkManager = NetworkManager()`. – Martin R Jan 14 '17 at 21:59

2 Answers2

4

I think you need to put self.dispatchGroup.leave() inside the Alamofire response handler. As written, you leave as soon as you queue the request.

    queue.async(group: dispatchGroup) {
        Alamofire.request(Content.url).responseJSON { response in
            switch response.result {
            case .success(let value):
                let json = JSON(value)
                // do some stuff and save to Content struct
                Content.annotations += [Station(...)]

            case .failure(let error):
                print("error: ",error)
            }
            self.dispatchGroup.leave()
        }
    }
Jon Brooks
  • 2,472
  • 24
  • 32
1

Change your code as shown below.

public func getData() {
    dispatchGroup.enter()
    queue.async(group: dispatchGroup) {
        Alamofire.request(Content.url).responseJSON { response in
            switch response.result {
            case .success(let value):
                let json = JSON(value)
                // do some stuff and save to Content struct
                Content.annotations += [Station(...)]

            case .failure(let error):
                print("error: ",error)
            }
            self.dispatchGroup.leave() // This statement has been moved
        }
    }
}

The mistake was that you were leaving the DispatchGroup soon after you entered it. If you have to wait for your network operation to complete, you should leave from within the response handler.