Why is it designed that way?
As long as you're only ever using readDataWithTimeout:tag: it may seem more intuitive to just have the delegate method called whenever some new data has arrived.
But readDataWithTimeout:tag: isn't the the only way to read data with GCDAsyncSocket. There are also e.g. readDataToLength:withTimeout:tag: and readDataToData:withTimeout:tag:
Both of these methods call the delegate at specific points in the incoming data, and you might want to call different ones at different points in your processing.
For example, if you were handling a stream format where there was a CRLF delimited header followed by a variable length body whose length was provided in the header then you might want to alternate between calls of readDataToData:withTimeout:tag: to read the header whose delimiter you know, and then readDataToLength:withTimeout:tag: to read the body whose length you have pulled from the header.