

swiftでアプリを開発しています。  
UIActivityViewControllerを使ってアクティビティダイアログを表示した際にメモリリークしています。  
リークを解消させる方法の見当がつかず困っています。解決方法についてご教示ください。  
コードは最後に載せておきます。(一部書き換えています。)

処理内容は、出力したCSVファイルをアクティビティダイアログに表示されたAirDropまたはメーラーで送信する、というものです。  
instrumentsで確認した際のssを添付します。iphone(ios8.4)と、ipadmini(ios9.3.4)で実行しました。それぞれダイアログを表示させる画面へ遷移し5回ダイアログを開閉しました。

[![iphoneで実行](https://i.stack.imgur.com/U9YEg.png)](https://i.stack.imgur.com/U9YEg.png)

↑iphoneでは「_UIAlertControllerCommmonInit」でNSMutableArrayがリークしているようです。このssでは2つのリークですが、開閉の回数分リークしている時もあります。

↓ipadのssはスタックトレースの内容が異なる3枚を載せておきます。(他のは、IsImage、IsContactの部分のみがIsPDFのような感じで異なっています。)  
ipadでは「CSStringCopyCFString」でNSCFStringがドカドカとリークしています。さらに開閉する毎にヒープが高くなっている(閉じても何か残っている？)点も気になります。こちらについても原因や回避策があればお教えください。よろしくお願いいたします。

[![ipadminiで実行\(1/3\)](https://i.stack.imgur.com/3ScCn.png)](https://i.stack.imgur.com/3ScCn.png)

[![ipadminiで実行\(2/3\)](https://i.stack.imgur.com/VZwwS.png)](https://i.stack.imgur.com/VZwwS.png)

[![ipadminiで実行\(3/3\)](https://i.stack.imgur.com/lpqPN.png)](https://i.stack.imgur.com/lpqPN.png)

[code]

    /// ボタン押下時処理(CSVファイル作成＋転送)
    func tapButton() {
    
        //CSVファイルを出力
        let strFullPath: String = outputCSVFile("sample.csv")
        print("csvpath:" + strFullPath)
    
        //(出力成功)アクティビティダイアログ表示
        if strFullPath != "" {
            _ad = MyAd() //広告をロード
    
            let body: String = NSLocalizedString("MSG_SEND", comment: "body文言")
            let file = NSURL(fileURLWithPath: strFullPath)
            let handler: (Bool -> Void) = { [unowned self] (completed) in
                if completed == true {
                    self._ad?.show(self)
                    print("CSV送信完了！")
                }
            }
            dispDialog(self, items: [body, file], btn: btnAction, arrow: .Up, handler: handler)
    
        //(出力失敗)エラーメッセージ表示
        } else {
            dispErrMsg(self, strMsg: NSLocalizedString("MSG_FILE_ERR", comment: "エラー発生"))
    
        }
    }
    
    /// アクティビティダイアログを表示
    class func dispDialog(vc: UIViewController, items: [AnyObject], btn: UIBarButtonItem, arrow: UIPopoverArrowDirection = .Unknown, handler: (Bool -> Void)! = nil) {
        let dialog = UIActivityViewController(activityItems: items, applicationActivities: nil)
    
        //使用しないアクティビティタイプ
        let excluded = [
            UIActivityTypeCopyToPasteboard,
            UIActivityTypeMessage,
        ]
        dialog.excludedActivityTypes = excluded
    
        //完了後の処理をセット
        if handler != nil {
            dialog.completionWithItemsHandler = { (activityType: String?, completed: Bool, returnedItems: [AnyObject]?, error: NSError?) in
                print("activityType: \(activityType)")
                handler(completed)
                return
            }
        }
    
        //For iPad And Univarsal Device
        if let popCtrl = dialog.popoverPresentationController {
            popCtrl.sourceView = vc.view
            popCtrl.permittedArrowDirections = arrow
            popCtrl.barButtonItem = btn
        }
    
        vc.presentViewController(dialog, animated: true, completion: nil)
    }
    
[/code]

画像を追加しました。  
[![iphone
autoreleasepool追加](https://i.stack.imgur.com/5XuFM.png)](https://i.stack.imgur.com/5XuFM.png)


CC BY-SA 3.0
2016-09-02T10:46:10.193
28653
2022-04-18T07:02:55.350
2016-09-03T10:53:15.853
14125
14125
question
swift memory-leaks
UIActivityViewControllerを使うと発生するメモリリークの解消方法を教えてください


Objective-Cでは、`@autoreleasepool`でメモリリークが起きるブロックを括ることでリークを減少させるので、

[code]

    autoreleasepool {
        dispDialog(self, items: [body, file], btn: btnAction, arrow: .Up, handler: handler)
    }
    
[/code]

と、`displayDialog`関数を`autoreleasepool`で括ってみてはいかがでしょうか


CC BY-SA 3.0
2016-09-03T04:37:04.757
28665
2016-09-03T04:37:04.757
14745
28653
answer