Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Example/RxRealmDataSources.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@
"${SRCROOT}/Pods/Target Support Files/Pods-Demo-RxRealmDataSources_MacExample/Pods-Demo-RxRealmDataSources_MacExample-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Realm-macOS/Realm.framework",
"${BUILT_PRODUCTS_DIR}/RealmSwift-macOS/RealmSwift.framework",
"${BUILT_PRODUCTS_DIR}/RxAtomic-macOS/RxAtomic.framework",
"${BUILT_PRODUCTS_DIR}/RxCocoa-macOS/RxCocoa.framework",
"${BUILT_PRODUCTS_DIR}/RxRealm-macOS/RxRealm.framework",
"${BUILT_PRODUCTS_DIR}/RxRealmDataSources-macOS/RxRealmDataSources.framework",
Expand All @@ -436,6 +437,7 @@
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RealmSwift.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxAtomic.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRealm.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRealmDataSources.framework",
Expand All @@ -455,6 +457,7 @@
"${SRCROOT}/Pods/Target Support Files/Pods-Demo-RxRealmDataSources_Example/Pods-Demo-RxRealmDataSources_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Realm-iOS/Realm.framework",
"${BUILT_PRODUCTS_DIR}/RealmSwift-iOS/RealmSwift.framework",
"${BUILT_PRODUCTS_DIR}/RxAtomic-iOS/RxAtomic.framework",
"${BUILT_PRODUCTS_DIR}/RxCocoa-iOS/RxCocoa.framework",
"${BUILT_PRODUCTS_DIR}/RxRealm-iOS/RxRealm.framework",
"${BUILT_PRODUCTS_DIR}/RxRealmDataSources-iOS/RxRealmDataSources.framework",
Expand All @@ -464,6 +467,7 @@
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RealmSwift.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxAtomic.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRealm.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRealmDataSources.framework",
Expand Down
21 changes: 13 additions & 8 deletions Example/RxRealmDataSources/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="e5b-i0-Sf8">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="e5b-i0-Sf8">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
Expand All @@ -22,9 +22,8 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="47" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="9wF-Hp-Zl1">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="47" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="9wF-Hp-Zl1">
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" rowHeight="47" id="0Fv-lJ-pdU" customClass="PersonCell" customModule="RxRealmDataSources_Example" customModuleProvider="target">
Expand Down Expand Up @@ -58,6 +57,12 @@
</tableView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="9wF-Hp-Zl1" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="KsW-LD-wdn"/>
<constraint firstItem="2fi-mo-0CV" firstAttribute="top" secondItem="9wF-Hp-Zl1" secondAttribute="bottom" id="U79-jT-Gz8"/>
<constraint firstAttribute="trailing" secondItem="9wF-Hp-Zl1" secondAttribute="trailing" id="Z66-lL-rSb"/>
<constraint firstItem="9wF-Hp-Zl1" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" id="pAN-54-93Z"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="bPo-jC-4xi"/>
<connections>
Expand Down Expand Up @@ -141,7 +146,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="e5b-i0-Sf8" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="NYx-HQ-0Jl">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
Expand All @@ -168,7 +173,7 @@
<rect key="frame" x="0.0" y="35" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="TUc-X7-1yK" id="oFC-nh-48l">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="1. Table View Data Source" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FOy-6e-7Rv">
Expand All @@ -188,7 +193,7 @@
<rect key="frame" x="0.0" y="79" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="iET-qa-wxc" id="CDi-eZ-kOd">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="2. Collection View Data Source" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lyi-Vs-zYj">
Expand Down
35 changes: 32 additions & 3 deletions Example/RxRealmDataSources/CollectionViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class CollectionViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(CollectionViewController.handleLongGesture(gesture:)))
collectionView.addGestureRecognizer(longPressGesture)

// create data source
let dataSource = RxCollectionViewRealmDataSource<Lap>(cellIdentifier: "Cell", cellType: LapCollectionCell.self) {cell, ip, lap in
cell.customLabel.text = "\(ip.row). \(lap.text)"
Expand All @@ -36,7 +39,7 @@ class CollectionViewController: UIViewController {

// bind to collection view
laps
.bind(to: collectionView.rx.realmChanges(dataSource))
.bind(to: collectionView.rx.items(dataSource: dataSource))
.disposed(by: bag)

// bind to vc title
Expand All @@ -48,13 +51,39 @@ class CollectionViewController: UIViewController {
.disposed(by: bag)

// react on cell taps
collectionView.rx.realmModelSelected(Lap.self)
collectionView.rx.modelSelected(Lap.self)
.map({ $0.text })
.bind(to: rx.title)
.disposed(by: bag)

collectionView.rx.dataSource.methodInvoked(#selector(UICollectionViewDataSource.collectionView(_:moveItemAt:to:)))
.subscribe(onNext: { a in
guard let from = a[1] as? IndexPath, let to = a[2] as? IndexPath else { return }
try! realm.write {
let laps = realm.objects(Timer.self).first!.laps
laps.swapAt(from.row, to.row)
}
})
.disposed(by: bag)

// demo inserting and deleting data
data.start()
}
}

@objc func handleLongGesture(gesture: UILongPressGestureRecognizer) {
switch(gesture.state) {
case .began:
guard let selectedIndexPath = collectionView.indexPathForItem(at: gesture.location(in: collectionView)) else { break }
collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
data.stop()
case .changed:
collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: gesture.view!))
case .ended:
collectionView.endInteractiveMovement()
data.start()
default:
collectionView.cancelInteractiveMovement()
data.start()
}
}
}
6 changes: 5 additions & 1 deletion Example/RxRealmDataSources/DataRandomizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension Int {

class DataRandomizer {

private let bag = DisposeBag()
private var bag = DisposeBag()

lazy var config: Realm.Configuration = {
var config = Realm.Configuration.defaultConfiguration
Expand Down Expand Up @@ -96,4 +96,8 @@ class DataRandomizer {
})
.disposed(by: bag)
}

func stop() {
bag = DisposeBag()
}
}
25 changes: 23 additions & 2 deletions Example/RxRealmDataSources/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = editButtonItem

// create data source
let dataSource = RxTableViewRealmDataSource<Lap>(cellIdentifier: "Cell", cellType: PersonCell.self) {cell, ip, lap in
Expand All @@ -36,7 +37,7 @@ class ViewController: UIViewController {

// bind to table view
laps
.bind(to: tableView.rx.realmChanges(dataSource))
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: bag)

// bind to vc title
Expand All @@ -48,12 +49,32 @@ class ViewController: UIViewController {
.disposed(by: bag)

// react on cell taps
tableView.rx.realmModelSelected(Lap.self)
tableView.rx.modelSelected(Lap.self)
.map({ $0.text })
.bind(to: rx.title)
.disposed(by: bag)

tableView.rx.itemDeleted.asObservable()
.subscribe(onNext: { indexPath in
try! realm.write {
let laps = realm.objects(Timer.self).first!.laps
realm.delete(laps[indexPath.row])
}
})
.disposed(by: bag)

// demo inserting and deleting data
data.start()
}

override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
tableView.setEditing(editing, animated: animated)

if editing {
data.stop()
} else {
data.start()
}
}
}
89 changes: 36 additions & 53 deletions Pod/Classes/Reactive+RxRealmDataSources.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,64 +12,46 @@ import RxSwift
import RxCocoa
import RxRealm

public typealias RealmChange<E: RealmCollectionValue> = (AnyRealmCollection<E>, RealmChangeset?)

#if os(iOS)
// MARK: - iOS / UIKit

import UIKit
extension Reactive where Base: UITableView {

public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {

return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if ds.tableView == nil {
ds.tableView = self.base
}
ds.tableView?.dataSource = ds
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
}
@available(*, deprecated, message: "use items(dataSource:) instead")
public func realmChanges<
DataSource: RxTableViewDataSourceType & UITableViewDataSource,
O: ObservableType>
(_ dataSource: DataSource)
-> (_ source: O)
-> Disposable
where DataSource.Element == O.E {
return items(dataSource: dataSource)
}

public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {

let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UITableView] indexPath -> Observable<E> in
guard let view = view, let ds = view.dataSource as? RxTableViewRealmDataSource<E> else {
return Observable.empty()
}

return Observable.just(ds.model(at: indexPath))
}

return ControlEvent(events: source)
}

@available(*, deprecated, renamed: "modelSelected")
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
return modelSelected(modelType)
}
}

extension Reactive where Base: UICollectionView {

public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {

return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if ds.collectionView == nil {
ds.collectionView = self.base
}
ds.collectionView?.dataSource = ds
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
}
@available(*, deprecated, message: "use items(dataSource:) instead")
public func realmChanges<
DataSource: RxCollectionViewDataSourceType & UICollectionViewDataSource,
O: ObservableType>
(_ dataSource: DataSource)
-> (_ source: O)
-> Disposable where DataSource.Element == O.E {
return items(dataSource: dataSource)
}

@available(*, deprecated, renamed: "modelSelected")
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {

let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UICollectionView] indexPath -> Observable<E> in
guard let view = view, let ds = view.dataSource as? RxCollectionViewRealmDataSource<E> else {
return Observable.empty()
}

return Observable.just(ds.model(at: indexPath))
}

return ControlEvent(events: source)
return modelSelected(modelType)
}
}

Expand All @@ -81,31 +63,32 @@ import Cocoa
extension Reactive where Base: NSTableView {

public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
-> Binder<RealmChange<E>> {

base.delegate = dataSource
base.dataSource = dataSource

return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
return Binder(base) { tableView, element in
if dataSource.tableView == nil {
dataSource.tableView = self.base
dataSource.tableView = tableView
}
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
dataSource.applyChanges(items: element.0, changes: element.1)
}
}
}

extension Reactive where Base: NSCollectionView {

public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
-> Binder<RealmChange<E>> {

return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if ds.collectionView == nil {
ds.collectionView = self.base
base.dataSource = dataSource

return Binder(base) { collectionView, element in
if dataSource.collectionView == nil {
dataSource.collectionView = collectionView
}
ds.collectionView?.dataSource = ds
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
dataSource.applyChanges(items: element.0, changes: element.1)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Pod/Classes/RealmBindObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import RxSwift
import RxCocoa
import RxRealm

@available(*, deprecated, message: "use RxCocoa Binder instead")
public class RealmBindObserver<O: Object, C: RealmCollection, DS>: ObserverType {
typealias BindingType = (DS, C, RealmChangeset?) -> Void
public typealias E = (C, RealmChangeset?)
Expand Down
Loading