diff options
author | NicoleYarroch <nicole@livio.io> | 2020-06-18 10:24:40 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-18 10:24:40 -0400 |
commit | f0c104cf3cef6d8f5458d7723197dcd02ae90f1d (patch) | |
tree | a65832d5c5c7cfe260e28ab1de3ea10413cc782c | |
parent | 5b5939a2b5c72176220e09d4243354e617efcab0 (diff) | |
parent | 6cf7b442e12234d3c85e963b2b993e1f94c1eb56 (diff) | |
download | sdl_ios-f0c104cf3cef6d8f5458d7723197dcd02ae90f1d.tar.gz |
Merge pull request #1686 from smartdevicelink/bugfix/issue_1629_lockscreen_deadlock
Fixed lockscreen deadlock
-rw-r--r-- | SmartDeviceLink/SDLLockScreenManager.m | 26 | ||||
-rw-r--r-- | SmartDeviceLink/SDLLockScreenPresenter.m | 18 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingVideoLifecycleManager.m | 12 | ||||
-rw-r--r-- | SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m | 124 |
4 files changed, 80 insertions, 100 deletions
diff --git a/SmartDeviceLink/SDLLockScreenManager.m b/SmartDeviceLink/SDLLockScreenManager.m index e1b02b8cd..1d4bc9e4a 100644 --- a/SmartDeviceLink/SDLLockScreenManager.m +++ b/SmartDeviceLink/SDLLockScreenManager.m @@ -69,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN self.canPresent = NO; __weak typeof(self) weakSelf = self; - [self sdl_runOnMainQueue:^{ + dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(weakSelf) strongSelf = weakSelf; if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive) { @@ -86,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN } else { [strongSelf sdl_start]; } - }]; + }); } - (void)sdl_start { @@ -159,7 +159,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)sdl_appDidBecomeActive:(NSNotification *)notification { __weak typeof(self) weakSelf = self; - [self sdl_runOnMainQueue:^{ + dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(weakSelf) strongSelf = weakSelf; // Restart, and potentially dismiss the lock screen if the app was disconnected in the background if (!strongSelf.canPresent) { @@ -167,7 +167,7 @@ NS_ASSUME_NONNULL_BEGIN } [strongSelf sdl_checkLockScreen]; - }]; + }); } - (void)sdl_driverDistractionStateDidChange:(SDLRPCNotificationNotification *)notification { @@ -187,9 +187,9 @@ NS_ASSUME_NONNULL_BEGIN } __weak typeof(self) weakSelf = self; - [self sdl_runOnMainQueue:^{ + dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf sdl_updatePresentation]; - }]; + }); } - (void)sdl_updatePresentation { @@ -248,7 +248,7 @@ NS_ASSUME_NONNULL_BEGIN } __weak typeof(self) weakSelf = self; - [self sdl_runOnMainQueue:^{ + dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(self) strongSelf = weakSelf; SDLLockScreenViewController *lockscreenViewController = (SDLLockScreenViewController *)strongSelf.lockScreenViewController; if (enabled) { @@ -261,17 +261,7 @@ NS_ASSUME_NONNULL_BEGIN [lockscreenViewController removeDismissGesture]; lockscreenViewController.lockedLabelText = nil; } - }]; -} - -#pragma mark - Threading Utilities - -- (void)sdl_runOnMainQueue:(void (^)(void))block { - if ([NSThread isMainThread]) { - block(); - } else { - dispatch_sync(dispatch_get_main_queue(), block); - } + }); } @end diff --git a/SmartDeviceLink/SDLLockScreenPresenter.m b/SmartDeviceLink/SDLLockScreenPresenter.m index 05fae4d6c..03bca9e0a 100644 --- a/SmartDeviceLink/SDLLockScreenPresenter.m +++ b/SmartDeviceLink/SDLLockScreenPresenter.m @@ -110,7 +110,7 @@ NS_ASSUME_NONNULL_BEGIN } __weak typeof(self) weakself = self; - [self sdl_runOnMainQueue:^{ + dispatch_async(dispatch_get_main_queue(), ^{ __typeof(weakself) strongself = weakself; if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive) { // If the the `UIWindow` is created while the app is backgrounded and the app is using `SceneDelegate` class (iOS 13+), then the window will not be created correctly. Wait until the app is foregrounded before creating the window. @@ -146,7 +146,7 @@ NS_ASSUME_NONNULL_BEGIN if (completionHandler == nil) { return; } return completionHandler(); }]; - }]; + }); } @@ -162,14 +162,14 @@ NS_ASSUME_NONNULL_BEGIN } __weak typeof(self) weakSelf = self; - [self sdl_runOnMainQueue:^{ + dispatch_async(dispatch_get_main_queue(), ^{ if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive) { SDLLogV(@"Application is backgrounded. The lockscreen will not be dismissed until the app is brought to the foreground."); if (completionHandler == nil) { return; } return completionHandler(NO); } [weakSelf sdl_dismissLockscreenWithCompletionHandler:completionHandler]; - }]; + }); } /// Handles the dismissal of the lockscreen with animation. @@ -208,16 +208,6 @@ NS_ASSUME_NONNULL_BEGIN }]; } -#pragma mark - Threading Utilities - -- (void)sdl_runOnMainQueue:(void (^)(void))block { - if ([NSThread isMainThread]) { - block(); - } else { - dispatch_sync(dispatch_get_main_queue(), block); - } -} - #pragma mark - Custom Presented / Dismissed Getters /// Returns whether or not the lockViewController is currently presented or currently animating the presentation of the lockscreen diff --git a/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m index ddee38a90..168ddf3e3 100644 --- a/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m @@ -474,16 +474,18 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } if (self.useDisplayLink) { + __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ - NSInteger targetFramerate = ((NSNumber *)self.videoEncoderSettings[(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate]).integerValue; + __strong typeof(weakSelf) strongSelf = weakSelf; + NSInteger targetFramerate = ((NSNumber *)strongSelf.videoEncoderSettings[(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate]).integerValue; SDLLogD(@"Initializing CADisplayLink with framerate: %ld", (long)targetFramerate); - self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(sdl_displayLinkFired:)]; + strongSelf.displayLink = [CADisplayLink displayLinkWithTarget:strongSelf selector:@selector(sdl_displayLinkFired:)]; if (@available(iOS 10, *)) { - self.displayLink.preferredFramesPerSecond = targetFramerate; + strongSelf.displayLink.preferredFramesPerSecond = targetFramerate; } else { - self.displayLink.frameInterval = (60 / targetFramerate); + strongSelf.displayLink.frameInterval = (60 / targetFramerate); } - [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; + [strongSelf.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; }); } else { self.touchManager.enableSyncedPanning = NO; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m index c45340c75..0c5078028 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m @@ -34,21 +34,21 @@ QuickSpecBegin(SDLLockScreenManagerSpec) describe(@"a lock screen manager", ^{ __block SDLLockScreenManager *testManager = nil; - __block SDLFakeViewControllerPresenter *fakePresenter = nil; + __block SDLFakeViewControllerPresenter *fakeViewControllerPresenter = nil; __block SDLNotificationDispatcher *testNotificationDispatcher = nil; beforeEach(^{ - fakePresenter = [[SDLFakeViewControllerPresenter alloc] init]; + fakeViewControllerPresenter = [[SDLFakeViewControllerPresenter alloc] init]; }); context(@"with a disabled configuration", ^{ beforeEach(^{ - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration disabledConfiguration] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration disabledConfiguration] notificationDispatcher:nil presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ // Note: We can't check the "lockScreenPresented" flag on the Lock Screen Manager because it's a computer property checking the window - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -58,7 +58,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should not have a lock screen controller", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -75,7 +75,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should not have presented the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); }); }); }); @@ -83,11 +83,11 @@ describe(@"a lock screen manager", ^{ context(@"with an enabled configuration", ^{ beforeEach(^{ - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfiguration] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfiguration] notificationDispatcher:nil presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -97,7 +97,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should set up the view controller correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).toNot(beNil()); expect(testManager.lockScreenViewController).to(beAnInstanceOf([SDLLockScreenViewController class])); }); @@ -120,27 +120,13 @@ describe(@"a lock screen manager", ^{ }); it(@"should have presented the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beTrue()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beTrue()); }); it(@"should not have a vehicle icon", ^{ expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).to(beNil()); }); - - describe(@"when a vehicle icon is received", ^{ - __block UIImage *testIcon = nil; - - beforeEach(^{ - testIcon = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; - }); - - it(@"should have a vehicle icon", ^{ - expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).toNot(beNil()); - expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).to(equal(testIcon)); - }); - }); - + describe(@"when a driver distraction notification is posted with lockScreenDismissableEnabled as true", ^{ __block SDLRPCNotificationNotification *testDriverDistractionNotification = nil; @@ -199,7 +185,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should have dismissed the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); }); }); @@ -217,35 +203,51 @@ describe(@"a lock screen manager", ^{ }); it(@"should have dismissed the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); }); }); }); }); }); - context(@"with showDeviceLogo as NO", ^{ + context(@"when a vehicle icon is received", ^{ + __block UIImage *testIcon = nil; + SDLLockScreenConfiguration *testsConfig = [SDLLockScreenConfiguration enabledConfiguration]; + beforeEach(^{ - SDLLockScreenConfiguration *config = [SDLLockScreenConfiguration enabledConfiguration]; - config.showDeviceLogo = NO; + testIcon = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; + }); - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakePresenter]; - [testManager start]; + it(@"should should set the vehicle icon on the default lockscreen if showDeviceLogo set to true", ^{ + testsConfig.showDeviceLogo = YES; + fakeViewControllerPresenter.lockViewController = [[SDLLockScreenViewController alloc] init]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testsConfig notificationDispatcher:nil presenter:fakeViewControllerPresenter]; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; + + expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).toEventually(equal(testIcon)); }); - describe(@"when a vehicle icon is received", ^{ - __block UIImage *testIcon = nil; + it(@"should should not set the vehicle icon on the default lockscreen if showDeviceLogo set to false", ^{ + testsConfig.showDeviceLogo = NO; + fakeViewControllerPresenter.lockViewController = [[SDLLockScreenViewController alloc] init]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testsConfig notificationDispatcher:nil presenter:fakeViewControllerPresenter]; - beforeEach(^{ - testIcon = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; - }); + [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; - it(@"should not have a vehicle icon if showDeviceLogo is set to NO", ^{ - expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).to(beNil()); - }); + expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).toEventually(beNil()); }); + it(@"should should not modify a custom lockscreen", ^{ + testsConfig.showDeviceLogo = YES; + UIViewController *customLockScreen = [[UIViewController alloc] init]; + fakeViewControllerPresenter.lockViewController = customLockScreen; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testsConfig notificationDispatcher:nil presenter:fakeViewControllerPresenter]; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; + + expect(fakeViewControllerPresenter.lockViewController).toEventually(equal(customLockScreen)); + }); }); context(@"with a custom color configuration", ^{ @@ -256,11 +258,11 @@ describe(@"a lock screen manager", ^{ testColor = [UIColor blueColor]; testImage = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithAppIcon:testImage backgroundColor:testColor] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithAppIcon:testImage backgroundColor:testColor] notificationDispatcher:nil presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -270,7 +272,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should set up the view controller correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).toNot(beNil()); expect(testManager.lockScreenViewController).to(beAnInstanceOf([SDLLockScreenViewController class])); expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).backgroundColor).to(equal(testColor)); @@ -284,11 +286,11 @@ describe(@"a lock screen manager", ^{ beforeEach(^{ testViewController = [[UIViewController alloc] init]; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithViewController:testViewController] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithViewController:testViewController] notificationDispatcher:nil presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -298,7 +300,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should set up the view controller correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).toNot(beNil()); expect(testManager.lockScreenViewController).toNot(beAnInstanceOf([SDLLockScreenViewController class])); expect(testManager.lockScreenViewController).to(equal(testViewController)); @@ -311,7 +313,7 @@ describe(@"a lock screen manager", ^{ SDLLockScreenConfiguration *config = [SDLLockScreenConfiguration enabledConfiguration]; config.enableDismissGesture = NO; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakeViewControllerPresenter]; [testManager start]; }); @@ -341,7 +343,7 @@ describe(@"a lock screen manager", ^{ }); describe(@"with an always enabled configuration", ^{ - __block SDLFakeViewControllerPresenter *fakePresenter = nil; + __block SDLFakeViewControllerPresenter *fakeViewControllerPresenter = nil; __block SDLRPCNotificationNotification *testLockStatusNotification = nil; #pragma clang diagnostic push @@ -350,7 +352,7 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic pop beforeEach(^{ - fakePresenter = [[SDLFakeViewControllerPresenter alloc] init]; + fakeViewControllerPresenter = [[SDLFakeViewControllerPresenter alloc] init]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -360,7 +362,7 @@ describe(@"a lock screen manager", ^{ SDLLockScreenConfiguration *config = [SDLLockScreenConfiguration enabledConfiguration]; config.displayMode = SDLLockScreenConfigurationDisplayModeAlways; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakeViewControllerPresenter]; [testManager start]; }); @@ -376,7 +378,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should present the lock screen if not already presented", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beTrue()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beTrue()); }); }); @@ -392,7 +394,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should present the lock screen if not already presented", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beTrue()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beTrue()); }); }); }); @@ -422,18 +424,16 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic pop testLockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:testLockScreenConfig notificationDispatcher:nil presenter:mockViewControllerPresenter]; - - [testLockScreenManager start]; // Sets `canPresent` to `true` + testLockScreenManager.canPresent = YES; }); it(@"should present the lock screen if not already presented", ^{ OCMStub([mockViewControllerPresenter lockViewController]).andReturn([OCMArg any]); + OCMExpect([mockViewControllerPresenter updateLockScreenToShow:YES withCompletionHandler:nil]); [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; - // Since lock screen must be presented/dismissed on the main thread, force the test to execute manually on the main thread. If this is not done, the test case may fail. - [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; - OCMVerify([mockViewControllerPresenter updateLockScreenToShow:YES withCompletionHandler:nil]); + OCMVerifyAllWithDelay(mockViewControllerPresenter, 0.5); }); }); @@ -445,18 +445,16 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic pop testLockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:testLockScreenConfig notificationDispatcher:nil presenter:mockViewControllerPresenter]; - - [testLockScreenManager start]; // Sets `canPresent` to `true` + testLockScreenManager.canPresent = YES; }); it(@"should dismiss the lock screen if already presented", ^{ OCMStub([mockViewControllerPresenter lockViewController]).andReturn([OCMArg any]); + OCMExpect([mockViewControllerPresenter updateLockScreenToShow:NO withCompletionHandler:nil]); [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; - // Since lock screen must be presented/dismissed on the main thread, force the test to execute manually on the main thread. If this is not done, the test case may fail. - [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; - OCMVerify([mockViewControllerPresenter updateLockScreenToShow:NO withCompletionHandler:nil]); + OCMVerifyAllWithDelay(mockViewControllerPresenter, 0.5); }); }); }); |