Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/116.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将NSCoding对象写入磁盘时性能下降_Ios_Objective C - Fatal编程技术网

Ios 将NSCoding对象写入磁盘时性能下降

Ios 将NSCoding对象写入磁盘时性能下降,ios,objective-c,Ios,Objective C,我正在开发一款iOS游戏,它可以生成大量的2d瓷砖,用户可以“无限”移动 仅用于上下文:每个磁贴为32x32px,每个“块”包含4x4个磁贴(总共16个)。大多数磁贴都是空的,但是当有东西放在磁贴上时,如果用户移动得太远,并且该区块“卸载”,我会将区块和磁贴数据保存到磁盘上 现在,区块和磁贴都使用NSCoding协议。区块保存了磁贴的NSArray和几个布尔值,每个磁贴保存了几个数字/布尔值 这是完美的-当区块卸载它保存时,当区块再次加载时,它被还原 然而,我注意到,write-to-disk方

我正在开发一款iOS游戏,它可以生成大量的2d瓷砖,用户可以“无限”移动

仅用于上下文:每个磁贴为32x32px,每个“块”包含4x4个磁贴(总共16个)。大多数磁贴都是空的,但是当有东西放在磁贴上时,如果用户移动得太远,并且该区块“卸载”,我会将区块和磁贴数据保存到磁盘上

现在,区块和磁贴都使用
NSCoding
协议。区块保存了磁贴的
NSArray
和几个布尔值,每个磁贴保存了几个数字/布尔值

这是完美的-当区块卸载它保存时,当区块再次加载时,它被还原

然而,我注意到,write-to-disk方法非常短暂地杀死了我的FPS。由于玩家移动时通常会有几个块卸载到一起,卸载时,玩家已经移动得越来越远,卸载量也越来越大,这就增加了

我已经尽我所能确保只保存具有实际更改的块,并且我更好地组织了保存代码,以避免每次保存调用都实例化对象

有没有更好的方法可以在不影响FPS的情况下保存数据

  • 由于我通常保存屏幕上看不到的数据,我可以异步保存吗
  • 有没有比NSCoding更快的方法,因为每个类只有一些float/bool值
以下是区块保存代码:

-(void)saveToDisk {
    if( !self.hasUnsavedChanges ){
        NSLog(@"skipping saving chunk that has not changed");
        return;
    }
    [self.saveFile writeData:self withKey:self.savefileKey];
    self.hasUnsavedChanges = false;
}

-(void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:[NSNumber numberWithFloat:self.position.x] forKey:@"chunk.x"];
    [encoder encodeObject:[NSNumber numberWithFloat:self.position.y] forKey:@"chunk.y"];
    [encoder encodeObject:tiles forKey:@"chunk.tiles"];
}

-(id)initWithCoder:(NSCoder *)decoder {

    Chunk *restore = [self init];

    NSNumber *xChunkNum = [decoder decodeObjectForKey:@"chunk.x"];
    NSNumber *yChunkNum = [decoder decodeObjectForKey:@"chunk.y"];
    restore.position = [Coord coordWithX:[xChunkNum intValue] Y:[yChunkNum intValue]];

    tiles = [decoder decodeObjectForKey:@"chunk.tiles"];

    return restore;
}
和瓷砖代码:

-(void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:[NSNumber numberWithFloat:self.worldContextCoordinate.x] forKey:@"tile.world.x"];
    [encoder encodeObject:[NSNumber numberWithFloat:self.worldContextCoordinate.y] forKey:@"tile.world.y"];
    [encoder encodeObject:[NSNumber numberWithFloat:self.color.red] forKey:@"tile.color.red"];
    [encoder encodeObject:[NSNumber numberWithFloat:self.color.green] forKey:@"tile.color.green"];
    [encoder encodeObject:[NSNumber numberWithFloat:self.color.blue] forKey:@"tile.color.blue"];
    [encoder encodeObject:[NSNumber numberWithFloat:self.isSourceTile] forKey:@"tile.isSource"];forKey:@"tile.hasBlackNeighbor"];
}

-(id)initWithCoder:(NSCoder *)decoder {

    Tile *restore = [self init];

    NSNumber *xNum = [decoder decodeObjectForKey:@"tile.world.x"];
    NSNumber *yNum = [decoder decodeObjectForKey:@"tile.world.y"];
    [restore setWorldContextCoordinate:b2Vec2( [xNum floatValue], [yNum floatValue] )];

    NSNumber *red = [decoder decodeObjectForKey:@"tile.color.red"];
    NSNumber *green = [decoder decodeObjectForKey:@"tile.color.green"];
    NSNumber *blue = [decoder decodeObjectForKey:@"tile.color.blue"];

    restore.color = [CCColor colorWithRed:[red floatValue] green:[green floatValue] blue:[blue floatValue]];

    restore.isSourceTile = [decoder decodeObjectForKey:@"tile.isSource"];

    return restore;
}

考虑到您不需要担心影响UI或UX的完成事件,您应该能够异步运行这些事件。如果需要,也可以使用完成块来完成此操作,以便在必要时处理完成事件

- (void)saveToDiskAsyncWithCompletion:(void(^)(BOOL finished))completion
{    
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NO), ^{
        [self saveToDisk];
        // or you could run any of your other operations here too.
        dispatch_async(dispatch_get_main_queue(), ^(void){
            completion(YES);
        });
    });
}

您是否依赖于保存这些文件的完成?如中所示,是否会发生一个事件,要求在开始之前将它们保存到磁盘?如果是这样的话,那么异步可能会是一场噩梦,即使有了完成块。除了CoreData之外,您可能在NSCoding方面走对了方向。不是真的。这些通常在我“卸载”它们时保存—当用户离开并且不再需要“土地”时。最终结果所需要的只是当数据再次加载时,当用户返回此位置并加载区块数据时。使用探查器和/或时间日志来确定时间在哪里。然后你可以决定加速什么。您将知道NSCoding所花费的时间与磁盘写入时间之比。您认为有没有可能通过异步加载数据来避免这种情况?查看新的评测数据和my Tile对象的initWithCoder仍然是一段相当长的时间,仍然会影响fps。有一点-您需要在方法中使用类似的完成块,以便在完成时通知系统。调用该方法时,将UI更新放在完成块中。