Можно ли обмениваться изображениями через NSBundles? - PullRequest
0 голосов
/ 20 августа 2011

Извините за неопределенный заголовок вопроса ...

вот мой сценарий:

Я динамически загружаю содержимое UIView из файлов пера, хранящихся в NSBundles

BOOL bundlePathExists = [fm fileExistsAtPath:bundlePath];
if (bundlePathExists) {
    NSBundle *tempBundle = [NSBundle bundleWithPath:bundlePath];

    UIViewController *vc = [[UIViewController alloc] initWithNibName:nibName bundle:tempBundle];

    [self.view addSubview:vc.view];
}

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

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

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

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

[commonImageViewIvar setImage:[UIImage imageWithName:commonImageName]]; 

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

1 Ответ

0 голосов
/ 21 августа 2011

Как и было обещано, вот решение, которое я придумал:

Сами файлы комплекта загружаются, как описано здесь .Чтобы добавить к информации, перечисленной там, я обнаружил, что если вы сначала создаете представления в приложении для iphone, вы можете предварительно просмотреть их в симуляторе.затем вы можете создать новый проект в виде пакета и перетащить ВСЕ файлы изображений и файл xib & .h в новый проект.не перетаскивайте файл .m, так как это создает проблемы при сборке.затем убедитесь, что настройки проекта определяют BASE SDK как «Последний IOS», а не настройку Mac OS X по умолчанию, которая была бы выбрана.затем вы все равно можете отредактировать xib, дважды щелкнув по нему.Любые распространенные файлы можно отменить в сборке, сняв флажок «target» для этого файла.см. «Дополнительная информация» далее в этом посте с ответом.

После того, как я скачал каждый пакет в zip-файле с сервера, я использую следующие методы, которые я кодировал для этой цели:

-(NSArray *) imageFileExtensions {
    return [NSArray arrayWithObjects:@".png",@".gif",@".jpg",@".jpeg",@".bmp",  nil];
}

и

-(void) cloneImageFilesInPath:(NSString *)path toPath:(NSString*)clonePath {

    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *extensions = [self imageFileExtensions];
    if ([fm fileExistsAtPath:path]) {
        NSArray *files = [fm contentsOfDirectoryAtPath:path error:nil];

        for (NSString *file in files){
            for (NSString *ext in extensions) {
                if ([file hasSuffix:ext]) {
                    NSString *targetFile = [clonePath stringByAppendingPathComponent:file];
                    if (![fm fileExistsAtPath:targetFile]) {
                        [fm createSymbolicLinkAtPath:targetFile withDestinationPath:[path  stringByAppendingPathComponent:file] error:nil];
                    }
                    break;
                }
            }

        }
    }

}

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

Они вызываются в моем приложении-делегате следующим образом:

        ...(insert code to unzip the file to bundlePath here)...

        [self cloneImageFilesInPath:[[NSBundle mainBundle] bundlePath] toPath:bundlePath];

Дополнительная информация

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

-(void) removeDuplicatedImageFilesInPath:(NSString *)sourcePath fromTargetPath:(NSString*)path {

    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *extensions = [self imageFileExtensions];
    if ([fm fileExistsAtPath:path]) {
        NSArray *files = [fm contentsOfDirectoryAtPath:sourcePath error:nil];

        for (NSString *file in files){
            for (NSString *ext in extensions) {
                if ([file hasSuffix:ext]) {
                    NSString *targetPath = [path stringByAppendingPathComponent:file];
                    if ([fm fileExistsAtPath:targetPath]) {
                        [fm removeItemAtPath:targetPath error:nil];
                    }
                    break;
                }
            }

        }
    }

}

Дополнительная информация для работы с файлами zip

Я выбрал ObjectiveZip (послепредложение автора здесь . Чтобы упростить задачу, я обернул это в следующие 2 метода делегата приложения (один используется в реальном приложении, другой в автономном приложении создания пакета)

в основном приложении

-(void) unzipArchive:(NSString *)zipFileName toPath:(NSString *)path {
    NSFileManager *fm  = [NSFileManager defaultManager];

    ZipFile *unzipFile = [[ZipFile alloc] initWithFileName:zipFileName mode:ZipFileModeUnzip];

    NSArray *infos= [unzipFile listFileInZipInfos];

    [unzipFile goToFirstFileInZip];
    for (FileInZipInfo *info in infos) {

        ZipReadStream *read1= [unzipFile readCurrentFileInZip];

        NSMutableData *fileData = [[[NSMutableData alloc] initWithLength:info.length] autorelease];
        int bytesRead1 = [read1 readDataWithBuffer:fileData];

        if (bytesRead1 == info.length) {
            NSString *fileName = [path stringByAppendingPathComponent:info.name ];
            NSString *filePath = [fileName stringByDeletingLastPathComponent];

            [fm createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];


            [fileData writeToFile:fileName atomically:YES];

        }

        [read1 finishedReading];        

        [unzipFile goToNextFileInZip];

    }

    [unzipFile close];
    [unzipFile release];


}

и в автономном приложении создания пользовательских пакетов.

-(void) createArchive:(NSString *) zipFileName usingPath:(NSString *)path {
    NSArray *files = [self filesInDirectory:path];
    ZipFile *zipFile= [[ZipFile alloc] initWithFileName:zipFileName mode:ZipFileModeCreate];

    for (NSString *file in files) {

        NSString *fileNameForZip = [file substringFromIndex:path.length];

        ZipWriteStream *stream= [zipFile writeFileInZipWithName:fileNameForZip fileDate:[NSDate dateWithTimeIntervalSinceNow:-86400.0] compressionLevel:ZipCompressionLevelBest];

        [stream writeData:[NSData dataWithContentsOfFile:file]];

        [stream finishedWriting];
    }
    [zipFile close];
    [zipFile release];
}

примечание: предыдущий метод основан на следующих 2 методах, которые создают NSArray, содержащийполный путь ко всем файлам по указанному пути (повторяется в подкаталогах)

-(void)loadFilesInDirectory:(NSString *)path intoArray:(NSMutableArray *)files {
    NSFileManager *fm  = [NSFileManager defaultManager];

    NSMutableArray *fileList = [NSMutableArray arrayWithArray:[fm contentsOfDirectoryAtPath:path error:nil]];
    for (NSString *file in fileList) {
        BOOL isDirectory = NO;
        NSString *filePath = [path stringByAppendingPathComponent:file];
        if ([fm fileExistsAtPath:filePath isDirectory:&isDirectory]) {
            if (isDirectory) {
                [self loadFilesInDirectory:filePath intoArray:files];
            } else {
                [files addObject:filePath];
            };          

        };
    }
}


-(NSArray *)filesInDirectory:(NSString *)path {
    NSMutableArray *files = [NSMutableArray array];
    [self loadFilesInDirectory:path intoArray:files];
    return files;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...