Skip to content

Commit 83d8cb3

Browse files
committed
#22. Fix leaks.
1 parent f46e84c commit 83d8cb3

File tree

6 files changed

+86
-42
lines changed

6 files changed

+86
-42
lines changed

Sources/FontAnimation.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,12 @@ import QuartzCore
77
import CoreFoundation
88

99
internal final class FontAnimation {
10-
11-
private let displayLink: CADisplayLink?
10+
private var displayLink: CADisplayLink?
1211
private(set) var startTime: CFTimeInterval?
1312

14-
private let target: Any
1513
private let selector: Selector
1614

17-
init(target: Any, selector: Selector) {
18-
self.target = target
15+
init(target: AnyObject, selector: Selector) {
1916
self.selector = selector
2017

2118
displayLink = CADisplayLink(target: target, selector: selector)
@@ -27,12 +24,14 @@ internal final class FontAnimation {
2724
}
2825

2926
func start() {
30-
startTime = CFAbsoluteTimeGetCurrent()
3127
displayLink?.isPaused = false
28+
29+
startTime = CFAbsoluteTimeGetCurrent()
3230
}
3331

3432
func stop() {
3533
startTime = nil
34+
3635
displayLink?.isPaused = true
3736
}
3837
}

Sources/TweePlaceholderTextField.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ open class TweePlaceholderTextField: UITextField {
8585
}
8686
}
8787

88-
private lazy var minimizeFontAnimation = FontAnimation(target: self, selector: #selector(minimizePlaceholderFontSize))
89-
private lazy var maximizeFontAnimation = FontAnimation(target: self, selector: #selector(maximizePlaceholderFontSize))
88+
private lazy var minimizeFontAnimation = FontAnimation(target: WeakTargetProxy(target: self), selector: #selector(minimizePlaceholderFontSize))
89+
private lazy var maximizeFontAnimation = FontAnimation(target: WeakTargetProxy(target: self), selector: #selector(maximizePlaceholderFontSize))
9090

9191
private let placeholderLayoutGuide = UILayoutGuide()
9292
private var leadingPlaceholderConstraint: NSLayoutConstraint?

Sources/WeakTargetProxy.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Created by Oleg Hnidets on 9/14/18.
2+
// Copyright © 2018 Oleg Hnidets. All rights reserved.
3+
//
4+
5+
import Foundation
6+
7+
internal final class WeakTargetProxy: NSObject {
8+
private weak var target: NSObjectProtocol?
9+
10+
init(target: NSObjectProtocol) {
11+
self.target = target
12+
13+
super.init()
14+
}
15+
16+
override func responds(to aSelector: Selector!) -> Bool {
17+
guard let target = target else {
18+
return super.responds(to: aSelector)
19+
}
20+
21+
return target.responds(to: aSelector) || super.responds(to: aSelector)
22+
}
23+
24+
override func forwardingTarget(for aSelector: Selector!) -> Any? {
25+
return target
26+
}
27+
}

TweeTextField.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
7C065D3920E3F02C00B8F983 /* TweeAttributedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A146091FEC228900CEADAA /* TweeAttributedTextField.swift */; };
1616
7C065D3A20E3F02C00B8F983 /* TweeActiveTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A1460A1FEC228900CEADAA /* TweeActiveTextField.swift */; };
1717
7C065D3B20E3F02C00B8F983 /* FontAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A1460B1FEC228900CEADAA /* FontAnimation.swift */; };
18+
7C15066C214BF43D006A7D4C /* WeakTargetProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */; };
19+
7C15066D214BF47E006A7D4C /* WeakTargetProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */; };
1820
7CF5909A2125DB5D0015777F /* PasswordTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CF590992125DB5D0015777F /* PasswordTextField.swift */; };
1921
92A1460C1FEC228900CEADAA /* TweePlaceholderTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A146071FEC228900CEADAA /* TweePlaceholderTextField.swift */; };
2022
92A1460D1FEC228900CEADAA /* TweeBorderedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A146081FEC228900CEADAA /* TweeBorderedTextField.swift */; };
@@ -56,6 +58,7 @@
5658
7C065D2B20E3EFCD00B8F983 /* TweeTextField.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TweeTextField.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5759
7C065D2D20E3EFCD00B8F983 /* TweeTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TweeTextField.h; sourceTree = "<group>"; };
5860
7C065D2E20E3EFCD00B8F983 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
61+
7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakTargetProxy.swift; sourceTree = "<group>"; };
5962
7CF590992125DB5D0015777F /* PasswordTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordTextField.swift; sourceTree = "<group>"; };
6063
92A146071FEC228900CEADAA /* TweePlaceholderTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TweePlaceholderTextField.swift; sourceTree = "<group>"; };
6164
92A146081FEC228900CEADAA /* TweeBorderedTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TweeBorderedTextField.swift; sourceTree = "<group>"; };
@@ -119,6 +122,7 @@
119122
92A146091FEC228900CEADAA /* TweeAttributedTextField.swift */,
120123
92A1460A1FEC228900CEADAA /* TweeActiveTextField.swift */,
121124
92A1460B1FEC228900CEADAA /* FontAnimation.swift */,
125+
7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */,
122126
);
123127
path = Sources;
124128
sourceTree = SOURCE_ROOT;
@@ -303,6 +307,7 @@
303307
7C065D3920E3F02C00B8F983 /* TweeAttributedTextField.swift in Sources */,
304308
7C065D3A20E3F02C00B8F983 /* TweeActiveTextField.swift in Sources */,
305309
7C065D3B20E3F02C00B8F983 /* FontAnimation.swift in Sources */,
310+
7C15066C214BF43D006A7D4C /* WeakTargetProxy.swift in Sources */,
306311
);
307312
runOnlyForDeploymentPostprocessing = 0;
308313
};
@@ -311,6 +316,7 @@
311316
buildActionMask = 2147483647;
312317
files = (
313318
92A146101FEC228900CEADAA /* FontAnimation.swift in Sources */,
319+
7C15066D214BF47E006A7D4C /* WeakTargetProxy.swift in Sources */,
314320
92A1460F1FEC228900CEADAA /* TweeActiveTextField.swift in Sources */,
315321
92E7FC3C1FE0374600E58DF5 /* ViewController.swift in Sources */,
316322
92E7FC3A1FE0374600E58DF5 /* AppDelegate.swift in Sources */,

TweeTextField/Base.lproj/Main.storyboard

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
2121
<subviews>
2222
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BwO-Q2-dKq">
23-
<rect key="frame" x="147" y="249" width="80" height="33"/>
23+
<rect key="frame" x="147" y="319" width="80" height="33"/>
2424
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
2525
<state key="normal" title="CONFIRM">
2626
<color key="titleColor" red="0.29019609089999998" green="0.5647059083" blue="0.88627451660000001" alpha="1" colorSpace="deviceRGB"/>
@@ -30,7 +30,7 @@
3030
</connections>
3131
</button>
3232
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Wz3-0y-Vnd">
33-
<rect key="frame" x="19" y="52" width="337.5" height="160"/>
33+
<rect key="frame" x="19" y="52" width="337.5" height="230"/>
3434
<subviews>
3535
<textField opaque="NO" contentMode="scaleToFill" semanticContentAttribute="forceRightToLeft" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="James Bond" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Ib7-Qf-pz7" customClass="TweeBorderedTextField" customModule="TweeTextField_Sample" customModuleProvider="target">
3636
<rect key="frame" x="0.0" y="0.0" width="337.5" height="40"/>
@@ -147,53 +147,63 @@
147147
<action selector="emailEndEditing:" destination="BYZ-38-t0r" eventType="editingDidEnd" id="PUh-nQ-uM3"/>
148148
</connections>
149149
</textField>
150+
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="GSD-GC-nGa" customClass="PasswordTextField" customModule="TweeTextField">
151+
<rect key="frame" x="0.0" y="180" width="337.5" height="50"/>
152+
<constraints>
153+
<constraint firstAttribute="height" constant="50" id="hX8-3C-iGN"/>
154+
</constraints>
155+
<nil key="textColor"/>
156+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
157+
<textInputTraits key="textInputTraits"/>
158+
<userDefinedRuntimeAttributes>
159+
<userDefinedRuntimeAttribute type="string" keyPath="tweePlaceholder" value="Password"/>
160+
<userDefinedRuntimeAttribute type="color" keyPath="placeholderColor">
161+
<color key="value" red="0.0039215686269999999" green="0.63137254899999995" blue="0.3803921569" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
162+
</userDefinedRuntimeAttribute>
163+
<userDefinedRuntimeAttribute type="number" keyPath="placeholderDuration">
164+
<real key="value" value="0.5"/>
165+
</userDefinedRuntimeAttribute>
166+
<userDefinedRuntimeAttribute type="number" keyPath="minimumPlaceholderFontSize">
167+
<real key="value" value="12"/>
168+
</userDefinedRuntimeAttribute>
169+
<userDefinedRuntimeAttribute type="number" keyPath="originalPlaceholderFontSize">
170+
<real key="value" value="17"/>
171+
</userDefinedRuntimeAttribute>
172+
</userDefinedRuntimeAttributes>
173+
</textField>
150174
</subviews>
151175
<constraints>
152176
<constraint firstItem="SwP-Fd-Fft" firstAttribute="height" secondItem="ipt-cn-CA9" secondAttribute="height" id="YoF-I6-WIk"/>
153177
<constraint firstItem="Ib7-Qf-pz7" firstAttribute="height" secondItem="SwP-Fd-Fft" secondAttribute="height" id="fMy-5c-WpL"/>
154178
</constraints>
155179
</stackView>
156-
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="GSD-GC-nGa" customClass="PasswordTextField" customModule="TweeTextField">
157-
<rect key="frame" x="32" y="288" width="312" height="50"/>
158-
<constraints>
159-
<constraint firstAttribute="height" constant="50" id="hX8-3C-iGN"/>
160-
</constraints>
161-
<nil key="textColor"/>
162-
<fontDescription key="fontDescription" type="system" pointSize="14"/>
163-
<textInputTraits key="textInputTraits"/>
164-
<userDefinedRuntimeAttributes>
165-
<userDefinedRuntimeAttribute type="string" keyPath="tweePlaceholder" value="Password"/>
166-
<userDefinedRuntimeAttribute type="color" keyPath="placeholderColor">
167-
<color key="value" red="0.0039215686269999999" green="0.63137254899999995" blue="0.3803921569" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
168-
</userDefinedRuntimeAttribute>
169-
<userDefinedRuntimeAttribute type="number" keyPath="placeholderDuration">
170-
<real key="value" value="0.5"/>
171-
</userDefinedRuntimeAttribute>
172-
<userDefinedRuntimeAttribute type="number" keyPath="minimumPlaceholderFontSize">
173-
<real key="value" value="12"/>
174-
</userDefinedRuntimeAttribute>
175-
<userDefinedRuntimeAttribute type="number" keyPath="originalPlaceholderFontSize">
176-
<real key="value" value="17"/>
177-
</userDefinedRuntimeAttribute>
178-
</userDefinedRuntimeAttributes>
179-
</textField>
180+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H4d-jf-O4s">
181+
<rect key="frame" x="109.5" y="360" width="156" height="30"/>
182+
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
183+
<state key="normal" title="REMOVE FIRST FIELD">
184+
<color key="titleColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
185+
</state>
186+
<connections>
187+
<action selector="removeFirstField" destination="BYZ-38-t0r" eventType="touchUpInside" id="diE-xv-ZVH"/>
188+
</connections>
189+
</button>
180190
</subviews>
181191
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
182192
<constraints>
183-
<constraint firstItem="GSD-GC-nGa" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="0pO-mT-DDF"/>
184193
<constraint firstItem="Wz3-0y-Vnd" firstAttribute="width" secondItem="8bC-Xf-vdC" secondAttribute="width" multiplier="0.9" id="DEP-8P-yxv"/>
194+
<constraint firstItem="H4d-jf-O4s" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="IqP-Pb-iIT"/>
185195
<constraint firstItem="Wz3-0y-Vnd" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="KQH-V3-b5K"/>
196+
<constraint firstItem="H4d-jf-O4s" firstAttribute="top" secondItem="BwO-Q2-dKq" secondAttribute="bottom" constant="8" id="R8c-TI-mLY"/>
186197
<constraint firstItem="BwO-Q2-dKq" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="SrW-DF-eDg"/>
187198
<constraint firstItem="BwO-Q2-dKq" firstAttribute="top" secondItem="Wz3-0y-Vnd" secondAttribute="bottom" constant="37" id="aa8-zk-OuM"/>
188199
<constraint firstItem="Wz3-0y-Vnd" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="32" id="mAe-Bq-7kh"/>
189-
<constraint firstItem="GSD-GC-nGa" firstAttribute="top" secondItem="BwO-Q2-dKq" secondAttribute="bottom" constant="6" id="mqm-Cr-3Yq"/>
190-
<constraint firstItem="GSD-GC-nGa" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="32" id="qkH-mq-Lqy"/>
191200
</constraints>
192201
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
193202
</view>
194203
<connections>
195204
<outlet property="emailTextField" destination="ipt-cn-CA9" id="ZEk-ud-teh"/>
196205
<outlet property="passwordTextField" destination="SwP-Fd-Fft" id="4b6-Xb-44G"/>
206+
<outlet property="stackView" destination="Wz3-0y-Vnd" id="vI5-yV-I8e"/>
197207
<outlet property="usernameTextField" destination="Ib7-Qf-pz7" id="TKO-SU-ATJ"/>
198208
</connections>
199209
</viewController>

TweeTextField/ViewController.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,24 @@ extension String {
1313
}
1414

1515
final class ViewController: UIViewController {
16-
16+
@IBOutlet private weak var stackView: UIStackView!
1717
@IBOutlet private weak var usernameTextField: TweeBorderedTextField!
18-
1918
@IBOutlet private weak var passwordTextField: TweeActiveTextField!
20-
2119
@IBOutlet private weak var emailTextField: TweeAttributedTextField!
2220

2321
override func viewDidLoad() {
2422
super.viewDidLoad()
25-
// usernameTextField.text = "text"
26-
// usernameTextField.tweePlaceholder = "User name"
2723

2824
passwordTextField.text = "password"
2925
emailTextField.text = "text"
3026
}
3127

28+
@IBAction private func removeFirstField() {
29+
stackView.arrangedSubviews.first.flatMap {
30+
$0.removeFromSuperview()
31+
}
32+
}
33+
3234
@IBAction private func confirm() {
3335
emailTextField.text = "Issue #8"
3436
}

0 commit comments

Comments
 (0)