├── .circleci
└── config.yml
├── .gitignore
├── .swiftlint.yml
├── CHANGELOG.md
├── Example
├── .swiftlint.yml
├── Default-568h@2x.png
├── Podfile
├── Podfile.lock
├── Pods
│ ├── Local Podspecs
│ │ └── Reusable.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── Reusable-iOS.xcscheme
│ │ │ └── Reusable-tvOS.xcscheme
│ └── Target Support Files
│ │ ├── Pods-ReusableDemo iOS
│ │ ├── Info.plist
│ │ ├── Pods-ReusableDemo iOS-Info.plist
│ │ ├── Pods-ReusableDemo iOS-acknowledgements.markdown
│ │ ├── Pods-ReusableDemo iOS-acknowledgements.plist
│ │ ├── Pods-ReusableDemo iOS-dummy.m
│ │ ├── Pods-ReusableDemo iOS-frameworks-Debug-input-files.xcfilelist
│ │ ├── Pods-ReusableDemo iOS-frameworks-Debug-output-files.xcfilelist
│ │ ├── Pods-ReusableDemo iOS-frameworks-Release-input-files.xcfilelist
│ │ ├── Pods-ReusableDemo iOS-frameworks-Release-output-files.xcfilelist
│ │ ├── Pods-ReusableDemo iOS-frameworks.sh
│ │ ├── Pods-ReusableDemo iOS-resources.sh
│ │ ├── Pods-ReusableDemo iOS-umbrella.h
│ │ ├── Pods-ReusableDemo iOS.debug.xcconfig
│ │ ├── Pods-ReusableDemo iOS.modulemap
│ │ └── Pods-ReusableDemo iOS.release.xcconfig
│ │ ├── Pods-ReusableDemo tvOS
│ │ ├── Info.plist
│ │ ├── Pods-ReusableDemo tvOS-Info.plist
│ │ ├── Pods-ReusableDemo tvOS-acknowledgements.markdown
│ │ ├── Pods-ReusableDemo tvOS-acknowledgements.plist
│ │ ├── Pods-ReusableDemo tvOS-dummy.m
│ │ ├── Pods-ReusableDemo tvOS-frameworks-Debug-input-files.xcfilelist
│ │ ├── Pods-ReusableDemo tvOS-frameworks-Debug-output-files.xcfilelist
│ │ ├── Pods-ReusableDemo tvOS-frameworks-Release-input-files.xcfilelist
│ │ ├── Pods-ReusableDemo tvOS-frameworks-Release-output-files.xcfilelist
│ │ ├── Pods-ReusableDemo tvOS-frameworks.sh
│ │ ├── Pods-ReusableDemo tvOS-resources.sh
│ │ ├── Pods-ReusableDemo tvOS-umbrella.h
│ │ ├── Pods-ReusableDemo tvOS.debug.xcconfig
│ │ ├── Pods-ReusableDemo tvOS.modulemap
│ │ └── Pods-ReusableDemo tvOS.release.xcconfig
│ │ ├── Reusable-iOS
│ │ ├── Info.plist
│ │ ├── Reusable-iOS-Info.plist
│ │ ├── Reusable-iOS-dummy.m
│ │ ├── Reusable-iOS-prefix.pch
│ │ ├── Reusable-iOS-umbrella.h
│ │ ├── Reusable-iOS.debug.xcconfig
│ │ ├── Reusable-iOS.modulemap
│ │ ├── Reusable-iOS.release.xcconfig
│ │ └── Reusable-iOS.xcconfig
│ │ └── Reusable-tvOS
│ │ ├── Info.plist
│ │ ├── Reusable-tvOS-Info.plist
│ │ ├── Reusable-tvOS-dummy.m
│ │ ├── Reusable-tvOS-prefix.pch
│ │ ├── Reusable-tvOS-umbrella.h
│ │ ├── Reusable-tvOS.debug.xcconfig
│ │ ├── Reusable-tvOS.modulemap
│ │ ├── Reusable-tvOS.release.xcconfig
│ │ └── Reusable-tvOS.xcconfig
├── ReusableDemo iOS
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── AppIcon-120.png
│ │ │ ├── AppIcon-152.png
│ │ │ ├── AppIcon-167.png
│ │ │ ├── AppIcon-180.png
│ │ │ ├── AppIcon-76.png
│ │ │ ├── Contents.json
│ │ │ └── Logo.png
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── CollectionViewCells
│ │ ├── CollectionHeaderView.swift
│ │ ├── CollectionHeaderView.xib
│ │ ├── MyColorSquareCell.swift
│ │ ├── MyStoryboardTextSquareCell.swift
│ │ ├── MyXIBIndexSquaceCell.swift
│ │ └── MyXIBIndexSquaceCell.xib
│ ├── CollectionViewController.swift
│ ├── CustomViews
│ │ ├── MyCustomWidget.swift
│ │ └── MyCustomWidget.xib
│ ├── Info.plist
│ ├── Storyboards
│ │ ├── InfoDetailViewController.swift
│ │ ├── InfoViewController.storyboard
│ │ └── InfoViewController.swift
│ ├── TableViewCells
│ │ ├── MyHeaderTableView.swift
│ │ ├── MyHeaderTableView.xib
│ │ ├── MySimpleColorCell.swift
│ │ ├── MyStoryBoardIndexPathCell.swift
│ │ ├── MyXIBInfoCell.swift
│ │ ├── MyXIBInfoCell.xib
│ │ ├── MyXIBTextCell.swift
│ │ └── MyXIBTextCell.xib
│ └── TableViewController.swift
├── ReusableDemo tvOS
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── App Icon & Top Shelf Image.brandassets
│ │ │ ├── App Icon - Large.imagestack
│ │ │ │ ├── Back.imagestacklayer
│ │ │ │ │ ├── Content.imageset
│ │ │ │ │ │ ├── AppleTV.png
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Front.imagestacklayer
│ │ │ │ │ ├── Content.imageset
│ │ │ │ │ │ ├── AppleTV.png
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Middle.imagestacklayer
│ │ │ │ │ ├── Content.imageset
│ │ │ │ │ ├── AppleTV.png
│ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ ├── App Icon - Small.imagestack
│ │ │ │ ├── Back.imagestacklayer
│ │ │ │ │ ├── Content.imageset
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Front.imagestacklayer
│ │ │ │ │ ├── Content.imageset
│ │ │ │ │ │ ├── AppleTV-small.png
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Middle.imagestacklayer
│ │ │ │ │ ├── Content.imageset
│ │ │ │ │ ├── AppleTV-small.png
│ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Top Shelf Image Wide.imageset
│ │ │ │ └── Contents.json
│ │ │ └── Top Shelf Image.imageset
│ │ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── MyCustomWidget.swift
│ └── MyCustomWidget.xib
├── ReusableDemo.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── ReusableDemo iOS.xcscheme
│ │ └── ReusableDemo tvOS.xcscheme
└── ReusableDemo.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── WorkspaceSettings.xcsettings
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Logo.png
├── Logo.xcf
├── NibOwnerLoadable-InStoryboard.png
├── NibOwnerLoadable.png
├── Package.swift
├── README.md
├── Rakefile
├── Reusable.podspec
├── Sources
├── Storyboard
│ ├── StoryboardBased.swift
│ └── StoryboardSceneBased.swift
└── View
│ ├── NibLoadable.swift
│ ├── NibOwnerLoadable.swift
│ ├── Reusable.swift
│ ├── UICollectionView+Reusable.swift
│ └── UITableView+Reusable.swift
└── _Pods.xcodeproj
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | defaults:
2 | - &default-config
3 | macos:
4 | xcode: 12.5.1
5 | shell: /bin/bash --login -eo pipefail
6 | environment:
7 | CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
8 | CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
9 | BUNDLE_PATH: vendor/bundle
10 | - &prepare-storage
11 | run:
12 | name: Create directories for artifacts and reports
13 | command: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS
14 | - &set-ruby-version
15 | run:
16 | name: Set Ruby Version
17 | command: echo 'chruby ruby-2.7.3' >> ~/.bash_profile
18 | - &restore-gems
19 | restore_cache:
20 | keys:
21 | - gems-{{ checksum "Gemfile.lock" }}
22 | - gems-
23 | - &install-gems
24 | run:
25 | name: Bundle install
26 | command: bundle check || bundle install
27 | environment:
28 | BUNDLE_JOBS: 4
29 | BUNDLE_RETRY: 3
30 | - &store-gems
31 | save_cache:
32 | key: gems-{{ checksum "Gemfile.lock" }}
33 | paths:
34 | - vendor/bundle
35 | - &fetch-xcode-logs
36 | run:
37 | name: Getting Xcode activity logs
38 | command: find $HOME/Library/Developer/Xcode/DerivedData -name '*.xcactivitylog' -exec cp {} $CIRCLE_ARTIFACTS/xcactivitylog \; || true
39 | - &store-artifacts
40 | store_artifacts:
41 | path: /tmp/circleci-artifacts
42 |
43 |
44 | version: 2
45 | jobs:
46 | lint:
47 | <<: *default-config
48 | steps:
49 | - *prepare-storage
50 | - checkout
51 | - *set-ruby-version
52 | - *restore-gems
53 | - *install-gems
54 | - *store-gems
55 | - run:
56 | name: Install SwiftLint
57 | command: bundle exec rake swiftlint:install
58 | - run:
59 | name: Lint source code
60 | command: bundle exec rake swiftlint:run
61 | - *store-artifacts
62 |
63 | spm-build:
64 | <<: *default-config
65 | steps:
66 | - *prepare-storage
67 | - checkout
68 | - *set-ruby-version
69 | - *restore-gems
70 | - *install-gems
71 | - *store-gems
72 | - run:
73 | name: SPM Build
74 | command: bundle exec rake spm:build
75 | - *store-artifacts
76 |
77 | xcode-ios-build:
78 | <<: *default-config
79 | steps:
80 | - *prepare-storage
81 | - checkout
82 | - *set-ruby-version
83 | - *restore-gems
84 | - *install-gems
85 | - *store-gems
86 | - run:
87 | name: Build iOS Framework
88 | command: bundle exec rake fmk:ios
89 | - run:
90 | name: Build iOS Demo
91 | command: bundle exec rake demo:ios
92 | - store_test_results:
93 | path: /tmp/circleci-test-results
94 | - *fetch-xcode-logs
95 | - *store-artifacts
96 |
97 | xcode-tvos-build:
98 | <<: *default-config
99 | steps:
100 | - *prepare-storage
101 | - checkout
102 | - *set-ruby-version
103 | - *restore-gems
104 | - *install-gems
105 | - *store-gems
106 | - run:
107 | name: Build tvOS Framework
108 | command: bundle exec rake fmk:tvos
109 | - run:
110 | name: Build tvOS Demo
111 | command: bundle exec rake demo:tvos
112 | - store_test_results:
113 | path: /tmp/circleci-test-results
114 | - *fetch-xcode-logs
115 | - *store-artifacts
116 |
117 | pod-lint:
118 | <<: *default-config
119 | steps:
120 | - *prepare-storage
121 | - checkout
122 | - *set-ruby-version
123 | - *restore-gems
124 | - *install-gems
125 | - *store-gems
126 | - run:
127 | name: Lint podspec
128 | command: bundle exec rake pod:lint
129 | - *store-artifacts
130 |
131 | carthage-build:
132 | <<: *default-config
133 | steps:
134 | - *prepare-storage
135 | - checkout
136 | - *set-ruby-version
137 | - *restore-gems
138 | - *install-gems
139 | - *store-gems
140 | - run:
141 | name: Install Carthage
142 | command: bundle exec rake carthage:install
143 | - run:
144 | name: Carthage Build
145 | command: bundle exec rake carthage:build
146 | - store_test_results:
147 | path: /tmp/circleci-test-results
148 | - *fetch-xcode-logs
149 | - *store-artifacts
150 |
151 | workflows:
152 | version: 2
153 | check_all_builds:
154 | jobs:
155 | - lint
156 | - xcode-ios-build:
157 | requires:
158 | - lint
159 | - xcode-tvos-build:
160 | requires:
161 | - lint
162 | - spm-build:
163 | requires:
164 | - lint
165 | - carthage-build:
166 | requires:
167 | - xcode-ios-build
168 | - xcode-tvos-build
169 | - pod-lint:
170 | requires:
171 | - spm-build
172 | - xcode-ios-build
173 | - xcode-tvos-build
174 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## macOS
2 |
3 | .DS_Store
4 |
5 | ## Xcode
6 |
7 | ### Build generated
8 | build/
9 | DerivedData
10 |
11 | ### Various settings
12 | *.pbxuser
13 | !default.pbxuser
14 | *.mode1v3
15 | !default.mode1v3
16 | *.mode2v3
17 | !default.mode2v3
18 | *.perspectivev3
19 | !default.perspectivev3
20 | xcuserdata
21 |
22 | ### Other
23 | *.xccheckout
24 | *.moved-aside
25 | *.xcuserstate
26 | *.xcscmblueprint
27 |
28 | ## Obj-C/Swift specific
29 | *.hmap
30 | *.ipa
31 |
32 |
33 | ## Swift Package Manager
34 |
35 | .swiftpm
36 | .build/
37 |
38 | ## Carthage
39 |
40 | Carthage/
41 | Reusable.framework.zip
42 |
43 | ## fastlane
44 |
45 | fastlane/report.xml
46 | fastlane/screenshots
47 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | line_length:
2 | warning: 120
3 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ## main branch
4 |
5 | _No pending changes to be released yet!_
6 |
7 | ## 4.1.2
8 |
9 | * Update `Package.swift` and `.podspec` to use newer min iOS version supported by Xcode 12+.
10 | [@AliSoftware](https://github.com/AliSoftware)
11 | [#115](https://github.com/AliSoftware/Reusable/pull/115)
12 |
13 | * Fix Xcode 12.5 warnings about the class keyword for protocol inheritance that is deprecated.
14 | [@johnarn](https://github.com/johnarn)
15 | [#113](https://github.com/AliSoftware/Reusable/pull/113)
16 |
17 | ## 4.1.1
18 |
19 | * Update the README with up-to-date Swift versions and Installation Instructions.
20 | [@kuyazee](https://github.com/kuyazee)
21 | [@AliSoftware](https://github.com/AliSoftware)
22 | [#95](https://github.com/AliSoftware/Reusable/pull/95)
23 |
24 | * Set `APPLICATION_EXTENSION_API_ONLY` build setting on built frameworks.
25 | [@AliSoftware](https://github.com/AliSoftware)
26 | [#98](https://github.com/AliSoftware/Reusable/pull/98)
27 | [@nahung89](https://github.com/nahung89)
28 | [#88](https://github.com/AliSoftware/Reusable/pull/88)
29 |
30 | * Update tools used by the project (Xcode, CocoaPods, CI, Carthage).
31 | Also SPM builds are now tested by CI.
32 | [@AliSoftware](https://github.com/AliSoftware)
33 | [#97](https://github.com/AliSoftware/Reusable/pull/97)
34 |
35 | * Update SPM `Package.swift` to mention supported platforms.
36 | [@MortyMerr](https://github.com/MortyMerr)
37 | [#89](https://github.com/AliSoftware/Reusable/pull/89)
38 | [@pahnev](https://github.com/pahnev)
39 | [#93](https://github.com/AliSoftware/Reusable/pull/93)
40 | [@mackoj](https://github.com/mackoj)
41 | [#85](https://github.com/AliSoftware/Reusable/pull/85)
42 |
43 | * Fix nib name lookup when using subclassing.
44 | [@calmez](https://github.com/calmez)
45 | [#96](https://github.com/AliSoftware/Reusable/pull/96)
46 |
47 | ## 4.1.0
48 |
49 | * Support for Swift 5.0
50 | [@florentmorin](https://github.com/florentmorin)
51 | [#80](https://github.com/AliSoftware/Reusable/pull/80)
52 |
53 | ## 4.0.5
54 |
55 | * Fix for only allowing the use of app extension API.
56 | [@igorkulman](https://github.com/igorkulman)
57 | [#73](https://github.com/AliSoftware/Reusable/pull/73)
58 |
59 | ## 4.0.4
60 |
61 | * Only allowing the use of app extension API so using the library in an app extension does not produce a warning.
62 | [@igorkulman](https://github.com/igorkulman)
63 | [#70](https://github.com/AliSoftware/Reusable/pull/70)
64 |
65 | ## 4.0.3
66 |
67 | * Upgrade to CircleCI 2.
68 | [@djbe](https://github.com/djbe)
69 | [#60](https://github.com/AliSoftware/Reusable/pull/60)
70 |
71 | * Update project to support Swift 4.2.
72 | [@djbe](https://github.com/djbe)
73 | [#58](https://github.com/AliSoftware/Reusable/pull/58)
74 |
75 | ## 4.0.2
76 |
77 | * Update project to support Swift 4.
78 | [@AYastrebov](https://github.com/AYastrebov)
79 | [#54](https://github.com/AliSoftware/Reusable/pull/54)
80 |
81 | * Fix typo in StoryboardBased examples.
82 | [@danshevluk](https://github.com/danshevluk)
83 | [#42](https://github.com/AliSoftware/Reusable/pull/42)
84 |
85 | * Updated README instructions to Swift 3.
86 | [@neilkimmett](https://github.com/neilkimmett)
87 | [#41](https://github.com/AliSoftware/Reusable/pull/41)
88 |
89 | ## 4.0.1
90 |
91 | * Added a tvOS target in the Example project.
92 | * Carthage should now see the tvOS framework
93 |
94 | ## 4.0.0
95 |
96 | ### Breaking changes
97 |
98 | * The method `static func loadFromNib(owner:)` of `NibOwnerLoadable` has been replaced by instance method `func loadNibContent()`.
99 | This is more consistent as we need an instance (owner) anyway, and also avoids possible crashes when used with `UIView` subclasses
100 | not implementing non-required initializers `init()`/`init(frame:)`.
101 | _(Method `static func loadFromNib()` of `NibLoadable` is still unchanged)_.
102 | [@Skoti](https://github.com/Skoti)
103 | [#40](https://github.com/AliSoftware/Reusable/pull/40)
104 | * The `storyboard` property of `StoryboardBased` and `StoryboardSceneBased` protocols has been renamed to `sceneStoryboard` to avoid conflicts.
105 | [@jakubgert](https://github.com/jakubgert)
106 | [#33](https://github.com/AliSoftware/Reusable/pull/33)
107 |
108 | ### Fixes
109 |
110 | * Fixing documentation typos for `CollectionHeaderView` and `MyXIBIndexSquaceCell`.
111 | [@Skoti](https://github.com/Skoti)
112 |
113 | * Fixing TableView Controller scene in Example project, to display cells above `UITabBar`.
114 | [@Skoti](https://github.com/Skoti)
115 |
116 | ## 3.0.1
117 |
118 | ### Bug Fixes
119 |
120 | * Fix `instantiate()` implementation on `StoryboardSceneBased` ViewControllers.
121 | [@jakubgert](https://github.com/jakubgert)
122 | [#38](https://github.com/AliSoftware/Reusable/pull/38)
123 | * Removed strict `NibReusable` protocol conforming in `register` functions.
124 | You can now make a `Reusable`-only cell with a `NibLoadable` subclass.
125 | [@nekrich](https://github.com/nekrich)
126 | [#37](https://github.com/AliSoftware/Reusable/pull/37)
127 |
128 | ## 3.0.0
129 |
130 | ### Breaking Changes
131 |
132 | * Converted library and Demo project to Swift 3.
133 | ⚠️ The following methods have new signatures:
134 | - `dequeueReusableCell(indexPath:)` is now `dequeueReusableCell(for:)`
135 | - `dequeueReusableCell(indexPath:cellType:)` is now `dequeueReusableCell(for:cellType:)`
136 | - `registerReusableCell(_:)` is now `register(cellType:)`
137 | - `registerReusableHeaderFooterView(_:)` is now `register(headerFooterViewType:)`
138 | - `registerReusableSupplementaryView(_:viewType:)` is now `register(supplementaryViewType:ofKind:)`
139 | - `dequeueReusableSupplementaryView(_:indexPath:viewType:)` is now `dequeueReusableSupplementaryView(ofKind:for:viewType:)`
140 | [@phatblat](https://github.com/phatblat)
141 | [#30](https://github.com/AliSoftware/Reusable/pull/30)
142 | [@ceyhuno](https://github.com/ceyhuno)
143 | [#31](https://github.com/AliSoftware/Reusable/pull/31)
144 |
145 | ## 2.5.1
146 |
147 | * Adapted source files and demo project for Swift 2.3
148 | [@antondomashnev](https://github.com/Antondomashnev)
149 | [#16](https://github.com/AliSoftware/Reusable/pull/28)
150 |
151 | ## 2.5.0
152 |
153 | * Added the possibility for `NibOwnerLoadable` confirming custom views to pass an existing instance as `owner`
154 | (used as the File's Owner) in case one already exists. This is especially useful to implement `init(coder:)`
155 | to load the content of the XIB as subviews of `self` after initialization. See `MyCustomWidget.swift` for an example.
156 | [@AliSoftware](https://github.com/AliSoftware)
157 |
158 | ## 2.4.0
159 |
160 | * Added `StoryboardBased` and `StoryboardSceneBased` protocols for storyboard based `UIViewController` easy instantiation.
161 | [@AliSoftware](https://github.com/AliSoftware)
162 |
163 | ## 2.3.0
164 |
165 | * Added ` NibOwnerLoadable` protocol for `UIView` set as XIB's File's Owner.
166 | [@PoissonBallon](https://github.com/PoissonBallon)
167 | [#16](https://github.com/AliSoftware/Reusable/pull/16)
168 |
169 | _While the `NibLoadable` protocol is adapted to views loaded from XIB but that are set as the root view of the XIB,
170 | this new `NibOwnerLoadable` protocol is adapted to view loaded from XIB too, but that are set as the XIB's File's Owner._
171 |
172 | ## 2.2.1
173 |
174 | * Fixed issue with `register…` methods registering the superclass `T` instead of the dynamic class `cellType` / `viewType`.
175 | [@narirou](https://github.com/narirou)
176 | [#13](https://github.com/AliSoftware/Reusable/pull/13)
177 |
178 | ## 2.2.0
179 |
180 | * Added optional `viewType` & `cellType` parameters to the dequeue functions.
181 | [@k3zi](https://github.com/k3zi)
182 | [#11](https://github.com/AliSoftware/Reusable/pull/11)
183 |
184 | This parameter is only needed if you can't write `… as MyCell` (to let Swift infer the cell type from the return type),
185 | which might be the case for example when your cell class is stored in a variable:
186 |
187 | ```swift
188 | let cellType: Any.Type = self.cellTypeForIndexPath(indexPath)
189 | // Can't do this in this case (because cellType is a variable):
190 | let cell = tableView.dequeueReusableCell(indexPath: indexPath) as cellType ❌ // compiler error
191 | // But now we can use that alternate way for such cases:
192 | let cell = tableView.dequeueReusableCell(indexPath: indexPath, cellType: cellType)
193 | ```
194 |
195 | But if you know the type at compile time, you can omit the `cellType` parameter and still do this, letting the return type infer it for you:
196 |
197 | ```swift
198 | let cell = tableView.dequeueReusableCell(indexPath: indexPath) as MyCell
199 | ```
200 |
201 | ## 2.1.1
202 |
203 | * Made every method `final` to allow more optimizations.
204 | [@AliSoftware](https://github.com/AliSoftware)
205 |
206 | * Banned the use of `as!` in the source code in favour of `guard let x = y else { fatalError(…) }`.
207 | This avoids force-casts (which are considered bad practice) and generate a more explicit fatal error in case the developer forgot something (typically forgot to set the reuseIdentifier in IB).
208 | [@AliSoftware](https://github.com/AliSoftware)
209 | [#6](https://github.com/AliSoftware/Reusable/issues/6)
210 |
211 | * Fixed bundle location of nibs. By default, `nib: UINib` of `NibLoadable` protocol will now use the nib located in the bundle of the conforming class.
212 | [@chrisamanse](https://github.com/chrisamanse)
213 | [#10](https://github.com/AliSoftware/Reusable/pull/10)
214 |
215 | * Fixed issue with subclasses of types conforming to `Reusable` — due to the [Swift bug SR-617](https://bugs.swift.org/browse/SR-617).
216 | [@chrisamanse](https://github.com/chrisamanse)
217 | [#2](https://github.com/AliSoftware/Reusable/issues/2)
218 |
219 | ## 2.1.0
220 |
221 | * Added support for direct instantiation of arbitrary `UIView` from a nib.
222 | [@jakubvano](https://github.com/jakubvano)
223 | [#5](https://github.com/AliSoftware/Reusable/pull/5)
224 |
225 | There is now a dedicated `NibLoadable` protocol which can be used on any arbitrary `UIView` (even non-"reusable" views) to load it from a XIB (via the `loadFromNib()` function injected via the protocol extension).
226 |
227 | _The `NibReusable` protocol still exists for reusable cells but is now declared just as a combination of both the `Reusable` and `NibLoadable` protocols.
228 |
229 | ## 2.0.0
230 |
231 | * Fixed missing `public` visibility for the protocols and extensions
232 | * Improved README documentation
233 |
234 | ## 1.1.0
235 |
236 | * Added documentation
237 | * Fixed generic constraints on the API working with `UICollectionView`'s `SupplementaryView`
238 | * Updated Example project to add an UICollectionView with cells from XIB & Code + Header views
239 |
240 | ## 1.0.0
241 |
242 | * Split protocol in two: `Reusable` and `NibReusable`
243 | * Now contains a Demo project
244 |
245 | ## 0.1.0
246 |
247 | Initial version. Only one `Reusable` protocol
248 | No demo project, but has a `podspec` and a `Package.swift`
249 |
--------------------------------------------------------------------------------
/Example/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | opt_in_rules:
2 | - empty_count
3 |
4 | included:
5 | - ../Sources
6 | - ReusableDemo
7 |
8 | line_length:
9 | warning: 120
10 | error: 160
11 |
12 |
--------------------------------------------------------------------------------
/Example/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/Default-568h@2x.png
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | target 'ReusableDemo iOS' do
4 | platform :ios, '12.0'
5 | pod 'Reusable', :path => '../'
6 | end
7 |
8 | target 'ReusableDemo tvOS' do
9 | platform :tvos, '12.0'
10 | pod 'Reusable', :path => '../'
11 | end
12 |
13 | post_install do |installer|
14 | installer.pods_project.targets.each do |target|
15 | target.build_configurations.each do |config|
16 | config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'YES'
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Reusable (4.1.2):
3 | - Reusable/Storyboard (= 4.1.2)
4 | - Reusable/View (= 4.1.2)
5 | - Reusable/Storyboard (4.1.2)
6 | - Reusable/View (4.1.2)
7 |
8 | DEPENDENCIES:
9 | - Reusable (from `../`)
10 |
11 | EXTERNAL SOURCES:
12 | Reusable:
13 | :path: "../"
14 |
15 | SPEC CHECKSUMS:
16 | Reusable: 6bae6a5e8aa793c9c441db0213c863a64bce9136
17 |
18 | PODFILE CHECKSUM: ae97c8d84b9148534471b041a33cec1ba3620b65
19 |
20 | COCOAPODS: 1.11.0
21 |
--------------------------------------------------------------------------------
/Example/Pods/Local Podspecs/Reusable.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Reusable",
3 | "cocoapods_version": "~> 1.4",
4 | "version": "4.1.2",
5 | "summary": "A Swift Mixin to deal with reusable UITableView & UICollectionView cells and XIB-based views",
6 | "description": "Reusable is a [Swift Mixin](http://alisoftware.github.io/swift/protocol/2015/11/08/mixins-over-inheritance/)\nto easily deal with your reusable UITableViewCell and UICollectionViewCell classes.\n\nSimply mark your `UITableViewCell` or `UICollectionViewCell` sublcasses as\nconforming to either `Reusable` or `NibReusable` and you'll be able to\nmanipulate them way easier, and without worrying with String-type reuseIdentifiers\never again, and instead use them in a type-safe manner!\n\nReusable also support marking any arbitrary `UIView` subclass as `NibLoadable` so that\nyou can then call `loadFromNib()` on the custom view class easily without adding any code.\n\nFor more info, see [my blog post](http://alisoftware.github.io/swift/generics/2016/01/06/generic-tableviewcells/)\nabout this technique.",
7 | "homepage": "https://github.com/AliSoftware/Reusable",
8 | "license": {
9 | "type": "MIT",
10 | "file": "LICENSE"
11 | },
12 | "authors": {
13 | "Olivier Halligon": "olivier@halligon.net"
14 | },
15 | "social_media_url": "http://twitter.com/aligatr",
16 | "platforms": {
17 | "ios": "9.0",
18 | "tvos": "9.0"
19 | },
20 | "source": {
21 | "git": "https://github.com/AliSoftware/Reusable.git",
22 | "tag": "4.1.2"
23 | },
24 | "swift_versions": "5.0",
25 | "frameworks": "UIKit",
26 | "subspecs": [
27 | {
28 | "name": "View",
29 | "source_files": "Sources/View/*.swift"
30 | },
31 | {
32 | "name": "Storyboard",
33 | "source_files": "Sources/Storyboard/*.swift"
34 | }
35 | ],
36 | "swift_version": "5.0"
37 | }
38 |
--------------------------------------------------------------------------------
/Example/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Reusable (4.1.2):
3 | - Reusable/Storyboard (= 4.1.2)
4 | - Reusable/View (= 4.1.2)
5 | - Reusable/Storyboard (4.1.2)
6 | - Reusable/View (4.1.2)
7 |
8 | DEPENDENCIES:
9 | - Reusable (from `../`)
10 |
11 | EXTERNAL SOURCES:
12 | Reusable:
13 | :path: "../"
14 |
15 | SPEC CHECKSUMS:
16 | Reusable: 6bae6a5e8aa793c9c441db0213c863a64bce9136
17 |
18 | PODFILE CHECKSUM: ae97c8d84b9148534471b041a33cec1ba3620b65
19 |
20 | COCOAPODS: 1.11.0
21 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Reusable-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
57 |
58 |
59 |
60 |
62 |
63 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Reusable-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
57 |
58 |
59 |
60 |
62 |
63 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Reusable
5 |
6 | The MIT License (MIT)
7 |
8 | Copyright (c) 2016 AliSoftware
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 | Generated by CocoaPods - https://cocoapods.org
29 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | The MIT License (MIT)
18 |
19 | Copyright (c) 2016 AliSoftware
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy
22 | of this software and associated documentation files (the "Software"), to deal
23 | in the Software without restriction, including without limitation the rights
24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the Software is
26 | furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in all
29 | copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 | SOFTWARE.
38 |
39 | License
40 | MIT
41 | Title
42 | Reusable
43 | Type
44 | PSGroupSpecifier
45 |
46 |
47 | FooterText
48 | Generated by CocoaPods - https://cocoapods.org
49 | Title
50 |
51 | Type
52 | PSGroupSpecifier
53 |
54 |
55 | StringsTable
56 | Acknowledgements
57 | Title
58 | Acknowledgements
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_ReusableDemo_iOS : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_ReusableDemo_iOS
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks-Debug-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Reusable-iOS/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks-Debug-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks-Release-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Reusable-iOS/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks-Release-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | set -u
4 | set -o pipefail
5 |
6 | function on_error {
7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
8 | }
9 | trap 'on_error $LINENO' ERR
10 |
11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
13 | # frameworks to, so exit 0 (signalling the script phase was successful).
14 | exit 0
15 | fi
16 |
17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
19 |
20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
22 | BCSYMBOLMAP_DIR="BCSymbolMaps"
23 |
24 |
25 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
26 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
27 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
28 |
29 | # Copies and strips a vendored framework
30 | install_framework()
31 | {
32 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
33 | local source="${BUILT_PRODUCTS_DIR}/$1"
34 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
35 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
36 | elif [ -r "$1" ]; then
37 | local source="$1"
38 | fi
39 |
40 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
41 |
42 | if [ -L "${source}" ]; then
43 | echo "Symlinked..."
44 | source="$(readlink "${source}")"
45 | fi
46 |
47 | if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then
48 | # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied
49 | find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do
50 | echo "Installing $f"
51 | install_bcsymbolmap "$f" "$destination"
52 | rm "$f"
53 | done
54 | rmdir "${source}/${BCSYMBOLMAP_DIR}"
55 | fi
56 |
57 | # Use filter instead of exclude so missing patterns don't throw errors.
58 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
59 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
60 |
61 | local basename
62 | basename="$(basename -s .framework "$1")"
63 | binary="${destination}/${basename}.framework/${basename}"
64 |
65 | if ! [ -r "$binary" ]; then
66 | binary="${destination}/${basename}"
67 | elif [ -L "${binary}" ]; then
68 | echo "Destination binary is symlinked..."
69 | dirname="$(dirname "${binary}")"
70 | binary="${dirname}/$(readlink "${binary}")"
71 | fi
72 |
73 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
74 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
75 | strip_invalid_archs "$binary"
76 | fi
77 |
78 | # Resign the code if required by the build settings to avoid unstable apps
79 | code_sign_if_enabled "${destination}/$(basename "$1")"
80 |
81 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
82 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
83 | local swift_runtime_libs
84 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u)
85 | for lib in $swift_runtime_libs; do
86 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
87 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
88 | code_sign_if_enabled "${destination}/${lib}"
89 | done
90 | fi
91 | }
92 | # Copies and strips a vendored dSYM
93 | install_dsym() {
94 | local source="$1"
95 | warn_missing_arch=${2:-true}
96 | if [ -r "$source" ]; then
97 | # Copy the dSYM into the targets temp dir.
98 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
99 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
100 |
101 | local basename
102 | basename="$(basename -s .dSYM "$source")"
103 | binary_name="$(ls "$source/Contents/Resources/DWARF")"
104 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}"
105 |
106 | # Strip invalid architectures from the dSYM.
107 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then
108 | strip_invalid_archs "$binary" "$warn_missing_arch"
109 | fi
110 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then
111 | # Move the stripped file into its final destination.
112 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
113 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
114 | else
115 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
116 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}"
117 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM"
118 | fi
119 | fi
120 | }
121 |
122 | # Used as a return value for each invocation of `strip_invalid_archs` function.
123 | STRIP_BINARY_RETVAL=0
124 |
125 | # Strip invalid architectures
126 | strip_invalid_archs() {
127 | binary="$1"
128 | warn_missing_arch=${2:-true}
129 | # Get architectures for current target binary
130 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
131 | # Intersect them with the architectures we are building for
132 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
133 | # If there are no archs supported by this binary then warn the user
134 | if [[ -z "$intersected_archs" ]]; then
135 | if [[ "$warn_missing_arch" == "true" ]]; then
136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
137 | fi
138 | STRIP_BINARY_RETVAL=1
139 | return
140 | fi
141 | stripped=""
142 | for arch in $binary_archs; do
143 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
144 | # Strip non-valid architectures in-place
145 | lipo -remove "$arch" -output "$binary" "$binary"
146 | stripped="$stripped $arch"
147 | fi
148 | done
149 | if [[ "$stripped" ]]; then
150 | echo "Stripped $binary of architectures:$stripped"
151 | fi
152 | STRIP_BINARY_RETVAL=0
153 | }
154 |
155 | # Copies the bcsymbolmap files of a vendored framework
156 | install_bcsymbolmap() {
157 | local bcsymbolmap_path="$1"
158 | local destination="${BUILT_PRODUCTS_DIR}"
159 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}""
160 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"
161 | }
162 |
163 | # Signs a framework with the provided identity
164 | code_sign_if_enabled() {
165 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
166 | # Use the current code_sign_identity
167 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
168 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
169 |
170 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
171 | code_sign_cmd="$code_sign_cmd &"
172 | fi
173 | echo "$code_sign_cmd"
174 | eval "$code_sign_cmd"
175 | fi
176 | }
177 |
178 | if [[ "$CONFIGURATION" == "Debug" ]]; then
179 | install_framework "${BUILT_PRODUCTS_DIR}/Reusable-iOS/Reusable.framework"
180 | fi
181 | if [[ "$CONFIGURATION" == "Release" ]]; then
182 | install_framework "${BUILT_PRODUCTS_DIR}/Reusable-iOS/Reusable.framework"
183 | fi
184 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
185 | wait
186 | fi
187 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | set -u
4 | set -o pipefail
5 |
6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then
7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy
8 | # resources to, so exit 0 (signalling the script phase was successful).
9 | exit 0
10 | fi
11 |
12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
13 |
14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
15 | > "$RESOURCES_TO_COPY"
16 |
17 | XCASSET_FILES=()
18 |
19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
22 |
23 | case "${TARGETED_DEVICE_FAMILY:-}" in
24 | 1,2)
25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
26 | ;;
27 | 1)
28 | TARGET_DEVICE_ARGS="--target-device iphone"
29 | ;;
30 | 2)
31 | TARGET_DEVICE_ARGS="--target-device ipad"
32 | ;;
33 | 3)
34 | TARGET_DEVICE_ARGS="--target-device tv"
35 | ;;
36 | 4)
37 | TARGET_DEVICE_ARGS="--target-device watch"
38 | ;;
39 | *)
40 | TARGET_DEVICE_ARGS="--target-device mac"
41 | ;;
42 | esac
43 |
44 | install_resource()
45 | {
46 | if [[ "$1" = /* ]] ; then
47 | RESOURCE_PATH="$1"
48 | else
49 | RESOURCE_PATH="${PODS_ROOT}/$1"
50 | fi
51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
52 | cat << EOM
53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
54 | EOM
55 | exit 1
56 | fi
57 | case $RESOURCE_PATH in
58 | *.storyboard)
59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
61 | ;;
62 | *.xib)
63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
65 | ;;
66 | *.framework)
67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
71 | ;;
72 | *.xcdatamodel)
73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
75 | ;;
76 | *.xcdatamodeld)
77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
79 | ;;
80 | *.xcmappingmodel)
81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
83 | ;;
84 | *.xcassets)
85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
87 | ;;
88 | *)
89 | echo "$RESOURCE_PATH" || true
90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
91 | ;;
92 | esac
93 | }
94 |
95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
100 | fi
101 | rm -f "$RESOURCES_TO_COPY"
102 |
103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ]
104 | then
105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
107 | while read line; do
108 | if [[ $line != "${PODS_ROOT}*" ]]; then
109 | XCASSET_FILES+=("$line")
110 | fi
111 | done <<<"$OTHER_XCASSETS"
112 |
113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then
114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
115 | else
116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist"
117 | fi
118 | fi
119 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_ReusableDemo_iOSVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_ReusableDemo_iOSVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS/Reusable.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
8 | OTHER_LDFLAGS = $(inherited) -framework "Reusable" -framework "UIKit"
9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
10 | PODS_BUILD_DIR = ${BUILD_DIR}
11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
13 | PODS_ROOT = ${SRCROOT}/Pods
14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
16 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_ReusableDemo_iOS {
2 | umbrella header "Pods-ReusableDemo iOS-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS/Reusable.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
8 | OTHER_LDFLAGS = $(inherited) -framework "Reusable" -framework "UIKit"
9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
10 | PODS_BUILD_DIR = ${BUILD_DIR}
11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
13 | PODS_ROOT = ${SRCROOT}/Pods
14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
16 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/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.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-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.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Reusable
5 |
6 | The MIT License (MIT)
7 |
8 | Copyright (c) 2016 AliSoftware
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 | Generated by CocoaPods - https://cocoapods.org
29 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | The MIT License (MIT)
18 |
19 | Copyright (c) 2016 AliSoftware
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy
22 | of this software and associated documentation files (the "Software"), to deal
23 | in the Software without restriction, including without limitation the rights
24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the Software is
26 | furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in all
29 | copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 | SOFTWARE.
38 |
39 | License
40 | MIT
41 | Title
42 | Reusable
43 | Type
44 | PSGroupSpecifier
45 |
46 |
47 | FooterText
48 | Generated by CocoaPods - https://cocoapods.org
49 | Title
50 |
51 | Type
52 | PSGroupSpecifier
53 |
54 |
55 | StringsTable
56 | Acknowledgements
57 | Title
58 | Acknowledgements
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_ReusableDemo_tvOS : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_ReusableDemo_tvOS
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks-Debug-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Reusable-tvOS/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks-Debug-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks-Release-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Reusable-tvOS/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks-Release-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reusable.framework
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | set -u
4 | set -o pipefail
5 |
6 | function on_error {
7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
8 | }
9 | trap 'on_error $LINENO' ERR
10 |
11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
13 | # frameworks to, so exit 0 (signalling the script phase was successful).
14 | exit 0
15 | fi
16 |
17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
19 |
20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
22 | BCSYMBOLMAP_DIR="BCSymbolMaps"
23 |
24 |
25 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
26 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
27 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
28 |
29 | # Copies and strips a vendored framework
30 | install_framework()
31 | {
32 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
33 | local source="${BUILT_PRODUCTS_DIR}/$1"
34 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
35 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
36 | elif [ -r "$1" ]; then
37 | local source="$1"
38 | fi
39 |
40 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
41 |
42 | if [ -L "${source}" ]; then
43 | echo "Symlinked..."
44 | source="$(readlink "${source}")"
45 | fi
46 |
47 | if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then
48 | # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied
49 | find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do
50 | echo "Installing $f"
51 | install_bcsymbolmap "$f" "$destination"
52 | rm "$f"
53 | done
54 | rmdir "${source}/${BCSYMBOLMAP_DIR}"
55 | fi
56 |
57 | # Use filter instead of exclude so missing patterns don't throw errors.
58 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
59 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
60 |
61 | local basename
62 | basename="$(basename -s .framework "$1")"
63 | binary="${destination}/${basename}.framework/${basename}"
64 |
65 | if ! [ -r "$binary" ]; then
66 | binary="${destination}/${basename}"
67 | elif [ -L "${binary}" ]; then
68 | echo "Destination binary is symlinked..."
69 | dirname="$(dirname "${binary}")"
70 | binary="${dirname}/$(readlink "${binary}")"
71 | fi
72 |
73 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
74 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
75 | strip_invalid_archs "$binary"
76 | fi
77 |
78 | # Resign the code if required by the build settings to avoid unstable apps
79 | code_sign_if_enabled "${destination}/$(basename "$1")"
80 |
81 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
82 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
83 | local swift_runtime_libs
84 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u)
85 | for lib in $swift_runtime_libs; do
86 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
87 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
88 | code_sign_if_enabled "${destination}/${lib}"
89 | done
90 | fi
91 | }
92 | # Copies and strips a vendored dSYM
93 | install_dsym() {
94 | local source="$1"
95 | warn_missing_arch=${2:-true}
96 | if [ -r "$source" ]; then
97 | # Copy the dSYM into the targets temp dir.
98 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
99 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
100 |
101 | local basename
102 | basename="$(basename -s .dSYM "$source")"
103 | binary_name="$(ls "$source/Contents/Resources/DWARF")"
104 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}"
105 |
106 | # Strip invalid architectures from the dSYM.
107 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then
108 | strip_invalid_archs "$binary" "$warn_missing_arch"
109 | fi
110 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then
111 | # Move the stripped file into its final destination.
112 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
113 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
114 | else
115 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
116 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}"
117 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM"
118 | fi
119 | fi
120 | }
121 |
122 | # Used as a return value for each invocation of `strip_invalid_archs` function.
123 | STRIP_BINARY_RETVAL=0
124 |
125 | # Strip invalid architectures
126 | strip_invalid_archs() {
127 | binary="$1"
128 | warn_missing_arch=${2:-true}
129 | # Get architectures for current target binary
130 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
131 | # Intersect them with the architectures we are building for
132 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
133 | # If there are no archs supported by this binary then warn the user
134 | if [[ -z "$intersected_archs" ]]; then
135 | if [[ "$warn_missing_arch" == "true" ]]; then
136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
137 | fi
138 | STRIP_BINARY_RETVAL=1
139 | return
140 | fi
141 | stripped=""
142 | for arch in $binary_archs; do
143 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
144 | # Strip non-valid architectures in-place
145 | lipo -remove "$arch" -output "$binary" "$binary"
146 | stripped="$stripped $arch"
147 | fi
148 | done
149 | if [[ "$stripped" ]]; then
150 | echo "Stripped $binary of architectures:$stripped"
151 | fi
152 | STRIP_BINARY_RETVAL=0
153 | }
154 |
155 | # Copies the bcsymbolmap files of a vendored framework
156 | install_bcsymbolmap() {
157 | local bcsymbolmap_path="$1"
158 | local destination="${BUILT_PRODUCTS_DIR}"
159 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}""
160 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"
161 | }
162 |
163 | # Signs a framework with the provided identity
164 | code_sign_if_enabled() {
165 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
166 | # Use the current code_sign_identity
167 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
168 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
169 |
170 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
171 | code_sign_cmd="$code_sign_cmd &"
172 | fi
173 | echo "$code_sign_cmd"
174 | eval "$code_sign_cmd"
175 | fi
176 | }
177 |
178 | if [[ "$CONFIGURATION" == "Debug" ]]; then
179 | install_framework "${BUILT_PRODUCTS_DIR}/Reusable-tvOS/Reusable.framework"
180 | fi
181 | if [[ "$CONFIGURATION" == "Release" ]]; then
182 | install_framework "${BUILT_PRODUCTS_DIR}/Reusable-tvOS/Reusable.framework"
183 | fi
184 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
185 | wait
186 | fi
187 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | set -u
4 | set -o pipefail
5 |
6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then
7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy
8 | # resources to, so exit 0 (signalling the script phase was successful).
9 | exit 0
10 | fi
11 |
12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
13 |
14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
15 | > "$RESOURCES_TO_COPY"
16 |
17 | XCASSET_FILES=()
18 |
19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
22 |
23 | case "${TARGETED_DEVICE_FAMILY:-}" in
24 | 1,2)
25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
26 | ;;
27 | 1)
28 | TARGET_DEVICE_ARGS="--target-device iphone"
29 | ;;
30 | 2)
31 | TARGET_DEVICE_ARGS="--target-device ipad"
32 | ;;
33 | 3)
34 | TARGET_DEVICE_ARGS="--target-device tv"
35 | ;;
36 | 4)
37 | TARGET_DEVICE_ARGS="--target-device watch"
38 | ;;
39 | *)
40 | TARGET_DEVICE_ARGS="--target-device mac"
41 | ;;
42 | esac
43 |
44 | install_resource()
45 | {
46 | if [[ "$1" = /* ]] ; then
47 | RESOURCE_PATH="$1"
48 | else
49 | RESOURCE_PATH="${PODS_ROOT}/$1"
50 | fi
51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
52 | cat << EOM
53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
54 | EOM
55 | exit 1
56 | fi
57 | case $RESOURCE_PATH in
58 | *.storyboard)
59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
61 | ;;
62 | *.xib)
63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
65 | ;;
66 | *.framework)
67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
71 | ;;
72 | *.xcdatamodel)
73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
75 | ;;
76 | *.xcdatamodeld)
77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
79 | ;;
80 | *.xcmappingmodel)
81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
83 | ;;
84 | *.xcassets)
85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
87 | ;;
88 | *)
89 | echo "$RESOURCE_PATH" || true
90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
91 | ;;
92 | esac
93 | }
94 |
95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
100 | fi
101 | rm -f "$RESOURCES_TO_COPY"
102 |
103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ]
104 | then
105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
107 | while read line; do
108 | if [[ $line != "${PODS_ROOT}*" ]]; then
109 | XCASSET_FILES+=("$line")
110 | fi
111 | done <<<"$OTHER_XCASSETS"
112 |
113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then
114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
115 | else
116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist"
117 | fi
118 | fi
119 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_ReusableDemo_tvOSVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_ReusableDemo_tvOSVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS/Reusable.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
8 | OTHER_LDFLAGS = $(inherited) -framework "Reusable" -framework "UIKit"
9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
10 | PODS_BUILD_DIR = ${BUILD_DIR}
11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
13 | PODS_ROOT = ${SRCROOT}/Pods
14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
16 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_ReusableDemo_tvOS {
2 | umbrella header "Pods-ReusableDemo tvOS-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS/Reusable.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
8 | OTHER_LDFLAGS = $(inherited) -framework "Reusable" -framework "UIKit"
9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
10 | PODS_BUILD_DIR = ${BUILD_DIR}
11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
13 | PODS_ROOT = ${SRCROOT}/Pods
14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
16 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.1.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Reusable_iOS : NSObject
3 | @end
4 | @implementation PodsDummy_Reusable_iOS
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double ReusableVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char ReusableVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_LDFLAGS = $(inherited) -framework "UIKit"
6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
7 | PODS_BUILD_DIR = ${BUILD_DIR}
8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Reusable {
2 | umbrella header "Reusable-iOS-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_LDFLAGS = $(inherited) -framework "UIKit"
6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
7 | PODS_BUILD_DIR = ${BUILD_DIR}
8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-iOS/Reusable-iOS.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Reusable-iOS
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_LDFLAGS = $(inherited) -framework "UIKit"
4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
5 | PODS_BUILD_DIR = ${BUILD_DIR}
6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
12 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/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 | 4.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS-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 | 4.1.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Reusable_tvOS : NSObject
3 | @end
4 | @implementation PodsDummy_Reusable_tvOS
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double ReusableVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char ReusableVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_LDFLAGS = $(inherited) -framework "UIKit"
6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
7 | PODS_BUILD_DIR = ${BUILD_DIR}
8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Reusable {
2 | umbrella header "Reusable-tvOS-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_LDFLAGS = $(inherited) -framework "UIKit"
6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
7 | PODS_BUILD_DIR = ${BUILD_DIR}
8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Reusable-tvOS/Reusable-tvOS.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Reusable-tvOS
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_LDFLAGS = $(inherited) -framework "UIKit"
4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
5 | PODS_BUILD_DIR = ${BUILD_DIR}
6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
12 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | func application(_ application: UIApplication,
17 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 | }
22 |
23 | // Swift < 4.2 support
24 | #if !(swift(>=4.2))
25 | extension UIApplication {
26 | typealias LaunchOptionsKey = UIApplicationLaunchOptionsKey
27 | }
28 | #endif
29 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-120.png
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-152.png
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-167.png
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-180.png
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-76.png
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/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 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "AppIcon-120.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "60x60",
41 | "idiom" : "iphone",
42 | "filename" : "AppIcon-180.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "idiom" : "ipad",
47 | "size" : "20x20",
48 | "scale" : "1x"
49 | },
50 | {
51 | "idiom" : "ipad",
52 | "size" : "20x20",
53 | "scale" : "2x"
54 | },
55 | {
56 | "idiom" : "ipad",
57 | "size" : "29x29",
58 | "scale" : "1x"
59 | },
60 | {
61 | "idiom" : "ipad",
62 | "size" : "29x29",
63 | "scale" : "2x"
64 | },
65 | {
66 | "idiom" : "ipad",
67 | "size" : "40x40",
68 | "scale" : "1x"
69 | },
70 | {
71 | "idiom" : "ipad",
72 | "size" : "40x40",
73 | "scale" : "2x"
74 | },
75 | {
76 | "size" : "76x76",
77 | "idiom" : "ipad",
78 | "filename" : "AppIcon-76.png",
79 | "scale" : "1x"
80 | },
81 | {
82 | "size" : "76x76",
83 | "idiom" : "ipad",
84 | "filename" : "AppIcon-152.png",
85 | "scale" : "2x"
86 | },
87 | {
88 | "size" : "83.5x83.5",
89 | "idiom" : "ipad",
90 | "filename" : "AppIcon-167.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "1024x1024",
95 | "idiom" : "ios-marketing",
96 | "filename" : "Logo.png",
97 | "scale" : "1x"
98 | }
99 | ],
100 | "info" : {
101 | "version" : 1,
102 | "author" : "xcode"
103 | }
104 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo iOS/Assets.xcassets/AppIcon.appiconset/Logo.png
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/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 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewCells/CollectionHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionHeaderView.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 20/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is loaded from a NIB, and is the XIB file's
14 | * root view (and not the File's Owner). => it is `NibLoadable`
15 | *
16 | * It is also reusable and has a `reuseIdentifier` (as it's a CollectionViewCell
17 | * and it uses the CollectionView recycling mechanism) => it is `Reusable`
18 | *
19 | * That's why it's annotated with the `NibReusable` protocol,
20 | * Which in fact is just a convenience typealias that combines
21 | * `NibLoadable` & `Reusable` protocols.
22 | */
23 | final class CollectionHeaderView: UICollectionReusableView, NibReusable {
24 | @IBOutlet private weak var titleLabel: UILabel! {
25 | didSet { update() }
26 | }
27 | var title: String? {
28 | didSet { update() }
29 | }
30 | private func update() {
31 | titleLabel?.text = title
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewCells/CollectionHeaderView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewCells/MyColorSquareCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyColorSquareCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is reusable and has a `reuseIdentifier` (as it's a CollectionViewCell
14 | * and it uses the Collectioniew recycling mechanism).
15 | *
16 | * That's why it's annotated with the `Reusable` protocol.
17 | *
18 | * This view is NOT loaded from a NIB (but defined entierly by code),
19 | * that's why it's not annotated as `NibLoadable` but only `Reusable`
20 | */
21 | final class MyColorSquareCell: UICollectionViewCell, Reusable {
22 | private lazy var colorView: UIView = {
23 | let colorView = UIView()
24 | colorView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
25 | colorView.frame = self.contentView.bounds.insetBy(dx: 10, dy: 10)
26 | self.contentView.addSubview(colorView)
27 | return colorView
28 | }()
29 |
30 | func fill(_ color: UIColor) {
31 | self.colorView.backgroundColor = color
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewCells/MyStoryboardTextSquareCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyStoryboardTextSquareCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This one can be either `NibReusable` or just `Reusable` it doesn't really matter,
14 | * as we will never have to explicitly call `collectionView.register(…)` to register it:
15 | * The `Main.storyboard` already auto-registers its cells without the need for additional code
16 | *
17 | * The only difference in marking a view `NibReusable` vs. `Reusable` is the way
18 | * `registerCell` is implemented, and as we won't need to call that method anyway
19 | * because the storyboard will register the cell for us, this makes no difference here.
20 | */
21 | final class MyStoryboardTextSquareCell: UICollectionViewCell, Reusable {
22 | @IBOutlet private weak var titleLabel: UILabel!
23 | func fill(_ text: String) {
24 | titleLabel.text = text
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewCells/MyXIBIndexSquaceCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyXIBIndexSquaceCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is loaded from a NIB, and is the XIB file's
14 | * root view (and not the File's Owner). => it is `NibLoadable`
15 | *
16 | * It is also reusable and has a `reuseIdentifier` (as it's a CollectionViewCell
17 | * and it uses the CollectionView recycling mechanism) => it is `Reusable`
18 | *
19 | * That's why it's annotated with the `NibReusable` protocol,
20 | * Which in fact is just a typealias that combines
21 | * `NibLoadable` & `Reusable` protocols.
22 | */
23 | final class MyXIBIndexSquaceCell: UICollectionViewCell, NibReusable {
24 | @IBOutlet private weak var sectionLabel: UILabel!
25 | @IBOutlet private weak var rowLabel: UILabel!
26 |
27 | func fill(_ indexPath: IndexPath) {
28 | sectionLabel.text = String(indexPath.section)
29 | rowLabel.text = String(indexPath.row)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewCells/MyXIBIndexSquaceCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CollectionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewController.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class CollectionViewController: UICollectionViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | guard let collectionView = self.collectionView else { return }
16 |
17 | // Register cell classes
18 | collectionView.register(cellType: MyColorSquareCell.self)
19 | collectionView.register(cellType: MyXIBIndexSquaceCell.self)
20 | // No need to register this one, the UIStoryboard already auto-register its cells
21 | // self.collectionView.registerReusableCell(MyStoryBoardIndexPathCell)
22 |
23 | collectionView.register(supplementaryViewType: CollectionHeaderView.self,
24 | ofKind: UICollectionView.elementKindSectionHeader)
25 |
26 | if let flowLayout = self.collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
27 | flowLayout.headerReferenceSize = CGSize(width: collectionView.bounds.size.width, height: 60)
28 | }
29 | }
30 |
31 | // MARK: UICollectionViewDataSource
32 |
33 | override func numberOfSections(in collectionView: UICollectionView) -> Int {
34 | return 3
35 | }
36 |
37 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
38 | return 5
39 | }
40 |
41 | override func collectionView(_ collectionView: UICollectionView,
42 | viewForSupplementaryElementOfKind kind: String,
43 | at indexPath: IndexPath) -> UICollectionReusableView {
44 | let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, for: indexPath) as CollectionHeaderView
45 | header.title = "Section \(indexPath.section)"
46 | return header
47 | }
48 |
49 | override func collectionView(_ collectionView: UICollectionView,
50 | cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
51 | switch indexPath.section {
52 | case 0:
53 | let cell = collectionView.dequeueReusableCell(for: indexPath) as MyColorSquareCell
54 | let red = CGFloat(indexPath.row) / CGFloat(collectionView.numberOfItems(inSection: indexPath.section))
55 | cell.fill(UIColor(red: red, green: 0.0, blue: 1.0-red, alpha: 1.0))
56 | return cell
57 | case 1:
58 | let cell = collectionView.dequeueReusableCell(for: indexPath) as MyStoryboardTextSquareCell
59 | cell.fill("Item #\(indexPath.row)")
60 | return cell
61 | case 2:
62 | let cell = collectionView.dequeueReusableCell(for: indexPath) as MyXIBIndexSquaceCell
63 | cell.fill(indexPath)
64 | return cell
65 | default:
66 | fatalError("Out of bounds, should not happen")
67 | }
68 | }
69 | }
70 |
71 | // Swift < 4.2 support
72 | #if !(swift(>=4.2))
73 | private extension UICollectionView {
74 | static let elementKindSectionHeader = UICollectionElementKindSectionHeader
75 | }
76 | #endif
77 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CustomViews/MyCustomWidget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyCustomWidget.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier HALLIGON on 18/08/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | class MyCustomWidget: UIView, NibOwnerLoadable {
13 | @IBInspectable var rectColor: UIColor? {
14 | didSet {
15 | self.rectView.backgroundColor = self.rectColor
16 | }
17 | }
18 | @IBInspectable var text: String? {
19 | didSet {
20 | self.textLabel.text = self.text
21 | }
22 | }
23 |
24 | @IBOutlet private var rectView: UIView!
25 | @IBOutlet private var textLabel: UILabel!
26 |
27 | required init?(coder aDecoder: NSCoder) {
28 | super.init(coder: aDecoder)
29 | self.loadNibContent()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/CustomViews/MyCustomWidget.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
29 |
30 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Storyboards/InfoDetailViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InfoDetailViewController.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 10/07/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | final class InfoDetailViewController: UIViewController, StoryboardSceneBased {
13 | static let sceneStoryboard = UIStoryboard(name: "InfoViewController", bundle: nil)
14 |
15 | @IBOutlet private weak var detailsLabel: UILabel!
16 | private var detailsText: String?
17 |
18 | func setDetails(_ text: String) {
19 | detailsText = text
20 | detailsLabel?.text = text
21 | }
22 |
23 | override func viewDidLoad() {
24 | super.viewDidLoad()
25 | detailsLabel.text = detailsText
26 | }
27 |
28 | @IBAction func closeAction(_ sender: UIButton) {
29 | self.presentingViewController?.dismiss(animated: true, completion: nil)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Storyboards/InfoViewController.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 |
31 |
38 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
82 |
88 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/Storyboards/InfoViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InfoViewController.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 10/07/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | final class InfoViewController: UIViewController, StoryboardBased {
13 | @IBOutlet private weak var infoLabel: UILabel!
14 | private var infoText: String?
15 |
16 | func setInfo(_ text: String) {
17 | infoText = text
18 | infoLabel?.text = text
19 | }
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 | infoLabel.text = infoText
24 | }
25 |
26 | @IBAction func closeAction(_ sender: UIButton) {
27 | self.presentingViewController?.dismiss(animated: true, completion: nil)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyHeaderTableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyHeaderTableViex.swift
3 | // ReusableDemo
4 | //
5 | // Created by Allan Vialatte on 29/05/16.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is loaded from a NIB, and is used as the File's Owner
14 | * of the XIB file (and not set as the XIB's root view)
15 | *
16 | * That's why it's annotated with the `NibOwnerLoadable` protocol.
17 | */
18 | final class MyHeaderTableView: UIView, NibOwnerLoadable {
19 |
20 | @IBOutlet private weak var titleLabel: UILabel!
21 | static let height: CGFloat = 55
22 |
23 | override init(frame: CGRect) {
24 | super.init(frame: frame)
25 | self.loadNibContent()
26 | }
27 |
28 | required init?(coder aDecoder: NSCoder) {
29 | super.init(coder: aDecoder)
30 | }
31 |
32 | func fillForSection(_ section: Int) {
33 | self.titleLabel.text = "Header Section #\(section)"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyHeaderTableView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MySimpleColorCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MySimpleColorCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is reusable and has a `reuseIdentifier` (as it's a TableViewCell
14 | * and it uses the TableView recycling mechanism).
15 | *
16 | * That's why it's annotated with the `Reusable` protocol.
17 | *
18 | * This view is NOT loaded from a NIB (but defined entierly by code),
19 | * that's why it's not annotated as `NibLoadable` but only `Reusable`
20 | */
21 | final class MySimpleColorCell: UITableViewCell, Reusable {
22 | private lazy var colorView: UIView = {
23 | let colorView = UIView()
24 | colorView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
25 | colorView.frame = self.contentView.bounds.insetBy(dx: 50, dy: 5)
26 | self.contentView.addSubview(colorView)
27 | return colorView
28 | }()
29 |
30 | func fill(_ color: UIColor) {
31 | self.colorView.backgroundColor = color
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyStoryBoardIndexPathCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyStoryBoardIndexPathCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | // This one can be either `NibReusable` or just `Reusable` it doesn't matter actually
13 | // As we will never have to explicitly call `tableView.register(…)` to register it:
14 | // The Main.storyboard already auto-registers its cells without the need for additional code
15 |
16 | final class MyStoryBoardIndexPathCell: UITableViewCell, Reusable {
17 | @IBOutlet private weak var sectionLabel: UILabel!
18 | @IBOutlet private weak var rowLabel: UILabel!
19 |
20 | func fill(_ indexPath: IndexPath) {
21 | sectionLabel.text = String(indexPath.section)
22 | rowLabel.text = String(indexPath.row)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyXIBInfoCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyXIBSwitchCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is loaded from a NIB, and is the XIB file's
14 | * root view (and not the File's Owner). => it is `NibLoadable`
15 | *
16 | * It is also reusable and has a `reuseIdentifier` (as it's a TableViewCell
17 | * and it uses the TableView recycling mechanism) => it is `Reusable`
18 | *
19 | * That's why it's annotated with the `NibReusable` typealias,
20 | * Which in fact is just a convenience typealias that combines
21 | * `NibLoadable` & `Reusable` protocols.
22 | */
23 | final class MyXIBInfoCell: UITableViewCell, NibReusable {
24 |
25 | @IBOutlet private weak var titleLabel: UILabel!
26 | private var info: String = ""
27 | private var details: String = ""
28 |
29 | func fill(_ title: String, info: String, details: String) {
30 | self.titleLabel.text = title
31 | self.info = info
32 | self.details = details
33 | }
34 |
35 | @IBAction func infoAction(_ sender: UIButton) {
36 | let infoVC = InfoViewController.instantiate()
37 | infoVC.setInfo(self.info)
38 | self.window?.rootViewController?.present(infoVC, animated: true, completion: nil)
39 | }
40 |
41 | @IBAction func detailsAction(_ sender: UIButton) {
42 | let detailsVC = InfoDetailViewController.instantiate()
43 | detailsVC.setDetails(self.details)
44 | self.window?.rootViewController?.present(detailsVC, animated: true, completion: nil)
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyXIBInfoCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
28 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyXIBTextCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyXIBTextCell.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | /**
13 | * This view is loaded from a NIB, and is the XIB file's
14 | * root view (and not the File's Owner). => it is `NibLoadable`
15 | *
16 | * It is also reusable and has a `reuseIdentifier` (as it's a TableViewCell
17 | * and it uses the TableView recycling mechanism) => it is `Reusable`
18 | *
19 | * That's why it's annotated with the `NibReusable` typealias,
20 | * Which in fact is just a convenience typealias that combines
21 | * `NibLoadable` & `Reusable` protocols.
22 | */
23 | final class MyXIBTextCell: UITableViewCell, NibReusable {
24 |
25 | @IBOutlet private weak var titleLabel: UILabel!
26 |
27 | func fill(_ text: String) {
28 | titleLabel.text = text
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewCells/MyXIBTextCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Example/ReusableDemo iOS/TableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier Halligon on 19/01/2016.
6 | // Copyright © 2016 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class TableViewController: UITableViewController {
12 | var boolValues = [false, false]
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 |
17 | tableView.register(cellType: MySimpleColorCell.self)
18 | tableView.register(cellType: MyXIBTextCell.self)
19 | tableView.register(cellType: MyXIBInfoCell.self)
20 |
21 | /* No need to register this one, the UIStoryboard already auto-register its cells */
22 | // tableView.registerReusableCell(MyStoryBoardIndexPathCell)
23 | }
24 |
25 | override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
26 | return MyHeaderTableView.height
27 | }
28 |
29 | override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
30 | let frame = CGRect(
31 | x: 0,
32 | y: 0,
33 | width: tableView.bounds.size.width,
34 | height: self.tableView(tableView, heightForHeaderInSection: section)
35 | )
36 | // See the overridden `MyHeaderTableView.init(frame:)` initializer, which
37 | // automatically loads the view content from its nib using loadNibContent()
38 | let view = MyHeaderTableView(frame: frame)
39 |
40 | view.fillForSection(section)
41 | return view
42 | }
43 |
44 | override func numberOfSections(in tableView: UITableView) -> Int {
45 | return 4
46 | }
47 |
48 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
49 | return 2
50 | }
51 |
52 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
53 | switch indexPath.section {
54 | case 0:
55 | let colorCell = tableView.dequeueReusableCell(for: indexPath) as MySimpleColorCell
56 | let redComp: CGFloat = indexPath.row == 0 ? 1.0 : 0.0
57 | colorCell.fill(UIColor(red: redComp, green: 0.0, blue: 1-redComp, alpha: 1.0))
58 | return colorCell
59 | case 1:
60 | let textCell = tableView.dequeueReusableCell(for: indexPath) as MyXIBTextCell
61 | textCell.fill("{section \(indexPath.section), row \(indexPath.row)}")
62 | return textCell
63 | case 2:
64 | let infoCell = tableView.dequeueReusableCell(for: indexPath) as MyXIBInfoCell
65 | infoCell.fill("InfoCell #\(indexPath.row)", info: "Info #\(indexPath.row)", details: "Details #\(indexPath.row)")
66 | return infoCell
67 | case 3:
68 | let pathCell = tableView.dequeueReusableCell(for: indexPath) as MyStoryBoardIndexPathCell
69 | pathCell.fill(indexPath)
70 | return pathCell
71 | default:
72 | fatalError("Out of bounds, should not happen")
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ReusableDemo tvOS
4 | //
5 | // Created by Olivier HALLIGON on 16/02/2017.
6 | // Copyright © 2017 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | func application(_ application: UIApplication,
17 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 | }
22 |
23 | // Swift < 4.2 support
24 | #if !(swift(>=4.2))
25 | extension UIApplication {
26 | typealias LaunchOptionsKey = UIApplicationLaunchOptionsKey
27 | }
28 | #endif
29 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/AppleTV.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/AppleTV.png
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppleTV.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "tv",
10 | "scale" : "2x"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers" : [
3 | {
4 | "filename" : "Front.imagestacklayer"
5 | },
6 | {
7 | "filename" : "Middle.imagestacklayer"
8 | },
9 | {
10 | "filename" : "Back.imagestacklayer"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/AppleTV.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/AppleTV.png
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppleTV.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "tv",
10 | "scale" : "2x"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/AppleTV.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/AppleTV.png
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppleTV.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "tv",
10 | "scale" : "2x"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "layers" : [
3 | {
4 | "filename" : "Front.imagestacklayer"
5 | },
6 | {
7 | "filename" : "Middle.imagestacklayer"
8 | },
9 | {
10 | "filename" : "Back.imagestacklayer"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/AppleTV-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/AppleTV-small.png
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppleTV-small.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "tv",
10 | "scale" : "2x"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/AppleTV-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/AppleTV-small.png
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppleTV-small.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "tv",
10 | "scale" : "2x"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "assets" : [
3 | {
4 | "size" : "1280x768",
5 | "idiom" : "tv",
6 | "filename" : "App Icon - Large.imagestack",
7 | "role" : "primary-app-icon"
8 | },
9 | {
10 | "size" : "400x240",
11 | "idiom" : "tv",
12 | "filename" : "App Icon - Small.imagestack",
13 | "role" : "primary-app-icon"
14 | },
15 | {
16 | "size" : "2320x720",
17 | "idiom" : "tv",
18 | "filename" : "Top Shelf Image Wide.imageset",
19 | "role" : "top-shelf-image-wide"
20 | },
21 | {
22 | "size" : "1920x720",
23 | "idiom" : "tv",
24 | "filename" : "Top Shelf Image.imageset",
25 | "role" : "top-shelf-image"
26 | }
27 | ],
28 | "info" : {
29 | "version" : 1,
30 | "author" : "xcode"
31 | }
32 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "tv",
6 | "minimum-system-version" : "11.0",
7 | "orientation" : "landscape",
8 | "scale" : "2x"
9 | },
10 | {
11 | "extent" : "full-screen",
12 | "idiom" : "tv",
13 | "minimum-system-version" : "9.0",
14 | "orientation" : "landscape",
15 | "scale" : "1x"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/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 | UIMainStoryboardFile
24 | Main
25 | UIRequiredDeviceCapabilities
26 |
27 | arm64
28 |
29 | UIUserInterfaceStyle
30 | Automatic
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/MyCustomWidget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyCustomWidget.swift
3 | // ReusableDemo
4 | //
5 | // Created by Olivier HALLIGON on 16/02/2017.
6 | // Copyright © 2017 AliSoftware. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Reusable
11 |
12 | class MyCustomWidget: UIView, NibOwnerLoadable {
13 | @IBInspectable var rectColor: UIColor? {
14 | didSet {
15 | self.rectView.backgroundColor = self.rectColor
16 | }
17 | }
18 | @IBInspectable var text: String? {
19 | didSet {
20 | self.textLabel.text = self.text
21 | }
22 | }
23 |
24 | @IBOutlet private var rectView: UIView!
25 | @IBOutlet private var textLabel: UILabel!
26 |
27 | required init?(coder aDecoder: NSCoder) {
28 | super.init(coder: aDecoder)
29 | self.loadNibContent()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Example/ReusableDemo tvOS/MyCustomWidget.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Example/ReusableDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/ReusableDemo.xcodeproj/xcshareddata/xcschemes/ReusableDemo iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Example/ReusableDemo.xcodeproj/xcshareddata/xcschemes/ReusableDemo tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Example/ReusableDemo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
9 |
10 |
12 |
13 |
15 |
16 |
17 |
19 |
20 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Example/ReusableDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/ReusableDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | # The bare minimum for building, e.g. in Homebrew
6 | group :build do
7 | gem 'rake', '~> 12.3'
8 | gem 'xcpretty'
9 | end
10 |
11 | # In addition to :build, for contributing
12 | group :development do
13 | gem 'cocoapods', '~> 1.8'
14 | end
15 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.3)
5 | activesupport (6.1.4.1)
6 | concurrent-ruby (~> 1.0, >= 1.0.2)
7 | i18n (>= 1.6, < 2)
8 | minitest (>= 5.1)
9 | tzinfo (~> 2.0)
10 | zeitwerk (~> 2.3)
11 | addressable (2.8.0)
12 | public_suffix (>= 2.0.2, < 5.0)
13 | algoliasearch (1.27.5)
14 | httpclient (~> 2.8, >= 2.8.3)
15 | json (>= 1.5.1)
16 | atomos (0.1.3)
17 | claide (1.0.3)
18 | cocoapods (1.11.0)
19 | addressable (~> 2.8)
20 | claide (>= 1.0.2, < 2.0)
21 | cocoapods-core (= 1.11.0)
22 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
23 | cocoapods-downloader (>= 1.4.0, < 2.0)
24 | cocoapods-plugins (>= 1.0.0, < 2.0)
25 | cocoapods-search (>= 1.0.0, < 2.0)
26 | cocoapods-trunk (>= 1.4.0, < 2.0)
27 | cocoapods-try (>= 1.1.0, < 2.0)
28 | colored2 (~> 3.1)
29 | escape (~> 0.0.4)
30 | fourflusher (>= 2.3.0, < 3.0)
31 | gh_inspector (~> 1.0)
32 | molinillo (~> 0.8.0)
33 | nap (~> 1.0)
34 | ruby-macho (>= 1.0, < 3.0)
35 | xcodeproj (>= 1.21.0, < 2.0)
36 | cocoapods-core (1.11.0)
37 | activesupport (>= 5.0, < 7)
38 | addressable (~> 2.8)
39 | algoliasearch (~> 1.0)
40 | concurrent-ruby (~> 1.1)
41 | fuzzy_match (~> 2.0.4)
42 | nap (~> 1.0)
43 | netrc (~> 0.11)
44 | public_suffix (~> 4.0)
45 | typhoeus (~> 1.0)
46 | cocoapods-deintegrate (1.0.5)
47 | cocoapods-downloader (1.5.1)
48 | cocoapods-plugins (1.0.0)
49 | nap
50 | cocoapods-search (1.0.1)
51 | cocoapods-trunk (1.6.0)
52 | nap (>= 0.8, < 2.0)
53 | netrc (~> 0.11)
54 | cocoapods-try (1.2.0)
55 | colored2 (3.1.2)
56 | concurrent-ruby (1.1.9)
57 | escape (0.0.4)
58 | ethon (0.14.0)
59 | ffi (>= 1.15.0)
60 | ffi (1.15.4)
61 | fourflusher (2.3.1)
62 | fuzzy_match (2.0.4)
63 | gh_inspector (1.1.3)
64 | httpclient (2.8.3)
65 | i18n (1.8.10)
66 | concurrent-ruby (~> 1.0)
67 | json (2.5.1)
68 | minitest (5.14.4)
69 | molinillo (0.8.0)
70 | nanaimo (0.3.0)
71 | nap (1.1.0)
72 | netrc (0.11.0)
73 | public_suffix (4.0.6)
74 | rake (12.3.3)
75 | rexml (3.2.5)
76 | rouge (2.0.7)
77 | ruby-macho (2.5.1)
78 | typhoeus (1.4.0)
79 | ethon (>= 0.9.0)
80 | tzinfo (2.0.4)
81 | concurrent-ruby (~> 1.0)
82 | xcodeproj (1.21.0)
83 | CFPropertyList (>= 2.3.3, < 4.0)
84 | atomos (~> 0.1.3)
85 | claide (>= 1.0.2, < 2.0)
86 | colored2 (~> 3.1)
87 | nanaimo (~> 0.3.0)
88 | rexml (~> 3.2.4)
89 | xcpretty (0.3.0)
90 | rouge (~> 2.0.7)
91 | zeitwerk (2.4.2)
92 |
93 | PLATFORMS
94 | ruby
95 |
96 | DEPENDENCIES
97 | cocoapods (~> 1.8)
98 | rake (~> 12.3)
99 | xcpretty
100 |
101 | BUNDLED WITH
102 | 2.2.25
103 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 AliSoftware
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 |
--------------------------------------------------------------------------------
/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Logo.png
--------------------------------------------------------------------------------
/Logo.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/Logo.xcf
--------------------------------------------------------------------------------
/NibOwnerLoadable-InStoryboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/NibOwnerLoadable-InStoryboard.png
--------------------------------------------------------------------------------
/NibOwnerLoadable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AliSoftware/Reusable/85e8ef7b2441433ffed2fc8cf4942961b70a83f6/NibOwnerLoadable.png
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.4
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "Reusable",
6 | platforms: [.iOS(.v9), .tvOS(.v9)],
7 | products: [
8 | .library(name: "Reusable", targets: ["Reusable"])
9 | ],
10 | targets: [
11 | .target(
12 | name: "Reusable",
13 | path: "Sources"
14 | )
15 | ],
16 | swiftLanguageVersions: [.v4, .v5]
17 | )
18 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/rake
2 |
3 | DESTINATIONS = {
4 | :ios_sim => "OS=14.5,name=iPhone 11,platform=iOS Simulator",
5 | :tvos_sim => "OS=14.5,name=Apple TV,platform=tvOS Simulator",
6 | }
7 |
8 | CARTHAGE_VERSION = '0.38.0'
9 | SWIFTLINT_VERSION = '0.44.0'
10 |
11 | ## UTILS ##
12 |
13 | def run(command, xcpretty: true)
14 | if xcpretty && system('xcpretty --version >/dev/null')
15 | sh "set -o pipefail && #{command} | xcpretty -c"
16 | else
17 | sh command
18 | end
19 | end
20 |
21 | def xcodebuild(scheme: '', sdk: '', destination: '', action: 'build')
22 | run %Q(xcodebuild -workspace Example/ReusableDemo.xcworkspace -scheme "#{scheme}" -sdk #{sdk} -destination="#{destination}" ONLY_ACTIVE_ARCH=NO #{action})
23 | end
24 |
25 | def install_pkg(pkg_url)
26 | require 'tmpdir'
27 | Dir.mktmpdir do |dir|
28 | tmppath = File.join(dir, File.basename(pkg_url))
29 | sh("curl -Lo #{tmppath} #{pkg_url}")
30 | sh("sudo installer -pkg #{tmppath} -target /")
31 | end
32 | end
33 |
34 | ## TASKS ##
35 |
36 | namespace :carthage do
37 | desc "Install Carthage from pkg"
38 | task :install do
39 | next if system('which carthage >/dev/null') && Gem::Version.new(`carthage version`.chomp) >= Gem::Version.new(CARTHAGE_VERSION)
40 | install_pkg("https://github.com/Carthage/Carthage/releases/download/#{CARTHAGE_VERSION}/Carthage.pkg")
41 | end
42 |
43 | desc "Builds the Reusable framework using Carthage"
44 | task :build => :install do
45 | run "carthage build --no-skip-current --use-xcframeworks --verbose"
46 | end
47 | end
48 |
49 | namespace :demo do
50 | desc "Builds the ReusableDemo app for iOS using xcodebuild."
51 | task :ios do |t, args|
52 | xcodebuild(scheme: 'ReusableDemo iOS', sdk: 'iphonesimulator', destination: DESTINATIONS[:ios_sim])
53 | end
54 |
55 | desc "Builds the ReusableDemo app for tvOS using xcodebuild."
56 | task :tvos do |t, args|
57 | xcodebuild(scheme: 'ReusableDemo tvOS', sdk: 'appletvsimulator', destination: DESTINATIONS[:tvos_sim])
58 | end
59 | end
60 |
61 | namespace :fmk do
62 | desc "Builds the Reusable framework for iOS using xcodebuild."
63 | task :ios do |t, args|
64 | xcodebuild(scheme: 'Reusable-iOS', sdk: 'iphonesimulator', destination: DESTINATIONS[:ios_sim])
65 | end
66 |
67 | desc "Builds the Reusable framework for tvOS using xcodebuild."
68 | task :tvos do |t, args|
69 | xcodebuild(scheme: 'Reusable-tvOS', sdk: 'appletvsimulator', destination: DESTINATIONS[:tvos_sim])
70 | end
71 | end
72 |
73 | namespace :pod do
74 | desc "Lints the Reusable.podspec"
75 | task :lint do |t|
76 | run("pod lib lint --allow-warnings --quick", xcpretty: false)
77 | end
78 | end
79 |
80 | namespace :spm do
81 | desc 'Build using SPM'
82 | task :build do |task|
83 | puts '*** Compile using SPM ***'
84 | sh 'xcrun swift build'
85 | end
86 | end
87 |
88 | namespace :swiftlint do
89 | desc "Install SwiftLint from pkg"
90 | task :install do
91 | next if system('which swiftlint >/dev/null') && Gem::Version.new(`swiftlint version`.chomp) >= Gem::Version.new(SWIFTLINT_VERSION)
92 | install_pkg("https://github.com/realm/SwiftLint/releases/download/#{SWIFTLINT_VERSION}/SwiftLint.pkg")
93 | end
94 |
95 | desc "Run SwiftLint on the source code"
96 | task :run => :install do
97 | run('swiftlint lint --strict', xcpretty: false)
98 | end
99 | end
100 |
101 | # TODO: "namespace :test" once we have Unit Tests
102 |
--------------------------------------------------------------------------------
/Reusable.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.cocoapods_version = '~> 1.4'
3 |
4 | s.name = "Reusable"
5 | s.version = "4.1.2"
6 | s.summary = "A Swift Mixin to deal with reusable UITableView & UICollectionView cells and XIB-based views"
7 |
8 | s.description = <<-DESC
9 | Reusable is a [Swift Mixin](http://alisoftware.github.io/swift/protocol/2015/11/08/mixins-over-inheritance/)
10 | to easily deal with your reusable UITableViewCell and UICollectionViewCell classes.
11 |
12 | Simply mark your `UITableViewCell` or `UICollectionViewCell` sublcasses as
13 | conforming to either `Reusable` or `NibReusable` and you'll be able to
14 | manipulate them way easier, and without worrying with String-type reuseIdentifiers
15 | ever again, and instead use them in a type-safe manner!
16 |
17 | Reusable also support marking any arbitrary `UIView` subclass as `NibLoadable` so that
18 | you can then call `loadFromNib()` on the custom view class easily without adding any code.
19 |
20 | For more info, see [my blog post](http://alisoftware.github.io/swift/generics/2016/01/06/generic-tableviewcells/)
21 | about this technique.
22 | DESC
23 |
24 | s.homepage = "https://github.com/AliSoftware/Reusable"
25 | s.license = { :type => "MIT", :file => "LICENSE" }
26 |
27 |
28 | s.author = { "Olivier Halligon" => "olivier@halligon.net" }
29 | s.social_media_url = "http://twitter.com/aligatr"
30 |
31 | s.ios.deployment_target = "9.0"
32 | s.tvos.deployment_target = "9.0"
33 |
34 | s.source = { :git => "https://github.com/AliSoftware/Reusable.git", :tag => s.version.to_s }
35 | s.swift_version = '5.0'
36 |
37 | s.subspec 'View' do |ss|
38 | ss.source_files = "Sources/View/*.swift"
39 | end
40 | s.subspec 'Storyboard' do |ss|
41 | ss.source_files = "Sources/Storyboard/*.swift"
42 | end
43 |
44 | s.framework = "UIKit"
45 |
46 | end
47 |
--------------------------------------------------------------------------------
/Sources/Storyboard/StoryboardBased.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Protocol Definition
13 |
14 | /// Make your UIViewController subclasses conform to this protocol when:
15 | /// * they *are* Storyboard-based, and
16 | /// * this ViewController is the initialViewController of your Storyboard
17 | ///
18 | /// to be able to instantiate them from the Storyboard in a type-safe manner
19 | public protocol StoryboardBased: AnyObject {
20 | /// The UIStoryboard to use when we want to instantiate this ViewController
21 | static var sceneStoryboard: UIStoryboard { get }
22 | }
23 |
24 | // MARK: Default Implementation
25 |
26 | public extension StoryboardBased {
27 | /// By default, use the storybaord with the same name as the class
28 | static var sceneStoryboard: UIStoryboard {
29 | return UIStoryboard(name: String(describing: self), bundle: Bundle(for: self))
30 | }
31 | }
32 |
33 | // MARK: Support for instantiation from Storyboard
34 |
35 | public extension StoryboardBased where Self: UIViewController {
36 | /**
37 | Create an instance of the ViewController from its associated Storyboard's initialViewController
38 |
39 | - returns: instance of the conforming ViewController
40 | */
41 | static func instantiate() -> Self {
42 | let viewController = sceneStoryboard.instantiateInitialViewController()
43 | guard let typedViewController = viewController as? Self else {
44 | fatalError("The initialViewController of '\(sceneStoryboard)' is not of class '\(self)'")
45 | }
46 | return typedViewController
47 | }
48 | }
49 | #endif
50 |
--------------------------------------------------------------------------------
/Sources/Storyboard/StoryboardSceneBased.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Protocol Definition
13 |
14 | /// Make your UIViewController subclasses conform to this protocol when:
15 | /// * they *are* Storyboard-based, and
16 | /// * this ViewController is not the initialViewController of your Storyboard, but a different scene
17 | ///
18 | /// to be able to instantiate them from the Storyboard in a type-safe manner.
19 | ///
20 | /// You need to implement `sceneStoryboard` yourself to indicate the UIStoryboard this scene is from.
21 | public protocol StoryboardSceneBased: AnyObject {
22 | /// The UIStoryboard to use when we want to instantiate this ViewController
23 | static var sceneStoryboard: UIStoryboard { get }
24 | /// The scene identifier to use when we want to instantiate this ViewController from its associated Storyboard
25 | static var sceneIdentifier: String { get }
26 | }
27 |
28 | // MARK: Default Implementation
29 |
30 | public extension StoryboardSceneBased {
31 | /// By default, use the `sceneIdentifier` with the same name as the class
32 | static var sceneIdentifier: String {
33 | return String(describing: self)
34 | }
35 | }
36 |
37 | // MARK: Support for instantiation from Storyboard
38 |
39 | public extension StoryboardSceneBased where Self: UIViewController {
40 | /**
41 | Create an instance of the ViewController from its associated Storyboard and the
42 | Scene with identifier `sceneIdentifier`
43 |
44 | - returns: instance of the conforming ViewController
45 | */
46 | static func instantiate() -> Self {
47 | let storyboard = Self.sceneStoryboard
48 | let viewController = storyboard.instantiateViewController(withIdentifier: self.sceneIdentifier)
49 | guard let typedViewController = viewController as? Self else {
50 | fatalError("The viewController '\(self.sceneIdentifier)' of '\(storyboard)' is not of class '\(self)'")
51 | }
52 | return typedViewController
53 | }
54 | }
55 | #endif
56 |
--------------------------------------------------------------------------------
/Sources/View/NibLoadable.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Protocol Definition
13 |
14 | /// Make your UIView subclasses conform to this protocol when:
15 | /// * they *are* NIB-based, and
16 | /// * this class is used as the XIB's root view
17 | ///
18 | /// to be able to instantiate them from the NIB in a type-safe manner
19 | public protocol NibLoadable: AnyObject {
20 | /// The nib file to use to load a new instance of the View designed in a XIB
21 | static var nib: UINib { get }
22 | }
23 |
24 | // MARK: Default implementation
25 |
26 | public extension NibLoadable {
27 | /// By default, use the nib which have the same name as the name of the class,
28 | /// and located in the bundle of that class
29 | static var nib: UINib {
30 | return UINib(nibName: String(describing: self), bundle: Bundle(for: self))
31 | }
32 | }
33 |
34 | // MARK: Support for instantiation from NIB
35 |
36 | public extension NibLoadable where Self: UIView {
37 | /**
38 | Returns a `UIView` object instantiated from nib
39 |
40 | - returns: A `NibLoadable`, `UIView` instance
41 | */
42 | static func loadFromNib() -> Self {
43 | guard let view = nib.instantiate(withOwner: nil, options: nil).first as? Self else {
44 | fatalError("The nib \(nib) expected its root view to be of type \(self)")
45 | }
46 | return view
47 | }
48 | }
49 | #endif
50 |
--------------------------------------------------------------------------------
/Sources/View/NibOwnerLoadable.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Protocol Definition
13 |
14 | /// Make your UIView subclasses conform to this protocol when:
15 | /// * they *are* NIB-based, and
16 | /// * this class is used as the XIB's File's Owner
17 | ///
18 | /// to be able to instantiate them from the NIB in a type-safe manner
19 | public protocol NibOwnerLoadable: AnyObject {
20 | /// The nib file to use to load a new instance of the View designed in a XIB
21 | static var nib: UINib { get }
22 | }
23 |
24 | // MARK: Default implementation
25 |
26 | public extension NibOwnerLoadable {
27 | /// By default, use the nib which have the same name as the name of the class,
28 | /// and located in the bundle of that class
29 | static var nib: UINib {
30 | return UINib(nibName: String(describing: self), bundle: Bundle(for: self))
31 | }
32 | }
33 |
34 | // MARK: Support for instantiation from NIB
35 |
36 | public extension NibOwnerLoadable where Self: UIView {
37 | /**
38 | Adds content loaded from the nib to the end of the receiver's list of subviews and adds constraints automatically.
39 | */
40 | func loadNibContent() {
41 | let layoutAttributes: [NSLayoutConstraint.Attribute] = [.top, .leading, .bottom, .trailing]
42 | for case let view as UIView in type(of: self).nib.instantiate(withOwner: self, options: nil) {
43 | view.translatesAutoresizingMaskIntoConstraints = false
44 | self.addSubview(view)
45 | NSLayoutConstraint.activate(layoutAttributes.map { attribute in
46 | NSLayoutConstraint(
47 | item: view, attribute: attribute,
48 | relatedBy: .equal,
49 | toItem: self, attribute: attribute,
50 | multiplier: 1, constant: 0.0
51 | )
52 | })
53 | }
54 | }
55 | }
56 | #endif
57 |
58 | /// Swift < 4.2 support
59 | #if !(swift(>=4.2))
60 | private extension NSLayoutConstraint {
61 | typealias Attribute = NSLayoutAttribute
62 | }
63 | #endif
64 |
--------------------------------------------------------------------------------
/Sources/View/Reusable.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Protocol definition
13 |
14 | /// Make your `UITableViewCell` and `UICollectionViewCell` subclasses
15 | /// conform to this protocol when they are *not* NIB-based but only code-based
16 | /// to be able to dequeue them in a type-safe manner
17 | public protocol Reusable: AnyObject {
18 | /// The reuse identifier to use when registering and later dequeuing a reusable cell
19 | static var reuseIdentifier: String { get }
20 | }
21 |
22 | /// Make your `UITableViewCell` and `UICollectionViewCell` subclasses
23 | /// conform to this typealias when they *are* NIB-based
24 | /// to be able to dequeue them in a type-safe manner
25 | public typealias NibReusable = Reusable & NibLoadable
26 |
27 | // MARK: - Default implementation
28 |
29 | public extension Reusable {
30 | /// By default, use the name of the class as String for its reuseIdentifier
31 | static var reuseIdentifier: String {
32 | return String(describing: self)
33 | }
34 | }
35 | #endif
36 |
--------------------------------------------------------------------------------
/Sources/View/UICollectionView+Reusable.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Reusable support for UICollectionView
13 |
14 | public extension UICollectionView {
15 | /**
16 | Register a NIB-Based `UICollectionViewCell` subclass (conforming to `Reusable` & `NibLoadable`)
17 |
18 | - parameter cellType: the `UICollectionViewCell` (`Reusable` & `NibLoadable`-conforming) subclass to register
19 |
20 | - seealso: `register(_:,forCellWithReuseIdentifier:)`
21 | */
22 | final func register(cellType: T.Type)
23 | where T: Reusable & NibLoadable {
24 | self.register(cellType.nib, forCellWithReuseIdentifier: cellType.reuseIdentifier)
25 | }
26 |
27 | /**
28 | Register a Class-Based `UICollectionViewCell` subclass (conforming to `Reusable`)
29 |
30 | - parameter cellType: the `UICollectionViewCell` (`Reusable`-conforming) subclass to register
31 |
32 | - seealso: `register(_:,forCellWithReuseIdentifier:)`
33 | */
34 | final func register(cellType: T.Type)
35 | where T: Reusable {
36 | self.register(cellType.self, forCellWithReuseIdentifier: cellType.reuseIdentifier)
37 | }
38 |
39 | /**
40 | Returns a reusable `UICollectionViewCell` object for the class inferred by the return-type
41 |
42 | - parameter indexPath: The index path specifying the location of the cell.
43 | - parameter cellType: The cell class to dequeue
44 |
45 | - returns: A `Reusable`, `UICollectionViewCell` instance
46 |
47 | - note: The `cellType` parameter can generally be omitted and infered by the return type,
48 | except when your type is in a variable and cannot be determined at compile time.
49 | - seealso: `dequeueReusableCell(withReuseIdentifier:,for:)`
50 | */
51 | final func dequeueReusableCell(for indexPath: IndexPath, cellType: T.Type = T.self) -> T
52 | where T: Reusable {
53 | let bareCell = self.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath)
54 | guard let cell = bareCell as? T else {
55 | fatalError(
56 | "Failed to dequeue a cell with identifier \(cellType.reuseIdentifier) matching type \(cellType.self). "
57 | + "Check that the reuseIdentifier is set properly in your XIB/Storyboard "
58 | + "and that you registered the cell beforehand"
59 | )
60 | }
61 | return cell
62 | }
63 |
64 | /**
65 | Register a NIB-Based `UICollectionReusableView` subclass (conforming to `Reusable` & `NibLoadable`)
66 | as a Supplementary View
67 |
68 | - parameter supplementaryViewType: the `UIView` (`Reusable` & `NibLoadable`-conforming) subclass
69 | to register as Supplementary View
70 | - parameter elementKind: The kind of supplementary view to create.
71 |
72 | - seealso: `register(_:,forSupplementaryViewOfKind:,withReuseIdentifier:)`
73 | */
74 | final func register(supplementaryViewType: T.Type, ofKind elementKind: String)
75 | where T: Reusable & NibLoadable {
76 | self.register(
77 | supplementaryViewType.nib,
78 | forSupplementaryViewOfKind: elementKind,
79 | withReuseIdentifier: supplementaryViewType.reuseIdentifier
80 | )
81 | }
82 |
83 | /**
84 | Register a Class-Based `UICollectionReusableView` subclass (conforming to `Reusable`) as a Supplementary View
85 |
86 | - parameter supplementaryViewType: the `UIView` (`Reusable`-conforming) subclass to register as Supplementary View
87 | - parameter elementKind: The kind of supplementary view to create.
88 |
89 | - seealso: `register(_:,forSupplementaryViewOfKind:,withReuseIdentifier:)`
90 | */
91 | final func register(supplementaryViewType: T.Type, ofKind elementKind: String)
92 | where T: Reusable {
93 | self.register(
94 | supplementaryViewType.self,
95 | forSupplementaryViewOfKind: elementKind,
96 | withReuseIdentifier: supplementaryViewType.reuseIdentifier
97 | )
98 | }
99 |
100 | /**
101 | Returns a reusable `UICollectionReusableView` object for the class inferred by the return-type
102 |
103 | - parameter elementKind: The kind of supplementary view to retrieve.
104 | - parameter indexPath: The index path specifying the location of the cell.
105 | - parameter viewType: The view class to dequeue
106 |
107 | - returns: A `Reusable`, `UICollectionReusableView` instance
108 |
109 | - note: The `viewType` parameter can generally be omitted and infered by the return type,
110 | except when your type is in a variable and cannot be determined at compile time.
111 | - seealso: `dequeueReusableSupplementaryView(ofKind:,withReuseIdentifier:,for:)`
112 | */
113 | final func dequeueReusableSupplementaryView
114 | (ofKind elementKind: String, for indexPath: IndexPath, viewType: T.Type = T.self) -> T
115 | where T: Reusable {
116 | let view = self.dequeueReusableSupplementaryView(
117 | ofKind: elementKind,
118 | withReuseIdentifier: viewType.reuseIdentifier,
119 | for: indexPath
120 | )
121 | guard let typedView = view as? T else {
122 | fatalError(
123 | "Failed to dequeue a supplementary view with identifier \(viewType.reuseIdentifier) "
124 | + "matching type \(viewType.self). "
125 | + "Check that the reuseIdentifier is set properly in your XIB/Storyboard "
126 | + "and that you registered the supplementary view beforehand"
127 | )
128 | }
129 | return typedView
130 | }
131 | }
132 | #endif
133 |
--------------------------------------------------------------------------------
/Sources/View/UITableView+Reusable.swift:
--------------------------------------------------------------------------------
1 | /*********************************************
2 | *
3 | * This code is under the MIT License (MIT)
4 | *
5 | * Copyright (c) 2016 AliSoftware
6 | *
7 | *********************************************/
8 |
9 | #if canImport(UIKit)
10 | import UIKit
11 |
12 | // MARK: Reusable support for UITableView
13 |
14 | public extension UITableView {
15 | /**
16 | Register a NIB-Based `UITableViewCell` subclass (conforming to `Reusable` & `NibLoadable`)
17 |
18 | - parameter cellType: the `UITableViewCell` (`Reusable` & `NibLoadable`-conforming) subclass to register
19 |
20 | - seealso: `register(_:,forCellReuseIdentifier:)`
21 | */
22 | final func register(cellType: T.Type)
23 | where T: Reusable & NibLoadable {
24 | self.register(cellType.nib, forCellReuseIdentifier: cellType.reuseIdentifier)
25 | }
26 |
27 | /**
28 | Register a Class-Based `UITableViewCell` subclass (conforming to `Reusable`)
29 |
30 | - parameter cellType: the `UITableViewCell` (`Reusable`-conforming) subclass to register
31 |
32 | - seealso: `register(_:,forCellReuseIdentifier:)`
33 | */
34 | final func register(cellType: T.Type)
35 | where T: Reusable {
36 | self.register(cellType.self, forCellReuseIdentifier: cellType.reuseIdentifier)
37 | }
38 |
39 | /**
40 | Returns a reusable `UITableViewCell` object for the class inferred by the return-type
41 |
42 | - parameter indexPath: The index path specifying the location of the cell.
43 | - parameter cellType: The cell class to dequeue
44 |
45 | - returns: A `Reusable`, `UITableViewCell` instance
46 |
47 | - note: The `cellType` parameter can generally be omitted and infered by the return type,
48 | except when your type is in a variable and cannot be determined at compile time.
49 | - seealso: `dequeueReusableCell(withIdentifier:,for:)`
50 | */
51 | final func dequeueReusableCell(for indexPath: IndexPath, cellType: T.Type = T.self) -> T
52 | where T: Reusable {
53 | guard let cell = self.dequeueReusableCell(withIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else {
54 | fatalError(
55 | "Failed to dequeue a cell with identifier \(cellType.reuseIdentifier) matching type \(cellType.self). "
56 | + "Check that the reuseIdentifier is set properly in your XIB/Storyboard "
57 | + "and that you registered the cell beforehand"
58 | )
59 | }
60 | return cell
61 | }
62 |
63 | /**
64 | Register a NIB-Based `UITableViewHeaderFooterView` subclass (conforming to `Reusable` & `NibLoadable`)
65 |
66 | - parameter headerFooterViewType: the `UITableViewHeaderFooterView` (`Reusable` & `NibLoadable`-conforming)
67 | subclass to register
68 |
69 | - seealso: `register(_:,forHeaderFooterViewReuseIdentifier:)`
70 | */
71 | final func register(headerFooterViewType: T.Type)
72 | where T: Reusable & NibLoadable {
73 | self.register(headerFooterViewType.nib, forHeaderFooterViewReuseIdentifier: headerFooterViewType.reuseIdentifier)
74 | }
75 |
76 | /**
77 | Register a Class-Based `UITableViewHeaderFooterView` subclass (conforming to `Reusable`)
78 |
79 | - parameter headerFooterViewType: the `UITableViewHeaderFooterView` (`Reusable`-confirming) subclass to register
80 |
81 | - seealso: `register(_:,forHeaderFooterViewReuseIdentifier:)`
82 | */
83 | final func register(headerFooterViewType: T.Type)
84 | where T: Reusable {
85 | self.register(headerFooterViewType.self, forHeaderFooterViewReuseIdentifier: headerFooterViewType.reuseIdentifier)
86 | }
87 |
88 | /**
89 | Returns a reusable `UITableViewHeaderFooterView` object for the class inferred by the return-type
90 |
91 | - parameter viewType: The view class to dequeue
92 |
93 | - returns: A `Reusable`, `UITableViewHeaderFooterView` instance
94 |
95 | - note: The `viewType` parameter can generally be omitted and infered by the return type,
96 | except when your type is in a variable and cannot be determined at compile time.
97 | - seealso: `dequeueReusableHeaderFooterView(withIdentifier:)`
98 | */
99 | final func dequeueReusableHeaderFooterView(_ viewType: T.Type = T.self) -> T?
100 | where T: Reusable {
101 | guard let view = self.dequeueReusableHeaderFooterView(withIdentifier: viewType.reuseIdentifier) as? T? else {
102 | fatalError(
103 | "Failed to dequeue a header/footer with identifier \(viewType.reuseIdentifier) "
104 | + "matching type \(viewType.self). "
105 | + "Check that the reuseIdentifier is set properly in your XIB/Storyboard "
106 | + "and that you registered the header/footer beforehand"
107 | )
108 | }
109 | return view
110 | }
111 | }
112 | #endif
113 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------