如何对未定义的选择器的警告在Objective C中工作? [英] How do warnings on undefined selectors work in Objective C?

查看:118
本文介绍了如何对未定义的选择器的警告在Objective C中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法使编译器在调用未定义的选择器时发出警告?例如,我有这个调用某处:

  methodcall time1:[[self.H1time copy] stringValue] 

stringValue方法在H1time类中不再存在,编译器没有提出任何内容。



copyWithZone声明为

   - (NSHour *)copyWithZone: 

如果调用 [self stringValue],编译器会在NSHour中引发一个警告
但不在 methodcall time1:[[self.H1time copy] stringValue]



只因为密集测试,随后发生崩溃。



我想编译器阻止我这样错误的调用。
我该如何做?



有些测试表明编译器可能在上述情况下警告:

  NSHour * titi = [NSHour hourWithString:@00:00:00]; 
id toto = [titi copy];
NSString * str2 = [toto doThis]; ---警告:没有找到这个方法

另一个测试:

  NSHour * titi = [NSHour hourWithString:@00:00:00]; 
NSString * str3 = [[titi copy] doThis]; ---警告:No doThis Method found


解决方案

如果你希望编译器警告你,将由 -copy 返回的对象转换成你期望的类型,例如

  [(NSHour *)[self.H1time copy] stringValue] 


$ b b

(顺便说一下,我不会为我的类使用NS前缀,因为它是苹果使用的前缀。)



正如其他人所说, code> -copy 被声明为返回类型 id 的值。由于 id 表示一个通用对象,编译器没有关于返回值可以响应哪个选择器的任何信息。它知道存在一个 stringValue 选择器(因为一些Cocoa类声明了 -stringValue 方法),所以它接受



如果你需要自定义复制行为,这是正确的事情,因为 -copy 只是一个方便的方法调用 -copyWithZone:。但是,如上所述,您的代码调用 -copy ,它没有被覆盖以返回 NSHour *



如果我还覆盖 -copy ,以便返回NSHour *? p>

然后编译器会知道,并会警告你,如果你试图发送一个消息包含一个选择器在 NSHour



我应该这样做吗?





你是否曾想过为什么所有重写 -init 的例子都会返回 id 而不是类类型?这是因为Objective-C运行时为给定的选择器创建了一个方法描述。因此,具有相同选择器(即相同的方法名)的不同类中的方法应该共享相同的参数类型和返回类型。



init 被描述为具有该名称和返回类型 id 的方法。同样,选择器 copy 被描述为具有该名称和返回类型 id 的方法。如果在具有不同返回类型或参数类型的方法中重复使用选择器名称,则会混淆运行时系统,从而导致崩溃或数据被破坏。



当你静态地输入对象时,你会向编译器提供信息,以便知道哪些方法可用,并且它将使用适当的方法,而不管其他具有不同返回类型和参数类型的类中的方法。



关于cocoabuilder.com的这个线程有关于这个主题的更多信息,包括Greg Parker的回复,他在Objective-C运行时工作。


Is there any way to make the compiler raise a warning when calling a selector that is not defined ? For example, I have this call somewhere :

methodcall time1:[[self.H1time copy] stringValue]

stringValue method does not exist anymore in the H1time class and the compiler did not raise anything.

copyWithZone is declared as

- (NSHour*)copyWithZone:(NSZone *)zone;

The compiler raises a warning inside NSHour if I call [self stringValue]. but not in methodcall time1:[[self.H1time copy] stringValue]

I saw this miss only because of an intensive test followed with a crash.

I'd like the compiler prevent me of such wrong calls. How may I do this ?

Some tests that says that the compiler may warn in the above case :

NSHour *titi = [NSHour hourWithString:@"00:00:00"];
    id toto = [titi copy];
NSString *str2 = [toto doThis];  --- Warning : "No doThis Method found"

Another test :

NSHour *titi = [NSHour hourWithString:@"00:00:00"];
NSString *str3 = [[titi copy] doThis];  --- Warning : "No doThis Method found"

解决方案

If you want the compiler to warn you, cast the object returned by -copy to the type you’re expecting, e.g.

[(NSHour *)[self.H1time copy] stringValue]

(by the way, I wouldn’t use the NS prefix for my classes since it’s a prefix used by Apple.)

As others have stated, -copy is declared as returning a value of type id. Since id denotes a generic object, the compiler doesn’t have any information as to which selectors the return value can respond to. It does know that there exists a stringValue selector (because a few Cocoa classes declare -stringValue methods), so it accepts that.

But I’ve overridden -copyWithZone: to return NSHour *!

And that’s the right thing to do if you need custom copying behaviour since -copy is just a convenience method that invokes -copyWithZone:. However, as stated above, your code invokes -copy, which hasn’t been overriden to return NSHour *.

What if I also override -copy so that it returns NSHour *?

Then the compiler would know that and would warn you in case you’re trying to send a message containing a selector that has no corresponding method in NSHour.

Should I do this?

Well, for the most part, not really.

Have you ever wondered why all examples of overriding -init return id instead of a class type? This happens because the Objective-C runtime creates a single method description for a given selector. Consequently, methods in different classes having same selectors (i.e., same method names) should share the same argument types and return types.

So, from the runtime perspective, the selector init is described as a method with that name and return type id. Similarly, the selector copy is described as a method with that name and return type id. If you reuse a selector name in methods with different return types or argument types, you’re confusing the runtime system, which could cause a crash or data being mangled.

That being said, when you’re statically typing your objects, you’re giving information to the compiler so that it knows which methods are available, and it will use the appropriate methods regardless of methods in other classes having different return types and argument types.

This thread on cocoabuilder.com has more information on the subject, including a reply by Greg Parker, who works on the Objective-C runtime.

这篇关于如何对未定义的选择器的警告在Objective C中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆