Отправка сообщения в objectForKey экземпляру NSMutableArray, и это работает !!Странный? - PullRequest
3 голосов
/ 08 декабря 2011

У меня очень плохой код, написанный в моей программе, я просто играл, изучая Objective C и iOS. То, что я сделал, это

Я создал NSMutableArray вот так,

placeInfo = [NSMutableArray array];

и затем в своем коде я делаю что-то вроде этого, в основном я манипулирую ответом API Google Места на карте (JSON).

NSDictionary *results = [responseString JSONValue];
placeInfo = [results objectForKey:@"result"];
self.phoneNumber = (NSString *)[placeInfo objectForKey:@"formatted_phone_number"]; // In this line compiler warns me that NSMutableArray might not response to this.

Я проверил документацию, но не нашел objectForKey в NSMutableArray.

  • Так в чем может быть причина? Почему мой код не падает? Почему он возвращает номер телефона клавишей "formatted_phone_number"?

EDIT

После первого ответа я отредактировал свой код и добавил приведение типа таким образом, но он все еще работает.

NSDictionary *results = [responseString JSONValue];
placeInfo = (NSMutableArray *)[results objectForKey:@"result"];
self.phoneNumber = (NSString *)[placeInfo objectForKey:@"formatted_phone_number"];

Ответы [ 2 ]

3 голосов
/ 08 декабря 2011

Я никогда не использовал API Google Адресов, но, наверное, [results objectForKey:@"result"] на самом деле возвращает другой словарь, поэтому objectForKey: работает.

Поскольку target-c просто использует указатели для ссылки на объекты, он никогда не преобразуется в NSMutableArray. Кроме того, target-c не знает во время компиляции, существует ли метод, из-за его динамической природы (вы можете фактически добавлять методы и даже целые классы во время выполнения).

В зависимости от настроек компилятора, он может просто показать предупреждение о том, что objectForKey: может не может быть найден во время выполнения, и позволить ему все равно продолжить компиляцию. В конечном итоге он работает просто отлично, если вы действительно передали его NSDictionary.

Даже если вы поставите перед собой (NSMutableArray *), он ничего не изменит. Это просто приводит к типу указателя и фактически не изменяет объект.

2 голосов
/ 08 декабря 2011

Он делает это, потому что [results objectForKey:@"result"] возвращает вам что-то, что не NSMutableArray. То, что возвращается, скорее всего, другое NSDictionary, которое, конечно, отвечает на objectForKey: Чтобы узнать, что у вас есть, установите точку останова после result = [placeInfo objectForKey:@"result"] и проверьте result. Отладчик скажет вам, с каким объектом вы имеете дело. Держу пари, все, что тебе нравится, это NSDictionary.

Цель C позволяет вам отправлять любое сообщение (называемое селектором) любому объекту в любое время; среда выполнения не заботится о том, реализует ли конкретный объект данный селектор. Если целевой объект не отвечает на данный селектор, он будет игнорировать его. Это не потерпит крах. В этом отношении он совершенно не похож на большинство других языков ООП, включая C ++ и Java, которые не будут компилироваться, если вы попытаетесь вызвать метод, который не реализует определенный класс. Вы можете узнать, реагирует ли объект на данный селектор (что аналогично использованию самоанализа для проверки того, реализует ли данный класс определенный метод), сказав [result respondsToSelector:@selector(objectForKey:)]. Это различие между методами и сообщениями крайне важно для понимания цели C. Я бы рекомендовал прочитать Язык программирования Objective C , прежде чем делать что-либо еще.

Кроме того, система типов в Objective C применяется менее строго, чем в других языках. Это вполне законно (хотя и очень плохая идея) делать то, что вы сделали здесь, то есть объявить указатель типа NSMutableArray, а затем присвоить его (я предполагаю) NSDictionary.

...