Приложение отлично работает на 4S, но вылетает на 3G из-за SIGABRT - PullRequest
1 голос
/ 31 января 2012

Когда пользователь запускает приложение в первый раз, он получает всплывающее окно и должен сохранить изображение.Работает на симуляторе и на 4S.Но когда я запускаю его с моим 3G, он выдает ошибку SIGABRT, как только я выбираю картинку.Я предполагаю, что это из-за размера картинки, которая слишком выбрана и, следовательно, претендует на все оперативной памяти - но это довольно странно, потому что я делаю его намного меньше.Вот код:

- (void)viewDidLoad
{ 
    [super viewDidLoad];
    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"bild"] == nil) { 
        picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [self presentModalViewController:picker animated:YES];
    }
}

- (void)imagePickerController:(UIImagePickerController *) Picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    double compressionRatio=1;
    NSData *imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
    while ([imageData length]>5000) { 
        compressionRatio=compressionRatio*0.20;
        imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
    }

    UIImage *yourUIImage;
    yourUIImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];
    [[NSUserDefaults standardUserDefaults] setObject:imageData forKey:@"bild"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [self dismissModalViewControllerAnimated:YES];
}

В этой строке я получаю ошибку SIGABRT imageData = [NSKeyedArchiver archivedDataWithRootObject: yourUIImage];

Следует ли использовать другой метод для изменения размера изображения?Или я должен сохранить его как локальный файл и получать его каждый раз при запуске приложения?(Если это возможно)

Ответы [ 3 ]

6 голосов
/ 31 января 2012

Вы используете NSCoding для архивирования UIImage в объект NSData.
До iOS5 UIImage не реализовывал методы для NSCoding. Вы просто не можете использовать archivedDataWithRootObject: с UIImages до iOS5.
Вот почему вы получаете исключение на iPhone 3G.

Это просто очень обоснованное предположение, потому что я не могу подтвердить это документацией или тестом на устройстве, но вокруг много вопросов и сообщений на форуме, которые спрашивают, как реализовать NSCoding в UIImage.


и весь этот блок кода вообще не вызывается, потому что [info objectForKey:@"bild"] вернет nil. Информационный словарь не содержит объекта для ключевого билда. Документация для UIImagePickerControllerDelegate_Protocol содержит Список действительных ключей

NSData *imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
while ([imageData length]>5000) { 
    compressionRatio=compressionRatio*0.20;
    imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
}

Вы, вероятно, хотите использовать что-то подобное:

NSData *data;
if ([[UIImage class] conformsToProtocol:@protocol(NSCoding)]) {
    // >= iOS5
    data = [NSKeyedArchiver archivedDataWithRootObject:image];
    // save so you know it's an archived UIImage object
}
else {
    // < iOS5
    data = /* your UIImageJPEGRepresentation method but this time with the key UIImagePickerControllerOriginalImage instead of "bild" */
    // save so you know it's raw JPEG data
}
3 голосов
/ 31 января 2012

Edit: Другая ошибка, вероятно, заключается в том, что вы ищете объект для ключа "bild" в информационном словаре, который вы передали из контроллера средства выбора изображений. У него не будет такого ключа. Вы должны передать ключ UIImagePickerControllerOriginalImage, чтобы получить вместо изображения.

-

Ты не выбрасываешь старое imageData. Если ваша проблема заключается в большом потреблении памяти, вам придется покончить с данными изображения, поскольку вы постепенно уменьшаете изображение.

Кроме того, в любом случае изображение может быть слишком большим, чтобы уместиться в пределах 5000 байт. Ваш текущий код не обрабатывает это изящно. Со временем степень сжатия вырастет за пределы 1,0, и в этот момент функция, вероятно, выдаст исключение.

Я бы предложил изменить размер изображения, прежде чем пытаться сильно его сжать.

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

1 голос
/ 31 января 2012

Если SIGABRT постоянно происходит на imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];, то я чувствую, что скорее всего это будет именно эта строка, а не проблема с памятью.

UIImage никогда не использовался для соответствия NSCoding, но текущие документы говорят, что это так. Возможно, что 3G, который будет ограничен iOS 4.2.1, использует несовместимую версию и поэтому вылетает при попытке архивирования, тогда как 4S на iOS 5 использует новую совместимую версию.

Попробуйте добавить категорию для NSCoding в UIImage, а затем повторно запустите на 3G. Пример на http://iphonedevelopment.blogspot.com/2009/03/uiimage-and-nscoding.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...