Можно создать категорию для NSString и создать функцию, которая получает формат, массив и возвращает строку с замененными объектами.
@interface NSString (NSArrayFormat)
+ (NSString *)stringWithFormat:(NSString *)format arrayArguments:(NSArray *)arrayArguments;
@end
@implementation NSString (NSArrayFormat)
+ (NSString *)stringWithFormat:(NSString *)format arrayArguments:(NSArray *)arrayArguments {
static NSString *objectSpecifier = @"%@"; // static is redundant because compiler will optimize this string to have same address
NSMutableString *string = [[NSMutableString alloc] init]; // here we'll create the string
NSRange searchRange = NSMakeRange(0, [format length]);
NSRange rangeOfPlaceholder = NSMakeRange(NSNotFound, 0); // variables are declared here because they're needed for NSAsserts
NSUInteger index;
for (index = 0; index < [arrayArguments count]; ++index) {
rangeOfPlaceholder = [format rangeOfString:objectSpecifier options:0 range:searchRange]; // find next object specifier
if (rangeOfPlaceholder.location != NSNotFound) { // if we found one
NSRange substringRange = NSMakeRange(searchRange.location, rangeOfPlaceholder.location - searchRange.location);
NSString *formatSubstring = [format substringWithRange:substringRange];
[string appendString:formatSubstring]; // copy the format from previous specifier up to this one
NSObject *object = [arrayArguments objectAtIndex:index];
NSString *objectDescription = [object description]; // convert object into string
[string appendString:objectDescription];
searchRange.location = rangeOfPlaceholder.location + [objectSpecifier length]; // update the search range in order to minimize search
searchRange.length = [format length] - searchRange.location;
} else {
break;
}
}
if (rangeOfPlaceholder.location != NSNotFound) { // we need to check if format still specifiers
rangeOfPlaceholder = [format rangeOfString:@"%@" options:0 range:searchRange];
}
NSAssert(rangeOfPlaceholder.location == NSNotFound, @"arrayArguments doesn't have enough objects to fill specified format");
NSAssert(index == [arrayArguments count], @"Objects starting with index %lu from arrayArguments have been ignored because there aren't enough object specifiers!", index);
return string;
}
@end
Поскольку NSArray создается во время выполнения, мы не можем предоставлять предупреждения во время компиляции, но мы можем использовать NSAssert, чтобы сообщить нам, равно ли число спецификаторов количеству объектов в массиве.
Создал проект на Github, где можно найти эту категорию. Также добавлена версия Чака с использованием 'stringByReplacingCharactersInRange:' плюс несколько тестов.
Используя миллион объектов в массиве, версия с 'stringByReplacingCharactersInRange:' не очень хорошо масштабируется (подождала около 2 минут, затем закрыла приложение). Используя версию с NSMutableString, функция создала строку примерно за 4 секунды. Тесты проводились с использованием симулятора. Перед использованием тесты должны проводиться на реальном устройстве (используйте устройство с наименьшими характеристиками).
Редактировать: На iPhone 5s версия с NSMutableString занимает 10,471655 с (один миллион объектов); на iPhone 5 занимает 21.304876 с.
rd yourdirname /s/q
Выполняет работу независимо от того, пусты они или нет.
Я не уверен, понял ли я вопрос. Если вы просто хотите удалить дерево, вы можете просто использовать rd / s
. Однако, если вы хотите удалить только пустых каталогов, то вы можете сделать следующее с помощью Cygwin:
find -type d -empty | xargs rmdir
В стандартной ИТ-сборке, в которой я работаю, установлен Cygwin, и я использовал это неоднократно.