Информация о версии основы для OS X v10.9

Сгенерированный документ: 05.06.2013 11:58:10 - 0700

Copyright © 2013 информации о версии OS X Apple Inc Все права защищены.

OS X 10.9 информации о версии для платформы основы какао

Платформа Основы является библиотекой классов Objective C, обеспечивающих инфраструктуру для основанных на объектах приложений без графических интерфейсов пользователя. Это доступно на OS X и iOS.

Можно найти информацию о версии для Набора Приложения, а также некоторых примечаний по общим проблемам обратной совместимости, обработке версии, и т.д., в Информации о версии Набора Приложения для OS X v10.8.

Эти примечания покрывают многих, но ни в коем случае все изменения в Наборе Основы в OS X 10.9 в семени 2013 года WWDC. Эти примечания, а также базовые изменения, к которым они обращаются, подвергаются для дальнейшего изменения перед заключительным выпуском 10,9.

Некоторые главные темы покрыли в этом документе:

NSXPCConnection

В OS X 10.8 Пум, если ошибка программиста вызвала исключение, когда сообщение получено на соединении, было бы отброшено сообщение, и никакие дальнейшие меры не будут предприняты. С OS X 10.9, NSXPCConnection также автоматически лишит законной силы соединение. Это гарантирует, что обработчик ошибок будет вызван на сторону вызова с ‘соединением, прерванное’ или ‘соединение лишило законной силы’ ошибку.

Производительность CPU и памяти отправки больших объемов данных по NSXPCConnection значительно увеличена.

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

NSKeyedArchiver

В предыдущих выпусках, архивируя строку с точным содержанием «$null» заставил бы его быть разархивированным как нулевой объект. Архивы с этой строкой, создаваемой на OS X 10.9, разархивируют правильно на OS X 10.9 и предыдущие выпуски.

NSKeyedArchiver поддерживает функцию NSSecureCoding, добавленную в OS X 10.8 Пум. Поддержка доступна на OS X 10.8 Пум и позже. Для использования безопасного кодирования создайте экземпляр NSKeyedUnarchiver или NSKeyedArchiver и используйте новый метод. Этот пример кода предполагает, что включен ARC.

NSString *myString = @"Hello world";
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver setRequiresSecureCoding:YES];
[archiver encodeObject:myString forKey:@"MyKey"];
[archiver finishEncoding];
 
// ...
 
NSData *dataToUnarchive = ...;
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:dataToUnarchive];
[unarchiver setRequiresSecureCoding:YES];
NSString *decodedString = [unarchiver decodeObjectOfClass:[NSString class] forKey:@"MyKey”];

Если класс декодируемого объекта не является NSString или подклассом NSString, то decodeObjectOfClass:forKey: метод будет выданный исключение.

В OS X 10.9, Основа экспортирует новый ключ: NSKeyedArchiveRootObjectKey. Это - корневой ключ, используемый для архивов, создаваемых с существующим методом NSKeyedArchiver +archivedDataWithRootObject: на всех предыдущих выпусках.

NSBundle

Несмотря на то, что документация позволяет NSBundle, и CFBundle для вставки новых ключей в Info.plist пакета, делая так привел к общему катастрофическому отказу, когда словарь Info.plist был считан на одном потоке и изменен на другом. NSBundle и CFBundle больше не будут устанавливать дополнительных ключей в словаре Info.plist, и приложения высоко отговорены пытаться изменить словарь Info.plist, возвращенный из-infoDictionary метода.

NSOperation и NSOperationQueue

Производительность-addOperationWithBlock:-addOperation: стартовое выполнение операций и стартовое выполнение блоков завершения значительно быстрее.

NSUserNotification

Вызов-removeDeliveredNotification: и-removeAllDeliveredNotifications: теперь удалит выведенные на экран уведомления.

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

NSUserNotification имеет новое свойство для указания изображения, показанного в содержании уведомления.

NSUserNotification допускает 'быстрый ответ'. Свойство responsePlaceholder может использоваться для установки строки заполнителя, и ответ может быть получен от свойства ответа.

Дремота приложения

Дремота приложения является новой функцией в OS X 10.9, который фокусирует системные ресурсы как CPU, I/O и энергия батареи на наиболее важной работе, сделанной для пользователя. Система использует эвристику для определения, когда приложение выполняет важную работу, и когда работа, которую это выполняет, не критически важна. Эта эвристика включает (но не ограничиваются): видимость на экране, таща действие, обработку событий, воспроизведение аудио, передний план по сравнению с фоном и тип приложения.

Когда приложение переходит к режиму дремоты приложения, система применяет до трех видов эффектов: приоритетное понижение CPU, приоритетное понижение I/O и регулировка таймера. Приоритетное понижение CPU подаст заявку более низкий приоритет, чем другие приложения, но не настолько низко как большинство системных демонов. Приоритетное понижение I/O позволит I/O продолжаться максимально быстро, но позволяет высокому приоритету I/O для движения сначала. Это разработано для улучшения скорости отклика в приоритетных приложениях, с которыми активно взаимодействует пользователь. Регулировка таймера сократит частоту большинства видов таймеров в приложении. Когда приложение выполняет частую ненужную работу, это совместное воздействие обеспечивает значительное увеличение во время работы от батареи.

Когда каждое приложение в их системе выполняет как можно меньше работы, самое большое преимущество пользователю прибывает. Поэтому Дремота Приложения является функцией уклонения. Пользователь может выбрать приложение из Дремоты Приложения вручную с флажком в области «Get Info..» Средства поиска. Разработчики могут временно отказаться от участия в приложении путем заключения в скобки инициируемых пользователями действий с новым NSProcessInfo API. Рассмотрите использование питания своего приложения прежде, чем выбрать из Дремоты Приложения.

Дремота приложения - пользовательские действия

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

Новый API имеет две формы. Первая форма является начать/закончить соединением. Вызовите - [NSProcessInfo beginActivityWithOptions:reason:] то, когда Ваше приложение начинает пользователя, инициировало действие. Возвращенный объект должен, тогда передал в - [NSProcessInfo endActivity:], когда закончено действие.

Вторая форма основана на блоке: - [NSProcessInfo performActivityWithOptions:reason:block:]. С этим API Вы указываете вид действия и выполняете работу в блоке. Метод выполнит блок синхронно и автоматически начнет и закончит действие вокруг блока.

Параметр опций описывает вид действия, которое выполняет Ваше приложение. Если работа является инициируемым пользователем, используйте NSActivityUserInitiated. Если работа является фоном, или другая работа по техобслуживанию тогда используют NSActivityBackground. Опции могут также использоваться, чтобы препятствовать тому, чтобы система ввела неактивный системный сон или неактивный сон дисплея с константами NSActivityIdleSystemSleepDisabled и NSActivityIdleDisplaySleepDisabled. Если Ваше приложение выполняет инициируемую работу пользователя, которая не должна препятствовать системе неактивный сон, затем использовать NSActivityUserInitiated. Необходимо стараться выбрать правильный вид действия любое время, Вы используете новый API. Препятствование тому, чтобы компьютер бездействовал и заснул, может привести к пустой батарее.

Инициируемые действия пользователя должны быть ограничены для работы явно запущенные пользователем. Примеры включают файлы экспорта или запись аудио. Инициируемые в приложение действия как выполнение обслуживания не должны или использовать этот API или использовать тип NSActivityBackground. Существует новый API в XPC для выполнения действий регулярного техобслуживания в более подходящее время (как, когда соединено с питанием A/C). См. <xpc/activity.h>.

Дремота приложения - отладка

Существует много новых инструментов, доступных в системе для исследования первопричины неожиданной разрядки батареи. XCode теперь включает представление энергетического использования при запуске приложения. Монитор действия включает новый столбец, показывающий, находится ли Ваше приложение в Дремоте Приложения или не плюс синтезируемый “счет питания”, указывающий полное использование питания Вашего приложения. Дополнительное меню батареи теперь сообщит о приложениях с помощью чрезмерной суммы питания. Новый инструмент командной строки timerfires (“человек timerfires” для получения дополнительной информации) может использоваться для исследования, какие таймеры приложение запланировало.

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

Допуск таймера

Теперь возможно сообщить системе о потенциальном «допуске» для объектов CFRunLoopTimerRef или NSTimer. Допуск является допустимой задержкой после запланированной даты огня таймера. Например, таймер является установкой с датой огня 5 секунд с этого времени, повторяясь каждые 7 секунд, и с допуском 3 секунд. Таймер может тогда запустить между временами 5 - 8 с, 12 к 15, 19 к 22, 26 к 29, и т.д.

Добавление допуска позволяет системе планировать таймеры значительно большим количеством благоприятного для питания способа. Большинству таймеров нужно установить допуск. Значение по крайней мере 10% интервала рекомендуется, но точное значение будет специализировано.

Исправления ошибок в обмене сообщениями NSFilePresenter

Координация файла позволяет Вам регистрировать NSFilePresenter для любого файла или каталога, даже одна внутренняя часть пакет файла. Например, когда Вы дважды щелкаете по встроенному изображению в TextEdit для открытия его в Предварительном просмотре, Предварительный просмотр регистрирует NSFilePresenter для файла образа, который является в пакете TextEdit .rtfd файла. В этом примере Вы могли бы ожидать что, когда TextEdit делает скоординированную запись пакета файла в целом, который это делает во время сохранения документа, что NSFilePresenter Предварительного просмотра был бы отправлен-relinquishPresentedItemToWriter:. Начиная с введения координации файла в Mac OS 10.7 это не имело место. Эта ошибка была исправлена в Mac OS 10.9.

Когда вызов обработчика завершения передал-savePresentedItemChangesWithCompletionHandler, NSFilePresenter может сигнализировать ошибку: или-accommodatePresentedItemDeletionWithCompletionHandler:. Так как введение координации файла в Mac OS 10.7, однако, делая так часто заставляло бы координацию файла не вызывать блок повторного приобретения, предоставленный Вашим NSFilePresenter в его ответе на предыдущий вызов-relinquishPresentedItemToReader: или-relinquishPresentedItemToWriter: для того же скоординированного чтения или записи. Эта ошибка была исправлена в Mac OS 10.9. Теперь блоки повторного приобретения Вашего NSFilePresenter всегда вызываются, даже когда Ваш NSFilePresenter сигнализировал отказ сохранить изменения или разместить удаление.

Исправление ошибки в Key Value Observing (KVO)

Mac OS 10.8 и ранее имел ошибку, в которой KVO мог отправить-observeValueForKeyPath:ofObject:change:context: наблюдателю после того, как это больше не был наблюдатель, и в некоторых случаях даже после того, как наблюдатель был освобожден. Например, если бы объект имел многократных наблюдателей ключевых путей и реализацию-observeValueForKeyPath:ofObject:change:context, это могло произойти: для одного наблюдателя, опробованного удаленному из других наблюдателей. Удаление не вступило бы в силу сразу достаточно для предотвращения обмена сообщениями зомби другого наблюдателя. Это было возможно, даже когда всего был включен один поток. Эта ошибка была исправлена в Mac OS 10.9.

Создание отчетов прогресса и отмена

Mac OS 10.9 включает новый механизм для создания отчетов прогресса. Это позволяет код, выполняющий работу, чтобы сообщить, что прогресс той работы и код пользовательского интерфейса замечают, что прогресс так прогресс может быть представлен пользователю. В частности это может использоваться, чтобы показать пользователю индикатор выполнения и объяснительный текст, оба обновленные должным образом, поскольку сделаны успехи. Это также позволяет работе быть отмененной или приостановленной пользователем. Этот механизм принимает форму нового класса в платформе Основы под названием NSProgress. Некоторые цели проекта этого класса были:

• Слабая связь. Код, выполняющий работу, может сообщить о прогрессе той работы независимо от того, что наблюдает его, или даже наблюдается ли это вообще. До меньшего градуса код, наблюдающий прогресс и представляющий его пользователю, не должен составлять, как структурирован код, выполняющий работу. Большая часть этой цели достигается просто, там будучи единственным классом NSProgress, который может использоваться большим разнообразием генераторов отчетов прогресса и наблюдателей.

• Composability. Код, выполняющий работу, может сообщить о прогрессе, не принимая во внимание, является ли та работа фактически просто частью большей работы, общий прогресс которой - то, что действительно интересно пользователю. С этой целью каждый NSProgress может иметь родителя-одиночку и многократные дочерние элементы. NSProgress представление общего прогресса работы, это интересно пользователю обычно, не имеет никакого родителя. Если существуют подоперации тогда, их прогресс представлен ребенком Нспрогрессесом. Отчеты сделанных успехов распространяют к родителям. Запросы на отмену распространяют дочерним элементам. Подразделение прогресса в дерево НСПРОГРЕССЕСА представляет некоторую концептуальную сложность классу, но это также включает повторное использование решений проблем как то, как прогресс работы, выполняемой разрозненными частями кода, должен использоваться для вычисления одного полного числа прогресса, которое стоит представить пользователю. Например, посмотрите - [NSProgress fractionCompleted], возвращающий значение, принимающее во внимание и получатель и его дочерние элементы.

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

• Удобство пользования. Для класса, чтобы быть допускающим повторное использование это должно быть применимо во-первых. Во многих случаях существенное препятствие использованию NSProgress устроило бы код, выполняющий работу для нахождения точного экземпляра NSProgress, который это должно использовать для создания отчетов о его прогрессе. Размер этого препятствия зависит от многих вещей, как то, насколько многоуровневый Ваш код (необходимо ли было бы передать NSProgress как параметр через многие уровни функций и методов?), как это уже используется многократными проектами (можно даже добавить параметры NSProgress, не повреждая вещи?), как это разделено между платформой и кодом приложения (делает всю эту поставку кода одновременно?) И т.д. Для помощи Вы преодолеть это препятствие существуете понятие текущего прогресса, который является экземпляром NSProgress, который должен использоваться для создания отчетов о прогрессе, когда существует не очевидная другая опция. Посмотрите - [NSProgress currentProgress]. Вы не должны использовать его в ситуациях, куда можно просто передать NSProgress в другом, более явном, путь, но часто это будет самый простой путь к генераторам отчетов прогресса и наблюдателям для нахождения друг друга. Например, можно ожидать, что, поскольку само Какао поправляется при создании отчетов о прогрессе код заметит, что прогресс путем установки текущего прогресса прежде, чем вызов методы Cocoa, выполняющие работу. (Не имеет значения, будет ли работа выполнена асинхронно и не будет завершена, когда возвратится вызываемый метод.) Аналогично, поскольку Какао поправляется при наблюдении прогресса и представлении его пользователю для Вас, Ваш код наиболее вероятно использует в своих интересах это путем создания одного или более дочерних элементов текущего прогресса и использования их.

Можно смотреть <Foundation/NSProgress.h> для получения дальнейшей информации о том, что NSProgress делает, но здесь является некоторой основной информацией об использовании его.

Создание отчетов о прогрессе

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

- (BOOL)readFromData:(NSData *)data error:(NSError **)outError {
 
  // If there is already current progress, make a child of it to report progress about the part of the work
       that's being done by this method. In this example we simply use "bytes of input" as the unit of
       progress.
  NSUInteger length = [data length];
  NSProgress *progress = [NSProgress
    progressWithTotalUnitCount:length];
 
  // A loop that does something with each byte of data.
  NSError *error = nil;
  for (NSUInteger index = 0; index<length; index++) {
 
    // For the most part cancellation is just another kind of error to Cocoa. In real code there might
            be some cleanup to do here, but it should be just more of the same thing that you would do
            after any kind of error.
    if ([progress isCancelled]) {
      error = [NSError errorWithDomain:NSCocoaErrorDomain
        code:NSUserCancelledError userInfo:nil];
      break;
    }
 
    // Do some work with each byte. This code also might set the error to something, clean up, and
            break out of the loop.
    […]
 
    // Report progress. Do you see why we add one to the index?
    [progress setCompletedUnitCount:(index + 1)];
 
  }
 
  // Finish up the error handling.
  if (error && outError) {
    *outError = error;
  }
  return error ? NO : YES;
 
}

Наблюдение прогресса

По большей части наблюдение прогресса означает создавать NSProgress и добавлять наблюдателей значения ключа свойств как «неопределенный», «fractionCompleted», и «localizedDescription» к нему. На OS X Вы часто будете в состоянии сделать это Какао использования Привязка. Можно также использовать Привязку Какао для снятия трубки Кнопки отмены так, чтобы - [Отмена NSProgress] была вызвана, когда она нажимается.

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

- (void)openFromFileAtURL:(NSURL *)url{
 
    // This is a method for some sort of controller object that reads model objects from a file, presenting a
             progress panel if that takes too long, and presenting an error panel if that fails.
 
    // The progress panel that might be presented has AppKit controls that are bound to properties of this
             object like "progress.localizedDescription", "progress.indeterminate",
             "progress.fractionCompleted" and, for whether the Cancel button is enabled,
             "progress.cancellable". The total unit count we use for this operation is arbitrary. What matters is
             that the counts of units we attribute to suboperations add up to it.
    _progress = [NSProgress progressWithTotalUnitCount:10];
 
    // Set properties like the localizedDescription of the NSProgress so they appear in the progress panel,
             if one is presented.
    […]
 
    // Set a timer that will present the progress panel if it goes off before the work is done. You don't want
             to present a progress panel immediately because if the work gets done instantaneously then the user
             will see a big flicker. A delay of a second is good.
    […]
 
    // You didn't really think we were going to show you how to block the main thread, did you? Our
             progress panel wouldn't even redraw or let you hit the Cancel button if we did that.
    [_concurrentQueue addOperationWithBlock:^(void) {
 
        // To take advantage of NSData's progress reporting, which will matter if the file is large
                       enough or slow enough to open, make our progress the current one before we ask NSData to
                       read the file. NSData will add a child NSProgress and report its reading progress through
                       that. After a little bit of theoretical experimentation, we theoretically determined that in this
                       example it's reasonable to call the actual reading of the file 20% of the work, and the parsing
                       of the file and the creation of objects from it the other 80%. Some files, like those on network
                       drives, take longer to read than others though. This is not an exact science.
        NSError *error = nil;
        BOOL didRead = NO;
        [_progress becomeCurrentWithPendingUnitCount:2];
        NSData *data = [NSData dataWithContentsOfURL:url options:0
            error:&error];
        [_progress resignCurrent];
        if (data) {
 
            // Once Apple adds progress reporting to NSData we're not likely to remove it, but there
                                are lots of cases where you won't know for sure whether the code you're invoking
                                actually does progress reporting. It's a good idea to record the completion of work even
                                when its progress was probably already reported with a child NSProgress, in case the
                                child NSProgress somehow didn't happen after all.
            [_progress setCompletedUnitCount:2];
 
            // -readFromData:error:, shown above in "Reporting Progress," does 80% of the work
                                here but its progress reporting is reusable in situations where it's some other fraction of
                                the work. This sort of thing is a much bigger deal when the code involved is spread all
                                over a large code base built for reusability.
            [_progress becomeCurrentWithPendingUnitCount:8];
            didRead = [self readFromData:data error:&error];
            [_progress resignCurrent];
            if (didRead) {
 
                // Done. 8 + 2 = 10.
                [_progress setCompletedUnitCount:10];
 
            }
 
        }
 
        // Get back on the main thread to do whatever it is this app does with the objects it just created.
        [[NSOperationQueue mainQueue] addOperationWithBlock:^(void) {
 
            // Success or failure, if our progress panel was presented then tear it down, and clean up.
            […]
            _progress = nil;
 
            // Success or failure?
            if (didRead) {
 
                // Do what we do.
                […]
 
            } else {
 
                // You never have to tell the user they hit the Cancel button! AppKit's error
                                          presentation methods in NSResponder and its subclasses take care of not doing
                                          that for you, but we're not using one of those here.
                BOOL errorIsCocoa = [[error domain]
                    isEqualToString:NSCocoaErrorDomain];
                if (!(errorIsCocoa &&
                    [error code]==NSUserCancelledError)) {
                    [self presentError:error];
                }
 
            }
 
        }];
 
    }];
 
}

Создание отчетов о прогрессе к другим процессам

Существует ряд причин, почему процесс мог бы потребовать прогресса работы, которую это выполняет, чтобы быть представленным другим процессом. Всего для одного примера, в Mac OS 10.9, когда Safari загружает файл, прогресс той загрузки представлен Средством поиска, на значке файла, и Прикреплением, на содержании элемента Прикрепления папки. Для создания такой вещи, возможные экземпляры NSProgress могут быть опубликованы. Посмотрите - публикуют и-unpublish методы.

Наблюдение прогресса других процессов

Процесс, который может представить успехи, сделанные другими процессами, должен обнаружить, что успехи даже делаются во-первых. Продолжая пример Средства поиска и Прикрепления, подписывающегося для обнаружения, что происходит с файлами, посмотрите +addSubscriberForFileURL:withPublishingHandler: и +removeSubscriber: методы.

Локализованный текст в межпроцессном прогрессе

Не каждый процесс в рабочей системе OS X обязательно работает с той же локализацией, таким образом, заботу нужно соблюдать, что текст о прогрессе локализуется в процессе, который представит его пользователю. Для создания этого выполнимым NSProgress инкапсулирует создание текста прогресса для представления пользователю. Посмотрите localizedDescription, localizedAdditionalDescrption, и добрые свойства.

NSProgresses имеют пользовательские информационные словари

NSProgress следует за образцом, установленным NSError, в котором весь локализованный текст, сгенерированный платформой Основы, получен, по крайней мере частично, от значений, найденных в пользовательском информационном словаре, присоединенном к каждому экземпляру. Посмотрите пользовательские информационные ключи как NSProgressFileOperationKindKey. Записи в пользовательском информационном словаре также влияют, как NSProgress публикуется, поэтому посмотрите NSProgressFileURLKey, например, также.

Можно поместить записи в пользовательский информационный словарь NSPROGRES в собственных целях. Если значения будут объектами списка свойств тогда, то они будут сохранены, когда NSProgress, опубликованный одним процессом, будет наблюдаться другим.

NSURL

Схема URL «файла» определяется так, чтобы никакие полномочия, пустой узел и «localhost» все среднее значение машина конечного пользователя. Для сокращения использования памяти файл, объекты URL, создаваемые с путями файловой системы или от представления файловой системы больше, не включают строку узла «localhost».

Это изменение также означает - узел больше не возвращает строку «localhost» для файла URLs и вместо этого возвратит ноль.

- initFileURLWithFileSystemRepresentation:isDirectory:relativeToURL: +fileURLWithFileSystemRepresentation:isDirectory:relativeToURL:-getfilesystemrepresentation:maxlength:. и-fileSystemRepresentation были добавлены для разрешения простого преобразования от представления файловой системы до URL и URL к представлению файловой системы.

- removeCachedResourceValueForKey: и-removeAllCachedResourceValues были добавлены для разрешения удаления кэшируемых значений ресурса от объекта URL.-setTemporaryResourceValue:forKey: обеспечивает способ установить временные значения ресурса на объекте URL.

Объекты URL создали из строк URL, где длина строки URL равнялась точно 1, больше не может создаваться с символами, не позволенными в строках URL. Это изменение влияет на CFURLCreateWithString CFURL (), и методы NSURL-initWithString:-initWithString:relativeToURL: +URLWithString: и +URLWithString:relativeToURL:.

Добавленный-stringByAddingPercentEncodingWithAllowedCharacters: и-stringByRemovingPercentEncoding.-stringByAddingPercentEncodingWithAllowedCharacters: предназначается к проценту - кодируют компонент URL или строку субкомпонента, НЕ всю строку URL. Предопределенные наборы NSCharacters, возвращенные +URLUserAllowedCharacterSet, +URLPasswordAllowedCharacterSet, +URLHostAllowedCharacterSet, +URLPathAllowedCharacterSet, +URLQueryAllowedCharacterSet, и +URLFragmentAllowedCharacterSet, предназначаются, чтобы быть переданными-stringByAddingPercentEncodingWithAllowedCharacters:.

Если данные URL являются очень большими, описания длинного URLs со схемой данных могут быть усеченными.

NSURLComponents

NSURLComponents является новым классом, инкапсулирующим компоненты URL объектно-ориентированным способом. Когда NSURLComponents создается из NSURL или строки URL, он обеспечивает IETF STD 66 (rfc3986) парсинг строки URL. Когда это используется для создания NSURL путем обеспечения компонентов и субкомпонентов, составляющих URL (схема, узел, порт, путь, запросите и т.д.), URL создается с помощью IETF STD 66 (rfc3986) правила. NSURLComponents упрощает правильно анализировать существующий NSURL или строку URL, упрощает создавать правильно сформированный NSURL из компонентов URL и упрощает создавать новый NSURL из существующего URL с модификациями.

Пользовательский NSData Deallocator для буферов без Копий

NSData долго предоставлял возможность для создания экземпляров, использующих буфер, предоставленный Вами, вместо того, чтобы копировать его содержание во внутренне создаваемый буфер. APIs, чтобы сделать это - [NSData initWithBytesNoCopy:length:] и - [NSData initWithBytesNoCopy:length:freeWhenDone:]. Одно ограничение этого APIs - то, что, если Вы хотите задержать освобождение буфера без копий к экземпляру NSData, тогда необходимо использовать malloc (3) (или тот, если его варианты), потому что NSData будет использовать свободный (3).

Для устранения этого ограничения NSData добавил API В OS X 10.9, который позволяет Вам указывать пользовательский метод освобождения через блочный параметр. Тот API - [NSData initWithBytesNoCopy:length:deallocator:].

Существуют некоторые важные вещи знать при использовании этого API. NSData, при необходимости, скопирует блок deallocator на «кучу». Как побочный продукт, любой Objective C возражает указателям, полученным в том блоке, будет сохранен. Во избежание любого непреднамеренного сохраняют циклы, необходимо избежать получать указатели на любые объекты, которые могут поочередно сохранить объект NSData, включая прямые ссылки на сам и неявные через ссылку переменной экземпляра. Для помощи в этом блок deallocator имеет два параметра, указатель буфера его длина. Необходимо всегда использовать эти значения вместо того, чтобы пытаться использовать ссылки извне блока.

NSData API для кодировки Base 64 и декодирования

NSData добавил API в OS X 10.9 для кодирования и декодирования Основы 64. Алгоритм кодирования может быть сконфигурирован для автоматической вставки разрывов строки с настраиваемыми конечными символами строки. Алгоритм декодирования по умолчанию отклонит весь ввод, если это встретится с какой-либо неосновой 64 символа (включая пробел), но существует опция, доступная для создания его более снисходительным. В зависимости от Ваших потребностей можно использовать один из двух вариантов кодирования и декодирования методов. Одна парная Основа использования 64 закодировала Нсстрингса, и другая Основа использования 64 закодировала NSDatas.

Если Ваше приложение должно предназначаться для операционной системы до OS X 10.9, можно использовать-initWithBase64Encoding NSDATA: и-base64Encoding вместо этого. Эти методы существовали начиная с OS X 10.6, но не были представлены до OS X 10.9. Эти методы ведут себя как новые методы, кроме-initWithBase64Encoding: проигнорирует неизвестные символы. Когда Ваше приложение больше не должно предназначаться для операционной системы до OS X 10.9, необходимо перейти к новым методам.

Потокобезопасность NSPurgeableData

До OS X 10.9, NSPurgeableData не был полностью ориентирован на многопотоковое исполнение. Если многократные потоки должны были вызвать определенные методы NSPurgeableData одновременно, исключение или катастрофический отказ могли закончиться. Это было разрешено на OS X 10.9.

NSString-stringByAppendingPathExtension: изменение поведения

До OS X 10.9, если получатель-stringByAppendingPathExtension NSSTRING: метод запустил с тильды (~) символ, метод тихо не добавит расширение и возвратит неизмененную строку. Это поведение было изменено для приложений, соединенных против 10,9 SDK, чтобы позволить этому методу вести себя как ожидалось для относительных путей дома (например, «~/user/path/to/file») и терминальные имена файлов (например, «~tempfile»).

Фиксированная ошибка NSFileProtectionKey

До iOS 7.0, когда устройство было заблокировано, - [NSFileManager attributesOfItemAtPath:error:] возвратил бы словарь без NSFileProtectionKey. Это было закреплено на iOS 7.0 так, чтобы возвращенный словарь сообщил о надлежащем значении NSFileProtectionKey.

Фиксированная ошибка метода делегата NSFileManager

До OS X 10.9, делегируйте реализации метода NSFileManagerDelegate-fileManager:shouldProceedAfterError:removingItemAtURL: никогда не вызывался бы. Это было закреплено на OS X 10.9. Для работы вокруг проблемы можно использовать-fileManager:shouldProceedAfterError:removingItemAtPath: метод вместо этого. Если реализовано, тот метод будет вызван независимо от того, вызвали ли Вы-removeItemAtPath:error: или-removeItemAtURL:error:.

NSData +dataWithData: изменение поведения

До OS X 10.9, это было возможно для - [NSData dataWithData:] для возврата нового экземпляра NSData, даже когда получатель был неизменным. В OS X 10.9, этот метод может начать возвращать тот же указатель как получатель (с сохранять постепенно увеличенное количество) для предотвращения ненужного выделения памяти. Это возможно, потому что неизменность NSDATA применяется к и своему указателю 'байтов' и содержанию указанного буфер.

В редких сценариях изменение, описанное выше, может вызвать неожиданное поведение для объектов NSData, создаваемых с одним из инициализаторов «NoCopy». Так как новый экземпляр NSData не создается, и буфер не копируется, изменения в буфере одного NSData могут неожиданно влиять на чей-либо. Для предотвращения этого необходимо гарантировать, чтобы Вы никогда не изменяли буфер после передачи его к одному из инициализаторов NSDATA «NoCopy», даже если NSData не ответственен за освобождение того буфера.

Если необходимо создать NSData, содержащий копию буфера существующего NSDATA, можно сделать что-то как [NSData dataWithBytes: [байты otherData] длина: [длина otherData]].

NSUserDefaults поддерживают для Security Application Groups (Игра в песочнице)

Для приложений, которые являются частью Security Application Group, NSUserDefaults «комплект» APIs (-initWithSuiteName:-addSuiteNamed: и-removeSuiteNamed:) будет воздействовать на комплект, совместно использованный приложениями в группе и сохраненный в контейнере группы, если идентификатор комплекта будет идентификатором группы.

Изменения в ключах «совместимости» NSUserDefaults

устаревшие (deprecated) постоянные пользовательские ключи значений по умолчанию у основания NSUserDefaults.h больше не функциональны в приложениях, созданных с 10.9 или более поздним SDK.

Повышенный уровень безопасности значений NSUserDefaults

Проверка, оценивающая набор в NSUserDefaults, является допустимыми типами Списка свойств, был сделан более полным, и проще отладить. Крешлоги от того, чтобы не удаваться сделать это будет теперь включать дополнительную информацию, отмечающую проблему.

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

Бессмысленные параметры к методам «Комплекта» на NSUserDefaults будут теперь отклонены с зарегистрированным сообщением. В настоящее время отклоненными случаями является NSGlobalDomain и идентификатор пакета основного пакета.

- [NSUserDefaults синхронизируются] и домены «не текущее приложение»

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

- [NSUserDefaults синхронизируются], не обычно полезно

Необходимо только должны быть вызвать - синхронизируются, если отдельное приложение будет читать значение по умолчанию, которое Вы просто устанавливаете, или если завершается процесс, не использующий AppKit. В большинстве приложений никогда не должен происходить ни один из них, и - синхронизируются, не должен быть вызван. Обратите внимание на то, что до Mac OS X 10.8.4 была ошибка, заставившая AppKit автоматически синхронизироваться немного преждевременно во время завершения приложения, таким образом, не мог бы быть сохранен предпочтительный набор в ответ на закрытие окон, в то время как приложение завершается; это было фиксировано.

dispatch_data_t-> образование моста NSData

В 64-разрядных приложениях с помощью или руководства сохраняют/выпускают или ARC, dispatch_data_t может теперь быть свободно брошен к NSData *, хотя не наоборот. Обратите внимание на то, что одна импликация этого - то, что объекты NSData, создаваемые Какао, могут теперь содержать несколько несмежных частей данных. Можно эффективно работать с несмежными диапазонами данных при помощи нового

- (void) enumerateByteRangesUsingBlock:(void (^)(const void *bytes, NSRange byteRange, BOOL *stop))block

API на NSData. Это будет примерно той же скоростью как - байты на непрерывном NSData, но избежит выделения и копирования для несмежного. Как только несмежный NSData уплотнен к непрерывному (обычно путем вызова - байты, другой API NSData сделает несмежные доступы), будущие доступы к непрерывной области не потребуют дополнительного копирования.

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

Пустые объекты NSData

Неизменные объекты NSData с длиной нуля - теперь весь отдельный объект. Это не должно иметь значения для большинства приложений, но доверия == оператор или методы как-indexOfObjectIdenticalTo: различать пустые объекты данных больше не будет работать.

Неизменные объекты NSData могут быть vm-backed

Запускаясь в 10,9, NSData может принять решение выделить свое запоминающее устройство с vm_allocate, а не malloc. Это не должно влиять на поведение вообще, но может быть полезно для знания при исследовании программы с инструментами анализа памяти (vmmap, Инструменты, и т.д. …). Это также означает, что передача объектов NSData по NSXPCConnection может повторно отобразить страницы вместо того, чтобы копировать их, которые могут улучшить производительность.

NSData - копия,-copyWithZone: и-initWithData:

Методы, создающие копии NSData, были улучшены, чтобы просто сохранить, если безопасно сделать так в большем количестве случаев. Это не должно иметь значения для большинства приложений, но доверия == оператор или методы как-indexOfObjectIdenticalTo: различать скопированные объекты данных, менее вероятно, будет работать, чем в прошлом.

plutil (1) редактирование plist

plutil (1) имеет четыре дополнительных глагола: вставьте, замените, извлеките и удалите, который может использоваться для управления plist файлами. Выполненный 'plutil - помогают' для получения дополнительной информации.

значения по умолчанию (1) дополнения для контакта с произвольными plist файлами

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

Производительность NSCalendar и потокобезопасность

До 10,9, NSCalendar не был ориентирован на многопотоковое исполнение, который потребовал +currentCalendar и-copy/-copyWithZone: методы для создания трудоемких полных копий. Это было улучшено так, чтобы дорогие операции копии были задержаны, пока объект не видоизменен. Если можно избежать вызывать методы установщика для экземпляров NSCalendar, Вы, вероятно, получите лучшую производительность.

Производительность NSTask и потокобезопасность

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

NSDateFormatter и потокобезопасность NSNumberFormatter

Когда установлено в современное поведение средства форматирования (NSNumberFormatterBehavior10_4), экземпляры NSNumberFormatter теперь ориентированы на многопотоковое исполнение. Когда установлено в современное поведение средства форматирования и использование нехрупкого ABI (приложения на 64 бита, на OSX), экземпляры NSDateFormatter также ориентированы на многопотоковое исполнение.

NSNetServices

Новое includesPeerToPeer свойство было добавлено к NSNetService и NSNetServiceBrowser для включения Добрый день открытия и связи по одноранговому Wi-Fi и Bluetooth.

Новая  опция NSNetServiceListenForConnections была добавлена к -publishWithOptions: это позволяет опубликованному NSNetService прислушиваться к входящим соединениям TCP. Новые соединения поставлены в форме NSStreams через новый -netService:didAcceptConnectionWithInputStream:outputStream: метод делегата.

NSURLSession

NSURLSession является заменой API для NSURLConnection. Это поддерживает загрузки из процесса и загрузки, уведомляющие Ваше приложение относительно завершения.  Кроме того, это обеспечивает новый способ сконфигурировать Ваши сетевые запросы (NSURLRequest) так, чтобы они не конфликтовали с другим сетевым кодом в Вашем приложении.

NSURLCredential

Используйте новый  флаг политики персистентности NSURLCredentialPersistenceSynchronizable для синхронизации учетных данных через устройства через iCloud.

Новое - [NSURLCredentialStorage removeCredential:forProtectionSpace:options:] API может использоваться для удаления учетных данных, имеющих политику персистентности NSURLCredentialPersistenceSynchronizable. Если переданный в объекте NSURLCredential будет иметь политику персистентности NSURLCredentialPersistenceSynchronizable, и если словарь опций будет присутствовать и будет включать набор ключей NSURLCredentialStorageRemoveSynchronizableCredentials в то ДА, удалять попытается удалить учетные данные из iCloud, который приведет к учетным данным, удаляемым из всех синхронизируемых устройств. Если переданный в объекте NSURLCredential будет иметь политику персистентности NSURLCredentialPersistenceSynchronizable, и никакой словарь опций не предоставлен, или NSURLCredentialStorageRemoveSynchronizableCredentials действительно существует, но установлен в нет, то вызов перестанет работать. Передача в NSURLCredential с политикой персистентности кроме NSURLCredentialPersistenceSynchronizable совпадает с вызовом существующего - [NSURLCredentialStorage removeCredential:forProtectionSpace:] метод.

NSPredicate, NSExpression и NSSortDescriptor

NSPredicate, NSExpression и NSSortDescriptor теперь поддерживают NSSecureCoding.

В то время как безопасно разархивировать эти объекты использование NSSecureCoding, не безопасно вслепую оценить что-либо, что Вы выходите из архива, и как таковой, оценка надежно декодируемых объектов будет отключена. Любой процесс, получающий predicates/expressions/sortDescriptors, должен предварительный рейс содержание архива путем проверки keypaths, селекторов, и т.д. содержавших в нем, чтобы гарантировать, что не будет выполняться никакой ошибочный или вредоносный код. Как только preflighting был сделан, оценка может быть включена путем вызова allowEvaluation на декодируемом объекте рекурсивно включить оценку на графе объектов, базированном в получателе.

NSCalendar

В OS X 10.9, Основа обеспечивает много новых APIs для упрощения calendrical вычислений. Это также помогает избежать ошибок от комплекса calendrical вычисления. Новый APIs:

+ (id)calendarWithIdentifier:(NSString *)calendarIdentiferConstant;
- (void)getEra:(out NSInteger *)eraValuePointer year:(out NSInteger *)yearValuePointer
           month:(out NSInteger *)monthValuePointer day:(out NSInteger *)dayValuePointer fromDate:(NSDate *)date;
- (void)getEra:(out NSInteger *)eraValuePointer yearForWeekOfYear:(out NSInteger *)yearValuePointer
           weekOfYear:(out NSInteger *)weekValuePointer weekday:(out NSInteger *)weekdayValuePointer fromDate:(NSDate *)date;
- (void)getHour:(out NSInteger *)hourValuePointer minute:(out NSInteger *)minuteValuePointer second:(out NSInteger *)secondValuePointer
           nanosecond:(out NSInteger *)nanosecondValuePointer fromDate:(NSDate *)date;
- (NSInteger)component:(NSCalendarUnit)unit fromDate:(NSDate *)date;
- (NSDate *)dateWithEra:(NSInteger)eraValue year:(NSInteger)yearValue month:(NSInteger)monthValue day:(NSInteger)dayValue
           hour:(NSInteger)hourValue minute:(NSInteger)minuteValue second:(NSInteger)secondValue nanosecond:(NSInteger)nanosecondValue;
- (NSDate *)dateWithEra:(NSInteger)eraValue yearForWeekOfYear:(NSInteger)yearValue weekOfYear:(NSInteger)weekValue
           weekday:(NSInteger)weekdayValue hour:(NSInteger)hourValue minute:(NSInteger)minuteValue second:(NSInteger)secondValue nanosecond:(NSInteger)nanosecondValue;
- (NSDate *)startOfDayForDate:(NSDate *)date;
- (NSDateComponents *)componentsInTimeZone:(NSTimeZone *)timezone fromDate:(NSDate *)date;
- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit;
- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit;
- (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2;
- (BOOL)isDateInToday:(NSDate *)date;
- (BOOL)isDateInYesterday:(NSDate *)date;
- (BOOL)isDateInTomorrow:(NSDate *)date;
- (BOOL)isDateInWeekend:(NSDate *)date;
- (BOOL)rangeOfWeekendStartDate:(out NSDate **)datep interval:(out NSTimeInterval *)tip containingDate:(NSDate *)date;
- (BOOL)nextWeekendStartDate:(out NSDate **)datep interval:(out NSTimeInterval *)tip options:(NSCalendarOptions)options afterDate:(NSDate *)date;
- (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDateComponents:(NSDateComponents *)startingDateComp
           toDateComponents:(NSDateComponents *)resultDateComp options:(NSCalendarOptions)options;
- (NSDate *)dateByAddingUnit:(NSCalendarUnit)unit value:(NSInteger)value toDate:(NSDate *)date options:(NSCalendarOptions)options;
- (void)enumerateDatesStartingAfterDate:(NSDate *)start matchingComponents:(NSDateComponents *)comps options:(NSCalendarOptions)opts
           usingBlock:(void (^)(NSDate *date, BOOL exactMatch, BOOL *stop))block;
- (NSDate *)nextDateAfterDate:(NSDate *)date matchingComponents:(NSDateComponents *)comps options:(NSCalendarOptions)options;
- (NSDate *)nextDateAfterDate:(NSDate *)date matchingUnit:(NSCalendarUnit)unit value:(NSInteger)value options:(NSCalendarOptions)options;
- (NSDate *)nextDateAfterDate:(NSDate *)date matchingHour:(NSInteger)hourValue minute:(NSInteger)minuteValue second:(NSInteger)secondValue options:(NSCalendarOptions)options;
- (NSDate *)dateBySettingUnit:(NSCalendarUnit)unit value:(NSInteger)v toDate:(NSDate *)date options:(NSCalendarOptions)opts;
- (NSDate *)dateBySettingHour:(NSInteger)h minute:(NSInteger)m second:(NSInteger)s toDate:(NSDate *)date options:(NSCalendarOptions)opts;

Больше подробных данных об этом новом APIs может быть найдено в NSCalendar.h. Руководство по программированию Даты и времени также имеет больше подробной дискуссии о том, как этот APIs использовался бы.

В дополнение к новому APIs Основа также экспортирует новое уведомление: NSCalendarDayChangeNotification. Когда системный день изменяется, это новое уведомление отправляется через [NSNotificationCenter defaultCenter]. Обратите внимание на то, что уведомление не отправляется на наблюдателей ни на каком определенном или определенном потоке или очереди, поэтому при необходимости в обработке уведомления, чтобы сделать вещи, которые должны только быть сделаны определенным потоком или очередью, необходимо тогда запланировать ту работу в ответ на уведомление.

CoreFoundation и Основа собираются осудить несколько существующих связанных с календарем APIs в следующем выпуске. Если макрос препроцессора, NS_ENABLE_CALENDAR_DEPRECATIONS установлен в ненулевое значение в проекте, то использование того APIs будет обозначено компилятором.

NSDateComponents

NSDateComponents имеет четыре новых APIs для удобства:

- (void)setValue:(NSInteger)value forComponent:(NSCalendarUnit)unit;
- (NSInteger)valueForComponent:(NSCalendarUnit)unit;
- (BOOL)isValidDate;
- (BOOL)isValidDateInCalendar:(NSCalendar *)calendar;

Больше подробных данных об этом новом APIs может быть найдено в NSCalendar.h.

Принятие instancetype

Много новых базовых APIs Основы используют тип возврата 'instancetype'. Это методы класса, возвращающие экземпляр класса получения, даже если класс получения является подклассом класса, объявляющего метод. Обычно эти методы возвратили бы 'ID' в прошлом.

Эта информация может помочь компилятору идентифицировать основные виды ошибок, как тип NSArray в следующей строке:

    NSArray *набор = [NSSet setWithObject:@ «строка»];

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

NSArray-firstObject

Если массив пуст,-firstObject метод возвращает первый объект в массиве или ноль.

Ошибки NSString

NSString за пределы индексируют, и диапазоны теперь генерируют лучшие сообщения об ошибках.

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

NSScanner

NSScanner теперь обеспечивает следующий API для сканирования длинных длинных значений без знака:

- (BOOL) scanUnsignedLongLong: (без знака длинный длинный *) значение;

Это работает точно как другие существующие методы NSScanner, включая протесты:

- это не сканирует локализованные числа или числа с тысячами разделителей

- возвраты YES на переполнении, с зафиксированным результатом

NSAttributedString

Для приложений, соединенных против 10,9 SDK или позже, копируя стандартный экземпляр NSAttributedString теперь, сохраняет его вместо этого.

Локализованный файл списка свойств

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

NSString *localizedString;
NSUInteger numberOfItems; // assume the number of selected item is stored
 
if (numberOfItems == 1) { // single item
   localizedString = NSLocalizedString(@"A file is selected", @"Message displayed when showing a single file selection.");
} else { // multiple item
   localizedString = [NSString localizedStringWithFormat:NSLocalizedString(@"%d files are selected", @"Message displayed when showing multiple file selection."), numberOfItems];
}

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

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

NSString *localizedString;
NSUInteger numberOfItems; // assume the number of selected item is stored
NSUInteger modValue = numberOfItems % 100;
 
if (numberOfItems == 0) { // no item
   localizedString = NSLocalizedString(@"No file is selected", @"Message displayed when showing no selection.");
} else if (numberOfItems == 1) { // single item
   localizedString = NSLocalizedString(@"A file is selected", @"Message displayed when showing a single file selection.");
} else if (numberOfItems == 2) { // dual items
   localizedString = NSLocalizedString(@"Two files are selected", @"Message displayed when showing two files selected.");
} else if ((modValue >= 3) && (modValue <= 10)) { // paucal items
   localizedString = [NSString localizedStringWithFormat:NSLocalizedString(@"A few files (%d items) are selected", @"Message displayed when showing paucal files selected."), numberOfItems];
} else { // multiple items
   localizedString = [NSString localizedStringWithFormat:NSLocalizedString(@"%d files are selected", @"Message displayed when showing multiple file selection."), numberOfItems];
}

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

Для решения этой проблемы localizers должен быть в состоянии указать более сложную структуру данных, чем простая пара ключ/значение от строкового формата файла. Существует новый формат файла с представленным суффиксом «.stringsdict». - [NSBundle localizedStringForKey:value:table:] теперь доступы два файла: .stringsdict и .strings. Это запрашивает .stringsdict файл сначала, тогда, .strings файл.

.stringsdict файл содержит исходный ключ (т.е. «%d файлы выбраны») со значением как произвольный список свойств (главным образом словарь или строка). Когда значение является словарем, оно должно содержать ключ для локализованного значения строки формата и его словарей конфигурации спецификатора формата.

Когда-localizedStringForKey:value:table: возвращает NSString, который инстанцируют из записи в .stringsdict файле, строковый объект переносит дополнительную информацию, хранившую в файле. Информация может быть сохранена и скопирована через - копия и-mutableCopy. Когда непостоянная копия видоизменена, это отбрасывается.

% NSString улучшение спецификатора формата

Для представления нового словаря, основанного форматирующий правило, % форматирует директиву, улучшен с альтернативным '# флага формы '.

Расширенный % синтаксис формата:

%[n$]#[FLAGS][FIELD WIDTH][.PRECISION]@<CONFIGURATION KEY>@

Ключ конфигурации между двумя @s используется для запросов элемента в словаре конфигурации внешнего формата. Только символы в [зона действий Z_0 9] позволяются. Пространство имен независимо для каждой строки формата.

Например, «%d файлы выбраны» can become «% # num_files_are выбранная» ссылка на элемент для «num_files_are» в словаре конфигурации внешнего формата.

Словарь конфигурации спецификатора формата

Словарь конфигурации спецификатора формата содержит пары ключ/значение данных конфигурации. Каждое значение представлено отдельно словарь.

Существует несколько предопределенных ключей словаря.

- NSStringFormatSpecTypeKey

Этот ключ определяет тип конфигурации спецификатора формата. Это - обязательный ключ. В настоящее время мы поддерживаем NSStringPluralRuleType и NSStringGenderRuleType. Остальная часть содержания словаря определяется типом.

- NSStringFormatValueTypeKey

Это - дополнительный ключ, описывающий исходный тип аргумента на штабеле. Значение является спецификатором исходного формата. Для отображения «%d файлы выбраны» to «% # num_files_are, выбрал»  , the configuration dictionary for num_files_are should contain an entry «NSStringFormatValueTypeKey = d». Если отсутствующий, % принят.

  Конфигурация NSStringPluralRuleType отображает число параметра во множественный выбор с помощью Unicode Множественное число CLDR, отображающее правило. Словарь конфигурации мог содержать ключи для «нуля», «один», «два», «немногие», «многие» и «другие». Они соответствуют Unicode, Множественное число CLDR дополняет элементы данных. Значение для «других» обязательно. Если «нуль» присутствует, значение используется для отображения нуля значения аргумента независимо от того, что правило CLDR указывает для числового значения. Если отображающийся ключ отсутствует, значение для «других» используется в качестве нейтрализации.

 Конфигурация NSStringGenderRuleType отображает число параметра на различную форму. Как с большинством других систем обработки изменения рода включая CLDR, мы присваиваем индексы родам. Например, штекер 0, розетке 1 год, и нейтральный 2. Так как число типов рода варьируется значительно от языков до языков (т.е. польский язык имеет 5). Ключ для этого информационного типа конфигурации представлен положительным целым числом. Ключ 0 обязателен и используется для отсутствия других ключей рода.

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

Демонстрационная конфигурационная информация для выбранного примера файла.

@"%d files are selected" = @"%#@num_files_are@ selected" // localized string dynamically substitute "%d files are"

Конфигурация dict:

{
    "NSStringFormatSpecTypeKey" = "NSStringPluralRuleType"; // plural type
    "NSStringFormatValueTypeKey" = "d"; // int argument
 
    "zero" = "No file is";
    "one" = "A file is";
    "other" = "%d files are";
}

С тех пор существуют случаи, где условие замены правила множественного числа/рода в зависимости от другой замены (т.е. французские статьи как le, la, и les), рекурсивная возможность форматирования важна для этой функции. Например, с «%d в %d файлах выбраны», давание localizers опции заменить целым предложением в зависимости от числа общих файлов необходимо. Мы позволяем рекурсивное форматирование путем применения всего списка аргументов к каждому спецификатору формата, которым заменяют.

@"%d in %d files are selected" = @"%2$#@d_in_d_files_are_selected@"

Словарь конфигурации может содержать

"d_in_d_files_are_selected" = {
    "NSStringFormatSpecTypeKey" = "NSStringPluralRuleType"; // plural type
    "NSStringFormatValueTypeKey" = "d"; // int argument
 
    "zero" = "There is no file";
    "one" = "There is a file, and %1$#@it_is_selected@";
    "other" = "%1$d in %2$d files are selected";
};
 
"it_is_selected" = {
    "NSStringFormatSpecTypeKey" = "NSStringPluralRuleType"; // plural type
    "NSStringFormatValueTypeKey" = "d"; // int argument
 
    "zero" = "it is not selected";
    "other" = "it is selected";
};

Результаты «Нет никакого файла» для 0 файлов, «существует файл, и он не выбран» for 0 in 1, and «3 в 5 файлах, выбраны» для 3 в 5.

Это - выборка stringsdict содержание:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>%d files are selected</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@num_files_are@ selected</string>
        <key>num_files_are</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>zero</key>
            <string>No file is</string>
            <key>one</key>
            <string>A file is</string>
            <key>other</key>
            <string>%d files are</string>
        </dict>
    </dict>
</dict>
</plist>