Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/95.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 这是运行泛型方法的正确方法吗?_Ios_Objective C_Macos_Cocoa_Cocoa Touch - Fatal编程技术网

Ios 这是运行泛型方法的正确方法吗?

Ios 这是运行泛型方法的正确方法吗?,ios,objective-c,macos,cocoa,cocoa-touch,Ios,Objective C,Macos,Cocoa,Cocoa Touch,我有这个方法,应该设置对象的名称,但是对象可以是3个类,A、B和C 如果我这么做的话 [object setName: @"new name"]; //at this point I am treating object as of type id Xcode会抱怨有多个名为“setName”的方法,然后我就这样做了 if ([object isKindOfClass:[ClassA class]]) { [(ClassA *)object setName:newName];

我有这个方法,应该设置对象的名称,但是对象可以是3个类,A、B和C

如果我这么做的话

[object setName: @"new name"];  //at this point I am treating object as of type id
Xcode会抱怨有多个名为“setName”的方法,然后我就这样做了

  if ([object isKindOfClass:[ClassA class]]) {
    [(ClassA *)object setName:newName];
  } else
  if ([object isKindOfClass:[ClassB class]]) {
    [(ClassB *)object setName:newName];
  } else
    [(ClassC *)object setName:newName];
  }
但这在我看来是站不住脚的

我试图用这样的东西愚弄Xcode

    [(typeof(object))object setName:newName];
但是Xcode也不喜欢它,可能是因为
typeof(object)
正在返回
id
,我们又回到了原点。同样的错误


有什么更好/优雅的方法可以做到这一点呢?

更好的方法是让
A
B
C
实现相同的
协议
,该协议将定义一个方法
setName

NameProtocol.h

@protocol NameProtocol <NSObject>

- (void)setName:(NSString *)name;

@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@协议名称协议
-(void)setName:(NSString*)名称;
@结束
A.h

@protocol NameProtocol <NSObject>

- (void)setName:(NSString *)name;

@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@接口A:NSObject
B.h

@protocol NameProtocol <NSObject>

- (void)setName:(NSString *)name;

@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@接口B:NSObject
C.h

@protocol NameProtocol <NSObject>

- (void)setName:(NSString *)name;

@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@接口C:NSObject

使用a类、B类和C类都符合的协议

@protocol MyProtocol <NSObject>
@required
- (void)setName:(NSString *)name;
@end
@protocol-MyProtocol
@必需的
-(void)setName:(NSString*)名称;
@结束
然后

id<MyProtocol> object = ...
[object setName:newName];
id对象=。。。
[对象集合名:newName];

协议是一条可行之路。但你也可以做到:

if ([object respondsToSelector: @selector(setName:)])
{
    [object performSelector: @selector(setName:) withObject: name];
}
使用键值编码

[object setValue:newName forKey:@"name"];
这是一种快速而肮脏的方法,我建议使用协议,但在适当的情况下它可能会很有用


更新

KVC没有编译时类型检查:增加了缺陷的可能性。运行时错误导致异常:缺陷导致应用程序崩溃。它的语法意味着
对象
是一个字典:隐藏代码的意图。这一点很模糊:初级开发人员通常不了解它是如何工作的,并且可能会导致维护问题


这是一个真正的恐怖节目,但在适当的情况下它可能会很有用。

声明的
对象是什么类型的?是否有多个名为
setName
的方法?我们需要了解为什么会出现初始错误?是的,A、B和C类都有setName@LyndseyScott应用程序中还有其他类(甚至可能在CoreFoundation或其他一些Apple库中),它们对
-setName:
具有不同的签名。我想就是这样!谢谢我会尽快接受你的回答,让我来。我本来也打算提出一个协议,但你抢先了我一步。另一种选择是为实现setName方法的所有3个类创建基类。您能描述一下这样做没有用的情况,这可能会导致问题吗?谢谢。@Unheilig添加了一些KVC攻击。谢谢,现在你让我对维护问题部分感到好奇。你能不能对这一部分再详细说明一下谢谢。@Unheilig使用重构工具重命名
name
时,字符串
@“name”
将不包括在内。更改关系时,您可能会错过这样设置的
name