Objective-C多个初始化程序

时间:2010-01-08 10:32:37

标签: objective-c initialization object-initializers

我有一个关于在objective-c类中创建多个初始化器的简单问题。 基本上我有一个代表我的数据库(用户)中的单行的类。我目前有一个初始化程序,它根据用户UserID(也是数据库中的主键)初始化类,当传递UserID时,类将连接到Web服务,解析结果并返回初始化为对应行的对象在数据库中。

在这个数据库中有许多独特的字段(用户名和电子邮件地址),我还希望能够根据这些值初始化我的对象。但我不确定如何使用多个初始化程序,我读过的所有内容都表明我可以自由拥有多个初始化程序,只要每个程序都调用指定的初始化程序。如果有人可以帮我解决这个问题,那就太好了。

我的初始化代码如下:

- (id) initWithUserID:(NSInteger) candidate {
    self = [super init];
    if(self) {
        // Load User Data Here
        NSString *soapMessage = [NSString stringWithFormat:
                                 @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
                                 "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
                                 "<soap:Body>\n"
                                 "<GetByUserID xmlns=\"http://tempuri.org/\">\n"
                                 "<UserID>%d</UserID>\n"
                                 "</GetByUserID>\n"
                                 "</soap:Body>\n"
                                 "</soap:Envelope>\n", candidate
                                 ];
        NSLog(@"%@",soapMessage);

        // Build Our Request
        NSURL *url = [NSURL URLWithString:@"http://photoswapper.mick-walker.co.uk/UsersService.asmx"];
        NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
        NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];

        [theRequest addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [theRequest addValue: @"http://tempuri.org/GetByUserID" forHTTPHeaderField:@"SOAPAction"];
        [theRequest addValue: msgLength forHTTPHeaderField:@"Content-Length"];
        [theRequest setHTTPMethod:@"POST"];
        [theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];

        NSError *WSerror;
        NSURLResponse *WSresponse;

        webData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&WSresponse error:&WSerror];

        xmlParser = [[NSXMLParser alloc] initWithData: webData];
        [xmlParser setDelegate: self];
        [xmlParser setShouldResolveExternalEntities: YES];
        [xmlParser parse];
    }
    return self;
}

根据Laurent的评论,我试图实施自己的解决方案,如果您能告诉我任何明显的解决方案,我将不胜感激:

我不完全确定我理解你的意思,我试图实现自己的解决方案。如果你能告诉我你的想法,我将不胜感激:

- (id) init {
    self = [super init];
    if(self){
        // For simplicity I am going to assume that the 3 possible
        // initialation vectors are mutually exclusive.
        // i.e if userName is used, then userID and emailAddress
        // will always be nil
        if(self.userName != nil){
            // Initialise object based on username
        }
        if(self.emailAddress != nil){
            // Initialise object based on emailAddress
        }
        if(self.userID != 0){ // UserID is an NSInteger Type
            // Initialise object based on userID
        }
    }
    return self;
}
- (id) initWithUserID:(NSInteger) candidate {
    self.userID = candidate;
    return [self init];
}
- (id) initWithEmailAddress:(NSString *) candidate {
    self.emailAddress = candidate;
    return [self init];
}
- (id) initWithUserName:(NSString *) candidate {
    self.userName = candidate;
    return [self init];
}

此致

2 个答案:

答案 0 :(得分:16)

指定的初始值设定项的定义为here。无论您使用何种初始化程序,都要确保您的实例保持一致。有关完整参考,请参阅Objective-C Programming Guide:初始化程序实现已有详细记录。

编辑2:修复@NSResponder报告的拼写错误

修改:

我认为在设置成员后调用init是不可靠的。成员可能有奇怪的值,无法通过初始化测试。

更好的方法是首先调用“init”方法(将为成员设置默认值),然后设置成员。这样,您的所有初始值设定项都具有相同的代码结构:

- (id) init {
    self = [super init];
    if(self){
        self.userID = 0;
        self.userName = nil;
        self.emailAddress = nil;
    }
    return self;
}

- (id) initWithUserID:(NSInteger) candidate {
    self = [self init];
    if(self){
        self.userID = candidate;
    }
    return self;
}

答案 1 :(得分:7)

我倾向于做这种事情的方式是指定的初始化程序是获取最多参数的方法,而更简单的初始化程序只发送更详细的-init消息。例如:

   // simple initializer
- (id) init
  {
  return [self initWithWidth: 1.0];
  }

  // not so simple initializer
- (id) initWithWidth:(float) aWidth
  {
  return [self initWithWidth:aWidth andColor:nil];
  }

  // designated initializer.  This is the one that subclasses should override.
- (id) initWithWidth: (float) aWidth andColor: (NSColor *) aColor 
  {
  if (self = [super init])
   {
   self.width = aWidth;
   self.color = aColor ? aColor : [[self class] defaultColor];
   }
  return self;
  }