Memleak с UIDocumentPickerViewController через SwiftUI - PullRequest
2 голосов
/ 19 июня 2020

Приложение создано для iOS. Я хочу, чтобы пользователь выбрал файл из его каталога и получил URL-адрес выбранного. Apple рекомендует UIDocumentPickerViewController для решения этой проблемы. Я обернул его в UIViewControllerRepresentable, так что это первое место, где я могу ошибиться

import SwiftUI
import MobileCoreServices

struct DocumentPickerView: UIViewControllerRepresentable {
    func makeCoordinator() -> Coordinator {
        return DocumentPickerView.Coordinator()
    }

    func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
        let picker = UIDocumentPickerViewController(documentTypes: [String(kUTTypeItem)], in: .import)
        picker.allowsMultipleSelection = false
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {
    }

    class Coordinator: NSObject, UIDocumentPickerDelegate {
        func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
            print("url: \(urls[0].absoluteString )")
        }
    }
}

struct ContentView: View {
    @State var showPicker = false

    var body: some View {
        Button(action: {
            self.showPicker.toggle()
        }, label: {
            Text("Push me")
        })
        .sheet(isPresented: self.$showPicker) {
            DocumentPickerView()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Причина, по которой я думаю, что существует проблема, заключается в том, что инструменты Xcode показывают утечки памяти, вот след:

 32 Bytes  100.0%   1       start
 32 Bytes  100.0%   1        main
 32 Bytes  100.0%   1         UIApplicationMain
 32 Bytes  100.0%   1          GSEventRunModal
 32 Bytes  100.0%   1           CFRunLoopRunSpecific
 32 Bytes  100.0%   1            __CFRunLoopRun
 32 Bytes  100.0%   1             __CFRunLoopDoObservers
 32 Bytes  100.0%   1              __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
 32 Bytes  100.0%   1               _afterCACommitHandler
 32 Bytes  100.0%   1                _cleanUpAfterCAFlushAndRunDeferredBlocks
 32 Bytes  100.0%   1                 _runAfterCACommitDeferredBlocks
 32 Bytes  100.0%   1                  __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.478
 32 Bytes  100.0%   1                   _UIViewControllerTransitioningRunCustomTransition
 32 Bytes  100.0%   1                    +[UIView(Animation) _setAlongsideAnimations:toRunByEndOfBlock:]
 32 Bytes  100.0%   1                     ___UIViewControllerTransitioningRunCustomTransition_block_invoke.648
 32 Bytes  100.0%   1                      +[UIInputResponderController _pinInputViewsForInputResponderController:onBehalfOfResponder:duringBlock:]
 32 Bytes  100.0%   1                       ___UIViewControllerTransitioningRunCustomTransition_block_invoke_2
 32 Bytes  100.0%   1                        -[UIViewControllerBuiltinTransitionViewAnimator animateTransition:]
 32 Bytes  100.0%   1                         -[UITransitionView transition:fromView:toView:removeFromView:]
 32 Bytes  100.0%   1                          -[UITransitionView _startTransition:withDuration:]
 32 Bytes  100.0%   1                           +[UIView(UIViewAnimationWithBlocks) conditionallyAnimate:withAnimation:layout:completion:]
 32 Bytes  100.0%   1                            __50-[UITransitionView _startTransition:withDuration:]_block_invoke.169
 32 Bytes  100.0%   1                             +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:]
 32 Bytes  100.0%   1                              +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:]
 32 Bytes  100.0%   1                               +[UIViewAnimationState popAnimationState]
 32 Bytes  100.0%   1                                -[UIViewAnimationState pop]
 32 Bytes  100.0%   1                                 -[UIViewAnimationState _runAlongsideAnimations]
 32 Bytes  100.0%   1                                  __63+[UIView(Animation) _setAlongsideAnimations:toRunByEndOfBlock:]_block_invoke
 32 Bytes  100.0%   1                                   -[_UIViewControllerTransitionContext __runAlongsideAnimations]
 32 Bytes  100.0%   1                                    -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:]
 32 Bytes  100.0%   1                                     __54-[_UISheetPresentationController transitionWillBegin:]_block_invoke.345
 32 Bytes  100.0%   1                                      +[UIView(Animation) performWithoutAnimation:]
 32 Bytes  100.0%   1                                       __54-[_UISheetPresentationController transitionWillBegin:]_block_invoke_2
 32 Bytes  100.0%   1                                        -[_UISheetLayoutInfo _layout]
 32 Bytes  100.0%   1                                         -[_UISheetPresentationController _sheetLayoutInfoLayout:]
 32 Bytes  100.0%   1                                          -[UIView(Hierarchy) layoutBelowIfNeeded]
 32 Bytes  100.0%   1                                           CA::Layer::layout_if_needed(CA::Transaction*)
 32 Bytes  100.0%   1                                            -[CALayer layoutSublayers]
 32 Bytes  100.0%   1                                             -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
 32 Bytes  100.0%   1                                              @objc _UIHostingView.layoutSubviews()
 32 Bytes  100.0%   1                                               _UIHostingView.layoutSubviews()
 32 Bytes  100.0%   1                                                ViewRendererHost.render(interval:updateDisplayList:)
 32 Bytes  100.0%   1                                                 closure #1 in ViewRendererHost.render(interval:updateDisplayList:)
 32 Bytes  100.0%   1                                                  closure #1 in closure #1 in ViewRendererHost.render(interval:updateDisplayList:)
 32 Bytes  100.0%   1                                                   ViewGraph.updateOutputs(at:)
 32 Bytes  100.0%   1                                                    closure #1 in ViewGraph.updateOutputs(at:)
 32 Bytes  100.0%   1                                                     ViewGraph.runTransaction(in:)
 32 Bytes  100.0%   1                                                      AG::Subgraph::update(unsigned int)
 32 Bytes  100.0%   1                                                       AG::Graph::update_attribute(unsigned int, bool)
 32 Bytes  100.0%   1                                                        AG::Graph::UpdateStack::update()
 32 Bytes  100.0%   1                                                         partial apply
 32 Bytes  100.0%   1                                                          protocol witness for static UntypedAttribute._update(_:graph:attribute:) in conformance PlatformViewChild<A>
 32 Bytes  100.0%   1                                                           PlatformViewChild.update(context:)
 32 Bytes  100.0%   1                                                            closure #1 in PlatformViewChild.update(context:)
 32 Bytes  100.0%   1                                                             swift_weakInit
 32 Bytes  100.0%   1                                                              swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::formWeakReference()
 32 Bytes  100.0%   1                                                               operator new(unsigned long)
 32 Bytes  100.0%   1                                                                malloc

С несколькими вызовами при распределении у меня есть такие сущности, которые потеряли свою память:

Category                                            Persistent  # Persistent    # Transient Total Bytes
UIDocumentBrowserViewController                     22,50 KiB       15              0       22,50 KiB
DOCRemoteViewController                             22,50 KiB       15              0       22,50 KiB
_UIResilientRemoteViewContainerViewController       13,36 KiB       15              0       13,36 KiB
_UIRemoteView                                       6,80 KiB        15              0       6,80 KiB
_UISizeTrackingView                                 6,56 KiB        15              0       6,56 KiB
DOCRemoteBarButtonTrackingView                      5,62 KiB        15              0       5,62 KiB
DOCConfiguration                                    2,58 KiB        15              0       2,58 KiB
DOCRemoteContext                                    1,88 KiB        15              0       1,88 KiB
_UIViewServiceInterface                             1,41 KiB        15              0       1,41 KiB
__NSXPCInterfaceProxy__NSExtensionContextVending    1,17 KiB        15              0       1,17 KiB
UISystemDefaultTextInputAssistantItem               1,17 KiB        15              0       1,17 KiB
UIKeyboardBIUImageGenerator                         960 Bytes       15              0       960 Bytes
_UIViewServiceReplyControlProxy                     720 Bytes       15              0       720 Bytes
Swift.__SwiftDeferredNSArray                        480 Bytes       15              0       480 Bytes
DOCRemoteBarButton                                  480 Bytes       15              0       480 Bytes
NSWeakObjectValue                                   480 Bytes       15              0       480 Bytes
_UIRemoteViewService                                480 Bytes       15              0       480 Bytes
_UIViewServiceImplicitAnimationEncodingProxy        480 Bytes       15              0       480 Bytes
DOCWeakProxy                                        240 Bytes       15              0       240 Bytes

UPD:

Я только начал обратная связь , чтобы решить эту проблему, но я обнаружил, что подобных проблем нет, поэтому, если у вас есть такая же, сообщите также

1 Ответ

0 голосов
/ 19 июня 2020

Это определенно ошибка Apple, поэтому стоит отправить им отзыв.

Между тем, вот безопасный обходной путь, применимый для большинства случаев использования. Протестировано с Xcode 11.4 / iOS 13.4. Идея состоит в том, чтобы использовать общий экземпляр средства выбора документов и просто перенастраивать его при каждом вызове.

struct DocumentPickerView: UIViewControllerRepresentable {
    static let picker = UIDocumentPickerViewController(documentTypes: [String(kUTTypeItem)], in: .import)

    func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
        Self.picker.allowsMultipleSelection = false
        Self.picker.delegate = context.coordinator
        return Self.picker
    }

    // ... other code no changes
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...