Updated iOS image classifier and object detector callback invocations to avoid retain cycles
This commit is contained in:
parent
d9a245b80b
commit
c82a27599b
|
@ -85,22 +85,34 @@ static NSString *const kTaskGraphName =
|
||||||
|
|
||||||
if (options.imageClassifierDelegate) {
|
if (options.imageClassifierDelegate) {
|
||||||
_imageClassifierDelegate = options.imageClassifierDelegate;
|
_imageClassifierDelegate = options.imageClassifierDelegate;
|
||||||
|
|
||||||
|
// Capturing `self` as weak in order to avoid `self` being kept in memory
|
||||||
|
// and cause a retain cycle, after self is set to `nil`.
|
||||||
|
MPPImageClassifier *__weak weakSelf = self;
|
||||||
|
dispatch_queue_t callbackQueue =
|
||||||
|
dispatch_queue_create("com.mediapipe.tasks.imageClassifierCallbackQueue", NULL);
|
||||||
packetsCallback = [=](absl::StatusOr<PacketMap> status_or_packets) {
|
packetsCallback = [=](absl::StatusOr<PacketMap> status_or_packets) {
|
||||||
NSError *callbackError = nil;
|
// Check to ensure that the delegate method is not called on a nil object
|
||||||
if (![MPPCommonUtils checkCppError:status_or_packets.status() toError:&callbackError]) {
|
// leading to a segmentation fault, we check `weakSelf` is `nil` before
|
||||||
if ([_imageClassifierDelegate
|
// performing any processing.
|
||||||
|
if (!weakSelf ||
|
||||||
|
![weakSelf.imageClassifierDelegate
|
||||||
respondsToSelector:@selector
|
respondsToSelector:@selector
|
||||||
(imageClassifier:
|
(imageClassifier:
|
||||||
didFinishClassificationWithResult:timestampInMilliseconds:error:)]) {
|
didFinishClassificationWithResult:timestampInMilliseconds:error:)]) {
|
||||||
[_imageClassifierDelegate imageClassifier:self
|
|
||||||
didFinishClassificationWithResult:nil
|
|
||||||
timestampInMilliseconds:Timestamp::Unset().Value()
|
|
||||||
error:callbackError];
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketMap &outputPacketMap = status_or_packets.value();
|
NSError *callbackError = nil;
|
||||||
|
if (![MPPCommonUtils checkCppError:status_or_packets.status() toError:&callbackError]) {
|
||||||
|
[weakSelf.imageClassifierDelegate imageClassifier:weakSelf
|
||||||
|
didFinishClassificationWithResult:nil
|
||||||
|
timestampInMilliseconds:Timestamp::Unset().Value()
|
||||||
|
error:callbackError];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketMap outputPacketMap = status_or_packets.value();
|
||||||
if (outputPacketMap[kImageOutStreamName.cppString].IsEmpty()) {
|
if (outputPacketMap[kImageOutStreamName.cppString].IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -109,18 +121,14 @@ static NSString *const kTaskGraphName =
|
||||||
[MPPImageClassifierResult imageClassifierResultWithClassificationsPacket:
|
[MPPImageClassifierResult imageClassifierResultWithClassificationsPacket:
|
||||||
outputPacketMap[kClassificationsStreamName.cppString]];
|
outputPacketMap[kClassificationsStreamName.cppString]];
|
||||||
|
|
||||||
if ([_imageClassifierDelegate
|
[weakSelf.imageClassifierDelegate
|
||||||
respondsToSelector:@selector
|
imageClassifier:weakSelf
|
||||||
(imageClassifier:
|
|
||||||
didFinishClassificationWithResult:timestampInMilliseconds:error:)]) {
|
|
||||||
[_imageClassifierDelegate imageClassifier:self
|
|
||||||
didFinishClassificationWithResult:result
|
didFinishClassificationWithResult:result
|
||||||
timestampInMilliseconds:outputPacketMap[kImageOutStreamName.cppString]
|
timestampInMilliseconds:outputPacketMap[kImageOutStreamName.cppString]
|
||||||
.Timestamp()
|
.Timestamp()
|
||||||
.Value() /
|
.Value() /
|
||||||
kMicroSecondsPerMilliSecond
|
kMicroSecondsPerMilliSecond
|
||||||
error:callbackError];
|
error:callbackError];
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,17 +81,23 @@ static NSString *const kTaskGraphName = @"mediapipe.tasks.vision.ObjectDetectorG
|
||||||
|
|
||||||
if (options.objectDetectorDelegate) {
|
if (options.objectDetectorDelegate) {
|
||||||
_objectDetectorDelegate = options.objectDetectorDelegate;
|
_objectDetectorDelegate = options.objectDetectorDelegate;
|
||||||
|
|
||||||
|
// Capturing `self` as weak in order to avoid `self` being kept in memory
|
||||||
|
// and cause a retain cycle, after self is set to `nil`.
|
||||||
|
MPPObjectDetector *__weak weakSelf = self;
|
||||||
packetsCallback = [=](absl::StatusOr<PacketMap> statusOrPackets) {
|
packetsCallback = [=](absl::StatusOr<PacketMap> statusOrPackets) {
|
||||||
NSError *callbackError = nil;
|
if ([!weakSelf && weakSelf.objectDetectorDelegate
|
||||||
if (![MPPCommonUtils checkCppError:statusOrPackets.status() toError:&callbackError]) {
|
|
||||||
if ([_objectDetectorDelegate
|
|
||||||
respondsToSelector:@selector
|
respondsToSelector:@selector
|
||||||
(objectDetector:didFinishDetectionWithResult:timestampInMilliseconds:error:)]) {
|
(objectDetector:didFinishDetectionWithResult:timestampInMilliseconds:error:)]) {
|
||||||
[_objectDetectorDelegate objectDetector:self
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSError *callbackError = nil;
|
||||||
|
if (![MPPCommonUtils checkCppError:statusOrPackets.status() toError:&callbackError]) {
|
||||||
|
[_objectDetectorDelegate objectDetector:weakSelf
|
||||||
didFinishDetectionWithResult:nil
|
didFinishDetectionWithResult:nil
|
||||||
timestampInMilliseconds:Timestamp::Unset().Value()
|
timestampInMilliseconds:Timestamp::Unset().Value()
|
||||||
error:callbackError];
|
error:callbackError];
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,17 +109,15 @@ static NSString *const kTaskGraphName = @"mediapipe.tasks.vision.ObjectDetectorG
|
||||||
MPPObjectDetectionResult *result = [MPPObjectDetectionResult
|
MPPObjectDetectionResult *result = [MPPObjectDetectionResult
|
||||||
objectDetectionResultWithDetectionsPacket:statusOrPackets.value()[kDetectionsStreamName
|
objectDetectionResultWithDetectionsPacket:statusOrPackets.value()[kDetectionsStreamName
|
||||||
.cppString]];
|
.cppString]];
|
||||||
if ([_objectDetectorDelegate
|
|
||||||
respondsToSelector:@selector
|
[weakSelf.objectDetectorDelegate
|
||||||
(objectDetector:didFinishDetectionWithResult:timestampInMilliseconds:error:)]) {
|
objectDetector:weakSelf
|
||||||
[_objectDetectorDelegate objectDetector:self
|
|
||||||
didFinishDetectionWithResult:result
|
didFinishDetectionWithResult:result
|
||||||
timestampInMilliseconds:outputPacketMap[kImageOutStreamName.cppString]
|
timestampInMilliseconds:outputPacketMap[kImageOutStreamName.cppString]
|
||||||
.Timestamp()
|
.Timestamp()
|
||||||
.Value() /
|
.Value() /
|
||||||
kMicroSecondsPerMilliSecond
|
kMicroSecondsPerMilliSecond
|
||||||
error:callbackError];
|
error:callbackError];
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user