kandi background
Explore Kits

RxSwift | Reactive Programming in Swift | Reactive Programming library

 by   ReactiveX Swift Version: 6.5.0 License: Non-SPDX

 by   ReactiveX Swift Version: 6.5.0 License: Non-SPDX

Download this library from

kandi X-RAY | RxSwift Summary

RxSwift is a Swift library typically used in Programming Style, Reactive Programming applications. RxSwift has no bugs, it has no vulnerabilities and it has medium support. However RxSwift has a Non-SPDX License. You can download it from GitHub.
Rx is a generic abstraction of computation expressed through Observable<Element> interface, which lets you broadcast and subscribe to values and other events from an Observable stream. RxSwift is the Swift-specific implementation of the Reactive Extensions standard. While this version aims to stay true to the original spirit and naming conventions of Rx, this projects also aims to provide a true Swift-first API for Rx APIs. Cross platform documentation can be found on ReactiveX.io. Like other Rx implementation, RxSwift's intention is to enable easy composition of asynchronous operations and streams of data in the form of Observable objects and a suite of methods to transform and compose these pieces of asynchronous work. KVO observation, async operations, UI Events and other streams of data are all unified under abstraction of sequence. This is the reason why Rx is so simple, elegant and powerful.
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • RxSwift has a medium active ecosystem.
  • It has 22027 star(s) with 3915 fork(s). There are 544 watchers for this library.
  • There were 1 major release(s) in the last 12 months.
  • There are 7 open issues and 1159 have been closed. On average issues are closed in 63 days. There are 5 open pull requests and 0 closed requests.
  • It has a neutral sentiment in the developer community.
  • The latest version of RxSwift is 6.5.0
RxSwift Support
Best in #Reactive Programming
Average in #Reactive Programming
RxSwift Support
Best in #Reactive Programming
Average in #Reactive Programming

quality kandi Quality

  • RxSwift has 0 bugs and 0 code smells.
RxSwift Quality
Best in #Reactive Programming
Average in #Reactive Programming
RxSwift Quality
Best in #Reactive Programming
Average in #Reactive Programming

securitySecurity

  • RxSwift has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
  • RxSwift code analysis shows 0 unresolved vulnerabilities.
  • There are 0 security hotspots that need review.
RxSwift Security
Best in #Reactive Programming
Average in #Reactive Programming
RxSwift Security
Best in #Reactive Programming
Average in #Reactive Programming

license License

  • RxSwift has a Non-SPDX License.
  • Non-SPDX licenses can be open source with a non SPDX compliant license, or non open source licenses, and you need to review them closely before use.
RxSwift License
Best in #Reactive Programming
Average in #Reactive Programming
RxSwift License
Best in #Reactive Programming
Average in #Reactive Programming

buildReuse

  • RxSwift releases are available to install and integrate.
  • Installation instructions, examples and code snippets are available.
  • It has 56337 lines of code, 0 functions and 79 files.
  • It has low code complexity. Code complexity directly impacts maintainability of the code.
RxSwift Reuse
Best in #Reactive Programming
Average in #Reactive Programming
RxSwift Reuse
Best in #Reactive Programming
Average in #Reactive Programming
Top functions reviewed by kandi - BETA

kandi's functional review helps you automatically verify the functionalities of the libraries and avoid rework.
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here

Get all kandi verified functions for this library.

Get all kandi verified functions for this library.

RxSwift Key Features

Reactive Programming in Swift

I came here because I want to ...

copy iconCopydownload iconDownload
┌──────────────┐    ┌──────────────┐
│   RxCocoa    ├────▶   RxRelay    │
└───────┬──────┘    └──────┬───────┘
        │                  │        
┌───────▼──────────────────▼───────┐
│             RxSwift              │
└───────▲──────────────────▲───────┘
        │                  │        
┌───────┴──────┐    ┌──────┴───────┐
│    RxTest    │    │  RxBlocking  │
└──────────────┘    └──────────────┘

Usage

copy iconCopydownload iconDownload
let searchResults = searchBar.rx.text.orEmpty
    .throttle(.milliseconds(300), scheduler: MainScheduler.instance)
    .distinctUntilChanged()
    .flatMapLatest { query -&gt; Observable&lt;[Repository]&gt; in
        if query.isEmpty {
            return .just([])
        }
        return searchGitHub(query)
            .catchAndReturn([])
    }
    .observe(on: MainScheduler.instance)

Manual

copy iconCopydownload iconDownload
# Podfile
use_frameworks!

target 'YOUR_TARGET_NAME' do
    pod 'RxSwift', '6.5.0'
    pod 'RxCocoa', '6.5.0'
end

# RxTest and RxBlocking make the most sense in the context of unit/integration tests
target 'YOUR_TESTING_TARGET' do
    pod 'RxBlocking', '6.5.0'
    pod 'RxTest', '6.5.0'
end

XCFrameworks

copy iconCopydownload iconDownload
github "ReactiveX/RxSwift" "6.5.0"

Manually using git submodules

copy iconCopydownload iconDownload
$ git submodule add git@github.com:ReactiveX/RxSwift.git

How to reset and start new timer when enter new email

copy iconCopydownload iconDownload
struct Output {
    let eventResendEmailCountdown: Observable<Int>
    let eventShowHideResendEmailButton: Observable<Bool>
    let eventDismissCountdownBottomSheet: Observable<Void>
}

func example(text: Observable<String?>) -> Output {
    let trigger = text.share()
    let eventResendEmailCountdown = trigger
        .flatMapLatest { _ in
            Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
                .map { 120 - $0 }
                .take(until: { $0 == -1 })
        }
    let eventShowHideResendEmailButton = Observable.merge(
        trigger.map { _ in false },
        eventResendEmailCountdown.filter { $0 == 0 }.map { _ in true }
    )
    let eventDismissCountdownBottomSheet = eventResendEmailCountdown
        .filter { $0 == 0 }
        .map { _ in }

    return Output(
        eventResendEmailCountdown: eventResendEmailCountdown,
        eventShowHideResendEmailButton: eventShowHideResendEmailButton,
        eventDismissCountdownBottomSheet: eventDismissCountdownBottomSheet
    )
}
let output = example(text: textField.rx.text.asObservable())

output.eventResendEmailCountdown
    .debug("eventResendEmailCountdown")
    .subscribe()

output.eventShowHideResendEmailButton
    .debug("eventShowHideResendEmailButton")
    .subscribe()

output.eventDismissCountdownBottomSheet
    .debug("eventDismissCountdownBottomSheet")
    .subscribe()
struct Output {
    let eventResendEmailCountdown: Observable<Int>
    let eventShowHideResendEmailButton: Observable<Bool>
    let eventDismissCountdownBottomSheet: Observable<Void>
}

func example(text: Observable<String?>) -> Output {
    let trigger = text.share()
    let eventResendEmailCountdown = trigger
        .flatMapLatest { _ in
            Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
                .map { 120 - $0 }
                .take(until: { $0 == -1 })
        }
    let eventShowHideResendEmailButton = Observable.merge(
        trigger.map { _ in false },
        eventResendEmailCountdown.filter { $0 == 0 }.map { _ in true }
    )
    let eventDismissCountdownBottomSheet = eventResendEmailCountdown
        .filter { $0 == 0 }
        .map { _ in }

    return Output(
        eventResendEmailCountdown: eventResendEmailCountdown,
        eventShowHideResendEmailButton: eventShowHideResendEmailButton,
        eventDismissCountdownBottomSheet: eventDismissCountdownBottomSheet
    )
}
let output = example(text: textField.rx.text.asObservable())

output.eventResendEmailCountdown
    .debug("eventResendEmailCountdown")
    .subscribe()

output.eventShowHideResendEmailButton
    .debug("eventShowHideResendEmailButton")
    .subscribe()

output.eventDismissCountdownBottomSheet
    .debug("eventDismissCountdownBottomSheet")
    .subscribe()

RxSwift | Best way to make consecutive network requests?

copy iconCopydownload iconDownload
func isRepoStarred(name: String) -> Observable<Bool> {
    URLSession.shared.rx.data(request: URLRequest(url: URL(string: "https://api.github.com/user/starred/\(name)")!))
        .map { data in
            var result = false
            // find out if repo is starred here and return true or false.
            return result
        }
}
func searchRepositories() -> Observable<RepositoryResponse> {
    var baseUrl = URLComponents(string: "https://api.github.com/search/repositories")   // base url
    let query = URLQueryItem(name: "q", value: "flutter")    // Keyword. flutter for this time.
    let sort = URLQueryItem(name: "sort", value: "stars")   // Sort by stars
    let order = URLQueryItem(name: "order", value: "desc")  // Desc order
    baseUrl?.queryItems = [query, sort, order]
    
    return URLSession.shared.rx.data(request: URLRequest(url: baseUrl!.url!))
        .map { data in
            try JSONDecoder().decode(RepositoryResponse.self, from: data)
        }
}
let repositories = searchRepositories()
    .flatMap {
        Observable.zip($0.items.map { item in
            isRepoStarred(name: item.fullName).map { Repository(item, isStarred: $0) }
        })
    }
let repositories = searchRepositories()
    .map { $0.items }

let starreds = repositories
    .flatMap { items in
        Observable.zip(items.map { isRepoStarred(name: $0.fullName) })
    }

let repos = Observable.zip(repositories, starreds) { items, starreds in
    zip(items, starreds)
        .map { Repository($0, isStarred: $1) }
}
func isRepoStarred(name: String) -> Observable<Bool> {
    URLSession.shared.rx.data(request: URLRequest(url: URL(string: "https://api.github.com/user/starred/\(name)")!))
        .map { data in
            var result = false
            // find out if repo is starred here and return true or false.
            return result
        }
}
func searchRepositories() -> Observable<RepositoryResponse> {
    var baseUrl = URLComponents(string: "https://api.github.com/search/repositories")   // base url
    let query = URLQueryItem(name: "q", value: "flutter")    // Keyword. flutter for this time.
    let sort = URLQueryItem(name: "sort", value: "stars")   // Sort by stars
    let order = URLQueryItem(name: "order", value: "desc")  // Desc order
    baseUrl?.queryItems = [query, sort, order]
    
    return URLSession.shared.rx.data(request: URLRequest(url: baseUrl!.url!))
        .map { data in
            try JSONDecoder().decode(RepositoryResponse.self, from: data)
        }
}
let repositories = searchRepositories()
    .flatMap {
        Observable.zip($0.items.map { item in
            isRepoStarred(name: item.fullName).map { Repository(item, isStarred: $0) }
        })
    }
let repositories = searchRepositories()
    .map { $0.items }

let starreds = repositories
    .flatMap { items in
        Observable.zip(items.map { isRepoStarred(name: $0.fullName) })
    }

let repos = Observable.zip(repositories, starreds) { items, starreds in
    zip(items, starreds)
        .map { Repository($0, isStarred: $1) }
}
func isRepoStarred(name: String) -> Observable<Bool> {
    URLSession.shared.rx.data(request: URLRequest(url: URL(string: "https://api.github.com/user/starred/\(name)")!))
        .map { data in
            var result = false
            // find out if repo is starred here and return true or false.
            return result
        }
}
func searchRepositories() -> Observable<RepositoryResponse> {
    var baseUrl = URLComponents(string: "https://api.github.com/search/repositories")   // base url
    let query = URLQueryItem(name: "q", value: "flutter")    // Keyword. flutter for this time.
    let sort = URLQueryItem(name: "sort", value: "stars")   // Sort by stars
    let order = URLQueryItem(name: "order", value: "desc")  // Desc order
    baseUrl?.queryItems = [query, sort, order]
    
    return URLSession.shared.rx.data(request: URLRequest(url: baseUrl!.url!))
        .map { data in
            try JSONDecoder().decode(RepositoryResponse.self, from: data)
        }
}
let repositories = searchRepositories()
    .flatMap {
        Observable.zip($0.items.map { item in
            isRepoStarred(name: item.fullName).map { Repository(item, isStarred: $0) }
        })
    }
let repositories = searchRepositories()
    .map { $0.items }

let starreds = repositories
    .flatMap { items in
        Observable.zip(items.map { isRepoStarred(name: $0.fullName) })
    }

let repos = Observable.zip(repositories, starreds) { items, starreds in
    zip(items, starreds)
        .map { Repository($0, isStarred: $1) }
}
func isRepoStarred(name: String) -> Observable<Bool> {
    URLSession.shared.rx.data(request: URLRequest(url: URL(string: "https://api.github.com/user/starred/\(name)")!))
        .map { data in
            var result = false
            // find out if repo is starred here and return true or false.
            return result
        }
}
func searchRepositories() -> Observable<RepositoryResponse> {
    var baseUrl = URLComponents(string: "https://api.github.com/search/repositories")   // base url
    let query = URLQueryItem(name: "q", value: "flutter")    // Keyword. flutter for this time.
    let sort = URLQueryItem(name: "sort", value: "stars")   // Sort by stars
    let order = URLQueryItem(name: "order", value: "desc")  // Desc order
    baseUrl?.queryItems = [query, sort, order]
    
    return URLSession.shared.rx.data(request: URLRequest(url: baseUrl!.url!))
        .map { data in
            try JSONDecoder().decode(RepositoryResponse.self, from: data)
        }
}
let repositories = searchRepositories()
    .flatMap {
        Observable.zip($0.items.map { item in
            isRepoStarred(name: item.fullName).map { Repository(item, isStarred: $0) }
        })
    }
let repositories = searchRepositories()
    .map { $0.items }

let starreds = repositories
    .flatMap { items in
        Observable.zip(items.map { isRepoStarred(name: $0.fullName) })
    }

let repos = Observable.zip(repositories, starreds) { items, starreds in
    zip(items, starreds)
        .map { Repository($0, isStarred: $1) }
}

Observe an RxSwift.BehaviorRelay just **before** a change happens

copy iconCopydownload iconDownload
extension ObservableType {
    func withPrevious() -> Observable<(Element?, Element)> {
        scan((Element?.none, Element?.none)) { ($0.1, $1) }
        .map { ($0.0, $0.1!) }
    }
}

How to writ good test for my ViewModel? (RxSwift)

copy iconCopydownload iconDownload
struct Storage {
    static let shared = Storage()
    func currentUserSettings() -> Observable<UserSettings?> { .just(nil) }
}

struct SettingsViewModel {
    let userSettings = BehaviorRelay<UserSettings>(value: UserSettings())
    
    func saveName(_ value: String) {
        userSettings.accept(UserSettings(name: value, tags: []))
    }
    
    func addTag(_ value: String) { }
    
    func removeTag(_ value: Int) { }
}

struct UserSettings {
    var name: String = ""
    var tags: [String] = []
}

What is &quot;Pod/***.a Pod/**.dia&quot; file?

copy iconCopydownload iconDownload
echo Pods/>.gitignore
git rm --cached -R Pods/
git rm --cached -R Pods/*.d
echo Pods/>.gitignore
git rm --cached -R Pods/
git rm --cached -R Pods/*.d

How to use RxSwift to implement the following logic with UITextfield?

copy iconCopydownload iconDownload

import Cause_Logic_Effect
import RxCocoa
import RxSwift
import UIKit

final class ViewController: UIViewController {
    var textCodeField: UITextField!
    var selectTypeAction: UIButton!
    var selectTypeLabel: UILabel!
    var passCodeField: UITextField!
    let disposeBag = DisposeBag()
}

extension ViewController {
    func connect() {
        // when user taps the selectTypeAction, display an action sheet alert to
        // get the selection type from the user.
        let selectType = selectTypeAction.rx.tap
            .flatMapFirst(
                presentScene(animated: true, over: selectTypeAction, scene: {
                    UIAlertController(
                        title: nil,
                        message: "Select Item:",
                        preferredStyle: .actionSheet
                    )
                        .scene { $0.connectChoice(choices: ["A", "B", "C"]) }
                })
            )
            .share()

        // when the user selects "B" grab the last value entered in the
        // textCodeField and push it to the passCodeField
        selectType
            .compactMap { $0 }
            .filter { $0 == "B" }
            .withLatestFrom(textCodeField.rx.text)
            .bind(to: passCodeField.rx.text)
            .disposed(by: disposeBag)

        // when the user selects a value push the value to the selectTypeLabel
        selectType
            .bind(to: selectTypeLabel.rx.text)
            .disposed(by: disposeBag)
    }
}

RxSwift/RxTest How to test async function with Observable return

copy iconCopydownload iconDownload
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        // note that you don't have to store this value. The disposable will hold it for you.
        let ref = Database.database().reference()
        // the `handleSnapshot(observer:)` function is defined below.
        ref.child("Posts").observe(.value, handleSnapshot(observer: observer))
        // make sure you turn off the observation on dispose.
        return Disposables.create { ref.stop() }
    }
}
// note that this is a free function. It should not be defined inside any class or struct.
// I'm guessing on the `Snapshot` type. I don't use Firebase.
func handleSnapshot(observer: AnyObserver<[PostItem]>) -> (Snapshot) -> Void {
    { snapshot in
        var postsList: [PostItem] = []
        for child in snapshot.children {
            let snap = child as! DataSnapshot

            let postDict = snap.value as! [String: Any]
            let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
            postsList.append(postAux)
        }
        observer.onNext(postsList)
    }
}
func testShapshotHandler() throws {
    let scheduler = TestScheduler(initialClock: 0)
    let observer = scheduler.createObserver([PostItem].self)
    let snapshot = Snapshot(children: [Child()]) // create a snapshot object here
    let sut = handleSnapshot(observer: observer.asObserver())

    sut(snapshot)

    // assumes `PostItem` is Equatable
    XCTAssertEqual(observer.events, [.next(0, [PostItem(id: "", authorId: "", name: "", content: "", createAt: "")])])
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        let ref = Database.database().reference()
        ref.child("Posts").observe(.value) { snapshot in
            observer.onNext(handle(snapshot: snapshot))
        }
        return Disposables.create { ref.stop() }
    }
}

func handle(snapshot: Snapshot) -> [PostItem] {
    var postsList: [PostItem] = []
    for child in snapshot.children {
        let snap = child as! DataSnapshot

        let postDict = snap.value as! [String: Any]
        let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
        postsList.append(postAux)
    }
    return postsList
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        // note that you don't have to store this value. The disposable will hold it for you.
        let ref = Database.database().reference()
        // the `handleSnapshot(observer:)` function is defined below.
        ref.child("Posts").observe(.value, handleSnapshot(observer: observer))
        // make sure you turn off the observation on dispose.
        return Disposables.create { ref.stop() }
    }
}
// note that this is a free function. It should not be defined inside any class or struct.
// I'm guessing on the `Snapshot` type. I don't use Firebase.
func handleSnapshot(observer: AnyObserver<[PostItem]>) -> (Snapshot) -> Void {
    { snapshot in
        var postsList: [PostItem] = []
        for child in snapshot.children {
            let snap = child as! DataSnapshot

            let postDict = snap.value as! [String: Any]
            let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
            postsList.append(postAux)
        }
        observer.onNext(postsList)
    }
}
func testShapshotHandler() throws {
    let scheduler = TestScheduler(initialClock: 0)
    let observer = scheduler.createObserver([PostItem].self)
    let snapshot = Snapshot(children: [Child()]) // create a snapshot object here
    let sut = handleSnapshot(observer: observer.asObserver())

    sut(snapshot)

    // assumes `PostItem` is Equatable
    XCTAssertEqual(observer.events, [.next(0, [PostItem(id: "", authorId: "", name: "", content: "", createAt: "")])])
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        let ref = Database.database().reference()
        ref.child("Posts").observe(.value) { snapshot in
            observer.onNext(handle(snapshot: snapshot))
        }
        return Disposables.create { ref.stop() }
    }
}

func handle(snapshot: Snapshot) -> [PostItem] {
    var postsList: [PostItem] = []
    for child in snapshot.children {
        let snap = child as! DataSnapshot

        let postDict = snap.value as! [String: Any]
        let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
        postsList.append(postAux)
    }
    return postsList
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        // note that you don't have to store this value. The disposable will hold it for you.
        let ref = Database.database().reference()
        // the `handleSnapshot(observer:)` function is defined below.
        ref.child("Posts").observe(.value, handleSnapshot(observer: observer))
        // make sure you turn off the observation on dispose.
        return Disposables.create { ref.stop() }
    }
}
// note that this is a free function. It should not be defined inside any class or struct.
// I'm guessing on the `Snapshot` type. I don't use Firebase.
func handleSnapshot(observer: AnyObserver<[PostItem]>) -> (Snapshot) -> Void {
    { snapshot in
        var postsList: [PostItem] = []
        for child in snapshot.children {
            let snap = child as! DataSnapshot

            let postDict = snap.value as! [String: Any]
            let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
            postsList.append(postAux)
        }
        observer.onNext(postsList)
    }
}
func testShapshotHandler() throws {
    let scheduler = TestScheduler(initialClock: 0)
    let observer = scheduler.createObserver([PostItem].self)
    let snapshot = Snapshot(children: [Child()]) // create a snapshot object here
    let sut = handleSnapshot(observer: observer.asObserver())

    sut(snapshot)

    // assumes `PostItem` is Equatable
    XCTAssertEqual(observer.events, [.next(0, [PostItem(id: "", authorId: "", name: "", content: "", createAt: "")])])
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        let ref = Database.database().reference()
        ref.child("Posts").observe(.value) { snapshot in
            observer.onNext(handle(snapshot: snapshot))
        }
        return Disposables.create { ref.stop() }
    }
}

func handle(snapshot: Snapshot) -> [PostItem] {
    var postsList: [PostItem] = []
    for child in snapshot.children {
        let snap = child as! DataSnapshot

        let postDict = snap.value as! [String: Any]
        let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
        postsList.append(postAux)
    }
    return postsList
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        // note that you don't have to store this value. The disposable will hold it for you.
        let ref = Database.database().reference()
        // the `handleSnapshot(observer:)` function is defined below.
        ref.child("Posts").observe(.value, handleSnapshot(observer: observer))
        // make sure you turn off the observation on dispose.
        return Disposables.create { ref.stop() }
    }
}
// note that this is a free function. It should not be defined inside any class or struct.
// I'm guessing on the `Snapshot` type. I don't use Firebase.
func handleSnapshot(observer: AnyObserver<[PostItem]>) -> (Snapshot) -> Void {
    { snapshot in
        var postsList: [PostItem] = []
        for child in snapshot.children {
            let snap = child as! DataSnapshot

            let postDict = snap.value as! [String: Any]
            let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
            postsList.append(postAux)
        }
        observer.onNext(postsList)
    }
}
func testShapshotHandler() throws {
    let scheduler = TestScheduler(initialClock: 0)
    let observer = scheduler.createObserver([PostItem].self)
    let snapshot = Snapshot(children: [Child()]) // create a snapshot object here
    let sut = handleSnapshot(observer: observer.asObserver())

    sut(snapshot)

    // assumes `PostItem` is Equatable
    XCTAssertEqual(observer.events, [.next(0, [PostItem(id: "", authorId: "", name: "", content: "", createAt: "")])])
}
func getAllPosts() -> Observable<[PostItem]> {
    return Observable.create { observer in
        let ref = Database.database().reference()
        ref.child("Posts").observe(.value) { snapshot in
            observer.onNext(handle(snapshot: snapshot))
        }
        return Disposables.create { ref.stop() }
    }
}

func handle(snapshot: Snapshot) -> [PostItem] {
    var postsList: [PostItem] = []
    for child in snapshot.children {
        let snap = child as! DataSnapshot

        let postDict = snap.value as! [String: Any]
        let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String  ?? "", name: postDict["name"] as? String  ?? "", content: postDict["content"] as? String  ?? "", createAt: postDict["createAt"] as? String  ?? "")
        postsList.append(postAux)
    }
    return postsList
}

Swift 5, RxSwift: Network request with RxSwift

copy iconCopydownload iconDownload
final class TimeDepositManager: Service, TimeDepositManagerProtocol {
    let timeDepositQuery = Bundle.main.queryValue

    func getTimeDeposits() -> Observable<[TimeDeposits]> {
        let body = ["query": timeDepositQuery]
        return Service().graphQL(body: body)
            .map { try JSONDecoder().decode(GraphQLResponse.self, from: $0).data?.account?.timeDeposits ?? [] }
    }
}

class Service: GraphQLService {

    func graphQL(body: [String: Any?]) -> Observable<Data> {
        guard let urlValue = Bundle.main.urlValue else { fatalError("Error with info.plist") }
        let request = urlRequest(urlValue: urlValue, body: body)
        return URLSession.shared.rx.data(request: request) // this is in RxCocoa
    }

    func urlRequest(urlValue: String, body: [String: Any?]) -> URLRequest {
        guard let url = URL(string: urlValue) else { fatalError("Error with urlValue") }
        var request = URLRequest(url: url)
        let userKey = Bundle.main.userKeyValue
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue(userKey, forHTTPHeaderField: "userid")
        request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
        return request
    }
}
extension URLSession {
    func data(request: URLRequest) -> Observable<Data> {
        Observable.create { observer in
            let task = self.dataTask(with: request, completionHandler: { data, response, error in
                guard let response = response as? HTTPURLResponse else {
                    observer.onError(URLError.notHTTPResponse(data: data, response: response))
                    return
                }
                guard 200 <= response.statusCode && response.statusCode < 300 else {
                    observer.onError(URLError.failedResponse(data: data, response: response))
                    return
                }
                guard let data = data else {
                    observer.onError(error ?? RxError.unknown)
                    return
                }
                observer.onNext(data)
                observer.onCompleted() // be sure to call `onCompleted()` when you are done emitting values.
                // make sure every possible path through the code calls some method on `observer`.
            })
            return Disposables.create { task.cancel() } // don't forget to handle cancelation properly. You don't want to kill *all* tasks, just this one.
        }
    }
}

enum URLError: Error {
    case notHTTPResponse(data: Data?, response: URLResponse?)
    case failedResponse(data: Data?, response: HTTPURLResponse)
}
final class TimeDepositManager: Service, TimeDepositManagerProtocol {
    let timeDepositQuery = Bundle.main.queryValue

    func getTimeDeposits() -> Observable<[TimeDeposits]> {
        let body = ["query": timeDepositQuery]
        return Service().graphQL(body: body)
            .map { try JSONDecoder().decode(GraphQLResponse.self, from: $0).data?.account?.timeDeposits ?? [] }
    }
}

class Service: GraphQLService {

    func graphQL(body: [String: Any?]) -> Observable<Data> {
        guard let urlValue = Bundle.main.urlValue else { fatalError("Error with info.plist") }
        let request = urlRequest(urlValue: urlValue, body: body)
        return URLSession.shared.rx.data(request: request) // this is in RxCocoa
    }

    func urlRequest(urlValue: String, body: [String: Any?]) -> URLRequest {
        guard let url = URL(string: urlValue) else { fatalError("Error with urlValue") }
        var request = URLRequest(url: url)
        let userKey = Bundle.main.userKeyValue
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue(userKey, forHTTPHeaderField: "userid")
        request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
        return request
    }
}
extension URLSession {
    func data(request: URLRequest) -> Observable<Data> {
        Observable.create { observer in
            let task = self.dataTask(with: request, completionHandler: { data, response, error in
                guard let response = response as? HTTPURLResponse else {
                    observer.onError(URLError.notHTTPResponse(data: data, response: response))
                    return
                }
                guard 200 <= response.statusCode && response.statusCode < 300 else {
                    observer.onError(URLError.failedResponse(data: data, response: response))
                    return
                }
                guard let data = data else {
                    observer.onError(error ?? RxError.unknown)
                    return
                }
                observer.onNext(data)
                observer.onCompleted() // be sure to call `onCompleted()` when you are done emitting values.
                // make sure every possible path through the code calls some method on `observer`.
            })
            return Disposables.create { task.cancel() } // don't forget to handle cancelation properly. You don't want to kill *all* tasks, just this one.
        }
    }
}

enum URLError: Error {
    case notHTTPResponse(data: Data?, response: URLResponse?)
    case failedResponse(data: Data?, response: HTTPURLResponse)
}

Combine - merging multiple shared filters

copy iconCopydownload iconDownload
Observable<Int>.create { observer in
    [1, 2, 3, 4, 5].forEach {
        observer.onNext($0)
    }
    observer.onCompleted()
    return Disposables.create()
}
let observable = emitSequence([1, 2, 3, 4, 5])
    .share(replay: 0, scope: .forever)

let filter1ʹ = observable
    .filter { $0 == 1 }
    .debug("filterʹ1")

let filter2ʹ = observable
    .filter { $0 == 2 }
    .debug("filterʹ2")

Observable.merge(filter1ʹ, filter2ʹ)
    .subscribe(onNext: {
        print("Resultʹ is: \($0)")
    })

func emitSequence<S>(_ sequence: S) -> Observable<S.Element> where S: Sequence {
    Observable.create { observer in
        sequence.forEach {
            observer.onNext($0)
        }
        observer.onCompleted()
        return Disposables.create()
    }
}
Observable<Int>.create { observer in
    [1, 2, 3, 4, 5].forEach {
        observer.onNext($0)
    }
    observer.onCompleted()
    return Disposables.create()
}
let observable = emitSequence([1, 2, 3, 4, 5])
    .share(replay: 0, scope: .forever)

let filter1ʹ = observable
    .filter { $0 == 1 }
    .debug("filterʹ1")

let filter2ʹ = observable
    .filter { $0 == 2 }
    .debug("filterʹ2")

Observable.merge(filter1ʹ, filter2ʹ)
    .subscribe(onNext: {
        print("Resultʹ is: \($0)")
    })

func emitSequence<S>(_ sequence: S) -> Observable<S.Element> where S: Sequence {
    Observable.create { observer in
        sequence.forEach {
            observer.onNext($0)
        }
        observer.onCompleted()
        return Disposables.create()
    }
}

How can execute operations sequentially and update UI

copy iconCopydownload iconDownload
class SyncManager {
    private init() { }
    static let shared = SyncManager()
    
    let refreshTokenStatus = BehaviorRelay<SyncStatus>(value: .todo)
    let updateCatalogDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
    let insertDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
    let getDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
    
    private let disposeBag = DisposeBag()
    
    func startDatabaseSync(completion: @escaping (Result<Void, Error>) -> Void) {
        let sync = Sync.startDatabaseSync()
        disposeBag.insert(
            sync.refreshTokenStatus.bind(to: refreshTokenStatus),
            sync.updateCatalogDataStatus.bind(to: updateCatalogDataStatus),
            sync.insertDataStatus.bind(to: insertDataStatus),
            sync.getDataStatus.bind(to: getDataStatus),
            sync.getDataStatus.subscribe(
                onError: { error in
                    completion(.failure(error))
                },
                onCompleted: {
                    completion(.success(()))
                }
            )
        )
    }
}

struct Sync {
    let refreshTokenStatus: Observable<SyncStatus>
    let updateCatalogDataStatus: Observable<SyncStatus>
    let getDataStatus: Observable<SyncStatus>
    let insertDataStatus: Observable<SyncStatus>
    
    static func startDatabaseSync() -> Sync {
        let refreshTokenStatus = handle(RefreshTokenManager.shared.refreshToken(), after: .just(.completed))
            .catchAndReturn(.error)
        let updateCatalogDataStatus = handle(UpdateCatalogDataSyncManager.shared.updateCatalogData(), after: refreshTokenStatus)
            .catchAndReturn(.error)
        let getDataStatus = handle(GetDataSyncManager.shared.getData(), after: updateCatalogDataStatus)
            .catchAndReturn(.error)
        let insertDataStatus = handle(InsertDataWorkSyncManager.shared.insertData(), after: getDataStatus)
            .catchAndReturn(.error)
        
        return Sync(
            refreshTokenStatus: refreshTokenStatus,
            updateCatalogDataStatus: updateCatalogDataStatus,
            getDataStatus: getDataStatus,
            insertDataStatus: insertDataStatus
        )
    }
}

func handle(_ operation: Single<Void>, after: Observable<SyncStatus>) -> Observable<SyncStatus> {
    after
        .ignoreElements()
        .asCompletable()
        .andThen(
            operation
                .map { SyncStatus.completed }
                .asObservable()
                .startWith(SyncStatus.running)
        )
        .startWith(.todo)
}

enum SyncStatus {
    case todo
    case completed
    case error
    case running
}

Community Discussions

Trending Discussions on RxSwift
  • How to reset and start new timer when enter new email
  • RxSwift | Best way to make consecutive network requests?
  • RxSwift Countdown time up to 0.1 seconds
  • Observe an RxSwift.BehaviorRelay just **before** a change happens
  • How to writ good test for my ViewModel? (RxSwift)
  • I have 2 view controllers with same logic but one of them is not working
  • What is &quot;Pod/***.a Pod/**.dia&quot; file?
  • How to use RxSwift to implement the following logic with UITextfield?
  • RxSwift/RxTest How to test async function with Observable return
  • Swift 5, RxSwift: Network request with RxSwift
Trending Discussions on RxSwift

QUESTION

How to reset and start new timer when enter new email

Asked 2022-Apr-01 at 23:25

I have an input that accept string, and store it in local data. My use case is when I enter an email, the user must wait for 2 minute for requesting send email verification. But when I enter a different email name, I can't make the timer reset when the last email I enter is still countdown. I'm using RxSwift for timer, I don't know how to invalidate the timer in RxSwift.

This is what I came so far to reset the timer when user enters new email

// function that accept email from uitextfield.text
func resendEmailCountdown(with email: String) {
        if email != getLoggedEmail() {
            startCountdown(countdown: 0)
            startCountdown(countdown: 120)
        } else {
            startCountdown(countdown: 120)
        }
    }
    
    private func startCountdown(countdown: Int) {
        let counter = countdown
        if counter == 0 {
            _ = Observable<Int>.timer(.seconds(0), period: .seconds(1), scheduler: MainScheduler.instance)
                .take(0)
                .subscribe(onNext: { [weak self] countdown in
                    guard let self = self else { return }
                    
                }).disposed(by: disposeBag)
        } else {
            _ = Observable<Int>.timer(.seconds(0), period: .seconds(1), scheduler: MainScheduler.instance)
                .take(counter + 1)
                .subscribe(onNext: { [weak self] countdown in
                    guard let self = self else { return }
                    let count = counter - countdown
                    if count != 0 {
                        self.eventResendEmailCountdown.onNext(count)
                        self.eventShowHideResendEmailButton.onNext(false)
                    } else {
                        self.eventShowHideResendEmailButton.onNext(true)
                        self.eventDismissCountdownBottomSheet.onNext(())
                    }
                }).disposed(by: disposeBag)
        }
        
    }

ANSWER

Answered 2022-Apr-01 at 23:25

The key is using flatMapLatest to cancel the previous timer and start up a new one.

Based on your description, here is what you need:

struct Output {
    let eventResendEmailCountdown: Observable<Int>
    let eventShowHideResendEmailButton: Observable<Bool>
    let eventDismissCountdownBottomSheet: Observable<Void>
}

func example(text: Observable<String?>) -> Output {
    let trigger = text.share()
    let eventResendEmailCountdown = trigger
        .flatMapLatest { _ in
            Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
                .map { 120 - $0 }
                .take(until: { $0 == -1 })
        }
    let eventShowHideResendEmailButton = Observable.merge(
        trigger.map { _ in false },
        eventResendEmailCountdown.filter { $0 == 0 }.map { _ in true }
    )
    let eventDismissCountdownBottomSheet = eventResendEmailCountdown
        .filter { $0 == 0 }
        .map { _ in }

    return Output(
        eventResendEmailCountdown: eventResendEmailCountdown,
        eventShowHideResendEmailButton: eventShowHideResendEmailButton,
        eventDismissCountdownBottomSheet: eventDismissCountdownBottomSheet
    )
}

Call it something like this:

let output = example(text: textField.rx.text.asObservable())

output.eventResendEmailCountdown
    .debug("eventResendEmailCountdown")
    .subscribe()

output.eventShowHideResendEmailButton
    .debug("eventShowHideResendEmailButton")
    .subscribe()

output.eventDismissCountdownBottomSheet
    .debug("eventDismissCountdownBottomSheet")
    .subscribe()

Source https://stackoverflow.com/questions/71708492

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install RxSwift

RxSwift doesn't contain any external dependencies.

Support

For any new features, suggestions and bugs create an issue on GitHub. If you have any questions check and ask questions on community page Stack Overflow .

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases
Explore Kits

Save this library and start creating your kit

Share this Page

share link
Consider Popular Reactive Programming Libraries
Try Top Libraries by ReactiveX
Compare Reactive Programming Libraries with Highest Support
Compare Reactive Programming Libraries with Highest Quality
Compare Reactive Programming Libraries with Highest Security
Compare Reactive Programming Libraries with Permissive License
Compare Reactive Programming Libraries with Highest Reuse
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases
Explore Kits

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.