diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index e852f7fa9..7d9fad74a 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -82,6 +82,7 @@ 34D8C0281ED3673300188D7C /* DebugUITableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D8C0261ED3673300188D7C /* DebugUITableViewController.m */; }; 34D8C02B1ED3685800188D7C /* DebugUIContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D8C02A1ED3685800188D7C /* DebugUIContacts.m */; }; 34D99C8E1F28DDCD00D284D6 /* OWSSwiftUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D99C8D1F28DDCD00D284D6 /* OWSSwiftUtils.swift */; }; + 34D99C8C1F27B13B00D284D6 /* OWSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D99C8B1F27B13B00D284D6 /* OWSViewController.m */; }; 34DFCB851E8E04B500053165 /* AddToBlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */; }; 34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E3E5671EC4B19400495BAC /* AudioProgressView.swift */; }; 34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */; }; @@ -510,6 +511,8 @@ 34D8C0291ED3685800188D7C /* DebugUIContacts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIContacts.h; sourceTree = ""; }; 34D8C02A1ED3685800188D7C /* DebugUIContacts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIContacts.m; sourceTree = ""; }; 34D99C8D1F28DDCD00D284D6 /* OWSSwiftUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSSwiftUtils.swift; sourceTree = ""; }; + 34D99C8A1F27B13B00D284D6 /* OWSViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSViewController.h; sourceTree = ""; }; + 34D99C8B1F27B13B00D284D6 /* OWSViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSViewController.m; sourceTree = ""; }; 34DFCB831E8E04B400053165 /* AddToBlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddToBlockListViewController.h; sourceTree = ""; }; 34DFCB841E8E04B500053165 /* AddToBlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddToBlockListViewController.m; sourceTree = ""; }; 34E3E5671EC4B19400495BAC /* AudioProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioProgressView.swift; sourceTree = ""; }; @@ -997,6 +1000,8 @@ 34B3F8631E8DF1700035BE1A /* OWSQRCodeScanningViewController.m */, 34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */, 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */, + 34D99C8A1F27B13B00D284D6 /* OWSViewController.h */, + 34D99C8B1F27B13B00D284D6 /* OWSViewController.m */, 34B3F8641E8DF1700035BE1A /* PrivacySettingsTableViewController.h */, 34B3F8651E8DF1700035BE1A /* PrivacySettingsTableViewController.m */, 34B3F8661E8DF1700035BE1A /* RegistrationViewController.h */, @@ -2234,6 +2239,7 @@ 45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */, 458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */, 451DE9FD1DC1A28200810E42 /* SyncPushTokensJob.swift in Sources */, + 34D99C8C1F27B13B00D284D6 /* OWSViewController.m in Sources */, 45666F761D9BFE00008FE134 /* OWS100RemoveTSRecipientsMigration.m in Sources */, 340CB2271EAC25820001CAA1 /* UpdateGroupViewController.m in Sources */, 34B3F89F1E8DF5490035BE1A /* OWSTableViewController.m in Sources */, diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index e204dbece..0a5a61e95 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -18,6 +18,7 @@ #import "OWSLogger.h" #import "OWSMessageEditing.h" #import "OWSProgressView.h" +#import "OWSViewController.h" #import "OWSWebRTCDataProtos.pb.h" #import "PrivacySettingsTableViewController.h" #import "PropertyListPreferences.h" diff --git a/Signal/src/ViewControllers/AdvancedSettingsTableViewController.m b/Signal/src/ViewControllers/AdvancedSettingsTableViewController.m index 97917c80c..19b5909da 100644 --- a/Signal/src/ViewControllers/AdvancedSettingsTableViewController.m +++ b/Signal/src/ViewControllers/AdvancedSettingsTableViewController.m @@ -98,7 +98,7 @@ NS_ASSUME_NONNULL_BEGIN [loggingSection addItem:[OWSTableItem actionItemWithText:NSLocalizedString(@"SETTINGS_ADVANCED_SUBMIT_DEBUGLOG", @"") actionBlock:^{ - DDLogInfo(@"%@ Submitting debug logs", self.tag); + DDLogInfo(@"%@ Submitting debug logs", weakSelf.tag); [DDLog flushLog]; [Pastelog submitLogs]; }]]; diff --git a/Signal/src/ViewControllers/AttachmentApprovalViewController.swift b/Signal/src/ViewControllers/AttachmentApprovalViewController.swift index eb5d6824c..20d843daf 100644 --- a/Signal/src/ViewControllers/AttachmentApprovalViewController.swift +++ b/Signal/src/ViewControllers/AttachmentApprovalViewController.swift @@ -5,7 +5,7 @@ import Foundation import MediaPlayer -class AttachmentApprovalViewController: UIViewController, OWSAudioAttachmentPlayerDelegate { +class AttachmentApprovalViewController: OWSViewController, OWSAudioAttachmentPlayerDelegate { let TAG = "[AttachmentApprovalViewController]" diff --git a/Signal/src/ViewControllers/BlockListViewController.h b/Signal/src/ViewControllers/BlockListViewController.h index 79bfd79d1..71668bbc6 100644 --- a/Signal/src/ViewControllers/BlockListViewController.h +++ b/Signal/src/ViewControllers/BlockListViewController.h @@ -2,8 +2,12 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSViewController.h" -@interface BlockListViewController : UIViewController +NS_ASSUME_NONNULL_BEGIN + +@interface BlockListViewController : OWSViewController @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/BlockListViewController.m b/Signal/src/ViewControllers/BlockListViewController.m index 527926770..72488c4ad 100644 --- a/Signal/src/ViewControllers/BlockListViewController.m +++ b/Signal/src/ViewControllers/BlockListViewController.m @@ -74,8 +74,6 @@ NS_ASSUME_NONNULL_BEGIN @"A label for the 'add phone number' button in the block list table.") actionBlock:^{ AddToBlockListViewController *vc = [[AddToBlockListViewController alloc] init]; - NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); - NSAssert(vc != nil, @"Privacy Settings View Controller must not be nil"); [weakSelf.navigationController pushViewController:vc animated:YES]; }]]; [contents addSection:addSection]; diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 640fd7408..6662291e2 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -8,7 +8,7 @@ import PromiseKit // TODO: Add category so that button handlers can be defined where button is created. // TODO: Ensure buttons enabled & disabled as necessary. -class CallViewController: UIViewController, CallObserver, CallServiceObserver, RTCEAGLVideoViewDelegate { +class CallViewController: OWSViewController, CallObserver, CallServiceObserver, RTCEAGLVideoViewDelegate { let TAG = "[CallViewController]" diff --git a/Signal/src/ViewControllers/CodeVerificationViewController.h b/Signal/src/ViewControllers/CodeVerificationViewController.h index 6d4817ee1..cccbc2bd8 100644 --- a/Signal/src/ViewControllers/CodeVerificationViewController.h +++ b/Signal/src/ViewControllers/CodeVerificationViewController.h @@ -2,10 +2,14 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSViewController.h" -@interface CodeVerificationViewController : UIViewController +NS_ASSUME_NONNULL_BEGIN + +@interface CodeVerificationViewController : OWSViewController - (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode; @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ContactsPicker.swift b/Signal/src/ViewControllers/ContactsPicker.swift index a1bdcba71..28b0e485b 100644 --- a/Signal/src/ViewControllers/ContactsPicker.swift +++ b/Signal/src/ViewControllers/ContactsPicker.swift @@ -34,7 +34,7 @@ public enum SubtitleCellValue { } @available(iOS 9.0, *) -open class ContactsPicker: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate { +open class ContactsPicker: OWSViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate { @IBOutlet var tableView: UITableView! @IBOutlet var searchBar: UISearchBar! diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 6701c5331..3ce9d8c7a 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -227,6 +227,9 @@ typedef enum : NSUInteger { - (void)dealloc { + // Surface memory leaks by logging the deallocation of view controllers. + DDLogVerbose(@"Dealloc: %@", self.class); + [[NSNotificationCenter defaultCenter] removeObserver:self]; } diff --git a/Signal/src/ViewControllers/DomainFrontingCountryViewController.h b/Signal/src/ViewControllers/DomainFrontingCountryViewController.h index c1be0ccfe..f0a3083c2 100644 --- a/Signal/src/ViewControllers/DomainFrontingCountryViewController.h +++ b/Signal/src/ViewControllers/DomainFrontingCountryViewController.h @@ -2,11 +2,11 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSViewController.h" NS_ASSUME_NONNULL_BEGIN -@interface DomainFrontingCountryViewController : UIViewController +@interface DomainFrontingCountryViewController : OWSViewController @end diff --git a/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift b/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift index a2e41dbae..b7c7d99ac 100644 --- a/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift +++ b/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift @@ -46,7 +46,7 @@ private class CallKitExperienceUpgradeViewController: ExperienceUpgradeViewContr } } -private class ExperienceUpgradeViewController: UIViewController { +private class ExperienceUpgradeViewController: OWSViewController { let TAG = "[ExperienceUpgradeViewController]" let header: String @@ -128,7 +128,7 @@ func setPageControlAppearance() { } } -class ExperienceUpgradesPageViewController: UIViewController, UIPageViewControllerDataSource { +class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControllerDataSource { let TAG = "[ExperienceUpgradeViewController]" diff --git a/Signal/src/ViewControllers/FingerprintViewController.h b/Signal/src/ViewControllers/FingerprintViewController.h index 43642b75e..c72096104 100644 --- a/Signal/src/ViewControllers/FingerprintViewController.h +++ b/Signal/src/ViewControllers/FingerprintViewController.h @@ -2,9 +2,11 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "OWSViewController.h" + NS_ASSUME_NONNULL_BEGIN -@interface FingerprintViewController : UIViewController +@interface FingerprintViewController : OWSViewController + (void)presentFromViewController:(UIViewController *)viewController recipientId:(NSString *)recipientId; diff --git a/Signal/src/ViewControllers/FingerprintViewScanController.h b/Signal/src/ViewControllers/FingerprintViewScanController.h index 9c5b2e9a4..c0aa9d52f 100644 --- a/Signal/src/ViewControllers/FingerprintViewScanController.h +++ b/Signal/src/ViewControllers/FingerprintViewScanController.h @@ -2,9 +2,11 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "OWSViewController.h" + NS_ASSUME_NONNULL_BEGIN -@interface FingerprintViewScanController : UIViewController +@interface FingerprintViewScanController : OWSViewController - (void)configureWithRecipientId:(NSString *)recipientId NS_SWIFT_NAME(configure(recipientId:)); diff --git a/Signal/src/ViewControllers/FullImageViewController.h b/Signal/src/ViewControllers/FullImageViewController.h index 7d7acba32..07868e4e6 100644 --- a/Signal/src/ViewControllers/FullImageViewController.h +++ b/Signal/src/ViewControllers/FullImageViewController.h @@ -2,12 +2,15 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSMessageData.h" +#import "OWSViewController.h" #import "TSAttachmentStream.h" #import "TSInteraction.h" -#import "OWSMessageData.h" +#import + +NS_ASSUME_NONNULL_BEGIN -@interface FullImageViewController : UIViewController +@interface FullImageViewController : OWSViewController - (instancetype)initWithAttachment:(TSAttachmentStream *)attachment fromRect:(CGRect)rect @@ -18,3 +21,5 @@ - (void)presentFromViewController:(UIViewController *)viewController; @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/FullImageViewController.m b/Signal/src/ViewControllers/FullImageViewController.m index 33e4e5020..8f87b34e7 100644 --- a/Signal/src/ViewControllers/FullImageViewController.m +++ b/Signal/src/ViewControllers/FullImageViewController.m @@ -12,6 +12,8 @@ #import "UIColor+OWS.h" #import "AttachmentSharing.h" +NS_ASSUME_NONNULL_BEGIN + #define kMinZoomScale 1.0f #define kMaxZoomScale 8.0f @@ -32,8 +34,7 @@ } // We only use custom actions in UIMenuController. -- (BOOL)canPerformAction:(SEL)action - withSender:(id)sender +- (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender { return NO; } @@ -459,7 +460,8 @@ #pragma mark - UIScrollViewDelegate -- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { +- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView +{ return self.imageView; } @@ -471,7 +473,8 @@ } } -- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { +- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale +{ self.scrollView.scrollEnabled = (scale > 1); self.scrollView.contentInset = [self contentInsetForScrollView:scale]; } @@ -510,3 +513,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/MessageComposeTableViewController.h b/Signal/src/ViewControllers/MessageComposeTableViewController.h index 64b76d2d3..b6a9c877c 100644 --- a/Signal/src/ViewControllers/MessageComposeTableViewController.h +++ b/Signal/src/ViewControllers/MessageComposeTableViewController.h @@ -2,9 +2,11 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "OWSViewController.h" + NS_ASSUME_NONNULL_BEGIN -@interface MessageComposeTableViewController : UIViewController +@interface MessageComposeTableViewController : OWSViewController @end diff --git a/Signal/src/ViewControllers/NewGroupViewController.h b/Signal/src/ViewControllers/NewGroupViewController.h index 0f69b5df8..9ae73fc39 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.h +++ b/Signal/src/ViewControllers/NewGroupViewController.h @@ -3,10 +3,11 @@ // #import "OWSConversationSettingsViewDelegate.h" +#import "OWSViewController.h" NS_ASSUME_NONNULL_BEGIN -@interface NewGroupViewController : UIViewController +@interface NewGroupViewController : OWSViewController @property (nonatomic, weak) id delegate; diff --git a/Signal/src/ViewControllers/NewGroupViewController.m b/Signal/src/ViewControllers/NewGroupViewController.m index 871282ddb..000d84905 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.m +++ b/Signal/src/ViewControllers/NewGroupViewController.m @@ -216,7 +216,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; [nonContactsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ NewGroupViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; SignalAccount *signalAccount = [contactsViewHelper signalAccountForRecipientId:recipientId]; @@ -309,7 +309,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; [signalAccountSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ NewGroupViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; diff --git a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m index 8ea19b0f8..c3685bee1 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m @@ -271,9 +271,11 @@ NS_ASSUME_NONNULL_BEGIN iconName:@"table_ic_add_to_existing_contact"]; } actionBlock:^{ - TSContactThread *contactThread = (TSContactThread *)self.thread; + OWSConversationSettingsTableViewController *strongSelf = weakSelf; + OWSCAssert(strongSelf); + TSContactThread *contactThread = (TSContactThread *)strongSelf.thread; NSString *recipientId = contactThread.contactIdentifier; - [weakSelf presentAddToContactViewControllerWithRecipientId:recipientId]; + [strongSelf presentAddToContactViewControllerWithRecipientId:recipientId]; }]]; } @@ -293,6 +295,8 @@ NS_ASSUME_NONNULL_BEGIN [mainSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ UITableViewCell *cell = [UITableViewCell new]; + OWSConversationSettingsTableViewController *strongSelf = weakSelf; + OWSCAssert(strongSelf); cell.preservesSuperviewLayoutMargins = YES; cell.contentView.preservesSuperviewLayoutMargins = YES; cell.selectionStyle = UITableViewCellSelectionStyleNone; @@ -303,7 +307,7 @@ NS_ASSUME_NONNULL_BEGIN [topView autoPinEdgeToSuperviewEdge:ALEdgeTop]; [topView autoSetDimension:ALDimensionHeight toSize:kOWSTable_DefaultCellHeight]; - UIImageView *iconView = [self viewForIconWithName:@"table_ic_hourglass"]; + UIImageView *iconView = [strongSelf viewForIconWithName:@"table_ic_hourglass"]; [topView addSubview:iconView]; [iconView autoVCenterInSuperview]; [iconView autoPinLeadingToSuperView]; @@ -318,8 +322,8 @@ NS_ASSUME_NONNULL_BEGIN [rowLabel autoPinLeadingToTrailingOfView:iconView margin:weakSelf.iconSpacing]; UISwitch *switchView = [UISwitch new]; - switchView.on = self.disappearingMessagesConfiguration.isEnabled; - [switchView addTarget:self + switchView.on = strongSelf.disappearingMessagesConfiguration.isEnabled; + [switchView addTarget:strongSelf action:@selector(disappearingMessagesSwitchValueDidChange:) forControlEvents:UIControlEventValueChanged]; [topView addSubview:switchView]; @@ -350,6 +354,8 @@ NS_ASSUME_NONNULL_BEGIN addItem:[OWSTableItem itemWithCustomCellBlock:^{ UITableViewCell *cell = [UITableViewCell new]; + OWSConversationSettingsTableViewController *strongSelf = weakSelf; + OWSCAssert(strongSelf); cell.preservesSuperviewLayoutMargins = YES; cell.contentView.preservesSuperviewLayoutMargins = YES; cell.selectionStyle = UITableViewCellSelectionStyleNone; @@ -360,13 +366,13 @@ NS_ASSUME_NONNULL_BEGIN [topView autoPinEdgeToSuperviewEdge:ALEdgeTop]; [topView autoSetDimension:ALDimensionHeight toSize:kOWSTable_DefaultCellHeight]; - UIImageView *iconView = [self viewForIconWithName:@"table_ic_hourglass"]; + UIImageView *iconView = [strongSelf viewForIconWithName:@"table_ic_hourglass"]; [topView addSubview:iconView]; [iconView autoVCenterInSuperview]; [iconView autoPinLeadingToSuperView]; - UILabel *rowLabel = self.disappearingMessagesDurationLabel; - [self updateDisappearingMessagesDurationLabel]; + UILabel *rowLabel = strongSelf.disappearingMessagesDurationLabel; + [strongSelf updateDisappearingMessagesDurationLabel]; rowLabel.textColor = [UIColor blackColor]; rowLabel.font = [UIFont ows_footnoteFont]; rowLabel.lineBreakMode = NSLineBreakByTruncatingTail; @@ -375,11 +381,11 @@ NS_ASSUME_NONNULL_BEGIN [rowLabel autoPinLeadingToTrailingOfView:iconView margin:weakSelf.iconSpacing]; UISlider *slider = [UISlider new]; - slider.maximumValue = (float)(self.disappearingMessagesDurations.count - 1); + slider.maximumValue = (float)(strongSelf.disappearingMessagesDurations.count - 1); slider.minimumValue = 0; slider.continuous = YES; // NO fires change event only once you let go - slider.value = self.disappearingMessagesConfiguration.durationIndex; - [slider addTarget:self + slider.value = strongSelf.disappearingMessagesConfiguration.durationIndex; + [slider addTarget:strongSelf action:@selector(durationSliderDidChange:) forControlEvents:UIControlEventValueChanged]; [cell.contentView addSubview:slider]; @@ -436,11 +442,13 @@ NS_ASSUME_NONNULL_BEGIN OWSTableSection *muteSection = [OWSTableSection new]; [muteSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil]; + OWSConversationSettingsTableViewController *strongSelf = weakSelf; + OWSCAssert(strongSelf); cell.preservesSuperviewLayoutMargins = YES; cell.contentView.preservesSuperviewLayoutMargins = YES; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - UIImageView *iconView = [self viewForIconWithName:@"table_ic_mute_thread"]; + UIImageView *iconView = [strongSelf viewForIconWithName:@"table_ic_mute_thread"]; [cell.contentView addSubview:iconView]; [iconView autoVCenterInSuperview]; [iconView autoPinLeadingToSuperView]; @@ -457,7 +465,7 @@ NS_ASSUME_NONNULL_BEGIN NSString *muteStatus = NSLocalizedString( @"CONVERSATION_SETTINGS_MUTE_NOT_MUTED", @"Indicates that the current thread is not muted."); - NSDate *mutedUntilDate = self.thread.mutedUntilDate; + NSDate *mutedUntilDate = strongSelf.thread.mutedUntilDate; NSDate *now = [NSDate date]; if (mutedUntilDate != nil && [mutedUntilDate timeIntervalSinceDate:now] > 0) { NSCalendar *calendar = [NSCalendar currentCalendar]; @@ -506,11 +514,13 @@ NS_ASSUME_NONNULL_BEGIN [weakSelf disclosureCellWithName:NSLocalizedString(@"CONVERSATION_SETTINGS_BLOCK_THIS_USER", @"table cell label in conversation settings") iconName:@"table_ic_block"]; + OWSConversationSettingsTableViewController *strongSelf = weakSelf; + OWSCAssert(strongSelf); cell.selectionStyle = UITableViewCellSelectionStyleNone; UISwitch *blockUserSwitch = [UISwitch new]; blockUserSwitch.on = isBlocked; - [blockUserSwitch addTarget:self + [blockUserSwitch addTarget:strongSelf action:@selector(blockUserSwitchDidChange:) forControlEvents:UIControlEventValueChanged]; cell.accessoryView = blockUserSwitch; @@ -521,7 +531,6 @@ NS_ASSUME_NONNULL_BEGIN } self.contents = contents; - [self.tableView reloadData]; } - (CGFloat)iconSpacing @@ -892,7 +901,7 @@ NS_ASSUME_NONNULL_BEGIN { self.disappearingMessagesConfiguration.enabled = flag; - [self.tableView reloadData]; + [self updateTableContents]; } - (void)durationSliderDidChange:(UISlider *)slider @@ -1045,7 +1054,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)setThreadMutedUntilDate:(nullable NSDate *)value { [self.thread updateWithMutedUntilDate:value]; - [self.tableView reloadData]; + [self updateTableContents]; } #pragma mark - Notifications diff --git a/Signal/src/ViewControllers/OWSLinkDeviceViewController.h b/Signal/src/ViewControllers/OWSLinkDeviceViewController.h index 8a8f95cae..6529564b0 100644 --- a/Signal/src/ViewControllers/OWSLinkDeviceViewController.h +++ b/Signal/src/ViewControllers/OWSLinkDeviceViewController.h @@ -1,13 +1,20 @@ -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "OWSQRCodeScanningViewController.h" +#import "OWSViewController.h" + +NS_ASSUME_NONNULL_BEGIN @class OWSLinkedDevicesTableViewController; -@interface OWSLinkDeviceViewController : UIViewController +@interface OWSLinkDeviceViewController : OWSViewController @property OWSLinkedDevicesTableViewController *linkedDevicesTableViewController; - (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithString:(NSString *)string; @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSQRCodeScanningViewController.h b/Signal/src/ViewControllers/OWSQRCodeScanningViewController.h index 533badb11..33bfe3d49 100644 --- a/Signal/src/ViewControllers/OWSQRCodeScanningViewController.h +++ b/Signal/src/ViewControllers/OWSQRCodeScanningViewController.h @@ -2,10 +2,13 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "OWSViewController.h" #import #import #import +NS_ASSUME_NONNULL_BEGIN + @class OWSQRCodeScanningViewController; @protocol OWSQRScannerDelegate @@ -20,10 +23,12 @@ #pragma mark - @interface OWSQRCodeScanningViewController - : UIViewController + : OWSViewController @property (nonatomic, weak) UIViewController *scanDelegate; - (void)startCapture; @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSQRCodeScanningViewController.m b/Signal/src/ViewControllers/OWSQRCodeScanningViewController.m index 25bc74cfa..9a2fd103d 100644 --- a/Signal/src/ViewControllers/OWSQRCodeScanningViewController.m +++ b/Signal/src/ViewControllers/OWSQRCodeScanningViewController.m @@ -7,6 +7,8 @@ #import "UIColor+OWS.h" #import "UIView+OWS.h" +NS_ASSUME_NONNULL_BEGIN + @interface OWSQRCodeScanningViewController () @property (atomic) ZXCapture *capture; @@ -36,7 +38,7 @@ return self; } -- (instancetype)initWithCoder:(NSCoder *)aDecoder +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (!self) { @@ -159,3 +161,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSTableViewController.h b/Signal/src/ViewControllers/OWSTableViewController.h index 1680d46c7..d3fd989a5 100644 --- a/Signal/src/ViewControllers/OWSTableViewController.h +++ b/Signal/src/ViewControllers/OWSTableViewController.h @@ -2,7 +2,7 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSViewController.h" NS_ASSUME_NONNULL_BEGIN @@ -103,7 +103,7 @@ typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(); #pragma mark - -@interface OWSTableViewController : UIViewController +@interface OWSTableViewController : OWSViewController @property (nonatomic, weak) id delegate; diff --git a/Signal/src/ViewControllers/OWSTableViewController.m b/Signal/src/ViewControllers/OWSTableViewController.m index 7091a8abc..a68de2c9d 100644 --- a/Signal/src/ViewControllers/OWSTableViewController.m +++ b/Signal/src/ViewControllers/OWSTableViewController.m @@ -282,10 +282,12 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; selector:(SEL)selector { OWSAssert(text.length > 0); + OWSAssert(target); OWSAssert(selector); OWSTableItem *item = [OWSTableItem new]; item.itemType = OWSTableItemTypeAction; + __weak id weakTarget = target; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = text; @@ -295,7 +297,7 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; UISwitch *cellSwitch = [UISwitch new]; cell.accessoryView = cellSwitch; [cellSwitch setOn:isOn]; - [cellSwitch addTarget:target action:selector forControlEvents:UIControlEventValueChanged]; + [cellSwitch addTarget:weakTarget action:selector forControlEvents:UIControlEventValueChanged]; cellSwitch.enabled = isEnabled; cell.selectionStyle = UITableViewCellSelectionStyleNone; diff --git a/Signal/src/ViewControllers/OWSViewController.h b/Signal/src/ViewControllers/OWSViewController.h new file mode 100644 index 000000000..465326a02 --- /dev/null +++ b/Signal/src/ViewControllers/OWSViewController.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OWSViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSViewController.m b/Signal/src/ViewControllers/OWSViewController.m new file mode 100644 index 000000000..cb177701c --- /dev/null +++ b/Signal/src/ViewControllers/OWSViewController.m @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "OWSViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation OWSViewController + +- (void)dealloc +{ + // Surface memory leaks by logging the deallocation of view controllers. + DDLogVerbose(@"Dealloc: %@", self.class); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OversizeTextMessageViewController.swift b/Signal/src/ViewControllers/OversizeTextMessageViewController.swift index 949242f9e..dd4202543 100644 --- a/Signal/src/ViewControllers/OversizeTextMessageViewController.swift +++ b/Signal/src/ViewControllers/OversizeTextMessageViewController.swift @@ -6,7 +6,7 @@ import Foundation import WebRTC import PromiseKit -class OversizeTextMessageViewController: UIViewController { +class OversizeTextMessageViewController: OWSViewController { let TAG = "[OversizeTextMessageViewController]" diff --git a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m b/Signal/src/ViewControllers/PrivacySettingsTableViewController.m index 66e7e6b14..d1b8e1836 100644 --- a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m +++ b/Signal/src/ViewControllers/PrivacySettingsTableViewController.m @@ -96,7 +96,6 @@ NS_ASSUME_NONNULL_BEGIN }]]; [contents addSection:historyLogsSection]; - self.contents = contents; } diff --git a/Signal/src/ViewControllers/RegistrationViewController.h b/Signal/src/ViewControllers/RegistrationViewController.h index 2c6bf9fdb..0f2d68ddb 100644 --- a/Signal/src/ViewControllers/RegistrationViewController.h +++ b/Signal/src/ViewControllers/RegistrationViewController.h @@ -2,11 +2,11 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSViewController.h" NS_ASSUME_NONNULL_BEGIN -@interface RegistrationViewController : UIViewController +@interface RegistrationViewController : OWSViewController @end diff --git a/Signal/src/ViewControllers/SelectRecipientViewController.h b/Signal/src/ViewControllers/SelectRecipientViewController.h index 4d43b62e7..319be0b5e 100644 --- a/Signal/src/ViewControllers/SelectRecipientViewController.h +++ b/Signal/src/ViewControllers/SelectRecipientViewController.h @@ -2,7 +2,7 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import +#import "OWSViewController.h" NS_ASSUME_NONNULL_BEGIN @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN @class ContactsViewHelper; -@interface SelectRecipientViewController : UIViewController +@interface SelectRecipientViewController : OWSViewController @property (nonatomic, weak) id delegate; diff --git a/Signal/src/ViewControllers/SelectRecipientViewController.m b/Signal/src/ViewControllers/SelectRecipientViewController.m index 572f7c2ab..0f43a5937 100644 --- a/Signal/src/ViewControllers/SelectRecipientViewController.m +++ b/Signal/src/ViewControllers/SelectRecipientViewController.m @@ -446,7 +446,6 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien - (void)updateTableContents { OWSTableContents *contents = [OWSTableContents new]; - __weak SelectRecipientViewController *weakSelf = self; ContactsViewHelper *helper = self.contactsViewHelper; @@ -458,57 +457,59 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien const CGFloat kButtonRowHeight = 60; [phoneNumberSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectRecipientViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); UITableViewCell *cell = [UITableViewCell new]; cell.preservesSuperviewLayoutMargins = YES; cell.contentView.preservesSuperviewLayoutMargins = YES; // Country Row - UIView *countryRow = [self createRowWithHeight:kCountryRowHeight previousRow:nil superview:cell.contentView]; - [countryRow addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self + UIView *countryRow = + [strongSelf createRowWithHeight:kCountryRowHeight previousRow:nil superview:cell.contentView]; + [countryRow addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:strongSelf action:@selector(countryRowTouched:)]]; - UILabel *countryCodeLabel = self.countryCodeLabel; + UILabel *countryCodeLabel = strongSelf.countryCodeLabel; [countryRow addSubview:countryCodeLabel]; [countryCodeLabel autoPinLeadingToSuperView]; [countryCodeLabel autoVCenterInSuperview]; - [countryRow addSubview:self.countryCodeButton]; - [self.countryCodeButton autoPinTrailingToSuperView]; - [self.countryCodeButton autoVCenterInSuperview]; + [countryRow addSubview:strongSelf.countryCodeButton]; + [strongSelf.countryCodeButton autoPinTrailingToSuperView]; + [strongSelf.countryCodeButton autoVCenterInSuperview]; // Phone Number Row UIView *phoneNumberRow = - [self createRowWithHeight:kPhoneNumberRowHeight previousRow:countryRow superview:cell.contentView]; + [strongSelf createRowWithHeight:kPhoneNumberRowHeight previousRow:countryRow superview:cell.contentView]; [phoneNumberRow - addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self + addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:strongSelf action:@selector(phoneNumberRowTouched:)]]; - UILabel *phoneNumberLabel = self.phoneNumberLabel; + UILabel *phoneNumberLabel = strongSelf.phoneNumberLabel; [phoneNumberRow addSubview:phoneNumberLabel]; [phoneNumberLabel autoPinLeadingToSuperView]; [phoneNumberLabel autoVCenterInSuperview]; - [phoneNumberRow addSubview:self.phoneNumberTextField]; - [self.phoneNumberTextField autoPinLeadingToTrailingOfView:phoneNumberLabel margin:10.f]; - [self.phoneNumberTextField autoPinTrailingToSuperView]; - [self.phoneNumberTextField autoVCenterInSuperview]; + [phoneNumberRow addSubview:strongSelf.phoneNumberTextField]; + [strongSelf.phoneNumberTextField autoPinLeadingToTrailingOfView:phoneNumberLabel margin:10.f]; + [strongSelf.phoneNumberTextField autoPinTrailingToSuperView]; + [strongSelf.phoneNumberTextField autoVCenterInSuperview]; // Example row. - UIView *examplePhoneNumberRow = [self createRowWithHeight:examplePhoneNumberRowHeight - previousRow:phoneNumberRow - superview:cell.contentView]; - [examplePhoneNumberRow addSubview:self.examplePhoneNumberLabel]; - [self.examplePhoneNumberLabel autoVCenterInSuperview]; - [self.examplePhoneNumberLabel autoPinTrailingToSuperView]; + UIView *examplePhoneNumberRow = [strongSelf createRowWithHeight:examplePhoneNumberRowHeight + previousRow:phoneNumberRow + superview:cell.contentView]; + [examplePhoneNumberRow addSubview:strongSelf.examplePhoneNumberLabel]; + [strongSelf.examplePhoneNumberLabel autoVCenterInSuperview]; + [strongSelf.examplePhoneNumberLabel autoPinTrailingToSuperView]; // Phone Number Button Row - UIView *buttonRow = - [self createRowWithHeight:kButtonRowHeight previousRow:examplePhoneNumberRow superview:cell.contentView]; - [buttonRow addSubview:self.phoneNumberButton]; - [self.phoneNumberButton autoVCenterInSuperview]; - [self.phoneNumberButton autoPinTrailingToSuperView]; + UIView *buttonRow = [strongSelf createRowWithHeight:kButtonRowHeight + previousRow:examplePhoneNumberRow + superview:cell.contentView]; + [buttonRow addSubview:strongSelf.phoneNumberButton]; + [strongSelf.phoneNumberButton autoVCenterInSuperview]; + [strongSelf.phoneNumberButton autoPinTrailingToSuperView]; [buttonRow autoPinEdgeToSuperviewEdge:ALEdgeBottom]; @@ -538,7 +539,7 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien for (SignalAccount *signalAccount in signalAccounts) { [contactsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectRecipientViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; BOOL isBlocked = [helper isRecipientIdBlocked:signalAccount.recipientId]; diff --git a/Signal/src/ViewControllers/SelectThreadViewController.h b/Signal/src/ViewControllers/SelectThreadViewController.h index 1ce59fde2..0cee930fd 100644 --- a/Signal/src/ViewControllers/SelectThreadViewController.h +++ b/Signal/src/ViewControllers/SelectThreadViewController.h @@ -2,6 +2,8 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "OWSViewController.h" + @class TSThread; NS_ASSUME_NONNULL_BEGIN @@ -20,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN // A base class for views used to pick a single signal user, either by // entering a phone number or picking from your contacts. -@interface SelectThreadViewController : UIViewController +@interface SelectThreadViewController : OWSViewController @property (nonatomic, weak) id delegate; diff --git a/Signal/src/ViewControllers/SelectThreadViewController.m b/Signal/src/ViewControllers/SelectThreadViewController.m index ac759faf9..268ffc1ca 100644 --- a/Signal/src/ViewControllers/SelectThreadViewController.m +++ b/Signal/src/ViewControllers/SelectThreadViewController.m @@ -136,7 +136,7 @@ NS_ASSUME_NONNULL_BEGIN for (TSThread *thread in [self filteredThreadsWithSearchText]) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectThreadViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); // To be consistent with the threads (above), we use ContactTableViewCell // instead of InboxTableViewCell to present contacts and threads. @@ -155,7 +155,7 @@ NS_ASSUME_NONNULL_BEGIN for (SignalAccount *signalAccount in filteredSignalAccounts) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ SelectThreadViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; BOOL isBlocked = [helper isRecipientIdBlocked:signalAccount.recipientId]; diff --git a/Signal/src/ViewControllers/SettingsTableViewController.m b/Signal/src/ViewControllers/SettingsTableViewController.m index cfa8f155f..113e10ee0 100644 --- a/Signal/src/ViewControllers/SettingsTableViewController.m +++ b/Signal/src/ViewControllers/SettingsTableViewController.m @@ -239,8 +239,6 @@ - (void)showPrivacy { PrivacySettingsTableViewController *vc = [[PrivacySettingsTableViewController alloc] init]; - NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); - NSAssert(vc != nil, @"Privacy Settings View Controller must not be nil"); [self.navigationController pushViewController:vc animated:YES]; } @@ -260,16 +258,12 @@ - (void)showAdvanced { AdvancedSettingsTableViewController *vc = [[AdvancedSettingsTableViewController alloc] init]; - NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); - NSAssert(vc != nil, @"Advanced Settings View Controller must not be nil"); [self.navigationController pushViewController:vc animated:YES]; } - (void)showAbout { AboutTableViewController *vc = [[AboutTableViewController alloc] init]; - NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); - NSAssert(vc != nil, @"About View Controller must not be nil"); [self.navigationController pushViewController:vc animated:YES]; } diff --git a/Signal/src/ViewControllers/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ShowGroupMembersViewController.m index 2113f26a9..605aaedba 100644 --- a/Signal/src/ViewControllers/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ShowGroupMembersViewController.m @@ -169,7 +169,7 @@ NS_ASSUME_NONNULL_BEGIN for (NSString *recipientId in [recipientIds sortedArrayUsingSelector:@selector(compare:)]) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ ShowGroupMembersViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; diff --git a/Signal/src/ViewControllers/SignalsViewController.h b/Signal/src/ViewControllers/SignalsViewController.h index bb0e050db..4ccddd75d 100644 --- a/Signal/src/ViewControllers/SignalsViewController.h +++ b/Signal/src/ViewControllers/SignalsViewController.h @@ -2,11 +2,12 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "OWSViewController.h" #import @class TSThread; -@interface SignalsViewController : UIViewController +@interface SignalsViewController : OWSViewController // TODO: Remove this property. @property (nonatomic) BOOL newlyRegisteredUser; diff --git a/Signal/src/ViewControllers/UpdateGroupViewController.h b/Signal/src/ViewControllers/UpdateGroupViewController.h index 9403cdf9b..9a9e07f76 100644 --- a/Signal/src/ViewControllers/UpdateGroupViewController.h +++ b/Signal/src/ViewControllers/UpdateGroupViewController.h @@ -3,6 +3,7 @@ // #import "OWSConversationSettingsViewDelegate.h" +#import "OWSViewController.h" NS_ASSUME_NONNULL_BEGIN @@ -14,7 +15,7 @@ typedef NS_ENUM(NSUInteger, UpdateGroupMode) { UpdateGroupMode_EditGroupAvatar, }; -@interface UpdateGroupViewController : UIViewController +@interface UpdateGroupViewController : OWSViewController @property (nonatomic, weak) id conversationSettingsViewDelegate; diff --git a/Signal/src/ViewControllers/UpdateGroupViewController.m b/Signal/src/ViewControllers/UpdateGroupViewController.m index ba200a737..22e48a76c 100644 --- a/Signal/src/ViewControllers/UpdateGroupViewController.m +++ b/Signal/src/ViewControllers/UpdateGroupViewController.m @@ -265,7 +265,7 @@ NS_ASSUME_NONNULL_BEGIN [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ UpdateGroupViewController *strongSelf = weakSelf; - OWSAssert(strongSelf); + OWSCAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; SignalAccount *signalAccount = [contactsViewHelper signalAccountForRecipientId:recipientId];