├── .gitignore ├── .travis.yml ├── Docs ├── CZInstagram.gif └── FLUX.jpeg ├── Example ├── ReactiveListViewKitDemo.xcodeproj │ └── project.pbxproj ├── ReactiveListViewKitDemo │ ├── Data Layer │ │ ├── CZMocker.swift │ │ ├── Feed.swift │ │ ├── ImageInfo.swift │ │ └── User.swift │ ├── FLUX │ │ ├── FeedListAction.swift │ │ ├── SuggestedUserAction.swift │ │ └── UserStoryAction.swift │ ├── Info.plist │ ├── Resources │ │ ├── feeds copy.json │ │ ├── feeds.json │ │ ├── users copy.json │ │ └── users.json │ ├── Supported Files │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── ColorFrame.imageset │ │ │ │ ├── ColorFrameFull.png │ │ │ │ └── Contents.json │ │ │ ├── Comment.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── ic_chat_1-1.png │ │ │ │ ├── ic_chat_1-2.png │ │ │ │ └── ic_chat_1.png │ │ │ ├── Contents.json │ │ │ ├── InstagramTitle.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── instagramTitle-1.png │ │ │ │ ├── instagramTitle-2.png │ │ │ │ └── instagramTitle.png │ │ │ ├── Like.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── ic_like-1.png │ │ │ │ ├── ic_like-2.png │ │ │ │ └── ic_like.png │ │ │ ├── Liked.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── ic_liked-1.png │ │ │ │ ├── ic_liked-2.png │ │ │ │ └── ic_liked.png │ │ │ ├── Menu.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── ic_menu-1.png │ │ │ │ └── ic_menu.png │ │ │ ├── PostImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── placeholder.png │ │ │ ├── Share.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── ic_share_file-1.png │ │ │ │ ├── ic_share_file-2.png │ │ │ │ └── ic_share_file.png │ │ │ └── noUser.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ └── SceneDelegate.swift │ ├── UI Layer │ │ └── FeedList │ │ │ ├── FeedCellView.swift │ │ │ ├── FeedCellView.xib │ │ │ ├── FeedCellViewModel.swift │ │ │ ├── FeedListActionHandler.swift │ │ │ ├── FeedListViewController.swift │ │ │ ├── FeedListViewModel.swift │ │ │ └── HotUsers │ │ │ ├── HotUserCellCardView.swift │ │ │ ├── HotUserCellCardView.xib │ │ │ ├── HotUserCellView.swift │ │ │ ├── HotUserCellView.xib │ │ │ ├── HotUserCellViewModel.swift │ │ │ ├── HotUsersCellViewController.swift │ │ │ ├── HotUsersCellViewController.xib │ │ │ └── HotUsersCellViewModel.swift │ └── Utils │ │ └── Constants.swift └── ReactiveListViewKitDemoUITests │ ├── IncrementalUpdatesUITest.swift │ ├── NoneIncrementalUpdatesUITest.swift │ ├── ReactiveListViewKitDemoUITests.swift │ └── ReactiveListViewKitDemoUITestsLaunchTests.swift ├── Experimental └── MERGED_SelfSizingCell │ ├── Example │ ├── ReactiveListViewKitDemo.xcodeproj │ │ └── project.pbxproj │ ├── ReactiveListViewKitDemo │ │ ├── Data Layer │ │ │ ├── CZMocker.swift │ │ │ ├── Feed.swift │ │ │ ├── ImageInfo.swift │ │ │ └── User.swift │ │ ├── FLUX │ │ │ ├── FeedListAction.swift │ │ │ ├── SuggestedUserAction.swift │ │ │ └── UserStoryAction.swift │ │ ├── ListViewUITest.swift │ │ ├── Supported Files │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── CommonCrypto │ │ │ │ ├── .gitignore │ │ │ │ ├── CommonCrypto.xcodeproj │ │ │ │ │ └── project.pbxproj │ │ │ │ ├── CommonCrypto │ │ │ │ │ ├── CommonCrypto.xcconfig │ │ │ │ │ ├── Info.plist │ │ │ │ │ ├── appletvos.modulemap │ │ │ │ │ ├── appletvsimulator.modulemap │ │ │ │ │ ├── iphoneos.modulemap │ │ │ │ │ ├── iphonesimulator.modulemap │ │ │ │ │ ├── macosx.modulemap │ │ │ │ │ ├── watchos.modulemap │ │ │ │ │ └── watchsimulator.modulemap │ │ │ │ └── README.md │ │ │ ├── Info.plist │ │ │ └── Resources │ │ │ │ ├── Assets.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ ├── ColorFrame.imageset │ │ │ │ │ ├── ColorFrameFull.png │ │ │ │ │ └── Contents.json │ │ │ │ ├── Comment.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── ic_chat_1-1.png │ │ │ │ │ ├── ic_chat_1-2.png │ │ │ │ │ └── ic_chat_1.png │ │ │ │ ├── Contents.json │ │ │ │ ├── InstagramTitle.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── instagramTitle-1.png │ │ │ │ │ ├── instagramTitle-2.png │ │ │ │ │ └── instagramTitle.png │ │ │ │ ├── Like.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── ic_like-1.png │ │ │ │ │ ├── ic_like-2.png │ │ │ │ │ └── ic_like.png │ │ │ │ ├── Liked.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── ic_liked-1.png │ │ │ │ │ ├── ic_liked-2.png │ │ │ │ │ └── ic_liked.png │ │ │ │ ├── Menu.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── ic_menu-1.png │ │ │ │ │ └── ic_menu.png │ │ │ │ ├── PostImage.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── placeholder.png │ │ │ │ ├── Share.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── ic_share_file-1.png │ │ │ │ │ ├── ic_share_file-2.png │ │ │ │ │ └── ic_share_file.png │ │ │ │ └── noUser.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg │ │ │ │ ├── feeds copy.json │ │ │ │ ├── feeds.json │ │ │ │ ├── users copy.json │ │ │ │ └── users.json │ │ ├── UI Layer │ │ │ └── FeedList │ │ │ │ ├── FeedCellView.swift │ │ │ │ ├── FeedCellView.xib │ │ │ │ ├── FeedCellViewModel.swift │ │ │ │ ├── FeedListActionHandler.swift │ │ │ │ ├── FeedListViewController.swift │ │ │ │ ├── FeedListViewModel.swift │ │ │ │ └── HotUsers │ │ │ │ ├── HotUserCellCardView.swift │ │ │ │ ├── HotUserCellCardView.xib │ │ │ │ ├── HotUserCellView.swift │ │ │ │ ├── HotUserCellView.xib │ │ │ │ ├── HotUserCellViewModel.swift │ │ │ │ ├── HotUsersCellViewController.swift │ │ │ │ ├── HotUsersCellViewController.xib │ │ │ │ └── HotUsersCellViewModel.swift │ │ └── Utils │ │ │ ├── CZNetworking │ │ │ ├── CZNetworking │ │ │ │ ├── CZHTTPCache.swift │ │ │ │ ├── CZHTTPJsonSerializer.swift │ │ │ │ ├── CZHTTPManager.swift │ │ │ │ ├── CZHTTPRequester.swift │ │ │ │ ├── CZNetError.swift │ │ │ │ ├── CZNetworking.h │ │ │ │ ├── CommonCrypto │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── CommonCrypto.xcodeproj │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── CommonCrypto │ │ │ │ │ │ ├── CommonCrypto.xcconfig │ │ │ │ │ │ ├── Info.plist │ │ │ │ │ │ ├── appletvos.modulemap │ │ │ │ │ │ ├── appletvsimulator.modulemap │ │ │ │ │ │ ├── iphoneos.modulemap │ │ │ │ │ │ ├── iphonesimulator.modulemap │ │ │ │ │ │ ├── macosx.modulemap │ │ │ │ │ │ ├── watchos.modulemap │ │ │ │ │ │ └── watchsimulator.modulemap │ │ │ │ │ └── README.md │ │ │ │ ├── Extensions.swift │ │ │ │ └── Info.plist │ │ │ ├── CZNetworkingTests │ │ │ │ ├── CZNetworkingTests.swift │ │ │ │ └── Info.plist │ │ │ ├── LICENSE │ │ │ └── README.md │ │ │ └── Constants.swift │ └── ReactiveListViewKitUITests │ │ ├── IncrementalUpdatesUITest.swift │ │ ├── Info.plist │ │ ├── NoneIncrementalUpdatesUITest.swift │ │ └── Utils │ │ ├── CZUITest.swift │ │ └── KIFUtils.swift │ └── ReactiveListViewKit │ ├── ReactiveListViewKit.podspec │ ├── ReactiveListViewKit.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── ReactiveListViewKit.xcscheme │ │ └── ReactiveListViewKitTests.xcscheme │ ├── ReactiveListViewKit │ ├── CZFeedCellViewable.swift │ ├── CZFeedDetailsFacadeView.swift │ ├── CZFeedDetailsModel.swift │ ├── CZFeedDetailsViewModel.swift │ ├── CZFeedListCell.swift │ ├── CZFeedListFacadeView.swift │ ├── CZFeedListViewAction.swift │ ├── CZFeedListViewModel.swift │ ├── CZFeedListViewStateMachine.swift │ ├── CZFeedModel.swift │ ├── CZFeedViewModelable.swift │ ├── CZListDiff.swift │ ├── CZReactiveFeedDetailsFacadeView.swift │ ├── CZReactiveFeedListFacadeView.swift │ ├── CZSectionModel.swift │ ├── Reactor.swift │ ├── TemplateViews │ │ ├── CZDividerView.swift │ │ ├── CZFeedListSupplementaryLineView.swift │ │ ├── CZFeedListSupplementaryTextView.swift │ │ ├── CZFeedListSupplementaryView.swift │ │ ├── CZHorizontalSectionAdapterCell.swift │ │ ├── CZHorizontalSectionAdapterView.swift │ │ ├── CZHorizontalSectionAdapterViewModel.swift │ │ ├── CZTextFeedCellView.swift │ │ └── CZTextFeedViewModel.swift │ └── Utils │ │ ├── Array+Extension.swift │ │ ├── CZFacadeViewHelper.swift │ │ ├── CZListDiffableHelper.swift │ │ ├── Constants.swift │ │ └── ReactiveListViewKitHelper.swift │ ├── ReactiveListViewKitTests │ ├── Info.plist │ ├── ListDiffTests.swift │ └── Utils │ │ └── CZListDiff+.swift │ └── Supported Files │ ├── CZUtils │ ├── Info.plist │ ├── LICENSE │ ├── Package.swift │ ├── README.md │ ├── Sources │ │ └── CZUtils │ │ │ ├── CZAlertManager.swift │ │ │ ├── CZConcurrentOperation.swift │ │ │ ├── CZDictionary.swift │ │ │ ├── CZError.swift │ │ │ ├── CZFileHelper.swift │ │ │ ├── CZHTTPJsonSerializer.swift │ │ │ ├── CZMainQueueScheduler.swift │ │ │ ├── CZMutexLock.swift │ │ │ ├── CZNibLoadable.swift │ │ │ ├── CZProMutexLock.swift │ │ │ ├── CZTheme.swift │ │ │ ├── CZUtils.swift │ │ │ ├── Error+.swift │ │ │ ├── Extensions │ │ │ ├── Array+.swift │ │ │ ├── Character+.swift │ │ │ ├── Codable+.swift │ │ │ ├── Date+.swift │ │ │ ├── Dictionary+.swift │ │ │ ├── NSObject+.swift │ │ │ ├── Optional+.swift │ │ │ ├── Set+.swift │ │ │ ├── String+.swift │ │ │ ├── UIButton+.swift │ │ │ ├── UIImage+.swift │ │ │ ├── UIScreen+.swift │ │ │ ├── UIView+.swift │ │ │ └── UIViewController+.swift │ │ │ ├── Investigation │ │ │ ├── CZDispatchGroup.swift │ │ │ └── CriticalSectionLock.swift │ │ │ ├── NSNullGuard.swift │ │ │ ├── RegExHelper.swift │ │ │ ├── Supported Files │ │ │ ├── CZUtils.h │ │ │ └── Info.plist │ │ │ ├── Swizzling.swift │ │ │ ├── ThreadSafeDictionary.swift │ │ │ └── Utils │ │ │ └── PrettyDescription.swift │ └── Tests │ │ ├── CZUtilsTests │ │ ├── CZUtilsTests.swift │ │ ├── TestArray.swift │ │ ├── TestThreadSafeDictionary.swift │ │ └── XCTestManifests.swift │ │ └── LinuxMain.swift │ ├── Info.plist │ └── ReactiveListViewKit.h ├── LICENSE ├── README.md └── ReactiveListViewKit ├── ReactiveListViewKit.podspec ├── ReactiveListViewKit.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── ReactiveListViewKit.xcscheme │ └── ReactiveListViewKitTests.xcscheme ├── ReactiveListViewKit ├── CZFeedCellViewable.swift ├── CZFeedDetailsFacadeView.swift ├── CZFeedDetailsModel.swift ├── CZFeedDetailsViewModel.swift ├── CZFeedListCell.swift ├── CZFeedListFacadeView.swift ├── CZFeedListViewAction.swift ├── CZFeedListViewModel.swift ├── CZFeedListViewStateMachine.swift ├── CZFeedModel.swift ├── CZFeedViewModelable.swift ├── CZListDiff.swift ├── CZReactiveFeedDetailsFacadeView.swift ├── CZReactiveFeedListFacadeView.swift ├── CZSectionModel.swift ├── Store │ ├── Store.swift │ └── StoreObserverProtocol.swift ├── TemplateViews │ ├── CZDividerView.swift │ ├── CZFeedListSupplementaryLineView.swift │ ├── CZFeedListSupplementaryTextView.swift │ ├── CZFeedListSupplementaryView.swift │ ├── CZHorizontalSectionAdapterCell.swift │ ├── CZHorizontalSectionAdapterView.swift │ ├── CZHorizontalSectionAdapterViewModel.swift │ ├── CZTextFeedCellView.swift │ └── CZTextFeedViewModel.swift └── Utils │ ├── Array+Extension.swift │ ├── CZFacadeViewHelper.swift │ ├── CZListDiffableHelper.swift │ ├── Constants.swift │ └── ReactiveListViewKitHelper.swift ├── ReactiveListViewKitTests ├── Info.plist ├── ListDiffTests.swift └── Utils │ └── CZListDiff+.swift └── Supported Files ├── CZUtils ├── Info.plist ├── LICENSE ├── Package.swift ├── README.md ├── Sources │ └── CZUtils │ │ ├── CZAlertManager.swift │ │ ├── CZConcurrentOperation.swift │ │ ├── CZDictionary.swift │ │ ├── CZError.swift │ │ ├── CZFileHelper.swift │ │ ├── CZHTTPJsonSerializer.swift │ │ ├── CZMainQueueScheduler.swift │ │ ├── CZMutexLock.swift │ │ ├── CZNibLoadable.swift │ │ ├── CZProMutexLock.swift │ │ ├── CZTheme.swift │ │ ├── CZUtils.swift │ │ ├── Error+.swift │ │ ├── Extensions │ │ ├── Array+.swift │ │ ├── Character+.swift │ │ ├── Codable+.swift │ │ ├── Date+.swift │ │ ├── Dictionary+.swift │ │ ├── NSObject+.swift │ │ ├── Optional+.swift │ │ ├── Set+.swift │ │ ├── String+.swift │ │ ├── UIButton+.swift │ │ ├── UIImage+.swift │ │ ├── UIScreen+.swift │ │ ├── UIView+.swift │ │ └── UIViewController+.swift │ │ ├── Investigation │ │ ├── CZDispatchGroup.swift │ │ └── CriticalSectionLock.swift │ │ ├── NSNullGuard.swift │ │ ├── RegExHelper.swift │ │ ├── Supported Files │ │ ├── CZUtils.h │ │ └── Info.plist │ │ ├── Swizzling.swift │ │ ├── ThreadSafeDictionary.swift │ │ └── Utils │ │ └── PrettyDescription.swift └── Tests │ ├── CZUtilsTests │ ├── CZUtilsTests.swift │ ├── TestArray.swift │ ├── TestThreadSafeDictionary.swift │ └── XCTestManifests.swift │ └── LinuxMain.swift ├── Info.plist └── ReactiveListViewKit.h /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | # Mac OS X 4 | **DS_Store 5 | 6 | # Xcode 7 | .DS_Store 8 | *xcuserstate 9 | **xcuserstate 10 | *.xcuserstate 11 | *.mode1v3 12 | *.pbxuser 13 | *.xccheckout 14 | *.moved-aside 15 | *.mode2v3 16 | xcuserdata 17 | *.perspectivev3 18 | project.xcworkspace 19 | Groupon.xcworkspace/xcshareddata/Groupon.xccheckout 20 | *.xcscmblueprint 21 | 22 | # AppCode 23 | .idea/ 24 | # VSCode 25 | .vscode/ 26 | 27 | # React-Capacitor 28 | .capacitor/ 29 | 30 | #Generated files 31 | *.pyc 32 | 33 | # Temporary files 34 | *.swp 35 | Pods/resources-to-copy-Groupon.txt 36 | 37 | # Ruby 38 | gems/ 39 | .bundle/ 40 | 41 | # Other 42 | build* 43 | data_archive* 44 | *.kpf 45 | *.wpr 46 | *.wpu 47 | *.db 48 | *.rej 49 | *.orig 50 | 3rd_party 51 | DerivedData/ 52 | GrouponUITests/odo 53 | GrouponUITests/screenshots 54 | GrouponUITests/Deeplink 55 | GrouponUITests/OfflineRepository 56 | GrouponUITests/scripts/DisableUITestsSetupScriptDefaultValue.txt 57 | 58 | # Carthage 59 | Carthage/Build/* 60 | 61 | # We have to unignore certain frameworks that come as pre-packaged. 62 | # Note: We HAVE to ignore ALL swift frameworks before Swift 3.0, that's why this is opt-in 63 | !Carthage/Build/iOS/Realm.framework 64 | !Carthage/Build/iOS/Realm.dsym 65 | !Carthage/Build/iOS/AFNetworking.framework 66 | !Carthage/Build/iOS/AFNetworking.framework.dsym 67 | !Carthage/Build/iOS/EasyMapping.framework 68 | !Carthage/Build/iOS/EasyMapping.framework.dsym 69 | 70 | # Fastlane 71 | /fastlane 72 | .fastlane/.fastlane 73 | .fastlane/output 74 | .fastlane/derived_data 75 | .fastlane/test_output 76 | .fastlane/report.xml 77 | code_coverage.tar.gz 78 | test_output/ 79 | output_log.txt 80 | 81 | # Swift merge files 82 | /Reference_Groupon.xcodeproj 83 | /GrouponUtilsTests-merge.swift 84 | /GrouponUtils-merge.swift 85 | /GrouponUITests-merge.swift 86 | /GrouponTests-merge.swift 87 | /GrouponImageStressTests-merge.swift 88 | /Groupon-merge.swift 89 | /GPNSTTests-merge.swift 90 | /GPNST-merge.swift 91 | /GPLoggingTests-merge.swift 92 | /GPLogging-merge.swift 93 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode11.3 3 | xcode_project: ReactiveListViewKit/ReactiveListViewKit.xcodeproj # path to your xcodeproj folder 4 | xcode_scheme: ReactiveListViewKit 5 | xcode_destination: platform=iOS Simulator,OS=11.3,name=iPhone X 6 | -------------------------------------------------------------------------------- /Docs/CZInstagram.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Docs/CZInstagram.gif -------------------------------------------------------------------------------- /Docs/FLUX.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Docs/FLUX.jpeg -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Data Layer/CZMocker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZMocker.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/12/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | class CZMocker: NSObject { 13 | static let shared = CZMocker() 14 | 15 | var feeds: [Feed] { 16 | let url = Bundle.main.url(forResource: "feeds", withExtension: "json")! 17 | return CodableHelper.decode(url) ?? [] 18 | } 19 | 20 | var hotUsers: [User] { 21 | let url = Bundle.main.url(forResource: "users", withExtension: "json")! 22 | return CodableHelper.decode(url) ?? [] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Data Layer/ImageInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageInfo.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | /// Model of image info 13 | class ImageInfo: ReactiveListDiffable { 14 | let url: String 15 | let width: Int 16 | let height: Int 17 | 18 | // MARK: - CZListDiffable 19 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 20 | return isEqual(toCodable: object) 21 | } 22 | 23 | // MARK: - NSCopying 24 | func copy(with zone: NSZone? = nil) -> Any { 25 | return codableCopy(with: zone) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Data Layer/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/3/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | /// Model of user 13 | class User: ReactiveListDiffable { 14 | let userId: String 15 | let userName: String 16 | let fullName: String? 17 | let portraitUrl: String? 18 | 19 | enum CodingKeys: String, CodingKey { 20 | case userId = "id" 21 | case userName = "username" 22 | case fullName = "full_name" 23 | case portraitUrl = "profile_picture" 24 | } 25 | 26 | // MARK: - CZListDiffable 27 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 28 | return isEqual(toCodable: object) 29 | } 30 | 31 | // MARK: - NSCopying 32 | func copy(with zone: NSZone? = nil) -> Any { 33 | return codableCopy(with: zone) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/FLUX/FeedListAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedListActions.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | // MARK: - Events 13 | 14 | /// Action that User likes one `Feed` 15 | struct LikeFeedAction: CZActionProtocol { 16 | var feed: Feed 17 | } 18 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/FLUX/SuggestedUserAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SuggestedUserEvent.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/28/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | /// Action that follow/ignore `SuggestedUser` 13 | enum SuggestedUserAction: CZActionProtocol { 14 | case follow(user: User) 15 | case ignore(user: User) 16 | } 17 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/FLUX/UserStoryAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserStoryEvent.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/28/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | /// Action that User selects `UserStory` 13 | enum UserStoryAction: CZActionProtocol { 14 | case selected(user: User) 15 | } 16 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Resources/users copy.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "full_name": "Diane", 3 | "username": "fallinlight", 4 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/fallinlight.jpg", 5 | "id": "0" 6 | }, { 7 | "full_name": "Caeli", 8 | "username": "caeliyt", 9 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/caeliyt.jpg", 10 | "id": "1" 11 | }, { 12 | "full_name": "Pixlr", 13 | "username": "pixlr", 14 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/pixlr.jpg", 15 | "id": "2" 16 | }, { 17 | "full_name": "Zayn Malik", 18 | "username": "zayn", 19 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/zayn.jpg", 20 | "id": "3" 21 | }, { 22 | "full_name": "Martin Garrix", 23 | "username": "martingarrix", 24 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/martingarrix.jpg", 25 | "id": "4" 26 | }, { 27 | "full_name": "Mariale Marrero", 28 | "username": "mariale", 29 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/mariale.jpg", 30 | "id": "5" 31 | }, { 32 | "full_name": "Picsart Editor", 33 | "username": "picsart_ediitor", 34 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/picsart_ediitor.jpg", 35 | "id": "6" 36 | }, { 37 | "full_name": "Tutorial edit PicsArt", 38 | "username": "picsart_indo", 39 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/picsart_indo.jpg", 40 | "id": "7" 41 | }, { 42 | "full_name": "Annegien", 43 | "username": "fetching_tigerss", 44 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/fetching_tigerss.jpg", 45 | "id": "8" 46 | }, { 47 | "full_name": "Lesslie Polinesia", 48 | "username": "ppteamlesslie", 49 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/ppteamlesslie.jpg", 50 | "id": "9" 51 | }] 52 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 7/14/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | var window: UIWindow? 14 | 15 | internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | return true 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.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" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/ColorFrame.imageset/ColorFrameFull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/ColorFrame.imageset/ColorFrameFull.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/ColorFrame.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "ColorFrameFull.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_chat_1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_chat_1-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_chat_1-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/ic_chat_1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/ic_chat_1-1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/ic_chat_1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/ic_chat_1-2.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/ic_chat_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Comment.imageset/ic_chat_1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "instagramTitle-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "instagramTitle-2.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "instagramTitle.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/instagramTitle-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/instagramTitle-1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/instagramTitle-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/instagramTitle-2.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/instagramTitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/InstagramTitle.imageset/instagramTitle.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_like.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_like-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_like-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/ic_like-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/ic_like-1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/ic_like-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/ic_like-2.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/ic_like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Like.imageset/ic_like.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_liked-2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_liked-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_liked.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/ic_liked-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/ic_liked-1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/ic_liked-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/ic_liked-2.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/ic_liked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Liked.imageset/ic_liked.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Menu.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_menu.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_menu-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_menu-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Menu.imageset/ic_menu-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Menu.imageset/ic_menu-1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Menu.imageset/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Menu.imageset/ic_menu.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/PostImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "placeholder.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/PostImage.imageset/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/PostImage.imageset/placeholder.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_share_file.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_share_file-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_share_file-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/ic_share_file-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/ic_share_file-1.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/ic_share_file-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/ic_share_file-2.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/ic_share_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/Share.imageset/ic_share_file.png -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/noUser.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/noUser.imageset/no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Example/ReactiveListViewKitDemo/Supported Files/Assets.xcassets/noUser.imageset/no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Supported Files/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/UI Layer/FeedList/FeedCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedCellViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | /** 13 | ViewModel of `FeedCellView`, composed of elements needed for UI populating, based on `Feed` model 14 | */ 15 | class FeedCellViewModel: NSObject, CZFeedViewModelable { 16 | var diffId: String { 17 | return currentClassName + feed.feedId 18 | } 19 | private(set) var feed: Feed 20 | var isInFeedDetails: Bool = false 21 | 22 | var userName: String? {return feed.user?.userName} 23 | var content: String? {return feed.content} 24 | 25 | var portraitUrl: URL? { 26 | guard let urlStr = feed.user?.portraitUrl else {return nil} 27 | return URL(string: urlStr) 28 | } 29 | var imageUrl: URL? { 30 | guard let urlStr = feed.imageInfo?.url else {return nil} 31 | return URL(string: urlStr) 32 | } 33 | var likesCount: Int { 34 | return feed.likesCount 35 | } 36 | var userHasLiked: Bool { 37 | return feed.userHasLiked 38 | } 39 | 40 | required init(_ feed: Feed) { 41 | self.feed = feed 42 | super.init() 43 | } 44 | 45 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 46 | guard let object = object as? FeedCellViewModel else {return false} 47 | return feed.isEqual(toDiffableObj: object.feed) && 48 | isInFeedDetails == object.isInFeedDetails 49 | } 50 | 51 | func copy(with zone: NSZone?) -> Any { 52 | let feedCopy = feed.copy() as! Feed 53 | return FeedCellViewModel(feedCopy) 54 | } 55 | } 56 | 57 | extension FeedCellViewModel: StateProtocol { 58 | func reduce(action: CZActionProtocol) -> Self { 59 | return self 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/UI Layer/FeedList/FeedListActionHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedListActionHandler.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 7/14/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CZUtils 11 | import ReactiveListViewKit 12 | 13 | protocol FeedListActionHandlerCoordinator {} 14 | 15 | /** 16 | Action handler for `FeedListViewController` 17 | 18 | Coordinator pattern decouples user action handling from ViewController to make it less massive 19 | */ 20 | class FeedListActionHandler: NSObject, StoreObserverProtocol { 21 | 22 | var coordinator: FeedListActionHandlerCoordinator? 23 | 24 | // MARK: - StoreObserverProtocol 25 | 26 | func storeDidUpdate(state: FeedListState, 27 | previousState: FeedListState?) { 28 | // No-op. 29 | } 30 | 31 | /// Handles the store `action`. 32 | func didReceiveStoreAction(_ action: CZActionProtocol) { 33 | dbgPrintWithFunc(self, "\(action)") 34 | 35 | switch action { 36 | case let CZFeedListViewAction.selectedCell(indexPath, feedModel): 37 | break 38 | default: 39 | break 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/UI Layer/FeedList/HotUsers/HotUserCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HotUserCellViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | class HotUserCellViewModel: NSObject, CZFeedViewModelable { 13 | var diffId: String { 14 | return currentClassName + (user.userId ?? "") 15 | } 16 | private(set) var user: User 17 | var userName: String? {return user.userName} 18 | var fullName: String? {return user.fullName} 19 | 20 | var portraitUrl: URL? { 21 | guard let urlStr = user.portraitUrl else {return nil} 22 | return URL(string: urlStr) 23 | } 24 | 25 | required init(_ user: User) { 26 | self.user = user 27 | super.init() 28 | } 29 | 30 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 31 | guard let object = object as? HotUserCellViewModel else {return false} 32 | return user.isEqual(toDiffableObj: object.user) 33 | } 34 | 35 | func copy(with zone: NSZone?) -> Any { 36 | let userCopy = user.copy() as! User 37 | return HotUserCellViewModel(userCopy) 38 | } 39 | } 40 | 41 | extension HotUserCellViewModel: StateProtocol { 42 | func reduce(action: CZActionProtocol) -> Self { 43 | return self 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/UI Layer/FeedList/HotUsers/HotUsersCellViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/UI Layer/FeedList/HotUsers/HotUsersCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HotUsersCellViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | class HotUsersCellViewModel: NSObject, CZFeedViewModelable { 13 | var diffId: String { 14 | return currentClassName 15 | } 16 | private(set) var users: [User] 17 | 18 | required init(_ users: [User]) { 19 | self.users = users 20 | super.init() 21 | } 22 | 23 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 24 | guard let object = object as? HotUsersCellViewModel else {return false} 25 | return users.isEqual(toDiffableObj: object.users) 26 | } 27 | 28 | func copy(with zone: NSZone?) -> Any { 29 | let usersCopy = users.copy() as! [User] 30 | return HotUsersCellViewModel(usersCopy) 31 | } 32 | } 33 | 34 | extension HotUsersCellViewModel: StateProtocol { 35 | func reduce(action: CZActionProtocol) -> Self { 36 | return self 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemo/Utils/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 7/14/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Constants of the project 12 | enum Constants { 13 | static let feedListViewInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) 14 | static let userStoriesSectionHeight: CGFloat = 40 15 | static let suggestedUsersCellHeight: CGFloat = 110 16 | static let suggestedUsersCellBGColor = UIColor(white: 250.0 / 255.0, alpha: 1) 17 | } 18 | 19 | enum AccessibilityLabel { 20 | static let feedListCollectionView = "feedListCollectionView" 21 | } 22 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemoUITests/ReactiveListViewKitDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKitDemoUITests.swift 3 | // ReactiveListViewKitDemoUITests 4 | // 5 | // Created by Cheng Zhang on 2025/03/29. 6 | // 7 | 8 | import XCTest 9 | 10 | final class ReactiveListViewKitDemoUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { 37 | // This measures how long it takes to launch your application. 38 | measure(metrics: [XCTApplicationLaunchMetric()]) { 39 | XCUIApplication().launch() 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Example/ReactiveListViewKitDemoUITests/ReactiveListViewKitDemoUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKitDemoUITestsLaunchTests.swift 3 | // ReactiveListViewKitDemoUITests 4 | // 5 | // Created by Cheng Zhang on 2025/03/29. 6 | // 7 | 8 | import XCTest 9 | 10 | final class ReactiveListViewKitDemoUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Data Layer/CZMocker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZMocker.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/12/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | class CZMocker: NSObject { 13 | static let shared = CZMocker() 14 | 15 | var feeds: [Feed] { 16 | let url = Bundle.main.url(forResource: "feeds", withExtension: "json")! 17 | return CodableHelper.decode(url) ?? [] 18 | } 19 | 20 | var hotUsers: [User] { 21 | let url = Bundle.main.url(forResource: "users", withExtension: "json")! 22 | return CodableHelper.decode(url) ?? [] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Data Layer/ImageInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageInfo.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | /// Model of image info 13 | class ImageInfo: ReactiveListDiffable { 14 | let url: String 15 | let width: Int 16 | let height: Int 17 | 18 | // MARK: - CZListDiffable 19 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 20 | return isEqual(toCodable: object) 21 | } 22 | 23 | // MARK: - NSCopying 24 | func copy(with zone: NSZone? = nil) -> Any { 25 | return codableCopy(with: zone) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Data Layer/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/3/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | /// Model of user 13 | class User: ReactiveListDiffable { 14 | let userId: String 15 | let userName: String 16 | let fullName: String? 17 | let portraitUrl: String? 18 | 19 | enum CodingKeys: String, CodingKey { 20 | case userId = "id" 21 | case userName = "username" 22 | case fullName = "full_name" 23 | case portraitUrl = "profile_picture" 24 | } 25 | 26 | // MARK: - CZListDiffable 27 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 28 | return isEqual(toCodable: object) 29 | } 30 | 31 | // MARK: - NSCopying 32 | func copy(with zone: NSZone? = nil) -> Any { 33 | return codableCopy(with: zone) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/FLUX/FeedListAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedListActions.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | // MARK: - Events 13 | 14 | /// Action that User likes one `Feed` 15 | struct LikeFeedAction: Action { 16 | var feed: Feed 17 | } 18 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/FLUX/SuggestedUserAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SuggestedUserEvent.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/28/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | /// Action that follow/ignore `SuggestedUser` 13 | enum SuggestedUserAction: Action { 14 | case follow(user: User) 15 | case ignore(user: User) 16 | } 17 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/FLUX/UserStoryAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserStoryEvent.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/28/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | /// Action that User selects `UserStory` 13 | enum UserStoryAction: Action { 14 | case selected(user: User) 15 | } 16 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/ListViewUITest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListViewUITest.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 10/26/18. 6 | // Copyright © 2018 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class ListViewUITest: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 7/14/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | var window: UIWindow? 14 | 15 | internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | return true 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/.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 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/CommonCrypto.xcconfig: -------------------------------------------------------------------------------- 1 | MODULEMAP_FILE[sdk=macosx*] = $(SRCROOT)/CommonCrypto/macosx.modulemap 2 | MODULEMAP_FILE[sdk=iphoneos*] = $(SRCROOT)/CommonCrypto/iphoneos.modulemap 3 | MODULEMAP_FILE[sdk=iphonesimulator*] = $(SRCROOT)/CommonCrypto/iphonesimulator.modulemap 4 | MODULEMAP_FILE[sdk=watchos*] = $(SRCROOT)/CommonCrypto/watchos.modulemap 5 | MODULEMAP_FILE[sdk=watchsimulator*] = $(SRCROOT)/CommonCrypto/watchsimulator.modulemap 6 | MODULEMAP_FILE[sdk=appletvos*] = $(SRCROOT)/CommonCrypto/appletvos.modulemap 7 | MODULEMAP_FILE[sdk=appletvsimulator*] = $(SRCROOT)/CommonCrypto/appletvsimulator.modulemap 8 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/appletvos.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/appletvsimulator.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/iphoneos.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/iphonesimulator.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/macosx.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/watchos.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/CommonCrypto/watchsimulator.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/CommonCrypto/README.md: -------------------------------------------------------------------------------- 1 | # CommonCrypto 2 | CommonCrypto module wrapper project for Xcode 8 and Swift 3 3 | 4 | # How to use 5 | 6 | ## Adding as subproject into Xcode 7 | Clone / download this project. Add this project as a subproject to your swift framework / app by dragging .xcodeproj file a little below your main project in Xcode. 8 | 9 | ## Adding as \*.framework binaries 10 | Build binary for each target which produces CommonCrypto.framework for each platform, then copy those \*.framework files with their parent folders into your parent project via dropping them to Xcode and applying “Copy items if needed” checkbox (unselect any target membership though). If you drop them without folders Xcode will not allow to do that because their names are equivalent. 11 | 12 | After you added it as a subproject or as binary frameworks into Xcode, just use "import CommonCrypto" statement in your target swift classes, now underlying CommonCrypto C API is available. 13 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/ColorFrame.imageset/ColorFrameFull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/ColorFrame.imageset/ColorFrameFull.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/ColorFrame.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "ColorFrameFull.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_chat_1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_chat_1-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_chat_1-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/ic_chat_1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/ic_chat_1-1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/ic_chat_1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/ic_chat_1-2.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/ic_chat_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Comment.imageset/ic_chat_1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "instagramTitle-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "instagramTitle-2.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "instagramTitle.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/instagramTitle-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/instagramTitle-1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/instagramTitle-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/instagramTitle-2.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/instagramTitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/InstagramTitle.imageset/instagramTitle.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_like.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_like-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_like-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/ic_like-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/ic_like-1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/ic_like-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/ic_like-2.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/ic_like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Like.imageset/ic_like.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_liked-2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_liked-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_liked.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/ic_liked-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/ic_liked-1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/ic_liked-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/ic_liked-2.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/ic_liked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Liked.imageset/ic_liked.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Menu.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_menu.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_menu-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_menu-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Menu.imageset/ic_menu-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Menu.imageset/ic_menu-1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Menu.imageset/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Menu.imageset/ic_menu.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/PostImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "placeholder.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/PostImage.imageset/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/PostImage.imageset/placeholder.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_share_file.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_share_file-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_share_file-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/ic_share_file-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/ic_share_file-1.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/ic_share_file-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/ic_share_file-2.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/ic_share_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/Share.imageset/ic_share_file.png -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/noUser.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/noUser.imageset/no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geekaurora/ReactiveListViewKit/3e94cde3afd99cf8f6f94ebea9932f60d478a1ad/Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/Assets.xcassets/noUser.imageset/no-user-image-square-9f6a473a32ad639f619216331d10d61ce1b35c9271d5683920960e1a5ee45bb8.jpg -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Supported Files/Resources/users copy.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "full_name": "Diane", 3 | "username": "fallinlight", 4 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/fallinlight.jpg", 5 | "id": "0" 6 | }, { 7 | "full_name": "Caeli", 8 | "username": "caeliyt", 9 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/caeliyt.jpg", 10 | "id": "1" 11 | }, { 12 | "full_name": "Pixlr", 13 | "username": "pixlr", 14 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/pixlr.jpg", 15 | "id": "2" 16 | }, { 17 | "full_name": "Zayn Malik", 18 | "username": "zayn", 19 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/zayn.jpg", 20 | "id": "3" 21 | }, { 22 | "full_name": "Martin Garrix", 23 | "username": "martingarrix", 24 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/martingarrix.jpg", 25 | "id": "4" 26 | }, { 27 | "full_name": "Mariale Marrero", 28 | "username": "mariale", 29 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/mariale.jpg", 30 | "id": "5" 31 | }, { 32 | "full_name": "Picsart Editor", 33 | "username": "picsart_ediitor", 34 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/picsart_ediitor.jpg", 35 | "id": "6" 36 | }, { 37 | "full_name": "Tutorial edit PicsArt", 38 | "username": "picsart_indo", 39 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/picsart_indo.jpg", 40 | "id": "7" 41 | }, { 42 | "full_name": "Annegien", 43 | "username": "fetching_tigerss", 44 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/fetching_tigerss.jpg", 45 | "id": "8" 46 | }, { 47 | "full_name": "Lesslie Polinesia", 48 | "username": "ppteamlesslie", 49 | "profile_picture": "https://d37t5b145o82az.cloudfront.net/portriats/ppteamlesslie.jpg", 50 | "id": "9" 51 | }] 52 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/UI Layer/FeedList/FeedCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedCellViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | import ReactiveListViewKit 11 | 12 | /** 13 | ViewModel of `FeedCellView`, composed of elements needed for UI populating, based on `Feed` model 14 | */ 15 | class FeedCellViewModel: NSObject, CZFeedViewModelable { 16 | var diffId: String { 17 | return currentClassName + feed.feedId 18 | } 19 | private(set) var feed: Feed 20 | var isInFeedDetails: Bool = false 21 | 22 | var userName: String? {return feed.user?.userName} 23 | var content: String? {return feed.content} 24 | 25 | var portraitUrl: URL? { 26 | guard let urlStr = feed.user?.portraitUrl else {return nil} 27 | return URL(string: urlStr) 28 | } 29 | var imageUrl: URL? { 30 | guard let urlStr = feed.imageInfo?.url else {return nil} 31 | return URL(string: urlStr) 32 | } 33 | var likesCount: Int { 34 | return feed.likesCount 35 | } 36 | var userHasLiked: Bool { 37 | return feed.userHasLiked 38 | } 39 | 40 | required init(_ feed: Feed) { 41 | self.feed = feed 42 | super.init() 43 | } 44 | 45 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 46 | guard let object = object as? FeedCellViewModel else {return false} 47 | return feed.isEqual(toDiffableObj: object.feed) && 48 | isInFeedDetails == object.isInFeedDetails 49 | } 50 | 51 | func copy(with zone: NSZone?) -> Any { 52 | let feedCopy = feed.copy() as! Feed 53 | return FeedCellViewModel(feedCopy) 54 | } 55 | } 56 | 57 | extension FeedCellViewModel: State { 58 | func reduce(action: Action) { 59 | // No-op. 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/UI Layer/FeedList/FeedListActionHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedListActionHandler.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 7/14/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | protocol FeedListActionHandlerCoordinator {} 13 | 14 | /** 15 | Action handler for `FeedListViewController` 16 | 17 | Coordinator pattern decouples user action handling from ViewController to make it less massive 18 | */ 19 | class FeedListActionHandler: NSObject, Middleware { 20 | 21 | var coordinator: FeedListActionHandlerCoordinator? 22 | 23 | // MARK: - Middleware 24 | 25 | func process(action: Action, state: FeedListState) { 26 | dbgPrint("Received action: \(action)") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/UI Layer/FeedList/HotUsers/HotUserCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HotUserCellViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | class HotUserCellViewModel: NSObject, CZFeedViewModelable { 13 | var diffId: String { 14 | return currentClassName + (user.userId ?? "") 15 | } 16 | private(set) var user: User 17 | var userName: String? {return user.userName} 18 | var fullName: String? {return user.fullName} 19 | 20 | var portraitUrl: URL? { 21 | guard let urlStr = user.portraitUrl else {return nil} 22 | return URL(string: urlStr) 23 | } 24 | 25 | required init(_ user: User) { 26 | self.user = user 27 | super.init() 28 | } 29 | 30 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 31 | guard let object = object as? HotUserCellViewModel else {return false} 32 | return user.isEqual(toDiffableObj: object.user) 33 | } 34 | 35 | func copy(with zone: NSZone?) -> Any { 36 | let userCopy = user.copy() as! User 37 | return HotUserCellViewModel(userCopy) 38 | } 39 | } 40 | 41 | extension HotUserCellViewModel: State { 42 | func reduce(action: Action) { 43 | // no-op 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/UI Layer/FeedList/HotUsers/HotUsersCellViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/UI Layer/FeedList/HotUsers/HotUsersCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HotUsersCellViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 3/4/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ReactiveListViewKit 11 | 12 | class HotUsersCellViewModel: NSObject, CZFeedViewModelable { 13 | var diffId: String { 14 | return currentClassName 15 | } 16 | private(set) var users: [User] 17 | 18 | required init(_ users: [User]) { 19 | self.users = users 20 | super.init() 21 | } 22 | 23 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 24 | guard let object = object as? HotUsersCellViewModel else {return false} 25 | return users.isEqual(toDiffableObj: object.users) 26 | } 27 | 28 | func copy(with zone: NSZone?) -> Any { 29 | let usersCopy = users.copy() as! [User] 30 | return HotUsersCellViewModel(usersCopy) 31 | } 32 | } 33 | 34 | extension HotUsersCellViewModel: State { 35 | func reduce(action: Action) { 36 | // no-op 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CZNetError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZNetError.swift 3 | // CZNetworking 4 | // 5 | // Created by Cheng Zhang on 12/9/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | 11 | /// Network Error class 12 | open class CZNetError: CZError { 13 | fileprivate static let domain = "CZNetworking" 14 | public static let `default` = CZNetError("Network Error") 15 | public static let returnType = CZNetError("ReturnType Error") 16 | 17 | public init(_ description: String? = nil, code: Int = 99) { 18 | super.init(domain: CZNetError.domain, code: code, description: description) 19 | } 20 | 21 | required public init?(coder aDecoder: NSCoder) { 22 | super.init(coder: aDecoder) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CZNetworking.h: -------------------------------------------------------------------------------- 1 | // 2 | // CZNetworking.h 3 | // CZNetworking 4 | // 5 | // Created by Cheng Zhang on 12/9/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CZNetworking. 12 | FOUNDATION_EXPORT double CZNetworkingVersionNumber; 13 | 14 | //! Project version string for CZNetworking. 15 | FOUNDATION_EXPORT const unsigned char CZNetworkingVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/.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 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/CommonCrypto.xcconfig: -------------------------------------------------------------------------------- 1 | MODULEMAP_FILE[sdk=macosx*] = $(SRCROOT)/CommonCrypto/macosx.modulemap 2 | MODULEMAP_FILE[sdk=iphoneos*] = $(SRCROOT)/CommonCrypto/iphoneos.modulemap 3 | MODULEMAP_FILE[sdk=iphonesimulator*] = $(SRCROOT)/CommonCrypto/iphonesimulator.modulemap 4 | MODULEMAP_FILE[sdk=watchos*] = $(SRCROOT)/CommonCrypto/watchos.modulemap 5 | MODULEMAP_FILE[sdk=watchsimulator*] = $(SRCROOT)/CommonCrypto/watchsimulator.modulemap 6 | MODULEMAP_FILE[sdk=appletvos*] = $(SRCROOT)/CommonCrypto/appletvos.modulemap 7 | MODULEMAP_FILE[sdk=appletvsimulator*] = $(SRCROOT)/CommonCrypto/appletvsimulator.modulemap 8 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/appletvos.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/appletvsimulator.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/iphoneos.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/iphonesimulator.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/macosx.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/watchos.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/CommonCrypto/watchsimulator.modulemap: -------------------------------------------------------------------------------- 1 | module CommonCrypto [system] { 2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/CommonCrypto/README.md: -------------------------------------------------------------------------------- 1 | # CommonCrypto 2 | CommonCrypto module wrapper project for Xcode 8 and Swift 3 3 | 4 | # How to use 5 | 6 | ## Adding as subproject into Xcode 7 | Clone / download this project. Add this project as a subproject to your swift framework / app by dragging .xcodeproj file a little below your main project in Xcode. 8 | 9 | ## Adding as \*.framework binaries 10 | Build binary for each target which produces CommonCrypto.framework for each platform, then copy those \*.framework files with their parent folders into your parent project via dropping them to Xcode and applying “Copy items if needed” checkbox (unselect any target membership though). If you drop them without folders Xcode will not allow to do that because their names are equivalent. 11 | 12 | After you added it as a subproject or as binary frameworks into Xcode, just use "import CommonCrypto" statement in your target swift classes, now underlying CommonCrypto C API is available. 13 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworking/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // CZNetworking 4 | // 5 | // Created by Cheng Zhang on 12/11/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CommonCrypto 11 | 12 | public extension String { 13 | /// MD5 HashValue: Should #import in your Bridging-Header file 14 | public var MD5: String { 15 | let length = Int(CC_MD5_DIGEST_LENGTH) 16 | var digest = [UInt8](repeating: 0, count: length) 17 | 18 | if let d = self.data(using: String.Encoding.utf8) { 19 | _ = d.withUnsafeBytes { (body: UnsafePointer) in 20 | CC_MD5(body, CC_LONG(d.count), &digest) 21 | } 22 | } 23 | 24 | return (0.. 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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworkingTests/CZNetworkingTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZNetworkingTests.swift 3 | // CZNetworkingTests 4 | // 5 | // Created by Cheng Zhang on 12/9/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CZNetworking 11 | 12 | class CZNetworkingTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/CZNetworkingTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Cheng Zhang 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/CZNetworking/README.md: -------------------------------------------------------------------------------- 1 | # CZNetworking 2 | 3 | Elegant progressive asynchronous HTTP request flow management framework. 4 | 5 | * Supports GET/PUT/POST/DELETE 6 | * Supports success/failure/pregress callback closure 7 | 8 | ### Instagram Demo - [Github](https://github.com/showt1me/CZInstagram) 9 | Implemented on top of **CZNetworking** 10 | 11 | 12 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitDemo/Utils/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // ReactiveListViewKitDemo 4 | // 5 | // Created by Cheng Zhang on 7/14/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Constants of the project 12 | enum Constants { 13 | static let feedListViewInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) 14 | static let userStoriesSectionHeight: CGFloat = 40 15 | static let suggestedUsersCellHeight: CGFloat = 110 16 | static let suggestedUsersCellBGColor = UIColor(white: 250.0 / 255.0, alpha: 1) 17 | } 18 | 19 | enum AccessibilityLabel { 20 | static let feedListCollectionView = "feedListCollectionView" 21 | } 22 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitUITests/Utils/CZUITest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZUITest.swift 3 | // 4 | // Created by Cheng Zhang on 2/6/17. 5 | // Copyright © 2017 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import KIF 9 | 10 | class CZUITest: KIFTestCase { 11 | override func setUp() { 12 | super.setUp() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/Example/ReactiveListViewKitUITests/Utils/KIFUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KIFUtils.swift 3 | // 4 | // Created by Cheng Zhang on 2/6/17. 5 | // Copyright © 2017 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import KIF 9 | 10 | extension XCTestCase { 11 | func tester(file : String = #file, _ line : Int = #line) -> KIFUITestActor { 12 | return KIFUITestActor(inFile: file, atLine: line, delegate: self) 13 | } 14 | 15 | func system(file : String = #file, _ line : Int = #line) -> KIFSystemTestActor { 16 | return KIFSystemTestActor(inFile: file, atLine: line, delegate: self) 17 | } 18 | } 19 | 20 | extension KIFTestActor { 21 | func tester(file : String = #file, _ line : Int = #line) -> KIFUITestActor { 22 | return KIFUITestActor(inFile: file, atLine: line, delegate: self) 23 | } 24 | 25 | func system(file : String = #file, _ line : Int = #line) -> KIFSystemTestActor { 26 | return KIFSystemTestActor(inFile: file, atLine: line, delegate: self) 27 | } 28 | } 29 | 30 | extension KIFUITestActor { 31 | /** 32 | Return View with given `accessibilityIdentifier` if present, nil otherwise 33 | 34 | - warning: Should specify accessibilityIdentifier, instead of accessibilityLabel 35 | */ 36 | func view(withAccessibilityIdentifier accessibilityIdentifier: String) -> UIView? { 37 | var view: UIView? 38 | wait(for: nil, view: &view, withIdentifier: accessibilityIdentifier, tappable: false) 39 | return view 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ReactiveListViewKit' 3 | s.version = '1.2.4' 4 | s.summary = 'MVVM + FLUX Reactive Facade ViewKit, eliminates Massive View Controller in unidirectional action/state flow manner.' 5 | 6 | s.description = <<-DESC 7 | - MVVM + FLUX reactive facade ViewKit for feed based app development 8 | - Eliminates Massive View Controller in unidirectional Action/State flow manner 9 | DESC 10 | 11 | s.homepage = 'https://github.com/geekaurora/ReactiveListViewKit' 12 | #s.screenshots = '' 13 | s.license = { :type => 'MIT', :file => 'LICENSE' } 14 | s.author = { 'geekaurora' => 'showt2me@gmail.com' } 15 | s.source = { :git => 'https://github.com/geekaurora/ReactiveListViewKit.git', :tag => s.version.to_s } 16 | # s.social_media_url = 'https://twitter.com/' 17 | 18 | s.ios.deployment_target = '10.0' 19 | s.source_files = 'ReactiveListViewKit/ReactiveListViewKit/**/*' 20 | s.pod_target_xcconfig = { 'SWIFT_VERSION' => '3' } 21 | 22 | # s.resource_bundles = { 23 | # 'ReactiveListViewKit' => ['ReactiveListViewKit/Assets/*.png'] 24 | # } 25 | 26 | # s.public_header_files = 'Pod/Classes/**/*.h' 27 | 28 | s.frameworks = 'UIKit' 29 | s.dependency 'CZUtils' 30 | 31 | end 32 | 33 | 34 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/CZFeedDetailsModel.swift: -------------------------------------------------------------------------------- 1 | /// 2 | // CZFeedDetailsModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/5/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Base building block for `CZFeedDetailsFacadeView`, highly decouples View/ViewModel layers 12 | /// 13 | /// Composed of: 14 | /// - viewClass: CZFeedCellViewSizeCalculatable 15 | /// - voewModel: CZFeedViewModelable 16 | /// 17 | public typealias CZFeedDetailsModel = CZFeedModel 18 | 19 | //public class CZFeedDetailsModel: NSObject, CZFeedModelable { 20 | // public let viewClass: CZFeedCellViewable.Type 21 | // public let viewModel: CZFeedViewModelable 22 | // 23 | // public required init(viewClass: CZFeedCellViewable.Type, 24 | // viewModel: CZFeedViewModelable) { 25 | // self.viewClass = viewClass 26 | // self.viewModel = viewModel 27 | // super.init() 28 | // } 29 | // 30 | // public func isEqual(toDiffableObj object: AnyObject) -> Bool { 31 | // guard let object = object as? CZFeedDetailsModel else {return false} 32 | // return viewClass == object.viewClass && 33 | // viewModel.isEqual(toDiffableObj: object.viewModel) 34 | // } 35 | // 36 | // public func copy(with zone: NSZone? = nil) -> Any { 37 | // let viewClassCopy = viewClass 38 | // let viewModelCopy = viewModel.copy(with: zone) as! CZFeedViewModelable 39 | // return type(of: self).init( 40 | // viewClass: viewClassCopy, 41 | // viewModel: viewModelCopy) 42 | // } 43 | //} 44 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/CZFeedDetailsViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedDetailsViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/3/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | ViewModel/State class for `CZFeedDetailsFacadeView` 13 | */ 14 | open class CZFeedDetailsViewModel: NSObject, NSCopying { 15 | 16 | private var _feedModels: [CZFeedModelable] 17 | required public init(feedModels: [CZFeedModelable]? = nil) { 18 | _feedModels = feedModels ?? [] 19 | } 20 | 21 | public func batchUpdate(with feedModels: [CZFeedModelable]) { 22 | _feedModels.removeAll() 23 | _feedModels.append(contentsOf: feedModels) 24 | } 25 | 26 | // MARK: - NSCopying 27 | public func copy(with zone: NSZone? = nil) -> Any { 28 | let feedModels = _feedModels.compactMap{ $0.copy(with: nil) as? CZFeedModelable} 29 | let viewModel = type(of: self).init(feedModels: feedModels) 30 | return viewModel 31 | } 32 | 33 | public var feedModels: [CZFeedDetailsModel] { 34 | return (_feedModels as? [CZFeedDetailsModel]) ?? [] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/CZFeedListViewAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedViewAction.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/10/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Action handler closure 13 | */ 14 | public typealias OnAction = (_ action: Action) -> Void 15 | 16 | /** 17 | General ViewAction 18 | */ 19 | public typealias CZViewAction = Action 20 | 21 | public struct BaseState: State { 22 | public func reduce(action: Action) {} 23 | } 24 | 25 | /** 26 | ViewAction for container feedListView 27 | */ 28 | public enum CZFeedListViewAction: CZViewAction { 29 | case selectedCell(CZFeedModel) 30 | case loadMore 31 | case pullToRefresh(isFirst: Bool) 32 | case prefetch([IndexPath]) 33 | case cancelPrefetching([IndexPath]) 34 | case visibleIndexPathsChanged(newValue: [IndexPath])// (oldIndexPaths, newIndexPaths) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/CZFeedViewModelable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedViewModelable.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/5/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | 11 | /** 12 | Fundamental protocol for CellView of `CZFeedListFacadeView`/`CZFeedDetailsFacadeView` 13 | */ 14 | public protocol CZFeedViewModelable: class, NSObjectProtocol, CZListDiffable, NSCopying { 15 | /// `diffId` is used for diff algorithm of batch update, verify whether two involved viewModels equal 16 | var diffId: String {get} 17 | 18 | var viewHeight: CGFloat {get} 19 | 20 | func isEqual(toDiffableObj object: AnyObject) -> Bool 21 | 22 | func copy(with zone: NSZone?) -> Any 23 | } 24 | 25 | public extension CZFeedViewModelable { 26 | var diffId: String { 27 | currentClassName 28 | } 29 | 30 | var viewHeight: CGFloat { 31 | -1 32 | } 33 | } 34 | 35 | public extension CZFeedViewModelable { 36 | var currentClassName: String { 37 | return NSStringFromClass(type(of: self)) 38 | } 39 | } 40 | 41 | /// Fundamental protocol for ViewModel involved in ListView, verify whether two viewModels equal 42 | public protocol CZListDiffable { 43 | /// Workaround of `Equatable`, because `Equatable` uses associatedType `Self`, which makes `Equatable` can only be used as generic constraint 44 | func isEqual(toDiffableObj object: AnyObject) -> Bool 45 | } 46 | 47 | /// Fundamental protocol composition of reactive listDiffable model 48 | /// - note: The protocol only requires conformance of `Codable` and `NSCopying`, other protocols are conformed by categories automatically. 49 | public typealias ReactiveListDiffable = Codable & NSCopying & CustomStringConvertible & CZListDiffable 50 | 51 | public typealias CZListDiffableObject = CZListDiffable & AnyObject 52 | 53 | // MARK: CZListDiffable 54 | public extension Encodable where Self: Decodable { 55 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 56 | return isEqual(toCodable: object) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/CZReactiveFeedDetailsFacadeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZReactiveFeedDetailsFacadeView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/11/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private var kViewModelObserverContext: Int = 0 12 | 13 | /** 14 | Reactive view class of `FeedDetailsFacadeView`, supports FLUX pattern 15 | */ 16 | open class CZReactiveFeedDetailsFacadeView: CZFeedDetailsFacadeView { 17 | var store: Store? 18 | public override var onAction: OnAction? { 19 | get { 20 | guard let store = store else { return super.onAction } 21 | return {action in store.dispatch(action: action) } 22 | } 23 | set { super.onAction = newValue } 24 | } 25 | 26 | public init(containerViewController: UIViewController? = nil, 27 | store: Store? = nil, 28 | onAction: OnAction? = nil) { 29 | super.init(containerViewController: containerViewController, onAction: onAction) 30 | self.store = store 31 | } 32 | public required init?(coder: NSCoder) { 33 | super.init(coder: coder) 34 | } 35 | 36 | public override func setup() { 37 | super.setup() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/CZReactiveFeedListFacadeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZReactiveFeedListFacadeView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/11/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Reactive view class of `FeedListFacadeView`, supports FLUX pattern 13 | */ 14 | open class CZReactiveFeedListFacadeView: CZFeedListFacadeView { 15 | 16 | let store: Store 17 | 18 | public init(store: Store, 19 | sectionModelsTransformer: @escaping SectionModelsTransformer, 20 | parentViewController: UIViewController? = nil, 21 | loadMoreThreshold: Int = CZFeedListFacadeView.kLoadMoreThreshold, 22 | minimumLineSpacing: CGFloat = ReactiveListViewKit.minimumLineSpacing) { 23 | self.store = store 24 | let onAction = { (action: Action) in 25 | store.dispatch(action: action) 26 | } 27 | super.init(sectionModelsTransformer: sectionModelsTransformer, 28 | onAction: onAction, 29 | parentViewController: parentViewController, 30 | loadMoreThreshold: loadMoreThreshold) 31 | } 32 | 33 | public required init?(coder: NSCoder) { fatalError("Must call designated initializer.") } 34 | } 35 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/TemplateViews/CZDividerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZDividerView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/16/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Convenience divider view class 13 | */ 14 | public final class CZDividerView: UIView { 15 | private let size: CGFloat 16 | private let bgColor: UIColor 17 | 18 | public init(size: CGFloat = 1, 19 | backgroudColor: UIColor = ReactiveListViewKit.GreyDividerColor) { 20 | self.size = size 21 | self.bgColor = backgroudColor 22 | super.init(frame: .zero) 23 | setup() 24 | } 25 | 26 | public required init?(coder: NSCoder) { 27 | fatalError("Must call designated initializer.") 28 | } 29 | } 30 | 31 | private extension CZDividerView { 32 | func setup() { 33 | translatesAutoresizingMaskIntoConstraints = false 34 | backgroundColor = self.bgColor 35 | let sizeContrait = heightAnchor.constraint(equalToConstant: size) 36 | sizeContrait.priority = UILayoutPriority(rawValue: 749) 37 | sizeContrait.isActive = true 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/TemplateViews/CZFeedListSupplementaryView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedListSupplementaryView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/7/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Convenience class of SectionHeaderView/SectionFooterView 13 | */ 14 | open class CZFeedListSupplementaryView: UICollectionReusableView { 15 | open override var reuseIdentifier: String? { 16 | return type(of: self).reuseId 17 | } 18 | private var model: CZFeedModel? 19 | private var contentView: CZFeedCellViewSizeCalculatable? 20 | public static var reuseId: String { 21 | return NSStringFromClass(object_getClass(self)!) 22 | } 23 | open func config(with model: CZFeedModel, 24 | onAction: OnAction?) { 25 | defer { 26 | self.model = model 27 | contentView?.config(with: model.viewModel) 28 | } 29 | // Reset contentView if contentViewClass differs from the current one 30 | if let contentView = contentView, 31 | let currModel = self.model, 32 | currModel.viewClass != model.viewClass { 33 | (contentView as? UIView)?.removeFromSuperview() 34 | self.contentView = nil 35 | } 36 | if contentView == nil { 37 | self.contentView = model.viewClass.init(viewModel: model.viewModel, onAction: onAction) 38 | guard let contentView = self.contentView as? UIView else { 39 | assertionFailure("\(model.viewClass) should be subClass of UIView!") 40 | return 41 | } 42 | contentView.translatesAutoresizingMaskIntoConstraints = false 43 | contentView.isUserInteractionEnabled = false 44 | addSubview(contentView) 45 | contentView.overlayOnSuperview() 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/Utils/Array+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array+Extension.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/15/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension Array where Element: CZListDiffableObject { 12 | /** 13 | Check whether elements in two arrays equal 14 | */ 15 | public func isEqual(toDiffableObj object: Any) -> Bool { 16 | guard let object = object as? [Element], 17 | count == object.count else { 18 | return false 19 | } 20 | return (0.. Bool { 14 | switch(obj1, obj2) { 15 | case let (obj1 as CZListDiffableObject, obj2 as CZListDiffableObject): 16 | return obj1.isEqual(toDiffableObj: obj2) 17 | default: 18 | return (obj1 == nil && obj2 == nil) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/Utils/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKitConstants.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/2/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Constants of ReactiveListViewKit 13 | */ 14 | public enum ReactiveListViewKit { 15 | public static var isDebugMode = true 16 | public static var isIncrementalUpdateEnabled = true 17 | public static var useGCD = false 18 | 19 | // MARK: - Self Sizing Cells 20 | 21 | public static var enableSelfSizingCellsForVerticalOrientation = true 22 | public static var enableSelfSizingCellsForHorizontalOrientation = true 23 | 24 | public static let ClearBGColor = UIColor.clear 25 | public static let GreyBGColor = UIColor(white: 240.0 / 255.0, alpha: 1.0) 26 | public static let GreyDividerColor = UIColor(white: 217.0 / 255.0, alpha: 1.0) 27 | public static let minimumLineSpacing: CGFloat = 10 28 | public static let minimumInteritemSpacing: CGFloat = 10 29 | public static let sectionInset = UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 0) 30 | 31 | public enum FeedListSupplementaryTextView { 32 | public static let inset = UIEdgeInsets(top: 8, left: 10, bottom: 3, right: 10) 33 | public static let titleFont = UIFont.boldSystemFont(ofSize: 14) 34 | public static let titleColor = UIColor(white: 0.1, alpha: 1) 35 | public static let actionButtonColor = UIColor(red: 62.0 / 255.0, green: 153 / 255.0, blue: 237 / 255.0, alpha: 1) 36 | } 37 | 38 | public static let horizontalSectionAdapterViewBGColor: UIColor = .clear 39 | 40 | public static let feedListSupplementaryLineHeaderViewInset = UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0) 41 | public static let feedListSupplementaryLineFooterViewInset = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) 42 | } 43 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKit/Utils/ReactiveListViewKitHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKitHelper.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 11/6/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | 11 | public func dbgPrint(_ item: CustomStringConvertible) { 12 | guard ReactiveListViewKit.isDebugMode else { return } 13 | _dbgPrint(item) 14 | } 15 | 16 | public func PrettyString(_ object: Any) -> String { 17 | guard let object = object as? CustomStringConvertible else { 18 | return "" 19 | } 20 | if let indexSet = object as? IndexSet { 21 | return indexSet.reduce("[") { (prevResult, index) -> String in 22 | prevResult + String(index) + ", " 23 | } + "]" 24 | } else { 25 | return object.description 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKitTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/ReactiveListViewKitTests/Utils/CZListDiff+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZListDiff.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/5/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import ReactiveListViewKit 10 | 11 | extension CZListDiff { 12 | /** 13 | Return empty SectionIndexDiffResult 14 | */ 15 | public static var emptyDiffSectionModelIndexes: SectionIndexDiffResult { 16 | let sectionsDiff: [SectionDiffResultKey: Any] = [:] 17 | let rowsDiff: [RowDiffResultKey: [Any]] = [:] 18 | return (sectionsDiff, rowsDiff) 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Cheng Zhang 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.1 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( 7 | name: "CZUtils", 8 | platforms: [ 9 | .iOS(.v11), 10 | ], 11 | products: [ 12 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 13 | .library( 14 | name: "CZUtils", 15 | targets: ["CZUtils"]), 16 | ], 17 | dependencies: [ 18 | // Dependencies declare other packages that this package depends on. 19 | // .package(url: /* package url */, from: "1.0.0"), 20 | ], 21 | targets: [ 22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 23 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 24 | .target( 25 | name: "CZUtils", 26 | dependencies: []), 27 | .testTarget( 28 | name: "CZUtilsTests", 29 | dependencies: ["CZUtils"]), 30 | ] 31 | ) 32 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/README.md: -------------------------------------------------------------------------------- 1 | # CZUtils 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/CZUtils.svg?style=flat)](http://cocoapods.org/pods/CZUtils) 4 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 5 | ![Swift Version](https://img.shields.io/badge/swift-3.2-orange.svg) 6 | [![License](https://img.shields.io/cocoapods/l/CZUtils.svg?style=flat)](http://cocoapods.org/pods/CZUtils) 7 | [![Platform](https://img.shields.io/cocoapods/p/CZUtils.svg?style=flat)](http://cocoapods.org/pods/CZUtils) 8 | 9 | ### Powerful toolset for Utils layer 10 | 11 | * CZMutexLock on top of GCD 12 | * NSNullGuard 13 | * MainQueueScheduler 14 | * SwizzlingHelper 15 | * ThreadSafeDictionary 16 | * NibLoadable for UIView/Cell 17 | 18 | 19 | ## Installation 20 | 21 | CZUtils is available through [CocoaPods](http://cocoapods.org). To install 22 | it, simply add the following line to your Podfile: 23 | 24 | ```ruby 25 | pod 'CZUtils' 26 | ``` 27 | 28 | And run `pod install` in your work folder. -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZAlertManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZAlertManager.swift 3 | // 4 | // Created by Cheng Zhang on 1/15/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | /// Convenient helper class for AlertViewController displaying 11 | open class CZAlertManager: NSObject { 12 | 13 | open class func showAlert(title: String? = nil, 14 | message: String, 15 | confirmText: String = "Ok", 16 | confirmHandler: ((UIAlertAction) -> Void)? = nil, 17 | cancelText: String? = nil, 18 | cancelHandler: ((UIAlertAction) -> Void)? = nil, 19 | on viewController: UIViewController? = nil, 20 | completion: (() -> Void)? = nil) { 21 | let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) 22 | let action1 = UIAlertAction(title: confirmText, style: .default, handler: confirmHandler) 23 | alertController.addAction(action1) 24 | if let cancelText = cancelText { 25 | let action2 = UIAlertAction(title: cancelText, style: .cancel, handler: cancelHandler) 26 | alertController.addAction(action2) 27 | } 28 | 29 | guard let presentingViewController = viewController ?? UIApplication.shared.keyWindow?.rootViewController else { 30 | assertionFailure("Couldn't find valid presenting ViewController.") 31 | return 32 | } 33 | presentingViewController.topMost.present(alertController, animated: true, completion: completion) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZDictionary.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZDictionary.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 2018/7/6. 6 | // Copyright © 2019 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public typealias CZDictionary = [AnyHashable : Any] 12 | 13 | public protocol CZDictionaryable { 14 | init(dictionary: CZDictionary) 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZError.swift 3 | // 4 | // Created by Cheng Zhang on 1/10/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Convenience Error class 11 | open class CZError: NSError { 12 | public init(domain: String, code: Int = 99, description: String? = nil) { 13 | var userInfo: [String: Any]? = nil 14 | if let description = description { 15 | userInfo = [NSLocalizedDescriptionKey: description] 16 | } 17 | super.init(domain: domain, code: code, userInfo: userInfo) 18 | } 19 | 20 | required public init?(coder aDecoder: NSCoder) { 21 | super.init(coder: aDecoder) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZFileHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFileHelper.swift 3 | // 4 | // Created by Cheng Zhang on 1/13/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Helper class for file related methods 11 | @objc open class CZFileHelper: NSObject { 12 | public static func getFileSize(_ filePath: String?) -> Int? { 13 | guard let filePath = filePath else {return nil} 14 | do { 15 | let attrs = try FileManager.default.attributesOfItem(atPath: filePath) 16 | let size = attrs[.size] as? Int 17 | return size 18 | } catch { 19 | dbgPrint("Failed to get file size of \(filePath). Error - \(error.localizedDescription)") 20 | } 21 | return nil 22 | } 23 | 24 | @objc public static var documentDirectory: String { 25 | return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZMainQueueScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZMainQueueScheduler.swift 3 | // 4 | // Created by Cheng Zhang on 1/4/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Convenience class for scheduling sync/async execution on main queue 11 | open class CZMainQueueScheduler: NSObject { 12 | 13 | /// Synchronous execution: inferring function returnType with `execution` closure returnType 14 | public class func sync(_ execution: @escaping () -> T) -> T { 15 | if Thread.isMainThread { 16 | return execution() 17 | } else { 18 | return DispatchQueue.main.sync { 19 | execution() 20 | } 21 | } 22 | } 23 | 24 | /// Asynchronous execution 25 | public class func async(execution: @escaping () -> Void ) { 26 | DispatchQueue.main.async { 27 | execution() 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZProMutexLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZProMutexLock.swift 3 | // 4 | // Created by Cheng Zhang on 2/3/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Mutex lock on top of `pthread_mutex_lock`/`pthread_mutex_unlock` 11 | open class CZProMutexLock: NSObject { 12 | private var mutex = pthread_mutex_t() 13 | 14 | public override init() { 15 | var attr = pthread_mutexattr_t() 16 | guard pthread_mutexattr_init(&attr) == 0 else { 17 | preconditionFailure() 18 | } 19 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL) 20 | guard pthread_mutex_init(&mutex, &attr) == 0 else { 21 | preconditionFailure() 22 | } 23 | } 24 | 25 | deinit { 26 | pthread_mutex_destroy(&mutex) 27 | } 28 | 29 | public func withLock(_ closure: () -> T) -> T { 30 | defer { 31 | pthread_mutex_unlock(&mutex) 32 | } 33 | pthread_mutex_lock(&mutex) 34 | return closure() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZTheme.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZTheme.swift 3 | // 4 | // Created by Cheng Zhang on 4/18/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | /// Common theme settings for projects 11 | public struct CZTheme { 12 | public static let greyDividerColor: CGFloat = 217.0 / 255.0 13 | } 14 | 15 | public extension UIColor { 16 | static let candyGreen = UIColor(red: 67.0/255.0, green: 205.0/255.0, blue: 135.0/255.0, alpha: 1.0) 17 | static let facebookBlue = UIColor(red: 68.0/255.0, green: 105.0/255.0, blue: 176.0/255.0, alpha: 1.0) 18 | static let dividerGrey = UIColor(white: CZTheme.greyDividerColor, alpha: 1) 19 | static let searchBarColor = UIColor(white: 217.0 / 255.0, alpha: 1) 20 | static let searchBarTextGrey = UIColor(white: 127.0 / 255.0, alpha: 1) 21 | static let tabBarTintColor = UIColor(white: 250.0 / 255.0, alpha: 1) 22 | static let tabBarItemTintColor = UIColor(white: 38.0 / 255.0, alpha: 1) 23 | } 24 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 2/19/18. 6 | // Copyright © 2018 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class CZUtils { 12 | public static func dbgPrint(_ item: CustomStringConvertible) { 13 | #if DEBUG 14 | print(item) 15 | #endif 16 | } 17 | } 18 | 19 | public func dbgPrint(_ item: CustomStringConvertible) { 20 | CZUtils.dbgPrint(item) 21 | } 22 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Error+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Error+.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 8/10/19. 6 | // Copyright © 2019 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Error { 12 | var retrievedCode: Int { 13 | return (self as NSError).code 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Array+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array+Extensoin.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 1/26/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Array { 12 | /** 13 | Returns element at specified `safe` index if exists, otherwise nil 14 | */ 15 | subscript (safe index: Index) -> Element? { 16 | return indices.contains(index) ? self[index] : nil 17 | } 18 | 19 | /** 20 | Pretty formatted description string 21 | */ 22 | var prettyDescription: String { 23 | return Pretty.describing(self) 24 | } 25 | } 26 | 27 | public extension Array where Element: NSCopying { 28 | func copy(with zone: NSZone? = nil) -> Any { 29 | return compactMap{ $0.copy() } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Character+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Character+.swift 3 | // 4 | // Created by Cheng Zhang on 12/30/18. 5 | // Copyright © 2018 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Character { 11 | 12 | public var ascii: Int { 13 | return Int(String(self).unicodeScalars.first!.value) 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Date+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 5/19/16. 6 | // Copyright © 2016 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Date { 12 | var simpleString: String { 13 | return string(withFormat: "yyyy-MM-dd hh:mm") 14 | } 15 | 16 | var complexString: String { 17 | return string(withFormat: "EEE, dd MMM yyyy hh:mm:ss +zzzz") 18 | } 19 | 20 | func string(withFormat formatterStr: String) -> String { 21 | let dateFormatter = DateFormatter() 22 | dateFormatter.dateFormat = formatterStr 23 | return dateFormatter.string(from: self) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Dictionary+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dictionary+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 1/29/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Dictionary { 12 | /// Retrieve value from `dotedKey`, compatible with multi-dot in keyPath. e.g. "user.profile.fullName" 13 | func value(forDotedKey dotedKey: String) -> Value? { 14 | return value(forSegmentedKey: dotedKey) 15 | } 16 | 17 | /// Retrieve value from `segmentedKey`, compatible with multi-segments separated by `splitter`. e.g. "user.profile.fullName", "user/profile/fullName" 18 | func value(forSegmentedKey segmentedKey: String, splitter: String = ".") -> Value? { 19 | var value: Any? = nil 20 | var dict: Dictionary? = self 21 | 22 | for subkey in segmentedKey.components(separatedBy: splitter) { 23 | guard dict != nil, let subkey = subkey as? Key else { 24 | return nil 25 | } 26 | value = dict?[subkey] 27 | dict = value as? Dictionary 28 | } 29 | return (value is NSNull) ? nil : (value as? Value) 30 | } 31 | 32 | /// Insert key/value pairs with input Dictionary 33 | mutating func insert(_ other: Dictionary) { 34 | for (key, value) in other { 35 | self[key] = value 36 | } 37 | } 38 | 39 | /// Pretty formatted description string 40 | var prettyDescription: String { 41 | return Pretty.describing(self) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/NSObject+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 5/19/16. 6 | // Copyright © 2016 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Convenient methods of NSObject 13 | */ 14 | public extension NSObject { 15 | var className: String { 16 | return NSStringFromClass(type(of: self)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Set+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dictionary+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 1/29/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Set { 12 | 13 | func compactMap(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] { 14 | return Array(self).compactMap(transform) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIButton+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 3/7/16. 6 | // Copyright © 2016 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private var controlHandlerKey: Int8 = 0 12 | public extension UIButton { 13 | /** 14 | Add self-contained action handler for button 15 | */ 16 | func addHandler(for controlEvents: UIControl.Event, handler: @escaping (UIButton) -> ()) { 17 | if let oldTarget = objc_getAssociatedObject(self, &controlHandlerKey) as? CocoaTarget { 18 | self.removeTarget(oldTarget, action: #selector(oldTarget.sendNext), for: controlEvents) 19 | } 20 | 21 | let target = CocoaTarget(handler) 22 | objc_setAssociatedObject(self, &controlHandlerKey, target, .OBJC_ASSOCIATION_RETAIN) 23 | self.addTarget(target, action: #selector(target.sendNext), for: controlEvents) 24 | } 25 | 26 | /** 27 | Set image with tintColor for desired controlState 28 | */ 29 | func setImage(_ imageName: String, for controlState: UIControl.State = .normal, tintColor: UIColor) { 30 | let image = UIImage(named: imageName)?.withRenderingMode(.alwaysTemplate) 31 | setImage(image, for: controlState) 32 | self.tintColor = tintColor 33 | } 34 | } 35 | 36 | /** 37 | A target that accepts action messages 38 | */ 39 | public final class CocoaTarget: NSObject { 40 | private let action: (T) -> () 41 | 42 | public init(_ action: @escaping (T) -> ()) { 43 | self.action = action 44 | } 45 | 46 | @objc 47 | public func sendNext(_ receiver: Any?) { 48 | guard let receiver = receiver as? T else { 49 | preconditionFailure("`receiver` isn't expected type.") 50 | } 51 | action(receiver) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIImage+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Extension.swift 3 | // 4 | // Created by Cheng Zhang on 1/12/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | import ImageIO 10 | 11 | public extension UIImage { 12 | @objc(cropToRect:) 13 | func crop(toRect rect: CGRect) -> UIImage { 14 | let croppedCGImage = self.cgImage!.cropping(to: rect)! 15 | let res = UIImage(cgImage: croppedCGImage) 16 | return res 17 | } 18 | 19 | @objc(cropToSize:) 20 | func crop(toSize size: CGSize) -> UIImage { 21 | var size = size 22 | let ratio = size.height / size.width 23 | if size.width < size.height { 24 | size.width = self.size.width * self.scale 25 | size.height = size.width * ratio 26 | } else { 27 | size.height = self.size.height * self.scale 28 | size.width = size.width * ratio 29 | } 30 | let rect = CGRect(origin: CGPoint(x: (self.size.width * self.scale - size.width) / 2, 31 | y: (self.size.height * self.scale - size.height) / 2), 32 | size: size) 33 | return crop(toRect: rect) 34 | } 35 | 36 | // height / width 37 | @objc(cropToRatio:) 38 | func crop(toRatio ratio: CGFloat) -> UIImage { 39 | var size: CGSize = self.size 40 | if ratio < 1 { 41 | size.width = self.size.width * self.scale 42 | size.height = size.width * ratio 43 | } else { 44 | size.height = self.size.height * self.scale 45 | size.width = size.height / ratio 46 | } 47 | let rect = CGRect(origin: CGPoint(x: (self.size.width * self.scale - size.width) / 2, 48 | y: (self.size.height * self.scale - size.height) / 2), 49 | size: size) 50 | return crop(toRect: rect) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIScreen+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScreen+Extension.swift 3 | // 4 | // Created by Cheng Zhang on 1/8/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | public extension UIScreen { 11 | static var currSize: CGSize { 12 | return main.bounds.size 13 | } 14 | 15 | static var currWidth: CGFloat { 16 | return currSize.width 17 | } 18 | 19 | static var currHeight: CGFloat { 20 | return currSize.height 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIView+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.swift 3 | // 4 | // Created by Cheng Zhang on 1/12/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | /// Constants for UIView extensions 11 | public enum UIViewConstants { 12 | public static let fadeInDuration: TimeInterval = 0.4 13 | public static let fadeInAnimationName = "com.tony.animation.fadein" 14 | } 15 | 16 | // MARK: - Corner/Border 17 | 18 | public extension UIView { 19 | 20 | func roundToCircle() { 21 | let width = self.bounds.size.width 22 | layer.cornerRadius = width / 2 23 | layer.masksToBounds = true 24 | } 25 | 26 | func roundCorner(_ cornerRadius: CGFloat = 2, 27 | boarderWidth: CGFloat = 0, 28 | boarderColor: UIColor = .clear, 29 | shadowColor: UIColor = .clear, 30 | shadowOffset: CGSize = .zero, 31 | shadowRadius: CGFloat = 2, 32 | shadowOpacity: Float = 1) { 33 | layer.masksToBounds = true 34 | layer.cornerRadius = cornerRadius 35 | layer.borderColor = boarderColor.cgColor 36 | layer.borderWidth = boarderWidth 37 | 38 | layer.shadowColor = shadowColor.cgColor 39 | layer.shadowOffset = shadowOffset 40 | layer.shadowRadius = shadowRadius 41 | } 42 | 43 | } 44 | 45 | // MARK: - Animations 46 | 47 | public extension UIView { 48 | func fadeIn(animationName: String = UIViewConstants.fadeInAnimationName, 49 | duration: TimeInterval = UIViewConstants.fadeInDuration) { 50 | let transition = CATransition() 51 | transition.duration = duration 52 | transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) 53 | transition.type = CATransitionType.fade 54 | layer.add(transition, forKey: animationName) 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Investigation/CriticalSectionLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CriticalSectionLock.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 11/3/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// Convenience mutex lock on top of NSLock 12 | open class CriticalSectionLock: NSLock { 13 | public func execute(_ execution: () -> T) -> T { 14 | lock() 15 | defer { 16 | unlock() 17 | } 18 | return execution() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/RegExHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RegExHelper.swift 3 | // 4 | // Created by Cheng Zhang on 2/18/20. 5 | // Copyright © 2020 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | public class RegExHelper { 11 | 12 | /// Extract variable with RegEx group match name. e.g. "

(?.*)

" pattern. 13 | /// - Note: Group name in `pattern` should be 'var'. 14 | public static func extractVariable(_ string: String, 15 | pattern: String, 16 | options: NSRegularExpression.Options = .caseInsensitive, 17 | groupName: String = "var") -> String? { 18 | guard let regex = (try? NSRegularExpression(pattern: pattern, options: options)).assertIfNil, 19 | let match = regex.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count)), 20 | let matchedRange = Range(match.range(withName: groupName), in: string) else { 21 | return nil 22 | } 23 | return String(string[matchedRange]) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Supported Files/CZUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // CZUtils.h 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 11/19/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CZUtils. 12 | FOUNDATION_EXPORT double CZUtilsVersionNumber; 13 | 14 | //! Project version string for CZUtils. 15 | FOUNDATION_EXPORT const unsigned char CZUtilsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Supported Files/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Swizzling.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Swizzling.swift 3 | // 4 | // Created by Cheng Zhang on 12/9/15. 5 | // Copyright © 2015 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Generic swizzling function - workable for subclasses of NSObject 11 | /// NSObject subclass maintains a DispatchTable which maps between method selector and actural IMP 12 | public func swizzling(_ aClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) { 13 | let originalMethod = class_getInstanceMethod(aClass, originalSelector) 14 | let swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector) 15 | let didAddMethod = class_addMethod(aClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!)) 16 | if didAddMethod { 17 | class_replaceMethod(aClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!)!) 18 | } else { 19 | method_exchangeImplementations(originalMethod!, swizzledMethod!) 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Utils/PrettyDescription.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrettyDescription.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 7/29/19. 6 | // Copyright © 2019 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class Pretty { 12 | 13 | /** 14 | Return Pretty formatted description for valid JSON object 15 | */ 16 | static func describing(_ object: Any) -> String { 17 | do { 18 | let data: Data = try JSONSerialization.data(withJSONObject: object, options: .prettyPrinted) 19 | return String(data: data, encoding: .utf8).assertIfNil ?? "" 20 | } catch { 21 | assertionFailure("Failed to retrieve pretty printed description. error - \(error.localizedDescription)") 22 | return "" 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Tests/CZUtilsTests/CZUtilsTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import CZUtils 3 | 4 | final class CZUtilsTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(CZUtils().text, "Hello, World!") 10 | } 11 | 12 | static var allTests = [ 13 | ("testExample", testExample), 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Tests/CZUtilsTests/TestArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestArray.swift 3 | // CZUtilsTests 4 | // 5 | // Created by Cheng Zhang on 7/26/18. 6 | // Copyright © 2018 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CZUtils 11 | 12 | class TestArray: XCTestCase { 13 | func testSafeSubscript() { 14 | let array = [Int](0..<10) 15 | 16 | // Elements within bounds 17 | [0, 3, 9].forEach { index in 18 | let element = array[safe: index] 19 | XCTAssert(element == index, "Unexpected element '\(String(describing: element))' at specified index '\(index)'. Expected value = '\(index)'") 20 | } 21 | 22 | // Elements out of bounds 23 | [-1, 10, 13, 20, 1000].forEach { index in 24 | let element = array[safe: index] 25 | XCTAssert(element == nil, "Unexpected element '\(String(describing: element))' at specified index '\(index)'. Expected value = nil") 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Tests/CZUtilsTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(CZUtilsTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/CZUtils/Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import CZUtilsTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += CZUtilsTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Experimental/MERGED_SelfSizingCell/ReactiveListViewKit/Supported Files/ReactiveListViewKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKit.h 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/2/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ReactiveListViewKit. 12 | FOUNDATION_EXPORT double ReactiveListViewKitVersionNumber; 13 | 14 | //! Project version string for ReactiveListViewKit. 15 | FOUNDATION_EXPORT const unsigned char ReactiveListViewKitVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Cheng Zhang 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ReactiveListViewKit' 3 | s.version = '1.2.4' 4 | s.summary = 'MVVM + FLUX Reactive Facade ViewKit, eliminates Massive View Controller in unidirectional action/state flow manner.' 5 | 6 | s.description = <<-DESC 7 | - MVVM + FLUX reactive facade ViewKit for feed based app development 8 | - Eliminates Massive View Controller in unidirectional Action/State flow manner 9 | DESC 10 | 11 | s.homepage = 'https://github.com/geekaurora/ReactiveListViewKit' 12 | #s.screenshots = '' 13 | s.license = { :type => 'MIT', :file => 'LICENSE' } 14 | s.author = { 'geekaurora' => 'showt2me@gmail.com' } 15 | s.source = { :git => 'https://github.com/geekaurora/ReactiveListViewKit.git', :tag => s.version.to_s } 16 | # s.social_media_url = 'https://twitter.com/' 17 | 18 | s.ios.deployment_target = '10.0' 19 | s.source_files = 'ReactiveListViewKit/ReactiveListViewKit/**/*' 20 | s.pod_target_xcconfig = { 'SWIFT_VERSION' => '3' } 21 | 22 | # s.resource_bundles = { 23 | # 'ReactiveListViewKit' => ['ReactiveListViewKit/Assets/*.png'] 24 | # } 25 | 26 | # s.public_header_files = 'Pod/Classes/**/*.h' 27 | 28 | s.frameworks = 'UIKit' 29 | s.dependency 'CZUtils' 30 | 31 | end 32 | 33 | 34 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/CZFeedDetailsModel.swift: -------------------------------------------------------------------------------- 1 | /// 2 | // CZFeedDetailsModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/5/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Base building block for `CZFeedDetailsFacadeView`, highly decouples View/ViewModel layers 12 | /// 13 | /// Composed of: 14 | /// - viewClass: CZFeedCellViewSizeCalculatable 15 | /// - voewModel: CZFeedViewModelable 16 | /// 17 | public typealias CZFeedDetailsModel = CZFeedModel 18 | 19 | //public class CZFeedDetailsModel: NSObject, CZFeedModelable { 20 | // public let viewClass: CZFeedCellViewable.Type 21 | // public let viewModel: CZFeedViewModelable 22 | // 23 | // public required init(viewClass: CZFeedCellViewable.Type, 24 | // viewModel: CZFeedViewModelable) { 25 | // self.viewClass = viewClass 26 | // self.viewModel = viewModel 27 | // super.init() 28 | // } 29 | // 30 | // public func isEqual(toDiffableObj object: AnyObject) -> Bool { 31 | // guard let object = object as? CZFeedDetailsModel else {return false} 32 | // return viewClass == object.viewClass && 33 | // viewModel.isEqual(toDiffableObj: object.viewModel) 34 | // } 35 | // 36 | // public func copy(with zone: NSZone? = nil) -> Any { 37 | // let viewClassCopy = viewClass 38 | // let viewModelCopy = viewModel.copy(with: zone) as! CZFeedViewModelable 39 | // return type(of: self).init( 40 | // viewClass: viewClassCopy, 41 | // viewModel: viewModelCopy) 42 | // } 43 | //} 44 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/CZFeedDetailsViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedDetailsViewModel.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/3/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | ViewModel/State class for `CZFeedDetailsFacadeView` 13 | */ 14 | open class CZFeedDetailsViewModel: NSObject, NSCopying { 15 | 16 | private var _feedModels: [CZFeedModelable] 17 | required public init(feedModels: [CZFeedModelable]? = nil) { 18 | _feedModels = feedModels ?? [] 19 | } 20 | 21 | public func batchUpdate(with feedModels: [CZFeedModelable]) { 22 | _feedModels.removeAll() 23 | _feedModels.append(contentsOf: feedModels) 24 | } 25 | 26 | // MARK: - NSCopying 27 | public func copy(with zone: NSZone? = nil) -> Any { 28 | let feedModels = _feedModels.compactMap{ $0.copy(with: nil) as? CZFeedModelable} 29 | let viewModel = type(of: self).init(feedModels: feedModels) 30 | return viewModel 31 | } 32 | 33 | public var feedModels: [CZFeedDetailsModel] { 34 | return (_feedModels as? [CZFeedDetailsModel]) ?? [] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/CZFeedListViewAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedViewAction.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/10/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | CZActionProtocol handler closure 13 | */ 14 | public typealias OnAction = (_ action: CZActionProtocol) -> Void 15 | 16 | /** 17 | General ViewAction 18 | */ 19 | public typealias CZViewAction = CZActionProtocol 20 | 21 | public struct BaseState: StateProtocol { 22 | public func reduce(action: CZActionProtocol) -> Self { 23 | return self 24 | } 25 | } 26 | 27 | /** 28 | ViewAction for container feedListView 29 | */ 30 | public enum CZFeedListViewAction: CZViewAction { 31 | case selectedCell(IndexPath, CZFeedModel) 32 | case loadMore 33 | case pullToRefresh(isFirst: Bool) 34 | case prefetch([IndexPath]) 35 | case cancelPrefetching([IndexPath]) 36 | case visibleIndexPathsChanged(newValue: [IndexPath])// (oldIndexPaths, newIndexPaths) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/CZFeedViewModelable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedViewModelable.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/5/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | 11 | /** 12 | Fundamental protocol for CellView of `CZFeedListFacadeView`/`CZFeedDetailsFacadeView` 13 | */ 14 | public protocol CZFeedViewModelable: class, NSObjectProtocol, CZListDiffable, NSCopying { 15 | /// `diffId` is used for diff algorithm of batch update, verify whether two involved viewModels equal 16 | var diffId: String {get} 17 | 18 | var viewHeight: CGFloat {get} 19 | 20 | func isEqual(toDiffableObj object: AnyObject) -> Bool 21 | 22 | func copy(with zone: NSZone?) -> Any 23 | } 24 | 25 | public extension CZFeedViewModelable { 26 | var diffId: String { 27 | currentClassName 28 | } 29 | 30 | var viewHeight: CGFloat { 31 | -1 32 | } 33 | } 34 | 35 | public extension CZFeedViewModelable { 36 | var currentClassName: String { 37 | return NSStringFromClass(type(of: self)) 38 | } 39 | } 40 | 41 | /// Fundamental protocol for ViewModel involved in ListView, verify whether two viewModels equal 42 | public protocol CZListDiffable { 43 | /// Workaround of `Equatable`, because `Equatable` uses associatedType `Self`, which makes `Equatable` can only be used as generic constraint 44 | func isEqual(toDiffableObj object: AnyObject) -> Bool 45 | } 46 | 47 | /// Fundamental protocol composition of reactive listDiffable model 48 | /// - note: The protocol only requires conformance of `Codable` and `NSCopying`, other protocols are conformed by categories automatically. 49 | public typealias ReactiveListDiffable = Codable & NSCopying & CustomStringConvertible & CZListDiffable 50 | 51 | public typealias CZListDiffableObject = CZListDiffable & AnyObject 52 | 53 | // MARK: CZListDiffable 54 | public extension Encodable where Self: Decodable { 55 | func isEqual(toDiffableObj object: AnyObject) -> Bool { 56 | return isEqual(toCodable: object) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/CZReactiveFeedDetailsFacadeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZReactiveFeedDetailsFacadeView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/11/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private var kViewModelObserverContext: Int = 0 12 | 13 | /** 14 | Reactive view class of `FeedDetailsFacadeView`, supports FLUX pattern 15 | */ 16 | open class CZReactiveFeedDetailsFacadeView: CZFeedDetailsFacadeView { 17 | var store: Store? 18 | public override var onAction: OnAction? { 19 | get { 20 | guard let store = store else { return super.onAction } 21 | return {action in store.dispatch(action: action) } 22 | } 23 | set { super.onAction = newValue } 24 | } 25 | 26 | public init(containerViewController: UIViewController? = nil, 27 | store: Store? = nil, 28 | onAction: OnAction? = nil) { 29 | super.init(containerViewController: containerViewController, onAction: onAction) 30 | self.store = store 31 | } 32 | public required init?(coder: NSCoder) { 33 | super.init(coder: coder) 34 | } 35 | 36 | public override func setup() { 37 | super.setup() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/CZReactiveFeedListFacadeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZReactiveFeedListFacadeView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/11/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Reactive view class of `FeedListFacadeView`, supports FLUX pattern 13 | */ 14 | open class CZReactiveFeedListFacadeView: CZFeedListFacadeView { 15 | 16 | let store: Store 17 | 18 | public init(store: Store, 19 | sectionModelsTransformer: @escaping SectionModelsTransformer, 20 | parentViewController: UIViewController? = nil, 21 | loadMoreThreshold: Int = CZFeedListFacadeView.kLoadMoreThreshold, 22 | minimumLineSpacing: CGFloat = ReactiveListViewKit.minimumLineSpacing) { 23 | self.store = store 24 | let onAction = { (action: CZActionProtocol) in 25 | store.dispatch(action: action) 26 | } 27 | super.init(sectionModelsTransformer: sectionModelsTransformer, 28 | onAction: onAction, 29 | parentViewController: parentViewController, 30 | loadMoreThreshold: loadMoreThreshold) 31 | } 32 | 33 | public required init?(coder: NSCoder) { fatalError("Must call designated initializer.") } 34 | } 35 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/Store/StoreObserverProtocol.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// The protocol that defines the observer to observe the store state changes. 4 | public protocol StoreObserverProtocol { 5 | associatedtype StateType 6 | 7 | /// Gets notified with the current `state` and `previousState` when the store state changes. 8 | func storeDidUpdate(state: StateType, 9 | previousState: StateType?) 10 | 11 | /// Gets notified with a dispatched action. 12 | func didReceiveStoreAction(_ action: CZActionProtocol) 13 | } 14 | 15 | public extension StoreObserverProtocol { 16 | func didReceiveStoreAction(_ action: CZActionProtocol) { 17 | // No-op. 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/TemplateViews/CZDividerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZDividerView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/16/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Convenience divider view class 13 | */ 14 | public final class CZDividerView: UIView { 15 | private let size: CGFloat 16 | private let bgColor: UIColor 17 | 18 | public init(size: CGFloat = 1, 19 | backgroudColor: UIColor = ReactiveListViewKit.GreyDividerColor) { 20 | self.size = size 21 | self.bgColor = backgroudColor 22 | super.init(frame: .zero) 23 | setup() 24 | } 25 | 26 | public required init?(coder: NSCoder) { 27 | fatalError("Must call designated initializer.") 28 | } 29 | } 30 | 31 | private extension CZDividerView { 32 | func setup() { 33 | translatesAutoresizingMaskIntoConstraints = false 34 | backgroundColor = self.bgColor 35 | let sizeContrait = heightAnchor.constraint(equalToConstant: size) 36 | sizeContrait.priority = UILayoutPriority(rawValue: 749) 37 | sizeContrait.isActive = true 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/TemplateViews/CZFeedListSupplementaryView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFeedListSupplementaryView.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 2/7/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Convenience class of SectionHeaderView/SectionFooterView 13 | */ 14 | open class CZFeedListSupplementaryView: UICollectionReusableView { 15 | open override var reuseIdentifier: String? { 16 | return type(of: self).reuseId 17 | } 18 | private var model: CZFeedModel? 19 | private var contentView: CZFeedCellViewSizeCalculatable? 20 | public static var reuseId: String { 21 | return NSStringFromClass(object_getClass(self)!) 22 | } 23 | open func config(with model: CZFeedModel, 24 | onAction: OnAction?) { 25 | defer { 26 | self.model = model 27 | contentView?.config(with: model.viewModel) 28 | } 29 | // Reset contentView if contentViewClass differs from the current one 30 | if let contentView = contentView, 31 | let currModel = self.model, 32 | currModel.viewClass != model.viewClass { 33 | (contentView as? UIView)?.removeFromSuperview() 34 | self.contentView = nil 35 | } 36 | if contentView == nil { 37 | self.contentView = model.viewClass.init(viewModel: model.viewModel, onAction: onAction) 38 | guard let contentView = self.contentView as? UIView else { 39 | assertionFailure("\(model.viewClass) should be subClass of UIView!") 40 | return 41 | } 42 | contentView.translatesAutoresizingMaskIntoConstraints = false 43 | contentView.isUserInteractionEnabled = false 44 | addSubview(contentView) 45 | contentView.overlayOnSuperview() 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/Utils/Array+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array+Extension.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/15/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension Array where Element: CZListDiffableObject { 12 | /** 13 | Check whether elements in two arrays equal 14 | */ 15 | public func isEqual(toDiffableObj object: Any) -> Bool { 16 | guard let object = object as? [Element], 17 | count == object.count else { 18 | return false 19 | } 20 | return (0.. Bool { 14 | switch(obj1, obj2) { 15 | case let (obj1 as CZListDiffableObject, obj2 as CZListDiffableObject): 16 | return obj1.isEqual(toDiffableObj: obj2) 17 | default: 18 | return (obj1 == nil && obj2 == nil) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/Utils/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKitConstants.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/2/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Constants of ReactiveListViewKit 13 | */ 14 | public enum ReactiveListViewKit { 15 | public static var isDebugMode = true 16 | public static var isIncrementalUpdateEnabled = false 17 | public static var useGCD = false 18 | 19 | // MARK: - Self Sizing Cells 20 | 21 | public static var enableSelfSizingCellsForVerticalOrientation = true 22 | public static var enableSelfSizingCellsForHorizontalOrientation = true 23 | 24 | public static let ClearBGColor = UIColor.clear 25 | public static let GreyBGColor = UIColor(white: 240.0 / 255.0, alpha: 1.0) 26 | public static let GreyDividerColor = UIColor(white: 217.0 / 255.0, alpha: 1.0) 27 | public static let minimumLineSpacing: CGFloat = 10 28 | public static let minimumInteritemSpacing: CGFloat = 10 29 | public static let sectionInset = UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 0) 30 | 31 | public enum FeedListSupplementaryTextView { 32 | public static let inset = UIEdgeInsets(top: 8, left: 10, bottom: 3, right: 10) 33 | public static let titleFont = UIFont.boldSystemFont(ofSize: 14) 34 | public static let titleColor = UIColor(white: 0.1, alpha: 1) 35 | public static let actionButtonColor = UIColor(red: 62.0 / 255.0, green: 153 / 255.0, blue: 237 / 255.0, alpha: 1) 36 | } 37 | 38 | public static let horizontalSectionAdapterViewBGColor: UIColor = .clear 39 | 40 | public static let feedListSupplementaryLineHeaderViewInset = UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0) 41 | public static let feedListSupplementaryLineFooterViewInset = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) 42 | } 43 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKit/Utils/ReactiveListViewKitHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKitHelper.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 11/6/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import CZUtils 10 | 11 | public func dbgPrint(_ item: CustomStringConvertible) { 12 | guard ReactiveListViewKit.isDebugMode else { return } 13 | _dbgPrint(item) 14 | } 15 | 16 | public func PrettyString(_ object: Any) -> String { 17 | guard let object = object as? CustomStringConvertible else { 18 | return "" 19 | } 20 | if let indexSet = object as? IndexSet { 21 | return indexSet.reduce("[") { (prevResult, index) -> String in 22 | prevResult + String(index) + ", " 23 | } + "]" 24 | } else { 25 | return object.description 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKitTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ReactiveListViewKit/ReactiveListViewKitTests/Utils/CZListDiff+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZListDiff.swift 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/5/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import ReactiveListViewKit 10 | 11 | extension CZListDiff { 12 | /** 13 | Return empty SectionIndexDiffResult 14 | */ 15 | public static var emptyDiffSectionModelIndexes: SectionIndexDiffResult { 16 | let sectionsDiff: [SectionDiffResultKey: Any] = [:] 17 | let rowsDiff: [RowDiffResultKey: [Any]] = [:] 18 | return (sectionsDiff, rowsDiff) 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Cheng Zhang 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.1 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( 7 | name: "CZUtils", 8 | platforms: [ 9 | .iOS(.v11), 10 | ], 11 | products: [ 12 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 13 | .library( 14 | name: "CZUtils", 15 | targets: ["CZUtils"]), 16 | ], 17 | dependencies: [ 18 | // Dependencies declare other packages that this package depends on. 19 | // .package(url: /* package url */, from: "1.0.0"), 20 | ], 21 | targets: [ 22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 23 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 24 | .target( 25 | name: "CZUtils", 26 | dependencies: []), 27 | .testTarget( 28 | name: "CZUtilsTests", 29 | dependencies: ["CZUtils"]), 30 | ] 31 | ) 32 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/README.md: -------------------------------------------------------------------------------- 1 | # CZUtils 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/CZUtils.svg?style=flat)](http://cocoapods.org/pods/CZUtils) 4 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 5 | ![Swift Version](https://img.shields.io/badge/swift-3.2-orange.svg) 6 | [![License](https://img.shields.io/cocoapods/l/CZUtils.svg?style=flat)](http://cocoapods.org/pods/CZUtils) 7 | [![Platform](https://img.shields.io/cocoapods/p/CZUtils.svg?style=flat)](http://cocoapods.org/pods/CZUtils) 8 | 9 | ### Powerful toolset for Utils layer 10 | 11 | * CZMutexLock on top of GCD 12 | * NSNullGuard 13 | * MainQueueScheduler 14 | * SwizzlingHelper 15 | * ThreadSafeDictionary 16 | * NibLoadable for UIView/Cell 17 | 18 | 19 | ## Installation 20 | 21 | CZUtils is available through [CocoaPods](http://cocoapods.org). To install 22 | it, simply add the following line to your Podfile: 23 | 24 | ```ruby 25 | pod 'CZUtils' 26 | ``` 27 | 28 | And run `pod install` in your work folder. -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZAlertManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZAlertManager.swift 3 | // 4 | // Created by Cheng Zhang on 1/15/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | /// Convenient helper class for AlertViewController displaying 11 | open class CZAlertManager: NSObject { 12 | 13 | open class func showAlert(title: String? = nil, 14 | message: String, 15 | confirmText: String = "Ok", 16 | confirmHandler: ((UIAlertAction) -> Void)? = nil, 17 | cancelText: String? = nil, 18 | cancelHandler: ((UIAlertAction) -> Void)? = nil, 19 | on viewController: UIViewController? = nil, 20 | completion: (() -> Void)? = nil) { 21 | let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) 22 | let action1 = UIAlertAction(title: confirmText, style: .default, handler: confirmHandler) 23 | alertController.addAction(action1) 24 | if let cancelText = cancelText { 25 | let action2 = UIAlertAction(title: cancelText, style: .cancel, handler: cancelHandler) 26 | alertController.addAction(action2) 27 | } 28 | 29 | guard let presentingViewController = viewController ?? UIApplication.shared.keyWindow?.rootViewController else { 30 | assertionFailure("Couldn't find valid presenting ViewController.") 31 | return 32 | } 33 | presentingViewController.topMost.present(alertController, animated: true, completion: completion) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZDictionary.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZDictionary.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 2018/7/6. 6 | // Copyright © 2019 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public typealias CZDictionary = [AnyHashable : Any] 12 | 13 | public protocol CZDictionaryable { 14 | init(dictionary: CZDictionary) 15 | } 16 | 17 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZError.swift 3 | // 4 | // Created by Cheng Zhang on 1/10/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Convenience Error class 11 | open class CZError: NSError { 12 | public init(domain: String, code: Int = 99, description: String? = nil) { 13 | var userInfo: [String: Any]? = nil 14 | if let description = description { 15 | userInfo = [NSLocalizedDescriptionKey: description] 16 | } 17 | super.init(domain: domain, code: code, userInfo: userInfo) 18 | } 19 | 20 | required public init?(coder aDecoder: NSCoder) { 21 | super.init(coder: aDecoder) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZFileHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZFileHelper.swift 3 | // 4 | // Created by Cheng Zhang on 1/13/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Helper class for file related methods 11 | @objc open class CZFileHelper: NSObject { 12 | public static func getFileSize(_ filePath: String?) -> Int? { 13 | guard let filePath = filePath else {return nil} 14 | do { 15 | let attrs = try FileManager.default.attributesOfItem(atPath: filePath) 16 | let size = attrs[.size] as? Int 17 | return size 18 | } catch { 19 | dbgPrint("Failed to get file size of \(filePath). Error - \(error.localizedDescription)") 20 | } 21 | return nil 22 | } 23 | 24 | @objc public static var documentDirectory: String { 25 | return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZMainQueueScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZMainQueueScheduler.swift 3 | // 4 | // Created by Cheng Zhang on 1/4/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Convenience class for scheduling sync/async execution on main queue 11 | open class CZMainQueueScheduler: NSObject { 12 | 13 | /// Synchronous execution: inferring function returnType with `execution` closure returnType 14 | public class func sync(_ execution: @escaping () -> T) -> T { 15 | if Thread.isMainThread { 16 | return execution() 17 | } else { 18 | return DispatchQueue.main.sync { 19 | execution() 20 | } 21 | } 22 | } 23 | 24 | /// Asynchronous execution 25 | public class func async(execution: @escaping () -> Void ) { 26 | DispatchQueue.main.async { 27 | execution() 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZProMutexLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZProMutexLock.swift 3 | // 4 | // Created by Cheng Zhang on 2/3/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Mutex lock on top of `pthread_mutex_lock`/`pthread_mutex_unlock` 11 | open class CZProMutexLock: NSObject { 12 | private var mutex = pthread_mutex_t() 13 | 14 | public override init() { 15 | var attr = pthread_mutexattr_t() 16 | guard pthread_mutexattr_init(&attr) == 0 else { 17 | preconditionFailure() 18 | } 19 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL) 20 | guard pthread_mutex_init(&mutex, &attr) == 0 else { 21 | preconditionFailure() 22 | } 23 | } 24 | 25 | deinit { 26 | pthread_mutex_destroy(&mutex) 27 | } 28 | 29 | public func withLock(_ closure: () -> T) -> T { 30 | defer { 31 | pthread_mutex_unlock(&mutex) 32 | } 33 | pthread_mutex_lock(&mutex) 34 | return closure() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZTheme.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CZTheme.swift 3 | // 4 | // Created by Cheng Zhang on 4/18/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | /// Common theme settings for projects 11 | public struct CZTheme { 12 | public static let greyDividerColor: CGFloat = 217.0 / 255.0 13 | } 14 | 15 | public extension UIColor { 16 | static let candyGreen = UIColor(red: 67.0/255.0, green: 205.0/255.0, blue: 135.0/255.0, alpha: 1.0) 17 | static let facebookBlue = UIColor(red: 68.0/255.0, green: 105.0/255.0, blue: 176.0/255.0, alpha: 1.0) 18 | static let dividerGrey = UIColor(white: CZTheme.greyDividerColor, alpha: 1) 19 | static let searchBarColor = UIColor(white: 217.0 / 255.0, alpha: 1) 20 | static let searchBarTextGrey = UIColor(white: 127.0 / 255.0, alpha: 1) 21 | static let tabBarTintColor = UIColor(white: 250.0 / 255.0, alpha: 1) 22 | static let tabBarItemTintColor = UIColor(white: 38.0 / 255.0, alpha: 1) 23 | } 24 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/CZUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 2/19/18. 6 | // Copyright © 2018 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class CZUtils { 12 | public static func dbgPrint(_ item: CustomStringConvertible) { 13 | #if DEBUG 14 | print(item) 15 | #endif 16 | } 17 | } 18 | 19 | public func dbgPrint(_ item: CustomStringConvertible) { 20 | CZUtils.dbgPrint(item) 21 | } 22 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Error+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Error+.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 8/10/19. 6 | // Copyright © 2019 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Error { 12 | var retrievedCode: Int { 13 | return (self as NSError).code 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Array+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array+Extensoin.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 1/26/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Array { 12 | /** 13 | Returns element at specified `safe` index if exists, otherwise nil 14 | */ 15 | subscript (safe index: Index) -> Element? { 16 | return indices.contains(index) ? self[index] : nil 17 | } 18 | 19 | /** 20 | Pretty formatted description string 21 | */ 22 | var prettyDescription: String { 23 | return Pretty.describing(self) 24 | } 25 | } 26 | 27 | public extension Array where Element: NSCopying { 28 | func copy(with zone: NSZone? = nil) -> Any { 29 | return compactMap{ $0.copy() } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Character+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Character+.swift 3 | // 4 | // Created by Cheng Zhang on 12/30/18. 5 | // Copyright © 2018 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Character { 11 | 12 | public var ascii: Int { 13 | return Int(String(self).unicodeScalars.first!.value) 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Date+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 5/19/16. 6 | // Copyright © 2016 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Date { 12 | var simpleString: String { 13 | return string(withFormat: "yyyy-MM-dd hh:mm") 14 | } 15 | 16 | var complexString: String { 17 | return string(withFormat: "EEE, dd MMM yyyy hh:mm:ss +zzzz") 18 | } 19 | 20 | func string(withFormat formatterStr: String) -> String { 21 | let dateFormatter = DateFormatter() 22 | dateFormatter.dateFormat = formatterStr 23 | return dateFormatter.string(from: self) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Dictionary+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dictionary+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 1/29/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Dictionary { 12 | /// Retrieve value from `dotedKey`, compatible with multi-dot in keyPath. e.g. "user.profile.fullName" 13 | func value(forDotedKey dotedKey: String) -> Value? { 14 | return value(forSegmentedKey: dotedKey) 15 | } 16 | 17 | /// Retrieve value from `segmentedKey`, compatible with multi-segments separated by `splitter`. e.g. "user.profile.fullName", "user/profile/fullName" 18 | func value(forSegmentedKey segmentedKey: String, splitter: String = ".") -> Value? { 19 | var value: Any? = nil 20 | var dict: Dictionary? = self 21 | 22 | for subkey in segmentedKey.components(separatedBy: splitter) { 23 | guard dict != nil, let subkey = subkey as? Key else { 24 | return nil 25 | } 26 | value = dict?[subkey] 27 | dict = value as? Dictionary 28 | } 29 | return (value is NSNull) ? nil : (value as? Value) 30 | } 31 | 32 | /// Insert key/value pairs with input Dictionary 33 | mutating func insert(_ other: Dictionary) { 34 | for (key, value) in other { 35 | self[key] = value 36 | } 37 | } 38 | 39 | /// Pretty formatted description string 40 | var prettyDescription: String { 41 | return Pretty.describing(self) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/NSObject+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 5/19/16. 6 | // Copyright © 2016 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Convenient methods of NSObject 13 | */ 14 | public extension NSObject { 15 | var className: String { 16 | return NSStringFromClass(type(of: self)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Optional+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Optional+.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 9/22/18. 6 | // Copyright © 2018 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Convenient methods of Swift Optional 13 | */ 14 | extension Optional { 15 | /** 16 | If this optional has a value, unwrap the optional and call the given function passing the unwrapped value 17 | */ 18 | public func ifPresent(_ function: ((Wrapped) -> Void)? = nil) { 19 | guard let function = function else { 20 | return 21 | } 22 | 23 | switch (self) { 24 | case .some(let value): 25 | function(value) 26 | default: 27 | break 28 | } 29 | } 30 | 31 | /** 32 | If this optional has a value, call the given function passing this optional 33 | */ 34 | public func ifPresent(_ function: ((Wrapped?) -> Void)? = nil) { 35 | guard let function = function else { 36 | return 37 | } 38 | 39 | switch (self) { 40 | case .some(let value): 41 | function(value) 42 | default: 43 | break 44 | } 45 | } 46 | 47 | /** 48 | Raises an assert if the value is nil. 49 | */ 50 | public var assertIfNil: Optional { 51 | assert(self != nil, "Expected a non-nil \(Wrapped.self)") 52 | return self 53 | } 54 | 55 | /** 56 | Returns a string-interpolated value for item contained in this optional, or the default value if the optional is nil. 57 | This can be used instead of String(describing:) if you don't want the result to contain "Optional()" 58 | 59 | Note: If this is a doubly-nested optional (e.g. Int??), you could still get the "Optional()" string as this only unwraps one level. 60 | */ 61 | public func interpolatedString(withDefaultValue defaultValue: String = "nil") -> String { 62 | return self.map { wrapped in "\(wrapped)" } ?? defaultValue 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/Set+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dictionary+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 1/29/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Set { 12 | 13 | func compactMap(_ transform: (Element) -> ElementOfResult?) -> [ElementOfResult] { 14 | return Array(self).compactMap(transform) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIButton+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Extension.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 3/7/16. 6 | // Copyright © 2016 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private var controlHandlerKey: Int8 = 0 12 | public extension UIButton { 13 | /** 14 | Add self-contained action handler for button 15 | */ 16 | func addHandler(for controlEvents: UIControl.Event, handler: @escaping (UIButton) -> ()) { 17 | if let oldTarget = objc_getAssociatedObject(self, &controlHandlerKey) as? CocoaTarget { 18 | self.removeTarget(oldTarget, action: #selector(oldTarget.sendNext), for: controlEvents) 19 | } 20 | 21 | let target = CocoaTarget(handler) 22 | objc_setAssociatedObject(self, &controlHandlerKey, target, .OBJC_ASSOCIATION_RETAIN) 23 | self.addTarget(target, action: #selector(target.sendNext), for: controlEvents) 24 | } 25 | 26 | /** 27 | Set image with tintColor for desired controlState 28 | */ 29 | func setImage(_ imageName: String, for controlState: UIControl.State = .normal, tintColor: UIColor) { 30 | let image = UIImage(named: imageName)?.withRenderingMode(.alwaysTemplate) 31 | setImage(image, for: controlState) 32 | self.tintColor = tintColor 33 | } 34 | } 35 | 36 | /** 37 | A target that accepts action messages 38 | */ 39 | public final class CocoaTarget: NSObject { 40 | private let action: (T) -> () 41 | 42 | public init(_ action: @escaping (T) -> ()) { 43 | self.action = action 44 | } 45 | 46 | @objc 47 | public func sendNext(_ receiver: Any?) { 48 | guard let receiver = receiver as? T else { 49 | preconditionFailure("`receiver` isn't expected type.") 50 | } 51 | action(receiver) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIImage+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Extension.swift 3 | // 4 | // Created by Cheng Zhang on 1/12/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | import ImageIO 10 | 11 | public extension UIImage { 12 | @objc(cropToRect:) 13 | func crop(toRect rect: CGRect) -> UIImage { 14 | let croppedCGImage = self.cgImage!.cropping(to: rect)! 15 | let res = UIImage(cgImage: croppedCGImage) 16 | return res 17 | } 18 | 19 | @objc(cropToSize:) 20 | func crop(toSize size: CGSize) -> UIImage { 21 | var size = size 22 | let ratio = size.height / size.width 23 | if size.width < size.height { 24 | size.width = self.size.width * self.scale 25 | size.height = size.width * ratio 26 | } else { 27 | size.height = self.size.height * self.scale 28 | size.width = size.width * ratio 29 | } 30 | let rect = CGRect(origin: CGPoint(x: (self.size.width * self.scale - size.width) / 2, 31 | y: (self.size.height * self.scale - size.height) / 2), 32 | size: size) 33 | return crop(toRect: rect) 34 | } 35 | 36 | // height / width 37 | @objc(cropToRatio:) 38 | func crop(toRatio ratio: CGFloat) -> UIImage { 39 | var size: CGSize = self.size 40 | if ratio < 1 { 41 | size.width = self.size.width * self.scale 42 | size.height = size.width * ratio 43 | } else { 44 | size.height = self.size.height * self.scale 45 | size.width = size.height / ratio 46 | } 47 | let rect = CGRect(origin: CGPoint(x: (self.size.width * self.scale - size.width) / 2, 48 | y: (self.size.height * self.scale - size.height) / 2), 49 | size: size) 50 | return crop(toRect: rect) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIScreen+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScreen+Extension.swift 3 | // 4 | // Created by Cheng Zhang on 1/8/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | public extension UIScreen { 11 | static var currSize: CGSize { 12 | return main.bounds.size 13 | } 14 | 15 | static var currWidth: CGFloat { 16 | return currSize.width 17 | } 18 | 19 | static var currHeight: CGFloat { 20 | return currSize.height 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Extensions/UIView+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.swift 3 | // 4 | // Created by Cheng Zhang on 1/12/16. 5 | // Copyright © 2016 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | /// Constants for UIView extensions 11 | public enum UIViewConstants { 12 | public static let fadeInDuration: TimeInterval = 0.4 13 | public static let fadeInAnimationName = "com.tony.animation.fadein" 14 | } 15 | 16 | // MARK: - Corner/Border 17 | 18 | public extension UIView { 19 | 20 | func roundToCircle() { 21 | let width = self.bounds.size.width 22 | layer.cornerRadius = width / 2 23 | layer.masksToBounds = true 24 | } 25 | 26 | func roundCorner(_ cornerRadius: CGFloat = 2, 27 | boarderWidth: CGFloat = 0, 28 | boarderColor: UIColor = .clear, 29 | shadowColor: UIColor = .clear, 30 | shadowOffset: CGSize = .zero, 31 | shadowRadius: CGFloat = 2, 32 | shadowOpacity: Float = 1) { 33 | layer.masksToBounds = true 34 | layer.cornerRadius = cornerRadius 35 | layer.borderColor = boarderColor.cgColor 36 | layer.borderWidth = boarderWidth 37 | 38 | layer.shadowColor = shadowColor.cgColor 39 | layer.shadowOffset = shadowOffset 40 | layer.shadowRadius = shadowRadius 41 | } 42 | 43 | } 44 | 45 | // MARK: - Animations 46 | 47 | public extension UIView { 48 | func fadeIn(animationName: String = UIViewConstants.fadeInAnimationName, 49 | duration: TimeInterval = UIViewConstants.fadeInDuration) { 50 | let transition = CATransition() 51 | transition.duration = duration 52 | transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) 53 | transition.type = CATransitionType.fade 54 | layer.add(transition, forKey: animationName) 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Investigation/CriticalSectionLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CriticalSectionLock.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 11/3/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// Convenience mutex lock on top of NSLock 12 | open class CriticalSectionLock: NSLock { 13 | public func execute(_ execution: () -> T) -> T { 14 | lock() 15 | defer { 16 | unlock() 17 | } 18 | return execution() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/RegExHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RegExHelper.swift 3 | // 4 | // Created by Cheng Zhang on 2/18/20. 5 | // Copyright © 2020 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | public class RegExHelper { 11 | 12 | /// Extract variable with RegEx group match name. e.g. "

(?.*)

" pattern. 13 | /// - Note: Group name in `pattern` should be 'var'. 14 | public static func extractVariable(_ string: String, 15 | pattern: String, 16 | options: NSRegularExpression.Options = .caseInsensitive, 17 | groupName: String = "var") -> String? { 18 | guard let regex = (try? NSRegularExpression(pattern: pattern, options: options)).assertIfNil, 19 | let match = regex.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count)), 20 | let matchedRange = Range(match.range(withName: groupName), in: string) else { 21 | return nil 22 | } 23 | return String(string[matchedRange]) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Supported Files/CZUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // CZUtils.h 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 11/19/15. 6 | // Copyright © 2015 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CZUtils. 12 | FOUNDATION_EXPORT double CZUtilsVersionNumber; 13 | 14 | //! Project version string for CZUtils. 15 | FOUNDATION_EXPORT const unsigned char CZUtilsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Supported Files/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Swizzling.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Swizzling.swift 3 | // 4 | // Created by Cheng Zhang on 12/9/15. 5 | // Copyright © 2015 Cheng Zhang. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Generic swizzling function - workable for subclasses of NSObject 11 | /// NSObject subclass maintains a DispatchTable which maps between method selector and actural IMP 12 | public func swizzling(_ aClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) { 13 | let originalMethod = class_getInstanceMethod(aClass, originalSelector) 14 | let swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector) 15 | let didAddMethod = class_addMethod(aClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!)) 16 | if didAddMethod { 17 | class_replaceMethod(aClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!)!) 18 | } else { 19 | method_exchangeImplementations(originalMethod!, swizzledMethod!) 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Sources/CZUtils/Utils/PrettyDescription.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrettyDescription.swift 3 | // CZUtils 4 | // 5 | // Created by Cheng Zhang on 7/29/19. 6 | // Copyright © 2019 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class Pretty { 12 | 13 | /** 14 | Return Pretty formatted description for valid JSON object 15 | */ 16 | static func describing(_ object: Any) -> String { 17 | do { 18 | let data: Data = try JSONSerialization.data(withJSONObject: object, options: .prettyPrinted) 19 | return String(data: data, encoding: .utf8).assertIfNil ?? "" 20 | } catch { 21 | assertionFailure("Failed to retrieve pretty printed description. error - \(error.localizedDescription)") 22 | return "" 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Tests/CZUtilsTests/CZUtilsTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import CZUtils 3 | 4 | final class CZUtilsTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(CZUtils().text, "Hello, World!") 10 | } 11 | 12 | static var allTests = [ 13 | ("testExample", testExample), 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Tests/CZUtilsTests/TestArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestArray.swift 3 | // CZUtilsTests 4 | // 5 | // Created by Cheng Zhang on 7/26/18. 6 | // Copyright © 2018 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CZUtils 11 | 12 | class TestArray: XCTestCase { 13 | func testSafeSubscript() { 14 | let array = [Int](0..<10) 15 | 16 | // Elements within bounds 17 | [0, 3, 9].forEach { index in 18 | let element = array[safe: index] 19 | XCTAssert(element == index, "Unexpected element '\(String(describing: element))' at specified index '\(index)'. Expected value = '\(index)'") 20 | } 21 | 22 | // Elements out of bounds 23 | [-1, 10, 13, 20, 1000].forEach { index in 24 | let element = array[safe: index] 25 | XCTAssert(element == nil, "Unexpected element '\(String(describing: element))' at specified index '\(index)'. Expected value = nil") 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Tests/CZUtilsTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(CZUtilsTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/CZUtils/Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import CZUtilsTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += CZUtilsTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ReactiveListViewKit/Supported Files/ReactiveListViewKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveListViewKit.h 3 | // ReactiveListViewKit 4 | // 5 | // Created by Cheng Zhang on 1/2/17. 6 | // Copyright © 2017 Cheng Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ReactiveListViewKit. 12 | FOUNDATION_EXPORT double ReactiveListViewKitVersionNumber; 13 | 14 | //! Project version string for ReactiveListViewKit. 15 | FOUNDATION_EXPORT const unsigned char ReactiveListViewKitVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | --------------------------------------------------------------------------------