Jamel  O'Reilly

Jamel O'Reilly

1656393360

AsyncNinja: Concurrency and Reactive Programming on Swift

A complete set of primitives for concurrency and reactive programming on Swift

  • 1.4.0 is the latest and greatest, but only for Swift 4.2 and 5.0
  • use 1.3.0 is for Swift 4.0+
  • use 1.2.4 for latest release for Swift 3
 Features
🦄 
powerful primitives
Future, Promise, Channel, Producer, Sink, Cache, ...
🤘 
versatile transformations
map, filter, recover, debounce, distinct, ...
✌️ 
convenient combination
flatMap, merge, zip, sample, scan, reduce, ...
🙌 
improves existing things
Key-Value Observing, target-action, notifications, bindings
🍳 
less boilerplate code
neat cancellation, threading, memory manament
🕶 
extendable
powerful extensions for URLSession, UI controls, CoreData, ...
🍱 
all platforms 
 
🖥 macOS 10.10+ 📱 iOS 8.0+ 📺 tvOS 9.0+ ⌚️ watchOS 2.0+ 🐧 Linux
🤓 
documentation
100% + sample code, see full documentation
🔩 
simple integration
SPM, CocoaPods, Carthage
  • Related articles
  • Known users

Reactive Programming

reactive properties

let searchResults = searchBar.rp.text
  .debounce(interval: 0.3)
  .distinct()
  .flatMap(behavior: .keepLatestTransform) { (query) -> Future<[SearchResult]> in
    return query.isEmpty
      ? .just([])
      : searchGitHub(query: query).recover([])
  }

bindings

  • unbinds automatically
  • dispatches to a correct queue automatically
  • no .observeOn(MainScheduler.instance) and .disposed(by: disposeBag)
class MyViewController: UIViewController {
  /* ... */
  @IBOutlet weak var myLabel: UILabel!

  override func viewDidLoad() {
    super.viewDidLoad()
    UIDevice.current.rp.orientation
      .map { $0.description }
      .bind(myLabel.rp.text)
  }
  
  /* ... */
}

contexts usage

  • no [weak self]
  • no DispatchQueue.main.async { ... }
  • no .observeOn(MainScheduler.instance)
class MyViewController: NSViewController {
  let service: MyService

  /* ... */
  
  func fetchAndPresentItems(for request: Request) {
    service.perform(request: request)
      .map(context: self, executor: .primary) { (self, response) in
        return self.items(from: response)
      }
      .onSuccess(context: self) { (self, items) in
        self.present(items: items)
      }
      .onFailure(context: self) { (self, error) in
        self.present(error: error)
      }
  }
  
  func items(from response: Response) throws -> [Items] {
    /* ... extract items from response ... */
  }
  
  func present(items: [Items]) {
    /* ... update UI ... */
  }
}

class MyService {
  func perform(request: Request) -> Future<Response> {
    /* ... */
  }
}

In Depth

Let's assume that we have:

  • Person is an example of a struct that contains information about the person.
  • MyService is an example of a class that serves as an entry point to the model. Works in a background.
  • MyViewController is an example of a class that manages UI-related instances. Works on the main queue.

Code on callbacks

extension MyViewController {
  func present(personWithID identifier: String) {
    myService.fetch(personWithID: identifier) {
      (person, error) in

      /* do not forget to dispatch to the main queue */
      DispatchQueue.main.async {

        /* do not forget the [weak self] */
        [weak self] in
        guard let strongSelf = self
          else { return }

        if let person = person {
          strongSelf.present(person: person)
        } else if let error = error {
          strongSelf.present(error: error)
        } else {
          fatalError("There is neither person nor error. What has happened to this world?")
        }
      }
    }
  }
}

extension MyService {
  func fetch(personWithID: String, callback: @escaping (Person?, Error?) -> Void) {
    /* ... */
  }
}
  • "do not forget" comment x2
  • the block will be retained and called even if MyViewController was already deallocated

Code with other libraries that provide futures

extension MyViewController {
  func present(personWithID identifier: String) {
    myService.fetch(personWithID: identifier)

      /* do not forget to dispatch to the main queue */
      .onComplete(executor: .main) {

        /* do not forget the [weak self] */
        [weak self] (completion) in
        if let strongSelf = self {
          completion.onSuccess(strongSelf.present(person:))
          completion.onFailure(strongSelf.present(error:))
        }
      }
  }
}

extension MyService {
  func fetch(personWithID: String) -> Future<Person> {
    /* ... */
  }
}
  • "do not forget" comment x2
  • the block will be retained and called even if MyViewController was already deallocated

Code with AsyncNinja

extension MyViewController {
  func present(personWithID identifier: String) {
    myService.fetch(personWithID: identifier)
      .onSuccess(context: self) { (self, person) in
        self.present(person: person)
      }
      .onFailure(context: self) { (self, error) in
        self.present(error: error)
      }
  }
}

extension MyService {
  func fetch(personWithID: String) -> Future<Person> {
    /* ... */
  }
}

Using Futures

Let's assume that we have function that finds all prime numbers lesser than n

func primeNumbers(to n: Int) -> [Int] { /* ... */ }

Making future

let futurePrimeNumbers: Future<[Int]> = future { primeNumbers(to: 10_000_000) }

Applying transformation

let futureSquaredPrimeNumbers = futurePrimeNumbers
  .map { (primeNumbers) -> [Int] in
    return primeNumbers.map { (number) -> Int
      return number * number
    }
  }

Synchronously waiting for completion

if let fallibleNumbers = futurePrimeNumbers.wait(seconds: 1.0) {
  print("Number of prime numbers is \(fallibleNumbers.success?.count)")
} else {
  print("Did not calculate prime numbers yet")
}

Subscribing for completion

futurePrimeNumbers.onComplete { (falliblePrimeNumbers) in
  print("Number of prime numbers is \(falliblePrimeNumbers.success?.count)")
}

Combining futures

let futureA: Future<A> = /* ... */
let futureB: Future<B> = /* ... */
let futureC: Future<C> = /* ... */
let futureABC: Future<(A, B, C)> = zip(futureA, futureB, futureC)

Transition from callbacks-based flow to futures-based flow:

class MyService {
  /* implementation */
  
  func fetchPerson(withID personID: Person.Identifier) -> Future<Person> {
    let promise = Promise<Person>()
    self.fetchPerson(withID: personID, callback: promise.complete)
    return promise
  }
}

Transition from futures-based flow to callbacks-based flow

class MyService {
  /* implementation */
  
  func fetchPerson(withID personID: Person.Identifier,
                   callback: @escaping (Fallible<Person>) -> Void) {
    self.fetchPerson(withID: personID)
      .onComplete(callback)
  }
}

Using Channels

Let's assume we have function that returns channel of prime numbers: sends prime numbers as finds them and sends number of found numbers as completion

func makeChannelOfPrimeNumbers(to n: Int) -> Channel<Int, Int> { /* ... */ }

Applying transformation

let channelOfSquaredPrimeNumbers = channelOfPrimeNumbers
  .map { (number) -> Int in
      return number * number
    }

Synchronously iterating over update values.

for number in channelOfPrimeNumbers {
  print(number)
}

Synchronously waiting for completion

if let fallibleNumberOfPrimes = channelOfPrimeNumbers.wait(seconds: 1.0) {
  print("Number of prime numbers is \(fallibleNumberOfPrimes.success)")
} else {
  print("Did not calculate prime numbers yet")
}

Synchronously waiting for completion #2

let (primeNumbers, numberOfPrimeNumbers) = channelOfPrimeNumbers.waitForAll()

Subscribing for update

channelOfPrimeNumbers.onUpdate { print("Update: \($0)") }

Subscribing for completion

channelOfPrimeNumbers.onComplete { print("Completed: \($0)") }

Making Channel

func makeChannelOfPrimeNumbers(to n: Int) -> Channel<Int, Int> {
  return channel { (update) -> Int in
    var numberOfPrimeNumbers = 0
    var isPrime = Array(repeating: true, count: n)

    for number in 2..<n where isPrime[number] {
      numberOfPrimeNumbers += 1
      update(number)

      // updating seive
      var seiveNumber = number + number
      while seiveNumber < n {
        isPrime[seiveNumber] = false
        seiveNumber += number
      }
    }

    return numberOfPrimeNumbers
  }
}

Author: AsyncNinja
Source Code: https://github.com/AsyncNinja/AsyncNinja
License: MIT license

#ios #swift 

What is GEEK

Buddha Community

AsyncNinja: Concurrency and Reactive Programming on Swift
Houston  Sipes

Houston Sipes

1600430400

10 Free Online Resources To Learn Swift Language

Swift is a fast and efficient general-purpose programming language that provides real-time feedback and can be seamlessly incorporated into existing Objective-C code. This is why developers are able to write safer, more reliable code while saving time. It aims to be the best language that can be used for various purposes ranging from systems programming to mobile as well as desktop apps and scaling up to cloud services.

Below here, we list down the 10 best online resources to learn Swift language.

(The list is in no particular order)

#developers corner #free online resources to learn swift language #learn swift #learn swift free #learn swift online free #resources to learn swift #swift language #swift programming

Top Swift Development Companies | Top Swift Developers - TopDevelopers.co

A thoroughly researched list of top Swift developers with ratings & reviews to help find the best Swift development companies around the world.

#swift development service providers #best swift development companies #top swift development companies #swift development solutions #top swift developers #swift

Hire Dedicated Swift Developers

Want to create a native iOS application for your Startup?

Hire Dedicated Swift Developers for end-to-end services like development, migration, upgrade, testing, and support & maintenance. Trust HourlyDeveloper.io our Swift development team for iOS device apps that are high on performance and security.

Consult with experts:- https://bit.ly/2C5M6cz

#hire dedicated swift developers #swift developers #swift development company #swift development services #swift development #swift

4 Fun Reasons to Avoid Using “Primitive” Swift Types in Your Code

Here is a list of four fun reasons you should avoid using data types such as Int and String to pass along and process the data in your Swift code. And a list of alternatives to use instead, so you can write much better code with just a few small changes to your current habits.

Note: I’ll troll around a bit because technical articles can be boring.

Note that I use the word Fun in a slightly sarcastic way, as in: “Losing is Fun”.

1. Primitive types aren’t documenting your code

When you see a function definition like this one, do you instantly know what both of the String will actually be?

func getData(for identifier: String) -> String {

Here, String can be anything, both the input String and the output String. If you’re developing the code alone, you will probably remember what is the typical content of those two.

I say probably, because as any developer knows — by Monday you may not remember what the code written on Friday does. It’s something I can promise you. Give this project a few months of a break and it will be easier for you to write the thing from scratch than to try to understand “what the poet had in mind”.

To (try to) ensure the inputs and outputs stay at least a bit clear, you will need to add comments to explain the details of what you expect those Strings to actually contain.

From the above function definition alone we only know we’re looking for some identifier. We may understand from the context of the app what that may be, but what is the result of this function exactly?

Will it give us some kind of person’s name? Or maybe a large chunk of JSON data? Maybe a specific number of animal emojis such as a 🐐 and a 🐠? For no reason. But a String can be all those, so make sure that your code will handle every possible case now. I think you see my point.

In reality, nobody knows what those are until they check the actual code of the function.

We have powerful IDEs (such as Xcode), which provide developers with previews of possible completions. They are useless in this case. Imagine what you would think if you were working on someone else’s code and you stumbled upon the above definition as an Xcode suggestion. My guess is: some rude words will be included in your reaction.

You can’t understand what is happening until you check the code or documentation. And chances are, if you see this kind of String usage, you won’t find any docs for that package or pod or repository. **And also, most docs can’t be trusted because we don’t like to write docs, maintain docs and keep up with the changes in the code. **There is nothing that would force developers to keep the docs and comments in sync.

#swift #swift-programming #programming-languages #ios-app-development #programming

Brain  Crist

Brain Crist

1600095600

Diving Into Reactive Microservices

What are Monoliths?

To start explaining the microservices it’s useful to compare it to the monolithic application. An application is said to be a monolith when it is deployed as a single unit. Monoliths have a single shared database. They communicate with synchronous method calls where you send a message and expect a response immediately.

What are the cons of Monoliths?

  • Monoliths are limited by the maximum size of a single physical machine. As the monolith grows, it acquires more and more system resources.
  • They scale as far as the database allows because they often rely on a relational database which probably runs only a single instance in order to maintain consistency.

#reactive-systems #reactive-microservice #reactive-programming #reactive-architecture