├── .github
└── workflows
│ ├── create-release.yml
│ └── pull_request.yml
├── .gitignore
├── .jazzy.yaml
├── .swiftformat
├── .swiftlint.yml
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── .versionrc
├── Brewfile
├── CHANGELOG.md
├── Cartfile
├── Cartfile.resolved
├── Dangerfile
├── Examples
├── Podfile
├── Podfile.lock
├── RxRealmDemo-iOS
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ └── ViewController.swift
├── RxRealmDemo.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── RxRealmDemo-iOS.xcscheme
├── RxRealmDemo.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── pod_install.sh
└── project.yml
├── File
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── LICENSE.md
├── Package.resolved
├── Package.swift
├── README.md
├── RxRealm.podspec
├── RxRealm.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ ├── RxRealm iOS.xcscheme
│ ├── RxRealm macOS.xcscheme
│ ├── RxRealm tvOS.xcscheme
│ └── RxRealm watchOS.xcscheme
├── Sources
└── RxRealm
│ ├── Info.plist
│ ├── RealmObserver.swift
│ └── RxRealm.swift
├── Tests
├── LinuxMain.swift
└── RxRealmTests
│ ├── RxRealmLinkingObjectsTests.swift
│ ├── RxRealmListTests.swift
│ ├── RxRealmObjectTests.swift
│ ├── RxRealmOnQueueTests.swift
│ ├── RxRealmRealmTests.swift
│ ├── RxRealmResultsTests.swift
│ ├── RxRealmTests.swift
│ ├── RxRealmWriteSinks.swift
│ ├── TestModels.swift
│ └── XCTestManifests.swift
├── assets
└── animatedChanges.gif
├── cleanup.sh
├── pods.sh
├── project-carthage.yml
├── project-spm.yml
└── scripts
├── bump-version.sh
├── carthage.sh
└── xcframeworks.sh
/.github/workflows/create-release.yml:
--------------------------------------------------------------------------------
1 | name: Create release
2 |
3 | on:
4 | push:
5 | branches: [main]
6 |
7 | jobs:
8 | build:
9 | if: "!contains(github.event.head_commit.message, 'skip ci')"
10 | runs-on: macos-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 |
17 | - name: Fetch all tags
18 | run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
19 |
20 | - name: Bump version
21 | run: |
22 | chmod +x ./scripts/bump-version.sh
23 | ./scripts/bump-version.sh
24 |
25 | # - name: Changelog
26 | # uses: scottbrenner/generate-changelog-action@master
27 | # id: Changelog
28 | # env:
29 | # REPO: ${{ github.repository }}
30 |
31 | - name: Push changes
32 | uses: ad-m/github-push-action@master
33 | with:
34 | github_token: ${{ secrets.GITHUB_TOKEN }}
35 | branch: ${{ github.ref }}
36 |
37 | - name: Restore SPM Cache
38 | uses: actions/cache@v1
39 | with:
40 | path: .build
41 | key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
42 | restore-keys: |
43 | ${{ runner.os }}-spm-
44 |
45 | - name: Release XCFrameworks
46 | run: |
47 | chmod +x ./scripts/xcframeworks.sh
48 | ./scripts/xcframeworks.sh
49 |
50 | - name: Create Release
51 | id: create_release
52 | uses: actions/create-release@v1
53 | env:
54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55 | with:
56 | tag_name: ${{ env.RELEASE_VERSION }}
57 | release_name: RxRealm ${{ env.RELEASE_VERSION }}
58 | # body: |
59 | # ${{ steps.Changelog.outputs.changelog }}
60 | draft: false
61 | prerelease: false
62 |
63 | - name: Upload XCFramework
64 | uses: actions/upload-release-asset@v1
65 | env:
66 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67 | with:
68 | upload_url: ${{ steps.create_release.outputs.upload_url }}
69 | asset_path: ./RxRealm.xcframework.zip
70 | asset_name: RxRealm.xcframework.zip
71 | asset_content_type: application/zip
72 |
73 | - name: Deploy to Cocoapods
74 | run: |
75 | set -eo pipefail
76 | export RELEASE_VERSION="$(git describe --abbrev=0 | tr -d '\n')"
77 | RELEASE_VERSION=${RELEASE_VERSION:1}
78 | pod lib lint --allow-warnings
79 | pod trunk push --allow-warnings
80 | env:
81 | COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
82 |
--------------------------------------------------------------------------------
/.github/workflows/pull_request.yml:
--------------------------------------------------------------------------------
1 | name: Lint, build and test
2 |
3 | on:
4 | pull_request:
5 | branches: [main]
6 |
7 | jobs:
8 | build:
9 | runs-on: macos-latest
10 |
11 | steps:
12 | - uses: maxim-lobanov/setup-xcode@v1
13 | with:
14 | xcode-version: latest-stable
15 |
16 | - uses: actions/checkout@v2
17 | with:
18 | fetch-depth: 0
19 |
20 | - name: Fetch all tags
21 | run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
22 |
23 | - name: Resolve dependencies
24 | run: |
25 | brew bundle
26 | bundle
27 |
28 | # - name: Danger
29 | # run: |
30 | # bundle exec danger
31 | # env:
32 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33 |
34 | - name: Restore SPM Cache
35 | uses: actions/cache@v1
36 | with:
37 | path: .build
38 | key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
39 | restore-keys: |
40 | ${{ runner.os }}-spm-
41 |
42 | - name: Build and test (SPM)
43 | run: |
44 | swift build
45 | swift test
46 |
47 | - name: Build Cocoapods iOS Demo
48 | run: |
49 | set -eo pipefail
50 | cd Examples
51 | xcodegen
52 | pod install --repo-update
53 | xcodebuild build -scheme 'RxRealmDemo-iOS' -workspace 'RxRealmDemo.xcworkspace' -sdk iphonesimulator -destination "platform=iOS simulator,name=iPhone 11"
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.swp
20 |
21 | ## Other
22 | *.xccheckout
23 | *.moved-aside
24 | *.xcuserstate
25 | *.xcscmblueprint
26 |
27 | ## Obj-C/Swift specific
28 | *.hmap
29 | *.ipa
30 |
31 | # CocoaPods
32 | #
33 | # We recommend against adding the Pods directory to your .gitignore. However
34 | # you should judge for yourself, the pros and cons are mentioned at:
35 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36 | #
37 | Pods/
38 |
39 | # Carthage
40 | #
41 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
42 | Carthage/Checkouts
43 | Carthage/Build
44 |
45 | # Swift Package Manager
46 | .build
47 | Package.resolved
48 |
49 | .DS_Store
50 | **/.idea/**
51 |
52 | RxRealm-SPM.xcodeproj
--------------------------------------------------------------------------------
/.jazzy.yaml:
--------------------------------------------------------------------------------
1 | output: ../docs/RxRealm
2 | module: RxRealm
3 | xcodebuild_arguments:
4 | - -scheme
5 | - RxRealm iOS
--------------------------------------------------------------------------------
/.swiftformat:
--------------------------------------------------------------------------------
1 | --allman false
2 | --binarygrouping none
3 | --commas inline
4 | --comments ignore
5 | --decimalgrouping 3,6
6 | --elseposition same-line
7 | --empty void
8 | --exponentcase lowercase
9 | --exponentgrouping disabled
10 | --fractiongrouping disabled
11 | --disable blankLinesAroundMark
12 | --header ignore
13 | --hexgrouping 4,8
14 | --hexliteralcase uppercase
15 | --patternlet hoist
16 | --ifdef indent
17 | --indent 2
18 | --indentcase false
19 | --linebreaks lf
20 | --octalgrouping none
21 | --operatorfunc nospace
22 | --patternlet hoist
23 | --ranges nospace
24 | --self remove
25 | --semicolons inline
26 | --stripunusedargs closure-only
27 | --trimwhitespace always
28 | --wraparguments after-first
29 | --wrapcollections before-first
30 | --enable blankLinesBetweenScopes
31 | --enable redundantVoidReturnType
32 | --enable strongifiedSelf
33 | --enable trailingClosures
34 | --enable trailingSpace
35 | --enable typeSugar
36 | --enable spaceInsideParens
37 | --enable spaceInsideBrackets
38 | --enable spaceInsideBraces
39 | --enable spaceAroundOperators
40 | --enable spaceAroundBraces
41 | --enable redundantParens
42 | --enable redundantNilInit
43 | --enable consecutiveSpaces
44 | --enable anyObjectProtocol
45 | --disable isEmpty
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - trailing_whitespace
3 | - trailing_comma
4 | - large_tuple
5 | - nesting
6 | - todo
7 | - operator_whitespace
8 | - colon
9 | - identifier_name
10 |
11 | opt_in_rules: # some rules are only opt-in
12 | - empty_count
13 | - yoda_condition
14 | # Find all the available rules by running:
15 | # swiftlint rules
16 |
17 | included:
18 | - Sources
19 | - Tests
20 | - Examples/RxRealmDemo-iOS
21 |
22 | # excluded: # paths to ignore during linting. Takes precedence over `included`.
23 |
24 | # configurable rules can be customized from this configuration file
25 | # binary rules can set their severity level
26 | force_cast: warning # implicitly
27 | force_try:
28 | severity: warning # explicitly
29 | # rules that have both warning and error levels, can set just the warning level
30 | # implicitly
31 | line_length: 180
32 | # they can set both implicitly with an array
33 | function_body_length: 120
34 | type_body_length:
35 | - 400 # warning
36 | - 500 # error
37 | # or they can set both explicitly
38 | file_length:
39 | warning: 500
40 | error: 1200
41 | # naming rules can set warnings/errors for min_length and max_length
42 | # additionally they can set excluded names
43 | generic_type_name:
44 | min_length: 1 # only warning
45 | max_length: 30
46 |
47 | type_name:
48 | min_length: 2 # only warning
49 | max_length: # warning and error
50 | warning: 100
51 | error: 120
52 | excluded: iPhone # excluded via string
53 | identifier_name:
54 | min_length:
55 | warning: 1
56 | reporter: "xcode"
57 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.versionrc:
--------------------------------------------------------------------------------
1 | {
2 | "releaseCommitMessageFormat": "chore(release): {{currentTag}} [skip ci]",
3 | "compareUrlFormat": "{{host}}/{{owner}}/{{repository}}/branches/compare/{{currentTag}}%0D{{previousTag}}",
4 | "commitUrlFormat": "{{host}}/{{owner}}/{{repository}}/commits/{{hash}}"
5 | }
6 |
--------------------------------------------------------------------------------
/Brewfile:
--------------------------------------------------------------------------------
1 | brew "xcodegen"
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ### [5.0.8](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.8%0Dv5.0.7) (2024-05-07)
6 |
7 | ### [5.0.6](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.6%0Dv5.0.5) (2023-10-29)
8 |
9 | ### 5.0.5 (2022-03-09)
10 |
11 | ## [5.0.8](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.8%0Dv5.0.7) (2024-05-07)
12 |
13 | - Merge pull request #210 from trmquang93/main; override namespace Observable
14 |
15 | ## [5.0.7](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.7%0Dv5.0.6) (2024-03-08)
16 |
17 | ### Updates
18 | - Merge pull request #209 from markusfi/main; update RxRealm.podspec: Realm dependency updated to 10.44
19 |
20 | ## [5.0.6](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.6%0Dv5.0.5) (2023-10-29)
21 |
22 | ### Bug Fixes
23 |
24 | * ci ([66e43ab](https://github.com/RxSwiftCommunity/RxRealm/commits/66e43ab63448892cbef60d11468614795582a3e2))
25 |
26 | ## [5.0.5](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.5%0Dv5.0.4) (2022-03-09)
27 |
28 | ### Bug Fixes
29 |
30 | * replacing rx attribute of Realm type by standard Reactive extension. ([dabb105](https://github.com/RxSwiftCommunity/RxRealm/commits/dabb105c94a6c0fdccbf99bb618b618be3f0d5c0))
31 | * update Realm and RxSwift to latest version ([#178](https://github.com/RxSwiftCommunity/RxRealm/issues/178)) ([63d00c6](https://github.com/RxSwiftCommunity/RxRealm/commits/63d00c6349b31d4e26fd5b5a5e428400b6b91356))
32 |
33 | ## [5.0.4](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.4%0Dv5.0.3) (2022-01-16)
34 |
35 | ### Bug Fixes
36 |
37 | * replacing rx attribute of Realm type by standard Reactive extension. ([dabb105](https://github.com/RxSwiftCommunity/RxRealm/commits/dabb105c94a6c0fdccbf99bb618b618be3f0d5c0))
38 |
39 | ## [5.0.3](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.3%0Dv5.0.2) (2021-09-05)
40 |
41 | ## [5.0.2](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.2%0Dv5.0.1) (2021-05-10)
42 |
43 | ### Bug Fixes
44 |
45 | * Brew before generate project ([7eef1d1](https://github.com/RxSwiftCommunity/RxRealm/commits/7eef1d1ba130627af7d140682f912c89830cf1eb))
46 | * Bump version script fix ([8f9f99f](https://github.com/RxSwiftCommunity/RxRealm/commits/8f9f99f4680a07cbeedd63cfb7a26e269b907bf9))
47 |
48 | ## [5.0.1](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.1%0Dv5.0.0) (2021-01-04)
49 |
50 | ### Bug Fixes
51 |
52 | * Bump version script fix ([8f9f99f](https://github.com/RxSwiftCommunity/RxRealm/commits/8f9f99f4680a07cbeedd63cfb7a26e269b907bf9))
53 |
54 | ### Bug Fixes
55 |
56 | * Bump version script fix ([8f9f99f](https://github.com/RxSwiftCommunity/RxRealm/commits/8f9f99f4680a07cbeedd63cfb7a26e269b907bf9))
57 |
58 | ## [5.0.0](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v5.0.0%0Dv4.0.3) (2021-01-03)
59 |
60 | ### ⚠ BREAKING CHANGES
61 |
62 | * RxSwift 6.0.0 support
63 |
64 | ### Features
65 |
66 | * Supports xcframework as per release ([09c2a93](https://github.com/RxSwiftCommunity/RxRealm/commits/09c2a93da5e0ca43fa323e2c76f356d07320069d))
67 |
68 | ### Bug Fixes
69 |
70 | * Podspec version ([5c750e7](https://github.com/RxSwiftCommunity/RxRealm/commits/5c750e788284f54b981eaf2d7af5c3f1d61600a8))
71 |
72 | ## [4.0.3](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v4.0.3%0Dv4.0.2) (2020-12-20)
73 |
74 | ## [4.0.2](https://github.com/RxSwiftCommunity/RxRealm/branches/compare/v4.0.2%0Dv4.0.1) (2020-12-05)
75 |
76 | ## 4.0.1 (2020-12-05)
77 |
78 | Changelog
79 | =========
80 |
81 | 3.1.0
82 | _____
83 |
84 | - Bump minimum iOS version to 9.0 to sync with realm-cocoa
85 |
86 | 3.0.0
87 | _____
88 |
89 | - added support for Realm 5
90 | - added `queue` optional parameter to `changeset`, `array` and `collection` to specify realm notifications queue
91 |
--------------------------------------------------------------------------------
/Cartfile:
--------------------------------------------------------------------------------
1 | github "realm/realm-cocoa" ~> 10.21
2 | github "ReactiveX/RxSwift" ~> 6.1
3 |
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "ReactiveX/RxSwift" "6.5.0"
2 | github "realm/realm-cocoa" "v10.21.1"
3 |
--------------------------------------------------------------------------------
/Dangerfile:
--------------------------------------------------------------------------------
1 | # Sometimes it's a README fix, or something like that - which isn't relevant for
2 | # including in a project's CHANGELOG for example
3 | declared_trivial = (github.pr_title + github.pr_body).include?("#trivial")
4 |
5 | # Make it more obvious that a PR is a work in progress and shouldn't be merged yet
6 | warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]"
7 |
8 | # Warn summary on pull request
9 | if github.pr_body.length < 5
10 | warn "Please provide a summary in the Pull Request description"
11 | end
12 |
13 | # If these are all empty something has gone wrong, better to raise it in a comment
14 | if git.modified_files.empty? && git.added_files.empty? && git.deleted_files.empty?
15 | fail "This PR has no changes at all, this is likely a developer issue."
16 | end
17 |
18 | # Warn when there is a big PR
19 | message("Big PR") if git.lines_of_code > 500
20 | warn("Huge PR") if git.lines_of_code > 1000
21 | fail("Enormous PR. Please split this pull request.") if git.lines_of_code > 3000
22 |
23 | # Warn Cartfile changes
24 | message("Cartfile changed") if git.modified_files.include?("Cartfile")
25 | message("Cartfile.resolved changed") if git.modified_files.include?("Cartfile.resolved")
26 |
27 | # Lint
28 | swiftlint.lint_all_files = true
29 | swiftlint.max_num_violations = 20
30 | swiftlint.config_file = ".swiftlint.yml"
31 | swiftlint.lint_files fail_on_error: true
32 |
33 | # xcov.report(
34 | # scheme: "RxRealm iOS",
35 | # project: "RxRealm.xcodeproj",
36 | # include_targets: "RxRealm.framework",
37 | # minimum_coverage_percentage: 20.0,
38 | # derived_data_path: "Build/",
39 | # )
40 |
--------------------------------------------------------------------------------
/Examples/Podfile:
--------------------------------------------------------------------------------
1 | source "https://cdn.cocoapods.org/"
2 | project "RxRealmDemo.xcodeproj"
3 | use_frameworks!
4 |
5 | def common
6 | pod "RxRealm", :path => "../"
7 | end
8 |
9 | def common_tests
10 | pod "RxBlocking", "~> 6.0"
11 | end
12 |
13 | target "RxRealmDemo-iOS" do
14 | platform :ios, "12.0"
15 | common
16 | end
17 |
18 | # target "RxRealmDemo-macOS" do
19 | # platform :osx, "10.12"
20 | # common
21 | # end
22 |
23 | # target "RxRealmDemo-tvOS" do
24 | # platform :tvos, "9.0"
25 | # common
26 | # end
27 |
28 | post_install do |installer|
29 | installer.pods_project.targets.each do |target|
30 | target.build_configurations.each do |config|
31 | if Gem::Version.new('12.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'])
32 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/Examples/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Realm (10.50.0):
3 | - Realm/Headers (= 10.50.0)
4 | - Realm/Headers (10.50.0)
5 | - RealmSwift (10.50.0):
6 | - Realm (= 10.50.0)
7 | - RxCocoa (6.7.1):
8 | - RxRelay (= 6.7.1)
9 | - RxSwift (= 6.7.1)
10 | - RxRealm (5.0.8):
11 | - Realm (~> 10.50)
12 | - RealmSwift (~> 10.50)
13 | - RxCocoa (~> 6.1)
14 | - RxSwift (~> 6.1)
15 | - RxRelay (6.7.1):
16 | - RxSwift (= 6.7.1)
17 | - RxSwift (6.7.1)
18 |
19 | DEPENDENCIES:
20 | - RxRealm (from `../`)
21 |
22 | SPEC REPOS:
23 | trunk:
24 | - Realm
25 | - RealmSwift
26 | - RxCocoa
27 | - RxRelay
28 | - RxSwift
29 |
30 | EXTERNAL SOURCES:
31 | RxRealm:
32 | :path: "../"
33 |
34 | SPEC CHECKSUMS:
35 | Realm: a0a6a99e3dfa8959358a95c3c05845b5e5d6af30
36 | RealmSwift: fa111fb98e092a4dff1d0785ad0c3483feda607a
37 | RxCocoa: f5609cb4637587a7faa99c5d5787e3ad582b75a4
38 | RxRealm: 4858ba414f07514e38657d85807479bae6d0b9a9
39 | RxRelay: 4151ba01152436b08271e08410135e099880eae5
40 | RxSwift: b9a93a26031785159e11abd40d1a55bcb8057e52
41 |
42 | PODFILE CHECKSUM: df29b255dac1d305deddb3b085a7407b288544fc
43 |
44 | COCOAPODS: 1.14.0
45 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo-iOS/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import RealmSwift
2 | import UIKit
3 |
4 | let formatter: DateFormatter = {
5 | let f = DateFormatter()
6 | f.timeStyle = .long
7 | return f
8 | }()
9 |
10 | @UIApplicationMain
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 | var window: UIWindow?
13 |
14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
15 | // reset the realm on each app launch
16 | let realm = try! Realm()
17 | try! realm.write {
18 | realm.deleteAll()
19 | }
20 |
21 | return true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo-iOS/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo-iOS/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo-iOS/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/Examples/RxRealmDemo-iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo-iOS/ViewController.swift:
--------------------------------------------------------------------------------
1 | import RealmSwift
2 | import RxCocoa
3 | import RxRealm
4 | import RxSwift
5 | import UIKit
6 |
7 | // realm model
8 | class Lap: Object {
9 | @objc dynamic var time: TimeInterval = Date().timeIntervalSinceReferenceDate
10 | }
11 |
12 | class TickCounter: Object {
13 | @objc dynamic var id = UUID().uuidString
14 | @objc dynamic var ticks: Int = 0
15 | override static func primaryKey() -> String? { return "id" }
16 | }
17 |
18 | // view controller
19 | class ViewController: UIViewController {
20 | let bag = DisposeBag()
21 |
22 | @IBOutlet var tableView: UITableView!
23 | @IBOutlet var tickItemButton: UIBarButtonItem!
24 | @IBOutlet var addTwoItemsButton: UIBarButtonItem!
25 |
26 | var laps: Results!
27 |
28 | let footer: UILabel = {
29 | let l = UILabel()
30 | l.textAlignment = .center
31 | return l
32 | }()
33 |
34 | lazy var ticker: TickCounter = {
35 | let realm = try! Realm()
36 | let ticker = TickCounter()
37 | try! realm.write {
38 | realm.add(ticker)
39 | }
40 | return ticker
41 | }()
42 |
43 | override func viewDidLoad() {
44 | super.viewDidLoad()
45 |
46 | let realm = try! Realm()
47 | laps = realm.objects(Lap.self).sorted(byKeyPath: "time", ascending: false)
48 |
49 | /*
50 | Observable> - wrap Results as observable
51 | */
52 | Observable.collection(from: laps)
53 | .map { results in "laps: \(results.count)" }
54 | .subscribe { event in
55 | self.title = event.element
56 | }
57 | .disposed(by: bag)
58 |
59 | /*
60 | Observable> - reacting to change sets
61 | */
62 | Observable.changeset(from: laps)
63 | .subscribe(onNext: { [unowned self] _, changes in
64 | if let changes = changes {
65 | self.tableView.applyChangeset(changes)
66 | } else {
67 | self.tableView.reloadData()
68 | }
69 | })
70 | .disposed(by: bag)
71 |
72 | /*
73 | Use bindable sink to add objects
74 | */
75 | addTwoItemsButton.rx.tap
76 | .map { [Lap(), Lap()] }
77 | .bind(to: Realm.rx.add(onError: { elements, error in
78 | if let elements = elements {
79 | print("Error \(error.localizedDescription) while saving objects \(String(describing: elements))")
80 | } else {
81 | print("Error \(error.localizedDescription) while opening realm.")
82 | }
83 | }))
84 | .disposed(by: bag)
85 |
86 | /*
87 | Bind bar item to increasing the ticker
88 | */
89 | tickItemButton.rx.tap
90 | .subscribe(onNext: { [unowned self] _ in
91 | try! realm.write {
92 | self.ticker.ticks += 1
93 | }
94 | })
95 | .disposed(by: bag)
96 |
97 | /*
98 | Observing a single object
99 | */
100 | let tickerChanges$ = Observable.propertyChanges(object: ticker)
101 | tickerChanges$
102 | .filter { $0.name == "ticks" }
103 | .map { "\($0.newValue!) ticks" }
104 | .bind(to: footer.rx.text)
105 | .disposed(by: bag)
106 | }
107 | }
108 |
109 | extension ViewController: UITableViewDataSource {
110 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
111 | return laps.count
112 | }
113 |
114 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
115 | let lap = laps[indexPath.row]
116 |
117 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
118 | cell.textLabel?.text = formatter.string(from: Date(timeIntervalSinceReferenceDate: lap.time))
119 | return cell
120 | }
121 |
122 | func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
123 | return "Delete objects by tapping them, add ticks to trigger a footer update"
124 | }
125 | }
126 |
127 | extension ViewController: UITableViewDelegate {
128 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
129 | Observable.from([laps[indexPath.row]])
130 | .subscribe(Realm.rx.delete())
131 | .disposed(by: bag)
132 | }
133 |
134 | func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
135 | return footer
136 | }
137 | }
138 |
139 | extension UITableView {
140 | func applyChangeset(_ changes: RealmChangeset) {
141 | beginUpdates()
142 | deleteRows(at: changes.deleted.map { IndexPath(row: $0, section: 0) }, with: .automatic)
143 | insertRows(at: changes.inserted.map { IndexPath(row: $0, section: 0) }, with: .automatic)
144 | reloadRows(at: changes.updated.map { IndexPath(row: $0, section: 0) }, with: .automatic)
145 | endUpdates()
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 025AFE3743CE73F806425BAF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 26DE8661C8721C6102A4F087 /* LaunchScreen.xib */; };
11 | 13BD54D2BB0EBD66F4F2DADC /* Pods_RxRealmDemo_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 562FE4AD26713C0C4DEF9226 /* Pods_RxRealmDemo_iOS.framework */; };
12 | 3BB28BD3D65B1369D1A64960 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 54597D6B66FBF23FCBF1A7DB /* Images.xcassets */; };
13 | 84E694181E51B3B4646D1225 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 49505648CF8974BEF397F106 /* Main.storyboard */; };
14 | 8E1DB46DA84AA944224297EC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18CF27BE5242F49EDEA89577 /* ViewController.swift */; };
15 | DAEB28CFA861A50143F84323 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6298C0EF6C7C86E33743B8B5 /* AppDelegate.swift */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXFileReference section */
19 | 18CF27BE5242F49EDEA89577 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
20 | 5050BD06022D9BA067993ACD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
21 | 54597D6B66FBF23FCBF1A7DB /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
22 | 562FE4AD26713C0C4DEF9226 /* Pods_RxRealmDemo_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RxRealmDemo_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
23 | 6298C0EF6C7C86E33743B8B5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
24 | 645D257F7774284AE08348E5 /* RxRealmDemo-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RxRealmDemo-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
25 | 82BCDF2341D78059DF2C89F2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; };
26 | C430B976866CC45900487D76 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
27 | C5A5D55D5CC50F77DE071B83 /* Pods-RxRealmDemo-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxRealmDemo-iOS.debug.xcconfig"; path = "Target Support Files/Pods-RxRealmDemo-iOS/Pods-RxRealmDemo-iOS.debug.xcconfig"; sourceTree = ""; };
28 | E7759D109C2ABA35C4C5A7ED /* Pods-RxRealmDemo-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxRealmDemo-iOS.release.xcconfig"; path = "Target Support Files/Pods-RxRealmDemo-iOS/Pods-RxRealmDemo-iOS.release.xcconfig"; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 0452B0E845B69604F8EFBE7C /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | 13BD54D2BB0EBD66F4F2DADC /* Pods_RxRealmDemo_iOS.framework in Frameworks */,
37 | );
38 | runOnlyForDeploymentPostprocessing = 0;
39 | };
40 | /* End PBXFrameworksBuildPhase section */
41 |
42 | /* Begin PBXGroup section */
43 | 4A214DAA98C5247C1C84689A /* RxRealmDemo-iOS */ = {
44 | isa = PBXGroup;
45 | children = (
46 | 6298C0EF6C7C86E33743B8B5 /* AppDelegate.swift */,
47 | 54597D6B66FBF23FCBF1A7DB /* Images.xcassets */,
48 | 82BCDF2341D78059DF2C89F2 /* Info.plist */,
49 | 26DE8661C8721C6102A4F087 /* LaunchScreen.xib */,
50 | 49505648CF8974BEF397F106 /* Main.storyboard */,
51 | 18CF27BE5242F49EDEA89577 /* ViewController.swift */,
52 | );
53 | path = "RxRealmDemo-iOS";
54 | sourceTree = "";
55 | };
56 | 6531959FA0DFC568430ACAAB /* Products */ = {
57 | isa = PBXGroup;
58 | children = (
59 | 645D257F7774284AE08348E5 /* RxRealmDemo-iOS.app */,
60 | );
61 | name = Products;
62 | sourceTree = "";
63 | };
64 | A6E8CE38563E4EA24A16F2CD = {
65 | isa = PBXGroup;
66 | children = (
67 | 4A214DAA98C5247C1C84689A /* RxRealmDemo-iOS */,
68 | 6531959FA0DFC568430ACAAB /* Products */,
69 | C0D0418E03D8CC5CCBCA74A2 /* Pods */,
70 | CFCCE2C0EDE6F7ECC0D0B468 /* Frameworks */,
71 | );
72 | indentWidth = 2;
73 | sourceTree = "";
74 | tabWidth = 2;
75 | usesTabs = 0;
76 | };
77 | C0D0418E03D8CC5CCBCA74A2 /* Pods */ = {
78 | isa = PBXGroup;
79 | children = (
80 | C5A5D55D5CC50F77DE071B83 /* Pods-RxRealmDemo-iOS.debug.xcconfig */,
81 | E7759D109C2ABA35C4C5A7ED /* Pods-RxRealmDemo-iOS.release.xcconfig */,
82 | );
83 | path = Pods;
84 | sourceTree = "";
85 | };
86 | CFCCE2C0EDE6F7ECC0D0B468 /* Frameworks */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 562FE4AD26713C0C4DEF9226 /* Pods_RxRealmDemo_iOS.framework */,
90 | );
91 | name = Frameworks;
92 | sourceTree = "";
93 | };
94 | /* End PBXGroup section */
95 |
96 | /* Begin PBXNativeTarget section */
97 | 7063BECAEC79C49007CE0BA3 /* RxRealmDemo-iOS */ = {
98 | isa = PBXNativeTarget;
99 | buildConfigurationList = 960759C5E7AEB6ABF2CBF1A5 /* Build configuration list for PBXNativeTarget "RxRealmDemo-iOS" */;
100 | buildPhases = (
101 | 9E09E32F7F593B502A0A9650 /* [CP] Check Pods Manifest.lock */,
102 | 9F070CB36A79D85BB2876A0D /* Sources */,
103 | 5C6A37C6E8CA2E27A0ECA6AA /* Resources */,
104 | 0452B0E845B69604F8EFBE7C /* Frameworks */,
105 | 21A0E7521E409A56D88F9065 /* [CP] Embed Pods Frameworks */,
106 | );
107 | buildRules = (
108 | );
109 | dependencies = (
110 | );
111 | name = "RxRealmDemo-iOS";
112 | productName = "RxRealmDemo-iOS";
113 | productReference = 645D257F7774284AE08348E5 /* RxRealmDemo-iOS.app */;
114 | productType = "com.apple.product-type.application";
115 | };
116 | /* End PBXNativeTarget section */
117 |
118 | /* Begin PBXProject section */
119 | F0843B327272B2D17F77F290 /* Project object */ = {
120 | isa = PBXProject;
121 | attributes = {
122 | LastUpgradeCheck = 1220;
123 | ORGANIZATIONNAME = RxSwiftCommunity;
124 | };
125 | buildConfigurationList = 94914E22EBC7A74B395EF186 /* Build configuration list for PBXProject "RxRealmDemo" */;
126 | compatibilityVersion = "Xcode 11.0";
127 | developmentRegion = en;
128 | hasScannedForEncodings = 0;
129 | knownRegions = (
130 | Base,
131 | en,
132 | );
133 | mainGroup = A6E8CE38563E4EA24A16F2CD;
134 | productRefGroup = 6531959FA0DFC568430ACAAB /* Products */;
135 | projectDirPath = "";
136 | projectRoot = "";
137 | targets = (
138 | 7063BECAEC79C49007CE0BA3 /* RxRealmDemo-iOS */,
139 | );
140 | };
141 | /* End PBXProject section */
142 |
143 | /* Begin PBXResourcesBuildPhase section */
144 | 5C6A37C6E8CA2E27A0ECA6AA /* Resources */ = {
145 | isa = PBXResourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | 3BB28BD3D65B1369D1A64960 /* Images.xcassets in Resources */,
149 | 025AFE3743CE73F806425BAF /* LaunchScreen.xib in Resources */,
150 | 84E694181E51B3B4646D1225 /* Main.storyboard in Resources */,
151 | );
152 | runOnlyForDeploymentPostprocessing = 0;
153 | };
154 | /* End PBXResourcesBuildPhase section */
155 |
156 | /* Begin PBXShellScriptBuildPhase section */
157 | 21A0E7521E409A56D88F9065 /* [CP] Embed Pods Frameworks */ = {
158 | isa = PBXShellScriptBuildPhase;
159 | buildActionMask = 2147483647;
160 | files = (
161 | );
162 | inputFileListPaths = (
163 | "${PODS_ROOT}/Target Support Files/Pods-RxRealmDemo-iOS/Pods-RxRealmDemo-iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist",
164 | );
165 | name = "[CP] Embed Pods Frameworks";
166 | outputFileListPaths = (
167 | "${PODS_ROOT}/Target Support Files/Pods-RxRealmDemo-iOS/Pods-RxRealmDemo-iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist",
168 | );
169 | runOnlyForDeploymentPostprocessing = 0;
170 | shellPath = /bin/sh;
171 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RxRealmDemo-iOS/Pods-RxRealmDemo-iOS-frameworks.sh\"\n";
172 | showEnvVarsInLog = 0;
173 | };
174 | 9E09E32F7F593B502A0A9650 /* [CP] Check Pods Manifest.lock */ = {
175 | isa = PBXShellScriptBuildPhase;
176 | buildActionMask = 2147483647;
177 | files = (
178 | );
179 | inputFileListPaths = (
180 | );
181 | inputPaths = (
182 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
183 | "${PODS_ROOT}/Manifest.lock",
184 | );
185 | name = "[CP] Check Pods Manifest.lock";
186 | outputFileListPaths = (
187 | );
188 | outputPaths = (
189 | "$(DERIVED_FILE_DIR)/Pods-RxRealmDemo-iOS-checkManifestLockResult.txt",
190 | );
191 | runOnlyForDeploymentPostprocessing = 0;
192 | shellPath = /bin/sh;
193 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
194 | showEnvVarsInLog = 0;
195 | };
196 | /* End PBXShellScriptBuildPhase section */
197 |
198 | /* Begin PBXSourcesBuildPhase section */
199 | 9F070CB36A79D85BB2876A0D /* Sources */ = {
200 | isa = PBXSourcesBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | DAEB28CFA861A50143F84323 /* AppDelegate.swift in Sources */,
204 | 8E1DB46DA84AA944224297EC /* ViewController.swift in Sources */,
205 | );
206 | runOnlyForDeploymentPostprocessing = 0;
207 | };
208 | /* End PBXSourcesBuildPhase section */
209 |
210 | /* Begin PBXVariantGroup section */
211 | 26DE8661C8721C6102A4F087 /* LaunchScreen.xib */ = {
212 | isa = PBXVariantGroup;
213 | children = (
214 | 5050BD06022D9BA067993ACD /* Base */,
215 | );
216 | name = LaunchScreen.xib;
217 | sourceTree = "";
218 | };
219 | 49505648CF8974BEF397F106 /* Main.storyboard */ = {
220 | isa = PBXVariantGroup;
221 | children = (
222 | C430B976866CC45900487D76 /* Base */,
223 | );
224 | name = Main.storyboard;
225 | sourceTree = "";
226 | };
227 | /* End PBXVariantGroup section */
228 |
229 | /* Begin XCBuildConfiguration section */
230 | 0FCE882B186F10CBD63A5EF1 /* Debug */ = {
231 | isa = XCBuildConfiguration;
232 | baseConfigurationReference = C5A5D55D5CC50F77DE071B83 /* Pods-RxRealmDemo-iOS.debug.xcconfig */;
233 | buildSettings = {
234 | ASSETCATALOG_COMPILER_APPICON_NAME = "$(APP_ICON_NAME)";
235 | CODE_SIGN_IDENTITY = "iPhone Developer";
236 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
237 | INFOPLIST_FILE = "RxRealmDemo-iOS/Info.plist";
238 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
239 | LD_RUNPATH_SEARCH_PATHS = (
240 | "$(inherited)",
241 | "@executable_path/Frameworks",
242 | );
243 | OTHER_LDFLAGS = "-ObjC";
244 | PRODUCT_BUNDLE_IDENTIFIER = RxSwiftCommunity.RxRealm.iOSDemo;
245 | PRODUCT_NAME = "RxRealmDemo-iOS";
246 | SDKROOT = iphoneos;
247 | TARGETED_DEVICE_FAMILY = "1,2";
248 | };
249 | name = Debug;
250 | };
251 | 6628CAC057A227BFABA81B75 /* Debug */ = {
252 | isa = XCBuildConfiguration;
253 | buildSettings = {
254 | ALWAYS_SEARCH_USER_PATHS = NO;
255 | CLANG_ANALYZER_NONNULL = YES;
256 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
257 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
258 | CLANG_CXX_LIBRARY = "libc++";
259 | CLANG_ENABLE_MODULES = YES;
260 | CLANG_ENABLE_OBJC_ARC = YES;
261 | CLANG_ENABLE_OBJC_WEAK = YES;
262 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
263 | CLANG_WARN_BOOL_CONVERSION = YES;
264 | CLANG_WARN_COMMA = YES;
265 | CLANG_WARN_CONSTANT_CONVERSION = YES;
266 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
267 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
268 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
269 | CLANG_WARN_EMPTY_BODY = YES;
270 | CLANG_WARN_ENUM_CONVERSION = YES;
271 | CLANG_WARN_INFINITE_RECURSION = YES;
272 | CLANG_WARN_INT_CONVERSION = YES;
273 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
274 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
275 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
276 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
277 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
279 | CLANG_WARN_STRICT_PROTOTYPES = YES;
280 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
281 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
282 | CLANG_WARN_UNREACHABLE_CODE = YES;
283 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
284 | COPY_PHASE_STRIP = NO;
285 | DEBUG_INFORMATION_FORMAT = dwarf;
286 | ENABLE_STRICT_OBJC_MSGSEND = YES;
287 | ENABLE_TESTABILITY = YES;
288 | GCC_C_LANGUAGE_STANDARD = gnu11;
289 | GCC_DYNAMIC_NO_PIC = NO;
290 | GCC_NO_COMMON_BLOCKS = YES;
291 | GCC_OPTIMIZATION_LEVEL = 0;
292 | GCC_PREPROCESSOR_DEFINITIONS = (
293 | "$(inherited)",
294 | "DEBUG=1",
295 | );
296 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
297 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
298 | GCC_WARN_UNDECLARED_SELECTOR = YES;
299 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
300 | GCC_WARN_UNUSED_FUNCTION = YES;
301 | GCC_WARN_UNUSED_VARIABLE = YES;
302 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
303 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
304 | MTL_FAST_MATH = YES;
305 | ONLY_ACTIVE_ARCH = YES;
306 | PRODUCT_NAME = "$(TARGET_NAME)";
307 | SDKROOT = iphoneos;
308 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
309 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
310 | SWIFT_VERSION = 5.0;
311 | };
312 | name = Debug;
313 | };
314 | 84000E9CA8521983711240B4 /* Release */ = {
315 | isa = XCBuildConfiguration;
316 | baseConfigurationReference = E7759D109C2ABA35C4C5A7ED /* Pods-RxRealmDemo-iOS.release.xcconfig */;
317 | buildSettings = {
318 | ASSETCATALOG_COMPILER_APPICON_NAME = "$(APP_ICON_NAME)";
319 | CODE_SIGN_IDENTITY = "iPhone Developer";
320 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
321 | INFOPLIST_FILE = "RxRealmDemo-iOS/Info.plist";
322 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
323 | LD_RUNPATH_SEARCH_PATHS = (
324 | "$(inherited)",
325 | "@executable_path/Frameworks",
326 | );
327 | OTHER_LDFLAGS = "-ObjC";
328 | PRODUCT_BUNDLE_IDENTIFIER = RxSwiftCommunity.RxRealm.iOSDemo;
329 | PRODUCT_NAME = "RxRealmDemo-iOS";
330 | SDKROOT = iphoneos;
331 | TARGETED_DEVICE_FAMILY = "1,2";
332 | };
333 | name = Release;
334 | };
335 | B540E817A24A570773BA37C0 /* Release */ = {
336 | isa = XCBuildConfiguration;
337 | buildSettings = {
338 | ALWAYS_SEARCH_USER_PATHS = NO;
339 | CLANG_ANALYZER_NONNULL = YES;
340 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
341 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
342 | CLANG_CXX_LIBRARY = "libc++";
343 | CLANG_ENABLE_MODULES = YES;
344 | CLANG_ENABLE_OBJC_ARC = YES;
345 | CLANG_ENABLE_OBJC_WEAK = YES;
346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
347 | CLANG_WARN_BOOL_CONVERSION = YES;
348 | CLANG_WARN_COMMA = YES;
349 | CLANG_WARN_CONSTANT_CONVERSION = YES;
350 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
352 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
353 | CLANG_WARN_EMPTY_BODY = YES;
354 | CLANG_WARN_ENUM_CONVERSION = YES;
355 | CLANG_WARN_INFINITE_RECURSION = YES;
356 | CLANG_WARN_INT_CONVERSION = YES;
357 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
358 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
359 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
360 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
361 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
362 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
363 | CLANG_WARN_STRICT_PROTOTYPES = YES;
364 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
365 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
366 | CLANG_WARN_UNREACHABLE_CODE = YES;
367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
368 | COPY_PHASE_STRIP = NO;
369 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
370 | ENABLE_NS_ASSERTIONS = NO;
371 | ENABLE_STRICT_OBJC_MSGSEND = YES;
372 | GCC_C_LANGUAGE_STANDARD = gnu11;
373 | GCC_NO_COMMON_BLOCKS = YES;
374 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
375 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
376 | GCC_WARN_UNDECLARED_SELECTOR = YES;
377 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
378 | GCC_WARN_UNUSED_FUNCTION = YES;
379 | GCC_WARN_UNUSED_VARIABLE = YES;
380 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
381 | MTL_ENABLE_DEBUG_INFO = NO;
382 | MTL_FAST_MATH = YES;
383 | PRODUCT_NAME = "$(TARGET_NAME)";
384 | SDKROOT = iphoneos;
385 | SWIFT_COMPILATION_MODE = wholemodule;
386 | SWIFT_OPTIMIZATION_LEVEL = "-O";
387 | SWIFT_VERSION = 5.0;
388 | };
389 | name = Release;
390 | };
391 | /* End XCBuildConfiguration section */
392 |
393 | /* Begin XCConfigurationList section */
394 | 94914E22EBC7A74B395EF186 /* Build configuration list for PBXProject "RxRealmDemo" */ = {
395 | isa = XCConfigurationList;
396 | buildConfigurations = (
397 | 6628CAC057A227BFABA81B75 /* Debug */,
398 | B540E817A24A570773BA37C0 /* Release */,
399 | );
400 | defaultConfigurationIsVisible = 0;
401 | defaultConfigurationName = Release;
402 | };
403 | 960759C5E7AEB6ABF2CBF1A5 /* Build configuration list for PBXNativeTarget "RxRealmDemo-iOS" */ = {
404 | isa = XCConfigurationList;
405 | buildConfigurations = (
406 | 0FCE882B186F10CBD63A5EF1 /* Debug */,
407 | 84000E9CA8521983711240B4 /* Release */,
408 | );
409 | defaultConfigurationIsVisible = 0;
410 | defaultConfigurationName = Release;
411 | };
412 | /* End XCConfigurationList section */
413 | };
414 | rootObject = F0843B327272B2D17F77F290 /* Project object */;
415 | }
416 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo.xcodeproj/xcshareddata/xcschemes/RxRealmDemo-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Examples/RxRealmDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/pod_install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -eo pipefail
4 | export RELEASE_VERSION="$(git describe --abbrev=0 | tr -d '\n')"
5 | RELEASE_VERSION=${RELEASE_VERSION:1}
6 | xcodegen
7 | pod install --repo-update
8 | open RxRealmDemo.xcworkspace
--------------------------------------------------------------------------------
/Examples/project.yml:
--------------------------------------------------------------------------------
1 | name: RxRealmDemo
2 | options:
3 | minimumXcodeGenVersion: "2.15.1"
4 | developmentLanguage: en
5 | usesTabs: false
6 | indentWidth: 2
7 | tabWidth: 2
8 | xcodeVersion: "1220"
9 | deploymentTarget:
10 | iOS: "12.0"
11 | defaultConfig: "Release"
12 | configs:
13 | Debug: debug
14 | Release: release
15 | attributes:
16 | ORGANIZATIONNAME: RxSwiftCommunity
17 | schemes:
18 | RxRealmDemo-iOS:
19 | scheme: {}
20 | build:
21 | parallelizeBuild: true
22 | buildImplicitDependencies: true
23 | targets:
24 | RxRealmDemo-iOS: all
25 | run:
26 | config: Debug
27 | profile:
28 | config: Release
29 | analyze:
30 | config: Debug
31 | archive:
32 | config: Release
33 | revealArchiveInOrganizer: true
34 | # RxRealmDemo-tvOS:
35 | # scheme: {}
36 | # build:
37 | # parallelizeBuild: true
38 | # buildImplicitDependencies: true
39 | # targets:
40 | # RxRealmDemo-tvOS: all
41 | # run:
42 | # config: Debug
43 | # profile:
44 | # config: Release
45 | # analyze:
46 | # config: Debug
47 | # archive:
48 | # config: Release
49 | # revealArchiveInOrganizer: true
50 | targets:
51 | RxRealmDemo-iOS:
52 | type: application
53 | platform: iOS
54 | sources: [RxRealmDemo-iOS]
55 | settings:
56 | INFOPLIST_FILE: RxRealmDemo-iOS/Info.plist
57 | PRODUCT_NAME: RxRealmDemo-iOS
58 | OTHER_LDFLAGS: -ObjC
59 | PRODUCT_BUNDLE_IDENTIFIER: RxSwiftCommunity.RxRealm.iOSDemo
60 | ASSETCATALOG_COMPILER_APPICON_NAME: $(APP_ICON_NAME)
61 | DEBUG_INFORMATION_FORMAT: dwarf-with-dsym
62 | # RxRealmDemo-tvOS:
63 | # type: application
64 | # platform: tvOS
65 | # deploymentTarget: "10.0"
66 | # sources: [RxRealmDemo-tvOS]
67 | # settings:
68 | # INFOPLIST_FILE: RxRealmDemo-tvOS/Info.plist
69 | # PRODUCT_NAME: RxRealmDemo-tvOS
70 | # OTHER_LDFLAGS: -ObjC
71 | # PRODUCT_BUNDLE_IDENTIFIER: RxSwiftCommunity.RxRealm.tvOSDemo
72 | # ASSETCATALOG_COMPILER_APPICON_NAME: $(APP_ICON_NAME)
73 | # DEBUG_INFORMATION_FORMAT: dwarf-with-dsym
--------------------------------------------------------------------------------
/File:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RxSwiftCommunity/RxRealm/f64bf1c4b07612185eb0d4935b4ef9cf06679357/File
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'cocoapods', '~> 1.14'
4 | gem 'danger', '~> 8.0'
5 | gem 'danger-swiftlint', '~> 0.20'
6 | gem 'jazzy', '~> 0.13'
7 | gem 'xcov', '~> 1.7.3'
8 | gem 'danger-xcov', '~> 0.5'
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.6)
5 | rexml
6 | activesupport (7.1.1)
7 | base64
8 | bigdecimal
9 | concurrent-ruby (~> 1.0, >= 1.0.2)
10 | connection_pool (>= 2.2.5)
11 | drb
12 | i18n (>= 1.6, < 2)
13 | minitest (>= 5.1)
14 | mutex_m
15 | tzinfo (~> 2.0)
16 | addressable (2.8.5)
17 | public_suffix (>= 2.0.2, < 6.0)
18 | algoliasearch (1.27.5)
19 | httpclient (~> 2.8, >= 2.8.3)
20 | json (>= 1.5.1)
21 | artifactory (3.0.15)
22 | atomos (0.1.3)
23 | aws-eventstream (1.2.0)
24 | aws-partitions (1.834.0)
25 | aws-sdk-core (3.185.1)
26 | aws-eventstream (~> 1, >= 1.0.2)
27 | aws-partitions (~> 1, >= 1.651.0)
28 | aws-sigv4 (~> 1.5)
29 | jmespath (~> 1, >= 1.6.1)
30 | aws-sdk-kms (1.72.0)
31 | aws-sdk-core (~> 3, >= 3.184.0)
32 | aws-sigv4 (~> 1.1)
33 | aws-sdk-s3 (1.136.0)
34 | aws-sdk-core (~> 3, >= 3.181.0)
35 | aws-sdk-kms (~> 1)
36 | aws-sigv4 (~> 1.6)
37 | aws-sigv4 (1.6.0)
38 | aws-eventstream (~> 1, >= 1.0.2)
39 | babosa (1.0.4)
40 | base64 (0.1.1)
41 | bigdecimal (3.1.4)
42 | claide (1.1.0)
43 | claide-plugins (0.9.2)
44 | cork
45 | nap
46 | open4 (~> 1.3)
47 | cocoapods (1.14.0)
48 | addressable (~> 2.8)
49 | claide (>= 1.0.2, < 2.0)
50 | cocoapods-core (= 1.14.0)
51 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
52 | cocoapods-downloader (>= 2.0)
53 | cocoapods-plugins (>= 1.0.0, < 2.0)
54 | cocoapods-search (>= 1.0.0, < 2.0)
55 | cocoapods-trunk (>= 1.6.0, < 2.0)
56 | cocoapods-try (>= 1.1.0, < 2.0)
57 | colored2 (~> 3.1)
58 | escape (~> 0.0.4)
59 | fourflusher (>= 2.3.0, < 3.0)
60 | gh_inspector (~> 1.0)
61 | molinillo (~> 0.8.0)
62 | nap (~> 1.0)
63 | ruby-macho (>= 2.3.0, < 3.0)
64 | xcodeproj (>= 1.23.0, < 2.0)
65 | cocoapods-core (1.14.0)
66 | activesupport (>= 5.0, < 8)
67 | addressable (~> 2.8)
68 | algoliasearch (~> 1.0)
69 | concurrent-ruby (~> 1.1)
70 | fuzzy_match (~> 2.0.4)
71 | nap (~> 1.0)
72 | netrc (~> 0.11)
73 | public_suffix (~> 4.0)
74 | typhoeus (~> 1.0)
75 | cocoapods-deintegrate (1.0.5)
76 | cocoapods-downloader (2.0)
77 | cocoapods-plugins (1.0.0)
78 | nap
79 | cocoapods-search (1.0.1)
80 | cocoapods-trunk (1.6.0)
81 | nap (>= 0.8, < 2.0)
82 | netrc (~> 0.11)
83 | cocoapods-try (1.2.0)
84 | colored (1.2)
85 | colored2 (3.1.2)
86 | commander (4.6.0)
87 | highline (~> 2.0.0)
88 | concurrent-ruby (1.2.2)
89 | connection_pool (2.4.1)
90 | cork (0.3.0)
91 | colored2 (~> 3.1)
92 | danger (8.6.1)
93 | claide (~> 1.0)
94 | claide-plugins (>= 0.9.2)
95 | colored2 (~> 3.1)
96 | cork (~> 0.1)
97 | faraday (>= 0.9.0, < 2.0)
98 | faraday-http-cache (~> 2.0)
99 | git (~> 1.7)
100 | kramdown (~> 2.3)
101 | kramdown-parser-gfm (~> 1.0)
102 | no_proxy_fix
103 | octokit (~> 4.7)
104 | terminal-table (>= 1, < 4)
105 | danger-swiftlint (0.33.0)
106 | danger
107 | rake (> 10)
108 | thor (~> 0.19)
109 | danger-xcov (0.5.0)
110 | danger (>= 2.1)
111 | xcov (>= 1.7.3)
112 | declarative (0.0.20)
113 | digest-crc (0.6.5)
114 | rake (>= 12.0.0, < 14.0.0)
115 | domain_name (0.5.20190701)
116 | unf (>= 0.0.5, < 1.0.0)
117 | dotenv (2.8.1)
118 | drb (2.1.1)
119 | ruby2_keywords
120 | emoji_regex (3.2.3)
121 | escape (0.0.4)
122 | ethon (0.16.0)
123 | ffi (>= 1.15.0)
124 | excon (0.104.0)
125 | faraday (1.10.3)
126 | faraday-em_http (~> 1.0)
127 | faraday-em_synchrony (~> 1.0)
128 | faraday-excon (~> 1.1)
129 | faraday-httpclient (~> 1.0)
130 | faraday-multipart (~> 1.0)
131 | faraday-net_http (~> 1.0)
132 | faraday-net_http_persistent (~> 1.0)
133 | faraday-patron (~> 1.0)
134 | faraday-rack (~> 1.0)
135 | faraday-retry (~> 1.0)
136 | ruby2_keywords (>= 0.0.4)
137 | faraday-cookie_jar (0.0.7)
138 | faraday (>= 0.8.0)
139 | http-cookie (~> 1.0.0)
140 | faraday-em_http (1.0.0)
141 | faraday-em_synchrony (1.0.0)
142 | faraday-excon (1.1.0)
143 | faraday-http-cache (2.5.0)
144 | faraday (>= 0.8)
145 | faraday-httpclient (1.0.1)
146 | faraday-multipart (1.0.4)
147 | multipart-post (~> 2)
148 | faraday-net_http (1.0.1)
149 | faraday-net_http_persistent (1.2.0)
150 | faraday-patron (1.0.0)
151 | faraday-rack (1.0.0)
152 | faraday-retry (1.0.3)
153 | faraday_middleware (1.2.0)
154 | faraday (~> 1.0)
155 | fastimage (2.2.7)
156 | fastlane (2.216.0)
157 | CFPropertyList (>= 2.3, < 4.0.0)
158 | addressable (>= 2.8, < 3.0.0)
159 | artifactory (~> 3.0)
160 | aws-sdk-s3 (~> 1.0)
161 | babosa (>= 1.0.3, < 2.0.0)
162 | bundler (>= 1.12.0, < 3.0.0)
163 | colored
164 | commander (~> 4.6)
165 | dotenv (>= 2.1.1, < 3.0.0)
166 | emoji_regex (>= 0.1, < 4.0)
167 | excon (>= 0.71.0, < 1.0.0)
168 | faraday (~> 1.0)
169 | faraday-cookie_jar (~> 0.0.6)
170 | faraday_middleware (~> 1.0)
171 | fastimage (>= 2.1.0, < 3.0.0)
172 | gh_inspector (>= 1.1.2, < 2.0.0)
173 | google-apis-androidpublisher_v3 (~> 0.3)
174 | google-apis-playcustomapp_v1 (~> 0.1)
175 | google-cloud-storage (~> 1.31)
176 | highline (~> 2.0)
177 | http-cookie (~> 1.0.5)
178 | json (< 3.0.0)
179 | jwt (>= 2.1.0, < 3)
180 | mini_magick (>= 4.9.4, < 5.0.0)
181 | multipart-post (>= 2.0.0, < 3.0.0)
182 | naturally (~> 2.2)
183 | optparse (~> 0.1.1)
184 | plist (>= 3.1.0, < 4.0.0)
185 | rubyzip (>= 2.0.0, < 3.0.0)
186 | security (= 0.1.3)
187 | simctl (~> 1.6.3)
188 | terminal-notifier (>= 2.0.0, < 3.0.0)
189 | terminal-table (~> 3)
190 | tty-screen (>= 0.6.3, < 1.0.0)
191 | tty-spinner (>= 0.8.0, < 1.0.0)
192 | word_wrap (~> 1.0.0)
193 | xcodeproj (>= 1.13.0, < 2.0.0)
194 | xcpretty (~> 0.3.0)
195 | xcpretty-travis-formatter (>= 0.0.3)
196 | ffi (1.16.3)
197 | fourflusher (2.3.1)
198 | fuzzy_match (2.0.4)
199 | gh_inspector (1.1.3)
200 | git (1.18.0)
201 | addressable (~> 2.8)
202 | rchardet (~> 1.8)
203 | google-apis-androidpublisher_v3 (0.50.0)
204 | google-apis-core (>= 0.11.0, < 2.a)
205 | google-apis-core (0.11.1)
206 | addressable (~> 2.5, >= 2.5.1)
207 | googleauth (>= 0.16.2, < 2.a)
208 | httpclient (>= 2.8.1, < 3.a)
209 | mini_mime (~> 1.0)
210 | representable (~> 3.0)
211 | retriable (>= 2.0, < 4.a)
212 | rexml
213 | webrick
214 | google-apis-iamcredentials_v1 (0.17.0)
215 | google-apis-core (>= 0.11.0, < 2.a)
216 | google-apis-playcustomapp_v1 (0.13.0)
217 | google-apis-core (>= 0.11.0, < 2.a)
218 | google-apis-storage_v1 (0.19.0)
219 | google-apis-core (>= 0.9.0, < 2.a)
220 | google-cloud-core (1.6.0)
221 | google-cloud-env (~> 1.0)
222 | google-cloud-errors (~> 1.0)
223 | google-cloud-env (1.6.0)
224 | faraday (>= 0.17.3, < 3.0)
225 | google-cloud-errors (1.3.1)
226 | google-cloud-storage (1.44.0)
227 | addressable (~> 2.8)
228 | digest-crc (~> 0.4)
229 | google-apis-iamcredentials_v1 (~> 0.1)
230 | google-apis-storage_v1 (~> 0.19.0)
231 | google-cloud-core (~> 1.6)
232 | googleauth (>= 0.16.2, < 2.a)
233 | mini_mime (~> 1.0)
234 | googleauth (1.8.1)
235 | faraday (>= 0.17.3, < 3.a)
236 | jwt (>= 1.4, < 3.0)
237 | multi_json (~> 1.11)
238 | os (>= 0.9, < 2.0)
239 | signet (>= 0.16, < 2.a)
240 | highline (2.0.3)
241 | http-cookie (1.0.5)
242 | domain_name (~> 0.5)
243 | httpclient (2.8.3)
244 | i18n (1.14.1)
245 | concurrent-ruby (~> 1.0)
246 | jazzy (0.14.4)
247 | cocoapods (~> 1.5)
248 | mustache (~> 1.1)
249 | open4 (~> 1.3)
250 | redcarpet (~> 3.4)
251 | rexml (~> 3.2)
252 | rouge (>= 2.0.6, < 5.0)
253 | sassc (~> 2.1)
254 | sqlite3 (~> 1.3)
255 | xcinvoke (~> 0.3.0)
256 | jmespath (1.6.2)
257 | json (2.6.3)
258 | jwt (2.7.1)
259 | kramdown (2.4.0)
260 | rexml
261 | kramdown-parser-gfm (1.1.0)
262 | kramdown (~> 2.0)
263 | liferaft (0.0.6)
264 | mini_magick (4.12.0)
265 | mini_mime (1.1.5)
266 | mini_portile2 (2.8.4)
267 | minitest (5.20.0)
268 | molinillo (0.8.0)
269 | multi_json (1.15.0)
270 | multipart-post (2.3.0)
271 | mustache (1.1.1)
272 | mutex_m (0.1.2)
273 | nanaimo (0.3.0)
274 | nap (1.1.0)
275 | naturally (2.2.1)
276 | netrc (0.11.0)
277 | no_proxy_fix (0.1.2)
278 | octokit (4.25.1)
279 | faraday (>= 1, < 3)
280 | sawyer (~> 0.9)
281 | open4 (1.3.4)
282 | optparse (0.1.1)
283 | os (1.1.4)
284 | plist (3.7.0)
285 | public_suffix (4.0.7)
286 | rake (13.0.6)
287 | rchardet (1.8.0)
288 | redcarpet (3.6.0)
289 | representable (3.2.0)
290 | declarative (< 0.1.0)
291 | trailblazer-option (>= 0.1.1, < 0.2.0)
292 | uber (< 0.2.0)
293 | retriable (3.1.2)
294 | rexml (3.2.6)
295 | rouge (2.0.7)
296 | ruby-macho (2.5.1)
297 | ruby2_keywords (0.0.5)
298 | rubyzip (2.3.2)
299 | sassc (2.4.0)
300 | ffi (~> 1.9)
301 | sawyer (0.9.2)
302 | addressable (>= 2.3.5)
303 | faraday (>= 0.17.3, < 3)
304 | security (0.1.3)
305 | signet (0.18.0)
306 | addressable (~> 2.8)
307 | faraday (>= 0.17.5, < 3.a)
308 | jwt (>= 1.5, < 3.0)
309 | multi_json (~> 1.10)
310 | simctl (1.6.10)
311 | CFPropertyList
312 | naturally
313 | slack-notifier (2.4.0)
314 | sqlite3 (1.6.6)
315 | mini_portile2 (~> 2.8.0)
316 | terminal-notifier (2.0.0)
317 | terminal-table (3.0.2)
318 | unicode-display_width (>= 1.1.1, < 3)
319 | thor (0.20.3)
320 | trailblazer-option (0.1.2)
321 | tty-cursor (0.7.1)
322 | tty-screen (0.8.1)
323 | tty-spinner (0.9.3)
324 | tty-cursor (~> 0.7)
325 | typhoeus (1.4.0)
326 | ethon (>= 0.9.0)
327 | tzinfo (2.0.6)
328 | concurrent-ruby (~> 1.0)
329 | uber (0.1.0)
330 | unf (0.1.4)
331 | unf_ext
332 | unf_ext (0.0.8.2)
333 | unicode-display_width (2.5.0)
334 | webrick (1.8.1)
335 | word_wrap (1.0.0)
336 | xcinvoke (0.3.0)
337 | liferaft (~> 0.0.6)
338 | xcodeproj (1.23.0)
339 | CFPropertyList (>= 2.3.3, < 4.0)
340 | atomos (~> 0.1.3)
341 | claide (>= 1.0.2, < 2.0)
342 | colored2 (~> 3.1)
343 | nanaimo (~> 0.3.0)
344 | rexml (~> 3.2.4)
345 | xcov (1.7.5)
346 | fastlane (>= 2.141.0, < 3.0.0)
347 | multipart-post
348 | slack-notifier
349 | terminal-table
350 | xcodeproj
351 | xcresult (~> 0.2.0)
352 | xcpretty (0.3.0)
353 | rouge (~> 2.0.7)
354 | xcpretty-travis-formatter (1.0.1)
355 | xcpretty (~> 0.2, >= 0.0.7)
356 | xcresult (0.2.1)
357 |
358 | PLATFORMS
359 | ruby
360 |
361 | DEPENDENCIES
362 | cocoapods (~> 1.14)
363 | danger (~> 8.0)
364 | danger-swiftlint (~> 0.20)
365 | danger-xcov (~> 0.5)
366 | jazzy (~> 0.13)
367 | xcov (~> 1.7.3)
368 |
369 | BUNDLED WITH
370 | 2.1.4
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 RxSwiftCommunity
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Junior B.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "RealmDatabase",
6 | "repositoryURL": "https://github.com/realm/realm-core.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "9cf7ef4ad8e2f4c7a519c9a395ca3d253bb87aa8",
10 | "version": "14.6.2"
11 | }
12 | },
13 | {
14 | "package": "Realm",
15 | "repositoryURL": "https://github.com/realm/realm-swift.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "2000569f03948c281afc83c36c710ab15e5dd33c",
19 | "version": "10.50.0"
20 | }
21 | },
22 | {
23 | "package": "RxSwift",
24 | "repositoryURL": "https://github.com/ReactiveX/RxSwift.git",
25 | "state": {
26 | "branch": null,
27 | "revision": "b06a8c8596e4c3e8e7788e08e720e3248563ce6a",
28 | "version": "6.7.1"
29 | }
30 | }
31 | ]
32 | },
33 | "version": 1
34 | }
35 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.0
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(name: "RxRealm",
7 | platforms: [
8 | .macOS(.v10_10), .iOS(.v11), .tvOS(.v9), .watchOS(.v3)
9 | ],
10 | products: [
11 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
12 | .library(name: "RxRealm",
13 | targets: ["RxRealm"])
14 | ],
15 |
16 | dependencies: [
17 | // Dependencies declare other packages that this package depends on.
18 | .package(url: "https://github.com/realm/realm-swift.git", .upToNextMajor(from: "10.21.1")),
19 | .package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "6.5.0"))
20 | ],
21 |
22 | targets: [
23 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
24 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
25 | .target(name: "RxRealm",
26 | dependencies: [
27 | .product(name: "RxSwift", package: "RxSwift"),
28 | .product(name: "RealmSwift", package: "Realm"),
29 | .product(name: "RxCocoa", package: "RxSwift")
30 | ],
31 | path: "Sources"),
32 | .testTarget(name: "RxRealmTests",
33 | dependencies: [
34 | .byName(name: "RxRealm"),
35 | .product(name: "RxSwift", package: "RxSwift"),
36 | .product(name: "RxBlocking", package: "RxSwift"),
37 | .product(name: "RealmSwift", package: "Realm"),
38 | .product(name: "RxCocoa", package: "RxSwift")
39 | ])
40 | ],
41 | swiftLanguageVersions: [.v5])
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RxRealm
2 |
3 | [](https://github.com/Carthage/Carthage)
4 | [](http://cocoapods.org/pods/RxRealm)
5 | [](https://github.com/apple/swift-package-manager)
6 | [](http://cocoapods.org/pods/RxRealm)
7 | [](http://cocoapods.org/pods/RxRealm)
8 |
9 | This library is a thin wrapper around __RealmSwift__ ( [Realm Docs](https://realm.io/docs/swift/latest/) ).
10 |
11 | **Table of contents:**
12 |
13 | 1. [Observing object collections](https://github.com/RxSwiftCommunity/RxRealm#observing-object-collections)
14 | 2. [Observing a single object](https://github.com/RxSwiftCommunity/RxRealm#observing-a-single-object)
15 | 3. [Write transactions](https://github.com/RxSwiftCommunity/RxRealm#write-transactions)
16 | 4. [Automatically binding table and collection views](https://github.com/RxSwiftCommunity/RxRealm#automatically-binding-table-and-collection-views)
17 | 5. [Example app](https://github.com/RxSwiftCommunity/RxRealm#example-app)
18 |
19 | ## Observing object collections
20 |
21 | RxRealm can be used to create `Observable`s from objects of type `Results`, `List`, `LinkingObjects` or `AnyRealmCollection`. These types are typically used to load and observe object collections from the Realm Mobile Database.
22 |
23 | ##### `Observable.collection(from:synchronousStart:)`
24 | Emits an event each time the collection changes:
25 |
26 | ```swift
27 | let realm = try! Realm()
28 | let laps = realm.objects(Lap.self)
29 |
30 | Observable.collection(from: laps)
31 | .map {
32 | laps in "\(laps.count) laps"
33 | }
34 | .subscribe(onNext: { text in
35 | print(text)
36 | })
37 | ```
38 |
39 | The above prints out "X laps" each time a lap is added or removed from the database. If you set `synchronousStart` to `true` (the default value), the first element will be emitted synchronously - e.g. when you're binding UI it might not be possible for an asynchronous notification to come through.
40 |
41 | ##### `Observable.array(from:synchronousStart:)`
42 | Upon each change fetches a snapshot of the Realm collection and converts it to an array value (for example if you want to use array methods on the collection):
43 |
44 | ```swift
45 | let realm = try! Realm()
46 | let laps = realm.objects(Lap.self)
47 |
48 | Observable.array(from: laps)
49 | .map { array in
50 | return array.prefix(3) //slice of first 3 items
51 | }
52 | .subscribe(onNext: { text in
53 | print(text)
54 | })
55 | ```
56 |
57 | ##### `Observable.changeset(from:synchronousStart:)`
58 | Emits every time the collection changes and provides the exact indexes that has been deleted, inserted or updated:
59 |
60 | ```swift
61 | let realm = try! Realm()
62 | let laps = realm.objects(Lap.self)
63 |
64 | Observable.changeset(from: laps)
65 | .subscribe(onNext: { results, changes in
66 | if let changes = changes {
67 | // it's an update
68 | print(results)
69 | print("deleted: \(changes.deleted)")
70 | print("inserted: \(changes.inserted)")
71 | print("updated: \(changes.updated)")
72 | } else {
73 | // it's the initial data
74 | print(results)
75 | }
76 | })
77 | ```
78 |
79 | ##### `Observable.arrayWithChangeset(from:synchronousStart:)`
80 | Combines the result of `Observable.array(from:)` and `Observable.changeset(from:)` returning an `Observable, RealmChangeset?>`
81 |
82 | ```swift
83 | let realm = try! Realm()
84 | let laps = realm.objects(Lap.self))
85 |
86 | Observable.arrayWithChangeset(from: laps)
87 | .subscribe(onNext: { array, changes in
88 | if let changes = changes {
89 | // it's an update
90 | print(array.first)
91 | print("deleted: \(changes.deleted)")
92 | print("inserted: \(changes.inserted)")
93 | print("updated: \(changes.updated)")
94 | } else {
95 | // it's the initial data
96 | print(array)
97 | }
98 | })
99 | ```
100 |
101 | ## Observing a single object
102 |
103 | There's a separate API to make it easier to observe a single object:
104 |
105 | ```swift
106 | Observable.from(object: ticker)
107 | .map { ticker -> String in
108 | return "\(ticker.ticks) ticks"
109 | }
110 | .bindTo(footer.rx.text)
111 | ```
112 |
113 | This API uses the [Realm object notifications](https://realm.io/news/realm-objc-swift-2.4/) under the hood to listen for changes.
114 |
115 | This method will by default emit the object initial state as its first `next` event. You can disable this behavior by using the `emitInitialValue` parameter and setting it to `false`.
116 |
117 | Finally you can set changes to which properties constitute an object change you'd like to observe for:
118 |
119 | ```swift
120 | Observable.from(object: ticker, properties: ["name", "id", "family"]) ...
121 | ```
122 |
123 | ## Write transactions
124 |
125 | ##### `rx.add()`
126 |
127 | Writing objects to **existing** realm reference. You can add newly created objects to a Realm that you already have initialized:
128 |
129 | ```swift
130 | let realm = try! Realm()
131 | let messages = [Message("hello"), Message("world")]
132 |
133 | Observable.from(messages)
134 | .subscribe(realm.rx.add())
135 | ```
136 |
137 | Be careful, this will retain your Realm until the `Observable` completes or errors out.
138 |
139 | ##### `Realm.rx.add()`
140 |
141 | Writing to the default Realm. You can leave it to RxRealm to grab the default Realm on any thread your subscribe and write objects to it:
142 |
143 | ```swift
144 | let messages = [Message("hello"), Message("world")]
145 |
146 | Observable.from(messages)
147 | .subscribe(Realm.rx.add())
148 | ```
149 |
150 | ###### `Realm.rx.add(configuration:)`
151 |
152 | Writing to a **custom** Realm. If you want to switch threads and not use the default Realm, provide a `Realm.Configuration`. You an also provide an error handler for the observer to be called if either creating the realm reference or the write transaction raise an error:
153 |
154 | ```swift
155 | var config = Realm.Configuration()
156 | /* custom configuration settings */
157 |
158 | let messages = [Message("hello"), Message("world")]
159 | Observable.from(messages)
160 | .observeOn( /* you can switch threads here */ )
161 | .subscribe(Realm.rx.add(configuration: config, onError: {elements, error in
162 | if let elements = elements {
163 | print("Error \(error.localizedDescription) while saving objects \(String(describing: elements))")
164 | } else {
165 | print("Error \(error.localizedDescription) while opening realm.")
166 | }
167 | }))
168 | ```
169 |
170 | If you want to create a Realm on a different thread manually, allowing you to handle errors, you can do that too:
171 |
172 | ```swift
173 | let messages = [Message("hello"), Message("world")]
174 |
175 | Observable.from(messages)
176 | .observeOn( /* you can switch threads here */ )
177 | .subscribe(onNext: {messages in
178 | let realm = try! Realm()
179 | try! realm.write {
180 | realm.add(messages)
181 | }
182 | })
183 | ```
184 |
185 | ##### `rx.delete()`
186 |
187 | Deleting object(s) from an existing realm reference:
188 |
189 | ```swift
190 | let realm = try! Realm()
191 | let messages = realm.objects(Message.self)
192 | Observable.from(messages)
193 | .subscribe(realm.rx.delete())
194 | ```
195 |
196 | Be careful, this will retain your realm until the `Observable` completes or errors out.
197 |
198 | ##### `Realm.rx.delete()`
199 |
200 | Deleting from the object's realm automatically. You can leave it to RxRealm to grab the Realm from the first object and use it:
201 |
202 | ```swift
203 | Observable.from(someCollectionOfPersistedObjects)
204 | .subscribe(Realm.rx.delete())
205 | ```
206 |
207 | ## Automatically binding table and collection views
208 |
209 | RxRealm does not depend on UIKit/Cocoa and it doesn't provide built-in way to bind Realm collections to UI components.
210 |
211 | #### a) Non-animated binding
212 |
213 | You can use the built-in RxCocoa `bindTo(_:)` method, which will automatically drive your table view from your Realm results:
214 |
215 | ```swift
216 | Observable.from( [Realm collection] )
217 | .bindTo(tableView.rx.items) {tv, ip, element in
218 | let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
219 | cell.textLabel?.text = element.text
220 | return cell
221 | }
222 | .addDisposableTo(bag)
223 | ```
224 |
225 | #### b) Animated binding with RxRealmDataSources
226 |
227 | The separate library [RxRealmDataSources](https://github.com/RxSwiftCommunity/RxRealmDataSources) mimics the default data sources library behavior for RxSwift.
228 |
229 | `RxRealmDataSources` allows you to bind an observable collection of Realm objects directly to a table or collection view:
230 |
231 | ```swift
232 | // create data source
233 | let dataSource = RxTableViewRealmDataSource(
234 | cellIdentifier: "Cell", cellType: PersonCell.self) {cell, ip, lap in
235 | cell.customLabel.text = "\(ip.row). \(lap.text)"
236 | }
237 |
238 | // RxRealm to get Observable
239 | let realm = try! Realm()
240 | let lapsList = realm.objects(Timer.self).first!.laps
241 | let laps = Observable.changeset(from: lapsList)
242 |
243 | // bind to table view
244 | laps
245 | .bindTo(tableView.rx.realmChanges(dataSource))
246 | .addDisposableTo(bag)
247 | ```
248 |
249 | The data source will reflect all changes via animations to the table view:
250 |
251 | 
252 |
253 | If you want to learn more about the features beyond animating changes, check the __`RxRealmDataSources`__ [README](https://github.com/RxSwiftCommunity/RxRealmDataSources).
254 |
255 | ## Example app
256 |
257 | To run the example project, clone the repo, and run `pod install` from the Example directory first. The app uses RxSwift, RxCocoa using RealmSwift, RxRealm to observe Results from Realm.
258 |
259 | Further you're welcome to peak into the __RxRealmTests__ folder of the example app, which features the library's unit tests.
260 |
261 | ## Installation
262 |
263 | This library depends on both __RxSwift__ and __RealmSwift__ 1.0+.
264 |
265 | #### CocoaPods
266 |
267 | RxRealm requires CocoaPods 1.1.x or higher.
268 |
269 | RxRealm is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:
270 |
271 | ```ruby
272 | pod "RxRealm"
273 | ```
274 |
275 | #### Carthage
276 |
277 | To integrate RxRealm into your Xcode project using Carthage, specify it in your `Cartfile`:
278 |
279 | ```ogdl
280 | github "RxSwiftCommunity/RxRealm"
281 | ```
282 |
283 | Run `carthage update` to build the framework and drag the built `RxRealm.framework` into your Xcode project.
284 |
285 | #### Swift Package Manager
286 |
287 | In your Package.swift:
288 |
289 | ```swift
290 | let package = Package(
291 | name: "Example",
292 | dependencies: [
293 | .package(url: "https://github.com/RxSwiftCommunity/RxRealm.git", from: "1.0.1")
294 | ],
295 | targets: [
296 | .target(name: "Example", dependencies: ["RxRealm"])
297 | ]
298 | )
299 | ```
300 |
301 | ## TODO
302 |
303 | * Test add platforms and add compatibility for the pod
304 |
305 | ## License
306 |
307 | This library belongs to _RxSwiftCommunity_. Maintainer is [Marin Todorov](https://github.com/icanzilb).
308 |
309 | RxRealm is available under the MIT license. See the LICENSE file for more info.
310 |
--------------------------------------------------------------------------------
/RxRealm.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "RxRealm"
3 | # Version to always follow latest tag, with fallback to major
4 | s.version = "5.0.8"
5 | s.license = "MIT"
6 | s.description = <<-DESC
7 | This is an Rx extension that provides an easy and straight-forward way
8 | to use Realm's natively reactive collection type as an Observable
9 | DESC
10 |
11 | s.summary = "An Rx wrapper of Realm's notifications and write bindings"
12 | s.homepage = "https://github.com/RxSwiftCommunity/RxRealm"
13 | s.authors = { "RxSwift Community" => "community@rxswift.org" }
14 | s.source = { :git => "https://github.com/RxSwiftCommunity/RxRealm.git", :tag => "v" + s.version.to_s }
15 | s.swift_version = "5.1"
16 |
17 | s.ios.deployment_target = "12.0"
18 | s.osx.deployment_target = "10.13"
19 | s.tvos.deployment_target = "12.0"
20 | s.watchos.deployment_target = "4.0"
21 |
22 | s.requires_arc = true
23 |
24 | s.source_files = "Sources/RxRealm/*.swift"
25 |
26 | s.frameworks = "Foundation"
27 | s.dependency "Realm", "~> 10.50"
28 | s.dependency "RealmSwift", "~> 10.50"
29 | s.dependency "RxSwift", "~> 6.1"
30 | s.dependency "RxCocoa", "~> 6.1"
31 | end
32 |
--------------------------------------------------------------------------------
/RxRealm.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RxRealm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RxRealm.xcodeproj/xcshareddata/xcschemes/RxRealm iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
52 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
77 |
78 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/RxRealm.xcodeproj/xcshareddata/xcschemes/RxRealm macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
52 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
77 |
78 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/RxRealm.xcodeproj/xcshareddata/xcschemes/RxRealm tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
52 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
77 |
78 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/RxRealm.xcodeproj/xcshareddata/xcschemes/RxRealm watchOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
53 |
59 |
60 |
61 |
62 |
68 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/Sources/RxRealm/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Sources/RxRealm/RealmObserver.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RxRealm extensions
3 | //
4 | // Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
5 | // Created by sergdort on 6/3/16.
6 | //
7 |
8 | import Foundation
9 | import RealmSwift
10 | import RxSwift
11 |
12 | /**
13 | `RealmObserver` retains target realm object until it receives a .Completed or .Error event
14 | or the observer is being deinitialized
15 | */
16 | class RealmObserver: ObserverType {
17 | var realm: Realm?
18 | var configuration: Realm.Configuration?
19 |
20 | let binding: (Realm?, Element, Error?) -> Void
21 |
22 | init(realm: Realm, binding: @escaping (Realm?, Element, Error?) -> Void) {
23 | self.realm = realm
24 | self.binding = binding
25 | }
26 |
27 | init(configuration: Realm.Configuration, binding: @escaping (Realm?, Element, Error?) -> Void) {
28 | self.configuration = configuration
29 | self.binding = binding
30 | }
31 |
32 | /**
33 | Binds next element
34 | */
35 | func on(_ event: Event) {
36 | switch event {
37 | case let .next(element):
38 | // this will "cache" the realm on this thread, until completed/errored
39 | if let configuration = configuration, realm == nil {
40 | do {
41 | let realm = try Realm(configuration: configuration)
42 | binding(realm, element, nil)
43 | } catch let e {
44 | binding(nil, element, e)
45 | }
46 | return
47 | }
48 |
49 | guard let realm = realm else {
50 | fatalError("No realm in RealmObserver at time of a .Next event")
51 | }
52 |
53 | binding(realm, element, nil)
54 |
55 | case .error:
56 | realm = nil
57 | case .completed:
58 | realm = nil
59 | }
60 | }
61 |
62 | /**
63 | Erases the type of observer
64 |
65 | - returns: AnyObserver, type erased observer
66 | */
67 | func asObserver() -> AnyObserver {
68 | return AnyObserver(eventHandler: on)
69 | }
70 |
71 | deinit {
72 | realm = nil
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Sources/RxRealm/RxRealm.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RxRealm extensions
3 | //
4 | // Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
5 | // Check the LICENSE file for details
6 | // Created by Marin Todorov
7 | //
8 |
9 | import Foundation
10 | import RealmSwift
11 | import RxSwift
12 |
13 | public typealias Observable = RxSwift.Observable
14 |
15 | public enum RxRealmError: Error {
16 | case objectDeleted
17 | case unknown
18 | }
19 |
20 | // MARK: Realm Collections type extensions
21 |
22 | /**
23 | `NotificationEmitter` is a protocol to allow for Realm's collections to be handled in a generic way.
24 |
25 | All collections already include a `addNotificationBlock(_:)` method - making them conform to `NotificationEmitter` just makes it easier to add Rx methods to them.
26 |
27 | The methods of essence in this protocol are `asObservable(...)`, which allow for observing for changes on Realm's collections.
28 | */
29 | public protocol NotificationEmitter {
30 | associatedtype ElementType: RealmCollectionValue
31 |
32 | /**
33 | Returns a `NotificationToken`, which while retained enables change notifications for the current collection.
34 |
35 | - returns: `NotificationToken` - retain this value to keep notifications being emitted for the current collection.
36 | */
37 | func observe(keyPaths: [String]?,
38 | on queue: DispatchQueue?,
39 | _ block: @escaping (RealmCollectionChange) -> Void) -> NotificationToken
40 |
41 | func toArray() -> [ElementType]
42 |
43 | func toAnyCollection() -> AnyRealmCollection
44 | }
45 |
46 | extension List: NotificationEmitter {
47 | public func toAnyCollection() -> AnyRealmCollection {
48 | return AnyRealmCollection(self)
49 | }
50 |
51 | public typealias ElementType = Element
52 | public func toArray() -> [Element] {
53 | return Array(self)
54 | }
55 | }
56 |
57 | extension AnyRealmCollection: NotificationEmitter {
58 | public func toAnyCollection() -> AnyRealmCollection {
59 | return AnyRealmCollection(self)
60 | }
61 |
62 | public typealias ElementType = Element
63 | public func toArray() -> [Element] {
64 | return Array(self)
65 | }
66 | }
67 |
68 | extension Results: NotificationEmitter {
69 | public func toAnyCollection() -> AnyRealmCollection {
70 | return AnyRealmCollection(self)
71 | }
72 |
73 | public typealias ElementType = Element
74 | public func toArray() -> [Element] {
75 | return Array(self)
76 | }
77 | }
78 |
79 | extension LinkingObjects: NotificationEmitter {
80 | public func toAnyCollection() -> AnyRealmCollection {
81 | return AnyRealmCollection(self)
82 | }
83 |
84 | public typealias ElementType = Element
85 | public func toArray() -> [Element] {
86 | return Array(self)
87 | }
88 | }
89 |
90 | /**
91 | `RealmChangeset` is a struct that contains the data about a single realm change set.
92 |
93 | It includes the insertions, modifications, and deletions indexes in the data set that the current notification is about.
94 | */
95 | public struct RealmChangeset {
96 | /// the indexes in the collection that were deleted
97 | public let deleted: [Int]
98 |
99 | /// the indexes in the collection that were inserted
100 | public let inserted: [Int]
101 |
102 | /// the indexes in the collection that were modified
103 | public let updated: [Int]
104 | }
105 |
106 | public extension ObservableType where Element: NotificationEmitter {
107 | @available(*, deprecated, renamed: "collection(from:synchronousStart:)")
108 | static func from(_ collection: Element, scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable {
109 | return self.collection(from: collection)
110 | }
111 |
112 | /**
113 | Returns an `Observable` that emits each time the collection data changes.
114 | The observable emits an initial value upon subscription.
115 |
116 | - parameter from: A Realm collection of type `Element`: either `Results`, `List`, `LinkingObjects` or `AnyRealmCollection`.
117 | - parameter synchronousStart: whether the resulting `Observable` should emit its first element synchronously (e.g. better for UI bindings)
118 | - parameter keyPaths: Only properties contained in the key paths array will trigger
119 | the block when they are modified. See description above for more detail on linked properties.
120 | - parameter queue: The serial dispatch queue to receive notification on. If `nil`, notifications are delivered to the current thread.
121 |
122 | - returns: `Observable`, e.g. when called on `Results` it will return `Observable>`, on a `List` it will return `Observable>`, etc.
123 | */
124 | static func collection(from collection: Element, synchronousStart: Bool = true, keyPaths: [String]? = nil, on queue: DispatchQueue? = nil)
125 | -> Observable {
126 | return Observable.create { observer in
127 | if synchronousStart {
128 | observer.onNext(collection)
129 | }
130 |
131 | let token = collection.observe(keyPaths: keyPaths, on: queue) { changeset in
132 |
133 | let value: Element
134 |
135 | switch changeset {
136 | case let .initial(latestValue):
137 | guard !synchronousStart else { return }
138 | value = latestValue
139 |
140 | case let .update(latestValue, _, _, _):
141 | value = latestValue
142 |
143 | case let .error(error):
144 | observer.onError(error)
145 | return
146 | }
147 |
148 | observer.onNext(value)
149 | }
150 |
151 | return Disposables.create {
152 | token.invalidate()
153 | }
154 | }
155 | }
156 |
157 | @available(*, deprecated, renamed: "array(from:synchronousStart:)")
158 | static func arrayFrom(_ collection: Element, scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable<[Element.ElementType]> {
159 | return array(from: collection)
160 | }
161 |
162 | /**
163 | Returns an `Observable>` that emits each time the collection data changes. The observable emits an initial value upon subscription.
164 | The result emits an array containing all objects from the source collection.
165 |
166 | - parameter from: A Realm collection of type `Element`: either `Results`, `List`, `LinkingObjects` or `AnyRealmCollection`.
167 | - parameter synchronousStart: whether the resulting Observable should emit its first element synchronously (e.g. better for UI bindings)
168 | - parameter queue: The serial dispatch queue to receive notification on. If `nil`, notifications are delivered to the current thread.
169 |
170 | - returns: `Observable>`, e.g. when called on `Results` it will return `Observable>`, on a `List` it will return `Observable>`, etc.
171 | */
172 | static func array(from collection: Element, synchronousStart: Bool = true, on queue: DispatchQueue? = nil)
173 | -> Observable<[Element.ElementType]> {
174 | return Observable.collection(from: collection, synchronousStart: synchronousStart, on: queue)
175 | .map { $0.toArray() }
176 | }
177 |
178 | @available(*, deprecated, renamed: "changeset(from:synchronousStart:)")
179 | static func changesetFrom(_ collection: Element, scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable<(AnyRealmCollection, RealmChangeset?)> {
180 | return changeset(from: collection)
181 | }
182 |
183 | /**
184 | Returns an `Observable<(Element, RealmChangeset?)>` that emits each time the collection data changes. The observable emits an initial value upon subscription.
185 |
186 | When the observable emits for the first time (if the initial notification is not coalesced with an update) the second tuple value will be `nil`.
187 |
188 | Each following emit will include a `RealmChangeset` with the indexes inserted, deleted or modified.
189 |
190 | - parameter from: A Realm collection of type `Element`: either `Results`, `List`, `LinkingObjects` or `AnyRealmCollection`.
191 | - parameter synchronousStart: whether the resulting Observable should emit its first element synchronously (e.g. better for UI bindings)
192 | - parameter queue: The serial dispatch queue to receive notification on. If `nil`, notifications are delivered to the current thread.
193 |
194 | - returns: `Observable<(AnyRealmCollection, RealmChangeset?)>`
195 | */
196 | static func changeset(from collection: Element, synchronousStart: Bool = true, on queue: DispatchQueue? = nil)
197 | -> Observable<(AnyRealmCollection, RealmChangeset?)> {
198 | return Observable.create { observer in
199 | if synchronousStart {
200 | observer.onNext((collection.toAnyCollection(), nil))
201 | }
202 |
203 | let token = collection.toAnyCollection().observe(on: queue) { changeset in
204 |
205 | switch changeset {
206 | case let .initial(value):
207 | guard !synchronousStart else { return }
208 | observer.onNext((value, nil))
209 | case let .update(value, deletes, inserts, updates):
210 | observer.onNext((value, RealmChangeset(deleted: deletes, inserted: inserts, updated: updates)))
211 | case let .error(error):
212 | observer.onError(error)
213 | return
214 | }
215 | }
216 |
217 | return Disposables.create {
218 | token.invalidate()
219 | }
220 | }
221 | }
222 |
223 | @available(*, deprecated, renamed: "arrayWithChangeset(from:synchronousStart:)")
224 | static func changesetArrayFrom(_ collection: Element, scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable<([Element.ElementType], RealmChangeset?)> {
225 | return arrayWithChangeset(from: collection)
226 | }
227 |
228 | /**
229 | Returns an `Observable<(Array, RealmChangeset?)>` that emits each time the collection data changes. The observable emits an initial value upon subscription.
230 |
231 | This method emits an `Array` containing all the realm collection objects, this means they all live in the memory. If you're using this method to observe large collections you might hit memory warnings.
232 |
233 | When the observable emits for the first time (if the initial notification is not coalesced with an update) the second tuple value will be `nil`.
234 |
235 | Each following emit will include a `RealmChangeset` with the indexes inserted, deleted or modified.
236 |
237 | - parameter from: A Realm collection of type `Element`: either `Results`, `List`, `LinkingObjects` or `AnyRealmCollection`.
238 | - parameter synchronousStart: whether the resulting Observable should emit its first element synchronously (e.g. better for UI bindings)
239 | - parameter queue: The serial dispatch queue to receive notification on. If `nil`, notifications are delivered to the current thread.
240 |
241 | - returns: `Observable<(Array, RealmChangeset?)>`
242 | */
243 | static func arrayWithChangeset(from collection: Element, synchronousStart: Bool = true, on queue: DispatchQueue? = nil)
244 | -> Observable<([Element.ElementType], RealmChangeset?)> {
245 | return Observable.changeset(from: collection, on: queue)
246 | .map { ($0.toArray(), $1) }
247 | }
248 | }
249 |
250 | public extension Observable {
251 | @available(*, deprecated, renamed: "from(realm:)")
252 | static func from(_ realm: Realm, scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable<(Realm, Realm.Notification)> {
253 | return from(realm: realm)
254 | }
255 |
256 | /**
257 | Returns an `Observable<(Realm, Realm.Notification)>` that emits each time the Realm emits a notification.
258 |
259 | The Observable you will get emits a tuple made out of:
260 |
261 | * the realm that emitted the event
262 | * the notification type: this can be either `.didChange` which occurs after a refresh or a write transaction ends,
263 | or `.refreshRequired` which happens when a write transaction occurs from a different thread on the same realm file
264 |
265 | For more information look up: [Realm.Notification](https://realm.io/docs/swift/latest/api/Enums/Notification.html)
266 |
267 | - parameter realm: A Realm instance
268 | - returns: `Observable<(Realm, Realm.Notification)>`, which you can subscribe to
269 | */
270 | static func from(realm: Realm) -> RxSwift.Observable<(Realm, Realm.Notification)> {
271 | return RxSwift.Observable<(Realm, Realm.Notification)>.create { observer in
272 | let token = realm.observe { (notification: Realm.Notification, realm: Realm) in
273 | observer.onNext((realm, notification))
274 | }
275 |
276 | return Disposables.create {
277 | token.invalidate()
278 | }
279 | }
280 | }
281 | }
282 |
283 | // MARK: Realm type extensions
284 |
285 | extension Realm: ReactiveCompatible {}
286 |
287 | public extension Reactive where Base == Realm {
288 | /**
289 | Returns bindable sink wich adds object sequence to the current Realm
290 |
291 | - parameter: update - update according to Realm.UpdatePolicy
292 | - parameter: onError - closure to implement custom error handling
293 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
294 | */
295 | func add(update: Realm.UpdatePolicy = .error, onError: ((S?, Error) -> Void)? = nil)
296 | -> AnyObserver where S.Iterator.Element: Object {
297 | return RealmObserver(realm: base) { realm, elements, error in
298 | guard let realm = realm else {
299 | onError?(nil, error ?? RxRealmError.unknown)
300 | return
301 | }
302 |
303 | do {
304 | try realm.write {
305 | realm.add(elements, update: update)
306 | }
307 | } catch let e {
308 | onError?(elements, e)
309 | }
310 | }
311 | .asObserver()
312 | }
313 |
314 | /**
315 | Returns bindable sink wich adds an object to Realm
316 |
317 | - parameter: update - update according to Realm.UpdatePolicy
318 | - parameter: onError - closure to implement custom error handling
319 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
320 | */
321 | func add(update: Realm.UpdatePolicy = .error,
322 | onError: ((O?, Error) -> Void)? = nil) -> AnyObserver {
323 | return RealmObserver(realm: base) { realm, element, error in
324 | guard let realm = realm else {
325 | onError?(nil, error ?? RxRealmError.unknown)
326 | return
327 | }
328 |
329 | do {
330 | try realm.write {
331 | realm.add(element, update: update)
332 | }
333 | } catch let e {
334 | onError?(element, e)
335 | }
336 | }.asObserver()
337 | }
338 |
339 | /**
340 | Returns bindable sink wich deletes objects in sequence from Realm.
341 |
342 | - parameter: onError - closure to implement custom error handling
343 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
344 | */
345 | func delete(onError: ((S?, Error) -> Void)? = nil)
346 | -> AnyObserver where S.Iterator.Element: Object {
347 | return RealmObserver(realm: base, binding: { realm, elements, error in
348 | guard let realm = realm else {
349 | onError?(nil, error ?? RxRealmError.unknown)
350 | return
351 | }
352 |
353 | do {
354 | try realm.write {
355 | realm.delete(elements)
356 | }
357 | } catch let e {
358 | onError?(elements, e)
359 | }
360 | }).asObserver()
361 | }
362 |
363 | /**
364 | Returns bindable sink wich deletes objects in sequence from Realm.
365 |
366 | - parameter: onError - closure to implement custom error handling
367 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
368 | */
369 | func delete(onError: ((O?, Error) -> Void)? = nil) -> AnyObserver {
370 | return RealmObserver(realm: base, binding: { realm, element, error in
371 | guard let realm = realm else {
372 | onError?(nil, error ?? RxRealmError.unknown)
373 | return
374 | }
375 |
376 | do {
377 | try realm.write {
378 | realm.delete(element)
379 | }
380 | } catch let e {
381 | onError?(element, e)
382 | }
383 | }).asObserver()
384 | }
385 | }
386 |
387 | public extension Reactive where Base == Realm {
388 | /**
389 | Returns bindable sink wich adds object sequence to a Realm
390 |
391 | - parameter: configuration (by default uses `Realm.Configuration.defaultConfiguration`)
392 | to use to get a Realm for the write operations
393 | - parameter: update - update according to Realm.UpdatePolicy
394 | - parameter: onError - closure to implement custom error handling
395 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
396 | */
397 | static func add(configuration: Realm.Configuration = Realm.Configuration.defaultConfiguration,
398 | update: Realm.UpdatePolicy = .error,
399 | onError: ((S?, Error) -> Void)? = nil) -> AnyObserver where S.Iterator.Element: Object {
400 | return RealmObserver(configuration: configuration) { realm, elements, error in
401 | guard let realm = realm else {
402 | onError?(nil, error ?? RxRealmError.unknown)
403 | return
404 | }
405 |
406 | do {
407 | try realm.write {
408 | realm.add(elements, update: update)
409 | }
410 | } catch let e {
411 | onError?(elements, e)
412 | }
413 | }.asObserver()
414 | }
415 |
416 | /**
417 | Returns bindable sink which adds an object to a Realm
418 |
419 | - parameter: configuration (by default uses `Realm.Configuration.defaultConfiguration`)
420 | to use to get a Realm for the write operations
421 | - parameter: update - update according to Realm.UpdatePolicy
422 | - parameter: onError - closure to implement custom error handling
423 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
424 | */
425 | static func add(configuration: Realm.Configuration = Realm.Configuration.defaultConfiguration,
426 | update: Realm.UpdatePolicy = .error,
427 | onError: ((O?, Error) -> Void)? = nil) -> AnyObserver {
428 | return RealmObserver(configuration: configuration) { realm, element, error in
429 | guard let realm = realm else {
430 | onError?(nil, error ?? RxRealmError.unknown)
431 | return
432 | }
433 |
434 | do {
435 | try realm.write {
436 | realm.add(element, update: update)
437 | }
438 | } catch let e {
439 | onError?(element, e)
440 | }
441 | }.asObserver()
442 | }
443 |
444 | /**
445 | Returns bindable sink, which deletes objects in sequence from Realm.
446 |
447 | - parameter: onError - closure to implement custom error handling
448 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
449 | */
450 | static func delete(onError: ((S?, Error) -> Void)? = nil)
451 | -> AnyObserver where S.Iterator.Element: Object {
452 | return AnyObserver { event in
453 |
454 | guard let elements = event.element,
455 | var generator = elements.makeIterator() as S.Iterator?,
456 | let first = generator.next(),
457 | let realm = first.realm
458 | else {
459 | onError?(nil, RxRealmError.unknown)
460 | return
461 | }
462 |
463 | do {
464 | try realm.write {
465 | realm.delete(elements)
466 | }
467 | } catch let e {
468 | onError?(elements, e)
469 | }
470 | }
471 | }
472 |
473 | /**
474 | Returns bindable sink, which deletes object from Realm
475 |
476 | - parameter: onError - closure to implement custom error handling
477 | - returns: `AnyObserver`, which you can use to subscribe an `Observable` to
478 | */
479 | static func delete(onError: ((O?, Error) -> Void)? = nil) -> AnyObserver {
480 | return AnyObserver { event in
481 |
482 | guard let element = event.element, let realm = element.realm else {
483 | onError?(nil, RxRealmError.unknown)
484 | return
485 | }
486 |
487 | do {
488 | try realm.write {
489 | realm.delete(element)
490 | }
491 | } catch let e {
492 | onError?(element, e)
493 | }
494 | }
495 | }
496 | }
497 |
498 | // MARK: Realm Object type extensions
499 |
500 | public extension Observable where Element: Object {
501 | @available(*, deprecated, renamed: "from(object:)")
502 | static func from(_ object: Element) -> Observable {
503 | return from(object: object)
504 | }
505 |
506 | /**
507 | Returns an `Observable