Home

Awesome

EasyCalls

Build Status codecov.io codebeat badge Version Platform GitHub license GitHub forks GitHub stars

Hi there,

This repository contains a number of methods over Swift API to use it safely. <br />

Contents

Queues

These methods are used to dispatch execution to the specified queue.

DispatchQueue.toMain {
    // update UI
}

DispatchQueue.toBackground {
    // load data
}

DispatchQueue.runAfter(time: 1) {
    // performs work on the main queue after 1 sec
}

Customization

DispatchQueue.toBackground(qos: .utility) { // Separate queue }

DispatchQueue.toBackground(label: "",
              qos: .background,
              attr: .concurrent,
              frequency: .inherit,
              target: DispatchQueue.global()) { // Separate queue }
DispatchQueue.runAfter(time: 1) { // Main thread }

DispatchQueue.runAfter(time: 1, qos: .userInteractive) { // Separate queue }

DispatchQueue.runAfter(time: 1,
              qos: .userInteractive,
              attr: .concurrent,
              frequency: .inherit,
              target: DispatchQueue.global()) { // Separate queue }

DispatchQueue.toMain <br />

DispatchQueue.toMain call safely dispatches execution to the main queue.<br /><br /> Since being on the main thread does not guarantee to be on the main queue, the DispatchQueue.toMain call checks whether the current queue is main. The operations of the main queue are always executed on the main thread.<br /> As described in the libdispatch, dispatch_sync performs work on the current queue. It can cause a situation when the main queue will wait for completion of another sync operation.

Here is an example when the main thread is able to execute operations from other queues:

DispatchQueue.main.async {
    // Main Queue
    DispatchQueue(label: "").sync {
        // Background Queue
        
        if Thread.isMainThread {
            // The thread is Main, but the current queue is NOT Main.
            // UI should NOT be updated here.
            
            // The 'DispatchQueue.toMain' call prevents this situation.
        }
    }
}

To sum up, DispatchQueue.toMain guarantees that the passed block will be executed on the main queue and, therefore, on the main thread. In addition, if the current queue and thread are not main, the operation will be synchronously added to the main queue to prevent a race condition.

DispatchQueue.toBackground

DispatchQueue.toBackground asynchronously dispatches an execution to the separate queue with default QoS.

DispatchQueue.runAfter

The DispatchQueue.runAfter(time: 1) call performs a block on the main queue after the passed time.<br /> However, runAfter(time: qos:) with specified QoS performs the given block on the separate queue. Do not update UI on it.

Swift Errors Handling

The syntactic sugar methods help to make the code more clear.

tryCatch({
    try call()
})
tryCatch({
    try call()
    try anotherCall()
}) { error in
    // handle an error
}

These are simple wrappers over the Optional type.

if error.isExist {
    // handle
}

if error.isNil {
    // success
}

Realm

Realm.read(transaction: { realm in
    // use realm
})

Realm.write(transaction: { realm in
    // use realm
})

The safe write transaction:

The error handling is also supported by attaching an error closure.

UIAlertController

There is a number of calls to present UIAlertController (including ActionSheet)<br />

// Alert
show(title: "Title", actions: Action.ok)

// ActionSheet
show(title: "Action Sheet", style: .actionSheet, actions: Action.ok)
// Alert with Message
show(message: "Message", actions: Action.ok, Action.cancel)

// Alert with Title and Message, Ok and Cancel buttons
show(title: "Title", message: "Message", actions: Action.ok, Action.cancel)

Actions Handling

let ok = Action.ok { _ in
    // handle ok
}

let cancel = Action.cancel { _ in
    // handle cancel
}

show(title: "Alert with ok/cancel buttons", actions: cancel, ok)

The Action factory can be used to create a UIAlertAction or you can pass your own.

let next = Action.with(title: "Next") { action in
    // handle
}

let delete = UIAlertAction(title: "Delete", style: .destructive) { _ in
    // handle
}

show(title: "Are you sure?", actions: next, delete)

Full control on the alert presentation

show(title: "Title", message: "Message", style: .actionSheet, completion: {
    // That is called when the alert has been presented
}, actions: [action])

Please note, the actions parameter takes Array of actions instead of a variadic function

Presentation of the custom alert

let alert = UIAlertController()

// configure

show(alert: , {
    /* handle */
})

The Configuration model provides an ability to override defaults for localization or other reasons.

public struct Configuration {
    public static var ok: String = "OK"
    public static var cancel: String = "Cancel"

    public struct Action {
        public static var defaultStyle = UIAlertActionStyle.default
        public static var cancelStyle = UIAlertActionStyle.cancel
    }
    public struct Alert {
        public static var style = UIAlertControllerStyle.alert
    }
}

Installation

Do not forget to import the module

import EasyCalls

CocoaPods

EasyCalls is available through CocoaPods.

Each module works independently so you can install the modules you need right now


pod 'EasyCalls/TryCatch'
pod 'EasyCalls/Queues'
pod 'EasyCalls/Realm'
pod 'EasyCalls/Alert'


pod 'EasyCalls' # contains 'TryCatch' and 'Queues' by default

Manually

$ git init
$ git submodule add https://github.com/devmeremenko/EasyCalls.git

Change Log

Version is the same for CocoaPods and GitTag.

VersionFunctionDescriptionMigration
1.2.1QueuesExtensions for DispatchQueue were used instead of global functions.<br /><br /> The SpecificKey for the main queue is set only once now.Please add DispatchQueue. expression before all toMain, toBackground, and runAfter calls.
1.1.1AlertEasyCalls/Alert were added

Author

Maksym Eremenko, devmeremenko@gmail.com

License

EasyCalls is available under the MIT license.

# Copyright (c) 2018 Maxim Eremenko <devmeremenko@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.