Engineering

Creating Box that can observe updating value

We can observe the changed value of a variable. Just like this.

var name: String {
  didSet {
    // here
  }
}

DidSet is very helpful. For example, printing about changing value for debugging.
But, If you have so many variables? You may be tired typing.

So, We can use KeyPath in Swift4.
KeyPath can read or write some value.

In my approach, Wrapped by Box, then updating from KeyPath.
So, updating operations pass the same function every time.
We can add any operations in the function.

Create Box

class Box<T> {

  private var _value: T {
    get { return value }
    set { value = newValue }
  }

  private var value: T

  init(_ value: T) {
    self.value = value
  }

  func update<E>(_ value: E, _ keyPath: WritableKeyPath<T, E>) {
    let old = _value[keyPath: keyPath]
    _value[keyPath: keyPath] = value
    print("Did change value \(old) -> \(value)")
  }
}

Usage

One of the usages is below.

class State {
  var a: String = "a"
  var b: String = "b"
}

let box = Box(State())

box.update("abc", \.a)
Did change value a -> abc

Which should we use forever or whileConnected of ShareReplay?

shareReplay of RxSwift has 2 types of sharing-scope.

  • whileConnected
  • forever

So, I've tried both sharing scopes.

shareReplay makes Observable Stateful.

The sharing-scopes indicate stateful that how long is it.

import RxSwift

print(".whileConnected, if it has subscribers that are subscribing forever")

do {
  let subject = PublishSubject<Int>()

  let s = subject.share(replay: 1, scope: .whileConnected)

  s.subscribe()
  s.debug().take(1).subscribe()

  subject.onNext(1)

  s.debug().subscribe()
}

print(".whileConnected, if all subscribes has been disposed before adding a new subscriber")

do {
  let subject = PublishSubject<Int>()

  let s = subject.share(replay: 1, scope: .whileConnected)

  s.debug().take(1).subscribe()

  subject.onNext(1)

  s.debug().subscribe()
}

print(".forever")

do {
  let subject = PublishSubject<Int>()

  let s = subject.share(replay: 1, scope: .forever)

  s.debug().take(1).subscribe()

  subject.onNext(1)

  s.debug().subscribe()
}

Result

.whileConnected, if it has subscribers that are subscribing forever
=> subscribed
=> Event next(1)
=> isDisposed
=> subscribed
=> Event next(1)

.whileConnected, if all subscribes has been disposed before adding a new subscriber
=> subscribed
=> Event next(1)
=> isDisposed
=> subscribed

.forever
=> subscribed
=> Event next(1)
=> isDisposed
=> subscribed
=> Event next(1)

Convert [String : Any?] to [String : Any]

This snippet convert [String : Any?] to [String : Any]. It would be helpful in building parameter for API Request.

extension Dictionary where Key == String, Value == Any? {

  func filterNil() -> Dictionary<String, Any> {

    var dic: [String : Any] = .init(minimumCapacity: self.count)

    for arg in self {
      guard let value = arg.value else {
        continue
      }
      dic[arg.key] = value
    }

    return dic
  }
}

SampleCode

let param: [String : Any?] = [
  "age" : nil,
  "name" : "muukii",
  "height" : nil,
  "weight" : 56,
]
print(param.filterNil())

Result

["name": "muukii", "weight": 56]

Get margin between UIView to target UIView

extension UIView {

  // The margin between self to target view
  public func margin(to: UICoordinateSpace) -> UIEdgeInsets {

    let frame = convert(bounds, to: to)

    return UIEdgeInsets(
      top: frame.minY,
      left: frame.minX,
      bottom: to.bounds.height - frame.maxY,
      right: to.bounds.width - frame.maxX
    )
  }
}

Try Observable.zip run concurrency with RxSwift

Observable.zip()

Observable.zip of RxSwift helps grouping results. In this case, If we want to get results by run concurrency, which scheduler should we use?

I've tried following code.

Try Scheduler

Base Code

Define a function that creates Observable for blocking 1sec.

func task(_ s: Int) -> Observable<Void> {
  return Observable.create { o in
    print("begin", s)
    sleep(1)
    print("end", s)
    o.onNext(())
    o.onCompleted()
    return Disposables.create()
  }
}
let s: SchedulerType

Observable.zip([
  task(1).subscribeOn(s),
  task(2).subscribeOn(s),
  task(3).subscribeOn(s),
  task(4).subscribeOn(s),
  ])
  .subscribe()

CurrentThreadScheduler

let s = CurrentThreadScheduler.instance

Result

begin 1
end 1
begin 2
end 2
begin 3
end 3
begin 4
end 4

SerialDispatchQueueScheduler

let s = SerialDispatchQueueScheduler(qos: .default)

Result

begin 1
end 1
begin 2
end 2
begin 3
end 3
begin 4
end 4

ConcurrentDispatchQueueScheduler

let s = ConcurrentDispatchQueueScheduler(qos: .default)

Result

begin 3
begin 2
begin 4
begin 1
end 3
end 1
end 4
end 2

OperationQueueScheduler

let q = OperationQueue()
q.maxConcurrentOperationCount = 2
let s = OperationQueueScheduler(operationQueue: q)

Result

begin 1
begin 2
end 2
end 1
begin 3
begin 4
end 4
end 3

SampleCode Posting Message to Slack with Incoming Web Hook

struct SlackMessage : Codable {

  struct Attachment : Codable {

    struct Field : Codable {
      let title: String
      let value: String
      let short: Bool
    }

    let color: String
    let pretext: String
    let author_name: String
    let author_icon: String
    let title: String
    let title_link: String
    let text: String
    let fields: [Field]
    let image_url: String
    let thumb_url: String
    let footer: String
    let footer_icon: String
  }

  var channel: String?
  let text: String?
  let as_user: Bool
  let parse: String
  let username: String
  let attachments: [Attachment]?
}

enum SlackSendMessage {

  static func send(message: SlackMessage, to urlString: String) {

    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
    guard let url = URL(string: urlString) else {return}
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")

    let encoder = JSONEncoder()
    let data = try! encoder.encode(message)
    request.httpBody = data

    let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
      if (error == nil) {
        // Success
        let statusCode = (response as! HTTPURLResponse).statusCode
        print("URL Session Task Succeeded: HTTP \(statusCode)")
      }
      else {
        // Failure
        print("URL Session Task Failed: %@", error!.localizedDescription);
      }
    })
    task.resume()
    session.finishTasksAndInvalidate()
  }
}

Try Signal in RxSwift 4.0

Signal

Signal has introduced in RxSwift4.0.
I've tried to watch differences Driver and Signal.

https://github.com/ReactiveX/RxSwift/pull/1116

Try

Code

import RxSwift
import RxCocoa

let source = PublishSubject<Int>()

let d = source.asDriver(onErrorRecover: { _ in .empty() })
let s = source.asSignal(onErrorRecover: { _ in .empty() })

source.onNext(1)

d.debug("First Drive").drive()
s.debug("First Emit ").emit()

source.onNext(2)

d.debug("Second Drive").drive()
s.debug("Second Emit ").emit()

Result

First Drive -> subscribed
First Emit  -> subscribed
First Drive -> Event next(2)
First Emit  -> Event next(2)
Second Drive -> subscribed
Second Drive -> Event next(2)
Second Emit  -> subscribed

Conclusion

  • Driver share events.
  • Signal doesn't share events.

Definitely, It just emits events.

Introduce filterLatestFrom in RxSwift 4.0

Filter is good operator

Filter of ReactiveProgramming is good operator. But, If you want evaluate with other Observable or Variable, you may write lenghty code.

For example

let source = PublishSubject<Void>()
let isEnabled = Variable(false)

source
  .filter {
    isEnabled.value == true
}

If isEnabled is stored property.

source
  .filter { [weak self] in
    guard let `self` = self else {
      return false // really?
    }
    return self.isEnabled.value == true
}

This is not good code.
So, I've created following snippet code.

filterLatestFrom

extension ObservableType {

  public func filterLatestFrom<S: ObservableConvertibleType>(_ second: S, _ predicate: @escaping (S.E) -> Bool) -> Observable<Self.E> {

    return withLatestFrom(second) { s, e -> Observable<Self.E> in
      if predicate(e) {
        return Observable<Self.E>.just(s)
      }
      return Observable<Self.E>.empty()
      }
      .merge()
  }
}

Usage

let source = PublishSubject<Void>()
let isEnabled = Variable(false)

source
  .filterLatestFrom(isEnabled.asObservable()) { $0 == true }
  .do(onNext: {
    // Through only isEnabled is true
  })

Is not this great?

[Snippet] CycleViewModel

import RxSwift
import RxCocoa

public enum NoState {}
public enum NoActivity {}
public enum NoMutation {}
public enum NoAction {}

public protocol CycleViewModel : class {

  associatedtype State
  associatedtype Activity
  associatedtype Action
  associatedtype Mutation

  var activity: CycleEvent<Activity> { get }
  var state: StateVariable<State> { get }
  func mutate(_ action: Action) -> Mutation
  func reduce(_ mutation: Mutation)
}

extension CycleViewModel where Action == Mutation {
  public func mutate(_ action: Action) -> Mutation {
    return action
  }
}

extension CycleViewModel where Activity == NoActivity {
  public var activity: Observable<Activity> {
    preconditionFailure("\(self) does not have Activity")
  }
}

extension CycleViewModel where State == NoState {
  public var state: StateVariable<State> {
    preconditionFailure("\(self) does not have State")
  }
}

extension CycleViewModel where Action == NoAction, Mutation == NoMutation {

  public func mutate(_ action: Action) -> Mutation {
    preconditionFailure("\(self) does not have Action")
  }

  public func reduce(_ mutation: Mutation) {
    preconditionFailure("\(self) does not have Mutation")
  }
}

extension CycleViewModel {

  // TODO: Use Binder on RxSwift 4.0
  public var action: AnyObserver<Action> {
    return AnyObserver<Action> { [weak self] e in
      guard let `self` = self else { return }
      if case .next(let action) = e {
        self.reduce(self.mutate(action))
      }
    }
  }

  public func run(_ action: Action) {
    self.reduce(self.mutate(action))
  }
}

public struct CycleEvent<PropertyType> : ObservableType {

  public typealias E = PropertyType

  let _events: Observable<PropertyType>

  public init<Ev: ObservableType>(_ events: Ev) where Ev.E == E {
    _events = events.asObservable()
  }

  public func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == E {
    return _events.subscribe(observer)
  }

  /// - returns: `Observable` interface.
  public func asObservable() -> Observable<E> {
    return _events
  }

  public func asDriver() -> Driver<E> {
    return _events.asDriver { _ in
      return .empty()
    }
  }
}

public final class StateVariable<T> {

  public var value: T {
    return source.value
  }

  private let source: MutableStateVariable<T>

  public init(_ variable: MutableStateVariable<T>) {
    self.source = variable
  }

  public func asObservable() -> Observable<T> {
    return source.asObservable()
  }

  public func asDriver() -> Driver<T> {
    return source.asDriver()
  }
}

public final class MutableStateVariable<T> {

  public var value: T {
    get {
      return source.value
    }
    set {
      source.value = newValue
    }
  }

  private let source: Variable<T>

  public init(_ value: T) {
    self.source = .init(value)
  }

  public func mutate<Source: ObservableType>(_ execute: @escaping (inout T, Source.E) -> Void) -> (Source) -> Disposable {
    return { source in
      source
        .do(onNext: { [weak self] e in
          guard let `self` = self else { return }
          execute(&self.value, e)
        })
        .subscribe()
    }
  }

  public func asObservable() -> Observable<T> {
    return source.asObservable()
  }

  public func asDriver() -> Driver<T> {
    return source.asDriver()
  }
}

UI.guardAsync and UI.GuardAsyncAfter

Sometimes, In iOS App Development, To display correctly, there are times use dispatch async.

This approach is a not good approach. Because It makes some side-effects.

For example, Tap the button to display ViewController.
If displaying ViewController is implemented asynchronously, the user can double tap.
Then, ViewController will show twice.

If you use dispatch async unavoidably, you need to disable user interface until complete task.

I created short utility for this approach.

public enum UI {

  public static func guardAsync(execute: @escaping () -> Void) {
    UIApplication.shared.beginIgnoringInteractionEvents()
    DispatchQueue.main.async {
      UIApplication.shared.endIgnoringInteractionEvents()
      execute()
    }
  }

  public static func guardAsyncAfter(deadline: DispatchTime, execute: @escaping () -> Void) {
    UIApplication.shared.beginIgnoringInteractionEvents()
    DispatchQueue.main.asyncAfter(deadline: deadline) {
      UIApplication.shared.endIgnoringInteractionEvents()
      execute()
    }
  }
}
func tapButton() {
  UI.guardAsync {
    // to do something
  }
}

Install Simulator Application

Build

xcodebuild -workspace <workspace> -scheme <scheme> -configuration <configuration> -arch i386 -sdk iphonesimulator

Find your device

$ xcrun simctl list devices

Boot the simulator.

$ xcrun simctl boot <device_id>

Install app to the simulator.

$ xcrun simctl install  <device_id> <path_to_app_bundle>

Launch app

$ xcrun simctl launch <Installed app bundle identifer>

Simple Interface for ViewModel

I've read some articles about Flux architecture.
One of Flux architecture's merit will be clear input and output. It like Actions and States.

So, I thought the idea about importing this merit to ViewModel.
Defining states is hard for current implementations.
But, Grouping inputs is not hard.

protocol ViewModelWireframe : class {
  associatedtype Action
  func run(_ action: Action)
}

Implemented sample code.
When you request run action, call run(_ action).
ViewModel can receive action in one function only.

final class ViewModel : ViewModelWireframe {

  enum Action {
    case like(partnerIdentifier: String)
    case nope(partnerIdentifier: String)
  }

  // Outputs
  let showComplete = PublishSubject<Void>()
  let processing = PublishSubject<Void>()

  // Input
  func run(_ action: Action) {

    switch action {
    case let .like(partnerIdentifier):
      // Do something
      break
    case let .nope(partnerIdentifier):
      // Do someting
      break
    }
  }
}

If you using RxSwift, the following code would be helpful binding.

// Optional Extension
extension ViewModelWireframe {

  public var action: AnyObserver<Action> {
    return AnyObserver<Action> { [weak self] e in

      guard let `self` = self else { return }

      switch e {
      case .next(let action):
        self.run(action)
      case .error(let error):
        assertionFailure("Don't send error \(error)")
        break
      case .completed:
        break
      }
    }
  }
}

Flexible Constants with Protocol and Generics

Usually, Choices are defined as Enum.

enum Kind {
  case a
  case b
  case c

  var value: Int { ... }
}

class Sample {

  func set(kind: Kind)
}

sample.set(kind: .a)

But, In some case, if Enum has some problems, How do we define? CodingKey in Swift4 uses very good idea.

Define protocol that can get value for choices.

protocol KindDescribing {
  var value: Int { get }
}

Make sample class to generic class.

class Sample<T: KindDescribing> {

  func set(kind: T)
}

Define Enum that conforms to KindDescribing.

enum KindEnum: KindDescribing {
  case a
  case b
  case c

  var value: Int { ... }

We can use it just like this.

let sample = Sample<KindEnum>

sample.set(kind: .a)

In other hands, We can define as Struct that conforms to KindDescribing.

struct KindStruct: KindDescribing {
  let value: Int

  static let a = KindStruct(value: ...)
  static let b = KindStruct(value: ...)
  static let c = KindStruct(value: ...)
  static func custom(value: Int) -> KindStruct {
      return KindStruct(value: value) 
    }
}

We can use this like followings.

let sample = Sample<KindStruct>

sample.set(kind: .a)
sample.set(kind: .custom(value: 100))

This approach will be useful for delegate defining choices.

Launching Require library.

Optional protect the runtime errors in Swift.

But, sometimes I've tired to wrapping values.
For example, in method chaining in RxSwift.

value.asObservable()
  .flatMap { [weak self] in
    guard let _self = self else {
      return Observable.empty()
    }
    return Observable.just(_self.converted())
}

Using flatMap because Value doesn't want to be Optional.
Just unwrap it and use 3 lines 😲
But, as we know map or flatMap can use throw.

I've created Require.
It can be easily unwrapping.

value.asObservable()
  .map { [weak self] in
    try self.require().converted()
}

Iterating ResponderChain

ResponderChain is used event handling.

UIResponder class has following method.
We can get next responder.

func next() -> UIResponder?

UIViewController and UIView has inherited UIResponder class.
Calling next() recursively can get UIApplication has UIWindow.

I've created following code. This iterate responder object.

final class ResponderChainIterator: IteratorProtocol, Sequence {

  typealias Element = UIResponder

  private var currentResponder: UIResponder?

  init(responder: UIResponder) {
    currentResponder = responder
  }

  func next() -> UIResponder? {
    let next = currentResponder?.next
    currentResponder = next
    return next
  }
}

We can find ViewController it has tapped UIButton.

let button: UIButton

let viewController = ResponderChainIterator(responder: view)
  .flatMap { $0 as? UIViewController }
  .first

Enabling Syntax highlighting in Squarespace

To enable syntax highlighting, I decided to add highlight.js to DOM of each post.

I referred to this article.
Then, I inserted following code into header.

<style type="text/css">
  pre.hljs {
    font-size: small;
    margin: 0;
  }
  div.hljs {
    border-radius: 4px;
  }
  code {
    border-radius: 4px;
  }
</style>

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/atom-one-dark.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/swift.min.js"></script>
<script>
Y.on('domready', function () {
  Y.all('pre code').each(function () {    
    hljs.highlightBlock(this.getDOMNode());
  });
  Y.all('pre.source-code').each(function () {    
    hljs.highlightBlock(this.getDOMNode());
    this.ancestor('div').addClass('hljs');
  });
});
</script>

Testing Syntax Highlighting

func abc() {}
class Foo {
  func foo() {
  }
}
protocol Bar {
}
func abc() {}
class Foo {
  func foo() {
  }
}
protocol Bar {
}
class Foo {}