我想创建绑定到作用域的obj c对象,这样对象就知道何时进入/退出作用域。
这是一个ARC环境。
目标是创建一些日志实用程序,这些实用程序可以轻松地生成封装进程的日志,如以下所示:
onHttpRequest {
deduce encoding - found UTF-8!
parsing xml took 0.08 seconds
unknown request found... sending error.
sendingResponse took 0.02 seconds.
} (0.10 seconds)
这在过去的C++和C#中是很容易的。现在我正在学习obj-c,想不出一种干净的方法。
在C++中,这很容易使用auto
变量:
struct ScopedLogMessage
{
ScopedLogMessage(std::string msg) { debugPrint(indentStr + msg + newline); indent ++; }
~ScopedLogMessage() { indent --; debugPrint(indentStr + "}" + newline); }
}
void onHttpRequest()
{
ScopedLogMessage x("onHttpRequest");
debugPrint("deduce encoding ...");
debugPrint("more stuff ....");
}
或者在C#中,使用IDisposable
和using(){}
块:
class ScopedLogMessage : IDisposable
{
public ScopedLogMessage(string msg) { debugPrint(indentStr + msg + newline); indent ++; }
public void Dispose() { indent --; debugPrint(indentStr + "}" + newline); }
}
static void onHttpRequest()
{
using(ScopedLogMessage x = new ScopedLogMessage("onHttpRequest"))
{
debugPrint("deduce encoding ...");
debugPrint("more stuff ....");
}
}
在objective-C中可以做类似的事情吗?
使用ARC,当变量超出范围时,编译器会自动保留和释放变量,因此代码如下所示:
NSLog(@"Logging at indent level 0");
{
ScopedLogMessage* log1 = [[ScopedLogMessage alloc] initWithMessage:@"Begin nested operations"];
[log1 debugLog:@"Logging at indent level 1"];
{
ScopedLogMessage* log2 = [[ScopedLogMessage alloc] initWithMessage:@"Another level of nested operations" parentLog:log1];
[log2 debugLog:@"Logging at indent level 2"];
}
[log1 debugLog:@"Logging at indent level 1 again"];
}
NSLog(@"Logging at indent level 0 again");
输出将是:
Logging at indent level 0
Begin nested operations {
Logging at indent level 1
Another level of nested operations {
Logging at indent level 2
}
Logging at indent level 1 again
}
Logging at indent level 0 again
ScopedLogMessage类的代码:
ScopedLogMessage.h:
#import <Foundation/Foundation.h>
@interface ScopedLogMessage : NSObject
- (id)initWithMessage:(NSString*)message;
- (id)initWithMessage:(NSString*)message parentLog:(ScopedLogMessage*)parentLog;
- (void)debugLog:(NSString*)message;
@end
ScopedLogMessage.m:
#import "ScopedLogMessage.h"
@interface ScopedLogMessage ()
@property ScopedLogMessage* parentLog;
@property int indent;
@end
@implementation ScopedLogMessage
- (id)initWithMessage:(NSString *)message {
if (self = [super init]) {
[self debugLog:[NSString stringWithFormat:@"%@ {", message]];
self.indent = 1;
}
return self;
}
- (id)initWithMessage:(NSString *)message parentLog:(ScopedLogMessage *)parentLog {
if (self = [super init]) {
self.parentLog = parentLog;
self.indent = parentLog.indent;
[self debugLog:[NSString stringWithFormat:@"%@ {", message]];
self.indent++;
}
return self;
}
- (void)dealloc {
self.indent --;
[self debugLog:@"}"];
}
- (void)debugLog:(NSString*)message {
#ifdef DEBUG
NSString* indentString = [@"" stringByPaddingToLength:self.indent * 4 withString: @" " startingAtIndex:0];
NSLog(@"%@%@", indentString, message);
#endif
}
@end
如您所见,dealloc
方法是关键,相当于C#Dispose
。如果没有ARC,您将被迫释放日志并在dealloc
方法上调用[super dealloc]
。
希望能有所帮助。