Подтвердить что ты не робот

Любой способ предварительно заполнить данные ядра?

Я создаю приложение списка и поддерживаю его с помощью основных данных.

Я хотел бы иметь список по умолчанию из 10 пунктов аэропорта, чтобы пользователь не начинал с нуля.

Есть ли способ сделать это?

Любая помощь приветствуется. Спасибо заранее.

4b9b3361

Ответ 1

Здесь лучший способ (и не требует знаний SQL):
Создайте быстрое приложение Core Data iPhone (или даже приложение Mac), используя ту же объектную модель, что и приложение "Список". Напишите несколько строк кода, чтобы сохранить управляемые объекты по умолчанию, которые вы хотите сохранить в хранилище. Затем запустите это приложение в симуляторе. Теперь перейдите в ~/Library/Application Support/iPhone Simulator/User/Applications. Найдите свое приложение среди GUID, а затем просто скопируйте хранилище sqlite в папку проекта приложения List.

Затем загрузите это хранилище, как в примере с CoreDataBooks.

Ответ 2

Да, на самом деле это пример CoreDataBooks, вы можете скачать здесь код: пример кода

Что вы делаете, так это создание внутреннего хранилища (базы данных) с помощью обычной процедуры для инициализации вашего магазина, как и в любом другом магазине, тогда вы просто запускаете свой код и позволяете ему выполнять код, как описано в примере CoreDataBooks (фрагмент кода ниже). После инициализации магазина вы захотите создать NSManagedObjectContext и инициализировать его созданным постоянным хранилищем, вставить все необходимые вам объекты и сохранить контекст.

После успешного сохранения контекста вы можете остановить приложение, затем перейти к поисковому устройству и перейти в папку: ~/Library/Developer Тип ~/Library/Developer в поиске.sqlite и посмотреть в разделе/​​Разработчик, сортировка по дате даст вам самое последнее. sqlite, которая должна соответствовать времени выполнения кода, вы можете взять этот магазин и добавить его в качестве ресурса своего проекта. Этот файл затем может быть прочитан постоянным координатором магазина.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

if (persistentStoreCoordinator) {
    return persistentStoreCoordinator;
}


NSString *storePath = [[self applicationDocumentsDirectory]      stringByAppendingPathComponent: @"CoreDataBooks.sqlite"];
 /*
  Set up the store.
 For the sake of illustration, provide a pre-populated default store.
 */
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
  NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"CoreDataBooks"      ofType:@"sqlite"];
 if (defaultStorePath) {
 [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
 }
}

NSURL *storeUrl = [NSURL fileURLWithPath:storePath];

 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber   numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

 NSError *error;
 if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
  // Update to handle the error appropriately.
  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
 exit(-1);  // Fail
}    

return persistentStoreCoordinator;
}

Надеюсь, это поможет.

-Oscar

Ответ 3

С помощью этого метода вам не нужно создавать отдельное приложение или иметь какие-либо знания SQL. Вам нужно только сделать файл JSON для ваших исходных данных.

Я использую JSON файл, который я анализирую на объекты, а затем вставляю их в Core Data. Я делаю это, когда приложение инициализируется. Я также создаю одну сущность в своих основных данных, которая указывает, были ли эти исходные данные уже вставлены, после того, как я вставляю исходные данные, я устанавливаю этот объект, поэтому в следующий раз при запуске script он видит, что начальные данные уже были инициализированы.

Чтобы прочитать json файл в объекты:

NSString *initialDataFile = [[NSBundle mainBundle] pathForResource:@"InitialData" ofType:@"json"];
NSError *readJsonError = nil;
NSArray *initialData = [NSJSONSerialization
                        JSONObjectWithData:[NSData dataWithContentsOfFile:initialDataFile]
                        options:kNilOptions
                        error:&readJsonError];

if(!initialData) {
    NSLog(@"Could not read JSON file: %@", readJsonError);
    abort();
}

Затем вы можете сделать объекты сущности для него следующим образом:

[initialData enumerateObjectsUsingBlock:^(id objData, NSUInteger idx, BOOL *stop) {

    MyEntityObject *obj = [NSEntityDescription
                          insertNewObjectForEntityForName:@"MyEntity"
                          inManagedObjectContext:dataController.managedObjectContext];

    obj.name = [objData objectForKey:@"name"];
    obj.description = [objData objectForKey:@"description"];

    // then insert 'obj' into Core Data

}];

Если вы хотите получить более подробное описание того, как это сделать, ознакомьтесь с этим руководством: http://www.raywenderlich.com/12170/core-data-tutorial-how-to-preloadimport-existing-data-updated

Ответ 4

Для 10 элементов вы можете просто сделать это в applicationDidFinishLaunching: в своем делете приложения.

Определите метод, например insertPredefinedObjects, который создает и заполняет экземпляры объекта, ответственного за управление пунктами вашего аэропорта, и сохраняет ваш контекст. Вы можете либо прочитать атрибуты из файла, либо просто переустановить их в своем коде. Затем вызовите этот метод внутри applicationDidFinishLaunching:.

Ответ 5

Помните, что, следуя примеру кода CoreDataBooks, он, вероятно, нарушает принципы хранения данных iOS:

https://developer.apple.com/icloud/documentation/data-storage/

У меня есть приложение, отклоненное для копирования предварительно заполненной базы данных (только для чтения) в каталог документов - поскольку она затем подкрепляется iCloud - и Apple хочет, чтобы это произошло с создаваемыми пользователем файлами.

В приведенных выше рекомендациях предлагаются некоторые решения, но они в основном сводятся к следующему:

  • храните БД в каталоге кэшей и грамотно обрабатывайте ситуации, когда ОС чистит кеши - вам придется перестроить БД, что, вероятно, для большинства из нас.

  • установите атрибут "не кэшировать" в файле DB, который является немного загадочным, поскольку для разных версий ОС это нужно сделать по-разному.

Я не думаю, что это слишком сложно, но помните, что у вас есть немного больше, чтобы сделать этот код кода вместе с iCloud...

Ответ 6

Итак, я разработал общий метод, который загружается из словаря (возможно, из JSON) и заполняет базу данных. Он должен использоваться ТОЛЬКО с надежными данными (из безопасного канала), он не может обрабатывать циклические ссылки, а миграции схем могут быть проблематичными... Но для простых случаев использования, таких как мои, должно быть хорошо

Здесь он идет

- (void)populateDBWithDict:(NSDictionary*)dict
               withContext:(NSManagedObjectContext*)context
{
    for (NSString* entitieName in dict) {

        for (NSDictionary* objDict in dict[entitieName]) {

            NSManagedObject* obj = [NSEntityDescription insertNewObjectForEntityForName:entitieName inManagedObjectContext:context];
            for (NSString* fieldName in objDict) {

                NSString* attName, *relatedClass, *relatedClassKey;

                if ([fieldName rangeOfString:@">"].location == NSNotFound) {
                    //Normal attribute
                    attName = fieldName; relatedClass=nil; relatedClassKey=nil;
                } else {
                    NSArray* strComponents = [fieldName componentsSeparatedByString:@">"];
                    attName = (NSString*)strComponents[0];
                    relatedClass = (NSString*)strComponents[1];
                    relatedClassKey = (NSString*)strComponents[2];
                }
                SEL selector = NSSelectorFromString([NSString stringWithFormat:@"set%@:", attName ]);
                NSMethodSignature* signature = [obj methodSignatureForSelector:selector];
                NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
                [invocation setTarget:obj];
                [invocation setSelector:selector];

                //Lets set the argument
                if (relatedClass) {
                    //It is a relationship
                    //Fetch the object
                    NSFetchRequest* query = [NSFetchRequest fetchRequestWithEntityName:relatedClass];
                    query.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:relatedClassKey ascending:YES]];
                    query.predicate = [NSPredicate predicateWithFormat:@"%K = %@", relatedClassKey, objDict[fieldName]];

                    NSError* error = nil;
                    NSArray* matches = [context executeFetchRequest:query error:&error];


                    if ([matches count] == 1) {
                        NSManagedObject* relatedObject = [matches lastObject];
                        [invocation setArgument:&relatedObject atIndex:2];
                    } else {
                        NSLog(@"Error! %@ = %@ (count: %d)", relatedClassKey,objDict[fieldName],[matches count]);
                    }


                } else if ([objDict[fieldName] isKindOfClass:[NSString class]]) {

                    //It is NSString
                    NSString* argument = objDict[fieldName];
                    [invocation setArgument:&argument atIndex:2];
                } else if ([objDict[fieldName] isKindOfClass:[NSNumber class]]) {

                    //It is NSNumber, get the type
                    NSNumber* argument = objDict[fieldName];
                    [invocation setArgument:&argument atIndex:2];

                }
                [invocation invoke];


            }

            NSError *error;
            if (![context save:&error]) {
                NSLog(@"%@",[error description]);
            }
        }
    }   
}

И загружается с json...

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"initialDB" ofType:@"json"];
NSData *jsonData = [NSData dataWithContentsOfFile:filePath];

NSError* error;
NSDictionary *initialDBDict = [NSJSONSerialization JSONObjectWithData:jsonData
                                                           options:NSJSONReadingMutableContainers error:&error];

[ self populateDBWithDict:initialDBDict withContext: [self managedObjectContext]];

Примеры JSON

    {
    "EntitieA": [ {"Att1": 1 }, {"Att1": 2} ],
    "EntitieB": [ {"Easy":"AS ABC", "Aref>EntitieA>Att1": 1} ]
    }

и

{
    "Country": [{"Code": 55, "Name": "Brasil","Acronym": "BR"}],
    "Region": [{"Country>Country>code": 55, "Code": 11, "Name": "Sao Paulo"},
               {"Country>Country>code": 55, "Code": 31, "Name": "Belo Horizonte"}]
}

Ответ 7

Как проверить, существуют ли какие-либо объекты, а если нет, создать один с некоторыми данными?

NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Settings"];
_managedObjectSettings = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];

if ([_managedObjectSettings count] == 0) {
    // first time, create some defaults
    NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:@"Settings" inManagedObjectContext:managedObjectContext];

    [newDevice setValue:[NSNumber numberWithBool: YES ] forKey:@"speed"];
    [newDevice setValue:[NSNumber numberWithBool: YES ] forKey:@"sound"];
    [newDevice setValue:[NSNumber numberWithBool: NO ] forKey:@"aspect"];
    [newDevice setValue:[NSNumber numberWithBool: NO  ] forKey: @"useH264"];
    [newDevice setValue:[NSNumber numberWithBool: NO ] forKey: @"useThumbnail"];

    NSError *error = nil;
    // Save the object to persistent store
    if (![managedObjectContext save:&error]) {
        NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
    }
}

Ответ 8

Этот ответ предназначен только для людей, которые

  • включая предварительно заполненную базу данных в вашем приложении
  • создание приложения для нескольких платформ (iOS, Android и т.д.).

Я сделал предварительно заполненную базу данных SQLite для приложения для Android. Затем, когда я делал версию приложения iOS, я думал, что лучше использовать Core Data. Поэтому я потратил довольно много времени на изучение Core Data, а затем переписал код для предварительного заполнения базы данных. Изучение того, как делать каждый шаг на обеих платформах, требует большого количества исследований, проб и ошибок. Было гораздо меньше совпадений, чем я бы надеялся.

В конце концов я просто решил использовать ту же базу SQLite из моего Android-проекта. Затем я использовал оболочку FMDB для прямого доступа к базе данных в iOS. Преимущества:

  • Необходимо только создать предварительно заполненную базу данных.
  • Не требует изменения парадигмы. Синтаксис между Android и FMDB, в то время как другой, по-прежнему довольно схож.
  • Имейте намного больше контроля над выполнением запросов.
  • Позволяет полнотекстовый поиск.

Хотя я не жалею о том, что изучаю Core Data, если бы я это сделал, я мог бы сэкономить много времени, просто придерживаясь SQLite.

Если вы начинаете работу в iOS, а затем планируете перейти на Android, я бы по-прежнему использовал оболочку SQLite, такую ​​как FMDB или другое программное обеспечение, чтобы предварительно заполнить базу данных. Хотя вы можете технически извлечь базу данных SQLite, которую вы предварительно заполняете с помощью Core Data, схема (имена таблиц и столбцов и т.д.) Будет названа странно.

Кстати, если вам не нужно изменять вашу предварительно заполненную базу данных, не копируйте ее в каталог документов после того, как приложение установлено. Просто обратитесь к нему непосредственно из пакета.

// get url reference to databaseName.sqlite in the bundle
let databaseURL: NSURL = NSBundle.mainBundle().URLForResource("databaseName", withExtension: "sqlite")!

// convert the url to a path so that FMDB can use it
let database = FMDatabase(path: databaseURL.path)

Это делает так, что у вас нет двух копий.

Обновление

Теперь я использую SQLite.swift, а не FMDB, потому что он лучше интегрируется с проектами Swift.

Ответ 9

Другим способом хранения значений по умолчанию является NSUserDefaults. (Сюрприз!) И его легко.

Предлагаемый некоторыми, поместите это в applicationDidFinishLaunching

В данном случае 10 значений по умолчанию, Airport0 thru 9

Настройка

NSUserDefaults *nud = [NSUserDefaults standardUserDefaults];
[nud setString:@"MACADDRESSORWHY" forKey:@"Airport0"];
    ...
[nud setString:@"MACADDRESSORWHY" forKey:@"Airport9"];
[nud synchronize];

или

[[NSUserDefaults standardUserDefaults] setString:@"MACADDRESSORWHY" forKey:@"Airport9"]];
     ...
[[NSUserDefaults standardUserDefaults] synchronize];

И затем, получив значения по умолчанию.

NSString *air0 = [[NSUserDefaults standardUserDefaults] stringForKey:@"Airport0"];

Ответ 10

Это сработало для меня. Это изменение ответа Андреа Тосо, созданное по мотивам этого блога. Единственная проблема с ответом состоит в том, что существует вероятность потери данных при перемещении файлов sqlite с помощью FileManager. Я сохранил около 500 строк данных, используя replacePersistentStore вместо FileManager.default.copyItem

Шаг 1
Заполните ваши базовые данные в другом приложении и получите путь к файлам, используя этот код:

let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
print(documentsDirectory)

Step2
Перетащите 3 файла с расширением .sqlite в ваш проект xCode. (Обязательно выберите опцию Добавить к целям).

Step3
Создать функцию для проверки запуска приложения в AppDelegate.swift

func isFirstLaunch() -> Bool {
    let hasBeenLaunchedBeforeFlag = "hasBeenLaunchedBeforeFlag"
    let isFirstLaunch = !UserDefaults.standard.bool(forKey: hasBeenLaunchedBeforeFlag)
    if (isFirstLaunch) {
        UserDefaults.standard.set(true, forKey: hasBeenLaunchedBeforeFlag)
        UserDefaults.standard.synchronize()
    }
    return isFirstLaunch
}

Step4
Скопируйте эту функцию в AppDelegate.swift, чтобы получить URL-адрес, куда должна быть перемещена база данных sqlite:

func getDocumentsDirectory()-> URL {
    let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
}

Шаг 5
Замените объявление persistentContainer следующим:

// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "ProjectName")

    let storeUrl = self.getDocumentsDirectory().appendingPathComponent("FileName.sqlite")

    if UserDefaults.isFirstLaunch() {
        let seededDataUrl = Bundle.main.url(forResource: "FileName", withExtension: "sqlite")
        try! container.persistentStoreCoordinator.replacePersistentStore(at: storeUrl, destinationOptions: nil, withPersistentStoreFrom: seededDataUrl!, sourceOptions: nil, ofType: NSSQLiteStoreType)
    }

    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

Ответ 11

Поскольку большинство ответов довольно старые, я рекомендую следующий урок. Это объясняет, как это можно сделать.

https://www.youtube.com/watch?v=xcV8Ow9nWFo