macOS Error Handling
Error Code Handling
1. Check API Return Values
All API calls should check return values:
objc
// Check engine creation
FBEngineConfig *config = [[FBEngineConfig alloc] init];
config.appId = @"your_app_id";
config.appKey = @"your_app_key";
self.engine = [FBBeautyEffectEngine createEngineWithConfig:config];
if (self.engine == nil) {
NSLog(@"Failed to create beauty engine");
return;
}
// Check beauty type enablement
int ret = [self.engine setBeautyTypeEnabled:FBBeautyType_Basic enabled:YES];
if (ret == 0) {
NSLog(@"Successfully enabled basic beauty");
} else {
NSLog(@"Failed to enable basic beauty, error code: %d", ret);
}
// Check parameter setting
int ret = [self.engine setBasicParam:FBBeautyParam_Smoothing floatValue:0.5f];
if (ret != 0) {
NSLog(@"Failed to set smoothing param, error code: %d", ret);
}2. Common Error Codes
According to API documentation, main error codes:
- 0: Success
- -1: Engine not initialized
objc
@interface BeautyErrorHandler : NSObject
@end
@implementation BeautyErrorHandler
+ (void)handleError:(int)errorCode operation:(NSString *)operation {
switch (errorCode) {
case 0:
NSLog(@"%@ succeeded", operation);
break;
case -1:
NSLog(@"%@ failed: Engine not initialized", operation);
break;
default:
NSLog(@"%@ failed: Unknown error code %d", operation, errorCode);
break;
}
}
@endHandle Image Data
1. Input Image Validation
objc
@interface ImageValidator : NSObject
+ (BOOL)validateImageFrame:(FBImageFrame *)imageFrame;
@end
@implementation ImageValidator
+ (BOOL)validateImageFrame:(FBImageFrame *)imageFrame {
if (imageFrame == nil) {
NSLog(@"ImageFrame is nil");
return NO;
}
// Check image dimensions
int width = imageFrame.width;
int height = imageFrame.height;
if (width <= 0 || height <= 0) {
NSLog(@"Invalid image dimensions: %dx%d", width, height);
return NO;
}
// macOS can support larger images
if (width > 8192 || height > 8192) {
NSLog(@"Image too large: %dx%d", width, height);
return NO;
}
return YES;
}
@end2. Image Processing Error Handling
objc
@interface ImageProcessor : NSObject
@property (nonatomic, strong) FBBeautyEffectEngine *engine;
@end
@implementation ImageProcessor
- (FBImageFrame *)processImageSafely:(FBImageFrame *)input {
// Validate input
if (![ImageValidator validateImageFrame:input]) {
return nil;
}
@try {
// Process image
FBImageFrame *output = [self.engine processImage:input processMode:FBProcessModeVideo];
if (output == nil) {
NSLog(@"Failed to process image: output is nil");
return nil;
}
return output;
} @catch (NSException *exception) {
NSLog(@"Exception during image processing: %@", exception.reason);
return nil;
}
}
@end3. Memory Management
objc
@interface SafeImageProcessor : NSObject
@property (nonatomic, strong) FBBeautyEffectEngine *engine;
@end
@implementation SafeImageProcessor
- (BOOL)processImageSafe:(FBImageFrame *)input output:(FBImageFrame *)output {
FBImageFrame *result = nil;
@try {
// Process image
result = [self.engine processImage:input processMode:FBProcessModeVideo];
if (result == nil) {
NSLog(@"Processing returned nil");
return NO;
}
// Copy result to output
[self copyImageFrame:result to:output];
return YES;
} @catch (NSException *exception) {
NSLog(@"Exception during processing: %@", exception.reason);
return NO;
}
}
- (void)copyImageFrame:(FBImageFrame *)src to:(FBImageFrame *)dst {
// Implement image copying logic
FBImageBuffer *srcBuffer = [src toRGBA];
FBImageBuffer *dstBuffer = [dst toRGBA];
if (srcBuffer != nil && dstBuffer != nil) {
const uint8_t *srcData = [srcBuffer data];
uint8_t *dstData = (uint8_t *)[dstBuffer data];
if (srcData != nil && dstData != nil) {
memcpy(dstData, srcData, MIN(srcBuffer.size, dstBuffer.size));
}
}
}
@endLogging and File Operations
1. Log Configuration Error Handling
objc
@interface LogConfigHandler : NSObject
+ (BOOL)configureLogging:(BOOL)enableConsole
enableFile:(BOOL)enableFile
logFilePath:(NSString *)logFilePath;
@end
@implementation LogConfigHandler
+ (BOOL)configureLogging:(BOOL)enableConsole
enableFile:(BOOL)enableFile
logFilePath:(NSString *)logFilePath {
@try {
FBLogConfig *logConfig = [[FBLogConfig alloc] init];
logConfig.consoleEnabled = enableConsole;
logConfig.fileEnabled = enableFile;
logConfig.level = FBLogLevel_Info;
if (enableFile && logFilePath != nil && logFilePath.length > 0) {
// Check if directory exists
NSString *logDir = [logFilePath stringByDeletingLastPathComponent];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:logDir]) {
NSError *error = nil;
if (![fileManager createDirectoryAtPath:logDir
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
NSLog(@"Failed to create log directory: %@", error.localizedDescription);
return NO;
}
}
logConfig.fileName = logFilePath;
}
int ret = [FBBeautyEffectEngine setLogConfig:logConfig];
return ret == 0;
} @catch (NSException *exception) {
NSLog(@"Failed to configure logging: %@", exception.reason);
return NO;
}
}
@end2. File Write Error Handling
objc
@interface FileWriteHandler : NSObject
+ (BOOL)saveImageBuffer:(FBImageBuffer *)buffer toPath:(NSString *)filePath;
@end
@implementation FileWriteHandler
+ (BOOL)saveImageBuffer:(FBImageBuffer *)buffer toPath:(NSString *)filePath {
if (buffer == nil) {
NSLog(@"ImageBuffer is nil");
return NO;
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *dir = [filePath stringByDeletingLastPathComponent];
// Create directory
if (![fileManager fileExistsAtPath:dir]) {
NSError *error = nil;
if (![fileManager createDirectoryAtPath:dir
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
NSLog(@"Failed to create directory: %@", error.localizedDescription);
return NO;
}
}
// Write file
const uint8_t *data = [buffer data];
NSData *nsData = [NSData dataWithBytes:data length:buffer.size];
NSError *error = nil;
BOOL success = [nsData writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (!success) {
NSLog(@"Failed to write file: %@", error.localizedDescription);
return NO;
}
NSLog(@"Image saved successfully: %@", filePath);
return YES;
}
@endException Handling
1. Catch and Handle Exceptions
objc
@interface ExceptionHandler : NSObject
+ (void)safeExecute:(void(^)(void))block operation:(NSString *)operation;
@end
@implementation ExceptionHandler
+ (void)safeExecute:(void(^)(void))block operation:(NSString *)operation {
@try {
if (block != nil) {
block();
}
} @catch (NSInvalidArgumentException *exception) {
NSLog(@"%@ failed: Invalid argument - %@", operation, exception.reason);
} @catch (NSException *exception) {
NSLog(@"%@ failed: Unexpected exception - %@", operation, exception.reason);
}
}
@end2. Retry Mechanism
objc
@interface RetryHandler : NSObject
@property (nonatomic, strong) FBBeautyEffectEngine *engine;
@end
@implementation RetryHandler
static const int MAX_RETRY = 3;
static const NSTimeInterval RETRY_DELAY = 0.1;
- (FBImageFrame *)processImageWithRetry:(FBImageFrame *)input {
for (int i = 0; i < MAX_RETRY; i++) {
@try {
FBImageFrame *result = [self.engine processImage:input processMode:FBProcessModeVideo];
if (result != nil) {
return result;
}
} @catch (NSException *exception) {
NSLog(@"Attempt %d failed: %@", i + 1, exception.reason);
}
if (i < MAX_RETRY - 1) {
[NSThread sleepForTimeInterval:RETRY_DELAY];
}
}
NSLog(@"All retry attempts failed");
return nil;
}
@endmacOS-Specific Error Handling
1. Sandbox Permission Handling
objc
@interface SandboxPermissionHandler : NSObject
+ (BOOL)requestFileAccessPermission:(NSURL *)fileURL;
+ (BOOL)hasFileAccessPermission:(NSURL *)fileURL;
@end
@implementation SandboxPermissionHandler
+ (BOOL)requestFileAccessPermission:(NSURL *)fileURL {
// macOS sandbox environment requires file access permission request
NSError *error = nil;
BOOL success = [fileURL startAccessingSecurityScopedResource];
if (!success) {
NSLog(@"Failed to request file access permission: %@", error.localizedDescription);
}
return success;
}
+ (BOOL)hasFileAccessPermission:(NSURL *)fileURL {
// Check if file access permission exists
NSFileManager *fileManager = [NSFileManager defaultManager];
return [fileManager isReadableFileAtPath:fileURL.path];
}
@end2. Multi-Display Environment Error Handling
objc
@interface MultiDisplayErrorHandler : NSObject
+ (void)handleDisplayChange:(NSNotification *)notification;
+ (BOOL)validateDisplayConfiguration;
@end
@implementation MultiDisplayErrorHandler
+ (void)handleDisplayChange:(NSNotification *)notification {
// Handle display configuration changes
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
CGFloat scaleFactor = screen.backingScaleFactor;
if (scaleFactor > 1.0) {
// Retina display
NSLog(@"Retina display detected with scale factor: %.1f", scaleFactor);
}
}
// Revalidate configuration
if (![self validateDisplayConfiguration]) {
NSLog(@"Display configuration validation failed");
}
}
+ (BOOL)validateDisplayConfiguration {
NSArray *screens = [NSScreen screens];
if (screens.count == 0) {
NSLog(@"No displays detected");
return NO;
}
// Validate all display configurations
for (NSScreen *screen in screens) {
if (screen.frame.size.width <= 0 || screen.frame.size.height <= 0) {
NSLog(@"Invalid screen dimensions");
return NO;
}
}
return YES;
}
@endDebugging Tips
1. Error Information Collection
objc
@interface DebugInfoCollector : NSObject
+ (NSString *)collectErrorInfo:(int)errorCode operation:(NSString *)operation exception:(NSException *)exception;
@end
@implementation DebugInfoCollector
+ (NSString *)collectErrorInfo:(int)errorCode operation:(NSString *)operation exception:(NSException *)exception {
NSMutableString *info = [NSMutableString string];
[info appendFormat:@"Operation: %@\n", operation];
[info appendFormat:@"Error Code: %d\n", errorCode];
[info appendFormat:@"Timestamp: %lld\n", (long long)([[NSDate date] timeIntervalSince1970] * 1000)];
if (exception != nil) {
[info appendFormat:@"Exception: %@\n", exception.name];
[info appendFormat:@"Reason: %@\n", exception.reason];
}
// Add system information
[info appendString:@"System Info:\n"];
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
[info appendFormat:@"Processor Count: %lu\n", (unsigned long)processInfo.processorCount];
[info appendFormat:@"Active Processor Count: %lu\n", (unsigned long)processInfo.activeProcessorCount];
return [info copy];
}
@end2. Performance Monitoring
objc
@interface PerformanceMonitor : NSObject
@property (nonatomic, assign) NSTimeInterval startTime;
@property (nonatomic, assign) NSInteger errorCount;
@end
@implementation PerformanceMonitor
- (void)startOperation {
self.startTime = [[NSDate date] timeIntervalSince1970];
}
- (void)endOperation:(NSString *)operation success:(BOOL)success {
NSTimeInterval duration = [[NSDate date] timeIntervalSince1970] - self.startTime;
if (!success) {
self.errorCount++;
NSLog(@"%@ failed after %.2fms (Error count: %ld)",
operation, duration * 1000, (long)self.errorCount);
} else if (duration > 0.05) {
// macOS has better performance, threshold can be set lower
NSLog(@"%@ took %.2fms (slow operation)", operation, duration * 1000);
}
}
@endSummary
Following these error handling best practices can help you:
- Improve App Stability: Through API return value checking and exception handling
- Improve User Experience: Through friendly error prompts and recovery mechanisms
- Facilitate Problem Troubleshooting: Through detailed logging and error information collection
- Optimize Performance: Through reasonable error recovery strategies and resource management
- macOS Optimization: Through sandbox permission handling and multi-display environment support
Remember to adjust error handling logic based on actual SDK error code definitions and continuously monitor and improve error handling mechanisms. The macOS platform has more memory and stronger processing capabilities compared to iOS, but also need to pay attention to special handling for sandbox permissions and multi-display environments.