Импорт файлов iOS в мое приложение

Я создаю приложение iOS, через которое пользователи могут распечатывать файлы на своем устройстве. Из моего приложения я могу получить доступ к файлам на устройстве через DocumentPicker, предоставляемый другими приложениями, такими как iCloud Drive, Dropbox и т. д.

Теперь я хочу добавить функциональность, с помощью которой пользователь может поделиться файлом с моим приложением через другое приложение. Я создал Action Extension для этого. Например, если я выбираю изображение в приложении «Фотографии» и выбираю Share, я получаю свое расширение на листе «Общий доступ», а когда я выбираю его, я также получаю URL-адрес файла. Затем я создаю zip-файл этого файла, чтобы отправить его на свой сервер. Но проблема в том, что zip-файл всегда пуст. Код, который я использую, выглядит следующим образом:

ViewDidLoad() в расширении действия

if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
    itemProvider.loadItemForTypeIdentifier(kUTTypeImage as String, options: nil, 
        completionHandler: { (image, error) in
            NSOperationQueue.mainQueue().addOperationWithBlock {
                print("Image: \(image.debugDescription)")
                //Image: Optional(file:///Users/guestUser/Library/Developer/CoreSimulator/Devices/00B81632-041E-47B1-BACD-2F15F114AA2D/data/Media/DCIM/100APPLE/IMG_0004.JPG)
                print("Image class: \(image.dynamicType)")
                //Image class: Optional<NSSecureCoding>
                self.filePaths.append(image.debugDescription)
                let zipPath = self.createZip(filePaths)
                print("Zip: \(zipPath)")
            }
         })
}

И моя функция createZip выглядит следующим образом:

func createZipWithFiles(filePaths: [AnyObject]) -> String {
    let zipPath = createZipPath()  //Creates an unique zip file name

    let success = SSZipArchive.createZipFileAtPath(zipPath, withFilesAtPaths: filePaths)

    if success {
        return zipPath
    }
    else {
        return "zip prepation failed"
    }
}

Есть ли способ создать zip-архив с общими файлами?


person Prerak Sola    schedule 13.04.2016    source источник
comment
SSZipArchive возвращает ошибку? Вы уверены, что у вас есть доступ на запись к zipPath и доступ на чтение ко всем путям в filePaths?   -  person JAL    schedule 20.04.2016
comment
Нет не выдает никакой ошибки. Он создает zip-файл в zipPath, поэтому у меня есть доступ для записи в zipPath. И файлы в filePaths — это файлы изображений, поступающие из приложения «Фотографии» по умолчанию. В журналах говорится, что файл не существует в указанной позиции, но я могу увидеть файл, если я перемещаюсь по терминалу (для симулятора).   -  person Prerak Sola    schedule 20.04.2016
comment
Использование image.debugDescription — это не способ получить путь к файлу изображения. Во-первых, каков фактический тип image в обработчике завершения? Каков результат image.debugDescription?   -  person rmaddy    schedule 22.04.2016
comment
@rmaddy: изображение имеет тип NSSecureCoding, а вывод image.debugDescription что-то вроде fie:///Users/xxx/Library/Developer/CoreSimulator/Devices/---xx-xx-xx/data/Media/DCIM/100APPLE/IMG_0004.jpg   -  person Prerak Sola    schedule 25.04.2016
comment
У вас есть сообщение 2 func. В первом вы используете self.createZip(filePaths), а во втором вы публикуете func createZipWithFiles, но я не вижу никакого метода createZip.   -  person Alessandro Ornano    schedule 25.04.2016
comment
@AlessandroOrnano: как я уже упоминал в комментариях, функция createZip() просто создает уникальное имя файла. Таким образом, он возвращает строку типа xxx-yy-zzz.zip.   -  person Prerak Sola    schedule 25.04.2016
comment
@PrerakSola Обновите свой вопрос, указав фактический и полный вывод строки print("Image: \(image.debugDescription)").   -  person rmaddy    schedule 25.04.2016
comment
@rmaddy: добавлен полный вывод в комментарии под оператором печати.   -  person Prerak Sola    schedule 25.04.2016
comment
Хорошо, теперь добавьте вывод print("Image class: \(image.dynamicType)").   -  person rmaddy    schedule 25.04.2016
comment
@rmaddy тоже добавил это.   -  person Prerak Sola    schedule 25.04.2016


Ответы (1)


Ваша основная проблема заключается в том, что вы слепо добавляете image.debugDescription к массиву, который ожидает путь к файлу. Вывод image.debugDescription вовсе не является допустимым путем к файлу. Вам нужно использовать правильную функцию на image, чтобы получить фактический путь к файлу.

Но объявлено, что image имеет тип NSSecureCoding. На основании вывода image.debugDescription кажется, что image действительно относится к типу NSURL. Итак, вам нужно преобразовать image в NSURL, используя строку вроде:

if let photoURL = image as? NSURL {
}

Когда у вас есть NSURL, вы можете использовать свойство path, чтобы получить фактически необходимый путь.

Итак, ваш код становится:

if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
    itemProvider.loadItemForTypeIdentifier(kUTTypeImage as String, options: nil, 
        completionHandler: { (image, error) in
            if let photoURL = image as? NSURL {
                NSOperationQueue.mainQueue().addOperationWithBlock {
                    let photoPath = photoURL.path
                    print("photoPath: \(photoPath)")
                    self.filePaths.append(photoPath)
                    let zipPath = self.createZip(filePaths)
                    print("Zip: \(zipPath)")
                }
            }
    })
}

Совет. Никогда не используйте debugDescription ни для чего, кроме оператора print. Его вывод — это просто некоторая строка, которая может содержать практически любую информацию, и этот вывод может меняться от одной версии iOS к другой.

person rmaddy    schedule 25.04.2016
comment
Спасибо за ответ. До этого, в качестве обходного пути, я создавал временное изображение, используя NSData в песочнице моего приложения, а затем копировал это изображение в zip-файл для загрузки на сервер. Но ваш способ экономит накладные расходы на обработку и память при создании дополнительного изображения. - person Prerak Sola; 25.04.2016
comment
@rmaddy, я реализовал общее расширение в своем приложении. В iOS 13 мое приложение расширения общего доступа не может открыть основное приложение для получения общего файла/изображения, потому что UIApplication.shared сейчас недоступен. Все предыдущие версии работают нормально. Итак, как разработчик может получать/импортировать данные из разных источников? Предположим, я хочу открыть файл в своем приложении из Gmail или с диска, какой-нибудь обходной путь? - person Jamshed Alam; 23.02.2020