他のアプリからファイルを受け取る

ちょっとしたコードや設定などですが、忘れがちであらためて調べるのも面倒なので、忘備録的なものです。
順不同で、気づいたものから順にSwift4で使えるコードを載せていきます。

Swift-Tips

スワイプ時に削除以外にも動作を設定

共有メニューにアプリを表示して、他のアプリからファイルを受け取る方法

 

・受け取ることができるファイルの形式をinfo.plistに設定
ここに設定された種類のファイルを受け取り可能になり、送信先アプリの候補に表示されるようになる。

ファイル管理については公式ページ ファイルシステムの基礎

ファイル種別の指定については公式ページ System-Declared Uniform Type Identifiers
もっと簡単に調べる方法がこちらにありました。すばらしい!niwatakoのはてなブログ

・拡張子から調べるコード


if let str = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "xlsx", nil)?.takeUnretainedValue() {
    print("\(str)") // org.openxmlformats.spreadsheetml.sheet
}

他のアプリでファイルを指定し送信先を選ぶとAppDelegeteにイベントが通知されるので、ファイルを受け取る処理を記述する
・ファイルはInbox内にあるので、自分の管理する場所に移動して使用する
・下記はAudioファイルを受け取って、再生画面に遷移する例

・受け取る処理をAppDelegeteに記述


    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        if let currentVc = window?.rootViewController?.presentedViewController {
            print(NSStringFromClass(currentVc.classForCoder))
            if NSStringFromClass(currentVc.classForCoder) == "RepeatAfterYou.ControlVC" {
                (currentVc as! ControlVC).busyMessage()
                return false
            }
            
        }
        // ファイルのURLを受け取る
        print("URL of recieved file = \(url)")
        // ファイルパスに変換
        let sourcePath:String = url.path
        let fileName = url.lastPathComponent
        let destPath = fileMoveToArchive(sourcePath)
        if destPath != nil {
           // ココで再生入力画面に遷移したい
            let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let ioVc:ControlVC = storyboard.instantiateViewController(withIdentifier: "ControlVC") as! ControlVC
            ioVc.entry = Entry(date:Date(),title:"",memo:"",audioFilePath:destPath!,audioFileName:fileName,texts:[TextPhrase(top:0,end:nil,speaker:"",text:"",comment:"")])
            ioVc.isNewEntry = true
            self.window?.rootViewController?.present(ioVc, animated: true, completion: nil)
        }
        
        return true

    }

・受け取ったファイルはInboxにあるので、管理するフォルダに移動して、Inboxのファイルは消す


    /// 受信したファイルをローカルアーカイブに移動
    ///
    @objc func fileMoveToArchive(_ fromPath:String)->String? {
        let fm = FileManager()
        
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let audioFolderPath = documentsPath + "/Audio"
        //Audioフォルダが無ければ作る
        var isDirExists : ObjCBool = false
        fm.fileExists(atPath: audioFolderPath, isDirectory:&isDirExists)
        if !isDirExists.boolValue {
            do {
                try fm.createDirectory(atPath: audioFolderPath, withIntermediateDirectories: true, attributes: nil)
            } catch let error1 {
                print("Error createDirectory : \(audioFolderPath) : " + error1.localizedDescription  )
                return nil
            }
        }
        let id = createFileID()
        let fileName = id + URL(fileURLWithPath: fromPath).lastPathComponent
        let destPath = audioFolderPath + "/" + fileName
        currentAudioFileName = destPath
        sourceAudioFileName = fromPath
        //異動先のファイルの有無をチェック
        if fm.fileExists(atPath: destPath) { // ファイル有りの場合は先に削除
            do {
                try fm.removeItem(atPath: destPath)
            } catch let error1 {
                print("Error move file : \(destPath) : " + error1.localizedDescription  )
                return nil
            }
        }
        //ファイルを移動
        do {
            try fm.moveItem(atPath: fromPath as String, toPath: destPath)
        } catch let error1 {
            print("Error move file : \(destPath) : " + error1.localizedDescription  )
            //return nil
        }
        
        // Inboxの余分なファイルは消す
        let inboxPath:String = documentsPath + "/Inbox/"
        var contents:[String] = []
        do {
            contents = try fm.contentsOfDirectory(atPath: inboxPath) as [String]
        } catch let error1 {
            print("Error serch file : \(inboxPath) : " + error1.localizedDescription  )
            return nil
        }
        
        for filePath in contents {
            let targetFilePath = inboxPath + filePath
            do {
                print(targetFilePath)
                try fm.removeItem(atPath: targetFilePath)
            } catch let error1 {
                print("Error remove file : \(filePath) : " + error1.localizedDescription  )
                return nil
            }
        }


        return fileName
    }

・おまけ:ローカルアーカイブからファイルを削除


    @objc func removeAudioFile(_ filename:String) {
        let fm = FileManager()
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let audioFolderPath = documentsPath + "/Audio/" + filename

        if fm.fileExists(atPath: audioFolderPath) {
            do {
                try fm.removeItem(at: URL(fileURLWithPath: audioFolderPath))
            } catch let error1 {
                print("Error file delete : \(audioFolderPath) : " + error1.localizedDescription  )
                return
            }
        }
    }