Skip to content

devMEremenko/EasyCalls

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

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

DispatchQueue.toMain call safely dispatches execution to the main queue.

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.
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.
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:

  • returns the default realm instance
  • contains an autorelease pool to prevent an uncontrolled increase of the file size of database. It might happen if objects are created inside of a GCD operation. The GCD only drains the queue-level autorelease pools relatively infrequently which can result in the lifetimes of Realm objects being significantly longer.
  • updates Realm objects to the most recent data at the end of transaction.

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

UIAlertController

There is a number of calls to present UIAlertController (including ActionSheet)

  • it is implemented as an extension for UIViewController
  • uses DispatchQueue.toMain under the hood to guarantee a presentation on the main queue
  • parameters of the show() method can be combined in different ways
// 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

  • Open up Terminal, cd into your top-level project directory, and run the following command if your project is not initialized as a git repository:
$ git init
  • Add EasyCalls as a git submodule by running the following commands:
$ git submodule add https://github.com/devmeremenko/EasyCalls.git
  • Open the new EasyCalls folder, and drag the necessary sources into the Project Navigator of your project.

Change Log

Version is the same for CocoaPods and GitTag.

Version Function Description Migration
1.2.1 Queues Extensions for DispatchQueue were used instead of global functions.

The SpecificKey for the main queue is set only once now.
Please add DispatchQueue. expression before all toMain, toBackground, and runAfter calls.
1.1.1 Alert EasyCalls/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.

About

A number of methods over Swift API to use it safely.

Resources

License

Stars

Watchers

Forks

Packages

No packages published