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

Сбой при добавлении постоянного хранилища (включен iCloud) в делегате приложения

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

Новое обновление

  • Я уверен, что нашел способ повторной синхронизации устройств, когда они перестали разговаривать друг с другом. Я собираюсь обновить свои ответьте ниже со всеми подробностями. Я полностью надеюсь, что вы все найдете это полезно. Прошло почти 2 месяца проб и ошибок, чтобы понять это один из. Поэтому, пожалуйста, дайте ссылку и поделитесь этим с другими, кто имея аналогичные проблемы, получая устройства, чтобы снова поговорить с каждым другой через iCloud. Мне потребовалось навсегда, чтобы все это понять, поэтому я я более чем счастлив сохранить как можно больше других разработчиков из чтобы создать свои собственные исправления для make-shift.

Другое дополнение для правильной настройки

  • Я обнаружил, что после обновления приложения, которое связано с данными iCloud с учетной записью может вызвать сбой при открытии, потому что iCloud данные будут пытаться немедленно слиться с устройством (где устройство еще не настроило свой постоянный магазин). Я добавил @property (nonatomic, readwrite) BOOL unlocked; до AppDelegate.h и @synthesize unlocked; до AppDelegate.m. Затем я изменил свой метод - (NSPersistentStoreCoordinator *)persistentStoreCoordinator как а также мой метод - (void)mergeChangesFrom_iCloud, оба из которых будет показано ниже (посередине для постоянной настройки хранилища и внизу для метода слияния iCloud). По сути, я говорю приложение, чтобы предотвратить iCloud от слияния данных до тех пор, пока приложение не установит его постоянный магазин. В противном случае вы увидите крах приложения из-за нечитаемые ошибки.

Вот как я настраиваю свой persistentStoreCoordinator:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }


    // here is where you declare the persistent store is not prepared;
    self.unlocked = NO;

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Maintain_My_Car.sqlite"];

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];   

    NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSDictionary *options = nil;

        NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:nil];

        NSString *coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"];

        if (coreDataCloudContent.length != 0) {
            // iCloud enabled;

            cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];
            options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, @"<bundleIdentifier>.store", NSPersistentStoreUbiquitousContentNameKey, cloudURL, NSPersistentStoreUbiquitousContentURLKey, nil];

        } else {

            // iCloud not enabled;
            options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

        }

        NSError *error = nil;

        [psc lock];

        if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {

            NSLog(@"bad things %@ %@", error, [error userInfo]);
            abort();

        }
        [psc unlock];

        // the store is now prepared and ready for iCloud to import data;
        self.unlocked = YES;


        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog(@"iCloud persistent store added");

            [[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil];

        });
    });

    return __persistentStoreCoordinator;
}

<myAppKey> и <bundleIdentifier> - это, конечно, фактические значения. Я просто маскирую их для совместного использования этого кода.

Я знаю, что некоторые люди по-прежнему испытывают проблемы с этим и могут использовать этот вопрос в качестве ссылки на то, как настроить свои собственные приложения Core Data с поддержкой iCloud, поэтому я хочу обновить его всякий раз, когда я вношу изменения в свой персональный код, чтобы все могли использовать код, который работает для меня. В этом обновлении я изменил начальный cloudURL с [fileManager URLForUbiquityContainerIdentifier:@"<TeamIdentifier>.<bundleIdentifier>"] на [fileManager URLForUbiquityContainerIdentifier:nil], гарантируя, что информация о контейнере будет собрана из файла прав.

Дополнительные методы _notificationArray определяется следующим образом: @property (nonatomice, strong) NSMutableArray *notificationArray; @synthesize notificationArray = _notificationArray;

- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {
    if (self.unlocked) {
        NSManagedObjectContext *moc = [self managedObjectContext];

        if (self.notificationArray.count != 0) {
            for (NSNotification *note in _notificationArray) {
                [moc performBlock:^{
                    [self mergeiCloudChanges:note forContext:moc];
                }];
            }
            [_notificationArray removeAllObjects];
            [moc performBlock:^{
                [self mergeiCloudChanges:notification forContext:moc];
            }];
        } else {
            [moc performBlock:^{
                [self mergeiCloudChanges:notification forContext:moc];
            }];
        }
    } else {
        if (_notificationArray == nil) {
            _notificationArray = [[NSMutableArray alloc] init];
        }
        [_notificationArray addObject:notification];
    }
}

- (void)resetStore {
    [self saveContext];
    __persistentStoreCoordinator = nil;
    __managedObjectContext = nil;
    // reset the managedObjectContext for your program as you would in application:didFinishLaunchingWithOptions:
    myMainView.managedObjectContext = [self managedObjectContext];
    // the example above will rebuild the MOC and PSC for you with the new parameters in mind;
}

Тогда существует метод mergeiCloudChanges:forContext::

- (void)mergeiCloudChanges:(NSNotification *)note forContext:(NSManagedObjectContext *)moc {
    // below are a few logs you can run to see what is being done and when;
    NSLog(@"insert %@", [[note userInfo] valueForKey:@"inserted"]);
    NSLog(@"delete %@", [[note userInfo] valueForKey:@"deleted"]);
    NSLog(@"update %@", [[note userInfo] valueForKey:@"updated"]);
    [moc mergeChangesFromContextDidSaveNotification:note];

    NSNotification *refreshNotification = [NSNotification notificationWithName:@"RefreshAllViews" object:self userInfo:[note userInfo]];
    [[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
    // do any additional work here;
}

Исходная проблема

  • Использование iCloud в iOS 5.0.1, я иногда получаю ошибки к постоянному магазину. Я собираюсь продолжить обновление новую информацию, поскольку я нахожу ее в экспериментах, но до сих пор решение, которое я предоставил, - это единственный способ заставить приложение работать (к сожалению, решение jlstrecker не работает me) как только я начну видеть ошибку, которая выглядит следующим образом:

    -NSPersistentStoreCoordinator addPersistentStoreWithType: configuration: URL: options: error:: CoreData: Ubiquity: ошибка при попытке прочитать корневой URL-адрес вездесущности: файл://localhost/private/var/mobile/Library/Mobile%20Documents/./data/. Ошибка: Error Domain = LibrarianErrorDomain Code = 1 "Операция не удалось завершить. (Ошибка LibrarianErrorDomain 1 - Невозможно выполнить initiate item download.)" UserInfo = 0x176000 {NSURL = Файл://localhost/private/var/mobile/Library/Mobile%20Documents/./data/, NSDescription = Невозможно инициировать загрузку элемента.}

    В жизни я не могу понять, почему я вижу это все внезапно или как заставить его остановиться. Я удалил приложение из обоих устройства удалили данные iCloud, которые были ранее синхронизированы между их и удалили любые данные из резервных копий в отношении приложений. у меня есть перезапустил Xcode, перезапустил оба устройства, очистил проект Xcode, но ничто не остановило ошибку. Я никогда не видел эта ошибка раньше и не имела нулевой информации как это сделать.

    Приложение вылетает здесь:

    if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
    
        NSLog(@"bad things %@ %@", error, [error userInfo]);
        abort();
    
    }
    

    Журнал никогда не попадает и не прерывается. Я просто вижу ошибку выше и само приложение становится невосприимчивым. Если кто-нибудь может мне помочь в правильном направлении, я был бы очень благодарен.

Предыдущие выпуски/вопросы

  • Это похоже на продолжение даже после обновления с бета-версии публичный выпуск 5.0.1. Последний раз, когда это случилось со мной изменение модели управляемых контекстных данных. Учитывая, что у меня нет выпустила приложение еще, я не беспокоился о слиянии новой версии модель. Я просто удалил и переустановил приложение на своих устройствах, но то он отказался сотрудничать с данными, хранящимися в iCloud контейнер, под которым я подразумеваю, что я получил сообщение об ошибке, что хранилище не удалось загрузить элементы. Я думаю, это связано с противоречивыми данными модели, что имеет смысл. Похоже, вам просто нужно избавиться от данных в контейнере iCloud, не избавляясь от контейнера. Удаление данных iCloud, кажется, убивает все по сути отключив контейнер и идентификатор приложения. Поскольку это казалось проще, я попытался создать новый контейнер, как это было предложено jlstrecker, но, к сожалению, это совсем не помогло. Поэтому еще раз я должен был выполните шаги, изложенные в моем ответе, которые снова сделали трюк. Но учитывая, как надоедает создание нового приложения Идентификаторы и обновления профилей подготовки каждый раз, я думал, что лучше всего обновите то, что я научился, чтобы сузить причину и получить к более быстрому решению.

    Переход через iCloud > Хранение и резервное копирование > Управление хранилищем, затем удаление приложения будет лучшим решением для данных, но это приводит к повреждению контейнера, что приводит к ошибка выше. И после успешного выполнения этого, независимо от того, сколько раза я удаляю приложение и переустанавливаю его на устройство (чтобы сделать это появляются, как будто это первый раз, появляющийся на устройстве, и, надеюсь воссоздайте контейнер), я никогда не смогу заставить приложение показать в Документы и список данных снова. Это несколько касается, если это означает что любой, кто удаляет данные из своего iCloud, iCloud больше не будет работать для приложения. Я использую только на данный момент профиль разработки приложения, поэтому, возможно, используя профиль распределения может иметь какое-то значение, но мне придется испытайте это, прежде чем что-то сказать наверняка.

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

4b9b3361

Ответ 1

Обновленный ответ для повторной синхронизации ваших устройств Месяцы возиться вокруг привели меня к выяснению, что (я считаю) корневая проблема. Проблема заключалась в том, что устройства снова разговаривали друг с другом после того, как они перестали синхронизироваться. Я не могу точно сказать, что вызывает это, но мое подозрение в том, что журнал транзакций поврежден или, скорее, воссоздан контейнер самого журнала. Это было бы похоже на перенос проводки A в контейнер A и устройство B, выполняющее то же самое, что и для обеих сообщений в контейнере C, где они могут читать/записывать в журналы.

Теперь, когда мы знаем проблему, это вопрос создания решения. Больше возиться привело меня к следующему. У меня есть метод под названием resetiCloudSync:(BOOL)isSource, который является модифицированной версией метода выше в моем первоначальном вопросе.

- (void)resetiCloudSync:(BOOL)isSource {
    NSLog(@"reset sync source %d", isSource);
    NSManagedObjectContext *moc = self.managedObjectContext;

    if (isSource) {
        // remove data from app cloud account, then repopulate with copy of existing data;

        // find your log transaction container;
        NSURL *cloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
        NSString *coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"store"];
        cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];
        NSError *error = nil;

        // remove the old log transaction container and it logs;
        [[NSFileManager defaultManager] removeItemAtURL:cloudURL error:&error];

        // rebuild the container to insert the "new" data into;
        if ([[NSFileManager defaultManager] createFileAtPath:coreDataCloudContent contents:nil attributes:nil]) {

            // this will differ for everyone else. here i set up an array that stores the core data objects that are to-many relationships; 
            NSArray *keyArray = [NSArray arrayWithObjects:@"addedFields", @"mileages", @"parts", @"repairEvents", nil];

            // create a request to temporarily store the objects you need to replicate;
            // my heirarchy starts with vehicles as parent entities with many attributes and relationships (both to-one and to-many);
            // as this format is a mix of just about everything, it works great for example purposes;
            NSFetchRequest *request = [[NSFetchRequest alloc] init];
            NSEntityDescription *entity = [NSEntityDescription entityForName:@"Vehicle" inManagedObjectContext:moc];
            [request setEntity:entity];
            NSError *error = nil;
            NSArray *vehicles = [moc executeFetchRequest:request error:&error];

            for (NSManagedObject *object in vehicles) {
                NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:object.entity.name inManagedObjectContext:moc];
                // check regular values;
                for (NSString *key in object.entity.attributesByName.allKeys) {
                    [newObject setValue:[object valueForKey:key] forKey:key];
                }

                // check relationships;
                NSMutableSet *relSet = [[NSMutableSet alloc] init];
                for (NSString *key in object.entity.relationshipsByName.allKeys) {
                    [relSet removeAllObjects];

                    // check to see relationship exists;
                    if ([object valueForKey:key] != nil) {

                        // check to see if relationship is to-many;
                        if ([keyArray containsObject:key]) {
                            for (NSManagedObject *toManyObject in [object valueForKey:key]) {
                                [relSet addObject:toManyObject];
                            }
                        } else {
                            [relSet addObject:[object valueForKey:key]];
                        }

                        // cycle through objects;
                        for (NSManagedObject *subObject in relSet) {
                            NSManagedObject *newSubObject = [NSEntityDescription insertNewObjectForEntityForName:subObject.entity.name inManagedObjectContext:moc];
                            // check sub values;
                            for (NSString *subKey in subObject.entity.attributesByName.allKeys) {
                                NSLog(@"subkey %@", subKey);
                                [newSubObject setValue:[subObject valueForKey:subKey] forKey:subKey];
                            }
                            // check sub relationships;
                            for (NSString *subRel in subObject.entity.relationshipsByName.allKeys) {
                                NSLog(@"sub relationship %@", subRel);
                                // set up any additional checks if necessary;
                                [newSubObject setValue:newObject forKey:subRel];
                            }
                        }
                    }
                }   
                [moc deleteObject:object];
            }
            [self resetStore];
        }
    } else {
        // here we remove all data from the current device to populate with data pushed to cloud from other device;
        for (NSManagedObject *object in moc.registeredObjects) {
            [moc deleteObject:object];
        }
    }
    [[[UIAlertView alloc] initWithTitle:@"Sync has been reset" message:nil delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil] show];
}

В этом коде у меня есть два разных пути. Один - для устройств, которые не синхронизированы, и им необходимо импортировать данные из исходного устройства. Весь этот путь очищает память, чтобы подготовить ее к данным, которые должны быть в ней.

Другой (isSource = YES) путь, делает несколько вещей. Как правило, он удаляет поврежденный контейнер. Затем он создает новый контейнер (для журналов должно быть место для проживания). Наконец, он ищет через родительские объекты и копирует их. Это означает, что контейнер контейнера транзакций заполняется информацией, которая должна быть там. Затем вам нужно удалить исходные объекты, чтобы у вас не было дубликатов. Наконец, reset постоянное хранилище "обновит" основные данные приложения и обновит все представления и fetchedResultsControllers.

Я могу подтвердить, что это работает чудесно. Я очистил данные с устройств (isSource = NO), которые не разговаривали с основным устройством (где хранятся данные) в течение нескольких месяцев. Затем я вытолкнул данные из основного устройства и с восхищением наблюдал, как ВСЕ мои данные появились в течение нескольких секунд.

Опять же, не стесняйтесь ссылаться и делиться этим со всеми, у кого возникли проблемы с синхронизацией с iCloud.

Отвечайте на оригинальный вопрос, который больше не затрагивается после выхода iOS 5.1, который исправил сбой после удаления вашего хранилища iCloud приложения в настройках

После многих многих попыток попробовать что-либо и все, чтобы получить это, я попытался создать новый идентификатор приложения, обновил профиль профилей, связанный с приложением, изменился вокруг полей контейнера iCloud, чтобы соответствовать новому профилю, и все снова работает, Я до сих пор не знаю, почему это произошло, но похоже, что хранилище iCloud, связанное с этим идентификатором приложения, повреждено?

Итак, нижняя строка, если это происходит с кем-то еще, выполните следующие действия, и вы должны быть хорошими:

  • Создайте новый идентификатор приложения на портале Provisioning Portal.
  • Найдите профиль обеспечения, связанный с приложением. Нажмите "Изменить" - "Изменить", а затем измените идентификатор приложения на тот, который вы только что создали.
  • Отправьте изменение, затем замените существующий профиль в Xcode тем, который вы только что создали.
  • Измените все экземпляры <bundleIdentifier>, чтобы они соответствовали новому идентификатору приложения (это было бы на главной странице приложения приложения, правах на контейнеры iCloud и хранилище ключевых слов iCloud и в вашем файле AppDelegate, где вы создаете постоянный магазин, как в моем коде выше).
  • Перезагрузите Xcode, так как вы изменили информацию о профилях подготовки (он будет жаловаться иначе и откажется работать на устройстве).
  • Убедитесь, что новый профиль находится на устройствах, на которых вы хотите установить приложение, а затем выполните сборку и запуск. В этот момент все должно работать нормально.

Ответ 2

Еще одно уточнение: Аналогичная ситуация со мной испытала устройства на iOS 6.0.1 и бета-версии 6.1.

Он не полностью исправлен в iOS 5.1, как указано @Slev. Одно устройство полностью замерзнет примерно на 80 секунд, пытаясь получить доступ к постоянному хранилищу в iCloud, но никогда не сможет получить доступ к хранящейся там информации.

Я считаю, что это связано с поврежденным файлом журнала в ОС устройства. Удаление данных приложения или iCloud на устройстве не помогло устранить заморозку/невозможность доступа к хранилищу iCloud.

Единственное исправление, которое я обнаружил, - reset all settings (также стереть все содержимое) на устройстве. settings->general->reset.

Только тогда я могу снова получить доступ к данным в iCloud с моим приложением на этом устройстве. Надеюсь, это поможет кому-то еще, кто пришел сюда, искать решение очень расстраивающей ошибки.

Ответ 3

Я получил эту ошибку при использовании одного устройства в версии 5.0.1 beta 1 и 1 на 5.0.0.

Я избавился от ошибки, изменив имя контейнера iCloud. В списке iCloud Containers первый должен соответствовать вашему идентификатору приложения, но вы можете добавить дополнительные контейнеры с разными именами.

(Как slev решение об изменении идентификатора приложения, это только хорошее решение, если приложение еще не выпущено.)

Ответ 4

UPDATE:

Каждый должен действительно взглянуть на сеанс 227 iDSoud Core Data от WWDC 2012. Исходный код, который они предоставляют, является отличной отправной точкой для решения на основе iCloud. Действительно потратьте время, чтобы пройти то, что они делают. Вам нужно будет заполнить некоторые отверстия, такие как копирование объектов из одного магазина в другой и удаление дубликатов. При этом я больше не использую подход migratePersistentStore, как описано ниже, для перемещения между локальными и iCloud-хранилищами.


Мой оригинальный ответ:

Слев попросил меня отправить код для переноса магазина из локальной копии в iCloud и обратно. Этот код является экспериментальным и не должен использоваться в производстве. Он представлен здесь только как ссылка для обмена и продвижения вперед. После того, как Apple выпустит надлежащее ссылочное приложение, вам следует, вероятно, проконсультироваться с этим для ваших шаблонов и практик.

-(void) onChangeiCloudSync
{
    YourAppDelegate* appDelegate = (YourAppDelegate*) [[UIApplication sharedApplication] delegate];
    NSFileManager *fileManager = [NSFileManager defaultManager];

    if ([iCloudUtility iCloudEnabled])
    {
        NSURL *storeUrl = [[appDelegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"YourApp2.sqlite"];
        NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:nil];
        NSString* coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"];
        cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];

        //  The API to turn on Core Data iCloud support here.
        NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@"com.yourcompany.yourapp.coredata", NSPersistentStoreUbiquitousContentNameKey, cloudURL, NSPersistentStoreUbiquitousContentURLKey, [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];

        NSPersistentStore* store = [appDelegate.persistentStoreCoordinator.persistentStores objectAtIndex:0];
        NSError* error;
        if (![appDelegate.persistentStoreCoordinator migratePersistentStore:store toURL:storeUrl options:options withType:NSSQLiteStoreType error:&error])
        {
            NSLog(@"Error migrating data: %@, %@", error, [error userInfo]);
            //abort();
        }
        [fileManager removeItemAtURL:[[appDelegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"YourApp.sqlite"] error:nil];
        [appDelegate resetStore];
    }
    else
    {
        NSURL *storeUrl = [[appDelegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"YourApp.sqlite"];

        //  The API to turn on Core Data iCloud support here.
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                 nil];

        NSPersistentStore* store = [appDelegate.persistentStoreCoordinator.persistentStores objectAtIndex:0];
        NSError* error;
        if (![appDelegate.persistentStoreCoordinator migratePersistentStore:store toURL:storeUrl options:options withType:NSSQLiteStoreType error:&error])
        {
            NSLog(@"Error migrating data: %@, %@", error, [error userInfo]);
            //abort();
        }
        [fileManager removeItemAtURL:[[appDelegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"YourApp2.sqlite"] error:nil];
        [appDelegate resetStore];
    }
}

Ответ 5

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

Ваш код:

- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {
    if (self.unlocked) {
       NSManagedObjectContext *moc = [self managedObjectContext];
        [moc performBlock:^{
            [self mergeiCloudChanges:notification forContext:moc];
        }];
    }
}

Я еще не пробовал, но смотрю на этот код. Интересно, что происходит с уведомлениями, которые появляются, когда "разблокировано" является ложным. Вы потеряете их?

Не было бы лучше иметь цикл while, который проверяет свойство "unlocked" и тратит несколько раз, пока свойство не станет истинным?

Надеюсь, вы поймете мой очень плохой английский...:) Спасибо вам Dave