У меня есть DataModel:
Код: Выделить всё
final class DataModel: ObservableObject {
let camera = Camera()
@Published var frame: Image?
var isPhotosLoaded = false
init() {
print("DataModel init")
Task {
await handleCameraPreviews()
}
}
deinit {
print("DataModel deinit")
}
func handleCameraPreviews() async {
let imageStream = camera.previewStream
.map { $0.image }
for await image in imageStream {
Task { @MainActor in
// CIFilters to come...
frame = image
}
}
}
}
Код: Выделить всё
class Camera: NSObject {
...
deinit() {
print("Camera > deinit")
}
private var addToPreviewStream: ((CIImage) -> Void)?
lazy var previewStream: AsyncStream = {
AsyncStream { continuation in
addToPreviewStream = { ciImage in
if !self.isPreviewPaused {
continuation.yield(ciImage)
}
}
}
}()
...
}
extension Camera: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let pixelBuffer = sampleBuffer.imageBuffer else { return }
addToPreviewStream?(CIImage(cvPixelBuffer: pixelBuffer))
}
}
Каждый раз, когда я перехожу ко второму виду, я никогда не вижу «deinit», напечатанного ни из DataModel(), ни из Camera(). И когда я возвращаюсь к представлению камеры, я вижу, что DataModel() и Camera() печатают «init».
Я признаю, что очень мало понимаю в управлении памятью, но подозреваю, что существует сильный цикл сохранения.
Когда я закомментирую функцию handleCameraPreviews(), проблема исчезает. Я подозреваю, что именно отсюда происходит цикл сохранения или какая-то другая утечка, потому что оба объекта инициализируют и деинитируют, как и ожидалось.
Я попробовал обновить handleCameraPreviews(), чтобы добавить [weak self]:
Код: Выделить всё
init() {
print("DataModel init")
cameraTask = Task {
await camera.start()
}
previewTask = Task { [weak self] in
await self?.handleCameraPreviews()
}
}
func handleCameraPreviews() async {
let stream = camera.previewStream
for await frame in stream {
try Task.checkCancellation()
await MainActor.run { [weak self] in
guard let self else { return }
self.frame = frame.image
}
}
Спасибо!
Подробнее здесь: https://stackoverflow.com/questions/798 ... p-tutorial
Мобильная версия