diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm index c6e3677b84..3b6e05dea1 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm +++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm @@ -147,7 +147,8 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2; @synchronized(self) { _delegates.erase(std::remove(_delegates.begin(), _delegates.end(), - delegate)); + delegate), + _delegates.end()); [self removeZeroedDelegates]; } } @@ -520,11 +521,11 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2; - (void)removeZeroedDelegates { @synchronized(self) { - for (auto it = _delegates.begin(); it != _delegates.end(); ++it) { - if (!*it) { - _delegates.erase(it); - } - } + _delegates.erase( + std::remove_if(_delegates.begin(), + _delegates.end(), + [](id delegate) -> bool { return delegate == nil; }), + _delegates.end()); } } diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm b/webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm index 603e450c75..7cbd2a982a 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm +++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm @@ -46,6 +46,28 @@ @end +// A delegate that adds itself to the audio session on init and removes itself +// in its dealloc. +@interface RTCTestRemoveOnDeallocDelegate : RTCAudioSessionTestDelegate +@end + +@implementation RTCTestRemoveOnDeallocDelegate + +- (instancetype)init { + if (self = [super init]) { + RTCAudioSession *session = [RTCAudioSession sharedInstance]; + [session addDelegate:self]; + } + return self; +} + +- (void)dealloc { + RTCAudioSession *session = [RTCAudioSession sharedInstance]; + [session removeDelegate:self]; +} + +@end + @interface RTCAudioSessionTest : NSObject @@ -142,6 +164,18 @@ EXPECT_TRUE(session.delegates[0]); } +// Tests that we don't crash when removing delegates in dealloc. +// Added as a regression test. +- (void)testRemoveDelegateOnDealloc { + @autoreleasepool { + RTCTestRemoveOnDeallocDelegate *delegate = + [[RTCTestRemoveOnDeallocDelegate alloc] init]; + EXPECT_TRUE(delegate); + } + RTCAudioSession *session = [RTCAudioSession sharedInstance]; + EXPECT_EQ(0u, session.delegates.size()); +} + @end namespace webrtc { @@ -176,4 +210,9 @@ TEST_F(AudioSessionTest, ZeroingWeakDelegate) { [test testZeroingWeakDelegate]; } +TEST_F(AudioSessionTest, RemoveDelegateOnDealloc) { + RTCAudioSessionTest *test = [[RTCAudioSessionTest alloc] init]; + [test testRemoveDelegateOnDealloc]; +} + } // namespace webrtc