AsyncViewController 2.1.1

AsyncViewController 2.1.1

Maintained by Lukas Würzburger.



  • By
  • Lukas Würzburger

Flow Diagram
AsyncViewController

Swift Version Build Status CocoaPods Compatible License MIT

Contents

✍️ Description

The AsyncViewController works as a bridge between loading your data for a specific view and presenting the view controller. It presents a loading screen as long as you're waiting for a response and you can provide the destination view controllers (either for success or error) beforehand without having to put all this logic into your final view controller.

Flow Diagram

🖥 Example

The old way:

The initial motivation was to get rid of the optional object property inside of a detail view controller and also remove the logic from the detail view controller including the data loading and displaying a loading view.

Imagine a BookViewController:

class BookViewController: UIViewController {

    var book: Book?
    // Having the represented object for this view controller as an optional is inconvenient.
    
    var loadingView: LoadingView?
    // Also having the loading view in here is inconvenient since we only need it once in the beginning.
    
    init(bookId: Int) {
        super.init(...)
        
        // Load the book here
        MyLibrary.loadBook(id: bookId) { result in
            // Refresh UI
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Then you initialize your UI, first without data but after loading again with data.
    }
}

The new way:

The AsyncViewController burries the boiler plate code and provides you a handy initializer to define your asynchronous call, the view controller when it was successful, and a resolution action when it fails.

Imagine calling this from a BookShelfViewController:

func presentBookViewController(bookId: Int) {
    let asyncViewController = AsyncViewController(load: { callback in
        MyLibrary.loadBook(id: bookId, handler: callback)
    }, success: { book -> BookViewController in
        return BookViewController(book: book)
    }) { error -> AsyncViewController<BookViewController, String, Error>.FailureResolution in
        return .showViewController(ErrorViewController(error))
    }
    asyncViewController.overridesNavigationItem = true
    present(asyncViewController, animated: true)
}

🎟 Demo

Async View Controller Demo

You can find this demo app in this repository.

🔨 Customization

Error Handling:

You can provide a custom action when the loading fails. The FailureResolution enum provides a case that you can use to pass a callback.
Maybe you want to dismiss the view controller, or pop it from the navigation stack.

return .custom({ asyncViewController in
    asyncViewController.dismiss(animated: true)
})

Custom Loading View:

If you want to show your own loading view you can use any UIViewController conforming to the LoadingAnimatable protocol described here.

asyncViewController.loadingViewController = MyLoadingViewController()

Check out the Demo

💻 How to use

Cocoapods:
AsyncViewController is available on Cocoapods. Just put following line in your Podfile:

pod 'AsyncViewController'

Swift Package Manager:
Add the following to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/lukaswuerzburger/AsyncViewController.git", from: "2.1.1")
]

⚠️ Requirements

  • Swift 5+
  • iOS 9+
  • Xcode 9+

💆 Inspiration

💪 Contribute

Issues and pull requests are welcome.