iOS 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;
}
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;
}
@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 memory information
struct mach_task_basic_info taskInfo;
mach_msg_type_number_t size = MACH_TASK_BASIC_INFO_COUNT;
kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&taskInfo, &size);
if (kerr == KERN_SUCCESS) {
[info appendFormat:@"Memory - Resident: %llu MB\n", taskInfo.resident_size / 1024 / 1024];
[info appendFormat:@"Memory - Virtual: %llu MB\n", taskInfo.virtual_size / 1024 / 1024];
}
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.1) {
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
Remember to adjust error handling logic based on actual SDK error code definitions and continuously monitor and improve error handling mechanisms. The iOS platform uses ARC for automatic memory management, but still need to pay attention to avoiding circular references and releasing unnecessary resources timely.