Синтаксис метода в Objective-C

176

Может кто-нибудь объяснить этот синтаксис объявления метода для меня? В этой функции возвращается число строк UIPickerView (пользовательский интерфейс игрового автомата на iPhone). Насколько я понимаю, метод называется ' pickerView' и возвращает NSInteger.

Он передает указатель на UIPickerview с именем ' pickerView' ... во-первых, почему метод называется тем же именем, что и параметр?

Затем следует параметр NSInteger, называемый компонентом, который сообщает нам, для какого компонента мы рассчитываем строки. Логика, чтобы решить, что находится в теле метода.

Что такое numberOfRowsInComponent? Кажется, оно описывает значение, которое мы возвращаем, но оно находится в середине параметров.

- (NSInteger) pickerView:(UIPickerView *)pickerView 
 numberOfRowsInComponent:(NSInteger)component
{
    if (component == kStateComponent)
        return [self.states count];

    return[self.zips count];
}
Craig
источник

Ответы:

358

Методы Objective-C предназначены для самодокументирования, и они заимствуют из богатой традиции Smalltalk.

Я постараюсь объяснить, что у вас здесь -(NSInteger) pickerView:(UIPickerView*)pickerView numberOfRowsInComponent:(NSInteger)component.

  • - (NSInteger)
    Эта первая часть указывает, что это метод экземпляра Objective C, который возвращает объект NSInteger. -(тире) указывает на то, что это экземпляр метода, в котором +будет означать , что это класс метод. Первое значение в скобках - это тип возвращаемого значения метода.

  • pickerView:
    Эта часть является частью имени сообщения . Полное имя сообщения в данном случае pickerView:numberOfRowsInComponent:. Среда выполнения Objective C берет эту информацию о методе и отправляет ее указанному получателю. В чистом C это будет выглядеть так
    NSInteger pickerView(UIPickerView* pickerView, NSInteger component). Однако, поскольку это Objective-C, дополнительная информация упакована в имя сообщения.

  • (UIPickerView*)pickerView
    Эта часть является частью ввода . Входные данные здесь имеют тип UIPickerView*и имеют имя локальной переменной pickerView.

  • numberOfRowsInComponent:
    Эта часть является второй частью имени сообщения . Как вы можете видеть здесь, имена сообщений разделены, чтобы помочь указать, какую информацию вы передаете получателю. Таким образом, если бы я к сообщению объект MyObject с Foo и бар переменных, я печатаю бы:
    [myObject pickerView:foo numberOfRowsInComponent:bar];
    в отличие от стиля C ++:
    myObject.pickerView(foo, bar);.

  • (NSInteger)component
    Это последняя часть ввода . вход здесь имеет типNSInteger и имеют локальную переменную имя компонента.

locriani
источник
18
+1 за отличный ответ. Я бы предложил изменить "фабрику" на "класс" в вашей первой точке, так как "+" официально указывает метод класса. Просто так получилось, что многие методы "+" являются фабричными, но это не правильное определение.
e.James,
2
Спасибо! Еще один вопрос: если вы хотите отправить объект myObject с переменными foo и bar, как вы показали: [myObject pickerView: foo numberOfRowsInComponent: bar]; Относится ли pickerView к имени метода или параметру?
Крейг
2
Ни. Это хороший стиль для ссылки как на имя метода, так и на параметр, но полное имя метода на самом деле - pickerView: numberOfRowsInComponent :. Если вы попытаетесь вызвать pickerView:, вы получите ошибку времени выполнения, так как метод не существует.
locriani
1
Позвольте мне прояснить это: часть pickerView: ДОЛЖНА ссылаться на следующий параметр, чтобы следовать хорошему стилю кодирования. Тем не менее, это только половина имени метода. Лучшим примером может быть [myObject setX: foo Y: bar], где метод setX: Y :.
locriani
1
Я знаю, что этот ответ старый, но последние несколько лет я живу в мире .NET. Я новичок в Objective C, и я перехожу с веб-мира на мобильную индустрию. Я хотел бы поблагодарить вас за такое хорошо документированное объяснение, которое так важно для вопроса. +1
d3v1lman1337
52

В Objective-C имя метода состоит из всех частей объявления, которые не являются аргументами и типами. Поэтому имя этого метода будет:

pickerView:numberOfRowsInComponent:

Метод будет эквивалентен функции в стиле C, которая выглядит следующим образом:

редактировать: (благодаря Джаррету Харди ):

NSInteger pickerViewNumberOfRowsInComponent(UIPickerView * pickerView, NSInteger component)
e.James
источник
1
+1 - хорошее краткое описание. Иногда я нахожу, что лампочка включается для людей, если вы пишете эквивалент стиля C как "NSInteger pickerViewNumberOfRowsInCompoent (UIPickerView * pickerView, компонент NSInteger)
Джаррет Харди
Мне нравится ваше объяснение, переписать на С гораздо лучше.
LCC
30

В дополнение к предыдущим ответам, я просто хотел бы сказать, что методы Objective-C (или сообщения, если вы предпочитаете) имеют внешние и внутренние имена параметров.

Итак, в этом случае:

- (NSInteger) pickerView:(UIPickerView *)pickerView 
 numberOfRowsInComponent:(NSInteger)component

numberOfRowsInComponentэто внешнее имя, которое вы бы использовали при вызове этого метода извне.

И componentэто внутренний имя параметра, которое вы используете для ссылки на параметр внутри метода.

Надеюсь, это немного прояснит.

Karolis
источник
1
В соответствии с вашим описанием, имя метода может рассматриваться как внешнее имя первого параметра. Это также согласуется с комментарием Вилчарза ниже.
Джейк
Черт, я считаю этот ответ таким неправильным. Нет ничего похожего на внешнее / внутреннее имя параметров. Это ТИП и ПЕРЕМЕННЫЙ идентификатор. Интересно, почему все так стараются определить ObjC как естественный язык, просто такой неестественный во всех отношениях. Это язык, вот и все. Позволяет просто изучать его, не используя при этом красивые слова.
Сиддхарт
Аргументы могут иметь внутренние / внешние имена. Это правда.
LCC
21

Мне кажется, что сигнатуры метода Objective-C больше похожи на предложения. Каждый параметр заслуживает участия в имени метода. Например, в C у нас может быть метод ( setPersonData ) для установки некоторой информации о персоне:

void setPersonData( char* name, int age, float height ) {

и в Objective-C метод будет более описательным ( setPersonName: andAge: andHeight:) , как

- (void) setPersonName: (char *)name andAge:(int)age andHeight:(float)height {
wilczarz
источник
8
И почему setPersonalData (char * andName, int также Age, float ТакжеHeight) не имеет смысла? Все дело в том, что вы понимаете в синтаксисе, а не в намерении дизайнеров objc быть умными. они просто добавили больше синтаксиса, который, откровенно говоря, не имел никакого смысла .. :)
Сиддхарт
5
Вы не поняли ответ, я боюсь. setPersonalData (char * andName, int такжеAge, float Кроме того, Height) является подписью, а не вызовом. Вызов этой функции будет setPersonData ("Том", 25, 175) - и это не говорит о многом, не так ли? Вызов Obj-C будет выглядеть следующим образом: [person setPersonName: @ "Tom" andAge: 25 andHeight: 175];
Вильчарз
3
Теперь, когда я думаю об этом, мой ответ - скорее жалоба, чем утверждение. Я не мог согласиться больше.
Сиддхарт