Skip to content

Commit

Permalink
#22. Fix leaks.
Browse files Browse the repository at this point in the history
  • Loading branch information
oleghnidets committed Sep 14, 2018
1 parent f46e84c commit 83d8cb3
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 42 deletions.
11 changes: 5 additions & 6 deletions Sources/FontAnimation.swift
Expand Up @@ -7,15 +7,12 @@ import QuartzCore
import CoreFoundation

internal final class FontAnimation {

private let displayLink: CADisplayLink?
private var displayLink: CADisplayLink?
private(set) var startTime: CFTimeInterval?

private let target: Any
private let selector: Selector

init(target: Any, selector: Selector) {
self.target = target
init(target: AnyObject, selector: Selector) {
self.selector = selector

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

func start() {
startTime = CFAbsoluteTimeGetCurrent()
displayLink?.isPaused = false

startTime = CFAbsoluteTimeGetCurrent()
}

func stop() {
startTime = nil

displayLink?.isPaused = true
}
}
4 changes: 2 additions & 2 deletions Sources/TweePlaceholderTextField.swift
Expand Up @@ -85,8 +85,8 @@ open class TweePlaceholderTextField: UITextField {
}
}

private lazy var minimizeFontAnimation = FontAnimation(target: self, selector: #selector(minimizePlaceholderFontSize))
private lazy var maximizeFontAnimation = FontAnimation(target: self, selector: #selector(maximizePlaceholderFontSize))
private lazy var minimizeFontAnimation = FontAnimation(target: WeakTargetProxy(target: self), selector: #selector(minimizePlaceholderFontSize))
private lazy var maximizeFontAnimation = FontAnimation(target: WeakTargetProxy(target: self), selector: #selector(maximizePlaceholderFontSize))

private let placeholderLayoutGuide = UILayoutGuide()
private var leadingPlaceholderConstraint: NSLayoutConstraint?
Expand Down
27 changes: 27 additions & 0 deletions Sources/WeakTargetProxy.swift
@@ -0,0 +1,27 @@
// Created by Oleg Hnidets on 9/14/18.
// Copyright 漏 2018 Oleg Hnidets. All rights reserved.
//

import Foundation

internal final class WeakTargetProxy: NSObject {
private weak var target: NSObjectProtocol?

init(target: NSObjectProtocol) {
self.target = target

super.init()
}

override func responds(to aSelector: Selector!) -> Bool {
guard let target = target else {
return super.responds(to: aSelector)
}

return target.responds(to: aSelector) || super.responds(to: aSelector)
}

override func forwardingTarget(for aSelector: Selector!) -> Any? {
return target
}
}
6 changes: 6 additions & 0 deletions TweeTextField.xcodeproj/project.pbxproj
Expand Up @@ -15,6 +15,8 @@
7C065D3920E3F02C00B8F983 /* TweeAttributedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A146091FEC228900CEADAA /* TweeAttributedTextField.swift */; };
7C065D3A20E3F02C00B8F983 /* TweeActiveTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A1460A1FEC228900CEADAA /* TweeActiveTextField.swift */; };
7C065D3B20E3F02C00B8F983 /* FontAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A1460B1FEC228900CEADAA /* FontAnimation.swift */; };
7C15066C214BF43D006A7D4C /* WeakTargetProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */; };
7C15066D214BF47E006A7D4C /* WeakTargetProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */; };
7CF5909A2125DB5D0015777F /* PasswordTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CF590992125DB5D0015777F /* PasswordTextField.swift */; };
92A1460C1FEC228900CEADAA /* TweePlaceholderTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A146071FEC228900CEADAA /* TweePlaceholderTextField.swift */; };
92A1460D1FEC228900CEADAA /* TweeBorderedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A146081FEC228900CEADAA /* TweeBorderedTextField.swift */; };
Expand Down Expand Up @@ -56,6 +58,7 @@
7C065D2B20E3EFCD00B8F983 /* TweeTextField.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TweeTextField.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7C065D2D20E3EFCD00B8F983 /* TweeTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TweeTextField.h; sourceTree = "<group>"; };
7C065D2E20E3EFCD00B8F983 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakTargetProxy.swift; sourceTree = "<group>"; };
7CF590992125DB5D0015777F /* PasswordTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordTextField.swift; sourceTree = "<group>"; };
92A146071FEC228900CEADAA /* TweePlaceholderTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TweePlaceholderTextField.swift; sourceTree = "<group>"; };
92A146081FEC228900CEADAA /* TweeBorderedTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TweeBorderedTextField.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -119,6 +122,7 @@
92A146091FEC228900CEADAA /* TweeAttributedTextField.swift */,
92A1460A1FEC228900CEADAA /* TweeActiveTextField.swift */,
92A1460B1FEC228900CEADAA /* FontAnimation.swift */,
7C15066B214BF43D006A7D4C /* WeakTargetProxy.swift */,
);
path = Sources;
sourceTree = SOURCE_ROOT;
Expand Down Expand Up @@ -303,6 +307,7 @@
7C065D3920E3F02C00B8F983 /* TweeAttributedTextField.swift in Sources */,
7C065D3A20E3F02C00B8F983 /* TweeActiveTextField.swift in Sources */,
7C065D3B20E3F02C00B8F983 /* FontAnimation.swift in Sources */,
7C15066C214BF43D006A7D4C /* WeakTargetProxy.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -311,6 +316,7 @@
buildActionMask = 2147483647;
files = (
92A146101FEC228900CEADAA /* FontAnimation.swift in Sources */,
7C15066D214BF47E006A7D4C /* WeakTargetProxy.swift in Sources */,
92A1460F1FEC228900CEADAA /* TweeActiveTextField.swift in Sources */,
92E7FC3C1FE0374600E58DF5 /* ViewController.swift in Sources */,
92E7FC3A1FE0374600E58DF5 /* AppDelegate.swift in Sources */,
Expand Down
68 changes: 39 additions & 29 deletions TweeTextField/Base.lproj/Main.storyboard
Expand Up @@ -20,7 +20,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BwO-Q2-dKq">
<rect key="frame" x="147" y="249" width="80" height="33"/>
<rect key="frame" x="147" y="319" width="80" height="33"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<state key="normal" title="CONFIRM">
<color key="titleColor" red="0.29019609089999998" green="0.5647059083" blue="0.88627451660000001" alpha="1" colorSpace="deviceRGB"/>
Expand All @@ -30,7 +30,7 @@
</connections>
</button>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Wz3-0y-Vnd">
<rect key="frame" x="19" y="52" width="337.5" height="160"/>
<rect key="frame" x="19" y="52" width="337.5" height="230"/>
<subviews>
<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">
<rect key="frame" x="0.0" y="0.0" width="337.5" height="40"/>
Expand Down Expand Up @@ -147,53 +147,63 @@
<action selector="emailEndEditing:" destination="BYZ-38-t0r" eventType="editingDidEnd" id="PUh-nQ-uM3"/>
</connections>
</textField>
<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">
<rect key="frame" x="0.0" y="180" width="337.5" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="hX8-3C-iGN"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="tweePlaceholder" value="Password"/>
<userDefinedRuntimeAttribute type="color" keyPath="placeholderColor">
<color key="value" red="0.0039215686269999999" green="0.63137254899999995" blue="0.3803921569" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="placeholderDuration">
<real key="value" value="0.5"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="minimumPlaceholderFontSize">
<real key="value" value="12"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="originalPlaceholderFontSize">
<real key="value" value="17"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textField>
</subviews>
<constraints>
<constraint firstItem="SwP-Fd-Fft" firstAttribute="height" secondItem="ipt-cn-CA9" secondAttribute="height" id="YoF-I6-WIk"/>
<constraint firstItem="Ib7-Qf-pz7" firstAttribute="height" secondItem="SwP-Fd-Fft" secondAttribute="height" id="fMy-5c-WpL"/>
</constraints>
</stackView>
<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">
<rect key="frame" x="32" y="288" width="312" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="hX8-3C-iGN"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="tweePlaceholder" value="Password"/>
<userDefinedRuntimeAttribute type="color" keyPath="placeholderColor">
<color key="value" red="0.0039215686269999999" green="0.63137254899999995" blue="0.3803921569" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="placeholderDuration">
<real key="value" value="0.5"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="minimumPlaceholderFontSize">
<real key="value" value="12"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="originalPlaceholderFontSize">
<real key="value" value="17"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textField>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H4d-jf-O4s">
<rect key="frame" x="109.5" y="360" width="156" height="30"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="REMOVE FIRST FIELD">
<color key="titleColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="removeFirstField" destination="BYZ-38-t0r" eventType="touchUpInside" id="diE-xv-ZVH"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="GSD-GC-nGa" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="0pO-mT-DDF"/>
<constraint firstItem="Wz3-0y-Vnd" firstAttribute="width" secondItem="8bC-Xf-vdC" secondAttribute="width" multiplier="0.9" id="DEP-8P-yxv"/>
<constraint firstItem="H4d-jf-O4s" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="IqP-Pb-iIT"/>
<constraint firstItem="Wz3-0y-Vnd" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="KQH-V3-b5K"/>
<constraint firstItem="H4d-jf-O4s" firstAttribute="top" secondItem="BwO-Q2-dKq" secondAttribute="bottom" constant="8" id="R8c-TI-mLY"/>
<constraint firstItem="BwO-Q2-dKq" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="SrW-DF-eDg"/>
<constraint firstItem="BwO-Q2-dKq" firstAttribute="top" secondItem="Wz3-0y-Vnd" secondAttribute="bottom" constant="37" id="aa8-zk-OuM"/>
<constraint firstItem="Wz3-0y-Vnd" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="32" id="mAe-Bq-7kh"/>
<constraint firstItem="GSD-GC-nGa" firstAttribute="top" secondItem="BwO-Q2-dKq" secondAttribute="bottom" constant="6" id="mqm-Cr-3Yq"/>
<constraint firstItem="GSD-GC-nGa" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="32" id="qkH-mq-Lqy"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
<connections>
<outlet property="emailTextField" destination="ipt-cn-CA9" id="ZEk-ud-teh"/>
<outlet property="passwordTextField" destination="SwP-Fd-Fft" id="4b6-Xb-44G"/>
<outlet property="stackView" destination="Wz3-0y-Vnd" id="vI5-yV-I8e"/>
<outlet property="usernameTextField" destination="Ib7-Qf-pz7" id="TKO-SU-ATJ"/>
</connections>
</viewController>
Expand Down
12 changes: 7 additions & 5 deletions TweeTextField/ViewController.swift
Expand Up @@ -13,22 +13,24 @@ extension String {
}

final class ViewController: UIViewController {

@IBOutlet private weak var stackView: UIStackView!
@IBOutlet private weak var usernameTextField: TweeBorderedTextField!

@IBOutlet private weak var passwordTextField: TweeActiveTextField!

@IBOutlet private weak var emailTextField: TweeAttributedTextField!

override func viewDidLoad() {
super.viewDidLoad()
// usernameTextField.text = "text"
// usernameTextField.tweePlaceholder = "User name"

passwordTextField.text = "password"
emailTextField.text = "text"
}

@IBAction private func removeFirstField() {
stackView.arrangedSubviews.first.flatMap {
$0.removeFromSuperview()
}
}

@IBAction private func confirm() {
emailTextField.text = "Issue #8"
}
Expand Down

0 comments on commit 83d8cb3

Please sign in to comment.