在Objective-C中预处理循环

5
我正在编写一个程序,帮助我控制复杂的灯光安装。我的想法是告诉程序启动一个预设值,然后应用程序有三个选项(取决于预设类型):
1. 灯光移到一个位置(因此当预设开始时只发送一组数据) 2. 灯光遵循数学方程(例如:正弦曲线并设置计时器以使圆形平滑过渡) 3. 灯光响应数据流(例如midi控制器)
因此,我决定使用一个被称为AppBrain的对象,它接收来自控制器和模板的数据,但也能够将处理过的数据发送到灯光。
现在,我来自非本地编程背景,对于处理、事件和时间方面有信任问题;以及理解Cocoa逻辑方面也存在困难。
这是实际问题的开始,抱歉。
我想要做的是,在加载预设值时,解析它以准备计时器/数据接收事件,以便不必每秒为100个灯光执行100次所有选项。
更深入地解释一下,在JavaScript中我会如何做(当然,这是糟糕的伪代码):
var lightsFunctions = {};

function prepareTemplate(theTemplate){
    //Let's assume here the template is just an array, and I won't show all the processing

    switch(theTemplate.typeOfTemplate){
        case "simpledata":
            sendAllDataTooLights(); // Simple here
            break;

        case "periodic":


               for(light in theTemplate.lights){

                    switch(light.typeOfEquation){
                        case "sin":
                            lightsFunctions[light.id] = doTheSinus; // doTheSinus being an existing function
                            break;

                        case "cos":

                            ...
                     }
                }


               function onFrame(){
                    for(light in lightsFunctions){
                        lightsFunctions[light]();
                    }
               }

                var theTimer = setTimeout(onFrame, theTemplate.delay);

                break;

            case "controller":

                //do the same pre-processing without the timer, to know which function to execute for which light

                break;

    }


    }

}

我的想法是将我需要的处理函数存储在NSArray中,这样我就不需要在每个帧上测试类型并浪费时间/CPU。我不知道自己表达清楚了没有,或者我的想法是否可行/可行。我主要是在寻找算法思路,如果您有一些可能指引我走向正确方向的代码...(我知道PerformSelector,但我不知道它是否适用于此情况。感谢;I_

4
先不要进行优化来构建它。在本地环境下,每秒钟执行 100*100 次 sin() 调用并不算什么。即使是 iPhone 5 也可以每秒钟执行约 600 万个 sin() 计算。 - mvds
告诉你吧,我对一些无关紧要的事情很害怕!但我就是停不下来想着如果在万人面前所有的灯都坏了会怎么样...目前我正在使用ARC来保护自己,但我又对自动化的东西缺乏信任... - Moustach
作为一个旁注,即使使用ARC,你仍然需要了解内存。ARC有“奇怪”的规则(更精确地说,使用ARC进行内存管理更加复杂),这部分是我建议你学习并最初使用MRC的原因之一。不要期望ARC是魔法! :) 顺便说一句,不错的第一个问题,+1。 - user529758
1个回答

4
首先,不要浪费时间优化你不确定是否存在性能问题的部分。在本地环境下,即使在较弱的移动CPU上,100次迭代也毫无意义。
现在,来看看你的问题。我猜你正在编写某种配置/DSL以指定灯控制序列。一种做法是将blocks存储在你的NSArray中。块是JavaScript中函数对象的等价物。例如:
typedef void (^LightFunction)(void);

- (NSArray*) parseProgram ... {
    NSMutableArray* result = [NSMutableArray array];
    if(...) {
        LightFunction simpledata = ^{ sendDataToLights(); };
        [result addObject:simpleData];
    } else if(...) {
        Light* light = [self getSomeLight:...];
        LightFunction periodic = ^{
            // Note how you can access the local scope of the outside function.
            // Make sure you use automatic reference counting for this.
            [light doSomethingWithParam:someParam];
        };
        [result addObject:periodic];
    }
    return result;
}
...
NSArray* program = [self parseProgram:...];

// To run your program
for(LightFunction func in program) {
    func();
}

1
一个代码块不等同于函数对象,请不要混淆。它是一个对象,但它比函数更强大。它会对内存管理进行疯狂的操作(保留周期),有一些奇怪的调用方式(调用一个“nil”块会导致 SIGABRT 错误),以及其他许多怪异之处。它更像一个传统的函数指针而非函数对象。 - Richard J. Ross III
嗯,看起来确实非常不错!那么我的问题是,是否可能将其存储为对象属性,这样我就可以做类似于[light prepareWithAction:...]; .... [light update];其中update当然是块? - Moustach
是的,您可以访问块范围外的本地变量。它的工作方式类似于JavaScript。请参阅更新后的示例。 - Krumelur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接