diff --git a/mediapipe/tasks/ios/test/vision/image_classifier/MPPImageClassifierTests.m b/mediapipe/tasks/ios/test/vision/image_classifier/MPPImageClassifierTests.m index c08976923..d8d05d872 100644 --- a/mediapipe/tasks/ios/test/vision/image_classifier/MPPImageClassifierTests.m +++ b/mediapipe/tasks/ios/test/vision/image_classifier/MPPImageClassifierTests.m @@ -30,10 +30,10 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks"; static NSString *const kLiveStreamTestsDictImageClassifierKey = @"image_classifier"; static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation"; -#define AssertEqualErrors(error, expectedError) \ - XCTAssertNotNil(error); \ - XCTAssertEqualObjects(error.domain, expectedError.domain); \ - XCTAssertEqual(error.code, expectedError.code); \ +#define AssertEqualErrors(error, expectedError) \ + XCTAssertNotNil(error); \ + XCTAssertEqualObjects(error.domain, expectedError.domain); \ + XCTAssertEqual(error.code, expectedError.code); \ XCTAssertEqualObjects(error.localizedDescription, expectedError.localizedDescription) #define AssertEqualCategoryArrays(categories, expectedCategories) \ @@ -439,7 +439,7 @@ static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation"; #pragma mark Running Mode Tests -- (void)testCreateImageClassifierFailsWithDelegateInNonLiveStreamMode { +- (void)testCreateImageClassifierSucceedsWithDelegateInNonLiveStreamMode { MPPRunningMode runningModesToTest[] = {MPPRunningModeImage, MPPRunningModeVideo}; for (int i = 0; i < sizeof(runningModesToTest) / sizeof(runningModesToTest[0]); i++) { MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName]; @@ -447,36 +447,20 @@ static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation"; options.runningMode = runningModesToTest[i]; options.imageClassifierLiveStreamDelegate = self; - [self - assertCreateImageClassifierWithOptions:options - failsWithExpectedError: - [NSError - errorWithDomain:kExpectedErrorDomain - code:MPPTasksErrorCodeInvalidArgumentError - userInfo:@{ - NSLocalizedDescriptionKey : - @"The vision task is in image or video mode. The " - @"delegate must not be set in the task's options." - }]]; + MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options + error:nil]; + XCTAssertNotNil(imageClassifier); } } -- (void)testCreateImageClassifierFailsWithMissingDelegateInLiveStreamMode { +- (void)testCreateImageClassifieSucceedsWithMissingDelegateInLiveStreamMode { MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName]; options.runningMode = MPPRunningModeLiveStream; - [self assertCreateImageClassifierWithOptions:options - failsWithExpectedError: - [NSError errorWithDomain:kExpectedErrorDomain - code:MPPTasksErrorCodeInvalidArgumentError - userInfo:@{ - NSLocalizedDescriptionKey : - @"The vision task is in live stream mode. An " - @"object must be set as the delegate of the task " - @"in its options to ensure asynchronous delivery " - @"of results." - }]]; + MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options + error:nil]; + XCTAssertNotNil(imageClassifier); } - (void)testClassifyFailsWithCallingWrongApiInImageMode { @@ -614,6 +598,30 @@ static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation"; } } +- (void)testClassifyFailsWithMissingDelegateInLiveStreamMode { + MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName]; + options.runningMode = MPPRunningModeLiveStream; + + MPPImageClassifier *imageClassifier = [self imageClassifierWithOptionsSucceeds:options]; + + NSError *expectedError = + [NSError errorWithDomain:kExpectedErrorDomain + code:MPPTasksErrorCodeFailedPreconditionError + userInfo:@{ + NSLocalizedDescriptionKey : + @"This method can only be called if the task is running in a stream " + @"mode and an object of a class is provided as the delegate in the " + @"task options to receive the results asynchronously." + }]; + + MPPImage *image = [self imageWithFileInfo:kBurgerImage]; + + NSError *error = nil; + XCTAssertFalse([imageClassifier classifyAsyncImage:image timestampInMilliseconds:1 error:&error]); + + AssertEqualErrors(error, expectedError); +} + - (void)testClassifyWithOutOfOrderTimestampsAndLiveStreamModeFails { MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName]; diff --git a/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifier.mm b/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifier.mm index 5d2595cd1..c886ee5ab 100644 --- a/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifier.mm +++ b/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifier.mm @@ -64,12 +64,7 @@ static const int kMicroSecondsPerMilliSecond = 1000; @implementation MPPImageClassifier - (void)processLiveStreamResult:(absl::StatusOr)liveStreamResult { - if (![self.imageClassifierLiveStreamDelegate - respondsToSelector:@selector - (imageClassifier:didFinishClassificationWithResult:timestampInMilliseconds:error:)]) { - return; - } - + NSError *callbackError = nil; if (![MPPCommonUtils checkCppError:liveStreamResult.status() toError:&callbackError]) { dispatch_async(_callbackQueue, ^{ diff --git a/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifierOptions.h b/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifierOptions.h index 058c21aed..eea6383ee 100644 --- a/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifierOptions.h +++ b/mediapipe/tasks/ios/vision/image_classifier/sources/MPPImageClassifierOptions.h @@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(ImageClassifierLiveStreamDelegate) @protocol MPPImageClassifierLiveStreamDelegate -@optional +@required /** * This method notifies a delegate that the results of asynchronous classification of * an image submitted to the `MPPImageClassifier` is available.