Compare commits

...

237 Commits

Author SHA1 Message Date
Ilya Puchka 317d67ca90 Merge pull request #64 from AliSoftware/release/4.3.1
Release 4.3.1
2016-03-24 12:23:17 +01:00
Ilya Puchka cbcef835f7 Bumped version to 4.3.1 2016-03-24 12:10:21 +01:00
Ilya Puchka 47a1870de1 Fixed sample app warnings 2016-03-24 12:02:50 +01:00
Ilya Puchka da2197c909 updated travis script to use Xcode 7.3 2016-03-24 11:48:41 +01:00
Ilya Puchka 3ee8b04118 Merge pull request #62 from mwoollard/develop
Fix build warnings / issues from Swift 2.2
2016-03-24 10:50:45 +01:00
Mark Woollard 29c1a3805f Fix build warnings / issues from Swift 2.2 2016-03-22 13:32:37 +00:00
Ilya Puchka 4dc11a6e2d Merge branch 'hotfix/pods' into develop 2016-03-19 17:53:09 +01:00
Ilya Puchka 7a4d9c554c Merge pull request #60 from AliSoftware/hotfix/pods
Pods hotfix
2016-03-19 17:52:46 +01:00
Ilya Puchka cf4bb0352a pods hotfix 2016-03-19 17:40:59 +01:00
Ilya Puchka 8c6a822eca Merge pull request #59 from AliSoftware/release/4.3.0
Release 4.3.0
2016-03-19 17:09:18 +01:00
Ilya Puchka 4c6718efb3 Merge branch 'release/4.3.0' into develop 2016-03-19 17:06:41 +01:00
Ilya Puchka 1306f12804 Merge branch 'master' into release/4.3.0 2016-03-19 17:02:06 +01:00
Ilya Puchka 764cb98a59 bumped version to 4.3.0 2016-03-19 16:54:42 +01:00
Ilya Puchka 130d71ce3c Added missing tests for Linux 2016-03-19 16:46:17 +01:00
Ilya Puchka 490c2a4d56 Updated CHANGELOG 2016-03-19 16:00:03 +01:00
Ilya Puchka 6e98f270bf Merge pull request #58 from AliSoftware/remove-resolution-failed-error
Removed ResolutionFailed error
2016-03-19 15:44:34 +01:00
Ilya Puchka b3d090c3fd Call didResolveDependencies when graph is complete 2016-03-19 15:33:10 +01:00
Ilya Puchka 4e5cf238c9 removed ResolutionFailed error 2016-03-19 15:33:10 +01:00
Ilya Puchka f4f660d81d Minor DependencyTagConvertible refactoring 2016-03-19 15:33:10 +01:00
Ilya Puchka 211b2fce97 Merge pull request #50 from gavrix/develop
DependencyTagConvertible for better typed Tags
2016-03-19 11:50:19 +01:00
Ilya Puchka 3aa79d1c69 Merge branch 'gavrix-develop' into develop
# Conflicts:
#	Sources/Dip.swift
#	Sources/RuntimeArguments.swift
2016-03-19 11:48:57 +01:00
Sergey Gavrilyuk 4d085d1329 DependencyTag reverted back to DependencyCotnainer.Tag 2016-03-19 11:39:13 +01:00
Ilya Puchka 84845c9b17 Merge pull request #57 from AliSoftware/feature/resolve-dependencies-callback
Added Resolvable protocol
2016-03-19 00:06:34 +01:00
Ilya Puchka f4c38f281e Merge pull request #55 from AliSoftware/feature/auto-wiring
Auto-wiring
2016-03-19 00:05:55 +01:00
Ilya Puchka 99315e32eb Added Resolvable protocol 2016-03-18 23:49:04 +01:00
Ilya Puchka b48fe9840a Moved numberOfArguments property to Definition 2016-03-18 23:40:04 +01:00
Ilya Puchka 6a6fbf906b added playground page, changelog and readmy entry, improved docs 2016-03-18 23:39:33 +01:00
Sergey Gavrilyuk 7e5a0c8ada DependencyTag reverted back to DependencyCotnainer.Tag 2016-03-16 14:43:32 -04:00
Ilya Puchka 1f7ce50035 auto-wiring 2016-03-07 23:59:34 +01:00
Ilya Puchka 6656116e12 Merge pull request #54 from AliSoftware/release/4.2.0
Release/4.2.0 to master
2016-02-27 15:27:14 +01:00
Ilya Puchka 3700f687a2 Merge branch 'release/4.2.0' into develop 2016-02-27 15:00:34 +01:00
Ilya Puchka 92499c9561 fixed auto-injection error description 2016-02-27 14:55:16 +01:00
Ilya Puchka 7c5ea83dc4 Fixed usage of Tag in README 2016-02-27 13:37:51 +01:00
Ilya Puchka 4793232d8c bumped version to 4.2.0 2016-02-25 18:44:21 +01:00
Ilya Puchka 2c09b4d6d1 Merge pull request #46 from AliSoftware/feature/linux-tests
Building tests on linux with spm
2016-02-25 18:32:56 +01:00
Ilya Puchka 34e920a348 building tests on linux with spm 2016-02-25 18:08:06 +01:00
Ilya Puchka 3357630deb updated README and CHANGELOG 2016-02-25 00:26:39 +01:00
Ilya Puchka f23492ee40 Improved auto-injection docs 2016-02-25 00:26:20 +01:00
Sergey Gavrilyuk c817980dd8 DependencyTagConvertible introduced 2016-02-23 11:39:55 -05:00
AliSoftware 328d1b98a5 Merge pull request #49 from AliSoftware/public-autoinjectedpropertybox-protocol
Public AutoInjectedPropertyBox protocol
2016-02-22 20:21:26 +01:00
Ilya Puchka 9f77677014 public AutoInjectedPropertyBox protocol 2016-02-22 15:13:06 +03:00
Ilya Puchka b13a38cf9e clear singleton instances on definition override 2016-02-12 19:50:08 +01:00
Ilya Puchka edb0d3e576 Merge pull request #42 from AliSoftware/feature/pthread
Implemented recursive lock using pthread mutex
2016-02-09 22:34:01 +01:00
Ilya Puchka bd8a503085 Merge pull request #43 from AliSoftware/feature/singleton-scope-fixed
Singleton scope fixed
2016-02-08 11:13:10 +01:00
Ilya Puchka 6af8f18a63 fixed typo 2016-02-08 10:55:53 +01:00
Ilya Puchka bcf2329312 added unit tests 2016-02-08 10:37:25 +01:00
Ilya Puchka b01b7fb055 added thread safety tests for Linux 2016-02-08 01:32:12 +01:00
Ilya Puchka 0515e7358d fixed getting lock 2016-02-07 21:06:26 +01:00
Ilya Puchka 463f9a37a3 added examples to component scope cases 2016-02-07 14:30:16 +01:00
Ilya Puchka 6c802d2c39 fixed releasing singleton instances when definition is removed or container is reset 2016-02-07 14:29:36 +01:00
Ilya Puchka 967a2342b4 storing singleton instances in container instead of definition 2016-02-07 14:00:39 +01:00
Ilya Puchka d7b3db1476 minor refactoring of internal methods 2016-02-07 14:00:39 +01:00
Ilya Puchka f65949bafc removed Foundation import 2016-02-06 20:41:15 +01:00
Ilya Puchka ba420c27a1 implemented recursive lock using pthread mutex 2016-02-06 20:40:04 +01:00
Ilya Puchka ef66212ba3 Merge pull request #41 from AliSoftware/feature/spm
Swift package manager support
2016-02-06 20:39:04 +01:00
Ilya Puchka 1d71eb08ca moved source files to Sources instead of symlink 2016-02-06 16:12:04 +01:00
Ilya Puchka 689ff2ed29 swift package manager support 2016-02-06 15:47:32 +01:00
Olivier Halligon 126c5d3191 Merge branch 'release/4.1.0' 2016-02-04 21:07:06 +01:00
AliSoftware 3b4dab4c97 Merge pull request #40 from AliSoftware/release/4.1.0
Release 4.1.0
2016-02-04 21:03:36 +01:00
Olivier Halligon 7de69e1fa0 Updated the framework's targets version too 2016-02-04 20:48:03 +01:00
Ilya Puchka a44d11b72f updated CHANGELOG and pod spec 2016-02-03 22:28:57 +01:00
AliSoftware 7352769a47 Merge pull request #37 from AliSoftware/feature/sample-app-refined
Refined sample app and readme
2016-02-01 11:24:58 +01:00
Ilya Puchka 5be2995ef1 added comments on the type of di patterns used, added illustration of tagged definitions, property injection and using runtime arguments 2016-02-01 11:04:30 +01:00
AliSoftware 306a52f9d5 Merge pull request #35 from AliSoftware/feature/auto-injection-safety-improvements
Auto-injection improvements
2016-02-01 10:32:23 +01:00
Ilya Puchka 764024700f updated docs and playground 2016-02-01 01:59:00 +01:00
Ilya Puchka ee6c9b6115 removed resolveDependenciesOf method
it's moved to DipUI for less confusion
2016-02-01 00:59:02 +01:00
Ilya Puchka da5cc8f1a7 improved documentation 2016-01-31 15:38:04 +01:00
Ilya Puchka b7b586cba1 rearranged methods of DependencyContainer by extensions 2016-01-31 15:07:15 +01:00
Ilya Puchka b50691205a added ResolutionFailed error
refactored definitions lookup in a separate method
2016-01-31 15:00:20 +01:00
Ilya Puchka d3d1f3cbf9 resolve dependencies of external instances 2016-01-31 14:54:07 +01:00
Ilya Puchka 8d4c71fe5a tagged auto-injected properties 2016-01-31 13:59:18 +01:00
Ilya Puchka 591c1bfefc extracted base class for auto-injection wrappers 2016-01-31 13:59:18 +01:00
Ilya Puchka 786b56b5ea added separate error for auto-injection 2016-01-31 13:59:18 +01:00
Ilya Puchka 4938023a60 reimplemented auto-injection without additional definitions 2016-01-31 13:59:18 +01:00
Ilya Puchka 0db1d2433d implemented optional auto-injected properties using required property 2016-01-31 13:58:26 +01:00
Ilya Puchka fbb1bcc94f bunch of refactoring 2016-01-31 13:58:26 +01:00
Ilya Puchka f41d28382d made auto-injected properties required, enabled code coverage, added few tests 2016-01-31 13:58:25 +01:00
Ilya Puchka 7a242a7656 made value property of auto-injection wrappers readonly for safer property injection, added injected values observers 2016-01-31 13:58:25 +01:00
Ilya Puchka 1c7e8419c7 some code and docs improvements 2016-01-31 13:58:25 +01:00
Ilya Puchka 03cf8f7b32 fixed remove/register methods and DefinitionKey properties access level
DefinitionKey init was never public and was never returned by container, so there is actually no way for clients to use those methods anyway
and it's safe to move them from public scope to internal
2016-01-31 13:40:08 +01:00
Ilya Puchka a36efc1c5e moved thread safety tests specific code to corresponding file 2016-01-30 23:46:41 +01:00
Ilya Puchka 19d1d38d63 removed public extension for Optional description 2016-01-30 23:46:41 +01:00
Ilya Puchka 2bae6bce60 noescape closure in threadSafe method 2016-01-30 23:46:40 +01:00
Ilya Puchka 66bca3d5b6 fix for clearing instances pool in case of error 2016-01-30 23:46:14 +01:00
Ilya Puchka 4dcdabc8ae refined sample app 2016-01-28 00:27:11 +01:00
Ilya Puchka d8859fb44a Refined README 2016-01-28 00:27:11 +01:00
AliSoftware fef5eb10ac Update README.md
Fix links in README
2016-01-26 20:56:56 +01:00
Ilya Puchka fc337f0fe3 fixed reuse on auto-injection 2016-01-22 01:16:58 +01:00
Ilya Puchka d3759baff6 fixed regex 2016-01-22 01:14:20 +01:00
Ilya Puchka bd45b97400 Merge pull request #36 from AliSoftware/mwoollard-develop
Add thread safety with NSRecursiveLock
2016-01-20 10:26:03 +01:00
Mark Woollard 4479b58ace Add thread safety with NSRecursiveLock 2016-01-19 23:23:09 +01:00
AliSoftware 47043a213e Merge pull request #13 from AliSoftware/feature/auto-injection
Auto-injection
2016-01-14 15:43:48 +01:00
Ilya Puchka cc399031e7 removed forced try in playground 2016-01-10 19:48:26 +01:00
Ilya Puchka d50ca57d49 updated CHANGELOG 2016-01-10 19:43:18 +01:00
Ilya Puchka 6f5ab994a0 fixed typos 2016-01-10 19:43:18 +01:00
Ilya Puchka 33601418f3 added throws to auto injection factories 2016-01-10 19:43:18 +01:00
Ilya Puchka 691762242f auto injection playground page and updated documentation 2016-01-10 19:43:18 +01:00
Ilya Puchka 345b6e164a minor internal protocols refactoring 2016-01-10 19:41:38 +01:00
Ilya Puchka 4b0554b539 auto-injection 2016-01-10 19:41:38 +01:00
AliSoftware d786eb17dd Merge pull request #32 from AliSoftware/feature/throwing-factories
Throwing factories and resolve dependencies block
2016-01-10 16:39:27 +01:00
Ilya Puchka d4d275cda6 changed throw to rethrows in private _resolve method 2016-01-10 15:39:05 +01:00
AliSoftware cdf9f43c9b Merge pull request #33 from ilyapuchka/develop
Added reference to Mark Seemann's book in playground and README
2016-01-10 15:37:52 +01:00
Ilya Puchka f8a4b40281 added reference to Mark Seemann's book in playground and README 2016-01-10 14:05:45 +01:00
Ilya Puchka 3803a72548 throwing factories and resolve dependencies block 2016-01-10 13:41:18 +01:00
Olivier Halligon 8f3fad759e Merge branch 'release/4.0.0' 2015-12-12 22:24:29 +01:00
Olivier Halligon c6bf18181f Merge branch 'release/4.0.0' into develop 2015-12-12 22:24:29 +01:00
Ilya Puchka d6908e1feb Update CHANGELOG.md 2015-12-12 21:16:59 +01:00
Ilya Puchka 288673ecb3 Update README.md 2015-12-12 17:54:40 +01:00
Ilya Puchka 14c13d7f35 Update CHANGELOG.md 2015-12-12 17:54:19 +01:00
Ilya Puchka 11a9c7fb70 added note on migration to 4.0.0 in CHANGELOG 2015-12-12 11:56:57 +01:00
Ilya Puchka c670a220d5 added remark about throwing errors in README 2015-12-12 11:51:17 +01:00
Ilya Puchka 049737dd2f bumped version to 4.0.0 2015-12-12 11:25:05 +01:00
Ilya Puchka 79adaed6d3 made DefinitionKey public 2015-12-12 11:23:48 +01:00
AliSoftware c7f9c82f81 Merge pull request #26 from AliSoftware/feature/targets
Added targets for OS X, tvOS and watchOS2
2015-12-12 01:19:00 +01:00
Ilya Puchka ad9c095041 make travis build with carthage 2015-12-11 22:19:43 +01:00
Ilya Puchka 409f0f1990 sudo installer on travis 2015-12-11 22:05:28 +01:00
Ilya Puchka 685809e6ec install carthage on travis 2015-12-11 22:00:24 +01:00
Ilya Puchka dcea032624 use specific tvOS and watchOS simulators on travis 2015-12-11 21:49:12 +01:00
Ilya Puchka ace73a2672 use xcode7.2 on travis 2015-12-11 21:37:34 +01:00
Ilya Puchka ff6645d012 added build for tvOS and watchOS to travis script 2015-12-11 21:30:46 +01:00
Ilya Puchka e3448d9148 minor CHANGELOG fixes 2015-12-11 00:55:57 +01:00
Olivier Halligon b14c4aeb10 Fix CodeSigning DevelopmentTeam to None
To be able to build in Release on any computer
2015-12-11 00:35:05 +01:00
Ilya Puchka 0adc671bd1 updated CHANGELOG 2015-12-08 01:15:54 +01:00
Ilya Puchka 1d7533a516 added targets for OS X, tvOS, watchOS2 2015-12-08 01:06:51 +01:00
Ilya Puchka 6ad4b82ec0 container made final class 2015-12-07 20:15:39 +01:00
Ilya Puchka 6bc96bc8af fixed tests 2015-12-02 22:09:27 +01:00
Ilya Puchka 8b9879a9a2 removed usage of unowned container 2015-12-02 20:58:09 +01:00
Ilya Puchka 406e47206a Merge pull request #22 from ilyapuchka/feature/throwing-errors
Throwing errors
2015-12-02 20:56:28 +01:00
Ilya Puchka 69e8eef0f1 updated docs 2015-11-30 22:59:53 +01:00
Ilya Puchka 78e789cbce enabled code coverage 2015-11-30 15:20:47 +01:00
Ilya Puchka ebbe9a1513 added test on throwing errors and keys eqaulity 2015-11-30 15:20:47 +01:00
Ilya Puchka bc0511261f throwing errors 2015-11-30 15:20:47 +01:00
Ilya Puchka 6a0fa295cb removed deprecated methods and foundation imports 2015-11-30 13:28:46 +01:00
Ilya Puchka 73d8990afa CHANGELOG minor update 2015-11-30 13:28:46 +01:00
Ilya Puchka d7d8f28a36 definition and container description 2015-11-30 13:28:46 +01:00
Ilya Puchka e97883efb0 reverted DefinitionOf back to final class 2015-11-30 13:28:46 +01:00
Olivier Halligon 342fdf9c92 Add @ilyapuchka as author in the Podspec 2015-11-30 12:42:28 +01:00
Olivier Halligon feb5064b93 Merge branch 'release/3.1.0' 2015-11-30 12:30:20 +01:00
Ilya Puchka 9778236416 Merge branch 'release/3.1.0' into develop 2015-11-30 11:02:00 +01:00
Ilya Puchka 184e1f4543 CHANGELOG minor fix 2015-11-30 10:55:12 +01:00
Olivier Halligon b50046c071 Merge branch 'hotfix/migration-note' into develop 2015-11-30 00:00:10 +01:00
Olivier Halligon 8be1139114 CHANGELOG re-org 2015-11-29 23:34:29 +01:00
Ilya Puchka afc8e49b18 bumped project version 2015-11-27 12:52:21 +01:00
Ilya Puchka 333fa96b62 added name for first runtime argument in resolve 2015-11-27 12:47:41 +01:00
Ilya Puchka d611ea240e added scope argument 2015-11-27 12:38:03 +01:00
Ilya Puchka ee16baacfc Merge branch 'master' into release/3.1.0 2015-11-26 23:37:02 +01:00
Ilya Puchka b4221e25a1 Merge pull request #17 from AliSoftware/hotfix/migration-note
Added note on migration from 2.0.0 to 3.0.0
2015-11-26 17:38:04 +01:00
Ilya Puchka 0edd3747e8 added note on migration from 2.0.0 to 3.0.0 2015-11-26 17:21:16 +01:00
Ilya Puchka 0c93e868f0 Added documentation note on definition generic parameters 2015-11-22 21:04:00 +01:00
Olivier Halligon ada995590f Fix depreciation warnings in Sample App 2015-11-22 19:02:04 +01:00
Olivier Halligon c0e5df3443 Merge branch 'feature/circular-dependencies' into develop 2015-11-22 16:52:08 +01:00
Olivier Halligon 37d42281c1 CHANGELOG 2015-11-22 16:51:32 +01:00
Olivier Halligon 6c56e12eeb Including whole MIT licence in comment headers
As license says: "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software." ;-)
2015-11-22 16:49:57 +01:00
Olivier Halligon 948b3cd780 [Playground] Nitpicking on the Circular Dependencies page 2015-11-22 16:49:57 +01:00
Ilya Puchka adde50a3d0 added references to articles about service locator 2015-11-22 16:49:57 +01:00
Ilya Puchka 450a2f8a72 updated playground and added page about circular dependencies 2015-11-22 16:49:57 +01:00
Ilya Puchka 59719a0c37 updated documentation 2015-11-22 16:48:44 +01:00
Ilya Puchka f6afdfd08e added tag property on DefinitionOf 2015-11-22 16:47:14 +01:00
Ilya Puchka abf2202eeb not mutating resolveDependencies method 2015-11-22 16:47:14 +01:00
Ilya Puchka 938108f2ab converted DefinitionOf to struct 2015-11-22 16:47:14 +01:00
Ilya Puchka 9d619d6a25 added note on thread safety in readme 2015-11-22 16:47:14 +01:00
Ilya Puchka 58efc586db added scoped function to increment/decrement recursion depth 2015-11-22 16:44:39 +01:00
Ilya Puchka 3a2aecbe48 circular dependencies 2015-11-22 16:44:39 +01:00
Olivier Halligon 2708f7e434 Merge branch 'release/3.0.0' into develop 2015-11-22 14:32:49 +01:00
Olivier Halligon 378432e376 Merge branch 'release/3.0.0' 2015-11-22 14:32:49 +01:00
Olivier Halligon 62b99edb59 Update CHANGELOG & podspec to 3.0.0 2015-11-22 14:32:08 +01:00
Olivier Halligon 4166afa387 Moved and cleanup SampleApp 2015-11-22 14:31:35 +01:00
Ilya Puchka b15fc47935 fixed travis script 2015-11-12 17:27:45 +01:00
Ilya Puchka 5623ff9d13 Updated Changelog 2015-11-11 21:01:31 +01:00
Ilya Puchka 79ef7e72f5 fixed readme example 2015-11-11 21:01:31 +01:00
Ilya Puchka aacf2adbd3 added note to readme about installing with Carthage 2015-11-11 20:44:36 +01:00
Ilya Puchka bc516a3cc3 moved Dip, playground and sample app to one workspace 2015-11-11 20:39:27 +01:00
Ilya Puchka 66ef3f7697 Merge pull request #10 from AliSoftware/feature/playground
Playground added
2015-11-11 20:21:25 +01:00
Olivier Halligon 794dec0d95 [Playground] Fix typos & formatting 2015-11-11 02:21:43 +01:00
Ilya Puchka 3f0d66bbd9 Page on using Dip with tests 2015-11-10 16:29:54 +01:00
Ilya Puchka 24e5c002ed Playground page on shared instances 2015-11-10 16:29:32 +01:00
Olivier Halligon 3317a9d994 [Playground] Typos & small fixes 2015-11-08 23:08:37 +01:00
Olivier Halligon 53c770c7fc nitpickings in the playground intro 2015-11-08 22:39:48 +01:00
Olivier Halligon 04a6230dd8 Mentioning the Playground in README
+ Moving the "Podspec Metadata" group outside of the project and inside the workspace instead
2015-11-08 22:37:58 +01:00
Ilya Puchka 5adb520a69 playground added 2015-11-08 22:06:43 +01:00
Ilya Puchka 69da1b0e1f Minor fix for docs examples 2015-11-08 21:59:37 +01:00
Olivier Halligon 4e101cab4d Merge branch 'feature/codestyle' into develop 2015-11-08 21:47:42 +01:00
Olivier Halligon a985ccb407 Credits. Also Fix #9 2015-11-08 21:45:43 +01:00
Olivier Halligon 42ea4b155b 2-space indent consistency 2015-11-08 21:45:34 +01:00
AliSoftware 3ccbff4780 Merge pull request #8 from AliSoftware/feature/runtime-args
Added support for up to six runtime arguments
2015-11-08 21:15:14 +01:00
Olivier Halligon 72663deec7 Code Style nitpicking: use 2-spaces indents (see also #9) 2015-11-08 21:07:06 +01:00
Olivier Halligon b9bf2da0d4 Documentation nitpickings 2015-11-08 21:03:10 +01:00
Olivier Halligon 89acac24c5 Moved Podspec Metadata Group outside the project
(So it doesn't risk to be included by mistake to one of the project target, and to avoid confusing the user opening the Sample app)
2015-11-08 20:46:52 +01:00
Ilya Puchka 2ea5e17a51 fixed documentation 2015-11-08 01:31:49 +01:00
Ilya Puchka f1c7c52f14 updated changelog and readme 2015-11-07 12:45:41 +01:00
Ilya Puchka ae04c11ae8 fixed test for optional runtime arguments 2015-11-05 20:16:40 +01:00
Ilya Puchka b5fca0a306 updated changelog and readme 2015-11-05 18:11:04 +01:00
Ilya Puchka 04aa2e190e tag argument is named in all methods 2015-11-05 18:11:04 +01:00
Ilya Puchka e97e3974d2 added test to demonstrate difference with optional runtime arguments 2015-11-05 13:42:21 +01:00
Ilya Puchka 6faf08096a renamed factory to factoryType in DefinitionKey 2015-11-05 13:03:21 +01:00
Ilya Puchka 23924ce4a4 fixed project file 2015-11-05 13:01:42 +01:00
Ilya Puchka 85807fea9c fixed sample app 2015-11-04 22:18:34 +01:00
Ilya Puchka ecac5ce29f made public methods to register/resolve instances with arbitrary number of runtime arguments
moved Definition and run time arguments to separate files
2015-11-04 21:59:46 +01:00
Ilya Puchka fbd4cb8321 removed registration with factory that accepts tag 2015-11-04 15:43:43 +01:00
Ilya Puchka 9e528da256 added support to register components with runtime arguments 2015-11-04 15:43:43 +01:00
Ilya Puchka ec3d979391 Dip scheme is shared 2015-11-04 15:39:25 +01:00
Ilya Puchka 25ef719be0 added travis task to test Dip framework itself 2015-11-04 15:34:50 +01:00
Ilya Puchka a37a8f2dbb fixed travis script 2015-11-04 15:29:58 +01:00
Ilya Puchka 1de582a2a5 added unit tests 2015-11-04 15:13:29 +01:00
Ilya Puchka 7952c0850a removed use of redundant generic tag from readme 2015-11-04 15:10:44 +01:00
Ilya Puchka 156347d5c2 updated pods in sample project 2015-11-04 15:10:44 +01:00
Ilya Puchka dbc8900270 added separate project for Dip framework 2015-11-04 15:10:43 +01:00
Ilya Puchka 6162c26963 renamed sample project to DipSampleApp 2015-11-04 15:10:43 +01:00
Olivier Halligon 7f9c54e484 Version Bump: 2.0.0 2015-10-31 15:21:48 +01:00
Olivier Halligon ec177fba78 Rearranged classes in Dip.swift
To make Tag and LookupKey (formerly ProtoTypeKey) inner classes of DependencyContainer
2015-10-31 15:17:25 +01:00
AliSoftware 6b6f85ba4c Merge pull request #3 from ilyapuchka/master
Remove DependencyContainer Generic constraints

See rationale in PR #3
2015-10-31 14:52:41 +01:00
Ilya Puchka 5f845e6701 updated change log 2015-10-30 23:19:15 +01:00
Ilya Puchka 0028083289 updated sample app 2015-10-30 15:30:17 +01:00
Ilya Puchka 10dd5a51a5 Updated readme 2015-10-29 19:50:26 +01:00
Ilya Puchka 4e3a53997e added support for string and integer literal convertible protocols 2015-10-29 19:50:25 +01:00
Ilya Puchka ae8d56e5d8 tag implemented as enum with String and Int cases 2015-10-29 17:01:58 +01:00
Ilya Puchka bc303da493 changed tag back to String 2015-10-23 23:55:44 +02:00
Ilya Puchka 0db3155835 Removed unneeded Any generic constraint 2015-10-23 23:02:18 +02:00
Olivier Halligon 74112c6051 Yummy animated GIF in README ;) 2015-10-11 17:27:41 +02:00
Olivier Halligon a98a9eed56 [README] Using local GIF + Fixing links to source code from the README 2015-10-11 16:25:23 +02:00
Olivier Halligon a4f6db4f8d Bump Version to 1.0.1 — Improved README and Discoverability 2015-10-11 16:11:54 +02:00
Olivier Halligon a74b527324 Better README 2015-10-11 15:43:51 +02:00
Olivier Halligon 225fb70bd4 Version bump: 1.0.0 2015-10-11 15:16:55 +02:00
Olivier Halligon 368d4f920f SWAPIStarshipProviderTests 2015-10-11 15:01:31 +02:00
Olivier Halligon 61042efb53 SWAPIPersonProviderTests 2015-10-11 14:26:39 +02:00
Olivier Halligon 4ba6e48fd2 Convert var fetchIDs and fetchOne to functions for readability
+ some code formatting fixes
2015-10-11 05:09:15 +02:00
Olivier Halligon 2303aee66f Bump to 0.1.0 2015-10-11 03:49:55 +02:00
Olivier Halligon 7dd3fc3c5c Source Documentation 2015-10-11 03:39:33 +02:00
Olivier Halligon c920c4f425 Thread Safety 2015-10-11 03:37:00 +02:00
Olivier Halligon c0833fd92f Addie ability to init with a block that allows to register dependencies directly 2015-10-11 02:57:56 +02:00
Olivier Halligon 31673bbf21 Cleanup + fix missing values in HardCoded Provider 2015-10-11 02:48:16 +02:00
Olivier Halligon 219e7fd5c1 Added SWAPIProviders that implement the swapi.co WS 2015-10-11 00:44:44 +02:00
Olivier Halligon 6085ce5f21 Use specific providers for some IDs to demonstrate the resolve(tag) usage
Also changed the XProviderAPIs to return a list of IDs instead of directly a list of object. This way we can use a provider to retrieve the IDs first and another to retrieve the Person from its ID which plays better with the demo
2015-10-10 21:36:35 +02:00
Olivier Halligon 3bca744c82 separate the FillableCell protocol requirements from the BaseCell protocol 2015-10-10 18:20:31 +02:00
Olivier Halligon c311eea591 Lazy vars for fetchOne/fetchAll 2015-10-09 04:23:15 +02:00
Olivier Halligon 120a98b157 Using the Mixins & Traits tip to factorize FetchableTrait between the two ViewControllers 2015-10-09 03:53:00 +02:00
Olivier Halligon 937709fba2 Completely changed the Sample project for a better example 2015-10-09 02:15:49 +02:00
159 changed files with 8472 additions and 2785 deletions
+5
View File
@@ -13,6 +13,7 @@ build/
!default.perspectivev3
xcuserdata
*.xccheckout
*.xcscmblueprint
profile
*.moved-aside
DerivedData
@@ -31,3 +32,7 @@ Carthage
# `pod install` in .travis.yml
#
# Pods/
# SPM
.build/
Packages
+8 -4
View File
@@ -1,15 +1,19 @@
language: objective-c
osx_image: xcode7
osx_image: xcode7.3
# cache: cocoapods
# podfile: Example/Podfile
# before_install:
# - gem install cocoapods # Since Travis is not always on latest version
# - pod install --project-directory=Example
install:
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
- curl -OlL "https://github.com/Carthage/Carthage/releases/download/0.11/Carthage.pkg" && sudo installer -pkg "Carthage.pkg" -target / && rm "Carthage.pkg"
script:
- set -o pipefail && xcodebuild test -workspace Example/Dip.xcworkspace -scheme DipSampleApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip-iOS -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip-OSX -sdk macosx -destination 'platform=OS X,arch=x86_64' ONLY_ACTIVE_ARCH=NO | xcpretty -c
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip-tvOS -sdk appletvsimulator -destination 'platform=tvOS Simulator,name=Apple TV 1080p,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c
- set -o pipefail && xcodebuild -workspace Dip.xcworkspace -scheme Dip-watchOS -sdk watchsimulator -destination 'platform=watchOS Simulator,name=Apple Watch - 38mm,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty - c
- set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme DipSampleApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c
- pod lib lint --quick
- carthage build --no-skip-current
+179
View File
@@ -1,7 +1,186 @@
# CHANGELOG
## 4.3.1
* Fix Swift 2.2 compile errors in tests
[#62](https://github.com/AliSoftware/Dip/pull/62), [@mwoollard](https://github.com/mwoollard)
## 4.3.0
* Added `DependencyTagConvertible` protocol for better typed tags.
[#50](https://github.com/AliSoftware/Dip/pull/50), [@gavrix](https://github.com/gavrix)
* Auto-wiring. `DependencyContainer` resolves constructor arguments automatically.
[#55](https://github.com/AliSoftware/Dip/pull/55), [@ilyapuchka](https://github.com/ilyapuchka)
* Added `Resolvable` protocol to get a callback when dependencies graph is complete.
[#57](https://github.com/AliSoftware/Dip/pull/57), [@ilyapuchka](https://github.com/ilyapuchka)
* Removed `DipError.ResolutionFailed` error for better consistency.
[#58](https://github.com/AliSoftware/Dip/pull/58), [@ilyapuchka](https://github.com/ilyapuchka)
## 4.2.0
* Added support for Swift Package Manager.
[#41](https://github.com/AliSoftware/Dip/pull/41), [@ilyapuchka](https://github.com/ilyapuchka)
* Added Linux support.
[#42](https://github.com/AliSoftware/Dip/pull/42), [#46](https://github.com/AliSoftware/Dip/pull/46), [@ilyapuchka](https://github.com/ilyapuchka)
* Fixed the issue that could cause singleton instances to be reused between different containers.
[#43](https://github.com/AliSoftware/Dip/pull/43), [@ilyapuchka](https://github.com/ilyapuchka)
* Added public `AutoInjectedPropertyBox` protocol for user-defined auto-injected property wrappers.
[#49](https://github.com/AliSoftware/Dip/pull/49), [@ilyapuchka](https://github.com/ilyapuchka)
## 4.1.0
#### New features
* Added auto-injection feature.
[#13](https://github.com/AliSoftware/Dip/pull/13), [@ilyapuchka](https://github.com/ilyapuchka)
* Factories and `resolveDependencies` blocks of `DefinitionOf` are now allowed to `throw`. Improved errors handling.
[#32](https://github.com/AliSoftware/Dip/pull/32), [@ilyapuchka](https://github.com/ilyapuchka)
* Thread safety reimplemented with support for recursive methods calls.
[#31](https://github.com/AliSoftware/Dip/pull/31), [@mwoollard](https://github.com/mwoollard)
## 4.0.0
#### New Features
* Added support for circular dependencies:
* Added `ObjectGraph` scope to reuse resolved instances
* Added `resolveDependencies` method on `DefinitionOf` class to resolve dependencies of resolved instance.
[#11](https://github.com/AliSoftware/Dip/pull/11), [@ilyapuchka](https://github.com/ilyapuchka)
* Added methods to register/remove individual definitions.
[#11](https://github.com/AliSoftware/Dip/pull/11), [@ilyapuchka](https://github.com/ilyapuchka)
* All `resolve` methods now can throw error if type can not be resolved.
[#15](https://github.com/AliSoftware/Dip/issues/15), [@ilyapuchka](https://github.com/ilyapuchka)
* `DependencyContainer` is marked as `final`.
* Added support for OSX, tvOS and watchOS2.
[#26](https://github.com/AliSoftware/Dip/pull/26), [@ilyapuchka](https://github.com/ilyapuchka)
#### Breaking Changes
* Removed container thread-safety to enable recursion calls to `resolve`.
**Access to container from multiple threads should be handled by clients** from now on.
* All `resolve` methods now can throw.
### Note on migration from 3.x to 4.0.0:
* Errors
In 4.0.0 each `resolve` method can throw `DefinitionNotFound(DefinitionKey)` error, so you need to call it using `try!` or `try?`, or catch the error if it's appropriate for your case. See [#15](https://github.com/AliSoftware/Dip/issues/15) for rationale of this change.
* Thread safety
In 4.0.0 `DependencyContainer` drops any guarantee of thread safety. From now on code that uses Dip must ensure that it's methods are called from a single thread. For example if you have registered type as a singleton and later two threads try to resolve it at the same time you can have two different instances of type instead of one as expected. This change was required to enable recursive calls of `resolve` method to resolve circular dependencies.
* Removed methods
Methods deprecated in 3.1.0 are now removed.
## 3.1.0
#### New
* Added name for the first runtime argument in `resolve(tag:withArguments: … )` methods to make more clear separation between tag and factory runtime arguments.
#### Depreciations
* `resolve(tag:_: … )` methods are deprecated in favor of those new `resolve(tag:withArguments: … )` methods.
* Deprecated `register(tag:instance:)` method in favor of `register(.Singleton) { … }`.
## 3.0.0
* Added support for factories with up to six runtime arguments.
[#8](https://github.com/AliSoftware/Dip/pull/8), [@ilyapuchka](https://github.com/ilyapuchka)
* Parameter `tag` is now named in all register/resolve methods.
* Playground added to project.
[#10](https://github.com/AliSoftware/Dip/pull/10), [@ilyapuchka](https://github.com/ilyapuchka)
### Note on migration from 2.0.0 to 3.0.0:
If you used tags to register and resolve your components you have to add `tag` name for tag parameter. Don't forget to add it both in `register` and `resolve` methods. If you forget to add it in `resolve` call then tag value will be treated as first runtime argument for a factory, but there is no such factory registerd, so resolve will fail.
**Example**:
This code:
```swift
container.register("some tag") { SomeClass() as SomeProtocol }
container.resolve("some tag") as SomeProtocol
```
becomes this:
```swift
container.register(tag: "some tag") { SomeClass() as SomeProtocol }
container.resolve(tag: "some tag") as SomeProtocol
```
## 2.0.0
* Moved from generic _tag_ parameter on container to `Tag` enum with `String` and `Int` cases
[#3](https://github.com/AliSoftware/Dip/pull/3), [@ilyapuchka](https://github.com/ilyapuchka)
> This API change allows easier use of `DependencyContainer` and avoid some constraints. For a complete rationale on that change, see [PR #3](https://github.com/AliSoftware/Dip/pull/3).
## 1.0.1
* Improved README
* Imrpoved discoverability using keywords in `podspec`
## 1.0.0
#### Dip
* Added Unit Tests for `SWAPIPersonProvider` and `SWAPIStarshipProvider`
_All work in progress is now done. I consider `Dip` to be ready for production and with a stable API, hence the `1.0.0` version bump._
#### Example Project
* Using `func fetchIDs` and `func fetchOne` instead of `lazy var` for readability
## 0.1.0
#### Dip
* Dip is now Thread-Safe
* Added a configuration block so we can easily create the container and register the dependencies all in one expression:
```swift
let deps = DependencyContainer() {
$0.register() { x as Foo }
$0.register() { y as Bar }
$0.register() { z as Baz }
}
```
* Source Documentation
#### Example Project
* Code Cleanup
* Added more values to `HardCodedStarshipProvider` so it works when the `PersonProviderAPI` uses real pilots from swapi.co (`SWAPIPersonProvider`)
## 0.0.4
#### Example Project
* Added `SWAPIPersonProvider` & `SWAPIStarshipProvider` that use http://swapi.co
## 0.0.3
#### Example Project
* Revamped the Sample project to a more complete example (using StarWars API!)
* Using Mixins & Traits in the Sample App for `FetchableTrait` and `FillableCell`
## 0.0.2
#### Dip
* Switched from class methods to instance methods ([#1](https://github.com/AliSoftware/Dip/issues/1)). This allows you to have multiple `DependencyContainers`
* Renamed the class from `Dependency` to `DependencyContainer`
* Renamed the `instanceFactory:` parameter to `factory:`
+10 -8
View File
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = "Dip"
s.version = "0.0.1"
s.summary = "A simple Dependency Resolver (Simplified Dependency Injection-like resolution)."
s.version = "4.3.1"
s.summary = "A simple Dependency Resolver: Dependency Injection using Protocol resolution."
s.description = <<-DESC
Dip is a Swift framework to manage your Dependencies between your classes
in your app.
in your app using Dependency Injection.
It's aimed to be very simple to use while improving testability
of your app by allowing you to get rid of those sharedInstances and instead
@@ -15,18 +15,20 @@ Pod::Spec.new do |s|
an instance dynamically in your classes. Then your App and your Tests can be
configured to resolve the protocol using a different instance or class so this
improve testability by decoupling the API and the concrete class used to implement it.
It's not real Dependency Injection _per se_, but it's close.
DESC
s.homepage = "https://github.com/AliSoftware/Dip"
s.license = 'MIT'
s.author = { "Olivier Halligon" => "olivier@halligon.net" }
s.authors = { "Olivier Halligon" => "olivier@halligon.net", "Ilya Puchka" => "ilya@puchka.me" }
s.source = { :git => "https://github.com/AliSoftware/Dip.git", :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/aligatr'
s.platform = :ios, '8.0'
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.9'
s.tvos.deployment_target = '9.0'
s.watchos.deployment_target = '2.0'
s.requires_arc = true
s.source_files = 'Sources/**/*'
s.source_files = 'Sources/**/*.swift'
end
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:DipPlayground.playground">
</FileRef>
<FileRef
location = "group:Dip/Dip.xcodeproj">
</FileRef>
<FileRef
location = "group:SampleApp/DipSampleApp.xcodeproj">
</FileRef>
<Group
location = "container:"
name = "Podspec Metadata">
<FileRef
location = "group:Dip.podspec">
</FileRef>
<FileRef
location = "group:README.md">
</FileRef>
<FileRef
location = "group:LICENSE">
</FileRef>
<FileRef
location = "group:CHANGELOG.md">
</FileRef>
</Group>
</Workspace>
File diff suppressed because it is too large Load Diff
@@ -2,9 +2,9 @@
<Workspace
version = "1.0">
<FileRef
location = "group:Dip.xcodeproj">
location = "group:../DipPlayground.playground">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3571C161543002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-OSX"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3601C161543002241C1"
BuildableName = "Dip-OSXTests.xctest"
BlueprintName = "Dip-OSXTests"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3571C161543002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-OSX"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3571C161543002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-OSX"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3571C161543002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-OSX"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3771C1615EC002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-iOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3801C1615EC002241C1"
BuildableName = "Dip-iOSTests.xctest"
BlueprintName = "Dip-iOSTests"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3771C1615EC002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-iOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3771C1615EC002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-iOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3771C1615EC002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-iOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3A51C1618AF002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-tvOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3AE1C1618AF002241C1"
BuildableName = "Dip-tvOSTests.xctest"
BlueprintName = "Dip-tvOSTests"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3A51C1618AF002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-tvOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3A51C1618AF002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-tvOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B3A51C1618AF002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-tvOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "61B2C099D2823B76EB65B5ECC8B08934"
BlueprintIdentifier = "0903B4031C162862002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip"
ReferencedContainer = "container:Pods.xcodeproj">
BlueprintName = "Dip-watchOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -45,10 +45,10 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "61B2C099D2823B76EB65B5ECC8B08934"
BlueprintIdentifier = "0903B4031C162862002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip"
ReferencedContainer = "container:Pods.xcodeproj">
BlueprintName = "Dip-watchOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
@@ -60,6 +60,15 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0903B4031C162862002241C1"
BuildableName = "Dip.framework"
BlueprintName = "Dip-watchOS"
ReferencedContainer = "container:Dip.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
+35
View File
@@ -0,0 +1,35 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
//! Project version number for Dip.
FOUNDATION_EXPORT double DipVersionNumber;
//! Project version string for Dip.
FOUNDATION_EXPORT const unsigned char DipVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Dip/PublicHeader.h>
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
+9
View File
@@ -0,0 +1,9 @@
import PackageDescription
let package = Package(
name: "DipTests",
dependencies: [
.Package(url: "../../../Dip", majorVersion: 4, minor: 2),
]
)
@@ -0,0 +1,286 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Server: class {
weak var client: Client? {get}
var anotherClient: Client? {get set}
var optionalProperty: AnyObject? {get}
}
private protocol Client: class {
var server: Server? {get}
var anotherServer: Server? {get set}
var optionalProperty: AnyObject? {get}
}
private class ServerImp: Server {
var _client = InjectedWeak<Client>() { _ in
AutoInjectionTests.clientDidInjectCalled = true
}
var client: Client? {
return _client.value
}
weak var anotherClient: Client?
weak var _optionalProperty = InjectedWeak<AnyObject>(required: false)
var optionalProperty: AnyObject? { return _optionalProperty?.value }
}
private class ClientImp: Client {
var _server = Injected<Server>() { _ in
AutoInjectionTests.serverDidInjectCalled = true
}
var server: Server? {
return _server.value
}
var anotherServer: Server?
var _optionalProperty = Injected<AnyObject>(required: false)
var optionalProperty: AnyObject? { return _optionalProperty.value }
var taggedServer = Injected<Server>(tag: "tagged")
}
private class Obj1 {
let obj2 = InjectedWeak<Obj2>()
let obj3 = Injected<Obj3>()
}
private class Obj2 {
let obj1 = Injected<Obj1>()
}
private class Obj3 {
weak var obj1: Obj1?
init(obj: Obj1) {
self.obj1 = obj
}
}
class AutoInjectionTests: XCTestCase {
static var serverDidInjectCalled: Bool = false
static var clientDidInjectCalled: Bool = false
let container = DependencyContainer()
#if os(Linux)
var allTests: [(String, () throws -> Void)] {
return [
("testThatItResolvesAutoInjectedDependencies", testThatItResolvesAutoInjectedDependencies),
("testThatItThrowsErrorIfFailsToAutoInjectDependency", testThatItThrowsErrorIfFailsToAutoInjectDependency),
("testThatItResolvesAutoInjectedSingletons", testThatItResolvesAutoInjectedSingletons),
("testThatItCallsResolveDependencyBlockWhenAutoInjecting", testThatItCallsResolveDependencyBlockWhenAutoInjecting),
("testThatItReusesResolvedAutoInjectedInstances", testThatItReusesResolvedAutoInjectedInstances),
("testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection", testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection),
("testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies", testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies),
("testThatItCallsDidInjectOnAutoInjectedProperty", testThatItCallsDidInjectOnAutoInjectedProperty),
("testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected", testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected),
("testThatItResolvesTaggedAutoInjectedProperties", testThatItResolvesTaggedAutoInjectedProperties)
]
}
func setUp() {
container.reset()
}
#else
override func setUp() {
container.reset()
}
#endif
func testThatItResolvesAutoInjectedDependencies() {
container.register(.ObjectGraph) { ServerImp() as Server }
container.register(.ObjectGraph) { ClientImp() as Client }
let client = try! container.resolve() as Client
let server = client.server
XCTAssertTrue(client === server?.client)
}
func testThatItThrowsErrorIfFailsToAutoInjectDependency() {
container.register(.ObjectGraph) { ClientImp() as Client }
AssertThrows(expression: try container.resolve() as Client)
}
func testThatItResolvesAutoInjectedSingletons() {
//given
container.register(.Singleton) { ServerImp() as Server }
container.register(.Singleton) { ClientImp() as Client }
//when
let sharedClient = try! container.resolve() as Client
let sharedServer = try! container.resolve() as Server
let client = try! container.resolve() as Client
let server = client.server
//then
XCTAssertTrue(client === sharedClient)
XCTAssertTrue(client === server?.client)
XCTAssertTrue(server === sharedServer)
}
func testThatItCallsResolveDependencyBlockWhenAutoInjecting() {
var serverBlockWasCalled = false
//given
container.register(.ObjectGraph) { ServerImp() as Server }
.resolveDependencies { (container, server) -> () in
serverBlockWasCalled = true
}
var clientBlockWasCalled = false
container.register(.ObjectGraph) { ClientImp() as Client }
.resolveDependencies { (container, client) -> () in
clientBlockWasCalled = true
}
//when
try! container.resolve() as Client
XCTAssertTrue(serverBlockWasCalled)
try! container.resolve() as Server
XCTAssertTrue(clientBlockWasCalled)
}
func testThatItReusesResolvedAutoInjectedInstances() {
//given
container.register(.ObjectGraph) { ServerImp() as Server }
.resolveDependencies { (container, server) -> () in
server.anotherClient = try! container.resolve() as Client
}
container.register(.ObjectGraph) { ClientImp() as Client }
.resolveDependencies { (container, client) -> () in
client.anotherServer = try! container.resolve() as Server
}
//when
let client = try! container.resolve() as Client
//then
let server = client.server
let anotherServer = client.anotherServer
XCTAssertTrue(server === anotherServer)
let oneClient = server!.client
let anotherClient = server!.anotherClient
XCTAssertTrue(oneClient === anotherClient)
XCTAssertTrue(client === anotherClient)
}
func testThatItReusesAutoInjectedInstancesOnNextResolveOrAutoInjection() {
//given
container.register(.ObjectGraph) { Obj1() }
container.register(.ObjectGraph) { Obj2() }
container.register(.ObjectGraph) { Obj3(obj: try self.container.resolve()) }
//when
let obj2 = try! container.resolve() as Obj2
//then
XCTAssertTrue(obj2 === obj2.obj1.value!.obj2.value!,
"Auto-injected instance should be reused on next auto-injection")
XCTAssertTrue(obj2.obj1.value! === obj2.obj1.value!.obj3.value!.obj1,
"Auto-injected instance should be reused on next resolve")
}
func testThatThereIsNoRetainCycleBetweenAutoInjectedCircularDependencies() {
//given
container.register(.ObjectGraph) { ServerImp() as Server }
container.register(.ObjectGraph) { ClientImp() as Client }
//when
var client: Client? = try! container.resolve() as Client
//then
weak var weakServer: Server? = client?.server
weak var weakClient = client
XCTAssertNotNil(weakClient)
XCTAssertNotNil(weakServer)
client = nil
XCTAssertNil(weakClient)
XCTAssertNil(weakServer)
}
func testThatItCallsDidInjectOnAutoInjectedProperty() {
AutoInjectionTests.clientDidInjectCalled = false
AutoInjectionTests.serverDidInjectCalled = false
//given
container.register(.ObjectGraph) { ServerImp() as Server }
container.register(.ObjectGraph) { ClientImp() as Client }
//when
try! container.resolve() as Client
//then
XCTAssertTrue(AutoInjectionTests.clientDidInjectCalled)
XCTAssertTrue(AutoInjectionTests.serverDidInjectCalled)
}
func testThatNoErrorThrownWhenOptionalPropertiesAreNotAutoInjected() {
//given
container.register(.ObjectGraph) { ServerImp() as Server }
container.register(.ObjectGraph) { ClientImp() as Client }
AssertNoThrow(expression: try container.resolve() as Client, "Container should not throw error if failed to resolve optional auto-injected properties.")
}
func testThatItResolvesTaggedAutoInjectedProperties() {
//given
container.register(.ObjectGraph) { ServerImp() as Server }
container.register(tag: "tagged", .ObjectGraph) { ServerImp() as Server }
container.register(.ObjectGraph) { ClientImp() as Client }
//when
let client = try! container.resolve() as Client
//then
let taggedServer = (client as! ClientImp).taggedServer.value!
let server = client.server!
//server and tagged server should be resolved as different instances
XCTAssertTrue(server !== taggedServer)
}
}
+299
View File
@@ -0,0 +1,299 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Service: class { }
private class ServiceImp1: Service { }
private class ServiceImp2: Service { }
private protocol AutoWiredClient: class {
var service1: Service! { get set }
var service2: Service! { get set }
}
private class AutoWiredClientImp: AutoWiredClient {
var service1: Service!
var service2: Service!
init(service1: Service, service2: ServiceImp2) {
self.service1 = service1
self.service2 = service2
}
init() {}
}
class AutoWiringTests: XCTestCase {
let container = DependencyContainer()
#if os(Linux)
var allTests: [(String, () throws -> Void)] {
return [
("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring),
("testThatItUsesAutoWireFactoryWithMostNumberOfArguments", testThatItUsesAutoWireFactoryWithMostNumberOfArguments),
("testThatItThrowsAmbiguityErrorWhenUsingAutoWire", testThatItThrowsAmbiguityErrorWhenUsingAutoWire),
("testThatItFirstTriesToUseTaggedFactoriesWhenUsingAutoWire", testThatItFirstTriesToUseTaggedFactoriesWhenUsingAutoWire),
("testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire", testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire),
("testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments", testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments),
("testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency", testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency),
("testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain", testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain),
("testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTagged", testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTagged),
("testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithNoTag", testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithNoTag)
]
}
func setUp() {
container.reset()
}
#else
override func setUp() {
container.reset()
}
#endif
func testThatItCanResolveWithAutoWiring() {
//given
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
//when
let client = try! container.resolve() as AutoWiredClient
//then
let service1 = client.service1
XCTAssertTrue(service1 is ServiceImp1)
let service2 = client.service2
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatItUsesAutoWireFactoryWithMostNumberOfArguments() {
//given
//1 arg
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient }
//1 arg
container.register(.ObjectGraph) { AutoWiredClientImp(service1: try self.container.resolve(), service2: $0) as AutoWiredClient }
//2 args
var factoryWithMostNumberOfArgumentsCalled = false
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
.resolveDependencies { _ in
factoryWithMostNumberOfArgumentsCalled = true
}
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
//when
let _ = try! container.resolve() as AutoWiredClient
//then
XCTAssertTrue(factoryWithMostNumberOfArgumentsCalled)
}
func testThatItThrowsAmbiguityErrorWhenUsingAutoWire() {
//given
//1 arg
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient }
//1 arg
container.register(.ObjectGraph) { AutoWiredClientImp(service1: try self.container.resolve(), service2: $0) as AutoWiredClient }
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
//when
AssertThrows(expression: try container.resolve() as AutoWiredClient) { error -> Bool in
switch error {
case DipError.AmbiguousDefinitions: return true
default: return false
}
}
}
func testThatItFirstTriesToUseTaggedFactoriesWhenUsingAutoWire() {
//given
//1 arg
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient }
//1 arg
container.register(.ObjectGraph) { AutoWiredClientImp(service1: try self.container.resolve(), service2: $0) as AutoWiredClient }
//2 args
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
//1 arg tagged
var taggedFactoryWithMostNumberOfArgumentsCalled = false
container.register(tag: "tag", .ObjectGraph) { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient }
//2 arg tagged
container.register(tag: "tag", .ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }.resolveDependencies { _ in
taggedFactoryWithMostNumberOfArgumentsCalled = true
}
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
//when
let _ = try! container.resolve(tag: "tag") as AutoWiredClient
//then
XCTAssertTrue(taggedFactoryWithMostNumberOfArgumentsCalled)
}
func testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire() {
//given
//1 arg
var notTaggedFactoryWithMostNumberOfArgumentsCalled = false
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient }.resolveDependencies {_ in
notTaggedFactoryWithMostNumberOfArgumentsCalled = true
}
//1 arg tagged
container.register(tag: "tag", .ObjectGraph) { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient }
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
//when
let _ = try! container.resolve(tag: "other tag") as AutoWiredClient
//then
XCTAssertTrue(notTaggedFactoryWithMostNumberOfArgumentsCalled)
}
func testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments() {
//given
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
//when
let service = try! container.resolve() as Service
AssertThrows(expression: try container.resolve(withArguments: service) as AutoWiredClient,
"Container should not use auto-wiring when resolving with runtime arguments")
}
func testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency() {
//given
container.register(.ObjectGraph) { AutoWiredClientImp() as AutoWiredClient }
.resolveDependencies { container, resolved in
resolved.service1 = try container.resolve() as Service
resolved.service2 = try container.resolve() as ServiceImp2
//simulate that something goes wrong on the way
throw DipError.DefinitionNotFound(key: DefinitionKey(protocolType: ServiceImp1.self, factoryType: Any.self))
}
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
.resolveDependencies { container, resolved in
//auto-wiring should be performed only when definition for type to resolve is not found
//but not for any other type along the way in the graph
XCTFail("Auto-wiring should not be performed if instance was actually resolved.")
}
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
//then
AssertThrows(expression: try container.resolve() as AutoWiredClient,
"Container should not use auto-wiring when definition for resolved type is registered.")
}
func testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgain() {
//given
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
var anotherInstance: AutoWiredClient?
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
.resolveDependencies { container, _ in
if anotherInstance == nil {
anotherInstance = try! container.resolve() as AutoWiredClient
}
}
//when
let resolved = try! container.resolve() as AutoWiredClient
//then
//when doing another auto-wiring during resolve we should reuse instance
XCTAssertTrue((resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp))
}
func testThatItReusesInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithTheSameTagged() {
//given
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
var anotherInstance: AutoWiredClient?
container.register(tag: "tag", .ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
.resolveDependencies { container, _ in
if anotherInstance == nil {
anotherInstance = try! container.resolve(tag: "tag") as AutoWiredClient
}
}
//when
let resolved = try! container.resolve(tag: "tag") as AutoWiredClient
//then
//when doing another auto-wiring during resolve we should reuse instance
XCTAssertTrue((resolved as! AutoWiredClientImp) === (anotherInstance as! AutoWiredClientImp))
}
func testThatItDoesNotReuseInstancesResolvedWithAutoWiringWhenUsingAutoWiringAgainWithNoTag() {
//given
container.register(.ObjectGraph) { ServiceImp1() as Service }
container.register(.ObjectGraph) { ServiceImp2() }
var anotherInstance: AutoWiredClient?
container.register(.ObjectGraph) { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient }
.resolveDependencies { container, _ in
if anotherInstance == nil {
anotherInstance = try! container.resolve() as AutoWiredClient
}
}
//when
let resolved = try! container.resolve(tag: "tag") as AutoWiredClient
//then
//when doing another auto-wiring during resolve we should reuse instance
XCTAssertTrue((resolved as! AutoWiredClientImp) !== (anotherInstance as! AutoWiredClientImp))
}
}
@@ -0,0 +1,222 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Service: class {}
private class ServiceImp1: Service {}
private class ServiceImp2: Service {}
private class Server {
weak var client: Client?
init() {}
}
private class Client {
var server: Server
init(server: Server) {
self.server = server
}
}
class ComponentScopeTests: XCTestCase {
let container = DependencyContainer()
#if os(Linux)
var allTests: [(String, () throws -> Void)] {
return [
("testThatPrototypeIsDefaultScope", testThatPrototypeIsDefaultScope),
("testThatScopeCanBeChanged", testThatScopeCanBeChanged),
("testThatItResolvesTypeAsNewInstanceForPrototypeScope", testThatItResolvesTypeAsNewInstanceForPrototypeScope),
("testThatItReusesInstanceForSingletonScope", testThatItReusesInstanceForSingletonScope),
("testThatSingletonIsNotReusedAcrossContainers", testThatSingletonIsNotReusedAcrossContainers),
("testThatSingletonIsReleasedWhenDefinitionIsRemoved", testThatSingletonIsReleasedWhenDefinitionIsRemoved),
("testThatSingletonIsReleasedWhenDefinitionIsOverridden", testThatSingletonIsReleasedWhenDefinitionIsOverridden),
("testThatSingletonIsReleasedWhenContainerIsReset", testThatSingletonIsReleasedWhenContainerIsReset),
("testThatItReusesInstanceInObjectGraphScopeDuringResolve", testThatItReusesInstanceInObjectGraphScopeDuringResolve),
("testThatItDoesNotReuseInstanceInObjectGraphScopeInNextResolve", testThatItDoesNotReuseInstanceInObjectGraphScopeInNextResolve),
("testThatItDoesNotReuseInstanceInObjectGraphScopeResolvedForNilTag", testThatItDoesNotReuseInstanceInObjectGraphScopeResolvedForNilTag)
]
}
func setUp() {
container.reset()
}
#else
override func setUp() {
container.reset()
}
#endif
func testThatPrototypeIsDefaultScope() {
let def = container.register { ServiceImp1() as Service }
XCTAssertEqual(def.scope, ComponentScope.Prototype)
}
func testThatScopeCanBeChanged() {
let def = container.register(.Singleton) { ServiceImp1() as Service }
XCTAssertEqual(def.scope, ComponentScope.Singleton)
}
func testThatItResolvesTypeAsNewInstanceForPrototypeScope() {
//given
container.register { ServiceImp1() as Service }
//when
let service1 = try! container.resolve() as Service
let service2 = try! container.resolve() as Service
//then
XCTAssertFalse(service1 === service2)
}
func testThatItReusesInstanceForSingletonScope() {
//given
container.register(.Singleton) { ServiceImp1() as Service }
//when
let service1 = try! container.resolve() as Service
let service2 = try! container.resolve() as Service
//then
XCTAssertTrue(service1 === service2)
}
func testThatSingletonIsNotReusedAcrossContainers() {
//given
let def = container.register(.Singleton) { ServiceImp1() as Service }
let secondContainer = DependencyContainer()
secondContainer.register(def, forTag: nil)
//when
let service1 = try! container.resolve() as Service
let service2 = try! secondContainer.resolve() as Service
//then
XCTAssertTrue(service1 !== service2, "Singleton instances should not be reused across containers")
}
func testThatSingletonIsReleasedWhenDefinitionIsRemoved() {
//given
let def = container.register(.Singleton) { ServiceImp1() as Service }
let service1 = try! container.resolve() as Service
//when
container.remove(def, forTag: nil)
container.register(def, forTag: nil)
//then
let service2 = try! container.resolve() as Service
XCTAssertTrue(service1 !== service2, "Singleton instances should be released when definition is removed from the container")
}
func testThatSingletonIsReleasedWhenDefinitionIsOverridden() {
//given
let def = container.register(.Singleton) { ServiceImp1() as Service }
let service1 = try! container.resolve() as Service
//when
container.register(def, forTag: nil)
//then
let service2 = try! container.resolve() as Service
XCTAssertTrue(service1 !== service2, "Singleton instances should be released when definition is overridden")
}
func testThatSingletonIsReleasedWhenContainerIsReset() {
//given
let def = container.register(.Singleton) { ServiceImp1() as Service }
let service1 = try! container.resolve() as Service
//when
container.reset()
container.register(def, forTag: nil)
//then
let service2 = try! container.resolve() as Service
XCTAssertTrue(service1 !== service2, "Singleton instances should be released when container is reset")
}
func testThatItReusesInstanceInObjectGraphScopeDuringResolve() {
//given
container.register(.ObjectGraph) { Client(server: try self.container.resolve()) as Client }
container.register(.ObjectGraph) { Server() as Server }.resolveDependencies { container, server in
server.client = try container.resolve() as Client
}
//when
let client = try! container.resolve() as Client
//then
let server = client.server
XCTAssertTrue(server.client === client)
}
func testThatItDoesNotReuseInstanceInObjectGraphScopeInNextResolve() {
//given
container.register(.ObjectGraph) { Client(server: try self.container.resolve()) as Client }
container.register(.ObjectGraph) { Server() as Server }.resolveDependencies { container, server in
server.client = try container.resolve() as Client
}
//when
let client = try! container.resolve() as Client
let server = client.server
let anotherClient = try! container.resolve() as Client
let anotherServer = anotherClient.server
//then
XCTAssertFalse(server === anotherServer)
XCTAssertFalse(client === anotherClient)
}
func testThatItDoesNotReuseInstanceInObjectGraphScopeResolvedForNilTag() {
//given
var service2: Service?
container.register(.ObjectGraph) { ServiceImp1() as Service }.resolveDependencies { (c, _) in
service2 = try c.resolve(tag: "service") as Service
//then
//when service1 is resolved using this definition due to fallback to nil tag
//we don't want every next resolve of service reuse it
XCTAssertTrue(service2 is ServiceImp2)
}
container.register(tag: "service", .ObjectGraph) { ServiceImp2() as Service}
//when
let service1 = try! container.resolve(tag: "tag") as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
}
}
+114
View File
@@ -0,0 +1,114 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Service {}
private class ServiceImp: Service {}
class DefinitionTests: XCTestCase {
private typealias F1 = () -> Service
private typealias F2 = (String) -> Service
let tag1 = DependencyContainer.Tag.String("tag1")
let tag2 = DependencyContainer.Tag.String("tag2")
#if os(Linux)
var allTests: [(String, () throws -> Void)] {
return [
("testThatDefinitionKeyIsEqualBy_Type_Factory_Tag", testThatDefinitionKeyIsEqualBy_Type_Factory_Tag),
("testThatDefinitionKeysWithDifferentTypesAreNotEqual", testThatDefinitionKeysWithDifferentTypesAreNotEqual),
("testThatDefinitionKeysWithDifferentFactoriesAreNotEqual", testThatDefinitionKeysWithDifferentFactoriesAreNotEqual),
("testThatDefinitionKeysWithDifferentTagsAreNotEqual", testThatDefinitionKeysWithDifferentTagsAreNotEqual),
("testThatResolveDependenciesCallsResolveDependenciesBlock", testThatResolveDependenciesCallsResolveDependenciesBlock),
("testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance", testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance)
]
}
#endif
func testThatDefinitionKeyIsEqualBy_Type_Factory_Tag() {
let equalKey1 = DefinitionKey(protocolType: Service.self, factoryType: F1.self, associatedTag: tag1)
let equalKey2 = DefinitionKey(protocolType: Service.self, factoryType: F1.self, associatedTag: tag1)
XCTAssertEqual(equalKey1, equalKey2)
XCTAssertEqual(equalKey1.hashValue, equalKey2.hashValue)
}
func testThatDefinitionKeysWithDifferentTypesAreNotEqual() {
let keyWithDifferentType1 = DefinitionKey(protocolType: Service.self, factoryType: F1.self, associatedTag: nil)
let keyWithDifferentType2 = DefinitionKey(protocolType: AnyObject.self, factoryType: F1.self, associatedTag: nil)
XCTAssertNotEqual(keyWithDifferentType1, keyWithDifferentType2)
XCTAssertNotEqual(keyWithDifferentType1.hashValue, keyWithDifferentType2.hashValue)
}
func testThatDefinitionKeysWithDifferentFactoriesAreNotEqual() {
let keyWithDifferentFactory1 = DefinitionKey(protocolType: Service.self, factoryType: F1.self, associatedTag: nil)
let keyWithDifferentFactory2 = DefinitionKey(protocolType: Service.self, factoryType: F2.self, associatedTag: nil)
XCTAssertNotEqual(keyWithDifferentFactory1, keyWithDifferentFactory2)
XCTAssertNotEqual(keyWithDifferentFactory1.hashValue, keyWithDifferentFactory2.hashValue)
}
func testThatDefinitionKeysWithDifferentTagsAreNotEqual() {
let keyWithDifferentTag1 = DefinitionKey(protocolType: Service.self, factoryType: F1.self, associatedTag: tag1)
let keyWithDifferentTag2 = DefinitionKey(protocolType: Service.self, factoryType: F1.self, associatedTag: tag2)
XCTAssertNotEqual(keyWithDifferentTag1, keyWithDifferentTag2)
XCTAssertNotEqual(keyWithDifferentTag1.hashValue, keyWithDifferentTag2.hashValue)
}
func testThatResolveDependenciesCallsResolveDependenciesBlock() {
var blockCalled = false
//given
let def = DefinitionOf<Service, () -> Service>(scope: .Prototype) { ServiceImp() as Service }.resolveDependencies { container, service in
blockCalled = true
}
//when
try! def.resolveDependenciesOf(ServiceImp(), withContainer: DependencyContainer())
//then
XCTAssertTrue(blockCalled)
}
func testThatResolveDependenciesBlockIsNotCalledWhenPassedWrongInstance() {
var blockCalled = false
//given
let def = DefinitionOf<Service, () -> Service>(scope: .Prototype) { ServiceImp() as Service }.resolveDependencies { container, service in
blockCalled = true
}
//when
try! def.resolveDependenciesOf(String(), withContainer: DependencyContainer())
//then
XCTAssertFalse(blockCalled)
}
}
+333
View File
@@ -0,0 +1,333 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Service: class { }
private class ServiceImp1: Service { }
private class ServiceImp2: Service { }
private protocol Server: class {
weak var client: Client? { get }
}
private protocol Client: class {
var server: Server? { get }
}
class DipTests: XCTestCase {
let container = DependencyContainer()
#if os(Linux)
var allTests: [(String, () throws -> Void)] {
return [
("testThatItResolvesInstanceRegisteredWithoutTag", testThatItResolvesInstanceRegisteredWithoutTag),
("testThatItResolvesInstanceRegisteredWithTag", testThatItResolvesInstanceRegisteredWithTag),
("testThatItResolvesDifferentInstancesRegisteredForDifferentTags", testThatItResolvesDifferentInstancesRegisteredForDifferentTags),
("testThatNewRegistrationOverridesPreviousRegistration", testThatNewRegistrationOverridesPreviousRegistration),
("testThatItCallsResolveDependenciesOnDefinition", testThatItCallsResolveDependenciesOnDefinition),
("testThatItThrowsErrorIfCanNotFindDefinitionForType", testThatItThrowsErrorIfCanNotFindDefinitionForType),
("testThatItThrowsErrorIfCanNotFindDefinitionForTag", testThatItThrowsErrorIfCanNotFindDefinitionForTag),
("testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments", testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments),
("testThatItThrowsErrorIfConstructorThrows", testThatItThrowsErrorIfConstructorThrows),
("testThatItThrowsErrorIfFailsToResolveDependency", testThatItThrowsErrorIfFailsToResolveDependency),
("testThatItCallsDidResolveDependenciesOnResolvableIntance", testThatItCallsDidResolveDependenciesOnResolvableIntance),
("testThatItResolvesCircularDependencies", testThatItResolvesCircularDependencies)
]
}
func setUp() {
container.reset()
}
#else
override func setUp() {
container.reset()
}
#endif
func testThatItResolvesInstanceRegisteredWithoutTag() {
//given
container.register { ServiceImp1() as Service }
//when
let serviceInstance = try! container.resolve() as Service
//then
XCTAssertTrue(serviceInstance is ServiceImp1)
}
func testThatItResolvesInstanceRegisteredWithTag() {
//given
container.register(tag: "service") { ServiceImp1() as Service }
//when
let serviceInstance = try! container.resolve(tag: "service") as Service
//then
XCTAssertTrue(serviceInstance is ServiceImp1)
}
func testThatItResolvesDifferentInstancesRegisteredForDifferentTags() {
//given
container.register(tag: "service1") { ServiceImp1() as Service }
container.register(tag: "service2") { ServiceImp2() as Service }
//when
let service1Instance = try! container.resolve(tag: "service1") as Service
let service2Instance = try! container.resolve(tag: "service2") as Service
//then
XCTAssertTrue(service1Instance is ServiceImp1)
XCTAssertTrue(service2Instance is ServiceImp2)
}
func testThatNewRegistrationOverridesPreviousRegistration() {
//given
container.register { ServiceImp1() as Service }
let service1 = try! container.resolve() as Service
//when
container.register { ServiceImp2() as Service }
let service2 = try! container.resolve() as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatItCallsResolveDependenciesOnDefinition() {
//given
var resolveDependenciesCalled = false
container.register { ServiceImp1() as Service }.resolveDependencies { (c, s) in
resolveDependenciesCalled = true
}
//when
try! container.resolve() as Service
//then
XCTAssertTrue(resolveDependenciesCalled)
}
func testThatItThrowsErrorIfCanNotFindDefinitionForType() {
//given
container.register { ServiceImp1() as ServiceImp1 }
//when
AssertThrows(expression: try container.resolve() as Service) { error in
guard case let DipError.DefinitionNotFound(key) = error else { return false }
//then
typealias F = () throws -> Service
let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: nil)
XCTAssertEqual(key, expectedKey)
return true
}
}
func testThatItThrowsErrorIfCanNotFindDefinitionForTag() {
//given
container.register(tag: "some tag") { ServiceImp1() as Service }
//when
AssertThrows(expression: try container.resolve(tag: "other tag") as Service) { error in
guard case let DipError.DefinitionNotFound(key) = error else { return false }
//then
typealias F = () throws -> Service
let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: "other tag")
XCTAssertEqual(key, expectedKey)
return true
}
}
func testThatItThrowsErrorIfCanNotFindDefinitionForFactoryWithArguments() {
//given
container.register { ServiceImp1() as Service }
//when
AssertThrows(expression: try container.resolve(withArguments: "some string") as Service) { error in
guard case let DipError.DefinitionNotFound(key) = error else { return false }
//then
typealias F = (String) throws -> Service
let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: nil)
XCTAssertEqual(key, expectedKey)
return true
}
}
func testThatItThrowsErrorIfConstructorThrows() {
//given
let failedKey = DefinitionKey(protocolType: Any.self, factoryType: Any.self)
let expectedError = DipError.DefinitionNotFound(key: failedKey)
container.register { () throws -> Service in throw expectedError }
//when
AssertThrows(expression: try container.resolve() as Service) { error in
switch error {
case let DipError.DefinitionNotFound(key) where key == failedKey: return true
default: return false
}
}
}
func testThatItThrowsErrorIfFailsToResolveDependency() {
//given
let failedKey = DefinitionKey(protocolType: Any.self, factoryType: Any.self)
let expectedError = DipError.DefinitionNotFound(key: failedKey)
container.register { ServiceImp1() as Service }
.resolveDependencies { container, service in
//simulate throwing error when resolving dependency
throw expectedError
}
//when
AssertThrows(expression: try container.resolve() as Service) { error in
switch error {
case let DipError.DefinitionNotFound(key) where key == failedKey: return true
default: return false
}
}
}
func testThatItCallsDidResolveDependenciesOnResolvableIntance() {
class ResolvableService: Service, Resolvable {
var didResolveDependenciesCalled = false
func didResolveDependencies() {
XCTAssertFalse(didResolveDependenciesCalled, "didResolveDependencies should be called only once per instance")
didResolveDependenciesCalled = true
}
}
container.register { ResolvableService() as Service }
.resolveDependencies { _, service in
XCTAssertFalse((service as! ResolvableService).didResolveDependenciesCalled, "didResolveDependencies should not be called yet")
return
}
container.register(tag: "graph", .ObjectGraph) { ResolvableService() as Service }
.resolveDependencies { _, service in
XCTAssertFalse((service as! ResolvableService).didResolveDependenciesCalled)
return
}
container.register(tag: "singleton", .Singleton) { ResolvableService() as Service }
.resolveDependencies { _, service in
XCTAssertFalse((service as! ResolvableService).didResolveDependenciesCalled)
return
}
let service = try! container.resolve() as Service
XCTAssertTrue((service as! ResolvableService).didResolveDependenciesCalled)
let graphService = try! container.resolve(tag: "graph") as Service
XCTAssertTrue((graphService as! ResolvableService).didResolveDependenciesCalled)
let singletonService = try! container.resolve(tag: "singleton") as Service
let _ = try! container.resolve(tag: "singleton") as Service
XCTAssertTrue((singletonService as! ResolvableService).didResolveDependenciesCalled)
}
func testThatItResolvesCircularDependencies() {
class ResolvableServer: Server, Resolvable {
weak var client: Client?
weak var secondClient: Client?
init(client: Client) {
self.client = client
}
var didResolveDependenciesCalled = false
func didResolveDependencies() {
XCTAssertFalse(didResolveDependenciesCalled, "didResolveDependencies should be called only once per instance")
didResolveDependenciesCalled = true
XCTAssertNotNil(self.client)
XCTAssertNotNil(self.secondClient)
XCTAssertNotNil(self.client?.server)
XCTAssertNotNil(self.secondClient)
XCTAssertNotNil(self.secondClient?.server)
}
}
class ResolvableClient: Client, Resolvable {
var server: Server?
var secondServer: Server?
init() {}
var didResolveDependenciesCalled = false
func didResolveDependencies() {
XCTAssertFalse(didResolveDependenciesCalled, "didResolveDependencies should be called only once per instance")
didResolveDependenciesCalled = true
XCTAssertNotNil(self.server)
XCTAssertNotNil(self.secondServer)
XCTAssertNotNil(self.server?.client)
XCTAssertNotNil(self.secondServer?.client)
}
}
container.register(.ObjectGraph) { try ResolvableServer(client: self.container.resolve()) as Server }
.resolveDependencies { (container: DependencyContainer, server: Server) in
let server = server as! ResolvableServer
server.secondClient = try container.resolve() as Client
}
container.register(.ObjectGraph) { ResolvableClient() as Client }
.resolveDependencies { (container: DependencyContainer, client: Client) in
let client = client as! ResolvableClient
client.server = try container.resolve() as Server
client.secondServer = try container.resolve() as Server
}
let client = (try! container.resolve() as Client) as! ResolvableClient
let server = client.server as! ResolvableServer
let secondServer = client.secondServer as! ResolvableServer
let secondClient = server.secondClient as! ResolvableClient
XCTAssertTrue(client === server.client)
XCTAssertTrue(client === server.secondClient)
XCTAssertTrue(client === secondServer.client)
XCTAssertTrue(client === secondServer.secondClient)
XCTAssertTrue(client === secondClient)
XCTAssertTrue(server === secondServer)
XCTAssertTrue(client.didResolveDependenciesCalled)
XCTAssertTrue(server.didResolveDependenciesCalled)
}
}
@@ -0,0 +1,260 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Service {
var name: String { get }
}
private class ServiceImp: Service {
let name: String
init(name: String, baseURL: String, port: Int) {
self.name = name
}
}
private class ServiceImp1: Service {
let name: String = "ServiceImp1"
}
private class ServiceImp2: Service {
let name: String = "ServiceImp2"
}
class RuntimeArgumentsTests: XCTestCase {
let container = DependencyContainer()
#if os(Linux)
var allTests: [(String, () throws -> Void)] {
return [
("testThatItResolvesInstanceWithOneArgument", testThatItResolvesInstanceWithOneArgument),
("testThatItResolvesInstanceWithTwoArguments", testThatItResolvesInstanceWithTwoArguments),
("testThatItResolvesInstanceWithThreeArguments", testThatItResolvesInstanceWithThreeArguments),
("testThatItResolvesInstanceWithFourArguments", testThatItResolvesInstanceWithFourArguments),
("testThatItResolvesInstanceWithFiveArguments", testThatItResolvesInstanceWithFiveArguments),
("testThatItResolvesInstanceWithSixArguments", testThatItResolvesInstanceWithSixArguments),
("testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments", testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments),
("testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments", testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments),
("testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments", testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments),
("testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration", testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration),
("testThatDifferentFactoriesRegisteredIfArgumentIsOptional", testThatDifferentFactoriesRegisteredIfArgumentIsOptional)
]
}
func setUp() {
container.reset()
}
#else
override func setUp() {
container.reset()
}
#endif
func testThatItResolvesInstanceWithOneArgument() {
//given
let arg1 = 1
container.register(factory: { (a1: Int) -> Service in
XCTAssertEqual(a1, arg1)
return ServiceImp1()
})
//when
let service = try! container.resolve(withArguments: arg1) as Service
//then
XCTAssertTrue(service is ServiceImp1)
}
func testThatItResolvesInstanceWithTwoArguments() {
//given
let arg1 = 1, arg2 = 2
container.register { (a1: Int, a2: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
return ServiceImp1()
}
//when
let service = try! container.resolve(withArguments: arg1, arg2) as Service
//then
XCTAssertTrue(service is ServiceImp1)
}
func testThatItResolvesInstanceWithThreeArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3
container.register { (a1: Int, a2: Int, a3: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
return ServiceImp1()
}
//when
let service = try! container.resolve(withArguments: arg1, arg2, arg3) as Service
//then
XCTAssertTrue(service is ServiceImp1)
}
func testThatItResolvesInstanceWithFourArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3, arg4 = 4
container.register { (a1: Int, a2: Int, a3: Int, a4: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
XCTAssertEqual(a4, arg4)
return ServiceImp1()
}
//when
let service = try! container.resolve(withArguments: arg1, arg2, arg3, arg4) as Service
//then
XCTAssertTrue(service is ServiceImp1)
}
func testThatItResolvesInstanceWithFiveArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3, arg4 = 4, arg5 = 5
container.register { (a1: Int, a2: Int, a3: Int, a4: Int, a5: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
XCTAssertEqual(a4, arg4)
XCTAssertEqual(a5, arg5)
return ServiceImp1()
}
//when
let service = try! container.resolve(withArguments: arg1, arg2, arg3, arg4, arg5) as Service
//then
XCTAssertTrue(service is ServiceImp1)
}
func testThatItResolvesInstanceWithSixArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3, arg4 = 4, arg5 = 5, arg6 = 6
container.register { (a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
XCTAssertEqual(a4, arg4)
XCTAssertEqual(a5, arg5)
XCTAssertEqual(a6, arg6)
return ServiceImp1()
}
//when
let service = try! container.resolve(withArguments: arg1, arg2, arg3, arg4, arg5, arg6) as Service
//then
XCTAssertTrue(service is ServiceImp1)
}
func testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments() {
//given
let arg1 = 1, arg2 = 2
container.register { (a1: Int) in ServiceImp1() as Service }
container.register { (a1: Int, a2: Int) in ServiceImp2() as Service }
//when
let service1 = try! container.resolve(withArguments: arg1) as Service
let service2 = try! container.resolve(withArguments: arg1, arg2) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments() {
//given
let arg1 = 1, arg2 = "string"
container.register(factory: { (a1: Int) in ServiceImp1() as Service })
container.register(factory: { (a1: String) in ServiceImp2() as Service })
//when
let service1 = try! container.resolve(withArguments: arg1) as Service
let service2 = try! container.resolve(withArguments: arg2) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments() {
//given
let arg1 = 1, arg2 = "string"
container.register { (a1: Int, a2: String) in ServiceImp1() as Service }
container.register { (a1: String, a2: Int) in ServiceImp2() as Service }
//when
let service1 = try! container.resolve(withArguments: arg1, arg2) as Service
let service2 = try! container.resolve(withArguments: arg2, arg1) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration() {
//given
let arg1 = 1, arg2 = 2
container.register { (a1: Int, a2: Int) in ServiceImp1() as Service }
let service1 = try! container.resolve(withArguments: arg1, arg2) as Service
//when
container.register { (a1: Int, a2: Int) in ServiceImp2() as Service }
let service2 = try! container.resolve(withArguments: arg1, arg2) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatDifferentFactoriesRegisteredIfArgumentIsOptional() {
//given
let name1 = "1", name2 = "2", name3 = "3"
container.register { (port: Int, url: String) in ServiceImp(name: name1, baseURL: url, port: port) as Service }
container.register { (port: Int, url: String?) in ServiceImp(name: name2, baseURL: url!, port: port) as Service }
container.register { (port: Int, url: String!) in ServiceImp(name: name3, baseURL: url, port: port) as Service }
//when
let service1 = try! container.resolve(withArguments: 80, "http://example.com") as Service
let service2 = try! container.resolve(withArguments: 80, "http://example.com" as String?) as Service
let service3 = try! container.resolve(withArguments: 80, "http://example.com" as String!) as Service
//then
XCTAssertEqual(service1.name, name1)
XCTAssertEqual(service2.name, name2)
XCTAssertEqual(service3.name, name3)
}
}
@@ -0,0 +1,225 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Server: class {
var client: Client? { get set }
}
private protocol Client: class {
var server: Server { get }
}
private class ClientImp: Client, Equatable {
var server: Server
init(server: Server) {
self.server = server
}
}
private func ==<T: ClientImp>(lhs: T, rhs: T) -> Bool {
return lhs === rhs
}
private class ServerImp: Server, Hashable {
weak var client: Client?
init() {}
var hashValue: Int {
return unsafeAddressOf(self).hashValue
}
}
private func ==<T: ServerImp>(lhs: T, rhs: T) -> Bool {
return lhs === rhs
}
private var resolvedServers = Set<ServerImp>()
private var resolvedClients = Array<ClientImp>()
private var container: DependencyContainer!
#if os(Linux)
import Glibc
private var lock: pthread_spinlock_t = 0
private let resolveClientSync: () -> Client? = {
var clientPointer: UnsafeMutablePointer<Void> = nil
clientPointer = dispatch_sync { _ in
let resolved = try! container.resolve() as Client
return UnsafeMutablePointer(Unmanaged.passUnretained(resolved as! ClientImp).toOpaque())
}
return Unmanaged<ClientImp>.fromOpaque(COpaquePointer(clientPointer)).takeUnretainedValue()
}
#else
let queue = NSOperationQueue()
let lock = NSRecursiveLock()
private let resolveClientSync: () -> Client? = {
var client: Client?
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
client = try! container.resolve() as Client
}
return client
}
#endif
let resolveServerAsync = {
let service = try! container.resolve() as Server
lock.lock()
resolvedServers.insert(service as! ServerImp)
lock.unlock()
}
let resolveClientAsync = {
let client = try! container.resolve() as Client
lock.lock()
resolvedClients.append(client as! ClientImp)
lock.unlock()
}
class ThreadSafetyTests: XCTestCase {
#if os(Linux)
init() {
pthread_spin_init(&lock, 0)
}
var allTests: [(String, () throws -> Void)] {
return [
("testSingletonThreadSafety", testSingletonThreadSafety),
("testFactoryThreadSafety", testFactoryThreadSafety),
("testCircularReferenceThreadSafety", testCircularReferenceThreadSafety)
]
}
func setUp() {
container = DependencyContainer()
}
func tearDown() {
resolvedServers.removeAll()
resolvedClients.removeAll()
}
#else
override func setUp() {
container = DependencyContainer()
}
override func tearDown() {
resolvedServers.removeAll()
resolvedClients.removeAll()
}
#endif
func testSingletonThreadSafety() {
container.register(.Singleton) { ServerImp() as Server }
for _ in 0..<100 {
#if os(Linux)
dispatch_async({ _ in
resolveServerAsync()
return nil
})
#else
queue.addOperationWithBlock(resolveServerAsync)
#endif
}
#if os(Linux)
sleep(1)
#else
queue.waitUntilAllOperationsAreFinished()
#endif
XCTAssertEqual(resolvedServers.count, 1, "Should create only one instance")
}
func testFactoryThreadSafety() {
container.register { ServerImp() as Server }
for _ in 0..<100 {
#if os(Linux)
dispatch_async({ _ in
resolveServerAsync()
return nil
})
#else
queue.addOperationWithBlock(resolveServerAsync)
#endif
}
#if os(Linux)
sleep(1)
#else
queue.waitUntilAllOperationsAreFinished()
#endif
XCTAssertEqual(resolvedServers.count, 100, "All instances should be different")
}
func testCircularReferenceThreadSafety() {
container.register(.ObjectGraph) {
ClientImp(server: try container.resolve()) as Client
}
container.register(.ObjectGraph) { ServerImp() as Server }
.resolveDependencies { container, server in
server.client = resolveClientSync()
}
for _ in 0..<100 {
#if os(Linux)
dispatch_async({ _ in
resolveClientAsync()
return nil
})
#else
queue.addOperationWithBlock(resolveClientAsync)
#endif
}
#if os(Linux)
sleep(1)
#else
queue.waitUntilAllOperationsAreFinished()
#endif
XCTAssertEqual(resolvedClients.count, 100, "Instances should be not reused in different object graphs")
for client in resolvedClients {
let service = client.server as! ServerImp
let serviceClient = service.client as! ClientImp
XCTAssertEqual(serviceClient, client, "Instances should be reused when resolving single object graph")
}
}
}
+88
View File
@@ -0,0 +1,88 @@
//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
func AssertThrows<T>(file: StaticString = #file, line: UInt = #line, @autoclosure expression: () throws -> T) {
AssertThrows(file, line: line, expression: expression, "")
}
func AssertThrows<T>(file: StaticString = #file, line: UInt = #line, @autoclosure expression: () throws -> T, _ message: String) {
AssertThrows(expression: expression, checkError: { _ in true }, message)
}
func AssertThrows<T>(file: StaticString = #file, line: UInt = #line, @autoclosure expression: () throws -> T, checkError: ErrorType -> Bool) {
AssertThrows(file, line: line, expression: expression, checkError: checkError, "")
}
func AssertThrows<T>(file: StaticString = #file, line: UInt = #line, @autoclosure expression: () throws -> T, checkError: ErrorType -> Bool, _ message: String) {
do {
try expression()
XCTFail(message, file: file, line: line)
}
catch {
XCTAssertTrue(checkError(error), "Thrown unexpected error: \(error)", file: file, line: line)
}
}
func AssertNoThrow<T>(file: StaticString = #file, line: UInt = #line, @autoclosure expression: () throws -> T) {
AssertNoThrow(file, line: line, expression: expression, "")
}
func AssertNoThrow<T>(file: StaticString = #file, line: UInt = #line, @autoclosure expression: () throws -> T, _ message: String) {
do {
try expression()
}
catch {
XCTFail(message, file: file, line: line)
}
}
#if os(Linux)
import Glibc
typealias TMain = @convention(c) (UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void>
func dispatch_async(block: TMain) {
var pid: pthread_t = 0
pthread_create(&pid, nil, block, nil)
}
func dispatch_sync(block: TMain) -> UnsafeMutablePointer<Void> {
var pid: pthread_t = 0
var result: UnsafeMutablePointer<Void> = nil
pthread_create(&pid, nil, block, nil)
pthread_join(pid, &result)
return result
}
extension pthread_spinlock_t {
mutating func lock() {
pthread_spin_lock(&self)
}
mutating func unlock() {
pthread_spin_unlock(&self)
}
}
#endif
+11
View File
@@ -0,0 +1,11 @@
import XCTest
XCTMain([
DipTests(),
DefinitionTests(),
RuntimeArgumentsTests(),
ComponentScopeTests(),
AutoInjectionTests(),
ThreadSafetyTests(),
AutoWiringTests()
])
@@ -0,0 +1,213 @@
//: [Previous: Shared Instances](@previous)
import UIKit
import Dip
let container = DependencyContainer()
/*:
### Auto-Injection
On the previous page you saw how auto-wiring helps us get rid of boilerplate code when registering and resolving components with consturctor injection. Auto-injection solves the same problem for property injection.
Let's say you have following related components:
*/
protocol Service: class {
var logger: Logger? { get }
var tracker: Tracker? { get }
}
class ServiceImp: Service {
var logger: Logger?
var tracker: Tracker?
}
/*:
When you register them in a container you will end up with something like this:
*/
container.register() { TrackerImp() as Tracker }
container.register() { LoggerImp() as Logger }
container.register() { ServiceImp() as Service }
.resolveDependencies { container, service in
let service = service as! ServiceImp
service.logger = try container.resolve() as Logger
service.tracker = try container.resolve() as Tracker
}
let service = try! container.resolve() as Service
service.logger
service.tracker
/*:
Notice that the same boilerplate code that we saw in constructor injection now moved to `resolveDepedencies` block.
With auto-injection your code transforms to this:
*/
class AutoInjectedServiceImp: Service {
private var injectedLogger = Injected<Logger>()
var logger: Logger? { return injectedLogger.value }
private var injectedTracker = Injected<Tracker>()
var tracker: Tracker? { return injectedTracker.value }
}
container.register() { AutoInjectedServiceImp() as Service }
let autoInjectedService = try! container.resolve() as Service
autoInjectedService.logger
autoInjectedService.tracker
/*:
As you can see we added two private properties to our implementation of `Service` - `injectedLogger` and `injectedTracker`. Their types are `Injeceted<Logger>` and `Injected<Tracker>` respectively. Note that we've not just defined them as properties of those types, but defined them with some initial value. `Injected<T>` is a simple _wrapper class_ that wraps value of generic type and provides read-write access to it with `value` property. This property is defined as optional, so that when we create instance of `Injected<T>` it will have `nil` in its value. There is also another wrapper - `InjectedWeak<T>` - which in contrast to `Injected<T>` holds a week reference to its wrapped object, thus requiring it to be a _reference type_ (or `AnyObject`), when `Injected<T>` can also wrap value types (or `Any`).
What is happening under the hood is that after concrete instance of resolved type is created (`Service` in that case), container will iterate through its properties using `Mirror`. For each of the properties wrapped with `Injected<T>` or `InjectedWeak<T>` it will search a definition that can be used to create an instance of wrapped type and use it to create and inject a concrete instance in a `value` property of a wrapper. The fact that wrappers are _classes_ or _reference types_ makes it possible at runtime to inject dependency in instance of resolved type.
The requirement for auto-injection is that types injected types should be registered in a container and should use factories with no runtime arguments.
Auto-injected properties can be marked with tag. Then container will search for definition tagged by the same tag to resolve this property.
You can provide closure that will be called when the dependency will be injected in the property. It is similar to `didSet` property observer.
Auto-injected properties are required by default. That means that if container fails to resolve any of auto-injected properties of the instance (or any of its dependencies) it will fail resolution of the object graph in whole.
*/
class ServerWithRequiredClient {
var client = Injected<Client>()
}
container.register { ServerWithRequiredClient() }
do {
let serverWithClient = try container.resolve() as ServerWithRequiredClient
}
catch {
print(error)
}
/*:
You can make auto-injected property optional by passing `false` to `required` parameter of `Injected<T>`/`InjectedWeak<T>` constructor. For such properties container will ignore any errors when it resolves this property (or any of its dependencies).
*/
class ServerWithOptionalClient {
var optionalClient = Injected<Client>(required: false)
}
container.register { ServerWithOptionalClient() }
let serverWithNoClient = try! container.resolve() as ServerWithOptionalClient
serverWithNoClient.optionalClient.value
/*:
Another example of using auto-injection is circular dependencies. Let's say you have a `Server` and a `ServerClient` both referencing each other.
*/
protocol Server: class {
weak var client: ServerClient? { get }
}
protocol ServerClient: class {
var server: Server? { get }
}
class ServerImp: Server {
weak var client: ServerClient?
}
class ServerClientImp: ServerClient {
var server: Server?
init(server: Server) {
self.server = server
}
}
/*:
The standard way to register such components in `DependencyContainer` will lead to such code:
*/
container.register(.ObjectGraph) {
ServerClientImp(server: try container.resolve()) as ServerClient
}
container.register(.ObjectGraph) { ServerImp() as Server }
.resolveDependencies { (container: DependencyContainer, server: Server) in
(server as! ServerImp).client = try container.resolve() as ServerClient
}
let client = try! container.resolve() as ServerClient
client.server
/*:
With auto-injection you will have the following code:
*/
class InjectedServerImp: Server {
private var injectedClient = InjectedWeak<ServerClient>()
var client: ServerClient? { return injectedClient.value }
}
class InjectedClientImp: ServerClient {
private var injectedServer = Injected<Server>()
var server: Server? { get { return injectedServer.value } }
}
container.register(.ObjectGraph) { InjectedServerImp() as Server }
container.register(.ObjectGraph) { InjectedClientImp() as ServerClient }
let injectedClient = try! container.resolve() as ServerClient
injectedClient.server
injectedClient.server?.client === injectedClient //circular dependencies were resolved correctly
/*:
You can see that component registration looks much simpler now. But on the other side it requires some boilerplate code in implementations, and also tightly coupls your code with Dip.
Here is an example with higher number of dependencies.
*/
container.register() { RouterImp() as Router }
container.register() { DataProviderImp() as DataProvider }
class ViewController: UIViewController {
var logger: Logger?
var tracker: Tracker?
var dataProvider: DataProvider?
var router: Router?
}
container.register { ViewController() }
.resolveDependencies { container, controller in
controller.logger = try container.resolve() as Logger
controller.tracker = try container.resolve() as Tracker
controller.dataProvider = try container.resolve() as DataProvider
controller.router = try container.resolve() as Router
}
let viewController = try! container.resolve() as ViewController
viewController.router
/*:
With auto-injection you can replace that with something like this:
*/
class AutoInjectedViewController: UIViewController {
let logger = Injected<Logger>()
let tracker = Injected<Tracker>()
let dataProvider = Injected<DataProvider>()
let router = Injected<Router>()
}
container.register { AutoInjectedViewController() }
let autoViewController = try! container.resolve() as AutoInjectedViewController
autoViewController.router.value
/*:
In such scenario when view controller is created by storyboard you will need to use property injection anyway, so the overhead of adding additional properties for auto-injection is smaller. Also all the boilerplate code of unwrapping injected properties (if you need that) can be moved to extension, cleaning implementation a bit.
> **Note**: For such cases concider using [DipUI](https://github.com/AliSoftware/Dip-UI). It is a small extension for Dip that allows you to do exactly what we need in this example - inject dependencies in instances created by storyboards. It does not require to use auto-injection feature but plays nice with it.
So as you can see there are certain advantages and disadvatages of using auto-injection. It makes your definitions simpler, especially if there are circular dependencies involved or the number of dependencies is high, removing boilerplate calls to `resolve` method in `resolveDependencies` block of your definitions. But it requires additional properties and some boilerplate code in your implementations, makes your implementatios tightly coupled with Dip. You can avoid tight coupoling by using your own boxing classes instead of `Injected<T>` and `InjectedWeak<T>` (see `AutoInjectedPropertyBox`).
*/
//: [Next: Testing](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,117 @@
//: [Previous: Shared Instances](@previous)
import Dip
import UIKit
/*:
### Auto-wiring
Among three main DI patterns - _constructor_, _property_ and _method_ injection - construction injection should be your choise by default. Dip makes use of this pattern very simple.
Let's say you have some VIPER module with following components:
*/
protocol Service {}
protocol Interactor {
var service: Service { get }
}
protocol Router {}
protocol ViewOutput {}
protocol Presenter {
var router: Router { get }
var interactor: Interactor { get }
var view: ViewOutput { get }
}
class RouterImp: Router {}
class View: UIView, ViewOutput {}
class ServiceImp: Service {}
/*:
VIPER module by its nature consists of a lot of components, wired up using protocols. Using construction injection you can end up with following constructors for presenter and interactor:
*/
class InteractorImp: Interactor {
var service: Service
init(service: Service) {
self.service = service
}
}
class PresenterImp: Presenter {
let router: Router
let interactor: Interactor
let view: ViewOutput
init(view: ViewOutput, interactor: Interactor, router: Router) {
self.view = view
self.interactor = interactor
self.router = router
}
}
/*:
If you register these components in a container you will end up with rather boilerplate code:
*/
let container = DependencyContainer()
container.register { ServiceImp() as Service }
container.register { RouterImp() as Router }
container.register { View() as ViewOutput }
container.register { try InteractorImp(service: container.resolve()) as Interactor }
container.register {
try PresenterImp(
view: container.resolve(),
interactor: container.resolve(),
router: container.resolve()) as Presenter
}
var presenter = try! container.resolve() as Presenter
presenter.interactor.service
/*:
While definition for `Interactor` looks fine, `Presenter`'s definition is overloaded with the same `resolve` calls to container.
The other option you have is to register factory with runtime arguments:
*/
container.register { InteractorImp(service: $0) as Interactor }
container.register { PresenterImp(view: $0, interactor: $1, router: $2) as Presenter }
/*:
But then to resolve presenter or interactor you will first need to resolve their dependencies and pass them as arguments to `resolve` method:
*/
let service = try! container.resolve() as Service
let interactor = try! container.resolve(withArguments: service) as Interactor
let view = try! container.resolve() as ViewOutput
let router = try! container.resolve() as Router
presenter = try! container.resolve(withArguments: view, interactor, router) as Presenter
presenter.interactor.service
/*:
Again to much of boilerplate code. Also it's easy to make a mistake in the order of arguments.
Auto-wiring solves this problem by combining these two approaches - you register factories with runtime arguments, but resolve components with just a call to `resolve()`. Container will resolve all consturctor arguments for you.
*/
container.register { InteractorImp(service: $0) as Interactor }
container.register { PresenterImp(view: $0, interactor: $1, router: $2) as Presenter }
presenter = try! container.resolve() as Presenter
presenter.interactor.service
/*:
You don't need to call `resolve` in a factory and care about order of arguments any more.
The only requirement is that all constructor arguments should be registered in the container and there should be no several factories with the same _number_ of arguments registered for the same components.
In very rare case when you have several different factories with different set of runtime arguments registered for the same component, when you try to resolve it container will try to use these factories one by one until one of them succeeds starting with a factory with most numbers of arguments. If it finds two factories with the same number of arguments it will throw an error.
You can use auto-wiring with tags. The tag that you pass to `resolve` method will be used to resolve each of the constructor arguments.
*/
//: [Next: Auto-injection](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,106 @@
//: [Previous: Scopes](@previous)
import Dip
let container = DependencyContainer()
/*:
### Circular Dependencies
Very often we encounter situations when we have circular dependencies between components. The most obvious example is delegation pattern. Dip can resolve such dependencies easily.
Let's say you have some network client and it's delegate defined like this:
*/
protocol NetworkClientDelegate: class {
var networkClient: NetworkClient { get }
}
protocol NetworkClient: class {
weak var delegate: NetworkClientDelegate? { get set }
}
class NetworkClientImp: NetworkClient {
weak var delegate: NetworkClientDelegate?
init() {}
}
class Interactor: NetworkClientDelegate {
let networkClient: NetworkClient
init(networkClient: NetworkClient) {
self.networkClient = networkClient
}
}
/*:
Note that:
- one of this classes uses _property injection_ (`NetworkClientImp`) you'll give the `delegate` value via its property directly, _after_ initialization
- and another uses _constructor injection_ (`Interactor`) you'll need to give the `networkclient` value via the constructor, _during_ initialization.
It's very important that _at least one_ of them uses property injection, because if you try to use constructor injection for both of them then you will enter infinite loop when you will call `resolve`.
Now you can register those classes in container:
*/
container.register(.ObjectGraph) {
Interactor(networkClient: try container.resolve()) as NetworkClientDelegate
}
container.register(.ObjectGraph) { NetworkClientImp() as NetworkClient }
.resolveDependencies { (container, client) -> () in
client.delegate = try container.resolve() as NetworkClientDelegate
}
/*:
Here you can spot the difference in the way we register classes.
- `Interactor` class uses constructor injection, so to register it we use the block factory where we call `resolve` to obtain instance of `NetworkClient` and pass it to constructor.
- `NetworkClientImp` uses property injection for it's delegate property. Again we use block factory to create instance, but to inject the delegate property we use the special `resolveDependencies` method. Block passed to this method will be called right _after_ the block factory. So you can use this block to perform additional setup or, like in this example, to resolve circular dependencies.
This way `DependencyContainer` breaks infinite recursion that would happen if we used constructor injection for both of our components.
*Note*: You can use container reference inside instance factory without using capture list, there will be [no retain cycle](https://github.com/AliSoftware/Dip/issues/23)
Now when you resolve `NetworkClientDelegate` you will get an instance of `Interactor` that will have client with delegate referencing the same `Interactor` instance:
*/
let interactor = try! container.resolve() as NetworkClientDelegate
interactor.networkClient.delegate === interactor // true: they are the same instances
/*:
**Warning**: Note that one of the properties (`delegate`) is defined as _weak_. That's crucial to avoid retain cycle. But now if you try to resolve `NetworkClient` first it's delegate will be released before `resolve` returns, bcause no one holds a reference to it except the container.
*/
let networkClient = try! container.resolve() as NetworkClient
networkClient.delegate // delegate was alread released =(
/*:
Note also that we used `.ObjectGraph` scope to register implementations. This is also very important to preserve consistency of objects relationships.
If we would have used `.Prototype` scope for both components then container would not reuse instances and we would have an infinite loop:
- Each attempt to resolve `NetworkClientDelegate` will create new instance of `Interactor`.
- It will resolve `NetworkClient` which will create new instance of `NetworkClientImp`.
- It will try to resolve it's delegate property and that will create new instance of `Interactor`
- And so on and so on.
If we would have used `.Prototype` for one of the components it will lead to the same infinite loop or one of the relationships will be invalid:
*/
container.reset()
container.register(.Prototype) {
Interactor(networkClient: try container.resolve()) as NetworkClientDelegate
}
container.register(.ObjectGraph) { NetworkClientImp() as NetworkClient }
.resolveDependencies { (container, client) -> () in
client.delegate = try container.resolve() as NetworkClientDelegate
}
let invalidInteractor = try! container.resolve() as NetworkClientDelegate
invalidInteractor.networkClient.delegate // that is not valid
//: [Next: Shared Instances](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,35 @@
//: [Previous: What is Dip?](@previous)
import Dip
/*:
Dip has two base components: a _DependencyContainer_ and its _Definitions_.
- _DependencyContainer_ is used to register _Definitions_ and to resolve them.
- _Definitions_ describe how component should be created by the _DependencyContainer_.
### Creating the container
You can create a container using a simple `init()`:
*/
var container = DependencyContainer()
//register components here
/*:
or using a configuration block:
*/
container = DependencyContainer { container in
//register components here
}
/*:
Both syntaxes are equivalent. The one using the configuration block is simply a convenience way to scope your components registrations in a nice looking way.
### When/where to create container?
While there is an option to use container as a global variable we advise instead to create and configure container in your app delegate and pass it between your objects (see [Shared Instances](Shared%20Instances)).
*/
//: [Next: Registering Components](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,58 @@
//: [Previous: Creating a DependencyContainer](@previous)
import Dip
/*:
### Registering components
You register a definition in a container using the `register` method:
*/
let container = DependencyContainer()
container.register { ServiceImp1() as Service }
/*:
That code means that when you need a `Service`, you want to use instances of `ServiceImp1` class created with it's `init()` initializer.
You can also register factories that accept runtime arguments:
*/
container.register { service in ClientImp1(service: service) as Client }
/*:
Dip supports up to six runtime arguments, but you can use as many as you want. For more details see ["Runtime arguments"](Runtime%20arguments).
You can also use factory methods in definitions. This can be useful if you already have some factories but want to migrate to Dip.
*/
let factory = ServiceFactory()
// factory.someService is a method with signature `() -> Service`, Cmd-Click to see definition
container.register(factory: factory.someService)
/*:
Optionally you can associate definitions with Integer or String tags. This way you can register different implementations for the same protocol.
You can use `DependencyContainer.Tag` enum, String or Integer literals, or instances of types that conform to `DependencyTagConvertible` protocol.
*/
container.register(tag: "tag") { ServiceImp1() as Service }
container.register(tag: .Int(0)) { ServiceImp1() as Service }
enum MyCustomTag: String, DependencyTagConvertible {
case SomeTag
}
container.register(tag: MyCustomTag.SomeTag) { ServiceImp1() as Service }
/*:
We recommand you to use constants for the tags, to make the intent clear and avoid magic numbers and typos.
You can remove all registered definitions or register and remove them one by one:
*/
let serviceDefinition = container.register { ServiceImp1() as Service }
container
container.remove(serviceDefinition)
container.reset()
//: [Next: Resolving Components](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,47 @@
//: [Previous: Registering Components](@previous)
import Dip
let container = DependencyContainer { container in
container.register { ServiceImp1() as Service }
}
/*:
### Resolving components
You resolve previously registered definition using `resolve` method:
*/
var service = try! container.resolve() as Service
/*:
That code says that you want your `container` to give you an instance that was registered as implementation of `Service` protocol.
It's important to specify the same type that you used for registration. You can use either `as` syntax, or specify type of you variable when you define it:
*/
let otherService: Service = try! container.resolve()
/*:
Both ways will let the `container` detect the type that you want to resolve as. We prefer the `as` syntax because it reads more naturally in Swift.
If you used a tag to register your component, you can use the same tag to resolve it. If there is no definition with such tag, the `container` will try to find a definition for the same type with no tag (`nil` tag), and resolve it instead, allowing you to provide default components in such cases.
*/
container.register(tag: "production") { ServiceImp1() as Service }
container.register(tag: "test") { ServiceImp2() as Service }
// Will give you a ServiceImp1 instance
let productionService = try! container.resolve(tag: "production") as Service
// Will give you a ServiceImp2 instance
let testService = try! container.resolve(tag: "test") as Service
// Will give you a ServiceImp1 because one was registered without a tag on line 4
let defaultService = try! container.resolve() as Service
/*:
You can use runtime arguments to resolve components. Dip supports up to six arguments. For more details see ["Runtime arguments"](Runtime%20arguments).
*/
container.register { service in ClientImp1(service: service) as Client }
let client = try! container.resolve(withArguments: service) as Client
//: [Next: Runtime Arguments](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,51 @@
//: [Previous: Resolving Components](@previous)
import Dip
let container = DependencyContainer()
/*:
### Runtime arguments
Dip lets you use runtime arguments to register and resolve your components.
Note that __types__, __number__ and __order__ of arguments matters and you can register different factories with different set of runtime arguments for the same protocol. To resolve using one of this factory you will need to pass runtime arguments of the same types, number and in the same order to `resolve` as you used in `register` method.
*/
container.register { (url: NSURL, port: Int) in ServiceImp4(name: "1", baseURL: url, port: port) as Service }
container.register { (port: Int, url: NSURL) in ServiceImp4(name: "2", baseURL: url, port: port) as Service }
container.register { (port: Int, url: NSURL?) in ServiceImp4(name: "3", baseURL: url!, port: port) as Service }
container.register { (port: Int, url: NSURL!) in ServiceImp4(name: "4", baseURL: url, port: port) as Service }
let url: NSURL = NSURL(string: "http://example.com")!
let service1 = try! container.resolve(withArguments: url, 80) as Service
let service2 = try! container.resolve(withArguments: 80, url) as Service
let service3 = try! container.resolve(withArguments: 80, NSURL(string: "http://example.com")) as Service
let service4 = try! container.resolve(withArguments: 80, NSURL(string: "http://example.com")! as NSURL!) as Service
(service1 as! ServiceImp4).name
(service2 as! ServiceImp4).name
(service3 as! ServiceImp4).name
(service4 as! ServiceImp4).name
/*:
Note that all of the services were resolved using different factories.
_Dip_ supports up to six runtime arguments. If that is not enougth you can extend `DependencyContainer` to accept more arguments. For example, here is how you can extend it to serve seven arguments.
*/
extension DependencyContainer {
public func register<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7>(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) throws -> T) -> DefinitionOf<T, (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) throws -> T> {
return registerFactory(tag: tag, scope: scope, factory: factory)
}
public func resolve<T, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7>(tag tag: Tag? = nil, _ arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5, _ arg6: Arg6, _ arg7: Arg7) throws -> T {
return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) throws -> T) in try factory(arg1, arg2, arg3, arg4, arg5, arg6, arg7) }
}
}
/*:
However, if you find yourself thinking about adding more runtime arguments, stop and think about your design instead. Having too many dependencies could be a sign of some problem in your architecture, so we strongly suggest that you refrain from doing so; six runtime arguments is already a lot.
*/
//: [Next: Scopes](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,47 @@
//: [Previous: Runtime Arguments](@previous)
import Dip
let container = DependencyContainer()
/*:
### Scopes
Dip supports three different scopes of objects: _Prototype_, _ObjectGraph_ and _Singleton_.
* The `.Prototype` scope will make the `DependencyContainer` resolve your type as __a new instance every time__ you call `resolve`. This is the default scope.
* The `.ObjectGraph` scope is like `.Prototype` scope, but it will make the `DependencyContainer` to reuse resolved instances during one (recursive) call to `resolve` method. When this call returns, all resolved instances will be discarded and next call to `resolve` will produce new instances. This scope should be used to resolve [circular dependencies](Circular%20dependencies).
* The `.Singleton` scope will make the `DependencyContainer` retain the instance once resolved the first time, and reuse it in the next calls to `resolve` during the container lifetime.
The `.Prototype` scope is the default. To set a scope you pass it as an argument to `register` method.
*/
container.register { ServiceImp1() as Service }
container.register(tag: "prototype", .Prototype) { ServiceImp1() as Service }
container.register(tag: "object graph", .ObjectGraph) { ServiceImp2() as Service }
container.register(tag: "shared instance", .Singleton) { ServiceImp3() as Service }
let service = try! container.resolve() as Service
let anotherService = try! container.resolve() as Service
// They are different instances as the scope defaults to .Prototype
service as! ServiceImp1 === anotherService as! ServiceImp1 // false
let prototypeService = try! container.resolve(tag: "prototype") as Service
let anotherPrototypeService = try! container.resolve(tag: "prototype") as Service
// They are different instances:
prototypeService as! ServiceImp1 === anotherPrototypeService as! ServiceImp1 // false
let graphService = try! container.resolve(tag: "object graph") as Service
let anotherGraphService = try! container.resolve(tag: "object graph") as Service
// still different instances the ObjectGraph scope only keep instances during one (recursive) resolution call,
// so the two calls on the two lines above are different calls and use different instances
graphService as! ServiceImp2 === anotherGraphService as! ServiceImp2 // false
let sharedService = try! container.resolve(tag: "shared instance") as Service
let sameSharedService = try! container.resolve(tag: "shared instance") as Service
// same instances, the singleton scope keep and reuse instances during the lifetime of the container
sharedService as! ServiceImp3 === sameSharedService as! ServiceImp3
//: [Next: Circular Dependencies](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,163 @@
//: [Previous: Circular Dependencies](@previous)
import Dip
import UIKit
/*:
### Shared Instances
The Singleton pattern is probably the most debatable and abused pattern in Cocoa development (and probably in programming in general). It's probably the first thing that you will hear from a candidate developer on interview when you ask about Cocoa patterns (the other one will be a delegate).
The problem with singleton is not that it's a worst pattern. The problem is that developers use it to solve problems that do not require it at all. Another problem is that it's very easy to be tempted by this pattern cause it's very easy to implement and use - import file and call `sharedInstance`. But that leads to all kinds of problems:
- First - singleton is a shared mutable state. And the worst thing is that it's a _mutable_ state.
- Second - singleton tigthly couple components of your system.
- Third - it limits your code flexibility.
Dip supports singletons, but it reduces cost of using them. Their singleton nature is managed by the _Container_ and defined only by the _Definitions_ that you register, not by concrete implementations of your classes.
- No need for calls to `sharedInstance` in your code anymore. Instead you get the instance from the _Container_ by resolving a protocol.
- You can easyly change concrete implementations without the rest of your system even notice that something changed.
- Also it's easy to test - you just register another object in your tests. Even if you still want to use a singleton in your system.
Those features you got when using Dip limits tight coupling in your code and gives you back your code flexibility.
Probably the most common example is using a singleton in the network layer or "API client".
*/
class ApiClientSingleton {
static let sharedInstance = ApiClientSingleton()
private init() {}
// Typically a method that makes a GET request on your API
func get(path: String, completion:()->()) {}
}
class MyViewControllerWithSingleton: UIViewController {
override func viewDidAppear(amimated: Bool) {
super.viewDidAppear(amimated)
ApiClientSingleton.sharedInstance.get("/users") { /* refresh your UI */ }
}
}
/*:
Sure, this is very easy to code indeed. And nothing bad so far.
But probably if you wrote a unit test or integration test for that code first, you would have noticed a problem earilier. How you test that code? And how you ensure that your tests are idenpendent of the API client's state from the previous test?
Of cource you can work around all of the problems and the fact that `ApiClient` is a singleton, reset it's state somehow, or mock a class so that it will not return a singleton instance. But look - a moment before the singleton was your best friend and now you are fighting against it.
Think - why do you want API client to be a singleton in a first place? To queue or throttle requests? Then do your queue or throttler a singleton, not an API client. Or is there any other reason. Most likely API client itself does not have a requirement to have one and only one instance during the lifecycle of your application. Imagine that in the future we need two API Clients, because you now have to address two different servers & plaforms? Imposing that singleton restricts now your flexibility a lot.
Instead, inject API client in view controller with property injection or constructor injection.
*/
protocol ApiClientProtocol {
func get(path: String, completion:()->())
}
class ApiClient: ApiClientProtocol {
private struct ApiScheduler {
/* */
}
private let scheduler = ApiScheduler()
init(){}
func get(path: String, completion:()->()) {}
}
class MyViewController: UIViewController {
var apiClient: ApiClientProtocol!
override func viewDidAppear(amimated: Bool) {
super.viewDidAppear(amimated)
apiClient.get("path") {}
}
convenience init(apiClient: ApiClientProtocol) {
self.init()
self.apiClient = apiClient
}
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//inject with constructor
let viewController = MyViewController(apiClient: ApiClient())
//or with property
viewController.apiClient = ApiClient()
/*:
With Dip this code can look like this:
*/
let container = DependencyContainer { container in
container.register { ApiClient() as ApiClientProtocol }
}
class DipViewController: UIViewController {
var apiClient: ApiClientProtocol!
override func viewDidAppear(amimated: Bool) {
super.viewDidAppear(amimated)
apiClient.get("path") {}
}
convenience init(dependencies: DependencyContainer) {
self.init()
self.apiClient = try! dependencies.resolve() as ApiClientProtocol
}
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
var dipController = DipViewController(dependencies: container)
/*:
Of cource `DependencyContainer` should not be a singleton too. Instead, inject it to objects that need to access it. And use a protocol for that. For example if your view controller needs to access API client, it does not need a reference to `DependencyContainer`, it only needs a reference to _something_ that can provide it an API client instance.
*/
protocol ApiClientProvider {
func apiClient() -> ApiClientProtocol
}
extension DependencyContainer: ApiClientProvider {
func apiClient() -> ApiClientProtocol {
return try! self.resolve() as ApiClientProtocol
}
}
extension DipViewController {
convenience init(apiClientProvider: ApiClientProvider) {
self.init()
self.apiClient = apiClientProvider.apiClient()
}
}
dipController = DipViewController(apiClientProvider: container)
/*:
This way you also does not depend directly on Dip. Instead you provide a boundary between Dip that you don't have control of and your source code. So when something chagnes in Dip, you update only the boundary code.
Dependency Injection is a pattern (more precisely - a set of patterns) as well as a singleton. And any pattern can be abused. DI can be used in a [wrong way]((http://www.loosecouplings.com/2011/01/dependency-injection-using-di-container.html)), container can easily become a [service locator](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/). You should carefully decide when to use DI, you should not inject everything and everywhere and define a protocol for every single class you use. For every tool there is a right time and the same way as singleton can harm you the same way DI and protocols abuse can make your code unnececerry complex.
If you want to know more about Dependency Injection in general we recomend you to read ["Dependency Injection in .Net" by Mark Seemann](https://www.manning.com/books/dependency-injection-in-dot-net). Dip was inspired by implementations of IoC container for .Net platform and shares core principles described in that book.
*/
//: [Next: Auto-wiring](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,70 @@
//: [Previous: Shared Instances](@previous)
/*:
### Testing
Dip is convenient to use for testing. Here is s simple example of how you can write tests with Dip.
__Note__: That's a very simple example just to demostrate use of Dip in tests, not how you should or should not tests your code in general.
You can learn more about testing based on state verification vs behavior verification [here](http://martinfowler.com/articles/mocksArentStubs.html).
*/
protocol Service {
func doSomething()
}
class Client {
var service: Service!
func callService() {
service.doSomething()
}
}
import XCTest
import Dip
/*:
Instead of the real `Service` implementation, provide a _fake_ implementation with test hooks that you need:
*/
class FakeService: Service {
var doSomethingCalled = false
func doSomething() {
doSomethingCalled = true
}
init() {}
}
class MyTests: XCTestCase {
var container: DependencyContainer!
override func setUp() {
super.setUp()
/*:
Register fake implementation as `Service`:
*/
container = DependencyContainer { container in
container.register { FakeService() as Service }
}
}
func testThatDoSomethingIsCalled() {
let sut = Client()
sut.service = try! container.resolve() as Service
sut.callService()
/*:
And finally you test it was called:
*/
XCTAssertTrue((sut.service as! FakeService).doSomethingCalled)
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,24 @@
/*:
__Note__: _This playground needs to be open as part of the `Dip.xcworkspace` so it can import the Dip framework / module and demonstrate its usage. (The playground won't work properly if you open it on its own)._
_You might also need to ask Xcode to build the Dip framework first (Command-B) before it can find and import it in this playground._
*/
/*:
## What is Dip?
_Dip_ is a lightweight Swift implementation of [IoC container](https://en.wikipedia.org/wiki/Inversion_of_control).
If you follow [Protocol-Oriented programming](https://developer.apple.com/videos/play/wwdc2015-408/) or [SOLID principles](http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod) then instead of concrete classes you should use protocols to define dependencies between components of your system. I.e. if you need to access some network API, you should use instances of an `APIClient` protocol instead of instances of a concrete class `APIClientImp`.
[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) is a good tool to leverage Protocol-Oriented or SOLID design. Using this principle, you move the point where you create concrete instances _from inside objects_ that use them, _to higher levels_ of your system. **Now your objects do not depend on concrete implementations of their dependencies**, they depend **only on their public interfaces**, defined by protocols that they implement. That gives you all sorts of advantages from **easier testability** to **greater flexibility** of your system.
But still there should be some point in your program where concrete instances are created. The thing is that it's better to have one well defined point for that than to scatter setup logic all over the place with different factories and lazy properties. IoC containers like _Dip_ play the role of that point.
The following pages in this Playground demonstrates how to use _Dip_ to adopt all those concepts in practice.
If you want to know more about Dependency Injection in general we recomend you to read ["Dependency Injection in .Net" by Mark Seemann](https://www.manning.com/books/dependency-injection-in-dot-net). Dip was inspired by implementations of IoC container for .Net platform and shares core principles described in that book.
*/
//: [Next: Creating a DependencyContainer](@next)
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -0,0 +1,78 @@
import Foundation
public protocol Service {}
public class ServiceImp1: Service {
public init() {}
}
public class ServiceImp2: Service {
public init() {}
}
public class ServiceImp3: Service {
public init() {}
}
public class ServiceImp4: Service {
public let name: String
public init(name: String, baseURL: NSURL, port: Int) {
self.name = name
}
}
public protocol Client: class {
var service: Service {get}
init(service: Service)
}
public class ClientImp1: Client {
public var service: Service
public required init(service: Service) {
self.service = service
}
}
public class ClientImp2: Client {
public var service: Service
public required init(service: Service) {
self.service = service
}
}
public class ServiceFactory {
public init() {}
public func someService() -> Service {
return ServiceImp1()
}
}
public class ClientServiceImp: Service {
public weak var client: Client?
public init() {}
}
public protocol Logger {}
public protocol Tracker {}
public protocol DataProvider {}
public protocol Router {}
public class LoggerImp: Logger {
public init() {}
}
public class TrackerImp: Tracker {
public init() {}
}
public class RouterImp: Router {
public init() {}
}
public class DataProviderImp: DataProvider {
public init() {}
}
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='ios' display-mode='rendered'>
<pages>
<page name='What is Dip?'/>
<page name='Creating container'/>
<page name='Registering components'/>
<page name='Resolving components'/>
<page name='Runtime arguments'/>
<page name='Scopes'/>
<page name='Circular dependencies'/>
<page name='Shared Instances'/>
<page name='Auto-wiring'/>
<page name='Auto-injection'/>
<page name='Testing'/>
</pages>
</playground>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
</Workspace>
-657
View File
@@ -1,657 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
097D52E81BC13B0D006C893C /* WebServiceAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52E71BC13B0D006C893C /* WebServiceAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D52EA1BC15FFF006C893C /* PersonFactoryAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52E91BC15FFF006C893C /* PersonFactoryAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D52ED1BC16091006C893C /* Person.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52EC1BC16091006C893C /* Person.swift */; settings = {ASSET_TAGS = (); }; };
097D52EF1BC1611C006C893C /* SWAPIWebService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52EE1BC1611C006C893C /* SWAPIWebService.swift */; settings = {ASSET_TAGS = (); }; };
097D52F11BC161F7006C893C /* SerializerAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F01BC161F7006C893C /* SerializerAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D52F51BC166F3006C893C /* JSONSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F41BC166F3006C893C /* JSONSerializer.swift */; settings = {ASSET_TAGS = (); }; };
097D52F71BC169C0006C893C /* SWAPIPersonFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F61BC169C0006C893C /* SWAPIPersonFactory.swift */; settings = {ASSET_TAGS = (); }; };
097D52F91BC17418006C893C /* PersonFormatterAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F81BC17418006C893C /* PersonFormatterAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D52FB1BC1745B006C893C /* MassHeightFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52FA1BC1745B006C893C /* MassHeightFormatter.swift */; settings = {ASSET_TAGS = (); }; };
097D52FD1BC174B6006C893C /* EyesHairFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52FC1BC174B6006C893C /* EyesHairFormatter.swift */; settings = {ASSET_TAGS = (); }; };
097D53011BC31F4A006C893C /* Tags.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D53001BC31F4A006C893C /* Tags.swift */; settings = {ASSET_TAGS = (); }; };
097D53021BC31FA6006C893C /* WebServiceAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52E71BC13B0D006C893C /* WebServiceAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D53031BC31FA6006C893C /* SerializerAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F01BC161F7006C893C /* SerializerAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D53041BC31FA6006C893C /* PersonFactoryAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52E91BC15FFF006C893C /* PersonFactoryAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D53051BC31FA6006C893C /* PersonFormatterAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F81BC17418006C893C /* PersonFormatterAPI.swift */; settings = {ASSET_TAGS = (); }; };
097D53061BC31FAE006C893C /* SWAPIWebService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52EE1BC1611C006C893C /* SWAPIWebService.swift */; settings = {ASSET_TAGS = (); }; };
097D53071BC31FC5006C893C /* Tags.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D53001BC31F4A006C893C /* Tags.swift */; settings = {ASSET_TAGS = (); }; };
097D53081BC32053006C893C /* Person.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52EC1BC16091006C893C /* Person.swift */; settings = {ASSET_TAGS = (); }; };
097D530A1BC3243D006C893C /* NetworkLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D53091BC3243D006C893C /* NetworkLayer.swift */; settings = {ASSET_TAGS = (); }; };
097D530C1BC324DA006C893C /* NSURLSessionNetworkLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D530B1BC324DA006C893C /* NSURLSessionNetworkLayer.swift */; settings = {ASSET_TAGS = (); }; };
097D530D1BC3250B006C893C /* SWAPIPersonFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F61BC169C0006C893C /* SWAPIPersonFactory.swift */; settings = {ASSET_TAGS = (); }; };
097D530E1BC3250E006C893C /* JSONSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52F41BC166F3006C893C /* JSONSerializer.swift */; settings = {ASSET_TAGS = (); }; };
097D530F1BC3250E006C893C /* MassHeightFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52FA1BC1745B006C893C /* MassHeightFormatter.swift */; settings = {ASSET_TAGS = (); }; };
097D53101BC3250E006C893C /* EyesHairFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D52FC1BC174B6006C893C /* EyesHairFormatter.swift */; settings = {ASSET_TAGS = (); }; };
097D53111BC32513006C893C /* NetworkLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097D53091BC3243D006C893C /* NetworkLayer.swift */; settings = {ASSET_TAGS = (); }; };
099022621BC123C000E76F43 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099022611BC123C000E76F43 /* AppDelegate.swift */; };
099022641BC123C000E76F43 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099022631BC123C000E76F43 /* ViewController.swift */; };
099022671BC123C000E76F43 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 099022651BC123C000E76F43 /* Main.storyboard */; };
099022691BC123C000E76F43 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 099022681BC123C000E76F43 /* Assets.xcassets */; };
0990226C1BC123C000E76F43 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0990226A1BC123C000E76F43 /* LaunchScreen.storyboard */; };
607FACEC1AFB9204008FA782 /* SWAPIWebServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* SWAPIWebServiceTests.swift */; };
7BBD849465D99D9D1987AE6D /* Pods_DipTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304AD039660A2C58EB08D985 /* Pods_DipTests.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
84D8EBE5B2D583BEFB17C45A /* Pods_DipSampleApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FE9C70E965FF88C3F20AC76 /* Pods_DipSampleApp.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
097D52E71BC13B0D006C893C /* WebServiceAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebServiceAPI.swift; sourceTree = "<group>"; };
097D52E91BC15FFF006C893C /* PersonFactoryAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonFactoryAPI.swift; sourceTree = "<group>"; };
097D52EC1BC16091006C893C /* Person.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Person.swift; sourceTree = "<group>"; };
097D52EE1BC1611C006C893C /* SWAPIWebService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SWAPIWebService.swift; sourceTree = "<group>"; };
097D52F01BC161F7006C893C /* SerializerAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerializerAPI.swift; sourceTree = "<group>"; };
097D52F41BC166F3006C893C /* JSONSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONSerializer.swift; sourceTree = "<group>"; };
097D52F61BC169C0006C893C /* SWAPIPersonFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SWAPIPersonFactory.swift; sourceTree = "<group>"; };
097D52F81BC17418006C893C /* PersonFormatterAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonFormatterAPI.swift; sourceTree = "<group>"; };
097D52FA1BC1745B006C893C /* MassHeightFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MassHeightFormatter.swift; sourceTree = "<group>"; };
097D52FC1BC174B6006C893C /* EyesHairFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EyesHairFormatter.swift; sourceTree = "<group>"; };
097D52FE1BC18A09006C893C /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = "<group>"; };
097D53001BC31F4A006C893C /* Tags.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tags.swift; sourceTree = "<group>"; };
097D53091BC3243D006C893C /* NetworkLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkLayer.swift; sourceTree = "<group>"; };
097D530B1BC324DA006C893C /* NSURLSessionNetworkLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSURLSessionNetworkLayer.swift; sourceTree = "<group>"; };
0990225F1BC123C000E76F43 /* DipSampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DipSampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
099022611BC123C000E76F43 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
099022631BC123C000E76F43 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
099022661BC123C000E76F43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
099022681BC123C000E76F43 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
0990226B1BC123C000E76F43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
0990226D1BC123C000E76F43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2FE9C70E965FF88C3F20AC76 /* Pods_DipSampleApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DipSampleApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
304AD039660A2C58EB08D985 /* Pods_DipTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DipTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
607FACE51AFB9204008FA782 /* DipTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DipTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
607FACEB1AFB9204008FA782 /* SWAPIWebServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SWAPIWebServiceTests.swift; sourceTree = "<group>"; };
64B6CB26CB93DFD18565BB72 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
6AB71DAFECF410F2FB12A44C /* Pods-DipSampleApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DipSampleApp.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DipSampleApp/Pods-DipSampleApp.debug.xcconfig"; sourceTree = "<group>"; };
7E5EDFB4A9194B50CAED7E1A /* Pods-DipTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DipTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DipTests/Pods-DipTests.debug.xcconfig"; sourceTree = "<group>"; };
9B78063878AFC700C876DEE9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
B16085421B606723B72DE694 /* Pods-DipSampleApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DipSampleApp.release.xcconfig"; path = "Pods/Target Support Files/Pods-DipSampleApp/Pods-DipSampleApp.release.xcconfig"; sourceTree = "<group>"; };
D9BBF14E74848332935F75C4 /* Pods-DipTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DipTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-DipTests/Pods-DipTests.release.xcconfig"; sourceTree = "<group>"; };
FDB7C1D2EFEC1BA700762782 /* Dip.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Dip.podspec; path = ../Dip.podspec; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
0990225C1BC123C000E76F43 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
84D8EBE5B2D583BEFB17C45A /* Pods_DipSampleApp.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE21AFB9204008FA782 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7BBD849465D99D9D1987AE6D /* Pods_DipTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
097D52E61BC139A8006C893C /* Services */ = {
isa = PBXGroup;
children = (
097D52F21BC16258006C893C /* Protocols */,
097D52F31BC16271006C893C /* Implementations */,
);
path = Services;
sourceTree = "<group>";
};
097D52EB1BC16083006C893C /* Model */ = {
isa = PBXGroup;
children = (
097D52EC1BC16091006C893C /* Person.swift */,
);
path = Model;
sourceTree = "<group>";
};
097D52F21BC16258006C893C /* Protocols */ = {
isa = PBXGroup;
children = (
097D52E71BC13B0D006C893C /* WebServiceAPI.swift */,
097D52F01BC161F7006C893C /* SerializerAPI.swift */,
097D52E91BC15FFF006C893C /* PersonFactoryAPI.swift */,
097D52F81BC17418006C893C /* PersonFormatterAPI.swift */,
097D53091BC3243D006C893C /* NetworkLayer.swift */,
);
path = Protocols;
sourceTree = "<group>";
};
097D52F31BC16271006C893C /* Implementations */ = {
isa = PBXGroup;
children = (
097D52EE1BC1611C006C893C /* SWAPIWebService.swift */,
097D52F61BC169C0006C893C /* SWAPIPersonFactory.swift */,
097D52F41BC166F3006C893C /* JSONSerializer.swift */,
097D52FA1BC1745B006C893C /* MassHeightFormatter.swift */,
097D52FC1BC174B6006C893C /* EyesHairFormatter.swift */,
097D530B1BC324DA006C893C /* NSURLSessionNetworkLayer.swift */,
);
path = Implementations;
sourceTree = "<group>";
};
099022601BC123C000E76F43 /* DipSampleApp */ = {
isa = PBXGroup;
children = (
097D52EB1BC16083006C893C /* Model */,
097D52E61BC139A8006C893C /* Services */,
097D53001BC31F4A006C893C /* Tags.swift */,
099022611BC123C000E76F43 /* AppDelegate.swift */,
099022631BC123C000E76F43 /* ViewController.swift */,
099022651BC123C000E76F43 /* Main.storyboard */,
099022681BC123C000E76F43 /* Assets.xcassets */,
0990226A1BC123C000E76F43 /* LaunchScreen.storyboard */,
0990226D1BC123C000E76F43 /* Info.plist */,
);
path = DipSampleApp;
sourceTree = "<group>";
};
1A92CB92072DE61786F63E4C /* Frameworks */ = {
isa = PBXGroup;
children = (
2FE9C70E965FF88C3F20AC76 /* Pods_DipSampleApp.framework */,
304AD039660A2C58EB08D985 /* Pods_DipTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
607FACC71AFB9204008FA782 = {
isa = PBXGroup;
children = (
607FACF51AFB993E008FA782 /* Podspec Metadata */,
099022601BC123C000E76F43 /* DipSampleApp */,
607FACE81AFB9204008FA782 /* Tests */,
607FACD11AFB9204008FA782 /* Products */,
1A92CB92072DE61786F63E4C /* Frameworks */,
B10E0DA4AD9E022CCA0B272F /* Pods */,
);
sourceTree = "<group>";
};
607FACD11AFB9204008FA782 /* Products */ = {
isa = PBXGroup;
children = (
607FACE51AFB9204008FA782 /* DipTests.xctest */,
0990225F1BC123C000E76F43 /* DipSampleApp.app */,
);
name = Products;
sourceTree = "<group>";
};
607FACE81AFB9204008FA782 /* Tests */ = {
isa = PBXGroup;
children = (
607FACEB1AFB9204008FA782 /* SWAPIWebServiceTests.swift */,
607FACE91AFB9204008FA782 /* Supporting Files */,
);
path = Tests;
sourceTree = "<group>";
};
607FACE91AFB9204008FA782 /* Supporting Files */ = {
isa = PBXGroup;
children = (
607FACEA1AFB9204008FA782 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
isa = PBXGroup;
children = (
FDB7C1D2EFEC1BA700762782 /* Dip.podspec */,
64B6CB26CB93DFD18565BB72 /* README.md */,
097D52FE1BC18A09006C893C /* CHANGELOG.md */,
9B78063878AFC700C876DEE9 /* LICENSE */,
);
name = "Podspec Metadata";
sourceTree = "<group>";
};
B10E0DA4AD9E022CCA0B272F /* Pods */ = {
isa = PBXGroup;
children = (
6AB71DAFECF410F2FB12A44C /* Pods-DipSampleApp.debug.xcconfig */,
B16085421B606723B72DE694 /* Pods-DipSampleApp.release.xcconfig */,
7E5EDFB4A9194B50CAED7E1A /* Pods-DipTests.debug.xcconfig */,
D9BBF14E74848332935F75C4 /* Pods-DipTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
0990225E1BC123C000E76F43 /* DipSampleApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0990226E1BC123C000E76F43 /* Build configuration list for PBXNativeTarget "DipSampleApp" */;
buildPhases = (
52BA3DF5A38A73C99738362E /* Check Pods Manifest.lock */,
0990225B1BC123C000E76F43 /* Sources */,
0990225C1BC123C000E76F43 /* Frameworks */,
0990225D1BC123C000E76F43 /* Resources */,
586A7844323215ADA94020FD /* Embed Pods Frameworks */,
8665FFA2238FD898C8846391 /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = DipSampleApp;
productName = DipSample;
productReference = 0990225F1BC123C000E76F43 /* DipSampleApp.app */;
productType = "com.apple.product-type.application";
};
607FACE41AFB9204008FA782 /* DipTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "DipTests" */;
buildPhases = (
5CA726E6162DF780766DC6CA /* Check Pods Manifest.lock */,
607FACE11AFB9204008FA782 /* Sources */,
607FACE21AFB9204008FA782 /* Frameworks */,
607FACE31AFB9204008FA782 /* Resources */,
7982A68D936539C16CA74E2D /* Embed Pods Frameworks */,
B0AB134AABD1E8CE42E5A2EC /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = DipTests;
productName = Tests;
productReference = 607FACE51AFB9204008FA782 /* DipTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
607FACC81AFB9204008FA782 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = AliSoftware;
TargetAttributes = {
0990225E1BC123C000E76F43 = {
CreatedOnToolsVersion = 7.0;
};
607FACE41AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
};
};
};
buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "Dip" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 607FACC71AFB9204008FA782;
productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
0990225E1BC123C000E76F43 /* DipSampleApp */,
607FACE41AFB9204008FA782 /* DipTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
0990225D1BC123C000E76F43 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0990226C1BC123C000E76F43 /* LaunchScreen.storyboard in Resources */,
099022691BC123C000E76F43 /* Assets.xcassets in Resources */,
099022671BC123C000E76F43 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE31AFB9204008FA782 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
52BA3DF5A38A73C99738362E /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
586A7844323215ADA94020FD /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DipSampleApp/Pods-DipSampleApp-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
5CA726E6162DF780766DC6CA /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
7982A68D936539C16CA74E2D /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DipTests/Pods-DipTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
8665FFA2238FD898C8846391 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DipSampleApp/Pods-DipSampleApp-resources.sh\"\n";
showEnvVarsInLog = 0;
};
B0AB134AABD1E8CE42E5A2EC /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DipTests/Pods-DipTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
0990225B1BC123C000E76F43 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
097D530A1BC3243D006C893C /* NetworkLayer.swift in Sources */,
097D52ED1BC16091006C893C /* Person.swift in Sources */,
097D52F11BC161F7006C893C /* SerializerAPI.swift in Sources */,
097D52F91BC17418006C893C /* PersonFormatterAPI.swift in Sources */,
099022641BC123C000E76F43 /* ViewController.swift in Sources */,
097D530C1BC324DA006C893C /* NSURLSessionNetworkLayer.swift in Sources */,
097D52F51BC166F3006C893C /* JSONSerializer.swift in Sources */,
097D53011BC31F4A006C893C /* Tags.swift in Sources */,
099022621BC123C000E76F43 /* AppDelegate.swift in Sources */,
097D52F71BC169C0006C893C /* SWAPIPersonFactory.swift in Sources */,
097D52EF1BC1611C006C893C /* SWAPIWebService.swift in Sources */,
097D52FD1BC174B6006C893C /* EyesHairFormatter.swift in Sources */,
097D52FB1BC1745B006C893C /* MassHeightFormatter.swift in Sources */,
097D52E81BC13B0D006C893C /* WebServiceAPI.swift in Sources */,
097D52EA1BC15FFF006C893C /* PersonFactoryAPI.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE11AFB9204008FA782 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
607FACEC1AFB9204008FA782 /* SWAPIWebServiceTests.swift in Sources */,
097D53051BC31FA6006C893C /* PersonFormatterAPI.swift in Sources */,
097D53071BC31FC5006C893C /* Tags.swift in Sources */,
097D53111BC32513006C893C /* NetworkLayer.swift in Sources */,
097D53021BC31FA6006C893C /* WebServiceAPI.swift in Sources */,
097D53041BC31FA6006C893C /* PersonFactoryAPI.swift in Sources */,
097D530E1BC3250E006C893C /* JSONSerializer.swift in Sources */,
097D53031BC31FA6006C893C /* SerializerAPI.swift in Sources */,
097D53081BC32053006C893C /* Person.swift in Sources */,
097D53101BC3250E006C893C /* EyesHairFormatter.swift in Sources */,
097D530F1BC3250E006C893C /* MassHeightFormatter.swift in Sources */,
097D530D1BC3250B006C893C /* SWAPIPersonFactory.swift in Sources */,
097D53061BC31FAE006C893C /* SWAPIWebService.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
099022651BC123C000E76F43 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
099022661BC123C000E76F43 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
0990226A1BC123C000E76F43 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
0990226B1BC123C000E76F43 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
0990226F1BC123C000E76F43 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 6AB71DAFECF410F2FB12A44C /* Pods-DipSampleApp.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_TESTABILITY = YES;
INFOPLIST_FILE = DipSampleApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.alisoftware.DipSampleApp;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
099022701BC123C000E76F43 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B16085421B606723B72DE694 /* Pods-DipSampleApp.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = DipSampleApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.alisoftware.DipSampleApp;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
607FACED1AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
607FACEE1AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
607FACF31AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7E5EDFB4A9194B50CAED7E1A /* Pods-DipTests.debug.xcconfig */;
buildSettings = {
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
607FACF41AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D9BBF14E74848332935F75C4 /* Pods-DipTests.release.xcconfig */;
buildSettings = {
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
0990226E1BC123C000E76F43 /* Build configuration list for PBXNativeTarget "DipSampleApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0990226F1BC123C000E76F43 /* Debug */,
099022701BC123C000E76F43 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "Dip" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACED1AFB9204008FA782 /* Debug */,
607FACEE1AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "DipTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACF31AFB9204008FA782 /* Debug */,
607FACF41AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 607FACC81AFB9204008FA782 /* Project object */;
}
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>
-34
View File
@@ -1,34 +0,0 @@
//
// AppDelegate.swift
// DipSampleApp
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import UIKit
import Dip
let dip: DependencyContainer<PersonFormatterTag> = {
let dip = DependencyContainer<PersonFormatterTag>()
dip.register(instance: NSURLSessionNetworkLayer() as NetworkLayer)
dip.register(instance: SWAPIWebService() as WebServiceAPI)
dip.register(instance: SWAPIPersonFactory() as PersonFactoryAPI)
dip.register(instance: JSONSerializer() as SerializerAPI)
dip.register(.MassHeight, instance: MassHeightFormatter() as PersonFormatterAPI)
dip.register(.EyesHair, instance: EyesHairFormatter() as PersonFormatterAPI)
return dip
}()
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
@@ -1,109 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="DipSampleApp" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="qXh-gx-TLm">
<rect key="frame" x="0.0" y="78" width="600" height="522"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="eJE-RI-YCj" detailTextLabel="bZ8-WN-uod" rowHeight="44" style="IBUITableViewCellStyleSubtitle" id="DrW-4I-t0H">
<rect key="frame" x="0.0" y="28" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="DrW-4I-t0H" id="8qv-kr-bqA">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="eJE-RI-YCj">
<rect key="frame" x="15" y="6" width="31.5" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bZ8-WN-uod">
<rect key="frame" x="15" y="25.5" width="40.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
</tableViewCellContentView>
<animations/>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="BYZ-38-t0r" id="VJL-tj-MzD"/>
<outlet property="delegate" destination="BYZ-38-t0r" id="3VC-R7-cB4"/>
</connections>
</tableView>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="9iY-My-sX6">
<rect key="frame" x="373" y="29" width="207" height="29"/>
<animations/>
<segments>
<segment title="Mass &amp; Height"/>
<segment title="Hair &amp; Eyes"/>
</segments>
<connections>
<action selector="displayModeChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="CBv-S7-Hhz"/>
</connections>
</segmentedControl>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="ZrJ-F8-ur5">
<rect key="frame" x="110" y="33" width="20" height="20"/>
<animations/>
</activityIndicatorView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ncZ-ht-Ksy">
<rect key="frame" x="20" y="28" width="82" height="30"/>
<animations/>
<state key="normal" title="fetchPeople"/>
<connections>
<action selector="fetchPeople:" destination="BYZ-38-t0r" eventType="touchUpInside" id="Mt6-Lr-Pil"/>
</connections>
</button>
</subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="qXh-gx-TLm" secondAttribute="trailing" id="9Kr-bh-UDV"/>
<constraint firstItem="qXh-gx-TLm" firstAttribute="top" secondItem="ncZ-ht-Ksy" secondAttribute="bottom" constant="20" id="Hmb-DO-Rfc"/>
<constraint firstItem="9iY-My-sX6" firstAttribute="centerY" secondItem="ncZ-ht-Ksy" secondAttribute="centerY" id="TBb-VW-yeu"/>
<constraint firstItem="ncZ-ht-Ksy" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="20" symbolic="YES" id="U15-6S-bXH"/>
<constraint firstItem="ZrJ-F8-ur5" firstAttribute="leading" secondItem="ncZ-ht-Ksy" secondAttribute="trailing" constant="8" symbolic="YES" id="YZP-u9-4yj"/>
<constraint firstItem="ncZ-ht-Ksy" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="8" symbolic="YES" id="Zj6-fq-3iI"/>
<constraint firstItem="ZrJ-F8-ur5" firstAttribute="centerY" secondItem="ncZ-ht-Ksy" secondAttribute="centerY" id="g7i-I1-gh8"/>
<constraint firstItem="qXh-gx-TLm" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="hhU-qP-IoI"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="qXh-gx-TLm" secondAttribute="bottom" id="koO-On-68B"/>
<constraint firstAttribute="trailing" secondItem="9iY-My-sX6" secondAttribute="trailing" constant="20" symbolic="YES" id="wRA-OJ-Uzd"/>
</constraints>
</view>
<connections>
<outlet property="activityIndicator" destination="ZrJ-F8-ur5" id="3If-JS-Sph"/>
<outlet property="displayModeSelector" destination="9iY-My-sX6" id="UvA-Vu-rkk"/>
<outlet property="tableView" destination="qXh-gx-TLm" id="agu-go-Toa"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="390" y="450"/>
</scene>
</scenes>
</document>
@@ -1,18 +0,0 @@
//
// EyesHairFormatter.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
class EyesHairFormatter : PersonFormatterAPI {
func textForPerson(person: Person) -> String {
return person.name
}
func subtextForPerson(person: Person) -> String {
return "\(person.eyesColor) eyes, \(person.hairColor) hair"
}
}
@@ -1,24 +0,0 @@
//
// JSONSerializer.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
class JSONSerializer : SerializerAPI {
enum Error : ErrorType {
case UnexpectedFormat
}
func dictionaryFromData(data: NSData) throws -> [String:AnyObject] {
let result = try NSJSONSerialization.JSONObjectWithData(data, options: [])
if let json = result as? [String:AnyObject] {
return json
} else {
throw Error.UnexpectedFormat
}
}
}
@@ -1,18 +0,0 @@
//
// MassHeightFormatter.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
class MassHeightFormatter : PersonFormatterAPI {
func textForPerson(person: Person) -> String {
return person.name
}
func subtextForPerson(person: Person) -> String {
return "\(person.mass)kg, \(person.height)cm"
}
}
@@ -1,22 +0,0 @@
//
// NSURLSessionNetworkLayer.swift
// Dip
//
// Created by Olivier Halligon on 05/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
class NSURLSessionNetworkLayer : NetworkLayer {
let session = NSURLSession.sharedSession()
func fetchURL(url: NSURL, completion: NSData? -> Void) {
let task = session.dataTaskWithURL(url) { (data: NSData?, resp: NSURLResponse?, error: NSError?) -> Void in
dispatch_async(dispatch_get_main_queue()) {
completion(data)
}
}
task.resume()
}
}
@@ -1,46 +0,0 @@
//
// SWAPIPersonFactory.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
import Dip
class SWAPIPersonFactory : PersonFactoryAPI {
typealias JSONDict = [String:AnyObject]
enum Error : ErrorType {
case MissingResultsEntry
case InvalidPersonSchema
}
let serializer = dip.resolve() as SerializerAPI
func peopleFromData(personData: NSData) throws -> [Person] {
let json = try serializer.dictionaryFromData(personData)
if let results = json["results"] as? [JSONDict] {
return try results.map { try personFromJSON($0) }
} else {
throw Error.MissingResultsEntry
}
}
func personFromData(personData: NSData) throws -> Person {
let json = try serializer.dictionaryFromData(personData)
return try personFromJSON(json)
}
private func personFromJSON(json: JSONDict) throws -> Person {
guard let name = json["name"] as? String,
let heightStr = json["height"] as? String, height = Int(heightStr),
let massStr = json["mass"] as? String, mass = Int(massStr),
let eyesColor = json["eye_color"] as? String,
let hairColor = json["hair_color"] as? String
else {
throw Error.InvalidPersonSchema
}
return Person(name: name, height: height, mass: mass, eyesColor: eyesColor, hairColor: hairColor)
}
}
@@ -1,31 +0,0 @@
//
// SWAPIWebService.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
import Dip
/// WebService for The StarWars API see http://swapi.co/documentation
class SWAPIWebService : WebServiceAPI {
let networkLayer = dip.resolve() as NetworkLayer
let personFactory = dip.resolve() as PersonFactoryAPI
func fetch(completion: [Person]? -> Void) {
let url = NSURL(string: "http://swapi.co/api/people/")!
networkLayer.fetchURLAndMap(url, completion: completion) { data in
return try self.personFactory.peopleFromData(data)
}
}
func fetch(id: Int, completion: Person? -> Void) {
let url = NSURL(string: "http://swapi.co/api/people/\(id)")!
networkLayer.fetchURLAndMap(url, completion: completion) { data in
return try self.personFactory.personFromData(data)
}
}
}
@@ -1,32 +0,0 @@
//
// NetworkLayer.swift
// Dip
//
// Created by Olivier Halligon on 05/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
protocol NetworkLayer {
func fetchURL(url: NSURL, completion: NSData? -> Void)
func fetchURLAndMap<T>(url: NSURL, completion: T? -> Void, transform: NSData throws -> T)
}
extension NetworkLayer {
func fetchURLAndMap<T>(url: NSURL, completion: T? -> Void, transform: NSData throws -> T) {
fetchURL(url) { (data: NSData?) -> Void in
guard let data = data else {
completion(nil)
return
}
let result: T?
do {
result = try transform(data)
} catch {
result = nil
}
completion(result)
}
}
}
@@ -1,14 +0,0 @@
//
// PersonFactoryAPI.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
protocol PersonFactoryAPI {
func peopleFromData(personData: NSData) throws -> [Person]
func personFromData(personData: NSData) throws -> Person
}
@@ -1,14 +0,0 @@
//
// PersonFormatterAPI.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
protocol PersonFormatterAPI {
func textForPerson(person: Person) -> String
func subtextForPerson(person: Person) -> String
}
@@ -1,13 +0,0 @@
//
// SerializerAPI.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
protocol SerializerAPI {
func dictionaryFromData(data: NSData) throws -> [String:AnyObject]
}
@@ -1,14 +0,0 @@
//
// WebServiceAPI.swift
// Dip
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
protocol WebServiceAPI {
func fetch(completion: [Person]? -> Void)
func fetch(id: Int, completion: Person? -> Void)
}
-14
View File
@@ -1,14 +0,0 @@
//
// Tags.swift
// Dip
//
// Created by Olivier Halligon on 05/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import Foundation
enum PersonFormatterTag {
case MassHeight
case EyesHair
}
-64
View File
@@ -1,64 +0,0 @@
//
// ViewController.swift
// DipSampleApp
//
// Created by Olivier Halligon on 04/10/2015.
// Copyright © 2015 AliSoftware. All rights reserved.
//
import UIKit
import Dip
let kCellIdentifier = "Cell"
class ViewController: UIViewController {
let ws = dip.resolve() as WebServiceAPI
var personList = [Person]()
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var displayModeSelector: UISegmentedControl!
@IBAction func fetchPeople(sender: UIButton) {
sender.enabled = false
self.activityIndicator.startAnimating()
ws.fetch { persons in
self.activityIndicator.stopAnimating()
sender.enabled = true
self.personList = persons ?? []
self.tableView.reloadData()
}
}
@IBAction func displayModeChanged(sender: UISegmentedControl) {
self.tableView.reloadData()
}
}
extension ViewController : UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.personList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath)
let person = personList[indexPath.row]
let formatter = dip.resolve(formatterTag) as PersonFormatterAPI
cell.textLabel?.text = formatter.textForPerson(person)
cell.detailTextLabel?.text = formatter.subtextForPerson(person)
return cell
}
var formatterTag: PersonFormatterTag {
switch displayModeSelector.selectedSegmentIndex {
case 0:
return .MassHeight
default:
return .EyesHair
}
}
}
-12
View File
@@ -1,12 +0,0 @@
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
platform :ios, '8.0'
target 'DipSampleApp' do
pod 'Dip', :path => '../'
end
target 'DipTests' do
pod "Dip", :path => '../'
end
-14
View File
@@ -1,14 +0,0 @@
PODS:
- Dip (0.1.0)
DEPENDENCIES:
- Dip (from `../`)
EXTERNAL SOURCES:
Dip:
:path: ../
SPEC CHECKSUMS:
Dip: c6d545af478b84d3708bf02d986fe687cb3322cc
COCOAPODS: 0.38.2
-21
View File
@@ -1,21 +0,0 @@
{
"name": "Dip",
"version": "0.1.0",
"summary": "A simple Dependency Resolver (Simplified Dependency Injection-like resolution).",
"description": "Dip is a Swift framework to manage your Dependencies between your classes\nin your app.\n\nIt's aimed to be very simple to use while improving testability\nof your app by allowing you to get rid of those sharedInstances and instead\ninject values based on protocol resolution.\n\nDefine your API using a protocol, then ask Dip to resolve this protocol into\nan instance dynamically in your classes. Then your App and your Tests can be\nconfigured to resolve the protocol using a different instance or class so this\nimprove testability by decoupling the API and the concrete class used to implement it.\n\nIt's not real Dependency Injection _per se_, but it's close.",
"homepage": "https://github.com/AliSoftware/Dip",
"license": "MIT",
"authors": {
"Olivier Halligon": "olivier@halligon.net"
},
"source": {
"git": "https://github.com/AliSoftware/Dip.git",
"tag": "0.1.0"
},
"social_media_url": "https://twitter.com/aligatr",
"platforms": {
"ios": "8.0"
},
"requires_arc": true,
"source_files": "Sources/**/*"
}
-14
View File
@@ -1,14 +0,0 @@
PODS:
- Dip (0.1.0)
DEPENDENCIES:
- Dip (from `../`)
EXTERNAL SOURCES:
Dip:
:path: ../
SPEC CHECKSUMS:
Dip: c6d545af478b84d3708bf02d986fe687cb3322cc
COCOAPODS: 0.38.2
-669
View File
@@ -1,669 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
4281B9E4626ED37910E70A6053051095 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2913DD9CC28CEF3EB44C812C80C5C242 /* Foundation.framework */; };
760ED030B3F9BF2B88E1F61BB696AF52 /* Pods-DipTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C6D62EFF728EC883AC33E16BEB08DA /* Pods-DipTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
848961CC560A7BF0C4CCEC7F49AD9D93 /* Dip-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B7737BE94231569FDA05F39555BABA9 /* Dip-dummy.m */; };
A56D11EEC8601D29B20437637A398FBE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2913DD9CC28CEF3EB44C812C80C5C242 /* Foundation.framework */; };
B43CB9F263659669B07655407B2663BD /* Pods-DipSampleApp-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 75D51085C4F230C1CC04D5C97D5CD181 /* Pods-DipSampleApp-dummy.m */; };
B7AF29D7DFAADCE1D059AB81388DC3A9 /* Dip.swift in Sources */ = {isa = PBXBuildFile; fileRef = E85D8C26DBEA227876D2B6BE49C060A3 /* Dip.swift */; };
B89AA8E9CD649EA8710AC177891DADF5 /* Pods-DipTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B538A5AA13D8CC5A2FB02B8C7E82ACB7 /* Pods-DipTests-dummy.m */; };
CBC622391FBCC36E48C7E3D295582D5A /* Dip-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8042B4793ED34FF6BB085F959C62C902 /* Dip-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
F71A77F6FC1D19954985C78BC04FFBCE /* Pods-DipSampleApp-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BB9324BB13F4127B03E00DAB78DF3D75 /* Pods-DipSampleApp-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
F8BB3BC94ED3830270E0447B6BA4D12D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2913DD9CC28CEF3EB44C812C80C5C242 /* Foundation.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
717E8357C15C9EC952989F1892DAADD9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 61B2C099D2823B76EB65B5ECC8B08934;
remoteInfo = Dip;
};
E1543D580D5FE849EA4540C35848C670 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 61B2C099D2823B76EB65B5ECC8B08934;
remoteInfo = Dip;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
040E6767354650F6353098E4EB50B3F7 /* Pods-DipSampleApp.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-DipSampleApp.modulemap"; sourceTree = "<group>"; };
093DB70F67DB4E609AB442CBB509D4E7 /* Pods-DipTests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DipTests-resources.sh"; sourceTree = "<group>"; };
17BD92E9BBD2033629156ED61085C674 /* Dip.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Dip.xcconfig; sourceTree = "<group>"; };
2913DD9CC28CEF3EB44C812C80C5C242 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
2DA289A9786072EC94A069BF0205D4D6 /* Dip-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Dip-prefix.pch"; sourceTree = "<group>"; };
3B7737BE94231569FDA05F39555BABA9 /* Dip-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Dip-dummy.m"; sourceTree = "<group>"; };
3BFEC463C4346DFBB40CFD331E7B8C8C /* Pods-DipSampleApp-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DipSampleApp-acknowledgements.plist"; sourceTree = "<group>"; };
4D03528B91AE7D78A28CE55BADFA6159 /* Pods-DipTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DipTests-acknowledgements.plist"; sourceTree = "<group>"; };
53E603F956BC0848C3DC16E858DAA805 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
56CC73CE7812C91DDB29DC2C84CE562F /* Dip-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Dip-Private.xcconfig"; sourceTree = "<group>"; };
6177EEC55F08DE3EBAB9A7AFFB99FA26 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
649D66F1DA814B5F17F49CA0D5948332 /* Pods_DipTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DipTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
65517CECF14CA488E474611D4E6C8A28 /* Pods_DipSampleApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DipSampleApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6571AF80F9340C8BBB03E41828B56DAE /* Pods-DipSampleApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DipSampleApp.release.xcconfig"; sourceTree = "<group>"; };
75D51085C4F230C1CC04D5C97D5CD181 /* Pods-DipSampleApp-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-DipSampleApp-dummy.m"; sourceTree = "<group>"; };
7C0F27E74B4689101CF66C46839222CA /* Pods-DipSampleApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DipSampleApp.debug.xcconfig"; sourceTree = "<group>"; };
8042B4793ED34FF6BB085F959C62C902 /* Dip-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Dip-umbrella.h"; sourceTree = "<group>"; };
865E74B4F963E602B5B976F7D5FFAA0A /* Dip.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Dip.modulemap; sourceTree = "<group>"; };
9B1020199AD13F9A6B345D4DA93D8FF0 /* Pods-DipTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DipTests.release.xcconfig"; sourceTree = "<group>"; };
A37235974396D8B3A4A2163B9FAF0328 /* Pods-DipSampleApp-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DipSampleApp-resources.sh"; sourceTree = "<group>"; };
AF0EA8CE3EB9D052ABA91BBDF5935932 /* Pods-DipSampleApp-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DipSampleApp-frameworks.sh"; sourceTree = "<group>"; };
B13AB9998F2CB1AA813B9AB7A6851FBA /* Pods-DipTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DipTests-frameworks.sh"; sourceTree = "<group>"; };
B538A5AA13D8CC5A2FB02B8C7E82ACB7 /* Pods-DipTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-DipTests-dummy.m"; sourceTree = "<group>"; };
BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
BB9324BB13F4127B03E00DAB78DF3D75 /* Pods-DipSampleApp-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DipSampleApp-umbrella.h"; sourceTree = "<group>"; };
CFFD5CBC2BC2688B5A6735AF757D7A13 /* Pods-DipTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DipTests.debug.xcconfig"; sourceTree = "<group>"; };
D5CB81F4D94CD0DC953C46A26FA193D9 /* Dip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Dip.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DD7CF98DF0A99296E41AF2D9C3B473F9 /* Pods-DipTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-DipTests-acknowledgements.markdown"; sourceTree = "<group>"; };
DDDDDD06DF5540C55DA4B0C74E1EC511 /* Pods-DipTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-DipTests.modulemap"; sourceTree = "<group>"; };
E2C25F36DD7F27E8BA0BDFFF808541A7 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E6C6D62EFF728EC883AC33E16BEB08DA /* Pods-DipTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DipTests-umbrella.h"; sourceTree = "<group>"; };
E85D8C26DBEA227876D2B6BE49C060A3 /* Dip.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Dip.swift; sourceTree = "<group>"; };
F5067212B9AFB98F7CCBC7151A60A220 /* Pods-DipSampleApp-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-DipSampleApp-acknowledgements.markdown"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
139BA28D38AF67B41F2223A714A1DE43 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A56D11EEC8601D29B20437637A398FBE /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7A84D2955EF7C71F5E6AF48E447815A1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4281B9E4626ED37910E70A6053051095 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FC3CB05065376B8016B026FD865ABAC0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F8BB3BC94ED3830270E0447B6BA4D12D /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
02DBDCD39FB1D88711D499C4EE8EE355 /* Pods-DipTests */ = {
isa = PBXGroup;
children = (
53E603F956BC0848C3DC16E858DAA805 /* Info.plist */,
DDDDDD06DF5540C55DA4B0C74E1EC511 /* Pods-DipTests.modulemap */,
DD7CF98DF0A99296E41AF2D9C3B473F9 /* Pods-DipTests-acknowledgements.markdown */,
4D03528B91AE7D78A28CE55BADFA6159 /* Pods-DipTests-acknowledgements.plist */,
B538A5AA13D8CC5A2FB02B8C7E82ACB7 /* Pods-DipTests-dummy.m */,
B13AB9998F2CB1AA813B9AB7A6851FBA /* Pods-DipTests-frameworks.sh */,
093DB70F67DB4E609AB442CBB509D4E7 /* Pods-DipTests-resources.sh */,
E6C6D62EFF728EC883AC33E16BEB08DA /* Pods-DipTests-umbrella.h */,
CFFD5CBC2BC2688B5A6735AF757D7A13 /* Pods-DipTests.debug.xcconfig */,
9B1020199AD13F9A6B345D4DA93D8FF0 /* Pods-DipTests.release.xcconfig */,
);
name = "Pods-DipTests";
path = "Target Support Files/Pods-DipTests";
sourceTree = "<group>";
};
331BF982C22B5DA66B25F742D01C5F7D /* Dip */ = {
isa = PBXGroup;
children = (
FAEF7893A179133A40296BA56F7E8846 /* Sources */,
7BF12AE4821DF0409A5DD1E494A23CB0 /* Support Files */,
);
name = Dip;
path = ../..;
sourceTree = "<group>";
};
46E7572EB1611944AB13E50F656187E9 /* Development Pods */ = {
isa = PBXGroup;
children = (
331BF982C22B5DA66B25F742D01C5F7D /* Dip */,
);
name = "Development Pods";
sourceTree = "<group>";
};
53F661C0CA7190D2CF05023FB33D61E4 /* iOS */ = {
isa = PBXGroup;
children = (
2913DD9CC28CEF3EB44C812C80C5C242 /* Foundation.framework */,
);
name = iOS;
sourceTree = "<group>";
};
7BF12AE4821DF0409A5DD1E494A23CB0 /* Support Files */ = {
isa = PBXGroup;
children = (
865E74B4F963E602B5B976F7D5FFAA0A /* Dip.modulemap */,
17BD92E9BBD2033629156ED61085C674 /* Dip.xcconfig */,
56CC73CE7812C91DDB29DC2C84CE562F /* Dip-Private.xcconfig */,
3B7737BE94231569FDA05F39555BABA9 /* Dip-dummy.m */,
2DA289A9786072EC94A069BF0205D4D6 /* Dip-prefix.pch */,
8042B4793ED34FF6BB085F959C62C902 /* Dip-umbrella.h */,
6177EEC55F08DE3EBAB9A7AFFB99FA26 /* Info.plist */,
);
name = "Support Files";
path = "Example/Pods/Target Support Files/Dip";
sourceTree = "<group>";
};
7DB346D0F39D3F0E887471402A8071AB = {
isa = PBXGroup;
children = (
BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */,
46E7572EB1611944AB13E50F656187E9 /* Development Pods */,
BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */,
CCA510CFBEA2D207524CDA0D73C3B561 /* Products */,
A9D31FC7B7A14D2E4651A6C66A1A86EC /* Targets Support Files */,
);
sourceTree = "<group>";
};
A9D31FC7B7A14D2E4651A6C66A1A86EC /* Targets Support Files */ = {
isa = PBXGroup;
children = (
E6EDC7112547C1E567413310A74E6AB2 /* Pods-DipSampleApp */,
02DBDCD39FB1D88711D499C4EE8EE355 /* Pods-DipTests */,
);
name = "Targets Support Files";
sourceTree = "<group>";
};
BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = {
isa = PBXGroup;
children = (
53F661C0CA7190D2CF05023FB33D61E4 /* iOS */,
);
name = Frameworks;
sourceTree = "<group>";
};
CCA510CFBEA2D207524CDA0D73C3B561 /* Products */ = {
isa = PBXGroup;
children = (
D5CB81F4D94CD0DC953C46A26FA193D9 /* Dip.framework */,
65517CECF14CA488E474611D4E6C8A28 /* Pods_DipSampleApp.framework */,
649D66F1DA814B5F17F49CA0D5948332 /* Pods_DipTests.framework */,
);
name = Products;
sourceTree = "<group>";
};
E6EDC7112547C1E567413310A74E6AB2 /* Pods-DipSampleApp */ = {
isa = PBXGroup;
children = (
E2C25F36DD7F27E8BA0BDFFF808541A7 /* Info.plist */,
040E6767354650F6353098E4EB50B3F7 /* Pods-DipSampleApp.modulemap */,
F5067212B9AFB98F7CCBC7151A60A220 /* Pods-DipSampleApp-acknowledgements.markdown */,
3BFEC463C4346DFBB40CFD331E7B8C8C /* Pods-DipSampleApp-acknowledgements.plist */,
75D51085C4F230C1CC04D5C97D5CD181 /* Pods-DipSampleApp-dummy.m */,
AF0EA8CE3EB9D052ABA91BBDF5935932 /* Pods-DipSampleApp-frameworks.sh */,
A37235974396D8B3A4A2163B9FAF0328 /* Pods-DipSampleApp-resources.sh */,
BB9324BB13F4127B03E00DAB78DF3D75 /* Pods-DipSampleApp-umbrella.h */,
7C0F27E74B4689101CF66C46839222CA /* Pods-DipSampleApp.debug.xcconfig */,
6571AF80F9340C8BBB03E41828B56DAE /* Pods-DipSampleApp.release.xcconfig */,
);
name = "Pods-DipSampleApp";
path = "Target Support Files/Pods-DipSampleApp";
sourceTree = "<group>";
};
FAEF7893A179133A40296BA56F7E8846 /* Sources */ = {
isa = PBXGroup;
children = (
E85D8C26DBEA227876D2B6BE49C060A3 /* Dip.swift */,
);
path = Sources;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
20D2FAD8897F05F0F21B6E88F602A8B1 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
CBC622391FBCC36E48C7E3D295582D5A /* Dip-umbrella.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
757551662869B25EE206B19D53CC8F29 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
760ED030B3F9BF2B88E1F61BB696AF52 /* Pods-DipTests-umbrella.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8F49CC8E1874111D7EF4D173435D7A24 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
F71A77F6FC1D19954985C78BC04FFBCE /* Pods-DipSampleApp-umbrella.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
12D3E41651D0F284852A4D526F3256AB /* Pods-DipTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = D7E091A3E6CE5EC7EA78C29D8A21CA70 /* Build configuration list for PBXNativeTarget "Pods-DipTests" */;
buildPhases = (
AAA3A1408B53FD669A84EBE81D8355D0 /* Sources */,
7A84D2955EF7C71F5E6AF48E447815A1 /* Frameworks */,
757551662869B25EE206B19D53CC8F29 /* Headers */,
);
buildRules = (
);
dependencies = (
59D193CC66DB380EE84635F4E2991CAF /* PBXTargetDependency */,
);
name = "Pods-DipTests";
productName = "Pods-DipTests";
productReference = 649D66F1DA814B5F17F49CA0D5948332 /* Pods_DipTests.framework */;
productType = "com.apple.product-type.framework";
};
61B2C099D2823B76EB65B5ECC8B08934 /* Dip */ = {
isa = PBXNativeTarget;
buildConfigurationList = CA02FBD0A4DFAC6631999B9E5DEAA891 /* Build configuration list for PBXNativeTarget "Dip" */;
buildPhases = (
27301CA68EAB0531B3E302342BE6B391 /* Sources */,
139BA28D38AF67B41F2223A714A1DE43 /* Frameworks */,
20D2FAD8897F05F0F21B6E88F602A8B1 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = Dip;
productName = Dip;
productReference = D5CB81F4D94CD0DC953C46A26FA193D9 /* Dip.framework */;
productType = "com.apple.product-type.framework";
};
F588C5114410BDD4CA3AF7BF16AF6FC8 /* Pods-DipSampleApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9ECD5CC6E806AF1E5D7F66D29B6DDADD /* Build configuration list for PBXNativeTarget "Pods-DipSampleApp" */;
buildPhases = (
811AA0482F2A12B79AFCB6A2C9AFA4A1 /* Sources */,
FC3CB05065376B8016B026FD865ABAC0 /* Frameworks */,
8F49CC8E1874111D7EF4D173435D7A24 /* Headers */,
);
buildRules = (
);
dependencies = (
E87C16215529DC10230F8D3773193425 /* PBXTargetDependency */,
);
name = "Pods-DipSampleApp";
productName = "Pods-DipSampleApp";
productReference = 65517CECF14CA488E474611D4E6C8A28 /* Pods_DipSampleApp.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D41D8CD98F00B204E9800998ECF8427E /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
};
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 7DB346D0F39D3F0E887471402A8071AB;
productRefGroup = CCA510CFBEA2D207524CDA0D73C3B561 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
61B2C099D2823B76EB65B5ECC8B08934 /* Dip */,
F588C5114410BDD4CA3AF7BF16AF6FC8 /* Pods-DipSampleApp */,
12D3E41651D0F284852A4D526F3256AB /* Pods-DipTests */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
27301CA68EAB0531B3E302342BE6B391 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
848961CC560A7BF0C4CCEC7F49AD9D93 /* Dip-dummy.m in Sources */,
B7AF29D7DFAADCE1D059AB81388DC3A9 /* Dip.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
811AA0482F2A12B79AFCB6A2C9AFA4A1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B43CB9F263659669B07655407B2663BD /* Pods-DipSampleApp-dummy.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
AAA3A1408B53FD669A84EBE81D8355D0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B89AA8E9CD649EA8710AC177891DADF5 /* Pods-DipTests-dummy.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
59D193CC66DB380EE84635F4E2991CAF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Dip;
target = 61B2C099D2823B76EB65B5ECC8B08934 /* Dip */;
targetProxy = 717E8357C15C9EC952989F1892DAADD9 /* PBXContainerItemProxy */;
};
E87C16215529DC10230F8D3773193425 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Dip;
target = 61B2C099D2823B76EB65B5ECC8B08934 /* Dip */;
targetProxy = E1543D580D5FE849EA4540C35848C670 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
179C38BF617A5FDB3138E3FBBCFBCF96 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 56CC73CE7812C91DDB29DC2C84CE562F /* Dip-Private.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 0.1.0;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 0.1.0;
DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)";
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_PREFIX_HEADER = "Target Support Files/Dip/Dip-prefix.pch";
INFOPLIST_FILE = "Target Support Files/Dip/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/Dip/Dip.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = Dip;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
1858E18D65A8B61BEAE72BD61ED409B9 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7C0F27E74B4689101CF66C46839222CA /* Pods-DipSampleApp.debug.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
INFOPLIST_FILE = "Target Support Files/Pods-DipSampleApp/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/Pods-DipSampleApp/Pods-DipSampleApp.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_NAME = Pods_DipSampleApp;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
530E51D69A65177A0CB8BA9337627948 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9B1020199AD13F9A6B345D4DA93D8FF0 /* Pods-DipTests.release.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
INFOPLIST_FILE = "Target Support Files/Pods-DipTests/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/Pods-DipTests/Pods-DipTests.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_NAME = Pods_DipTests;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
956BB501D5CF8EBD179183A55861D46E /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 6571AF80F9340C8BBB03E41828B56DAE /* Pods-DipSampleApp.release.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
INFOPLIST_FILE = "Target Support Files/Pods-DipSampleApp/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/Pods-DipSampleApp/Pods-DipSampleApp.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_NAME = Pods_DipSampleApp;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
9867AC43F4246CE452AFD55B859928CC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 56CC73CE7812C91DDB29DC2C84CE562F /* Dip-Private.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 0.1.0;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 0.1.0;
DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)";
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_PREFIX_HEADER = "Target Support Files/Dip/Dip-prefix.pch";
INFOPLIST_FILE = "Target Support Files/Dip/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/Dip/Dip.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = Dip;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
A70CDAD61F90AC503C7D04CC22DA2923 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
ONLY_ACTIVE_ARCH = YES;
STRIP_INSTALLED_PRODUCT = NO;
SYMROOT = "${SRCROOT}/../build";
};
name = Debug;
};
A72E6B5B0A3D3E28381E5C0A7A93C0A5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = CFFD5CBC2BC2688B5A6735AF757D7A13 /* Pods-DipTests.debug.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
INFOPLIST_FILE = "Target Support Files/Pods-DipTests/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/Pods-DipTests/Pods-DipTests.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_NAME = Pods_DipTests;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
FB45FFD90572718D82AB9092B750F0CA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
STRIP_INSTALLED_PRODUCT = NO;
SYMROOT = "${SRCROOT}/../build";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A70CDAD61F90AC503C7D04CC22DA2923 /* Debug */,
FB45FFD90572718D82AB9092B750F0CA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9ECD5CC6E806AF1E5D7F66D29B6DDADD /* Build configuration list for PBXNativeTarget "Pods-DipSampleApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1858E18D65A8B61BEAE72BD61ED409B9 /* Debug */,
956BB501D5CF8EBD179183A55861D46E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CA02FBD0A4DFAC6631999B9E5DEAA891 /* Build configuration list for PBXNativeTarget "Dip" */ = {
isa = XCConfigurationList;
buildConfigurations = (
179C38BF617A5FDB3138E3FBBCFBCF96 /* Debug */,
9867AC43F4246CE452AFD55B859928CC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D7E091A3E6CE5EC7EA78C29D8A21CA70 /* Build configuration list for PBXNativeTarget "Pods-DipTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A72E6B5B0A3D3E28381E5C0A7A93C0A5 /* Debug */,
530E51D69A65177A0CB8BA9337627948 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
}
@@ -1,6 +0,0 @@
#include "Dip.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Dip" "${PODS_ROOT}/Headers/Public"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_ROOT = ${SRCROOT}
SKIP_INSTALL = YES
-5
View File
@@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Dip : NSObject
@end
@implementation PodsDummy_Dip
@end
-4
View File
@@ -1,4 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
-6
View File
@@ -1,6 +0,0 @@
#import <UIKit/UIKit.h>
FOUNDATION_EXPORT double DipVersionNumber;
FOUNDATION_EXPORT const unsigned char DipVersionString[];
-6
View File
@@ -1,6 +0,0 @@
framework module Dip {
umbrella header "Dip-umbrella.h"
export *
module * { export * }
}
View File
-26
View File
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -1,26 +0,0 @@
# Acknowledgements
This application makes use of the following third party libraries:
## Dip
Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Generated by CocoaPods - http://cocoapods.org
@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2015 Olivier Halligon &lt;olivier@halligon.net&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</string>
<key>Title</key>
<string>Dip</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - http://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>
@@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_DipSampleApp : NSObject
@end
@implementation PodsDummy_Pods_DipSampleApp
@end
@@ -1,59 +0,0 @@
#!/bin/sh
set -e
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
install_framework()
{
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
local source="${BUILT_PRODUCTS_DIR}/$1"
else
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
fi
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L "${source}" ]; then
echo "Symlinked..."
source="$(readlink "${source}")"
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
# Resign the code if required by the build settings to avoid unstable apps
code_sign_if_enabled "${destination}/$(basename "$1")"
# Embed linked Swift runtime libraries
local basename
basename="$(basename "$1" | sed -E s/\\..+// && exit ${PIPESTATUS[0]})"
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
code_sign_if_enabled "${destination}/${lib}"
done
}
# Signs a framework with the provided identity
code_sign_if_enabled() {
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
# Use the current code_sign_identitiy
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\""
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
fi
}
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework 'Pods-DipSampleApp/Dip.framework'
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework 'Pods-DipSampleApp/Dip.framework'
fi
@@ -1,95 +0,0 @@
#!/bin/sh
set -e
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
XCASSET_FILES=()
realpath() {
DIRECTORY="$(cd "${1%/*}" && pwd)"
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
case $1 in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.framework)
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1")
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
/*)
echo "$1"
echo "$1" >> "$RESOURCES_TO_COPY"
;;
*)
echo "${PODS_ROOT}/$1"
echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
;;
esac
}
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]]; then
mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
@@ -1,6 +0,0 @@
#import <UIKit/UIKit.h>
FOUNDATION_EXPORT double Pods_DipSampleAppVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_DipSampleAppVersionString[];
@@ -1,7 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Dip.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "Dip"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-DipSampleApp
PODS_ROOT = ${SRCROOT}/Pods
@@ -1,6 +0,0 @@
framework module Pods_DipSampleApp {
umbrella header "Pods-DipSampleApp-umbrella.h"
export *
module * { export * }
}
@@ -1,7 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Dip.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "Dip"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-DipSampleApp
PODS_ROOT = ${SRCROOT}/Pods
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -1,26 +0,0 @@
# Acknowledgements
This application makes use of the following third party libraries:
## Dip
Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Generated by CocoaPods - http://cocoapods.org
@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2015 Olivier Halligon &lt;olivier@halligon.net&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</string>
<key>Title</key>
<string>Dip</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - http://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>
@@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_DipTests : NSObject
@end
@implementation PodsDummy_Pods_DipTests
@end
@@ -1,59 +0,0 @@
#!/bin/sh
set -e
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
install_framework()
{
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
local source="${BUILT_PRODUCTS_DIR}/$1"
else
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
fi
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L "${source}" ]; then
echo "Symlinked..."
source="$(readlink "${source}")"
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
# Resign the code if required by the build settings to avoid unstable apps
code_sign_if_enabled "${destination}/$(basename "$1")"
# Embed linked Swift runtime libraries
local basename
basename="$(basename "$1" | sed -E s/\\..+// && exit ${PIPESTATUS[0]})"
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
code_sign_if_enabled "${destination}/${lib}"
done
}
# Signs a framework with the provided identity
code_sign_if_enabled() {
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
# Use the current code_sign_identitiy
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\""
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
fi
}
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework 'Pods-DipTests/Dip.framework'
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework 'Pods-DipTests/Dip.framework'
fi
@@ -1,95 +0,0 @@
#!/bin/sh
set -e
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
XCASSET_FILES=()
realpath() {
DIRECTORY="$(cd "${1%/*}" && pwd)"
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
case $1 in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.framework)
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1")
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
/*)
echo "$1"
echo "$1" >> "$RESOURCES_TO_COPY"
;;
*)
echo "${PODS_ROOT}/$1"
echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
;;
esac
}
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]]; then
mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
@@ -1,6 +0,0 @@
#import <UIKit/UIKit.h>
FOUNDATION_EXPORT double Pods_DipTestsVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_DipTestsVersionString[];
@@ -1,7 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Dip.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "Dip"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-DipTests
PODS_ROOT = ${SRCROOT}/Pods
@@ -1,6 +0,0 @@
framework module Pods_DipTests {
umbrella header "Pods-DipTests-umbrella.h"
export *
module * { export * }
}
@@ -1,7 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Dip.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "Dip"
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-DipTests
PODS_ROOT = ${SRCROOT}/Pods
-89
View File
@@ -1,89 +0,0 @@
import UIKit
import XCTest
import Dip
var dip = DependencyContainer<PersonFormatterTag>()
let p1 = ["name": "John Doe", "mass": "72", "height": "172", "eye_color": "brown", "hair_color": "black"]
let p2 = ["name": "Jane Doe", "mass": "63", "height": "167", "eye_color": "blue", "hair_color": "red"]
class SWAPIWebServiceTests: XCTestCase {
// MARK: - Mock object used for tests
struct NetworkMock : NetworkLayer {
let fakeData: NSData?
init(json: AnyObject) {
do {
fakeData = try NSJSONSerialization.dataWithJSONObject(json, options: [])
} catch {
fakeData = nil
}
}
func fetchURL(url: NSURL, completion: NSData? -> Void) {
completion(fakeData)
}
}
// MARK: - Test Suite
override func setUp() {
super.setUp()
dip.reset()
dip.register(instance: SWAPIPersonFactory() as PersonFactoryAPI)
dip.register(instance: JSONSerializer() as SerializerAPI)
}
func testFetchPersons() {
let mock = NetworkMock(json: ["results":[p1,p2]])
dip.register(instance: mock as NetworkLayer)
let ws = SWAPIWebService()
ws.fetch { persons in
XCTAssertNotNil(persons)
XCTAssertEqual(persons?.count, 2)
XCTAssertEqual(persons?[0].name, "John Doe")
XCTAssertEqual(persons?[0].mass, 72)
XCTAssertEqual(persons?[0].height, 172)
XCTAssertEqual(persons?[0].eyesColor, "brown")
XCTAssertEqual(persons?[0].hairColor, "black")
XCTAssertEqual(persons?[1].name, "Jane Doe")
XCTAssertEqual(persons?[1].mass, 63)
XCTAssertEqual(persons?[1].height, 167)
XCTAssertEqual(persons?[1].eyesColor, "blue")
XCTAssertEqual(persons?[1].hairColor, "red")
}
}
func testFetchOnePerson() {
let mock = NetworkMock(json: p1)
dip.register(instance: mock as NetworkLayer)
let ws = SWAPIWebService()
ws.fetch(1) { person in
XCTAssertNotNil(person)
XCTAssertEqual(person?.name, "John Doe")
XCTAssertEqual(person?.mass, 72)
XCTAssertEqual(person?.height, 172)
XCTAssertEqual(person?.eyesColor, "brown")
XCTAssertEqual(person?.hairColor, "black")
}
}
func testFetchInvalidPerson() {
let json = ["error":"whoops"]
let mock = NetworkMock(json: json)
dip.register(instance: mock as NetworkLayer)
let ws = SWAPIWebService()
ws.fetch(12) { person in
XCTAssertNil(person)
}
}
}

Some files were not shown because too many files have changed in this diff Show More