首先,我是一名 Objective-C 新手。所以我对 OS X 或 iOS 开发不是很熟悉。我的经验主要是在 Java 中。
我正在创建一个基于代理的建模框架。我想显示模拟并为此编写一个小应用程序。首先,关于框架。该框架有一个World
类,其中有一个start
方法,该方法遍历所有代理并让它们执行其任务。在世界的一个“步骤”结束时(即,在所有代理都完成了他们的事情之后),该start
方法调用intercept
实现的对象的方法InterceptorProtocol
。该对象之前是通过构造函数传入的。使用拦截器,任何人都可以了解世界的状态。这对于日志记录很有用,或者在我试图完成的场景中:以图形方式显示信息。调用intercept
是同步的。
现在就 GUI 应用程序而言,它非常简单。我有一个初始化自定义视图的控制器。这个自定义视图还实现InterceptorProtocol
了它可以监听世界上发生的事情。我创建一个World
对象并将视图作为拦截器传递。视图通过私有属性维护对世界的引用,因此一旦我初始化了世界,我将视图的世界属性设置为我刚刚创建的世界(我意识到这会创建一个循环,但我需要对视图方法中的世界,drawRect
我能拥有它的唯一方法是如果我从类中保持对它的引用)。
由于世界的start
方法是同步的,我不会立即启动世界。在drawRect
方法中,我检查世界是否正在运行。如果不是,我在后台线程中启动它。如果是,我会检查这个世界并显示我需要的所有图形。
在方法中(从后台线程上运行intercept
调用),我设置为. 由于世界的方法在一个单独的线程中运行,所以我还有一个用于同步的锁定对象,这样我就不会在它被变异时处理该对象(这部分有点笨拙,它可能不工作我期望它的方式 - 有不止几个粗糙的地方,我只是想努力工作;我计划稍后清理)。start
setNeedsToDisplay
YES
start
World
我的问题是视图渲染了一些东西,然后它几乎被锁定了。我可以看到NSLog
正在调用语句,因此代码正在运行,但视图上没有任何更新。
这是一些相关的代码:
主视图控制器
#import "MasterViewController.h"
#import "World.h"
#import "InfectableBug.h"
@interface MasterViewController ()
@end
@implementation MasterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_worldView = [[WorldView alloc] init];
World* world = [[World alloc] initWithName: @"Bhumi"
rows: 100
columns: 100
iterations: 2000
snapshotInterval: 1
interceptor: _worldView];
for(int i = 0; i < 999; i++) {
NSMutableString* name = [NSMutableString stringWithString: @"HealthyBug"];
[name appendString: [[NSNumber numberWithInt: i] stringValue]];
[world addBug: [[InfectableBug alloc] initWithWorld: world
name: name
layer: @"FirstLayer"
infected: NO
infectionRadius: 1
incubationPeriod: 10
infectionStartIteration: 0]];
}
NSLog(@"Added all bugs. Going to add infected");
[world addBug: [[InfectableBug alloc] initWithWorld: world
name: @"InfectedBug"
layer: @"FirstLayer"
infected: YES
infectionRadius: 1
incubationPeriod: 10
infectionStartIteration: 0]];
[_worldView setWorld: world];
//[world start];
}
return self;
}
- (NSView*) view {
return self.worldView;
}
@end
世界观
#import "WorldView.h"
#import "World.h"
#import "InfectableBug.h"
@implementation WorldView
@synthesize world;
- (id) initWithFrame:(NSRect) frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void) drawRect:(NSRect) dirtyRect {
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
CGContextClearRect(myContext, CGRectMake(0, 0, 1024, 768));
NSUInteger rows = [world rows];
NSUInteger columns = [world columns];
NSUInteger cellWidth = 1024 / columns;
NSUInteger cellHeight = 768 / rows;
if([world running]) {
@synchronized (_lock) {
//Ideally we would need layers, but for now let's just get this to display
NSArray* bugs = [world bugs];
NSEnumerator* enumerator = [bugs objectEnumerator];
InfectableBug* bug;
while ((bug = [enumerator nextObject])) {
if([bug infected] == YES) {
CGContextSetRGBFillColor(myContext, 128, 0, 0, 1);
} else {
CGContextSetRGBFillColor(myContext, 0, 0, 128, 1);
}
NSLog(@"Drawing bug %@ at %lu, %lu with width %lu and height %lu", [bug name], [bug x] * cellWidth, [bug y] * cellHeight, cellWidth, cellHeight);
CGContextFillRect(myContext, CGRectMake([bug x] * cellWidth, [bug y] * cellHeight, cellWidth, cellHeight));
}
}
} else {
[world performSelectorInBackground: @selector(start) withObject: nil];
}
}
- (BOOL) isFlipped {
return YES;
}
- (void) intercept: (World *) aWorld {
struct timespec time;
time.tv_sec = 0;
time.tv_nsec = 500000000L;
//nanosleep(&time, NULL);
@synchronized (_lock) {
[self setNeedsDisplay: YES];
}
}
@end
World.m中的启动方法:
- (void) start {
running = YES;
while(currentIteration < iterations) {
@autoreleasepool {
[bugs shuffle];
NSEnumerator* bugEnumerator = [bugs objectEnumerator];
Bug* bug;
while((bug = [bugEnumerator nextObject])) {
NSString* originalLayer = [bug layer];
NSUInteger originalX = [bug x];
NSUInteger originalY = [bug y];
//NSLog(@"Bug %@ is going to act and location %i:%i is %@", [bug name], [bug x], [bug y], [self isOccupied: [bug layer] x: [bug x] y: [bug y]] ? @"occupied" : @"not occupied");
[bug act];
//NSLog(@"Bug has acted");
if(![originalLayer isEqualToString: [bug layer]] || originalX != [bug x] || originalY != [bug y]) {
//NSLog(@"Bug has moved");
[self moveBugFrom: originalLayer atX: originalX atY: originalY toLayer: [bug layer] atX: [bug x] atY: [bug y]];
//NSLog(@"Updated bug position");
}
}
if(currentIteration % snapshotInterval == 0) {
[interceptor intercept: self];
}
currentIteration++;
}
}
//NSLog(@"Done.");
}
如果您想查看任何其他代码,请告诉我。我意识到代码并不漂亮。我只是想让东西正常工作,我计划稍后清理它。另外,如果我违反了 Objective-C 最佳实践,请告诉我!
走出去一点;抱歉,如果我没有立即回复!