First, from the documentation of -UTF8String:
This C string is a pointer to a structure inside the string object, which may have a lifetime shorter than the string object and will certainly not have a longer lifetime. Therefore, you should copy the C string if it needs to be stored outside of the memory context in which you use this property.
Second, note that the declaration of -UTF8String is annotated with NS_RETURNS_INNER_POINTER. This is an alis for objc_returns_inner_pointer, which is documented here. From that:
When such a message is sent to an object, the object’s lifetime will be extended until at least the earliest of:
- the last use of the returned pointer, or any pointer derived from it, in the calling function or
- the autorelease pool is restored to a previous state.
So, if you were to assign the result from -UTF8String to a local variable, you could rely on it continuing to be valid long enough to, say, strdup() it. But returning it from your function is not safe, since it then survives past "the last use of the returned pointer, or any pointer derived from it, in the calling function".
If you want to implement a function with semantics like this, you may need to use Core Foundation. Do a CFBridgingRetain() on the NSString object and then CFAutorelease() it. This makes sure that the string object survives until the autorelease pool is drained. Alternatively, you can create a CFData object from the C string and CFAutorelease() that. You'd return its byte pointer.