The way ObjC did it is to use exceptions to signal programmer error, and error objects for program errors. I think it’s the best style, at least until the day programmer errors just won’t compile , but that needs something like Idris to take over.
To be fair, it's not always true. Many APIs actually don't have NSError argument and throw Obj-C exceptions on actionable errors. For example, reading from an NSFileHandle may throw NSFileHandleOperationException. I suppose, in most cases it has been done for brevity. Though, you can also argue that only opening a file could fail (due to invalid path or insufficient permissions).