- Use `NSError **` out-parameters for recoverable errors: `- (BOOL)saveData:(NSData *)data error:(NSError **)error` — this is the standard Cocoa error propagation pattern.
- Always check the BOOL return value before inspecting the `NSError` out-parameter — the error object may be set even on success in some APIs.
- Use `@try`/`@catch` only for exceptions from Cocoa framework code — exceptions in Objective-C signal programmer errors and are not for control flow.
- Create `NSError` objects with a custom domain constant and typed error codes: `NSError *err = [NSError errorWithDomain:MGErrorDomain code:MGErrorCodeNotFound userInfo:@{NSLocalizedDescriptionKey: @"Item not found"}]`.
- Define your error domain as a string constant: `NSString *const MGErrorDomain = @"com.myapp.error"` — use reverse-DNS notation for uniqueness.
- Populate `NSLocalizedDescriptionKey` and `NSLocalizedRecoverySuggestionErrorKey` in `userInfo` for errors that will be shown to users.
- Use `NSError.localizedDescription` in UI; use `NSError.domain` and `NSError.code` in code for programmatic error handling.