Latest 1.1
Homepage https://github.com/josete89/swifttor
License MIT
Platforms ios 11.1, osx 10.13, tvos 11.1, watchos 4.1
Frameworks Foundation
Authors

Build Status
codecov

Swifttor is a library which allows you to use the actors paradimng from the popular akka library.

  • All the messages are being reicived on parallel.
  • Uses structs as actor so is easy to paralellize.
  • Works in all platforms.
  • Includes the ask and tell actions.
  • Can compose the ask calls

Real example

In the Example folder we have an example project which is using swifttor.

I’ve created 3 different actors

struct NetworkActor: ActorAsk {    

    typealias ResultType = Result<Data,String>
    typealias MessageType = URL

    func reiciveAsk(message: URL,completion:@escaping (Result<Data,String>)->()) {
        perfomNetWorkCall(url: message, completion: completion)
    }

    func perfomNetWorkCall(url:URL,completion:@escaping (Result<Data,String>)->()){
        let session = URLSession(configuration: .ephemeral)
        session.dataTask(with: url, completionHandler: { (data, response, err) in
            if let dat = data{
                completion(Result.success(dat))
            }else{
                completion(Result.failure("error happend"))
            }
        }).resume()
    }
}
struct ParserActor: ActorAsk {

    typealias ResultType = Result<Model,String>
    typealias MessageType = Result<Data,String>

    func reiciveAsk(message: Result<Data,String>, completion: @escaping (Result<Model, String>) -> ()) {

        let result = message.fmap { (data) -> Result <Model,String>  in
            if let result = try? JSONDecoder().decode(Model.self, from: data){
                return Result.success(result)
            }
            return Result.failure("Cannot parse")
        }
        completion(result)

    }

}
struct MainActor: ActorTell {

    var queue: DispatchQueue {
        return DispatchQueue.main
    }

    typealias MessageType = MainActorMessages

    func reiciveTell(message: MainActorMessages) {
        switch message {
        case .refreshStuffWithData(let callback,let data):
            callback(data)
        case .refreshStuff(let callback):
            callback()
        case .displayInfo(let callback,let data):
            callback(data)
        }

    }

}

And this are the enums used for messaging between them

enum MainActorMessages {
    case displayInfo(callback:(Model) -> (),data:Model)
    case refreshStuffWithData(callback:(String) -> (),data:String)
    case refreshStuff(callbac:() -> ())
}
enum Result<A,B>{
    case success(A)
    case failure(B)
}

extension Result {
    func map<C>(_ transform: (A) -> C) -> Result<C,B> {
        switch self {
        case .success(let value): return .success(transform(value))
        case .failure(let error): return .failure(error)
        }
    }
    func fmap<C>(_ transform: (A) -> Result<C,B>) -> Result<C,B> {
        switch self {
        case .success(let value):
            return transform(value)
        case .failure(let error):
            return .failure(error)
        }
    }
}

And now you are able to do this

        let actorRef = ActorSystem.actorOf(actorType: MainActor.self)

        let networkActor = ActorSystem.actorOf(actorType: NetworkActor.self)
        let parserActor = ActorSystem.actorOf(actorType: ParserActor.self)
        let actorChain =  networkActor.ask(URL(string: "https://httpbin.org/ip")!) >>> parserActor.ask

        actorChain.onResult { (result) in
            switch result {
            case .success(let model):
                actorRef.tell(MainActorMessages.displayInfo(callback: { print($0) }, data: model))
            case .failure(let err):
                actorRef.tell(MainActorMessages.refreshStuffWithData(callback: { print($0) }, data: err))
            }
        }

Code examples

Create a new actor

struct MainActor:ActorAsk,ActorTell {
    /* Optional if you don't specify creates a new one*/
    var queue: DispatchQueue {
        return DispatchQueue.main
    }

    typealias MessageType = String
    typealias ResulType = String

    func reiciveAsk(message: String,completion:@escaping(String)->Void) {
        completion(message)
    }

    func reiciveTell(message: String) {
        print(message)
    }

}

Inicialization

/*If we use this we are saving the actor in a cache*/
let actor1 = ActorSystem.actorOf(actorType: MainActor.self)

/*We are just craeting the actor without saving anywhere*/
let main = MainActor()
let actorRef = ActorSystem.actorOfInstance(main)

Compose calls

let actor1 = ActorSystem.actorOf(actorType: MainActor.self)
let actor2 = ActorSystem.actorOf(actorType: MainActor.self)
let result = actor1 !! "Hello" >>> actor2.ask
result.onResult(callback:{
    print($0)
})

How to add to your projects

Using one of this depency managers:

  • Carthage
  • Cocoapods
  • SwiftPM

Todos

  • Deadletter
  • Mailbox

License

Apache 2.0

Latest podspec

{
    "name": "Swifttor",
    "version": "1.1",
    "summary": "An akka implementation on Swift",
    "description": "Library to use the actor paradming on swift with differnt kind of actors",
    "module_name": "Swifttor",
    "homepage": "https://github.com/josete89/swifttor",
    "license": "MIT",
    "authors": {
        "Jose Luis Alcala": "[email protected]"
    },
    "source": {
        "git": "https://github.com/josete89/swifttor.git",
        "tag": "1.1"
    },
    "social_media_url": "https://twitter.com/joseluisalcala",
    "source_files": "Swifttor/*.swift",
    "cocoapods_version": ">= 1.0",
    "platforms": {
        "ios": "11.1",
        "osx": "10.13",
        "tvos": "11.1",
        "watchos": "4.1"
    },
    "frameworks": "Foundation",
    "pushed_with_swift_version": "4.0"
}

Pin It on Pinterest

Share This