iPhone OS: создание оператора switch, который использует строковые литералы в качестве компараторов вместо целых - PullRequest
2 голосов
/ 25 мая 2010

Итак, я хотел бы сделать это:

switch (keyPath) {
    case @"refreshCount":
        //do stuff
    case @"timesLaunched":
       //do other stuff
}

но, видимо, вы можете использовать только целые числа в качестве величины переключения. Является ли единственный способ сделать это, проанализировать строку в целочисленный идентификатор и затем запустить оператор switch?

как это:

nsinteger num = nil;

if (keyPath isEqual:@"refreshCount") {

num = 0

}

if (keyPath isEqual:@"timesLaunched") {

num = 1

}

Я пытаюсь оптимизировать этот код так быстро, насколько это возможно, потому что его будут вызывать довольно часто.

спасибо,

Ник

ПРИМЕЧАНИЕ. Да, я использую KVO, поэтому получаю строку в «обратном вызове».

ПРИМЕЧАНИЕ # 2: Итак, что заставило меня в первую очередь подумать о выражении switch, так это то, что моя оригинальная реализация кода была такой:

if ([keyPath isEqual:@"refreshCount"] && ([[change valueForKey:@"new"] intValue] == 10)) { //  
NSLog(@"achievemnt hit inside");
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"title" message:@"Achievement Unlocked!" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:nil];
    [alert show];

Я хочу сделать кучу таких с разными значениями XX одним и тем же способом:

if ([keyPath isEqual:@"refreshCount"] && ([[change valueForKey:@"new"] intValue] == 10)) {

//unlock small achievement

}
 if ([keyPath isEqual:@"refreshCount"] && ([[change valueForKey:@"new"] intValue] == 50))   {

//unlock bigger achievement

}   

//etc

Мне это показалось очень неэффективным, но, возможно, я ошибаюсь.

Ответы [ 3 ]

6 голосов
/ 25 мая 2010

То есть, чтобы оператор приведения работал, ему просто нужно было бы в любом случае вызвать isEqualToString: и он был бы таким же медленным, но, вероятно, далеко не таким медленным, как вы думаете.

Первый вопрос, конечно, таков: измеряли ли вы производительность, и есть ли у вас доказательства того, что код вызывает проблемы с производительностью?

Если нет, то иди и закончи свое приложение. Приложение доставки всегда превосходит приложение, которое еще находится в разработке!

Держу пари, у вас нет проблем с производительностью; если все ваши строки действительно являются строковыми константами - @"refreshCount" и т. п. - относящимися к наблюдению значения ключа, то вполне вероятно, что все они являются константными строками, скомпилированными в приложение, и, таким образом, сравнение будет очень быстро, потому что каждый раз, когда вы упоминаете "@refreshCount", это действительно одна и та же строка с одним и тем же адресом (который сравнивается очень быстро).

Если у вас есть проблема с производительностью, поддающаяся количественной оценке, опубликуйте детали в другом вопросе, и кто-то может ответить конкретно. На самом деле, недостаточно архитектурной или количественной информации, чтобы делать что-то большее, чем спекулировать.

4 голосов
/ 25 мая 2010

Почему бы просто не использовать enum?

typedef enum _KeyPath
{
     KeyPathNone,
     KeyPathRefreshCount,
     KeyPathTimesLaunched,
     KeyPathCount
} KeyPath;

Если вы должны использовать строки, которые вы должны сравнивать с isEqualToString:

Из документов NSString:

Special Considerations
When you know both objects are strings, this method is a faster way to check equality than isEqual:.
2 голосов
/ 25 мая 2010

Краткий ответ - не использовать строки в первую очередь. За исключением этого, строки могут быть ключами в словаре с целочисленными значениями (NSNumber). Или вы можете использовать хеши строк.

switch ( [keyPath myQuickHash] ) {
case kHashRefreshCount:
case kHashTimesLaunched:
}

Если есть только несколько отдельных строк, вы можете использовать первые (или последние) 4 символа в качестве строкового литерала и считать, что хэш.

switch ( [keyPath stringLiteral] ) {
case 'refr':
case 'time':
}

Edit:

Оператор switch по сути является разреженным массивом фрагментов кода. Хеш-таблица - это средство поиска индекса в разреженном массиве по произвольному значению. При известном наборе строковых входов оператор switch может работать как хеш-таблица, то есть иметь постоянное время поиска. Все, что вам нужно сделать, это выбрать алгоритм хеширования без коллизий для известных входных данных. Если набор входов неизвестен, это не вариант, но в этом вопросе возможно, что все входы известны.

Это не имеет абсолютно никакого отношения к тому, как Apple реализует свой алгоритм хэширования, потому что вы должны реализовать свой собственный алгоритм хэширования. Выбранный алгоритм, вероятно, может быть таким же простым, как сложение длины и букв в строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...