How to use NSFileHandle's writeabilityHandler?
Asked Answered
C

1

6

Starting from OS X 10.7 and iOS 5.0 NSFileHandle has two new properties: readabilityHandler and writeabilityHandler. I tried to use writeabilityHandler, but no luck. The documentation is weird, it looks like they copy-pasted description of readabilityHandler and replaced word read with write.

According to the documentation assigning the block should eventually call the block. It does not.

- (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];
}

It is called only if I try to write to the handle synchronously [_incomingHandle writeData:dataToSend] which does not make sense. After it is called it throws an exception: EXC_BAD_INSTRUCTION

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

I have also tried to send the data piece by piece. No luck.

Has anyone successfully used this property?

Chippy answered 24/10, 2011 at 3:33 Comment(5)
It'd be nice if Apple had some published sample code that demonstrated these new handlers, but as far as I can tell, they do not. Maybe the WWDC videos (which you have access to, if you're a registered developer) have some hints and sample code?Malenamalet
This is the point, I have not found any samples. Also I do not remember they mentioned NSFileHandle in WWDC 2011 videos, at least in those once I have watched.Chippy
"Resource temporarily unavailable" means that write is returning EAGAIN, which means that your file handle isn't currently writeable, which explains why it's not calling your writeabilityHandler. The question is why is write returning EAGAIN? Where did _incomingHandle come from? What else might be happening to it?Rank
@rob mayoff I open a socket and initialise a file handle with it. I subscribe to 'NSFileHandleConnectionAcceptedNotification' notification. When it is received I get the file handle from '[[aNotification userInfo] objectForKey:NSFileHandleNotificationFileHandleItem]' which I retain and use when I need to write the data '[_incomingHandle writeData:dataToSend];'. This code has been working for about three years. It works in OSX 10.4-10.7, iOS2.0-4.2. It stopped working in iOS5 when I write a big file. Basically it throws an exception on 130 kb. Anything below this amount still works perfectly.Chippy
@rob mayoff So, I though they might have changed something in NSFileHandle. Maybe from now on I need to use the new properties provided, but I cannot figure out how to use them.Chippy
R
0

Hmm, do you have a sample project I could try? I haven't had any issues with it, even when doing silly things like nesting handlers. A test case that shows it not working might help figure out what's wrong.

One issue you could be running into is that the use of dispatch_io inside NSFileHandle will modify the properties of any fd you've passed in. That's arguably a bug in NSFileHandle, but is true for now :/

Rosales answered 17/1, 2012 at 6:53 Comment(6)
However, the question is how to use the new handlers they provided?Chippy
Right. I'm saying I've used the new handlers, and it sounds like you're running into bugs. I'd be interested in analyzing those bugs to see if I can learn something about what's going on.Rosales
Cool. How did you use them? I personally did not understand how to write data into the file handle. What should I do to make it call the writeabilityHandler block?Chippy
Only with NSPipes rather than network sockets, but it shouldn't matter. The block will be called in exactly the same situations that the event handler block for a dispatch_source event handler of type DISPATCH_SOURCE_TYPE_WRITE would be. A very very simple test would be something like this: pastebin.com/mUS8bjEERosales
Oh, except you'd probably want to set the read handler first. That's what I get for typing code into a web form.Rosales
Thanks of the sample. It looks pretty simple. Will try it soon.Chippy

© 2022 - 2024 — McMap. All rights reserved.