From 260bedcf10e7c11f76e3a7e59851e8f59b18de09 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Tue, 7 Jul 2020 23:23:39 -0400 Subject: [PATCH] Fix retain cycle between status cells and menu actions --- Tusker/Screens/Utilities/Previewing.swift | 36 +++++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Tusker/Screens/Utilities/Previewing.swift b/Tusker/Screens/Utilities/Previewing.swift index 8db90ebe..e0995512 100644 --- a/Tusker/Screens/Utilities/Previewing.swift +++ b/Tusker/Screens/Utilities/Previewing.swift @@ -10,7 +10,7 @@ import UIKit import SafariServices import Pachyderm -protocol MenuPreviewProvider { +protocol MenuPreviewProvider: class { typealias PreviewProviders = (content: UIContextMenuContentPreviewProvider, actions: () -> [UIMenuElement]) @@ -38,7 +38,8 @@ extension MenuPreviewProvider { let account = mastodonController.persistentContainer.account(for: accountID) else { return [] } var actionsSection: [UIMenuElement] = [ - createAction(identifier: "sendmessage", title: "Send Message", systemImageName: "envelope", handler: { (_) in + createAction(identifier: "sendmessage", title: "Send Message", systemImageName: "envelope", handler: { [weak self] (_) in + guard let self = self else { return } self.navigationDelegate?.compose(mentioning: account.acct) }), ] @@ -53,13 +54,14 @@ extension MenuPreviewProvider { return } let request = Client.getRelationships(accounts: [account.id]) - mastodonController.run(request) { (response) in - if case let .success(results, _) = response, + mastodonController.run(request) { [weak self] (response) in + if let self = self, + case let .success(results, _) = response, let relationship = results.first { let following = relationship.following DispatchQueue.main.async { elementHandler([ - createAction(identifier: "follow", title: following ? "Unfollow" : "Follow", systemImageName: following ? "person.badge.minus" : "person.badge.minus", handler: { (_) in + self.createAction(identifier: "follow", title: following ? "Unfollow" : "Follow", systemImageName: following ? "person.badge.minus" : "person.badge.minus", handler: { (_) in let request = (following ? Account.unfollow : Account.follow)(accountID) mastodonController.run(request) { (_) in } @@ -74,7 +76,8 @@ extension MenuPreviewProvider { let shareSection = [ openInSafariAction(url: account.url), - createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { (_) in + createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in + guard let self = self else { return } self.navigationDelegate?.showMoreOptions(forAccount: accountID, sourceView: sourceView) }) ] @@ -88,7 +91,8 @@ extension MenuPreviewProvider { func actionsForURL(_ url: URL, sourceView: UIView?) -> [UIAction] { return [ openInSafariAction(url: url), - createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { (_) in + createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in + guard let self = self else { return } self.navigationDelegate?.showMoreOptions(forURL: url, sourceView: sourceView) }) ] @@ -123,10 +127,12 @@ extension MenuPreviewProvider { let muted = status.muted var actionsSection = [ - createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { (_) in + createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { [weak self] (_) in + guard let self = self else { return } self.navigationDelegate?.reply(to: statusID) }), - createAction(identifier: "bookmark", title: bookmarked ? "Unbookmark" : "Bookmark", systemImageName: bookmarked ? "bookmark.fill" : "bookmark", handler: { (_) in + createAction(identifier: "bookmark", title: bookmarked ? "Unbookmark" : "Bookmark", systemImageName: bookmarked ? "bookmark.fill" : "bookmark", handler: { [weak self] (_) in + guard let self = self else { return } let request = (bookmarked ? Status.unbookmark : Status.bookmark)(statusID) self.mastodonController?.run(request) { (response) in if case let .success(status, _) = response { @@ -134,7 +140,8 @@ extension MenuPreviewProvider { } } }), - createAction(identifier: "mute", title: muted ? "Unmute" : "Mute", systemImageName: muted ? "speaker" : "speaker.slash", handler: { (_) in + createAction(identifier: "mute", title: muted ? "Unmute" : "Mute", systemImageName: muted ? "speaker" : "speaker.slash", handler: { [weak self] (_) in + guard let self = self else { return } let request = (muted ? Status.unmuteConversation : Status.muteConversation)(statusID) self.mastodonController?.run(request) { (response) in if case let .success(status, _) = response { @@ -146,9 +153,11 @@ extension MenuPreviewProvider { if mastodonController.account != nil && mastodonController.account.id == status.account.id { let pinned = status.pinned ?? false - actionsSection.append(createAction(identifier: "", title: pinned ? "Unpin" : "Pin", systemImageName: pinned ? "pin.slash" : "pin", handler: { (_) in + actionsSection.append(createAction(identifier: "", title: pinned ? "Unpin" : "Pin", systemImageName: pinned ? "pin.slash" : "pin", handler: { [weak self] (_) in + guard let self = self else { return } let request = (pinned ? Status.unpin : Status.pin)(statusID) - self.mastodonController?.run(request, completion: { (response) in + self.mastodonController?.run(request, completion: { [weak self] (response) in + guard let self = self else { return } if case let .success(status, _) = response { self.mastodonController?.persistentContainer.addOrUpdate(status: status, incrementReferenceCount: false) } @@ -158,7 +167,8 @@ extension MenuPreviewProvider { let shareSection = [ openInSafariAction(url: status.url!), - createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { (_) in + createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in + guard let self = self else { return } self.navigationDelegate?.showMoreOptions(forStatus: statusID, sourceView: sourceView) }), ]