├── .gitignore
├── LICENSE
├── Package.swift
├── README.md
├── Sources
├── Info.plist
├── Weakable.h
└── Weakable.swift
├── WeakableSelf.podspec
├── WeakableSelf.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ └── Weakable.xcscheme
└── WeakableSelfTests
├── Info.plist
└── WeakableSelfTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | # Package.resolved
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 | Carthage/Build
57 |
58 | # fastlane
59 | #
60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
61 | # screenshots whenever they are needed.
62 | # For more information about the recommended setup visit:
63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
64 |
65 | fastlane/report.xml
66 | fastlane/Preview.html
67 | fastlane/screenshots/**/*.png
68 | fastlane/test_output
69 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Vincent Pradeilles
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:4.2
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "WeakableSelf",
6 | products: [
7 | .library(
8 | name: "WeakableSelf",
9 | targets: ["WeakableSelf"]
10 | )
11 | ],
12 | dependencies: [],
13 | targets: [
14 | .target(
15 | name: "WeakableSelf",
16 | dependencies: [],
17 | path: "Sources"
18 | ),
19 | .testTarget(
20 | name: "WeakableSelfTests",
21 | dependencies: ["WeakableSelf"],
22 | path: "WeakableSelfTests"
23 | )
24 | ]
25 | )
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WeakableSelf
2 |
3 | 
4 | 
5 | [](https://github.com/Carthage/Carthage)
6 |
7 | ## Context
8 |
9 | Closures are one of Swift must-have features, and Swift developers are aware of how tricky they can be when they capture the reference of an external object, especially when this object is `self`.
10 |
11 | To deal with this issue, developers are required to write additional code, using constructs such as `[weak self]` and `guard`, and the result looks like the following:
12 |
13 | ```swift
14 | service.call(completion: { [weak self] result in
15 | guard let self = self else { return }
16 |
17 | // use weak non-optional `self` to handle `result`
18 | })
19 | ```
20 |
21 | ## Purpose of `WeakableSelf`
22 |
23 | The purpose of this micro-framework is to provide the developer with a helper function `weakify` that will allow him to declaratively indicate that he wishes to use a weak non-optional reference to `self` in closure, and not worry about how this reference is provided.
24 |
25 | ## Usage
26 |
27 | Using this `weakify` function, the code above will be transformed into the much more concise:
28 |
29 | ```swift
30 | import WeakableSelf
31 |
32 | service.call(completion: weakify { strongSelf, result in
33 | // use weak non-optional `strongSelf` to handle `result`
34 | })
35 | ```
36 |
37 | `weakify` works with closures that take up to 7 arguments.
38 |
39 | ## Installation
40 |
41 | ### Requirements
42 |
43 | * Swift 4.2+
44 | * Xcode 10+
45 |
46 | ### CocoaPods
47 |
48 | Add the following to your `Podfile`:
49 |
50 | `pod "WeakableSelf"`
51 |
52 | ### Carthage
53 |
54 | Add the following to your `Cartfile`:
55 |
56 | `github "vincent-pradeilles/weakable-self"`
57 |
--------------------------------------------------------------------------------
/Sources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Sources/Weakable.h:
--------------------------------------------------------------------------------
1 | //
2 | // WeakableSelf.h
3 | // WeakableSelf
4 | //
5 | // Created by Vincent on 04/10/2018.
6 | // Copyright © 2018 Vincent. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for WeakableSelf.
12 | FOUNDATION_EXPORT double WeakableSelfVersionNumber;
13 |
14 | //! Project version string for WeakableSelf.
15 | FOUNDATION_EXPORT const unsigned char WeakableSelfVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Sources/Weakable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Weakable.swift
3 | // WeakableSelf
4 | //
5 | // Created by Vincent on 04/10/2018.
6 | // Copyright © 2018 Vincent. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol Weakable: class { }
12 |
13 | extension NSObject: Weakable { }
14 |
15 | public extension Weakable {
16 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self) -> ReturnType) -> () -> ReturnType {
17 | return { [weak self] in
18 | guard let self = self else { return defaultValue }
19 |
20 | return code(self)
21 | }
22 | }
23 |
24 | func weakify(_ code: @escaping (Self) -> Void) -> () -> Void {
25 | return weakify(defaultValue: (), code)
26 | }
27 |
28 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A) -> ReturnType) -> (A) -> ReturnType {
29 | return { [weak self] a in
30 | guard let self = self else { return defaultValue }
31 |
32 | return code(self, a)
33 | }
34 | }
35 |
36 | func weakify(_ code: @escaping (Self, A) -> Void) -> (A) -> Void {
37 | return weakify(defaultValue: (), code)
38 | }
39 |
40 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A, B) -> ReturnType) -> (A, B) -> ReturnType {
41 | return { [weak self] a, b in
42 | guard let self = self else { return defaultValue }
43 |
44 | return code(self, a, b)
45 | }
46 | }
47 |
48 | func weakify(_ code: @escaping (Self, A, B) -> Void) -> (A, B) -> Void {
49 | return weakify(defaultValue: (), code)
50 | }
51 |
52 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A, B, C) -> ReturnType) -> (A, B, C) -> ReturnType {
53 | return { [weak self] a, b, c in
54 | guard let self = self else { return defaultValue }
55 |
56 | return code(self, a, b, c)
57 | }
58 | }
59 |
60 | func weakify(_ code: @escaping (Self, A, B, C) -> Void) -> (A, B, C) -> Void {
61 | return weakify(defaultValue: (), code)
62 | }
63 |
64 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A, B, C, D) -> ReturnType) -> (A, B, C, D) -> ReturnType {
65 | return { [weak self] a, b, c, d in
66 | guard let self = self else { return defaultValue }
67 |
68 | return code(self, a, b, c, d)
69 | }
70 | }
71 |
72 | func weakify(_ code: @escaping (Self, A, B, C, D) -> Void) -> (A, B, C, D) -> Void {
73 | return weakify(defaultValue: (), code)
74 | }
75 |
76 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A, B, C, D, E) -> ReturnType) -> (A, B, C, D, E) -> ReturnType {
77 | return { [weak self] a, b, c, d, e in
78 | guard let self = self else { return defaultValue }
79 |
80 | return code(self, a, b, c, d, e)
81 | }
82 | }
83 |
84 | func weakify(_ code: @escaping (Self, A, B, C, D, E) -> Void) -> (A, B, C, D, E) -> Void {
85 | return weakify(defaultValue: (), code)
86 | }
87 |
88 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A, B, C, D, E, F) -> ReturnType) -> (A, B, C, D, E, F) -> ReturnType {
89 | return { [weak self] a, b, c, d, e, f in
90 | guard let self = self else { return defaultValue }
91 |
92 | return code(self, a, b, c, d, e, f)
93 | }
94 | }
95 |
96 | func weakify(_ code: @escaping (Self, A, B, C, D, E, F) -> Void) -> (A, B, C, D, E, F) -> Void {
97 | return weakify(defaultValue: (), code)
98 | }
99 |
100 | func weakify(defaultValue: ReturnType, _ code: @escaping (Self, A, B, C, D, E, F, G) -> ReturnType) -> (A, B, C, D, E, F, G) -> ReturnType {
101 | return { [weak self] a, b, c, d, e, f, g in
102 | guard let self = self else { return defaultValue }
103 |
104 | return code(self, a, b, c, d, e, f, g)
105 | }
106 | }
107 |
108 | func weakify(_ code: @escaping (Self, A, B, C, D, E, F, G) -> Void) -> (A, B, C, D, E, F, G) -> Void {
109 | return weakify(defaultValue: (), code)
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/WeakableSelf.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'WeakableSelf'
3 | s.version = '1.1.1'
4 | s.summary = 'A Swift micro-framework to easily deal with weak references to self inside closures'
5 |
6 | s.description = <<-DESC
7 | Closures are one of Swift must-have features, and Swift developers are aware of how tricky they can be when they capture the reference of an external object, especially when this object is self.
8 |
9 | To deal with this issue, developers are required to write additional code, using constructs such as [weak self] and guard, and the result looks like the following:
10 |
11 | service.call(completion: { [weak self] result in
12 | guard let self = self else { return }
13 |
14 | // use weak non-optional `self` to handle `result`
15 | })
16 |
17 | The purpose of this micro-framework is to provide the developer with a helper function weakify that will allow him to declaratively indicate that he wishes to use a weak non-optional reference to self in closure, and not worry about how this reference is provided.
18 |
19 | Using this weakify function, the code above will be transformed into the much more concise:
20 |
21 | import WeakableSelf
22 |
23 | service.call(completion: weakify { result, strongSelf in
24 | // use weak non-optional `strongSelf` to handle `result`
25 | })
26 |
27 | `weakify` works with closures that take up to 7 arguments.
28 | DESC
29 |
30 | s.homepage = 'https://github.com/vincent-pradeilles/weakable-self'
31 | s.license = { :type => 'MIT', :file => 'LICENSE' }
32 | s.author = { 'Vincent Pradeilles' => 'vin.pradeilles+weakableself@gmail.com' }
33 | s.source = { :git => 'https://github.com/vincent-pradeilles/weakable-self.git', :tag => s.version.to_s }
34 |
35 | s.swift_version = '4.2'
36 |
37 | s.ios.deployment_target = '9.0'
38 | s.tvos.deployment_target = '10.0'
39 | s.osx.deployment_target = '10.12'
40 | s.watchos.deployment_target = "3.0"
41 |
42 | s.framework = 'Foundation'
43 |
44 | s.source_files = 'Sources/**/*.swift'
45 |
46 | end
47 |
--------------------------------------------------------------------------------
/WeakableSelf.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | BF31CECA21669A93002A7F3D /* WeakableSelf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF31CEC021669A93002A7F3D /* WeakableSelf.framework */; };
11 | BF31CECF21669A93002A7F3D /* WeakableSelfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF31CECE21669A93002A7F3D /* WeakableSelfTests.swift */; };
12 | BF5CD87C2166A9B6000B42E0 /* Weakable.h in Headers */ = {isa = PBXBuildFile; fileRef = BF5CD8792166A9B6000B42E0 /* Weakable.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | BF5CD87E2166A9B6000B42E0 /* Weakable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5CD87B2166A9B6000B42E0 /* Weakable.swift */; };
14 | /* End PBXBuildFile section */
15 |
16 | /* Begin PBXContainerItemProxy section */
17 | BF31CECB21669A93002A7F3D /* PBXContainerItemProxy */ = {
18 | isa = PBXContainerItemProxy;
19 | containerPortal = BF31CEB721669A93002A7F3D /* Project object */;
20 | proxyType = 1;
21 | remoteGlobalIDString = BF31CEBF21669A93002A7F3D;
22 | remoteInfo = Weakable;
23 | };
24 | /* End PBXContainerItemProxy section */
25 |
26 | /* Begin PBXFileReference section */
27 | BF31CEC021669A93002A7F3D /* WeakableSelf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WeakableSelf.framework; sourceTree = BUILT_PRODUCTS_DIR; };
28 | BF31CEC921669A93002A7F3D /* WeakableSelfTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WeakableSelfTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
29 | BF31CECE21669A93002A7F3D /* WeakableSelfTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakableSelfTests.swift; sourceTree = ""; };
30 | BF31CED021669A93002A7F3D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | BF5CD8792166A9B6000B42E0 /* Weakable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Weakable.h; sourceTree = ""; };
32 | BF5CD87A2166A9B6000B42E0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | BF5CD87B2166A9B6000B42E0 /* Weakable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weakable.swift; sourceTree = ""; };
34 | /* End PBXFileReference section */
35 |
36 | /* Begin PBXFrameworksBuildPhase section */
37 | BF31CEBD21669A93002A7F3D /* Frameworks */ = {
38 | isa = PBXFrameworksBuildPhase;
39 | buildActionMask = 2147483647;
40 | files = (
41 | );
42 | runOnlyForDeploymentPostprocessing = 0;
43 | };
44 | BF31CEC621669A93002A7F3D /* Frameworks */ = {
45 | isa = PBXFrameworksBuildPhase;
46 | buildActionMask = 2147483647;
47 | files = (
48 | BF31CECA21669A93002A7F3D /* WeakableSelf.framework in Frameworks */,
49 | );
50 | runOnlyForDeploymentPostprocessing = 0;
51 | };
52 | /* End PBXFrameworksBuildPhase section */
53 |
54 | /* Begin PBXGroup section */
55 | BF31CEB621669A93002A7F3D = {
56 | isa = PBXGroup;
57 | children = (
58 | BF5CD8782166A9B6000B42E0 /* Sources */,
59 | BF31CECD21669A93002A7F3D /* WeakableSelfTests */,
60 | BF31CEC121669A93002A7F3D /* Products */,
61 | );
62 | sourceTree = "";
63 | };
64 | BF31CEC121669A93002A7F3D /* Products */ = {
65 | isa = PBXGroup;
66 | children = (
67 | BF31CEC021669A93002A7F3D /* WeakableSelf.framework */,
68 | BF31CEC921669A93002A7F3D /* WeakableSelfTests.xctest */,
69 | );
70 | name = Products;
71 | sourceTree = "";
72 | };
73 | BF31CECD21669A93002A7F3D /* WeakableSelfTests */ = {
74 | isa = PBXGroup;
75 | children = (
76 | BF31CECE21669A93002A7F3D /* WeakableSelfTests.swift */,
77 | BF31CED021669A93002A7F3D /* Info.plist */,
78 | );
79 | path = WeakableSelfTests;
80 | sourceTree = "";
81 | };
82 | BF5CD8782166A9B6000B42E0 /* Sources */ = {
83 | isa = PBXGroup;
84 | children = (
85 | BF5CD8792166A9B6000B42E0 /* Weakable.h */,
86 | BF5CD87A2166A9B6000B42E0 /* Info.plist */,
87 | BF5CD87B2166A9B6000B42E0 /* Weakable.swift */,
88 | );
89 | path = Sources;
90 | sourceTree = "";
91 | };
92 | /* End PBXGroup section */
93 |
94 | /* Begin PBXHeadersBuildPhase section */
95 | BF31CEBB21669A93002A7F3D /* Headers */ = {
96 | isa = PBXHeadersBuildPhase;
97 | buildActionMask = 2147483647;
98 | files = (
99 | BF5CD87C2166A9B6000B42E0 /* Weakable.h in Headers */,
100 | );
101 | runOnlyForDeploymentPostprocessing = 0;
102 | };
103 | /* End PBXHeadersBuildPhase section */
104 |
105 | /* Begin PBXNativeTarget section */
106 | BF31CEBF21669A93002A7F3D /* WeakableSelf */ = {
107 | isa = PBXNativeTarget;
108 | buildConfigurationList = BF31CED421669A93002A7F3D /* Build configuration list for PBXNativeTarget "WeakableSelf" */;
109 | buildPhases = (
110 | BF31CEBB21669A93002A7F3D /* Headers */,
111 | BF31CEBC21669A93002A7F3D /* Sources */,
112 | BF31CEBD21669A93002A7F3D /* Frameworks */,
113 | BF31CEBE21669A93002A7F3D /* Resources */,
114 | );
115 | buildRules = (
116 | );
117 | dependencies = (
118 | );
119 | name = WeakableSelf;
120 | productName = Weakable;
121 | productReference = BF31CEC021669A93002A7F3D /* WeakableSelf.framework */;
122 | productType = "com.apple.product-type.framework";
123 | };
124 | BF31CEC821669A93002A7F3D /* WeakableSelfTests */ = {
125 | isa = PBXNativeTarget;
126 | buildConfigurationList = BF31CED721669A93002A7F3D /* Build configuration list for PBXNativeTarget "WeakableSelfTests" */;
127 | buildPhases = (
128 | BF31CEC521669A93002A7F3D /* Sources */,
129 | BF31CEC621669A93002A7F3D /* Frameworks */,
130 | BF31CEC721669A93002A7F3D /* Resources */,
131 | );
132 | buildRules = (
133 | );
134 | dependencies = (
135 | BF31CECC21669A93002A7F3D /* PBXTargetDependency */,
136 | );
137 | name = WeakableSelfTests;
138 | productName = WeakableTests;
139 | productReference = BF31CEC921669A93002A7F3D /* WeakableSelfTests.xctest */;
140 | productType = "com.apple.product-type.bundle.unit-test";
141 | };
142 | /* End PBXNativeTarget section */
143 |
144 | /* Begin PBXProject section */
145 | BF31CEB721669A93002A7F3D /* Project object */ = {
146 | isa = PBXProject;
147 | attributes = {
148 | LastSwiftUpdateCheck = 1000;
149 | LastUpgradeCheck = 1000;
150 | ORGANIZATIONNAME = Vincent;
151 | TargetAttributes = {
152 | BF31CEBF21669A93002A7F3D = {
153 | CreatedOnToolsVersion = 10.0;
154 | LastSwiftMigration = 1000;
155 | };
156 | BF31CEC821669A93002A7F3D = {
157 | CreatedOnToolsVersion = 10.0;
158 | };
159 | };
160 | };
161 | buildConfigurationList = BF31CEBA21669A93002A7F3D /* Build configuration list for PBXProject "WeakableSelf" */;
162 | compatibilityVersion = "Xcode 9.3";
163 | developmentRegion = en;
164 | hasScannedForEncodings = 0;
165 | knownRegions = (
166 | en,
167 | );
168 | mainGroup = BF31CEB621669A93002A7F3D;
169 | productRefGroup = BF31CEC121669A93002A7F3D /* Products */;
170 | projectDirPath = "";
171 | projectRoot = "";
172 | targets = (
173 | BF31CEBF21669A93002A7F3D /* WeakableSelf */,
174 | BF31CEC821669A93002A7F3D /* WeakableSelfTests */,
175 | );
176 | };
177 | /* End PBXProject section */
178 |
179 | /* Begin PBXResourcesBuildPhase section */
180 | BF31CEBE21669A93002A7F3D /* Resources */ = {
181 | isa = PBXResourcesBuildPhase;
182 | buildActionMask = 2147483647;
183 | files = (
184 | );
185 | runOnlyForDeploymentPostprocessing = 0;
186 | };
187 | BF31CEC721669A93002A7F3D /* Resources */ = {
188 | isa = PBXResourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | );
192 | runOnlyForDeploymentPostprocessing = 0;
193 | };
194 | /* End PBXResourcesBuildPhase section */
195 |
196 | /* Begin PBXSourcesBuildPhase section */
197 | BF31CEBC21669A93002A7F3D /* Sources */ = {
198 | isa = PBXSourcesBuildPhase;
199 | buildActionMask = 2147483647;
200 | files = (
201 | BF5CD87E2166A9B6000B42E0 /* Weakable.swift in Sources */,
202 | );
203 | runOnlyForDeploymentPostprocessing = 0;
204 | };
205 | BF31CEC521669A93002A7F3D /* Sources */ = {
206 | isa = PBXSourcesBuildPhase;
207 | buildActionMask = 2147483647;
208 | files = (
209 | BF31CECF21669A93002A7F3D /* WeakableSelfTests.swift in Sources */,
210 | );
211 | runOnlyForDeploymentPostprocessing = 0;
212 | };
213 | /* End PBXSourcesBuildPhase section */
214 |
215 | /* Begin PBXTargetDependency section */
216 | BF31CECC21669A93002A7F3D /* PBXTargetDependency */ = {
217 | isa = PBXTargetDependency;
218 | target = BF31CEBF21669A93002A7F3D /* WeakableSelf */;
219 | targetProxy = BF31CECB21669A93002A7F3D /* PBXContainerItemProxy */;
220 | };
221 | /* End PBXTargetDependency section */
222 |
223 | /* Begin XCBuildConfiguration section */
224 | BF31CED221669A93002A7F3D /* Debug */ = {
225 | isa = XCBuildConfiguration;
226 | buildSettings = {
227 | ALWAYS_SEARCH_USER_PATHS = NO;
228 | CLANG_ANALYZER_NONNULL = YES;
229 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
231 | CLANG_CXX_LIBRARY = "libc++";
232 | CLANG_ENABLE_MODULES = YES;
233 | CLANG_ENABLE_OBJC_ARC = YES;
234 | CLANG_ENABLE_OBJC_WEAK = YES;
235 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
236 | CLANG_WARN_BOOL_CONVERSION = YES;
237 | CLANG_WARN_COMMA = YES;
238 | CLANG_WARN_CONSTANT_CONVERSION = YES;
239 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
240 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
241 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
242 | CLANG_WARN_EMPTY_BODY = YES;
243 | CLANG_WARN_ENUM_CONVERSION = YES;
244 | CLANG_WARN_INFINITE_RECURSION = YES;
245 | CLANG_WARN_INT_CONVERSION = YES;
246 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
247 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
248 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
249 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
250 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
251 | CLANG_WARN_STRICT_PROTOTYPES = YES;
252 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
253 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
254 | CLANG_WARN_UNREACHABLE_CODE = YES;
255 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
256 | CODE_SIGN_IDENTITY = "iPhone Developer";
257 | COPY_PHASE_STRIP = NO;
258 | CURRENT_PROJECT_VERSION = 1;
259 | DEBUG_INFORMATION_FORMAT = dwarf;
260 | ENABLE_STRICT_OBJC_MSGSEND = YES;
261 | ENABLE_TESTABILITY = YES;
262 | GCC_C_LANGUAGE_STANDARD = gnu11;
263 | GCC_DYNAMIC_NO_PIC = NO;
264 | GCC_NO_COMMON_BLOCKS = YES;
265 | GCC_OPTIMIZATION_LEVEL = 0;
266 | GCC_PREPROCESSOR_DEFINITIONS = (
267 | "DEBUG=1",
268 | "$(inherited)",
269 | );
270 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
271 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
272 | GCC_WARN_UNDECLARED_SELECTOR = YES;
273 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
274 | GCC_WARN_UNUSED_FUNCTION = YES;
275 | GCC_WARN_UNUSED_VARIABLE = YES;
276 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
277 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
278 | MTL_FAST_MATH = YES;
279 | ONLY_ACTIVE_ARCH = YES;
280 | SDKROOT = iphoneos;
281 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
282 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
283 | VERSIONING_SYSTEM = "apple-generic";
284 | VERSION_INFO_PREFIX = "";
285 | };
286 | name = Debug;
287 | };
288 | BF31CED321669A93002A7F3D /* Release */ = {
289 | isa = XCBuildConfiguration;
290 | buildSettings = {
291 | ALWAYS_SEARCH_USER_PATHS = NO;
292 | CLANG_ANALYZER_NONNULL = YES;
293 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
295 | CLANG_CXX_LIBRARY = "libc++";
296 | CLANG_ENABLE_MODULES = YES;
297 | CLANG_ENABLE_OBJC_ARC = YES;
298 | CLANG_ENABLE_OBJC_WEAK = YES;
299 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
300 | CLANG_WARN_BOOL_CONVERSION = YES;
301 | CLANG_WARN_COMMA = YES;
302 | CLANG_WARN_CONSTANT_CONVERSION = YES;
303 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
305 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
306 | CLANG_WARN_EMPTY_BODY = YES;
307 | CLANG_WARN_ENUM_CONVERSION = YES;
308 | CLANG_WARN_INFINITE_RECURSION = YES;
309 | CLANG_WARN_INT_CONVERSION = YES;
310 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
311 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
312 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
313 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
314 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
315 | CLANG_WARN_STRICT_PROTOTYPES = YES;
316 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
317 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
318 | CLANG_WARN_UNREACHABLE_CODE = YES;
319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
320 | CODE_SIGN_IDENTITY = "iPhone Developer";
321 | COPY_PHASE_STRIP = NO;
322 | CURRENT_PROJECT_VERSION = 1;
323 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
324 | ENABLE_NS_ASSERTIONS = NO;
325 | ENABLE_STRICT_OBJC_MSGSEND = YES;
326 | GCC_C_LANGUAGE_STANDARD = gnu11;
327 | GCC_NO_COMMON_BLOCKS = YES;
328 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
329 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
330 | GCC_WARN_UNDECLARED_SELECTOR = YES;
331 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
332 | GCC_WARN_UNUSED_FUNCTION = YES;
333 | GCC_WARN_UNUSED_VARIABLE = YES;
334 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
335 | MTL_ENABLE_DEBUG_INFO = NO;
336 | MTL_FAST_MATH = YES;
337 | SDKROOT = iphoneos;
338 | SWIFT_COMPILATION_MODE = wholemodule;
339 | SWIFT_OPTIMIZATION_LEVEL = "-O";
340 | VALIDATE_PRODUCT = YES;
341 | VERSIONING_SYSTEM = "apple-generic";
342 | VERSION_INFO_PREFIX = "";
343 | };
344 | name = Release;
345 | };
346 | BF31CED521669A93002A7F3D /* Debug */ = {
347 | isa = XCBuildConfiguration;
348 | buildSettings = {
349 | CLANG_ENABLE_MODULES = YES;
350 | CODE_SIGN_IDENTITY = "";
351 | CODE_SIGN_STYLE = Automatic;
352 | DEFINES_MODULE = YES;
353 | DEVELOPMENT_TEAM = 2937XWQ9VF;
354 | DYLIB_COMPATIBILITY_VERSION = 1;
355 | DYLIB_CURRENT_VERSION = 1;
356 | DYLIB_INSTALL_NAME_BASE = "@rpath";
357 | INFOPLIST_FILE = Sources/Info.plist;
358 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
359 | LD_RUNPATH_SEARCH_PATHS = (
360 | "$(inherited)",
361 | "@executable_path/Frameworks",
362 | "@loader_path/Frameworks",
363 | );
364 | PRODUCT_BUNDLE_IDENTIFIER = fr.vincentpradeilles.WeakableSelf;
365 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
366 | SKIP_INSTALL = YES;
367 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
368 | SWIFT_VERSION = 4.2;
369 | TARGETED_DEVICE_FAMILY = "1,2";
370 | };
371 | name = Debug;
372 | };
373 | BF31CED621669A93002A7F3D /* Release */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | CLANG_ENABLE_MODULES = YES;
377 | CODE_SIGN_IDENTITY = "";
378 | CODE_SIGN_STYLE = Automatic;
379 | DEFINES_MODULE = YES;
380 | DEVELOPMENT_TEAM = 2937XWQ9VF;
381 | DYLIB_COMPATIBILITY_VERSION = 1;
382 | DYLIB_CURRENT_VERSION = 1;
383 | DYLIB_INSTALL_NAME_BASE = "@rpath";
384 | INFOPLIST_FILE = Sources/Info.plist;
385 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
386 | LD_RUNPATH_SEARCH_PATHS = (
387 | "$(inherited)",
388 | "@executable_path/Frameworks",
389 | "@loader_path/Frameworks",
390 | );
391 | PRODUCT_BUNDLE_IDENTIFIER = fr.vincentpradeilles.WeakableSelf;
392 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
393 | SKIP_INSTALL = YES;
394 | SWIFT_VERSION = 4.2;
395 | TARGETED_DEVICE_FAMILY = "1,2";
396 | };
397 | name = Release;
398 | };
399 | BF31CED821669A93002A7F3D /* Debug */ = {
400 | isa = XCBuildConfiguration;
401 | buildSettings = {
402 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
403 | CODE_SIGN_STYLE = Automatic;
404 | DEVELOPMENT_TEAM = 2937XWQ9VF;
405 | INFOPLIST_FILE = WeakableSelfTests/Info.plist;
406 | LD_RUNPATH_SEARCH_PATHS = (
407 | "$(inherited)",
408 | "@executable_path/Frameworks",
409 | "@loader_path/Frameworks",
410 | );
411 | PRODUCT_BUNDLE_IDENTIFIER = fr.vincentpradeilles.WeakableSelfTests;
412 | PRODUCT_NAME = "$(TARGET_NAME)";
413 | SWIFT_VERSION = 4.2;
414 | TARGETED_DEVICE_FAMILY = "1,2";
415 | };
416 | name = Debug;
417 | };
418 | BF31CED921669A93002A7F3D /* Release */ = {
419 | isa = XCBuildConfiguration;
420 | buildSettings = {
421 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
422 | CODE_SIGN_STYLE = Automatic;
423 | DEVELOPMENT_TEAM = 2937XWQ9VF;
424 | INFOPLIST_FILE = WeakableSelfTests/Info.plist;
425 | LD_RUNPATH_SEARCH_PATHS = (
426 | "$(inherited)",
427 | "@executable_path/Frameworks",
428 | "@loader_path/Frameworks",
429 | );
430 | PRODUCT_BUNDLE_IDENTIFIER = fr.vincentpradeilles.WeakableSelfTests;
431 | PRODUCT_NAME = "$(TARGET_NAME)";
432 | SWIFT_VERSION = 4.2;
433 | TARGETED_DEVICE_FAMILY = "1,2";
434 | };
435 | name = Release;
436 | };
437 | /* End XCBuildConfiguration section */
438 |
439 | /* Begin XCConfigurationList section */
440 | BF31CEBA21669A93002A7F3D /* Build configuration list for PBXProject "WeakableSelf" */ = {
441 | isa = XCConfigurationList;
442 | buildConfigurations = (
443 | BF31CED221669A93002A7F3D /* Debug */,
444 | BF31CED321669A93002A7F3D /* Release */,
445 | );
446 | defaultConfigurationIsVisible = 0;
447 | defaultConfigurationName = Release;
448 | };
449 | BF31CED421669A93002A7F3D /* Build configuration list for PBXNativeTarget "WeakableSelf" */ = {
450 | isa = XCConfigurationList;
451 | buildConfigurations = (
452 | BF31CED521669A93002A7F3D /* Debug */,
453 | BF31CED621669A93002A7F3D /* Release */,
454 | );
455 | defaultConfigurationIsVisible = 0;
456 | defaultConfigurationName = Release;
457 | };
458 | BF31CED721669A93002A7F3D /* Build configuration list for PBXNativeTarget "WeakableSelfTests" */ = {
459 | isa = XCConfigurationList;
460 | buildConfigurations = (
461 | BF31CED821669A93002A7F3D /* Debug */,
462 | BF31CED921669A93002A7F3D /* Release */,
463 | );
464 | defaultConfigurationIsVisible = 0;
465 | defaultConfigurationName = Release;
466 | };
467 | /* End XCConfigurationList section */
468 | };
469 | rootObject = BF31CEB721669A93002A7F3D /* Project object */;
470 | }
471 |
--------------------------------------------------------------------------------
/WeakableSelf.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/WeakableSelf.xcodeproj/xcshareddata/xcschemes/Weakable.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
69 |
70 |
76 |
77 |
78 |
79 |
80 |
81 |
87 |
88 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/WeakableSelfTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/WeakableSelfTests/WeakableSelfTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WeakableSelfTests.swift
3 | // WeakableSelfTests
4 | //
5 | // Created by Vincent on 04/10/2018.
6 | // Copyright © 2018 Vincent. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import WeakableSelf
11 |
12 | private var producerWasDeinit = false
13 | private var consumerWasDeinit = false
14 |
15 | private class Producer: NSObject {
16 |
17 | deinit {
18 | producerWasDeinit = true
19 | }
20 |
21 | private var handlerZeroArg: () -> Void = { }
22 | private var handlerZeroArgReturn: () -> Int = { return 2 }
23 | private var handlerOneArg: (Int) -> Void = { _ in }
24 | private var handlerOneArgReturn: (Int) -> Int = { return $0 }
25 | private var handlerTwoArgs: (Int, Int) -> Void = { _, _ in }
26 | private var handlerTwoArgsReturn: (Int, Int) -> Int = { return $1 }
27 | private var handlerThreeArgs: (Int, Int, Int) -> Void = { _, _, _ in }
28 | private var handlerThreeArgsReturn: (Int, Int, Int) -> Int = { return $2 }
29 | private var handlerFourArgs: (Int, Int, Int, Int) -> Void = { _, _, _, _ in }
30 | private var handlerFourArgsReturn: (Int, Int, Int, Int) -> Int = { return $3 }
31 | private var handlerFiveArgs: (Int, Int, Int, Int, Int) -> Void = { _, _, _, _, _ in }
32 | private var handlerFiveArgsReturn: (Int, Int, Int, Int, Int) -> Int = { return $4 }
33 | private var handlerSixArgs: (Int, Int, Int, Int, Int, Int) -> Void = { _, _, _, _, _, _ in }
34 | private var handlerSixArgsReturn: (Int, Int, Int, Int, Int, Int) -> Int = { return $5 }
35 | private var handlerSevenArgs: (Int, Int, Int, Int, Int, Int, Int) -> Void = { _, _, _, _, _, _, _ in }
36 | private var handlerSevenArgsReturn: (Int, Int, Int, Int, Int, Int, Int) -> Int = { return $6 }
37 |
38 | func registerZeroArg(handler: @escaping () -> Void) {
39 | self.handlerZeroArg = handler
40 | self.handlerZeroArg()
41 | }
42 |
43 | func registerZeroArgReturn(handler: @escaping () -> Int) {
44 | self.handlerZeroArgReturn = handler
45 | _ = self.handlerZeroArgReturn()
46 | }
47 |
48 | func registerOneArg(handler: @escaping (Int) -> Void) {
49 | self.handlerOneArg = handler
50 | self.handlerOneArg(42)
51 | }
52 |
53 | func registerOneArgReturn(handler: @escaping (Int) -> Int) {
54 | self.handlerOneArgReturn = handler
55 | _ = self.handlerOneArgReturn(42)
56 | }
57 |
58 | func registerTwoArgs(handler: @escaping (Int, Int) -> Void) {
59 | self.handlerTwoArgs = handler
60 | self.handlerTwoArgs(42, 42)
61 | }
62 |
63 | func registerTwoArgsReturn(handler: @escaping (Int, Int) -> Int) {
64 | self.handlerTwoArgsReturn = handler
65 | _ = self.handlerTwoArgsReturn(42, 42)
66 | }
67 |
68 | func registerThreeArgs(handler: @escaping (Int, Int, Int) -> Void) {
69 | self.handlerThreeArgs = handler
70 | self.handlerThreeArgs(42, 42, 42)
71 | }
72 |
73 | func registerThreeArgsReturn(handler: @escaping (Int, Int, Int) -> Int) {
74 | self.handlerThreeArgsReturn = handler
75 | _ = self.handlerThreeArgsReturn(42, 42, 42)
76 | }
77 |
78 | func registerFourArgs(handler: @escaping (Int, Int, Int, Int) -> Void) {
79 | self.handlerFourArgs = handler
80 | self.handlerFourArgs(42, 42, 42, 42)
81 | }
82 |
83 | func registerFourArgsReturn(handler: @escaping (Int, Int, Int, Int) -> Int) {
84 | self.handlerFourArgsReturn = handler
85 | _ = self.handlerFourArgsReturn(42, 42, 42, 42)
86 | }
87 |
88 | func registerFiveArgs(handler: @escaping (Int, Int, Int, Int, Int) -> Void) {
89 | self.handlerFiveArgs = handler
90 | self.handlerFiveArgs(42, 42, 42, 42, 42)
91 | }
92 |
93 | func registerFiveArgsReturn(handler: @escaping (Int, Int, Int, Int, Int) -> Int) {
94 | self.handlerFiveArgsReturn = handler
95 | _ = self.handlerFiveArgsReturn(42, 42, 42, 42, 42)
96 | }
97 |
98 | func registerSixArgs(handler: @escaping (Int, Int, Int, Int, Int, Int) -> Void) {
99 | self.handlerSixArgs = handler
100 | self.handlerSixArgs(42, 42, 42, 42, 42, 42)
101 | }
102 |
103 | func registerSixArgsReturn(handler: @escaping (Int, Int, Int, Int, Int, Int) -> Int) {
104 | self.handlerSixArgsReturn = handler
105 | _ = self.handlerSixArgsReturn(42, 42, 42, 42, 42, 42)
106 | }
107 |
108 | func registerSevenArgs(handler: @escaping (Int, Int, Int, Int, Int, Int, Int) -> Void) {
109 | self.handlerSevenArgs = handler
110 | self.handlerSevenArgs(42, 42, 42, 42, 42, 42, 42)
111 | }
112 |
113 | func registerSevenArgsReturn(handler: @escaping (Int, Int, Int, Int, Int, Int, Int) -> Int) {
114 | self.handlerSevenArgsReturn = handler
115 | _ = self.handlerSevenArgsReturn(42, 42, 42, 42, 42, 42, 42)
116 | }
117 | }
118 |
119 | private class Consumer: NSObject {
120 |
121 | deinit {
122 | consumerWasDeinit = true
123 | }
124 |
125 | let producer = Producer()
126 |
127 | func consumeWithoutWeakify() {
128 | producer.registerZeroArg(handler: {
129 | self.handleZeroArg()
130 | })
131 | }
132 |
133 | func consumeZeroArg() {
134 | producer.registerZeroArg(handler: weakify { strongSelf in
135 | strongSelf.handleZeroArg()
136 | })
137 | }
138 |
139 | func consumeZeroArgReturn() {
140 | producer.registerZeroArgReturn(handler: weakify(defaultValue: 0) { strongSelf in
141 | return strongSelf.handleZeroArgReturn()
142 | })
143 | }
144 |
145 | func consumeOneArg() {
146 | producer.registerOneArg(handler: weakify { strongSelf, a in
147 | strongSelf.handleOneArg(a)
148 | })
149 | }
150 |
151 | func consumeOneArgReturn() {
152 | producer.registerOneArgReturn(handler: weakify(defaultValue: 0) { strongSelf, a in
153 | return strongSelf.handleOneArgReturn(a)
154 | })
155 | }
156 |
157 | func consumeTwoArgs() {
158 | producer.registerTwoArgs(handler: weakify { strongSelf, a, b in
159 | strongSelf.handleTwoArgs(a,b)
160 | })
161 | }
162 |
163 | func consumeTwoArgsReturn() {
164 | producer.registerTwoArgsReturn(handler: weakify(defaultValue: 0) { strongSelf, a, b in
165 | return strongSelf.handleTwoArgsReturn(a,b)
166 | })
167 | }
168 |
169 | func consumeThreeArgs() {
170 | producer.registerThreeArgs(handler: weakify { strongSelf, a, b, c in
171 | strongSelf.handleThreeArgs(a,b,c)
172 | })
173 | }
174 |
175 | func consumeThreeArgsReturn() {
176 | producer.registerThreeArgsReturn(handler: weakify(defaultValue: 0) { strongSelf, a, b, c in
177 | return strongSelf.handleThreeArgsReturn(a,b,c)
178 | })
179 | }
180 |
181 | func consumeFourArgs() {
182 | producer.registerFourArgs(handler: weakify { strongSelf, a, b, c, d in
183 | strongSelf.handleFourArgs(a,b,c,d)
184 | })
185 | }
186 |
187 | func consumeFourArgsReturn() {
188 | producer.registerFourArgsReturn(handler: weakify(defaultValue: 0) { strongSelf, a, b, c, d in
189 | return strongSelf.handleFourArgsReturn(a,b,c,d)
190 | })
191 | }
192 |
193 | func consumeFiveArgs() {
194 | producer.registerFiveArgs(handler: weakify { strongSelf, a, b, c, d, e in
195 | strongSelf.handleFiveArgs(a,b,c,d,e)
196 | })
197 | }
198 |
199 | func consumeFiveArgsReturn() {
200 | producer.registerFiveArgsReturn(handler: weakify(defaultValue: 0) { strongSelf, a, b, c, d, e in
201 | return strongSelf.handleFiveArgsReturn(a,b,c,d,e)
202 | })
203 | }
204 |
205 | func consumeSixArgs() {
206 | producer.registerSixArgs(handler: weakify { strongSelf, a, b, c, d, e, f in
207 | strongSelf.handleSixArgs(a,b,c,d,e,f)
208 | })
209 | }
210 |
211 | func consumeSixArgsReturn() {
212 | producer.registerSixArgsReturn(handler: weakify(defaultValue: 0) { strongSelf, a, b, c, d, e, f in
213 | return strongSelf.handleSixArgsReturn(a,b,c,d,e,f)
214 | })
215 | }
216 |
217 | func consumeSevenArgs() {
218 | producer.registerSevenArgs(handler: weakify { strongSelf, a, b, c, d, e, f, g in
219 | strongSelf.handleSevenArgs(a,b,c,d,e,f,g)
220 | })
221 | }
222 |
223 | func consumeSevenArgsReturn() {
224 | producer.registerSevenArgsReturn(handler: weakify(defaultValue: 0) { strongSelf, a, b, c, d, e, f, g in
225 | return strongSelf.handleSevenArgsReturn(a,b,c,d,e,f,g)
226 | })
227 | }
228 |
229 | private func handleZeroArg() {
230 | print("🎉")
231 | }
232 |
233 | private func handleZeroArgReturn() -> Int {
234 | print("🎉")
235 | return 2
236 | }
237 |
238 | private func handleOneArg(_ a: Int) {
239 | print("🎉 \(a)")
240 | }
241 |
242 | private func handleOneArgReturn(_ a: Int) -> Int {
243 | print("🎉 \(a)")
244 | return 2
245 | }
246 |
247 | private func handleTwoArgs(_ a: Int, _ b: Int) {
248 | print("🎉 \(a) \(b)")
249 | }
250 |
251 | private func handleTwoArgsReturn(_ a: Int, _ b: Int) -> Int {
252 | print("🎉 \(a) \(b)")
253 | return 2
254 | }
255 |
256 | private func handleThreeArgs(_ a: Int, _ b: Int, _ c: Int) {
257 | print("🎉 \(a) \(b) \(c)")
258 | }
259 |
260 | private func handleThreeArgsReturn(_ a: Int, _ b: Int, _ c: Int) -> Int {
261 | print("🎉 \(a) \(b) \(c)")
262 | return 2
263 | }
264 |
265 | private func handleFourArgs(_ a: Int, _ b: Int, _ c: Int, _ d: Int) {
266 | print("🎉 \(a) \(b) \(c) \(d)")
267 | }
268 |
269 | private func handleFourArgsReturn(_ a: Int, _ b: Int, _ c: Int, _ d: Int) -> Int {
270 | print("🎉 \(a) \(b) \(c) \(d)")
271 | return 2
272 | }
273 |
274 | private func handleFiveArgs(_ a: Int, _ b: Int, _ c: Int, _ d: Int, _ e: Int) {
275 | print("🎉 \(a) \(b) \(c) \(d) \(e)")
276 | }
277 |
278 | private func handleFiveArgsReturn(_ a: Int, _ b: Int, _ c: Int, _ d: Int, _ e: Int) -> Int {
279 | print("🎉 \(a) \(b) \(c) \(d) \(e)")
280 | return 2
281 | }
282 |
283 | private func handleSixArgs(_ a: Int, _ b: Int, _ c: Int, _ d: Int, _ e: Int, _ f: Int) {
284 | print("🎉 \(a) \(b) \(c) \(d) \(e) \(f)")
285 | }
286 |
287 | private func handleSixArgsReturn(_ a: Int, _ b: Int, _ c: Int, _ d: Int, _ e: Int, _ f: Int) -> Int {
288 | print("🎉 \(a) \(b) \(c) \(d) \(e) \(f)")
289 | return 2
290 | }
291 |
292 | private func handleSevenArgs(_ a: Int, _ b: Int, _ c: Int, _ d: Int, _ e: Int, _ f: Int, _ g: Int) {
293 | print("🎉 \(a) \(b) \(c) \(d) \(e) \(f) \(g)")
294 | }
295 |
296 | private func handleSevenArgsReturn(_ a: Int, _ b: Int, _ c: Int, _ d: Int, _ e: Int, _ f: Int, _ g: Int) -> Int {
297 | print("🎉 \(a) \(b) \(c) \(d) \(e) \(f) \(g)")
298 | return 2
299 | }
300 | }
301 |
302 | class SharedTests: XCTestCase {
303 |
304 | override func setUp() {
305 | super.setUp()
306 |
307 | producerWasDeinit = false
308 | consumerWasDeinit = false
309 | }
310 |
311 | /// This test proves that without the use of weakify a memory leak is indeed created.
312 | func testWithoutWeakifying() {
313 | var consumer: Consumer? = Consumer()
314 | consumer?.consumeWithoutWeakify()
315 |
316 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
317 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
318 |
319 | consumer = nil
320 |
321 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
322 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
323 | }
324 |
325 | func testWeakifyZeroArgument() {
326 | var consumer: Consumer? = Consumer()
327 |
328 | consumer?.consumeZeroArg()
329 |
330 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
331 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
332 |
333 | consumer = nil
334 |
335 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
336 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
337 | }
338 |
339 | func testWeakifyZeroArgumentWithReturn() {
340 | var consumer: Consumer? = Consumer()
341 |
342 | consumer?.consumeZeroArgReturn()
343 |
344 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
345 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
346 |
347 | consumer = nil
348 |
349 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
350 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
351 | }
352 |
353 | func testWeakifyOneArgument() {
354 | var consumer: Consumer? = Consumer()
355 |
356 | consumer?.consumeOneArg()
357 |
358 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
359 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
360 |
361 | consumer = nil
362 |
363 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
364 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
365 | }
366 |
367 | func testWeakifyOneArgumentWithReturn() {
368 | var consumer: Consumer? = Consumer()
369 |
370 | consumer?.consumeOneArgReturn()
371 |
372 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
373 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
374 |
375 | consumer = nil
376 |
377 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
378 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
379 | }
380 |
381 | func testWeakifyTwoArguments() {
382 | var consumer: Consumer? = Consumer()
383 |
384 | consumer?.consumeTwoArgs()
385 |
386 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
387 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
388 |
389 | consumer = nil
390 |
391 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
392 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
393 | }
394 |
395 | func testWeakifyTwoArgumentsWithReturn() {
396 | var consumer: Consumer? = Consumer()
397 |
398 | consumer?.consumeTwoArgsReturn()
399 |
400 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
401 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
402 |
403 | consumer = nil
404 |
405 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
406 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
407 | }
408 |
409 | func testWeakifyThreeArguments() {
410 | var consumer: Consumer? = Consumer()
411 |
412 | consumer?.consumeThreeArgs()
413 |
414 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
415 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
416 |
417 | consumer = nil
418 |
419 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
420 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
421 | }
422 |
423 | func testWeakifyThreeArgumentsWithReturn() {
424 | var consumer: Consumer? = Consumer()
425 |
426 | consumer?.consumeThreeArgsReturn()
427 |
428 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
429 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
430 |
431 | consumer = nil
432 |
433 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
434 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
435 | }
436 |
437 | func testWeakifyFourArguments() {
438 | var consumer: Consumer? = Consumer()
439 |
440 | consumer?.consumeFourArgs()
441 |
442 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
443 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
444 |
445 | consumer = nil
446 |
447 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
448 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
449 | }
450 |
451 | func testWeakifyFourArgumentsWithReturn() {
452 | var consumer: Consumer? = Consumer()
453 |
454 | consumer?.consumeFourArgsReturn()
455 |
456 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
457 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
458 |
459 | consumer = nil
460 |
461 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
462 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
463 | }
464 |
465 | func testWeakifyFiveArguments() {
466 | var consumer: Consumer? = Consumer()
467 |
468 | consumer?.consumeFiveArgs()
469 |
470 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
471 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
472 |
473 | consumer = nil
474 |
475 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
476 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
477 | }
478 |
479 | func testWeakifyFiveArgumentsWithReturn() {
480 | var consumer: Consumer? = Consumer()
481 |
482 | consumer?.consumeFiveArgsReturn()
483 |
484 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
485 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
486 |
487 | consumer = nil
488 |
489 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
490 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
491 | }
492 |
493 | func testWeakifySixArguments() {
494 | var consumer: Consumer? = Consumer()
495 |
496 | consumer?.consumeSixArgs()
497 |
498 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
499 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
500 |
501 | consumer = nil
502 |
503 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
504 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
505 | }
506 |
507 | func testWeakifySixArgumentsWithReturn() {
508 | var consumer: Consumer? = Consumer()
509 |
510 | consumer?.consumeSixArgsReturn()
511 |
512 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
513 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
514 |
515 | consumer = nil
516 |
517 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
518 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
519 | }
520 |
521 | func testWeakifySevenArguments() {
522 | var consumer: Consumer? = Consumer()
523 |
524 | consumer?.consumeSevenArgs()
525 |
526 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
527 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
528 |
529 | consumer = nil
530 |
531 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
532 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
533 | }
534 |
535 | func testWeakifySevenArgumentsWithReturn() {
536 | var consumer: Consumer? = Consumer()
537 |
538 | consumer?.consumeSevenArgsReturn()
539 |
540 | XCTAssertFalse(producerWasDeinit, "producerWasDeinit")
541 | XCTAssertFalse(consumerWasDeinit, "consumerWasDeinit")
542 |
543 | consumer = nil
544 |
545 | XCTAssertTrue(producerWasDeinit, "producerWasDeinit")
546 | XCTAssertTrue(consumerWasDeinit, "consumerWasDeinit")
547 | }
548 | }
549 |
550 |
--------------------------------------------------------------------------------