scheduleInRunLoop - threading network connections scheduleInRunLoop - threading network connections multithreading multithreading

scheduleInRunLoop - threading network connections


Note the differences between heap and stack.

Each thread has its own stack but all threads access the same heap.

The input stream needs its own thread because when reading the stream without reaching any EOF, the thread blocks if no new characters come and therefore waits. So to prevent your application from blocking the input stream needs a separate thread.

Continuing since delegates can't be static methods you have to copy or at least synchronise the use of a buffer to return results. Remember each thread has its own stack but both access to the same heap.

The NSStreamDelegate is an interface that allows you to specify who will manage events from a stream. Therefore allowing you to split programming for the handling of streams and the handling of their events. As your can think of delegates as pointers to functions you have to make sure they exist at runtime, which is why they are usually used and defined with protocols. But calling a method of a delegate does not mean you call a function of another thread. You only apply parameters/objects to a method of another object/class that will/must exist at runtime.

Apples NSThread class and NSRunloop class make it easy but confuse because a runloop is not the same as a thread.Each thread can have a runloop which is at least looped once and return immediately when nothing else is there to do. With [NSRunLoop currentRunLoop] you are asking for the runloop of the thread you are in, you are not creating another thread.So calling for the very same runloop from the same thread twice results in work in the same thread. Following this means if one part is blocking, you are blocking the thread so the other parts in the same thread wait also. (Where in the last sentence you could exchange the word thread with runloop and its still the same, its is blocking the thread)

As a matter of simultaneousness usually more than one socket port is involved when input and output streams should work at the 'same' time. NSInputStream is read -only & NSOutputStream is write-only.Where it is wise to give the input stream its own thread for reasons of possibly unexpected results from data and timing given by the nature of a remote sender which is out of your control. You are responsible to define if a runloop (respective thread) should stay active after invoking once.

Doing so your output stream is then in an/the other thread, the one you asked for its current runloop.You can not create or manage runloops, you just ask for it because each thread has one and if not - one is created for you.

On iOS you have a bunch of solutions available to implement your personal design pattern for simultan input and output streams.You could go with NSThread also with -performSelectorInBackground:SEL withObject:(nullable Id) which is actually an extension of NSObject defined in NSThread.h. But the last one does not allow you to define a special run-mode.

If you do not want to create a costume NSThread subclass to your needs here is a simple solution mentioned that may also work for you.iOS how can i perform multiple NSInputStreamHere [NSRunLoop currentRunloop] is the runloop of the thread that is detached. It is also possible to detach a new thread with a block

id<NSStreamDelegate> streamDelegate = //object that conforms to the protocol[NSThread detachNewThreadWithBlock:^(void){    NSInputStream *inputStream;    [inputStream setDelegate:streamDelegate];    // define your stream here    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]                   forMode:NSRunLoopCommonModes];    [inputStream open];}];`

PS: the example from @Ping is a switch to interact on events of both streams, it does not make streaming in & out simultaneous. Well, but you could use the example on both streams and their events no matter if they are simultaneous or not, typical NSStreamDelegate stuff.


- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{    switch (eventCode) {        case NSStreamEventNone:            break;        case NSStreamEventOpenCompleted:            break;        case NSStreamEventHasBytesAvailable:            [self _readData];            break;        case NSStreamEventHasSpaceAvailable:            [self _writeData];            break;        case NSStreamEventErrorOccurred:            break;        case NSStreamEventEndEncountered:            break;        default:            break;    }}