0

我有带有属性的对象,当我更改一些属性时,我会进行大量计算。如果我更改一个属性,然后更改另一个属性,则计算执行 2 次。我想进行所有计算 1 次。我看到3个解决方案:

  1. 制作方法commit。但我不想做多余的方法。
  2. 更改所有属性的方法。我不想这样做的原因相同。如果我将来有更多的房产该怎么办。
  3. 在延迟提交更改后进行延迟。我真的不知道这可能会导致什么后果。像这样的东西:

.

@interface TestObject : NSObject
@property (nonatomic, assign) float x;
@property (nonatomic, assign) float y;
@end

@implementation TestObject
{
    BOOL flag;
}

- (id)init
{
    self = [super init];
    if(self){
        flag = NO;
    }
    return self;
}

- (void)setX:(float)x
{
    _x = x;
    [self delayCommit];
}

- (void)setY:(float)y
{
    _y = y;
    [self delayCommit];
}

- (void)delayCommit
{
    if(flag == NO){
        flag = YES;
        [self performSelector:@selector(commit) withObject:nil afterDelay:0];
    }
}

- (void)commit
{
    flag = NO;
    NSLog(@"Do a lot of calculations....");
}

@end

第三个解决方案是好的做法吗?我想要简单的界面,我不想要多余的方法。

4

3 回答 3

1

如果您真的想要这样的行为,那么您应该有一个计时器,N每秒钟检查一次是否更改了任何属性,并进行计算。就像是:

- (void)setX:(float)x
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(_mySem, DISPATCH_TIME_FOREVER);
        _x = x;
        flag = YES;
        dispatch_semaphore_signal(_mySem);
    });  
}

- (void)setY:(float)y
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(_mySem, DISPATCH_TIME_FOREVER);
        _y = y;
        flag = YES;
        dispatch_semaphore_signal(_mySem);
    });  
}

- (void)updateCycle
{        
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(_mySem, DISPATCH_TIME_FOREVER);
        if(flag){
            flag = NO;
            NSLog(@"Do a lot of calculations....");
        }
        dispatch_semaphore_signal(_mySem);
    });           
}

在您的init方法中,您必须使用

_mySem = dispatch_semaphore_create(1);
[NSTimer scheduledTimerWithTimeInterval:N 
                                 target:self 
                               selector:@selector(updateCycle) 
                               userInfo:nil 
                                repeats:YES];

那么使用它的方法就是:

[object setX:4.5f];
[object setY:0.3f];
于 2013-09-30T08:15:17.333 回答
0

根据您拥有的属性数量,这可能对您有用:

- (void)setX:(float)x y:(float)y
{
    _x = x;
    _y = y;
    [self commit];
}

在这里,您通过一个方法调用设置了多个属性。你知道你有你需要的所有值,所以你可以commit直接调用。

于 2013-09-30T07:55:08.717 回答
0

我建议您不要对延迟提交过于花哨(除非您真的必须这样做),并将提交用作单独的调用并在单独的线程中执行您的长计算,例如:

- (void)setX:(float)x
{
    _x = x;
}

- (void)setY:(float)y
{
    _y = y;
}

- (void)commitChanges
{
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // ... Long calculations go here ...
    dispatch_async(dispatch_get_main_queue(), ^{
      // ... Once you done with your long calculation, put your UI code here
      // ... (e.g. display results of your calculation in text box)
    });
   });
}

然后从你的主要代码看起来像:

[obj setX:123.0f];
[obj setY:345.0f];
[obj commitChanges];
于 2013-09-30T08:31:27.613 回答