🎯 empfohlene Sammlungen
Balanced sample collections from various categories for you to explore
Fehlerbehandlung macOS Objective-C - Beispiele
macOS Objective-C Fehlerbehandlungsbeispiele einschließlich Ausnahmebehandlung, Protokollierung und Parametervalidierung
💻 Protokollierung objectivec
🟢 simple
⭐⭐
Protokolle mit verschiedenen Ebenen und Zeitstempeln mit NSLog und benutzerdefinierten Loggern in Dateien schreiben
⏱️ 20 min
🏷️ objectivec, macos, error handling, logging
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Log Recording Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Log Levels
typedef NS_ENUM(NSInteger, LogLevel) {
LogLevelDebug = 0,
LogLevelInfo = 1,
LogLevelWarning = 2,
LogLevelError = 3,
LogLevelCritical = 4
};
NSString *NSStringFromLogLevel(LogLevel level) {
switch (level) {
case LogLevelDebug: return @"DEBUG";
case LogLevelInfo: return @"INFO";
case LogLevelWarning: return @"WARNING";
case LogLevelError: return @"ERROR";
case LogLevelCritical: return @"CRITICAL";
default: return @"UNKNOWN";
}
}
// MARK: - 2. Simple File Logger
@interface SimpleFileLogger : NSObject
@property (nonatomic, strong) NSString *logFilePath;
@property (nonatomic, assign) LogLevel minimumLevel;
+ (instancetype)loggerWithFile:(NSString *)filePath;
- (void)log:(LogLevel)level message:(NSString *)message;
- (void)debug:(NSString *)message;
- (void)info:(NSString *)message;
- (void)warning:(NSString *)message;
- (void)error:(NSString *)message;
- (void)critical:(NSString *)message;
@end
@implementation SimpleFileLogger
+ (instancetype)loggerWithFile:(NSString *)filePath {
SimpleFileLogger *logger = [[SimpleFileLogger alloc] init];
logger.logFilePath = filePath;
logger.minimumLevel = LogLevelDebug;
return logger;
}
- (void)log:(LogLevel)level message:(NSString *)message {
if (level < self.minimumLevel) {
return;
}
// Create log entry
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
NSString *timestamp = [formatter stringFromDate:[NSDate date]];
NSString *logEntry = [NSString stringWithFormat:@"[%@] [%@] %@\n",
timestamp, NSStringFromLogLevel(level), message];
// Append to file
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.logFilePath];
if (!fileHandle) {
// Create new file
[[NSFileManager defaultManager] createFileAtPath:self.logFilePath
contents:nil
attributes:nil];
fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.logFilePath];
}
if (fileHandle) {
[fileHandle seekToEndOfFile];
[fileHandle writeData:[logEntry dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
}
// Also print to console
NSLog(@"[%@] %@", NSStringFromLogLevel(level), message);
}
- (void)debug:(NSString *)message {
[self log:LogLevelDebug message:message];
}
- (void)info:(NSString *)message {
[self log:LogLevelInfo message:message];
}
- (void)warning:(NSString *)message {
[self log:LogLevelWarning message:message];
}
- (void)error:(NSString *)message {
[self log:LogLevelError message:message];
}
- (void)critical:(NSString *)message {
[self log:LogLevelCritical message:message];
}
@end
// MARK: - 3. Advanced Logger with Rotation
@interface AdvancedLogger : NSObject
@property (nonatomic, strong) NSString *logDirectory;
@property (nonatomic, strong) NSString *currentLogFile;
@property (nonatomic, assign) NSUInteger maxFileSize;
@property (nonatomic, assign) NSUInteger maxBackupFiles;
+ (instancetype)loggerWithDirectory:(NSString *)directory
maxFileSize:(NSUInteger)maxFileSize
maxBackupFiles:(NSUInteger)maxBackupFiles;
- (void)log:(LogLevel)level
file:(const char *)file
line:(NSInteger)line
method:(const char *)method
message:(NSString *)message;
- (void)rotateLogFile;
@end
@implementation AdvancedLogger
+ (instancetype)loggerWithDirectory:(NSString *)directory
maxFileSize:(NSUInteger)maxFileSize
maxBackupFiles:(NSUInteger)maxBackupFiles {
AdvancedLogger *logger = [[AdvancedLogger alloc] init];
logger.logDirectory = directory;
logger.maxFileSize = maxFileSize;
logger.maxBackupFiles = maxBackupFiles;
// Create directory if needed
[[NSFileManager defaultManager] createDirectoryAtPath:directory
withIntermediateDirectories:YES
attributes:nil
error:nil];
// Set current log file
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"yyyy-MM-dd";
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
logger.currentLogFile = [directory stringByAppendingPathComponent:
[NSString stringWithFormat:@"app_%@.log", dateString]];
return logger;
}
- (void)log:(LogLevel)level
file:(const char *)file
line:(NSInteger)line
method:(const char *)method
message:(NSString *)message {
// Check file size and rotate if needed
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.currentLogFile
error:nil];
if (attributes) {
NSUInteger fileSize = [attributes[NSFileSize] unsignedIntegerValue];
if (fileSize >= self.maxFileSize) {
[self rotateLogFile];
}
}
// Create log entry
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
NSString *timestamp = [formatter stringFromDate:[NSDate date]];
NSString *fileName = [[NSString stringWithUTF8String:file] lastPathComponent];
NSString *methodName = [NSString stringWithUTF8String:method];
NSString *logEntry = [NSString stringWithFormat:@"[%@] [%@] [%@:%@:%ld] %@\n",
timestamp,
NSStringFromLogLevel(level),
fileName,
methodName,
(long)line,
message];
// Write to file
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.currentLogFile];
if (!fileHandle) {
[[NSFileManager defaultManager] createFileAtPath:self.currentLogFile
contents:nil
attributes:nil];
fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.currentLogFile];
}
if (fileHandle) {
[fileHandle seekToEndOfFile];
[fileHandle writeData:[logEntry dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
}
}
- (void)rotateLogFile {
NSString *baseName = [[self.currentLogFile lastPathComponent] stringByDeletingPathExtension];
NSString *extension = [self.currentLogFile pathExtension];
// Remove oldest backup if needed
NSString *oldestBackup = [self.logDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"%@_%ld.%@",
baseName, (long)(self.maxBackupFiles + 1), extension]];
[[NSFileManager defaultManager] removeItemAtPath:oldestBackup error:nil];
// Rotate existing backups
for (NSInteger i = self.maxBackupFiles; i >= 1; i--) {
NSString *oldFile = [self.logDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"%@_%ld.%@", baseName, (long)i, extension]];
NSString *newFile = [self.logDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"%@_%ld.%@", baseName, (long)(i + 1), extension]];
[[NSFileManager defaultManager] moveItemAtPath:oldFile toPath:newFile error:nil];
}
// Move current log to backup_1
NSString *backup1 = [self.logDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"%@_1.%@", baseName, extension]];
[[NSFileManager defaultManager] moveItemAtPath:self.currentLogFile toPath:backup1 error:nil];
NSLog(@"Log file rotated: %@", self.currentLogFile);
}
@end
// MARK: - 4. Structured Logging
@interface StructuredLogger : NSObject
@property (nonatomic, strong) NSString *logFilePath;
- (void)logWithLevel:(LogLevel)level
message:(NSString *)message
fields:(NSDictionary *)fields;
- (void)logEvent:(NSString *)eventName
fields:(NSDictionary *)fields;
- (void)logError:(NSError *)error
context:(NSDictionary *)context;
@end
@implementation StructuredLogger
- (instancetype)init {
self = [super init];
if (self) {
_logFilePath = @"/tmp/structured_log.jsonl";
}
return self;
}
- (void)logWithLevel:(LogLevel)level
message:(NSString *)message
fields:(NSDictionary *)fields {
NSMutableDictionary *logEntry = [NSMutableDictionary dictionary];
logEntry[@"timestamp"] = @([NSDate date].timeIntervalSince1970);
logEntry[@"level"] = NSStringFromLogLevel(level);
logEntry[@"message"] = message;
if (fields) {
[logEntry addEntriesFromDictionary:fields];
}
[self writeLogEntry:logEntry];
}
- (void)logEvent:(NSString *)eventName
fields:(NSDictionary *)fields {
[self logWithLevel:LogLevelInfo
message:[NSString stringWithFormat:@"Event: %@", eventName]
fields:fields];
}
- (void)logError:(NSError *)error
context:(NSDictionary *)context {
NSMutableDictionary *errorFields = [NSMutableDictionary dictionary];
errorFields[@"errorDomain"] = error.domain;
errorFields[@"errorCode"] = @(error.code);
errorFields[@"errorDescription"] = error.localizedDescription;
if (context) {
[errorFields addEntriesFromDictionary:context];
}
[self logWithLevel:LogLevelError
message:@"Error occurred"
fields:errorFields];
}
- (void)writeLogEntry:(NSDictionary *)logEntry {
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:logEntry
options:0
error:nil];
if (jsonData) {
NSString *jsonLine = [NSString stringWithFormat:@"%@\n",
[[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding]];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.logFilePath];
if (!fileHandle) {
[[NSFileManager defaultManager] createFileAtPath:self.logFilePath
contents:nil
attributes:nil];
fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.logFilePath];
}
if (fileHandle) {
[fileHandle seekToEndOfFile];
[fileHandle writeData:[jsonLine dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
}
}
}
@end
// MARK: - 5. Performance Logging
@interface PerformanceLogger : NSObject
@property (nonatomic, strong) NSMutableDictionary *startTime;
- (void)startTiming:(NSString *)operationName;
- (NSTimeInterval)endTiming:(NSString *)operationName;
- (void)logTiming:(NSString *)operationName duration:(NSTimeInterval)duration;
@end
@implementation PerformanceLogger
- (instancetype)init {
self = [super init];
if (self) {
_startTime = [NSMutableDictionary dictionary];
}
return self;
}
- (void)startTiming:(NSString *)operationName {
self.startTime[operationName] = @([NSDate date].timeIntervalSince1970);
}
- (NSTimeInterval)endTiming:(NSString *)operationName {
NSNumber *start = self.startTime[operationName];
if (!start) {
NSLog(@"No start time found for operation: %@", operationName);
return 0;
}
NSTimeInterval end = [NSDate date].timeIntervalSince1970;
NSTimeInterval duration = end - [start doubleValue];
[self.startTime removeObjectForKey:operationName];
[self logTiming:operationName duration:duration];
return duration;
}
- (void)logTiming:(NSString *)operationName duration:(NSTimeInterval)duration {
NSString *logMessage = [NSString stringWithFormat:@"Operation '%@' completed in %.3f seconds",
operationName, duration];
NSLog(@"[PERFORMANCE] %@", logMessage);
// Also write to performance log file
NSString *perfLogFile = @"/tmp/performance.log";
NSString *logEntry = [NSString stringWithFormat:@"[%@] %@\n",
[NSDate date], logEntry];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:perfLogFile];
if (!fileHandle) {
[[NSFileManager defaultManager] createFileAtPath:perfLogFile
contents:nil
attributes:nil];
fileHandle = [NSFileHandle fileHandleForWritingAtPath:perfLogFile];
}
if (fileHandle) {
[fileHandle seekToEndOfFile];
[fileHandle writeData:[logEntry dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
}
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Log Recording Examples ===\n");
// 1. Simple file logging
NSLog(@"--- 1. Simple File Logging ---");
SimpleFileLogger *logger = [SimpleFileLogger loggerWithFile:@"/tmp/app.log"];
[logger debug:@"Application starting"];
[logger info:@"User logged in"];
[logger warning:@"Low memory warning"];
[logger error:@"Database connection failed"];
[logger critical:@"System shutdown required"];
NSLog(@"\nLogs written to /tmp/app.log");
// 2. Advanced logging
NSLog(@"\n--- 2. Advanced Logging ---");
AdvancedLogger *advLogger = [AdvancedLogger loggerWithDirectory:@"/tmp/logs"
maxFileSize:1024
maxBackupFiles:3];
[advLogger log:LogLevelInfo
file:__FILE__
line:__LINE__
method:__func__
message:@"Advanced logger initialized"];
[advLogger log:LogLevelError
file:__FILE__
line:__LINE__
method:__func__
message:@"Test error message"];
NSLog(@"\nAdvanced logs written to /tmp/logs/");
// 3. Structured logging
NSLog(@"\n--- 3. Structured Logging ---");
StructuredLogger *structLogger = [[StructuredLogger alloc] init];
[structLogger logWithLevel:LogLevelInfo
message:@"User action"
fields:@{
@"userId": @"12345",
@"action": @"login",
@"ipAddress": @"192.168.1.1"
}];
[structLogger logEvent:@"purchase_completed"
fields:@{
@"userId": @"12345",
@"productId": @"prod-678",
@"amount": @99.99
}];
NSError *testError = [NSError errorWithDomain:@"TestDomain"
code:404
userInfo:@{
NSLocalizedDescriptionKey: @"Resource not found"
}];
[structLogger logError:testError
context:@{
@"requestId": @"req-123",
@"endpoint": @"/api/users"
}];
NSLog(@"\nStructured logs written to /tmp/structured_log.jsonl");
// 4. Performance logging
NSLog(@"\n--- 4. Performance Logging ---");
PerformanceLogger *perfLogger = [[PerformanceLogger alloc] init];
[perfLogger startTiming:@"dataProcessing"];
[NSThread sleepForTimeInterval:0.1]; // Simulate work
[perfLogger endTiming:@"dataProcessing"];
[perfLogger startTiming:@"databaseQuery"];
[NSThread sleepForTimeInterval:0.05]; // Simulate query
[perfLogger endTiming:@"databaseQuery"];
// 5. Log level filtering
NSLog(@"\n--- 5. Log Level Filtering ---");
SimpleFileLogger *warningLogger = [SimpleFileLogger loggerWithFile:@"/tmp/warning.log"];
warningLogger.minimumLevel = LogLevelWarning;
[warningLogger debug:@"This won't be logged"];
[warningLogger info:@"Neither will this"];
[warningLogger warning:@"This warning will be logged"];
[warningLogger error:@"This error will be logged"];
NSLog(@"\nFiltered logs written to /tmp/warning.log");
// Cleanup
NSLog(@"\n--- Cleanup ---");
NSArray *logFiles = @[
@"/tmp/app.log",
@"/tmp/structured_log.jsonl",
@"/tmp/warning.log",
@"/tmp/performance.log"
];
for (NSString *file in logFiles) {
NSString *content = [NSString stringWithContentsOfFile:file
encoding:NSUTF8StringEncoding
error:nil];
if (content) {
NSLog(@"\nContent of %@:", file);
NSLog(@"%@", content);
}
}
// Clean up log directory
[[NSFileManager defaultManager] removeItemAtPath:@"/tmp/logs" error:nil];
NSLog(@"\n=== Log Recording Examples Completed ===");
}
return 0;
}
💻 Parametervalidierung objectivec
🟢 simple
⭐⭐
Funktionsparameter validieren einschließlich Nil-Prüfungen, Bereichsvalidierung und Typprüfung
⏱️ 20 min
🏷️ objectivec, macos, error handling, validation
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Parameter Validation Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic Validation Macros
#define VALIDATE_NOT_NULL(param, error) \
if (!param) { \
if (error) { \
*error = [NSError errorWithDomain:@"ValidationError" \
code:1001 \
userInfo:@{NSLocalizedDescriptionKey: @"Parameter cannot be null"}]; \
} \
return NO; \
}
#define VALIDATE_NOT_EMPTY_STRING(param, error) \
if (!param || param.length == 0) { \
if (error) { \
*error = [NSError errorWithDomain:@"ValidationError" \
code:1002 \
userInfo:@{NSLocalizedDescriptionKey: @"String cannot be empty"}]; \
} \
return NO; \
}
#define VALIDATE_RANGE(param, min, max, error) \
if (param < min || param > max) { \
if (error) { \
*error = [NSError errorWithDomain:@"ValidationError" \
code:1003 \
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Parameter must be between %ld and %ld", (long)(min), (long)(max)]}]; \
} \
return NO; \
}
// MARK: - 2. String Validation
@interface StringValidator : NSObject
+ (BOOL)isValidString:(NSString *)string
error:(NSError **)error;
+ (BOOL)isValidEmail:(NSString *)email
error:(NSError **)error;
+ (BOOL)isValidURL:(NSString *)url
error:(NSError **)error;
+ (BOOL)isValidPhoneNumber:(NSString *)phone
error:(NSError **)error;
+ (BOOL)isValidLength:(NSString *)string
minLength:(NSInteger)minLength
maxLength:(NSInteger)maxLength
error:(NSError **)error;
@end
@implementation StringValidator
+ (BOOL)isValidString:(NSString *)string
error:(NSError **)error {
if (!string) {
if (error) {
*error = [NSError errorWithDomain:@"StringValidationError"
code:1001
userInfo:@{NSLocalizedDescriptionKey: @"String cannot be nil"}];
}
return NO;
}
if (string.length == 0) {
if (error) {
*error = [NSError errorWithDomain:@"StringValidationError"
code:1002
userInfo:@{NSLocalizedDescriptionKey: @"String cannot be empty"}];
}
return NO;
}
return YES;
}
+ (BOOL)isValidEmail:(NSString *)email
error:(NSError **)error {
if (![self isValidString:email error:error]) {
return NO;
}
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
if (![emailTest evaluateWithObject:email]) {
if (error) {
*error = [NSError errorWithDomain:@"StringValidationError"
code:1003
userInfo:@{NSLocalizedDescriptionKey: @"Invalid email format"}];
}
return NO;
}
return YES;
}
+ (BOOL)isValidURL:(NSString *)url
error:(NSError **)error {
if (![self isValidString:url error:error]) {
return NO;
}
NSURL *urlObj = [NSURL URLWithString:url];
if (!urlObj || !urlObj.scheme || !urlObj.host) {
if (error) {
*error = [NSError errorWithDomain:@"StringValidationError"
code:1004
userInfo:@{NSLocalizedDescriptionKey: @"Invalid URL format"}];
}
return NO;
}
return YES;
}
+ (BOOL)isValidPhoneNumber:(NSString *)phone
error:(NSError **)error {
if (![self isValidString:phone error:error]) {
return NO;
}
// Basic phone validation: digits, spaces, dashes, parentheses, plus
NSString *phoneRegex = @"^[+]?[(]?[0-9]{1,3}[)]?[-\\s.]?[(]?[0-9]{1,4}[)]?[-\\s.]?[0-9]{1,4}[-\\s.]?[0-9]{1,9}$";
NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", phoneRegex];
if (![phoneTest evaluateWithObject:phone]) {
if (error) {
*error = [NSError errorWithDomain:@"StringValidationError"
code:1005
userInfo:@{NSLocalizedDescriptionKey: @"Invalid phone number format"}];
}
return NO;
}
return YES;
}
+ (BOOL)isValidLength:(NSString *)string
minLength:(NSInteger)minLength
maxLength:(NSInteger)maxLength
error:(NSError **)error {
if (![self isValidString:string error:error]) {
return NO;
}
if (string.length < minLength || string.length > maxLength) {
if (error) {
*error = [NSError errorWithDomain:@"StringValidationError"
code:1006
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"String length must be between %ld and %ld", (long)minLength, (long)maxLength]}];
}
return NO;
}
return YES;
}
@end
// MARK: - 3. Numeric Validation
@interface NumericValidator : NSObject
+ (BOOL)isValidInteger:(NSInteger)value
min:(NSInteger)min
max:(NSInteger)max
error:(NSError **)error;
+ (BOOL)isValidDouble:(double)value
min:(double)min
max:(double)max
error:(NSError **)error;
+ (BOOL)isPositive:(NSInteger)value
error:(NSError **)error;
+ (BOOL)isNonNegative:(double)value
error:(NSError **)error;
@end
@implementation NumericValidator
+ (BOOL)isValidInteger:(NSInteger)value
min:(NSInteger)min
max:(NSInteger)max
error:(NSError **)error {
if (value < min || value > max) {
if (error) {
*error = [NSError errorWithDomain:@"NumericValidationError"
code:2001
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Value %ld must be between %ld and %ld", (long)value, (long)min, (long)max]}];
}
return NO;
}
return YES;
}
+ (BOOL)isValidDouble:(double)value
min:(double)min
max:(double)max
error:(NSError **)error {
if (value < min || value > max) {
if (error) {
*error = [NSError errorWithDomain:@"NumericValidationError"
code:2002
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Value %.2f must be between %.2f and %.2f", value, min, max]}];
}
return NO;
}
return YES;
}
+ (BOOL)isPositive:(NSInteger)value
error:(NSError **)error {
if (value <= 0) {
if (error) {
*error = [NSError errorWithDomain:@"NumericValidationError"
code:2003
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Value %ld must be positive", (long)value]}];
}
return NO;
}
return YES;
}
+ (BOOL)isNonNegative:(double)value
error:(NSError **)error {
if (value < 0) {
if (error) {
*error = [NSError errorWithDomain:@"NumericValidationError"
code:2004
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Value %.2f cannot be negative", value]}];
}
return NO;
}
return YES;
}
@end
// MARK: - 4. Collection Validation
@interface CollectionValidator : NSObject
+ (BOOL)isValidArray:(NSArray *)array
minCount:(NSInteger)minCount
maxCount:(NSInteger)maxCount
error:(NSError **)error;
+ (BOOL)arrayContains:(NSArray *)array
type:(Class)classType
error:(NSError **)error;
+ (BOOL)isValidDictionary:(NSDictionary *)dict
requiredKeys:(NSArray<NSString *> *)requiredKeys
error:(NSError **)error;
@end
@implementation CollectionValidator
+ (BOOL)isValidArray:(NSArray *)array
minCount:(NSInteger)minCount
maxCount:(NSInteger)maxCount
error:(NSError **)error {
if (!array) {
if (error) {
*error = [NSError errorWithDomain:@"CollectionValidationError"
code:3001
userInfo:@{NSLocalizedDescriptionKey: @"Array cannot be nil"}];
}
return NO;
}
if (array.count < minCount || array.count > maxCount) {
if (error) {
*error = [NSError errorWithDomain:@"CollectionValidationError"
code:3002
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Array count %lu must be between %ld and %ld", (unsigned long)array.count, (long)minCount, (long)maxCount]}];
}
return NO;
}
return YES;
}
+ (BOOL)arrayContains:(NSArray *)array
type:(Class)classType
error:(NSError **)error {
if (!array) {
if (error) {
*error = [NSError errorWithDomain:@"CollectionValidationError"
code:3003
userInfo:@{NSLocalizedDescriptionKey: @"Array cannot be nil"}];
}
return NO;
}
for (id item in array) {
if (![item isKindOfClass:classType]) {
if (error) {
*error = [NSError errorWithDomain:@"CollectionValidationError"
code:3004
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Array must contain only %@ objects", NSStringFromClass(classType)]}];
}
return NO;
}
}
return YES;
}
+ (BOOL)isValidDictionary:(NSDictionary *)dict
requiredKeys:(NSArray<NSString *> *)requiredKeys
error:(NSError **)error {
if (!dict) {
if (error) {
*error = [NSError errorWithDomain:@"CollectionValidationError"
code:3005
userInfo:@{NSLocalizedDescriptionKey: @"Dictionary cannot be nil"}];
}
return NO;
}
NSMutableSet *missingKeys = [NSMutableSet set];
for (NSString *key in requiredKeys) {
if (!dict[key]) {
[missingKeys addObject:key];
}
}
if (missingKeys.count > 0) {
if (error) {
*error = [NSError errorWithDomain:@"CollectionValidationError"
code:3006
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Missing required keys: %@", [missingKeys allObjects]}]};
}
return NO;
}
return YES;
}
@end
// MARK: - 5. User Input Validator
@interface UserInputValidator : NSObject
+ (BOOL)validateUsername:(NSString *)username
error:(NSError **)error;
+ (BOOL)validatePassword:(NSString *)password
error:(NSError **)error;
+ (BOOL)validateAge:(NSInteger)age
error:(NSError **)error;
+ (BOOL)validateUserDictionary:(NSDictionary *)userDict
error:(NSError **)error;
@end
@implementation UserInputValidator
+ (BOOL)validateUsername:(NSString *)username
error:(NSError **)error {
if (![StringValidator isValidString:username error:error]) {
return NO;
}
// Username: 3-20 characters, alphanumeric and underscore
NSString *usernameRegex = @"^[a-zA-Z0-9_]{3,20}$";
NSPredicate *usernameTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", usernameRegex];
if (![usernameTest evaluateWithObject:username]) {
if (error) {
*error = [NSError errorWithDomain:@"UserValidationError"
code:4001
userInfo:@{NSLocalizedDescriptionKey: @"Username must be 3-20 alphanumeric characters or underscores"}];
}
return NO;
}
return YES;
}
+ (BOOL)validatePassword:(NSString *)password
error:(NSError **)error {
if (![StringValidator isValidString:password error:error]) {
return NO;
}
// Password: at least 8 characters, must contain uppercase, lowercase, and digit
if (password.length < 8) {
if (error) {
*error = [NSError errorWithDomain:@"UserValidationError"
code:4002
userInfo:@{NSLocalizedDescriptionKey: @"Password must be at least 8 characters"}];
}
return NO;
}
BOOL hasUppercase = NO, hasLowercase = NO, hasDigit = NO;
for (NSInteger i = 0; i < password.length; i++) {
unichar c = [password characterAtIndex:i];
if (c >= 'A' && c <= 'Z') hasUppercase = YES;
else if (c >= 'a' && c <= 'z') hasLowercase = YES;
else if (c >= '0' && c <= '9') hasDigit = YES;
}
if (!hasUppercase || !hasLowercase || !hasDigit) {
if (error) {
*error = [NSError errorWithDomain:@"UserValidationError"
code:4003
userInfo:@{NSLocalizedDescriptionKey: @"Password must contain uppercase, lowercase, and digit"}];
}
return NO;
}
return YES;
}
+ (BOOL)validateAge:(NSInteger)age
error:(NSError **)error {
return [NumericValidator isValidInteger:age min:13 max:120 error:error];
}
+ (BOOL)validateUserDictionary:(NSDictionary *)userDict
error:(NSError **)error {
// Check required fields
NSArray *requiredKeys = @[@"username", @"password", @"age", @"email"];
if (![CollectionValidator isValidDictionary:userDict
requiredKeys:requiredKeys
error:error]) {
return NO;
}
// Validate each field
NSString *username = userDict[@"username"];
if (![self validateUsername:username error:error]) {
return NO;
}
NSString *password = userDict[@"password"];
if (![self validatePassword:password error:error]) {
return NO;
}
NSNumber *ageNum = userDict[@"age"];
if (![self validateAge:ageNum.integerValue error:error]) {
return NO;
}
NSString *email = userDict[@"email"];
if (![StringValidator isValidEmail:email error:error]) {
return NO;
}
return YES;
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Parameter Validation Examples ===\n");
NSError *error = nil;
// 1. String validation
NSLog(@"--- 1. String Validation ---");
BOOL valid = [StringValidator isValidString:@"test" error:&error];
NSLog(@"Valid string: %@", valid ? @"YES" : @"NO");
valid = [StringValidator isValidString:@"" error:&error];
NSLog(@"Empty string valid: %@", valid ? @"YES" : @"NO");
if (!valid) NSLog(@" Error: %@", error.localizedDescription);
valid = [StringValidator isValidEmail:@"[email protected]" error:&error];
NSLog(@"Valid email: %@", valid ? @"YES" : @"NO");
valid = [StringValidator isValidEmail:@"invalid" error:&error];
NSLog(@"Invalid email: %@", valid ? @"YES" : @"NO");
if (!valid) NSLog(@" Error: %@", error.localizedDescription);
valid = [StringValidator isValidURL:@"https://example.com" error:&error];
NSLog(@"Valid URL: %@", valid ? @"YES" : @"NO");
// 2. Numeric validation
NSLog(@"\n--- 2. Numeric Validation ---");
valid = [NumericValidator isValidInteger:50 min:1 max:100 error:&error];
NSLog(@"50 in range [1,100]: %@", valid ? @"YES" : @"NO");
valid = [NumericValidator isValidInteger:150 min:1 max:100 error:&error];
NSLog(@"150 in range [1,100]: %@", valid ? @"YES" : @"NO");
if (!valid) NSLog(@" Error: %@", error.localizedDescription);
valid = [NumericValidator isPositive:10 error:&error];
NSLog(@"10 is positive: %@", valid ? @"YES" : @"NO");
valid = [NumericValidator isNonNegative:-5 error:&error];
NSLog(@"-5 is non-negative: %@", valid ? @"YES" : @"NO");
// 3. Collection validation
NSLog(@"\n--- 3. Collection Validation ---");
NSArray *array = @[@1, @2, @3];
valid = [CollectionValidator isValidArray:array minCount:1 maxCount:5 error:&error];
NSLog(@"Array with 3 items [1,5]: %@", valid ? @"YES" : @"NO");
valid = [CollectionValidator arrayContains:array type:[NSNumber class] error:&error];
NSLog(@"Array contains only numbers: %@", valid ? @"YES" : @"NO");
NSDictionary *dict = @{@"name": @"John", @"age": @30};
NSArray *requiredKeys = @[@"name", @"age"];
valid = [CollectionValidator isValidDictionary:dict requiredKeys:requiredKeys error:&error];
NSLog(@"Dictionary has required keys: %@", valid ? @"YES" : @"NO");
// 4. User input validation
NSLog(@"\n--- 4. User Input Validation ---");
valid = [UserInputValidator validateUsername:@"john_doe" error:&error];
NSLog(@"Username 'john_doe' valid: %@", valid ? @"YES" : @"NO");
valid = [UserInputValidator validatePassword:@"Pass123" error:&error];
NSLog(@"Password 'Pass123' valid: %@", valid ? @"YES" : @"NO");
valid = [UserInputValidator validateAge:25 error:&error];
NSLog(@"Age 25 valid: %@", valid ? @"YES" : @"NO");
// 5. Complete user validation
NSLog(@"\n--- 5. Complete User Validation ---");
NSDictionary *validUser = @{
@"username": @"jane_doe",
@"password": @"SecurePass123",
@"age": @28,
@"email": @"[email protected]"
};
valid = [UserInputValidator validateUserDictionary:validUser error:&error];
NSLog(@"Valid user dictionary: %@", valid ? @"YES" : @"NO");
NSDictionary *invalidUser = @{
@"username": @"ab",
@"password": @"weak",
@"age": @10,
@"email": @"not-an-email"
};
valid = [UserInputValidator validateUserDictionary:invalidUser error:&error];
NSLog(@"Invalid user dictionary: %@", valid ? @"YES" : @"NO");
if (!valid) NSLog(@" Error: %@", error.localizedDescription);
NSLog(@"\n=== Parameter Validation Examples Completed ===");
}
return 0;
}
💻 Ausnahmebehandlung objectivec
🟡 intermediate
⭐⭐⭐
Ausnahmen mit @try-@catch-@finally-Blöcken und NSException behandeln
⏱️ 25 min
🏷️ objectivec, macos, error handling, exception
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Exception Handling Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic Exception Handling
@interface ExceptionHandler : NSObject
+ (void)demonstrateBasicException;
+ (void)demonstrateMultipleCatchBlocks;
+ (void)demonstrateFinallyBlock;
@end
@implementation ExceptionHandler
+ (void)demonstrateBasicException {
NSLog(@"--- Basic Exception Handling ---");
@try {
NSLog(@"Entering try block");
// Throw an exception
[NSException raise:@"TestException"
format:@"This is a test exception"];
NSLog(@"This will not execute");
}
@catch (NSException *exception) {
NSLog(@"Caught exception: %@", exception.name);
NSLog(@"Reason: %@", exception.reason);
}
@finally {
NSLog(@"Finally block always executes");
}
NSLog(@"\nContinuing after exception handling\n");
}
+ (void)demonstrateMultipleCatchBlocks {
NSLog(@"--- Multiple Catch Blocks ---");
@try {
NSLog(@"Entering try block");
// Simulate different exception types
NSInteger exceptionType = 1; // Change to test different exceptions
switch (exceptionType) {
case 1:
[NSException raise:@"InvalidArgumentException"
format:@"Invalid argument provided"];
break;
case 2:
[NSException raise:@"RangeException"
format:@"Index out of bounds"];
break;
default:
[NSException raise:@"GenericException"
format:@"Something went wrong"];
}
}
@catch (NSException *exception) {
if ([exception.name isEqualToString:@"InvalidArgumentException"]) {
NSLog(@"Caught invalid argument: %@", exception.reason);
} else if ([exception.name isEqualToString:@"RangeException"]) {
NSLog(@"Caught range exception: %@", exception.reason);
} else {
NSLog(@"Caught generic exception: %@", exception.reason);
}
}
@finally {
NSLog(@"Cleanup in finally block");
}
NSLog(@"\n");
}
+ (void)demonstrateFinallyBlock {
NSLog(@"--- Finally Block Demo ---");
NSFileHandle *fileHandle = nil;
BOOL success = NO;
@try {
NSLog(@"Opening file");
// Simulate file operations
NSString *testFile = @"/tmp/test_exception.txt";
[@("Test content") writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
fileHandle = [NSFileHandle fileHandleForReadingAtPath:testFile];
success = YES;
// Simulate an exception
if (YES) {
[NSException raise:@"FileException"
format:@"Error processing file"];
}
}
@catch (NSException *exception) {
NSLog(@"Caught exception: %@", exception.reason);
success = NO;
}
@finally {
NSLog(@"Finally block: Cleaning up resources");
if (fileHandle) {
[fileHandle closeFile];
NSLog(@"File handle closed");
}
// Cleanup test file
[[NSFileManager defaultManager] removeItemAtPath:@"/tmp/test_exception.txt" error:nil];
}
NSLog(@"Operation completed %@\n", success ? @"successfully" : @"with errors");
}
@end
// MARK: - 2. Custom Exception Classes
@interface CustomValidationException : NSException
+ (instancetype)exceptionWithReason:(NSString *)reason
field:(NSString *)field
value:(id)value;
@property (nonatomic, readonly) NSString *field;
@property (nonatomic, readonly) id value;
@end
@implementation CustomValidationException
+ (instancetype)exceptionWithReason:(NSString *)reason
field:(NSString *)field
value:(id)value {
NSString *fullReason = [NSString stringWithFormat:@"Field '%@' failed validation: %@ (value: %@)",
field, reason, value];
CustomValidationException *exception = [[CustomValidationException alloc]
initWithName:@"ValidationException"
reason:fullReason
userInfo:@{@"field": field, @"value": value ?: [NSNull null]}];
return exception;
}
- (NSString *)field {
return self.userInfo[@"field"];
}
- (id)value {
return self.userInfo[@"value"];
}
@end
// MARK: - 3. Exception in Methods
@interface SafeCalculator : NSObject
+ (NSInteger)divide:(NSInteger)numerator
by:(NSInteger)denominator
error:(NSError **)error;
+ (NSInteger)safeDivide:(NSInteger)numerator
by:(NSInteger)denominator
error:(NSError **)error;
@end
@implementation SafeCalculator
+ (NSInteger)divide:(NSInteger)numerator
by:(NSInteger)denominator
error:(NSError **)error {
if (denominator == 0) {
[NSException raise:@"DivisionByZeroException"
format:@"Cannot divide %ld by zero", (long)numerator];
}
return numerator / denominator;
}
+ (NSInteger)safeDivide:(NSInteger)numerator
by:(NSInteger)denominator
error:(NSError **)error {
if (denominator == 0) {
if (error) {
*error = [NSError errorWithDomain:@"CalculatorError"
code:1001
userInfo:@{
NSLocalizedDescriptionKey: @"Division by zero",
NSLocalizedFailureReasonErrorKey: @"Cannot divide by zero",
@"numerator": @(numerator)
}];
}
return 0;
}
return numerator / denominator;
}
@end
// MARK: - 4. Nested Exception Handling
@interface NestedExceptionDemo : NSObject
+ (void)innerMethod;
+ (void)middleMethod;
+ (void)outerMethod;
@end
@implementation NestedExceptionDemo
+ (void)innerMethod {
@throw [NSException exceptionWithName:@"InnerException"
reason:@"Error in inner method"
userInfo:nil];
}
+ (void)middleMethod {
@try {
NSLog(@"Middle method: calling inner method");
[self innerMethod];
}
@catch (NSException *exception) {
NSLog(@"Middle method caught: %@", exception.name);
// Re-throw with additional context
@throw [NSException exceptionWithName:@"MiddleException"
reason:[NSString stringWithFormat:@"Wrapped: %@", exception.reason]
userInfo:@{@"originalException": exception.name}];
}
}
+ (void)outerMethod {
@try {
NSLog(@"Outer method: calling middle method");
[self middleMethod];
}
@catch (NSException *exception) {
NSLog(@"Outer method caught: %@", exception.name);
NSLog(@"Original exception: %@", exception.userInfo[@"originalException"]);
}
}
@end
// MARK: - 5. Exception with Resource Management
@interface ResourceManager : NSObject
@property (nonatomic, strong) NSMutableArray *resources;
- (void)allocateResource:(NSString *)resourceName;
- (void)releaseAllResources;
- (void)demonstrateResourceCleanup;
@end
@implementation ResourceManager
- (instancetype)init {
self = [super init];
if (self) {
_resources = [NSMutableArray array];
}
return self;
}
- (void)allocateResource:(NSString *)resourceName {
[self.resources addObject:resourceName];
NSLog(@"Allocated resource: %@", resourceName);
}
- (void)releaseAllResources {
for (NSString *resource in self.resources) {
NSLog(@"Released resource: %@", resource);
}
[self.resources removeAllObjects];
}
- (void)demonstrateResourceCleanup {
@try {
NSLog(@"--- Resource Management with Exceptions ---");
[self allocateResource:@"Database Connection"];
[self allocateResource:@"File Handle"];
[self allocateResource:@"Network Socket"];
// Simulate an exception
if (YES) {
[NSException raise:@"ResourceException"
format:@"Error during resource usage"];
}
}
@catch (NSException *exception) {
NSLog(@"Exception caught: %@", exception.reason);
}
@finally {
NSLog(@"Cleaning up all resources");
[self releaseAllResources];
}
NSLog(@"\n");
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Exception Handling Examples ===\n");
// 1. Basic exception handling
NSLog(@"1. BASIC EXCEPTION HANDLING\n");
[ExceptionHandler demonstrateBasicException];
[ExceptionHandler demonstrateMultipleCatchBlocks];
[ExceptionHandler demonstrateFinallyBlock];
// 2. Custom exceptions
NSLog(@"2. CUSTOM EXCEPTIONS\n");
@try {
@throw [CustomValidationException exceptionWithReason:@"Cannot be empty"
field:@"username"
value:@""];
}
@catch (CustomValidationException *e) {
NSLog(@"Validation Error:");
NSLog(@" Field: %@", e.field);
NSLog(@" Value: %@", e.value);
NSLog(@" Reason: %@", e.reason);
}
NSLog(@"\n");
// 3. Exception in methods
NSLog(@"3. EXCEPTION IN METHODS\n");
@try {
NSInteger result = [SafeCalculator divide:10 by:0 error:nil];
NSLog(@"Result: %ld", (long)result);
}
@catch (NSException *exception) {
NSLog(@"Caught: %@", exception.reason);
}
// Safe version with NSError
NSError *error = nil;
NSInteger result = [SafeCalculator safeDivide:10 by:0 error:&error];
if (error) {
NSLog(@"Safe method returned error: %@", error.localizedDescription);
NSLog(@"Result: %ld", (long)result);
}
NSLog(@"\n");
// 4. Nested exception handling
NSLog(@"4. NESTED EXCEPTION HANDLING\n");
[NestedExceptionDemo outerMethod];
NSLog(@"\n");
// 5. Resource management
NSLog(@"5. RESOURCE MANAGEMENT\n");
ResourceManager *manager = [[ResourceManager alloc] init];
[manager demonstrateResourceCleanup];
// 6. Exception information
NSLog(@"6. EXCEPTION INFORMATION\n");
@try {
NSDictionary *userInfo = @{
@"errorCode": @(500),
@"requestId": @"req-12345",
@"timestamp": @([NSDate date].timeIntervalSince1970)
};
[NSException raise:@"APIException"
format:@"API request failed"
userInfo:userInfo];
}
@catch (NSException *exception) {
NSLog(@"Exception name: %@", exception.name);
NSLog(@"Exception reason: %@", exception.reason);
NSLog(@"User info: %@", exception.userInfo);
NSLog(@"Call stack symbols:");
NSArray *callStack = exception.callStackSymbols;
for (NSString *symbol in callStack) {
NSLog(@" %@", symbol);
}
}
NSLog(@"\n=== Exception Handling Examples Completed ===");
}
return 0;
}