Приложение зависает в iOS7, но не в 8 и 9 из-за автоматического выпуска NSDictionary

+ (NSString *)getValueforLocale:(NSString*) i18nkey :(NSString*)locale{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSLog(@"paths are : %@",paths);
    NSString *libraryDirectory = [paths objectAtIndex:0];
    NSLog(@"libraryDirectory : %@",libraryDirectory);
    NSString *filePath = [libraryDirectory stringByAppendingPathComponent:@"I8nDB"];
    filePath = [filePath stringByAppendingPathComponent:locale];
    NSLog(@"file path is : %@",filePath);
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
    if(fileExists)
    {
        NSDictionary *dict = [[[NSDictionary alloc] initWithContentsOfFile:filePath]autorelease];
        NSDictionary *resourceBundle = [[[NSDictionary alloc] init]autorelease];
        NSString *keyValue = [[[NSString alloc]init]autorelease];
        resourceBundle = [dict valueForKey:@"hash"];
        keyValue=[resourceBundle valueForKey:i18nkey];
        NSLog(@"value for %@ is(container) : %@",i18nkey,keyValue);
        if(keyValue != nil || keyValue != NULL)
        {
            return keyValue;
        }
        else
        {
            NSLog(@"key not found in the container file");
            NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
                                                             ofType:@"strings"
                                                        inDirectory:nil
                                                    forLocalization:locale];
            NSLog(@"path for %@ is : %@",locale,path);
            fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
            if(fileExists)
            {
                NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
                NSLog(@"value for %@ is(resources) : %@",i18nkey,[dict objectForKey:i18nkey]);
                return [dict objectForKey:i18nkey];
            }
            else
            {
                return NULL;
            }
        }
    }
    else
    {
        NSLog(@"%@ locale does not exist in container",locale);
        NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
                                                         ofType:@"strings"
                                                    inDirectory:nil
                                                forLocalization:locale];
        NSLog(@"path for %@ in resources is : %@",locale,path);
        fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
        if(fileExists)
        {
            NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
            NSLog(@"value for %@ is : %@",i18nkey,[dict objectForKey:i18nkey]);
            return [dict objectForKey:i18nkey];
        }
        else
        {
            return NULL;
        }
    }
}

Если мы удалим Autorelease из приведенного выше кода, он работает в iOS7, если не происходит сбой приложения

Моя главная проблема заключается в том, почему не происходит сбой в iOS8 и 9, а происходит только сбой в iOS7, есть изменения, связанные с автоматическим выпуском в этих версиях

3 ответа

Почему вы не используете ARC? Тогда вам не понадобится autorelease... См. http://rypress.com/tutorials/objective-c/memory-management

Ваша проблема может быть связана с настройками о ARC.

При ручном подсчете ссылок удержания и выпуски должны быть сбалансированы.

В

NSDictionary *dict = [[[NSDictionary alloc] initWithContentsOfFile:filePath]autorelease];
NSDictionary *resourceBundle = [[[NSDictionary alloc] init]autorelease];

удержания и выпуски сбалансированы, потому что alloc (вместе с retain, new, copy, mutableCopy) возвращает сохраненный экземпляр и autorelease считается как release,

Однако в

NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];

у вас есть перевыпуск, потому что вы autorelease то, что вы не сохранили.

Версия для iOS не имеет к этому никакого отношения.

В вашем коде вы размещаете только словарь

NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];

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

Попробуйте текущий код

+ (NSString *)getValueforLocale:(NSString*) i18nkey :(NSString*)locale
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
        NSLog(@"paths are : %@",paths);
        NSString *libraryDirectory = [paths objectAtIndex:0];
        NSLog(@"libraryDirectory : %@",libraryDirectory);
        NSString *filePath = [libraryDirectory stringByAppendingPathComponent:@"I8nDB"];
        filePath = [filePath stringByAppendingPathComponent:locale];
        NSLog(@"file path is : %@",filePath);
        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
        if(fileExists)
        {
            NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
            //NSDictionary *resourceBundle = [[[NSDictionary alloc] init]autorelease];
            //NSString *keyValue = [[[NSString alloc]init]autorelease];
            NSDictionary *resourceBundle = [dict valueForKey:@"hash"];
            // relese dict here because not use after
            [dict release];
            NSString *keyValue=[resourceBundle valueForKey:i18nkey];
            NSLog(@"value for %@ is(container) : %@",i18nkey,keyValue);
            if(keyValue != nil || keyValue != NULL)
            {
                return keyValue;
            }
            else
            {
                NSLog(@"key not found in the container file");
                NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
                                                                 ofType:@"strings"
                                                            inDirectory:nil
                                                        forLocalization:locale];
                NSLog(@"path for %@ is : %@",locale,path);
                fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
                if(fileExists)
                {
                    // NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
                    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
                    NSLog(@"value for %@ is(resources) : %@",i18nkey,[dict objectForKey:i18nkey]);
                    return [dict objectForKey:i18nkey];
                }
                else
                {
                    return NULL;
                }
            }
        }
        else
        {
            NSLog(@"%@ locale does not exist in container",locale);
            NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
                                                             ofType:@"strings"
                                                        inDirectory:nil
                                                    forLocalization:locale];
            NSLog(@"path for %@ in resources is : %@",locale,path);
            fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
            if(fileExists)
            {
                // NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
                NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
                NSLog(@"value for %@ is : %@",i18nkey,[dict objectForKey:i18nkey]);
                return [dict objectForKey:i18nkey];
            }
            else
            {
                return NULL;
            }
        }
    }
Другие вопросы по тегам