From 3494d16d1fe94e12d486c03cfe8a47943cdca499 Mon Sep 17 00:00:00 2001 From: Yongjun Lee Date: Wed, 5 Oct 2022 13:55:03 +0900 Subject: [PATCH] Support safe indexing --- RxDataSources.xcodeproj/project.pbxproj | 4 ++++ .../RxDataSources/Collection+Extensions.swift | 18 ++++++++++++++++ .../CollectionViewSectionedDataSource.swift | 21 +++++++++++++++++++ .../TableViewSectionedDataSource.swift | 21 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 Sources/RxDataSources/Collection+Extensions.swift diff --git a/RxDataSources.xcodeproj/project.pbxproj b/RxDataSources.xcodeproj/project.pbxproj index 2e84b80..7436ff2 100644 --- a/RxDataSources.xcodeproj/project.pbxproj +++ b/RxDataSources.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 03EEEE981F5B7D71006068BC /* XCTest+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EEEE871F5B7D5C006068BC /* XCTest+Extensions.swift */; }; 70C0622425A8FE3D002A57ED /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80FB1F48228489EC009D6516 /* RxSwift.framework */; platformFilter = ios; }; 70C0623425A8FE54002A57ED /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80FB1F4A228489EC009D6516 /* RxCocoa.framework */; platformFilter = ios; }; + 183A555028ED44E8005BF2E3 /* Collection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183A554F28ED44E8005BF2E3 /* Collection+Extensions.swift */; }; 70C0622425A8FE3D002A57ED /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80FB1F48228489EC009D6516 /* RxSwift.framework */; }; 70C0623425A8FE54002A57ED /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80FB1F4A228489EC009D6516 /* RxCocoa.framework */; }; C81FBF461F3B9CED0094061E /* Differentiator.podspec in Resources */ = {isa = PBXBuildFile; fileRef = C81FBF451F3B9CED0094061E /* Differentiator.podspec */; }; @@ -145,6 +146,7 @@ 03EEEE851F5B7D5C006068BC /* Randomizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Randomizer.swift; sourceTree = ""; }; 03EEEE861F5B7D5C006068BC /* s.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = s.swift; sourceTree = ""; }; 03EEEE871F5B7D5C006068BC /* XCTest+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTest+Extensions.swift"; sourceTree = ""; }; + 183A554F28ED44E8005BF2E3 /* Collection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+Extensions.swift"; sourceTree = ""; }; 1E38DA4A22778D1A00C07A09 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 80FB1F3A228489EB009D6516 /* Rx.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Rx.xcodeproj; path = Carthage/Checkouts/RxSwift/Rx.xcodeproj; sourceTree = ""; }; C81905AE1DEA019100AE679C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -349,6 +351,7 @@ C8BBFBD61F3B8F8D00A225F7 /* UI+SectionedViewType.swift */, C833338C1F8A5FAC00D46EAE /* Deprecated.swift */, C84043C21F9D33CE0093C3E7 /* ViewTransition.swift */, + 183A554F28ED44E8005BF2E3 /* Collection+Extensions.swift */, ); path = RxDataSources; sourceTree = ""; @@ -655,6 +658,7 @@ C8BBFBDA1F3B8F8D00A225F7 /* RxCollectionViewSectionedAnimatedDataSource.swift in Sources */, C8BBFBD81F3B8F8D00A225F7 /* DataSources.swift in Sources */, C8BBFBD71F3B8F8D00A225F7 /* CollectionViewSectionedDataSource.swift in Sources */, + 183A555028ED44E8005BF2E3 /* Collection+Extensions.swift in Sources */, C8BBFBE01F3B8F8D00A225F7 /* TableViewSectionedDataSource.swift in Sources */, C8BBFBE11F3B8F8D00A225F7 /* UI+SectionedViewType.swift in Sources */, C8BBFBDB1F3B8F8D00A225F7 /* RxCollectionViewSectionedReloadDataSource.swift in Sources */, diff --git a/Sources/RxDataSources/Collection+Extensions.swift b/Sources/RxDataSources/Collection+Extensions.swift new file mode 100644 index 0000000..aa9a12c --- /dev/null +++ b/Sources/RxDataSources/Collection+Extensions.swift @@ -0,0 +1,18 @@ +// +// Collection+Extensions.swift +// RxDataSources +// +// Created by layton on 2022/10/05. +// Copyright © 2022 kzaher. All rights reserved. +// + +import Foundation +#if os(iOS) || os(tvOS) +import Foundation + +extension Collection { + subscript (safe index: Index) -> Element? { + return indices.contains(index) ? self[index] : nil + } +} +#endif diff --git a/Sources/RxDataSources/CollectionViewSectionedDataSource.swift b/Sources/RxDataSources/CollectionViewSectionedDataSource.swift index ebb5645..0e92b79 100644 --- a/Sources/RxDataSources/CollectionViewSectionedDataSource.swift +++ b/Sources/RxDataSources/CollectionViewSectionedDataSource.swift @@ -68,6 +68,14 @@ open class CollectionViewSectionedDataSource let sectionModel = self._sectionModels[section] return Section(original: sectionModel.model, items: sectionModel.items) } + open subscript(safe section: Int) -> Section? { + let sectionModel = self._sectionModels[safe: section] + if let sectionModel = sectionModel { + return Section(original: sectionModel.model, items: sectionModel.items) + } else { + return nil + } + } open subscript(indexPath: IndexPath) -> Item { get { @@ -79,6 +87,19 @@ open class CollectionViewSectionedDataSource self._sectionModels[indexPath.section] = section } } + + open subscript(safe indexPath: IndexPath) -> Item? { + get { + return self._sectionModels[safe: indexPath.section]?.items[safe: indexPath.item] + } + set(item) { + var section = self._sectionModels[indexPath.section] + if let item = item { + section.items[indexPath.item] = item + self._sectionModels[indexPath.section] = section + } + } + } open func model(at indexPath: IndexPath) throws -> Any { guard indexPath.section < self._sectionModels.count, diff --git a/Sources/RxDataSources/TableViewSectionedDataSource.swift b/Sources/RxDataSources/TableViewSectionedDataSource.swift index 0ba1558..1ce631f 100644 --- a/Sources/RxDataSources/TableViewSectionedDataSource.swift +++ b/Sources/RxDataSources/TableViewSectionedDataSource.swift @@ -96,6 +96,15 @@ open class TableViewSectionedDataSource let sectionModel = self._sectionModels[section] return Section(original: sectionModel.model, items: sectionModel.items) } + + open subscript(safe section: Int) -> Section? { + let sectionModel = self._sectionModels[safe: section] + if let sectionModel = sectionModel { + return Section(original: sectionModel.model, items: sectionModel.items) + } else { + return nil + } + } open subscript(indexPath: IndexPath) -> Item { get { @@ -107,6 +116,18 @@ open class TableViewSectionedDataSource self._sectionModels[indexPath.section] = section } } + open subscript(safe indexPath: IndexPath) -> Item? { + get { + return self._sectionModels[safe: indexPath.section]?.items[safe: indexPath.item] + } + set(item) { + var section = self._sectionModels[indexPath.section] + if let item = item { + section.items[indexPath.item] = item + self._sectionModels[indexPath.section] = section + } + } + } open func model(at indexPath: IndexPath) throws -> Any { guard indexPath.section < self._sectionModels.count,