iPhone OS:制作一个 switch 语句,使用字符串文字而不是整数作为比较器

发布于 2024-09-02 12:09:35 字数 1246 浏览 5 评论 0原文

所以我想这样做:

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

这对我来说似乎效率很低,但也许我错了。

So I'd like to do this:

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

but apparently you can only use integers as the switch quantity. Is the only way to do this parse the string into an integer identifier and then run the switch statement?

like this:

nsinteger num = nil;

if (keyPath isEqual:@"refreshCount") {

num = 0

}

if (keyPath isEqual:@"timesLaunched") {

num = 1

}

I'm trying to optimize this code to be as quick as possible because its going to get called quite often.

thanks,

Nick

NOTE: Yes I'm using KVO so I am recieving a string in the "callback."

NOTE #2: So what made me first consider the switch statement is my original code implementation was like this:

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];

I want to do a bunch of these with different XX values all in the same method:

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

This just seemed very inefficient to me but maybe I'm wrong.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撩发小公举 2024-09-09 12:09:36

为什么不直接使用枚举呢?

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

如果您必须使用应该与

NSString 文档中的 isEqualToString: 进行比较的字符串:

Special Considerations
When you know both objects are strings, this method is a faster way to check equality than isEqual:.

Why not just use an enum?

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

If you must use strings that you should be comparing with isEqualToString:

From the NSString docs:

Special Considerations
When you know both objects are strings, this method is a faster way to check equality than isEqual:.
2024-09-09 12:09:36

简短的答案是首先不要使用字符串。除此之外,您可以将字符串作为具有整数 (NSNumber) 值的字典中的键。或者您可以使用字符串的哈希值。

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

如果只有几个不同的字符串,您可以使用前(或最后)4 个字符作为字符串文字,并考虑哈希。

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

编辑:

switch 语句本质上是代码片段的稀疏数组。哈希表是一种在给定任意值的稀疏数组中查找索引的方法。给定一组已知的字符串输入,switch 语句可以像哈希表一样操作,也就是说,具有恒定的查找时间。您所要做的就是选择一种与已知输入不会发生冲突的哈希算法。如果输入集未知,则这不是一个选项,但在这个问题中,所有输入可能都是已知的。

这与苹果如何实现他们的哈希算法完全无关,因为你必须实现你自己的哈希算法。所选择的算法可能就像将字符串中的长度和字母相加一样简单。

The short answer is to not use strings in the first place. Barring that, you can have the strings be keys in a dictionary with integer (NSNumber) values. Or you can use the hashes of the strings.

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

If there are just a few distinct strings, you can use the first (or last) 4 characters as a string literal and consider that the hash.

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

Edit:

A switch statement is essentially a sparse array of code snippets. A hash table is a means of looking up an index in a sparse array given an arbitrary value. Given a known set of string inputs, a switch statement can operate like a hash table, which is to say, have constant lookup time. All you have to do is choose a hash algorithm with no collisions for the known inputs. If the set of inputs is not known, this is not an option, but in this question it is possible that all inputs are known.

This has absolutely nothing to do with how Apple implements their hash algorithm because you have to implement your own hash algorithm. The algorithm chosen could probably be as simple as adding up the length and letters in the string.

吻安 2024-09-09 12:09:35

也就是说,要使强制转换语句起作用,它只需要调用 isEqualToString: 即可,并且速度会一样慢,但可能不会像您想象的那么慢。

当然,第一个问题是您是否测量过性能并且有证据表明代码导致了性能问题?

如果没有,请完成您的应用程序。运输应用程序总是优于仍在开发中的应用程序!

我敢打赌你不会遇到性能问题;如果所有字符串确实都是内联字符串常量 - @"refreshCount" 等 - 与键值观察相关,那么它们很可能都是编译到因此,比较速度会非常快,因为每次提到 "@refreshCount" 时,它实际上都是同一地址处的相同字符串(比较速度非常快)。

如果您确实有可量化的性能问题,请在不同的问题中发布详细信息,然后有人可以具体回答。事实上,除了推测之外,没有足够的架构或定量信息来进行任何操作。

That is, for a cast statement to work, it would just have to call isEqualToString: anyway and would be just as slow, but probably not anywhere near as slow as you think.

The first question, of course, is have you measured performance and do you have evidence that the code is causing a performance issue?

If not, go and finish your app. A shipping app always outperforms an app still in development!

I would bet you don't have a performance issue; if all of your strings really are inline string constants -- @"refreshCount" and the like -- related to key-value observing, then it is quite likely that all of them are constant strings compiled into the app and, thus, comparison will be really fast because every time you mention "@refreshCount" it really is the same string at the same address (which compares very fast).

If you do have a quantifiable performance issue, post the details in a different question and someone can answer specifically. As it is, there isn't enough architectural or quantitative information to do anything more than speculate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文