Merge pull request #377 from oxen-io/memory-leaks

Fix Memory Leaks
This commit is contained in:
Niels Andriesse 2021-04-01 14:25:25 +11:00 committed by GitHub
commit 0daa91facd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 56 additions and 56 deletions

View file

@ -6,38 +6,38 @@ extension ContextMenuVC {
let title: String let title: String
let work: () -> Void let work: () -> Void
static func reply(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate) -> Action { static func reply(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action {
let title = "Reply" let title = "Reply"
return Action(icon: UIImage(named: "ic_reply")!, title: title) { delegate.reply(viewItem) } return Action(icon: UIImage(named: "ic_reply")!, title: title) { delegate?.reply(viewItem) }
} }
static func copy(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate) -> Action { static func copy(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action {
let title = "Copy" let title = "Copy"
return Action(icon: UIImage(named: "ic_copy")!, title: title) { delegate.copy(viewItem) } return Action(icon: UIImage(named: "ic_copy")!, title: title) { delegate?.copy(viewItem) }
} }
static func copySessionID(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate) -> Action { static func copySessionID(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action {
let title = "Copy Session ID" let title = "Copy Session ID"
return Action(icon: UIImage(named: "ic_copy")!, title: title) { delegate.copySessionID(viewItem) } return Action(icon: UIImage(named: "ic_copy")!, title: title) { delegate?.copySessionID(viewItem) }
} }
static func delete(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate) -> Action { static func delete(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action {
let title = "Delete" let title = "Delete"
return Action(icon: UIImage(named: "ic_trash")!, title: title) { delegate.delete(viewItem) } return Action(icon: UIImage(named: "ic_trash")!, title: title) { delegate?.delete(viewItem) }
} }
static func save(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate) -> Action { static func save(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action {
let title = "Save" let title = "Save"
return Action(icon: UIImage(named: "ic_download")!, title: title) { delegate.save(viewItem) } return Action(icon: UIImage(named: "ic_download")!, title: title) { delegate?.save(viewItem) }
} }
static func ban(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate) -> Action { static func ban(_ viewItem: ConversationViewItem, _ delegate: ContextMenuActionDelegate?) -> Action {
let title = "Ban User" let title = "Ban User"
return Action(icon: UIImage(named: "ic_block")!, title: title) { delegate.ban(viewItem) } return Action(icon: UIImage(named: "ic_block")!, title: title) { delegate?.ban(viewItem) }
} }
} }
static func actions(for viewItem: ConversationViewItem, delegate: ContextMenuActionDelegate) -> [Action] { static func actions(for viewItem: ConversationViewItem, delegate: ContextMenuActionDelegate?) -> [Action] {
func isReplyingAllowed() -> Bool { func isReplyingAllowed() -> Bool {
guard let message = viewItem.interaction as? TSOutgoingMessage else { return true } guard let message = viewItem.interaction as? TSOutgoingMessage else { return true }
switch message.messageState { switch message.messageState {
@ -71,7 +71,7 @@ extension ContextMenuVC {
} }
// MARK: Delegate // MARK: Delegate
protocol ContextMenuActionDelegate { protocol ContextMenuActionDelegate : class {
func reply(_ viewItem: ConversationViewItem) func reply(_ viewItem: ConversationViewItem)
func copy(_ viewItem: ConversationViewItem) func copy(_ viewItem: ConversationViewItem)

View file

@ -3,8 +3,8 @@ final class ContextMenuVC : UIViewController {
private let snapshot: UIView private let snapshot: UIView
private let viewItem: ConversationViewItem private let viewItem: ConversationViewItem
private let frame: CGRect private let frame: CGRect
private let delegate: ContextMenuActionDelegate
private let dismiss: () -> Void private let dismiss: () -> Void
private weak var delegate: ContextMenuActionDelegate?
// MARK: UI Components // MARK: UI Components
private lazy var blurView = UIVisualEffectView(effect: nil) private lazy var blurView = UIVisualEffectView(effect: nil)

View file

@ -1,6 +1,6 @@
final class ExpandingAttachmentsButton : UIView, InputViewButtonDelegate { final class ExpandingAttachmentsButton : UIView, InputViewButtonDelegate {
private let delegate: ExpandingAttachmentsButtonDelegate private weak var delegate: ExpandingAttachmentsButtonDelegate?
private var isExpanded = false { didSet { expandOrCollapse() } } private var isExpanded = false { didSet { expandOrCollapse() } }
// MARK: Constraints // MARK: Constraints
@ -22,7 +22,7 @@ final class ExpandingAttachmentsButton : UIView, InputViewButtonDelegate {
lazy var mainButtonContainer = container(for: mainButton) lazy var mainButtonContainer = container(for: mainButton)
// MARK: Lifecycle // MARK: Lifecycle
init(delegate: ExpandingAttachmentsButtonDelegate) { init(delegate: ExpandingAttachmentsButtonDelegate?) {
self.delegate = delegate self.delegate = delegate
super.init(frame: CGRect.zero) super.init(frame: CGRect.zero)
setUpViewHierarchy() setUpViewHierarchy()
@ -93,10 +93,10 @@ final class ExpandingAttachmentsButton : UIView, InputViewButtonDelegate {
// MARK: Interaction // MARK: Interaction
func handleInputViewButtonTapped(_ inputViewButton: InputViewButton) { func handleInputViewButtonTapped(_ inputViewButton: InputViewButton) {
if inputViewButton == gifButton { delegate.handleGIFButtonTapped(); isExpanded = false } if inputViewButton == gifButton { delegate?.handleGIFButtonTapped(); isExpanded = false }
if inputViewButton == documentButton { delegate.handleDocumentButtonTapped(); isExpanded = false } if inputViewButton == documentButton { delegate?.handleDocumentButtonTapped(); isExpanded = false }
if inputViewButton == libraryButton { delegate.handleLibraryButtonTapped(); isExpanded = false } if inputViewButton == libraryButton { delegate?.handleLibraryButtonTapped(); isExpanded = false }
if inputViewButton == cameraButton { delegate.handleCameraButtonTapped(); isExpanded = false } if inputViewButton == cameraButton { delegate?.handleCameraButtonTapped(); isExpanded = false }
if inputViewButton == mainButton { isExpanded = !isExpanded } if inputViewButton == mainButton { isExpanded = !isExpanded }
} }
@ -112,7 +112,7 @@ final class ExpandingAttachmentsButton : UIView, InputViewButtonDelegate {
} }
// MARK: Delegate // MARK: Delegate
protocol ExpandingAttachmentsButtonDelegate { protocol ExpandingAttachmentsButtonDelegate : class {
func handleGIFButtonTapped() func handleGIFButtonTapped()
func handleDocumentButtonTapped() func handleDocumentButtonTapped()

View file

@ -1,6 +1,6 @@
public final class InputTextView : UITextView, UITextViewDelegate { public final class InputTextView : UITextView, UITextViewDelegate {
private let snDelegate: InputTextViewDelegate private weak var snDelegate: InputTextViewDelegate?
private let maxWidth: CGFloat private let maxWidth: CGFloat
private lazy var heightConstraint = self.set(.height, to: minHeight) private lazy var heightConstraint = self.set(.height, to: minHeight)
@ -60,7 +60,7 @@ public final class InputTextView : UITextView, UITextViewDelegate {
} }
private func handleTextChanged() { private func handleTextChanged() {
defer { snDelegate.inputTextViewDidChangeContent(self) } defer { snDelegate?.inputTextViewDidChangeContent(self) }
placeholderLabel.isHidden = !text.isEmpty placeholderLabel.isHidden = !text.isEmpty
let height = frame.height let height = frame.height
let size = sizeThatFits(CGSize(width: maxWidth, height: .greatestFiniteMagnitude)) let size = sizeThatFits(CGSize(width: maxWidth, height: .greatestFiniteMagnitude))
@ -69,12 +69,12 @@ public final class InputTextView : UITextView, UITextViewDelegate {
let newHeight = size.height.clamp(minHeight, maxHeight) let newHeight = size.height.clamp(minHeight, maxHeight)
guard newHeight != height else { return } guard newHeight != height else { return }
heightConstraint.constant = newHeight heightConstraint.constant = newHeight
snDelegate.inputTextViewDidChangeSize(self) snDelegate?.inputTextViewDidChangeSize(self)
} }
} }
// MARK: Delegate // MARK: Delegate
protocol InputTextViewDelegate { protocol InputTextViewDelegate : class {
func inputTextViewDidChangeSize(_ inputTextView: InputTextView) func inputTextViewDidChangeSize(_ inputTextView: InputTextView)
func inputTextViewDidChangeContent(_ inputTextView: InputTextView) func inputTextViewDidChangeContent(_ inputTextView: InputTextView)

View file

@ -1,6 +1,6 @@
final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate, QuoteViewDelegate, LinkPreviewViewDelegate, MentionSelectionViewDelegate { final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate, QuoteViewDelegate, LinkPreviewViewDelegate, MentionSelectionViewDelegate {
private let delegate: InputViewDelegate private weak var delegate: InputViewDelegate?
var quoteDraftInfo: (model: OWSQuotedReplyModel, isOutgoing: Bool)? { didSet { handleQuoteDraftChanged() } } var quoteDraftInfo: (model: OWSQuotedReplyModel, isOutgoing: Bool)? { didSet { handleQuoteDraftChanged() } }
var linkPreviewInfo: (url: String, draft: OWSLinkPreviewDraft?)? var linkPreviewInfo: (url: String, draft: OWSLinkPreviewDraft?)?
private var voiceMessageRecordingView: VoiceMessageRecordingView? private var voiceMessageRecordingView: VoiceMessageRecordingView?
@ -135,7 +135,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
sendButton.isHidden = !hasText sendButton.isHidden = !hasText
voiceMessageButtonContainer.isHidden = hasText voiceMessageButtonContainer.isHidden = hasText
autoGenerateLinkPreviewIfPossible() autoGenerateLinkPreviewIfPossible()
delegate.inputTextViewDidChangeContent(inputTextView) delegate?.inputTextViewDidChangeContent(inputTextView)
} }
// We want to show either a link preview or a quote draft, but never both at the same time. When trying to // We want to show either a link preview or a quote draft, but never both at the same time. When trying to
@ -164,7 +164,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
let userDefaults = UserDefaults.standard let userDefaults = UserDefaults.standard
if !OWSLinkPreview.allPreviewUrls(forMessageBodyText: text).isEmpty && !SSKPreferences.areLinkPreviewsEnabled if !OWSLinkPreview.allPreviewUrls(forMessageBodyText: text).isEmpty && !SSKPreferences.areLinkPreviewsEnabled
&& !userDefaults[.hasSeenLinkPreviewSuggestion] { && !userDefaults[.hasSeenLinkPreviewSuggestion] {
delegate.showLinkPreviewSuggestionModal() delegate?.showLinkPreviewSuggestionModal()
userDefaults[.hasSeenLinkPreviewSuggestion] = true userDefaults[.hasSeenLinkPreviewSuggestion] = true
return return
} }
@ -235,12 +235,12 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
} }
func handleInputViewButtonTapped(_ inputViewButton: InputViewButton) { func handleInputViewButtonTapped(_ inputViewButton: InputViewButton) {
if inputViewButton == sendButton { delegate.handleSendButtonTapped() } if inputViewButton == sendButton { delegate?.handleSendButtonTapped() }
} }
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton) { func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton) {
guard inputViewButton == voiceMessageButton else { return } guard inputViewButton == voiceMessageButton else { return }
delegate.startVoiceMessageRecording() delegate?.startVoiceMessageRecording()
showVoiceMessageUI() showVoiceMessageUI()
} }
@ -257,7 +257,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
} }
func handleQuoteViewCancelButtonTapped() { func handleQuoteViewCancelButtonTapped() {
delegate.handleQuoteViewCancelButtonTapped() delegate?.handleQuoteViewCancelButtonTapped()
} }
override func resignFirstResponder() -> Bool { override func resignFirstResponder() -> Bool {
@ -326,7 +326,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
} }
func handleMentionSelected(_ mention: Mention, from view: MentionSelectionView) { func handleMentionSelected(_ mention: Mention, from view: MentionSelectionView) {
delegate.handleMentionSelected(mention, from: view) delegate?.handleMentionSelected(mention, from: view)
} }
// MARK: Convenience // MARK: Convenience
@ -341,7 +341,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
} }
// MARK: Delegate // MARK: Delegate
protocol InputViewDelegate : ExpandingAttachmentsButtonDelegate, VoiceMessageRecordingViewDelegate { protocol InputViewDelegate : class, ExpandingAttachmentsButtonDelegate, VoiceMessageRecordingViewDelegate {
func showLinkPreviewSuggestionModal() func showLinkPreviewSuggestionModal()
func handleSendButtonTapped() func handleSendButtonTapped()

View file

@ -2,7 +2,7 @@
final class InputViewButton : UIView { final class InputViewButton : UIView {
private let icon: UIImage private let icon: UIImage
private let isSendButton: Bool private let isSendButton: Bool
private let delegate: InputViewButtonDelegate private weak var delegate: InputViewButtonDelegate?
private let hasOpaqueBackground: Bool private let hasOpaqueBackground: Bool
private lazy var widthConstraint = set(.width, to: InputViewButton.size) private lazy var widthConstraint = set(.width, to: InputViewButton.size)
private lazy var heightConstraint = set(.height, to: InputViewButton.size) private lazy var heightConstraint = set(.height, to: InputViewButton.size)
@ -103,22 +103,22 @@ final class InputViewButton : UIView {
longPressTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { [weak self] _ in longPressTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { [weak self] _ in
guard let self = self else { return } guard let self = self else { return }
self.isLongPress = true self.isLongPress = true
self.delegate.handleInputViewButtonLongPressBegan(self) self.delegate?.handleInputViewButtonLongPressBegan(self)
}) })
} }
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if isLongPress { if isLongPress {
delegate.handleInputViewButtonLongPressMoved(self, with: touches.first!) delegate?.handleInputViewButtonLongPressMoved(self, with: touches.first!)
} }
} }
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
collapse() collapse()
if !isLongPress { if !isLongPress {
delegate.handleInputViewButtonTapped(self) delegate?.handleInputViewButtonTapped(self)
} else { } else {
delegate.handleInputViewButtonLongPressEnded(self, with: touches.first!) delegate?.handleInputViewButtonLongPressEnded(self, with: touches.first!)
} }
invalidateLongPressIfNeeded() invalidateLongPressIfNeeded()
} }
@ -135,7 +135,7 @@ final class InputViewButton : UIView {
} }
// MARK: Delegate // MARK: Delegate
protocol InputViewButtonDelegate { protocol InputViewButtonDelegate : class {
func handleInputViewButtonTapped(_ inputViewButton: InputViewButton) func handleInputViewButtonTapped(_ inputViewButton: InputViewButton)
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton) func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton)

View file

@ -9,7 +9,7 @@ final class MentionSelectionView : UIView, UITableViewDataSource, UITableViewDel
var openGroupServer: String? var openGroupServer: String?
var openGroupChannel: UInt64? var openGroupChannel: UInt64?
var openGroupRoom: String? var openGroupRoom: String?
var delegate: MentionSelectionViewDelegate? weak var delegate: MentionSelectionViewDelegate?
// MARK: Components // MARK: Components
lazy var tableView: UITableView = { // TODO: Make this private lazy var tableView: UITableView = { // TODO: Make this private
@ -177,7 +177,7 @@ private extension MentionSelectionView {
// MARK: - Delegate // MARK: - Delegate
protocol MentionSelectionViewDelegate { protocol MentionSelectionViewDelegate : class {
func handleMentionSelected(_ mention: Mention, from view: MentionSelectionView) func handleMentionSelected(_ mention: Mention, from view: MentionSelectionView)
} }

View file

@ -1,7 +1,7 @@
final class VoiceMessageRecordingView : UIView { final class VoiceMessageRecordingView : UIView {
private let voiceMessageButtonFrame: CGRect private let voiceMessageButtonFrame: CGRect
private let delegate: VoiceMessageRecordingViewDelegate private weak var delegate: VoiceMessageRecordingViewDelegate?
private lazy var slideToCancelStackViewRightConstraint = slideToCancelStackView.pin(.right, to: .right, of: self) private lazy var slideToCancelStackViewRightConstraint = slideToCancelStackView.pin(.right, to: .right, of: self)
private lazy var slideToCancelLabelCenterHorizontalConstraint = slideToCancelLabel.center(.horizontal, in: self) private lazy var slideToCancelLabelCenterHorizontalConstraint = slideToCancelLabel.center(.horizontal, in: self)
private lazy var pulseViewWidthConstraint = pulseView.set(.width, to: VoiceMessageRecordingView.circleSize) private lazy var pulseViewWidthConstraint = pulseView.set(.width, to: VoiceMessageRecordingView.circleSize)
@ -115,7 +115,7 @@ final class VoiceMessageRecordingView : UIView {
private static let lockViewHitMargin: CGFloat = 40 private static let lockViewHitMargin: CGFloat = 40
// MARK: Lifecycle // MARK: Lifecycle
init(voiceMessageButtonFrame: CGRect, delegate: VoiceMessageRecordingViewDelegate) { init(voiceMessageButtonFrame: CGRect, delegate: VoiceMessageRecordingViewDelegate?) {
self.voiceMessageButtonFrame = voiceMessageButtonFrame self.voiceMessageButtonFrame = voiceMessageButtonFrame
self.delegate = delegate self.delegate = delegate
super.init(frame: CGRect.zero) super.init(frame: CGRect.zero)
@ -269,7 +269,7 @@ final class VoiceMessageRecordingView : UIView {
func handleLongPressEnded(at location: CGPoint) { func handleLongPressEnded(at location: CGPoint) {
if pulseView.frame.contains(location) { if pulseView.frame.contains(location) {
delegate.endVoiceMessageRecording() delegate?.endVoiceMessageRecording()
} else if isValidLockViewLocation(location) { } else if isValidLockViewLocation(location) {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCircleViewTap)) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCircleViewTap))
circleView.addGestureRecognizer(tapGestureRecognizer) circleView.addGestureRecognizer(tapGestureRecognizer)
@ -282,16 +282,16 @@ final class VoiceMessageRecordingView : UIView {
// Do nothing // Do nothing
}) })
} else { } else {
delegate.cancelVoiceMessageRecording() delegate?.cancelVoiceMessageRecording()
} }
} }
@objc private func handleCircleViewTap() { @objc private func handleCircleViewTap() {
delegate.endVoiceMessageRecording() delegate?.endVoiceMessageRecording()
} }
@objc private func handleCancelButtonTapped() { @objc private func handleCancelButtonTapped() {
delegate.cancelVoiceMessageRecording() delegate?.cancelVoiceMessageRecording()
} }
// MARK: Convenience // MARK: Convenience
@ -397,7 +397,7 @@ extension VoiceMessageRecordingView {
} }
// MARK: Delegate // MARK: Delegate
protocol VoiceMessageRecordingViewDelegate { protocol VoiceMessageRecordingViewDelegate : class {
func startVoiceMessageRecording() func startVoiceMessageRecording()
func endVoiceMessageRecording() func endVoiceMessageRecording()

View file

@ -1,7 +1,7 @@
import UIKit import UIKit
class MessageCell : UITableViewCell { class MessageCell : UITableViewCell {
var delegate: MessageCellDelegate? weak var delegate: MessageCellDelegate?
var viewItem: ConversationViewItem? { didSet { update() } } var viewItem: ConversationViewItem? { didSet { update() } }
// MARK: Settings // MARK: Settings
@ -48,7 +48,7 @@ class MessageCell : UITableViewCell {
} }
} }
protocol MessageCellDelegate { protocol MessageCellDelegate : class {
var lastSearchedText: String? { get } var lastSearchedText: String? { get }
func getMediaCache() -> NSCache<NSString, AnyObject> func getMediaCache() -> NSCache<NSString, AnyObject>

View file

@ -1,7 +1,7 @@
final class ConversationTitleView : UIView { final class ConversationTitleView : UIView {
private let thread: TSThread private let thread: TSThread
var delegate: ConversationTitleViewDelegate? weak var delegate: ConversationTitleViewDelegate?
override var intrinsicContentSize: CGSize { override var intrinsicContentSize: CGSize {
return UIView.layoutFittingExpandedSize return UIView.layoutFittingExpandedSize
@ -121,7 +121,7 @@ final class ConversationTitleView : UIView {
} }
// MARK: Delegate // MARK: Delegate
protocol ConversationTitleViewDelegate { protocol ConversationTitleViewDelegate : class {
func handleTitleViewTapped() func handleTitleViewTapped()
} }

View file

@ -1,6 +1,6 @@
final class ScrollToBottomButton : UIView { final class ScrollToBottomButton : UIView {
private let delegate: ScrollToBottomButtonDelegate private weak var delegate: ScrollToBottomButtonDelegate?
// MARK: Settings // MARK: Settings
private static let size: CGFloat = 40 private static let size: CGFloat = 40
@ -57,11 +57,11 @@ final class ScrollToBottomButton : UIView {
// MARK: Interaction // MARK: Interaction
@objc private func handleTap() { @objc private func handleTap() {
delegate.handleScrollToBottomButtonTapped() delegate?.handleScrollToBottomButtonTapped()
} }
} }
protocol ScrollToBottomButtonDelegate { protocol ScrollToBottomButtonDelegate : class {
func handleScrollToBottomButtonTapped() func handleScrollToBottomButtonTapped()
} }