[закрыто] coreData, cloudKit, резервное копирование


#21

Да.
Вот есть очень хороший пример того, что нужно. Там самое главное читайте первый ответ про один из ключей в info.plist - от этого, похоже, может зависить вся роботоспособность кода )).

И вот ещё тоже похожий пример того что нужно в дополнение и сравнение.

И вот ещё материал, на которые ссылается один из авторов (я его и так находил, но он мне показался какой-то небольшой, но сейчас смотрю - там всё локанично и понятно :slight_smile: ).

З.Ы. Сам ещё не проверял на практике - не было времени. Вечером попробую сделать под себя и протестить.


#22

Что-то я так и не поняла, как это работает. А у вас получилось?


#23

В процессе. Пока нет, но должно ))


#24

Вот рабочий код:

func saveToIcloud (localPath: String) throws {
    //is iCloud working?
    guard let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: "YourIdentifire")?.appendingPathComponent("yourFileName") else {print("iCloud is NOT working!"); return}
    print("create container successfully")
    //Create the Directory if it doesn't exist
    if !FileManager.default.fileExists(atPath: iCloudDocumentsURL.path, isDirectory: nil) {
        //This gets skipped after initial run saying directory exists, but still don't see it on iCloud
        do {
            try FileManager.default.createDirectory(at: iCloudDocumentsURL, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("error create dir to icloud - \(error.localizedDescription)")
            return
        }
    }
    //If file exists on iCloud remove it
    var isDir:ObjCBool = false
    if FileManager.default.fileExists(atPath: iCloudDocumentsURL.path, isDirectory: &isDir) {
        do {
            try FileManager.default.removeItem(at: iCloudDocumentsURL)
        } catch {
            print("error remove old file")
            return
        }
    }
    //copy from my local to iCloud
    do {
        try FileManager.default.copyItem(atPath: localPath, toPath: iCloudDocumentsURL.path)
    } catch {
        print("error copy local file to icloud")
        return
    }
    print("saving to icloud has been successfully")
}

сюда в localPath я передаю путь к своему локальному файлу. Сохраняется этот локальный файл у менят так:

var pathForSaveLibrary : String {
    let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0]
    return path
}
var pathForSaveData : String {
    let path = pathForSaveLibrary + "/data.plist"
    return path
}

Вот ещё код для проверки наличия файла в айклоуд:

guard let iCloudDocumentsURL2 = FileManager.default.url(forUbiquityContainerIdentifier: "YourIdentifire") else { print("the test is not work"); return}
if let fileList = try? FileManager().contentsOfDirectory(at: iCloudDocumentsURL2, includingPropertiesForKeys: nil, options: .skipsHiddenFiles) {
    print("fileList - \(fileList)")
    for s in fileList {
        print("file in icloud: \(s)")
    }
} else {
    print("no read backup in icloud")
}

Загрузка - это тот же самый FileManager.default.copyItem только пути наоборот:

func loadFromIcloud(localPath: String) throws {

guard let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: "YourIdentifire")?.appendingPathComponent("yourFileName") else { print("iCloud is NOT working!"); return }
print("create container successfully")

var isDir:ObjCBool = false

if FileManager.default.fileExists(atPath: iCloudDocumentsURL.path, isDirectory: nil) {
    
    if FileManager.default.fileExists(atPath: localPath, isDirectory: &isDir) {
        do {
            try FileManager.default.removeItem(atPath: localPath)
        } catch {
            print("error remove old local file: \(error.localizedDescription)")
            return
        }
    }
    
    do {
        try FileManager.default.copyItem(atPath: iCloudDocumentsURL.path, toPath: localPath)
    } catch {
        print("error copy files from icloud - \(error.localizedDescription)")
        return
    }
} else {
    print("No backup data")
}

}


#25

Админы, ау, помогите? как сохранить базу coredata в облако - делать резервные копии (мы не про cloudKit, синхронизация на разных устройсвах не нужна, хотя по cloudKit-у тоже нужен курс) … но бэкапить корДату нужно, если телефон сломался и …

и нужно при переустановке приложение - чтобы данные вернулись из нашей сохраненной в облако базы … !? ЧТобы она сама бэюкапилась (точнее синхронизировалась с облаком) по времени или по изменениям в базе + наличию инета …

ПОМОГИТЕ НАМ … а то мы скоро опять велосипед какой-нибудь изобретем и только время потратим …


#26

Так всё же понятно! Именно для кордаты был создан cloudkit - там это всё делается несложно и схоже с кор датой - материала много! Если не нужно делиться данными, то создаётся приватный контейнер и всё.

Если надо писать бэкап в клоуд пользователя, то сохраняйте локальные файлы как я написал выше. Материал тоже есть.
Другой вопрос, что если вы хотите бекапить кордату не в клоудкит, то вам надо сначала ваши данный сохранить в файл! Как это делать я описывал тут. Но тогда не очень понятно зачем вам вообще кордата, если вы данные будете хранить в локальном файле???

Универсального ответа нет! И ни кто не принесёт ни чего на блюдечке :slight_smile:

По вашей ситуации ответа 2:

  1. если вы используете кордату, то бэкапте в клоудкит.
  2. если хотите в айклоуд пользователя, то и корадата вам ни к чему на простых приложениях.

#27

Как выше и написали - хранилище легко отделяется и копируется в облако.

И в более-менее проектах не советовал бы использовать сам CloudKit - проблемы с тестированием, автоматизацией и другие плюшки этого решения обеспечены.


#28

Я бы посоветовал отказаться от CoreData и пересесть на Firebase. База всегда в онлайне, не нужно переживать из-за поломки телефона или смены оного.


#29

А почему не вместе? Кор для локального сохранения и Firebase для сохранения данных в резерв?:thinking:


#30

Какой смысл держать 2 одинаковых функционала? Firevase в этом случае удовлетворит все потребности.


#31

Ну к примеру у меня и то и другое. Но чтобы не требовалось постоянный интернет я сохраняю локально. Потому что данные грузятся в трёх случаях: 1. При регистрации, 2. При авторизации, 3. При редактировании профиля.


#32

А синхронизация предусмотрена?


#33

Естественно. Но пока не сделал при редактировании без сети синхронизацию. По этому ограничил им редактирование оффлайн(


#34

Тогда другой разговор. Это нужно для оффлайн доступа.


#35

Ну и если удалил приложение и заново установил. Чтоб по 100 раз одно и то же не указывать.


#36

Это не относится к этому, т.к. для этого и нужна онлайн база.


#37

Теперь я ещё больше запуталась … вот смотрите, например мы с вами создаем приложение-напоминалку. У него есть 2 поля, которые заполняются и сохраняются в корДату - это сама дата + какой-то текст. При сохранении создается на основании даты - локальное уведомление. Регистрации у приложения нет. Человек его просто скачивает и пользуется. Мы хотим, чтобы если вдруг человек сменит телефон или сделает ресет, или просто решит приложение переустановить, то все данные, которые были введены в приложение - автоматически подгрузились из резервной копии. При этом не нужна синхронизация на разных устройствах.

Вопрос, как такое сделать … по факту нам нужны и данные и уведомления, но без использования сторонних продуктов, типа firebase. В настройках телефона есть вкл/выкл Резервной копии всего телефона, но это не спасет от “просто переустановки приложения” … так же в настройках есть iCloud Drive и мне кажется нужно как-то его использовать, но как тогда быть с уведомлениями (в теории, когда копию подгружаем - можно пробежаться по ней и пересоздать уведомления) … Но сейчас главный вопрос, как правильно, без костылей, выбрать способ решения такого вопроса.

:roll_eyes:


#38

В этом случае нету серебрянной пули. Всегда будут каке-то факторы, которые будут требовать дополнительного решения.
В вашем случае придется выбирать: либо жертвовать каким-то функционалом, либо использовать дополнительные сервисы/библиотеки.
Опять же, для вашей синхронизации так или иначе нужен интернет, так почему же в таком случае не использовать механизм, который уже умеет и хранить данные и отправлять пуши. Я про Firebase. Как мне кажется, он должен вам подойти очень хорошо. Он избавит вас от гемороя с синхронизацией и от мыслей при переустановке или смене телефона. Единственное, нужно будет сделать проверку на наличие интернета, если надо будет что-то подтянуть или обновить.


#39

тогда вообще не понятно зачем вам кордата? ))) храните в файле типа .plist (ключ-значение) такие простые данные и записывайте файл в айклоуд )


#40

Только сейчас осенило. Если регистрации нет, то в случае с Firebase нужно будет сделать, что бы знать какие записи подтягивать для пользователя. Это будет еще один нюанс.
Хотя я могу ошибаться, не пользовался пока Firebase, но возможно у него есть привязка к AppleID.