From b2091431dcb967b747964d82333dbbc2161a357e Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 19 Jan 2017 10:57:07 -0500 Subject: [PATCH] Fix retain cycle // FREEBIE --- Signal.xcodeproj/project.pbxproj | 4 +++ Signal/src/call/CallAudioService.swift | 5 ++- Signal/src/util/WeakTimer.swift | 43 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 Signal/src/util/WeakTimer.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index c44ef0761..4640ad18f 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -105,6 +105,7 @@ 45F170BB1E2FC5D3003FC1F2 /* CallAudioService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F170BA1E2FC5D3003FC1F2 /* CallAudioService.swift */; }; 45F170BC1E2FC5D3003FC1F2 /* CallAudioService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F170BA1E2FC5D3003FC1F2 /* CallAudioService.swift */; }; 45F170D61E315310003FC1F2 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F170D51E315310003FC1F2 /* Weak.swift */; }; + 45F170CC1E310E22003FC1F2 /* WeakTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F170CB1E310E22003FC1F2 /* WeakTimer.swift */; }; 45F2B1941D9C9F48000D2C69 /* OWSOutgoingMessageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 45F2B1931D9C9F48000D2C69 /* OWSOutgoingMessageCollectionViewCell.m */; }; 45F2B1971D9CA207000D2C69 /* OWSIncomingMessageCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 45F2B1951D9CA207000D2C69 /* OWSIncomingMessageCollectionViewCell.xib */; }; 45F2B1981D9CA207000D2C69 /* OWSOutgoingMessageCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 45F2B1961D9CA207000D2C69 /* OWSOutgoingMessageCollectionViewCell.xib */; }; @@ -701,6 +702,7 @@ 45F170B31E2F0A6A003FC1F2 /* RTCAudioSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCAudioSession.h; sourceTree = ""; }; 45F170BA1E2FC5D3003FC1F2 /* CallAudioService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallAudioService.swift; sourceTree = ""; }; 45F170D51E315310003FC1F2 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = ""; }; + 45F170CB1E310E22003FC1F2 /* WeakTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeakTimer.swift; sourceTree = ""; }; 45F2B1921D9C9F48000D2C69 /* OWSOutgoingMessageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSOutgoingMessageCollectionViewCell.h; sourceTree = ""; }; 45F2B1931D9C9F48000D2C69 /* OWSOutgoingMessageCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOutgoingMessageCollectionViewCell.m; sourceTree = ""; }; 45F2B1951D9CA207000D2C69 /* OWSIncomingMessageCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OWSIncomingMessageCollectionViewCell.xib; sourceTree = ""; }; @@ -1951,6 +1953,7 @@ 45CD81F11DC03A22004C9430 /* OWSLogger.m */, 450DF2041E0D74AC003D14BE /* Platform.swift */, 45F170D51E315310003FC1F2 /* Weak.swift */, + 45F170CB1E310E22003FC1F2 /* WeakTimer.swift */, ); path = util; sourceTree = ""; @@ -3138,6 +3141,7 @@ 453D28BA1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */, 45F170AC1E2F0351003FC1F2 /* CallAudioSession.swift in Sources */, B68EF9BB1C0B1EBD009C3DCD /* FLAnimatedImageView.m in Sources */, + 45F170CC1E310E22003FC1F2 /* WeakTimer.swift in Sources */, A5E9D4BB1A65FAD800E4481C /* TSVideoAttachmentAdapter.m in Sources */, E197B61118BBEC1A00F073E5 /* AudioProcessor.m in Sources */, FCAC964019FEF99A0046DFC5 /* InboxTableViewCell.m in Sources */, diff --git a/Signal/src/call/CallAudioService.swift b/Signal/src/call/CallAudioService.swift index 70cd7ab95..9c1d05ee3 100644 --- a/Signal/src/call/CallAudioService.swift +++ b/Signal/src/call/CallAudioService.swift @@ -129,7 +129,10 @@ import Foundation return } - vibrateTimer = Timer.scheduledTimer(timeInterval: vibrateRepeatDuration, target: self, selector: #selector(ringVibration), userInfo: nil, repeats: true) + vibrateTimer = WeakTimer.scheduledTimer(timeInterval: vibrateRepeatDuration, target: self, userInfo: nil, repeats: true) {[weak self] timer in + self?.ringVibration() + } + vibrateTimer?.fire() // Stop other sounds and play ringer through external speaker setAudioSession(category: AVAudioSessionCategorySoloAmbient) diff --git a/Signal/src/util/WeakTimer.swift b/Signal/src/util/WeakTimer.swift new file mode 100644 index 000000000..1eea5e153 --- /dev/null +++ b/Signal/src/util/WeakTimer.swift @@ -0,0 +1,43 @@ +// +// Copyright © 2017 Open Whisper Systems. All rights reserved. +// + +/** + * As of iOS10, the timer API's take a block, which makes it easy to reference weak self in Swift. This class offers a + * similar API that works pre iOS10. + * + * Solution modified from + * http://stackoverflow.com/questions/16821736/weak-reference-to-nstimer-target-to-prevent-retain-cycle/41003985#41003985 + */ +final class WeakTimer { + + fileprivate weak var timer: Timer? + fileprivate weak var target: AnyObject? + fileprivate let action: (Timer) -> Void + + fileprivate init(timeInterval: TimeInterval, target: AnyObject, userInfo: Any?, repeats: Bool, action: @escaping (Timer) -> Void) { + self.target = target + self.action = action + self.timer = Timer.scheduledTimer(timeInterval: timeInterval, + target: self, + selector: #selector(fire), + userInfo: userInfo, + repeats: repeats) + } + + class func scheduledTimer(timeInterval: TimeInterval, target: AnyObject, userInfo: Any?, repeats: Bool, action: @escaping (Timer) -> Void) -> Timer { + return WeakTimer(timeInterval: timeInterval, + target: target, + userInfo: userInfo, + repeats: repeats, + action: action).timer! + } + + @objc fileprivate func fire(timer: Timer) { + if target != nil { + action(timer) + } else { + timer.invalidate() + } + } +}