├── .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 | ![platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20macOS%20%7C%20tvOS%20%7C%20watchOS-333333.svg) 4 | ![pod](https://img.shields.io/cocoapods/v/WeakableSelf.svg) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](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 | --------------------------------------------------------------------------------