Как использовать обработчик возможности записи NSFileHandle?

#objective-c #ios5 #objective-c-blocks #osx-lion #nsfilehandle

#objective-c #ios5 #objective-c-блоки #osx-lion #nsfilehandle

Вопрос:

Начиная с OS X 10.7 и iOS 5.0, у NSFileHandle появилось два новых свойства: readabilityHandler и writeabilityHandler. Я пытался использовать обработчик возможности записи, но безуспешно. Документация странная, похоже, что они скопировали описание readabilityHandler и заменили слово read на write .

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

 - (void)sendResponse:(NSData*)dataToSend
{
    _incomingHandle.writeabilityHandler = 
    ^(NSFileHandle* fileHandle)
    {
        [fileHandle writeData:dataToSend]; // exception is thrown here
        fileHandle.writeabilityHandler = nil;
    };
    // Above block is not called without this line:
    //[_incomingHandle writeData:dataToSend];
}
 

Он вызывается только в том случае, если я пытаюсь выполнить запись в дескриптор синхронно [_incomingHandle writeData:dataToSend] , что не имеет смысла. После его вызова он выдает исключение: EXC_BAD_INSTRUCTION

 *** Terminating app due to uncaught exception 'NSFileHandleOperationException', reason:
'*** -[NSConcreteFileHandle writeData:]: Resource temporarily unavailable'
 

Я также пытался отправлять данные по частям. Не повезло.

Кто-нибудь успешно использовал это свойство?

Комментарии:

1. Было бы неплохо, если бы у Apple был какой-нибудь опубликованный пример кода, демонстрирующий эти новые обработчики, но, насколько я могу судить, они этого не делают. Может быть, в видеороликах WWDC (к которым у вас есть доступ, если вы зарегистрированный разработчик) есть какие-то подсказки и примеры кода?

2. В том-то и дело, что я не нашел ни одного примера. Также я не помню, чтобы они упоминали NSFileHandle в видеороликах WWDC 2011, по крайней мере, в тех, которые я когда-то смотрел.

3. «Ресурс временно недоступен» означает, что write возвращает EAGAIN, что означает, что ваш дескриптор файла в данный момент недоступен для записи, что объясняет, почему он не вызывает ваш обработчик возможности записи. Вопрос в том, почему write возвращает EAGAIN? Откуда взялся _incomingHandle? Что еще может с ним происходить?

4. @rob mayoff Я открываю сокет и инициализирую с его помощью дескриптор файла. Я подписываюсь на уведомление ‘NSFileHandleConnectionAcceptedNotification’. Когда он получен, я получаю дескриптор файла из ‘[[aNotification userInfo] objectForKey:NSFileHandleNotificationFileHandleItem]’, который я сохраняю и использую, когда мне нужно записать данные ‘[_incomingHandle writeData:dataToSend];’. Этот код работает около трех лет. Он работает в OSX 10.4-10.7, iOS2.0-4.2. Он перестал работать в iOS5, когда я записываю большой файл. По сути, он выдает исключение на 130 КБ. Все, что ниже этого значения, по-прежнему работает отлично.

5. @rob mayoff Итак, я подумал, что они могли что-то изменить в NSFileHandle. Возможно, теперь мне нужно использовать предоставленные новые свойства, но я не могу понять, как их использовать.

Ответ №1:

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

Одна из проблем, с которой вы можете столкнуться, заключается в том, что использование dispatch_io внутри NSFileHandle изменит свойства любого переданного вами fd. Возможно, это ошибка в NSFileHandle, но пока это правда :/

Комментарии:

1. Код, который я использовал, был написан несколько лет назад. Самый близкий пример, который я нашел, находится здесь iphonedevsdk.com/forum/iphone-sdk-development /…

2. Однако вопрос в том, как использовать новые обработчики, которые они предоставили?

3. Правильно. Я говорю, что использовал новые обработчики, и, похоже, вы столкнулись с ошибками. Мне было бы интересно проанализировать эти ошибки, чтобы посмотреть, смогу ли я узнать что-нибудь о том, что происходит.

4. Прохладный. Как вы их использовали? Я лично не понял, как записывать данные в дескриптор файла. Что я должен сделать, чтобы он вызывал блок writeabilityHandler?

5. Только с NSPipes, а не с сетевыми сокетами, но это не должно иметь значения. Блок будет вызываться точно в тех же ситуациях, что и блок обработчика событий для обработчика событий dispatch_source типа DISPATCH_SOURCE_TYPE_WRITE . Очень, очень простой тест будет выглядеть примерно так: pastebin.com/mUS8bjEE