Pull to refresh

Comments 61

Можно добавить еще блоки (http://pragmaticstudio.com/blog/2010/7/28/ios4-blocks-1), synthesize by default и возможность объявлять переменные в расширениях(http://www.mcubedsw.com/blog/index.php/site/comments/new_objective-c_features/). Для последних двух фич нужен компилятор LLVM 1.5 или 2.0
Можно, но это будет уже не с нуля :)
а rss по тегам прикрутите? ^_^`
Ммм… ок, пойду прикручу. :)
Эх… где ж вы были пол годика назад?!
Но пост отличный, большое спасибо.
Будет ли продолжение?
Спасибо. Конечно, но уже не чисто о языке, а о реальных проектах с его применением.
очень интересно будет почитать
Это не «5 копеек», судя по тому сколько оборотов колесика мышки мне пришлось сделать чтобы добраться до комментариев, тут рублей 500 как минимум.
Это по сравнению с официальной документацией :)
UFO just landed and posted this here
У Вас есть очень грубая ошибка в тексте:
> id myObject; //будущий бъект myObject произвольного класса
> myObject = [MyClass alloc]; //метод класса alloc выделяет участок памяти нужного размера и возвращает указатель на него
> [myObject init]; //метод объекта init иннициализирует инварианты объекта myObject

Это очень серьезная ошибка! Никогда нельзя разделять строку myObject = [[MyClass alloc] init], это связанно с тем, что результат метода init не всегда возвращает указатель на ту же область, что и alloc! И этот момент отлично расписан в официальной документации! Так же с этим связана строка self = [super init] в конструкторах.
Почему нельзя разделять:)
можно написать вот так (хотя естественно исходный вариант опасный):
id obj = [MyClass alloc];
obj = [obj init];
Постойте, но ведь в данном случае результат метода init нигде не сохраняется и не используется. Разъясните, пожалуйста.
Ошибка как раз в том, что он «не сохраняется и не используется». Метод alloc лишь выделяет память, метод init может вернуть не тот результат, который был возвращен методом alloc. Самы простой пример: метод initWith… вернет nil в случае неправильных параметров, но если Вы не будете использовать этот результат и не сохраните его, то даже не узнаете о возможной ошибке.
Я понял — указатель, который необходимо использовать, возвращается методом init, а не alloc.
Благодарю за разъяснение!
Объясните, пожалуйста, незнакомому с этой проблемой человеку, разве нет компиляторов нормальных языков под яблочные платформы? Я слышал, что есть компиляторы для c++, и что не обязательно изучать objective-c чтобы писать под мак, айфон и т.п.
UFO just landed and posted this here
Чтобы писать программы одного компилятора недостаточно, нужна стандартная библиотека.
А для Маков такая библиотека (аж целый фреймворк!) — это Cocoa. Вот она-то и писана на Objective-C.
Cocoa не фреймворк — это Objective-C (си с обьектами) и набор фреймворков — AppKit и Foundation Kit. По сути, как Delphi под Windows — «паскаль с объектами», VCL и прочие мелкие плюшки. При этом под обе системы вполне можно писать и без Cocoa/Delphi, просто с ними быстрее и удобней.
для десктопа XCode умеет C, C++, Fortran, Objective-C, Objective-C++, Java, Applescript, Python and Ruby
для iPhone — тока Objective-C.
Есть monoTouch, который позволяет на c# писать с кучей ограничений. Мне не особо понравилось, да и библиотеки другие — разбираться придётся почти столько же.
Вроде для с++ что-то было
Немного дополню.
Objective-C полностью совместим с С и С++. Поэтому, если сильно не нужен Cocoa Touch (например, для игр) можно писать используя Objective-C по минимуму.
Кроме MonoTouch еще есть:
Appcelerator Titanium, PhoneGap — Javascript
Rhodes — Ruby
Airplay SDK — С++, возможна разработка из под Windows
Кроме айфона вышеперечисленные инструменты поддерживают и другие платформы
Что значит «нормальных» языков? Objective С не только синтаксисом отличается, если вы не заметили :)
Про десктоп уже сказали, а для iOS можно писать на Obj-C только интерфейс, а остальное на C/C++ — без проблем. Если прога кроссплатформенная, то так и делают (всё, что можно — на «плюсах»).

Сейчас Эппл сняли ограничения не фреймворки, думаю, в течение полугода-года будет Qt для iOS на базе Cocoa или Qt Lighthouse/QPA, да и что-то ещё подтянется.
Уточнение: и Qt поверх Cocoa, и Lighthouse поверх Cocoa уже есть в разработке, и у второго есть шанс дорасти до юзабельного состояния реально быстро (за недели). Как результат, самый продвинутый C++ фреймворк будет и на iPhone.
Опечатка:
Посыка сообщения, как и любая функция C, возвращает определенное (может void) значение:
Я б добавил в статью проверку на наличие объявленного класса, рядом с проверкой сообщений. Для общей картины.
К примеру:
Class gcClass = (NSClassFromString(@«GKLocalPlayer»));
if(gcClass) {
//true
} else {
//false
}

Спасибо за подробную статью.
Повторенье — мать учения!
У вас ошибка, в примере с NSAutoreleasePool в конце функции вы вызываете [pool release];, это неверно, метод release класса NSAutoreleasePool не выполняет каких либо действий, для очистки пула надо слать сообщение [pool drain];
Извиняюсь, данное поведение характерно при использовании GC, в отсутсвии GC можно использовать и [pool release];
Все ok, спасибо! drain конечно. То был мой недосмотр.
UFO just landed and posted this here
Мда, и его я решил учить, купив MBP. :( много. :)
Спасибо за статью! Было бы очень интересно, если бы Вы написали статьи по созданию каких-нибудь небольших простых и интересных примеров приложений под iPhone/iPad с комментариями и описанием.
Очень прошу общее введение в ООП (до абзаца с «Objective-C возник в 80-x как модификация С в сторону Smalltalk. „) отделить под отдельный заголовок. Для тех, кто про ООП уже слышал и зашёл под кат почитать именно про Objective-C. А то до той строчки текста много, но как-то ну совсем ничего нового. Пока там читаешь, кажется что остальная статья будет в том же духе, поверхностна банальна.

А в том первом абзаце про Objective-C надо б чуть пораньше обозначить похожесть на С++ и не забыть перечислить отличия, или хотя бы просто сказать (анонсировать), что они есть.
Многие знают о ООП по сям или джаве. А Obj-C — это другая трубка и курить ее надо с другой стороны ;)
ничего этакого про другую сторону в том разделе я лично не вижу… Обычное поверхностное экспресс-введение в методологии программирования, вплоть до ООП.
Во-первых, главный камень преткновения — терминология (хотя ИМХО как раз этот момент в статье раскрыт плохо), во-вторых, если я правильно понял, есть различия в логике работы.
При первом упоминании NS в именах классов стоило бы сказать, как оно расшифровывается…
в примере с протоколами нужно указать что класс MyPrinter реализует протокол MyPrinterProtocol, вот так

@interface MyPrinter: NSObject <MyPrinterProtocol>

иначе класс не обязан отзываться на селекторы из протокола

еще недавно октрыл для себя, что класс можно «заставить» следовать протоколу, уже на этапе добавления категорий
вот такие вещи вполне работают
@interface MyClass () <NewProtocol>
@interface MyClass (NewCategory) <NewProtocol>

ну и объявить указатель на объект «не знаю какого класса, но знаю что реализует протокол» таким образом:
id <SomeProtocol> delegate;
и можно вызывать у delegate методы из протокола SomeProtocol без ругани со стороны компилятора

и вообще статья отличная, спасибо
Если вы прочитаете официальную документацию, то у вас больше не будет «открытий», поверьте =)
А она есть на русском? А эта статья теперь есть ;)
Нужно признать, что подобные мелочи на русском как правило всеравно не описываются, и даже если посмотреть на ссылки про блоки выше в комментариях, то там также описан лишь самые основы. Исключительно с русским — это не серьезно.
Если к уже написанному (а, возможно, и откомпилированному) классу нужно добавить некоторые методы, а не переопределять его собственные или добавлять инварианты (для чего вообще-то и нужно наследование)...

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

Добавление к существующему классу своих переменных так же широко используется, для этого пользуются связкой из ассоциативного хранилища и KVC. Причем последние реализации категорий в llvm уже позволяют добавлять свои переменные класса к чужому классу, так что это будущее развитие и данность.
Я правильно понимаю, что это практически то самое, что в других кругах называется «Аспектно-ориентированное программирование»?
Точнее одна из плюшек, если не ошибаюсь, в терминологии АОП категории будут именоваться inter-type, т.е. то, что позволяет динамически изменять стуктуру программы. Но например с их помощью вы уже не получите join-point'ы, потому что доступа к исходной реализации заменяемого метода нет (а как было бы красиво), впрочем это уже мелочи ибо подобные вопросы рещаются легко на уровне самого исходного кода, а вот без категорий пришлось бы куда сложнее и менее элегантно.
Спасибо за статью!

Конечно, очень режет глаза синтаксис Objective-C, который просто чудовищно страшный.
При том что это ведь по сути достаточно высокоуровневый язык (компилируемый в чистый C по ходу, если я верно понял), то ведь можно было бы вместо него сделать что угодно — что-нибудь в разы более эстетичнее и читабельней. Что-нибудь Явообразное, например.
Какой-то каменный век…

Да и когнинивный диссонанс с образом Эппла, помешанной на красоте и простоте.
На самом деле он чудовищно челевечный и красивый, а вы просто не привыкли к синтаксису, ну и вдобавок не видели правил именования, благодаря которым любая программа вам становится понятна с первого же знакомства и нигде никогда не нужно ломать голову, что же тут происходит или читать документацию для методов какого-либо чужого класса :)

Сам же Obj-C — это по сути синтаксический сахар над C, можно переписать программу с Obj-C исключительно на C, просто классы заменятся структурами, вызовы методов функциями и т.д.
не знаю, не знаю, полгода пишу на Objective-C и скажу что после него мне трудно уже писать на С++ и JAVA.
Сам язык по началу показался страшный ужасть, но суть тут не в языке.
Тут особенность в том что у Эппл замечательные фреймворки и хороший редактор которые дополняют язык.
А объектная система и протоколы в Objective-c со временем кажуться намного более простыми и удобными чем традиционные решения Java /C++. ИМХО
З.Ы.
Хотя своего гемороя тут навалом, нужно признать
Спасибо за воодушевление.

Но на вид там конечно дикий зоопарк. И обычные скобки, и квадратные и фигурные. И плюсики и минусики и собачки. И звездочки, которые при этом вовсе не означают умножение. В общем такого винегрета давно не видел.
Семантика явно хромает.
На вид там ужас программиста, но я повторяю — только на вид)
Даже собачка там имеет пользу. Потому что нажав @ + пара первых символов макра,
тебе автоматически его предлагают, достаточно нажать интер. Это очень ускоряет написание различных. На других языках я не знаю как бы можно было различить переменную и макро так сходу.
Да и вообще в XCode одно из лучших автодополнений что я видел.Через некоторое время забываешь про все эти условности, и то что раньше Objective-C казался вырви глазом, я сейчас даже не помню точно названия большинства методов что использую, потому что набираю их автоматом).
Честно говоря не смотря на кажущуюся сложность, я например в Objective-C въехал за пару недель (в рамках написать простенькое приложение с анимацией и webview), а вот в MFC и Windows API въезжал намного дольше).
В моем представлении Objective-C это даже не язык а такой набор макр для С, потому что когда я пишу что то на нем, я могу предположить в какой примерно С код это потом переделается.
З.Ы.
много написал, видимо потому что давно искал шанса сделать такое сравнение).

статтья слишком большая, оборвалась, а так "+" — фундаментально! хотя и ничего нового, но повторил на ура :)
Единственный топик, после прошествия стольки времени, который больше в 4 раза комментариев :)
Thx!
Большое спасибо за статью! Начал копаться в разработке под iOS, по книжке-для-чайников ничего не было понятно до вашей статьи, сейчас многое прояснилось.
Возник вопрос: вот у вас в каких-то методах autorelease стоит (типа [Complex withRe: 1 andIm: 1] ), а в каких-то его может не быть. Как вообще узнать, выполняет ли, например, библиотечный метод autorelease к результату или нет? Ну и ещё вопрос: что будет, если я напишу [[obj autorelease] autorelease] (ну или применю autorelease к тому методу класса Complex, который это автоосвобождение уже осуществляет)?

Ещё один вопрос. Есть ли в ObjectiveC перехват сообщений, для которых не нашлось селектора? типа method_missing в ruby (они ведь оба от смолтока взяли свои ООП).
UFO just landed and posted this here
Просьба не воспринимать мой комментарий, как личную критику, поскольку это лишь желание разобраться в деталях. Но мне как новичку в Objective-C было крайне тяжело понять вашу интерпретацию официальной документации, сложнее, чем читать специализированные книги в оригинале.
Например, зачем вообще использовать термин «инвариант» и называть им всё подряд?
«…Основным преимуществом объектно-ориентированного подхода стала возможность создавать новые классы на основе уже написанных (добавлять инварианты и методы, переопределять методы…»

Здесь вместо «инварианты» подошло бы распространённое «переменные» или хотя-бы «свойства». Но это было не суть важно, если бы не дальше:
«…Инвариант isa относится к зарезервированному типу Class…»

Тоесть isa тоже инвариант? Но ведь это не переменная, это указатель, который является лишь частью переменной или объекта.

«Строковая константа такого класса записывается как @”Hello world”»

@«Hello world» -это объект класса NSString. Почему он константа?

«Чтобы заставить объект выполнить какой-нибудь метод нужно послать ему сообщение, именуемое так же, как и требуемый метод. Такое сообщение называется селектор метода. Синтаксис посылки таков:
[receiver method];»

Из этого предложения я могу лишь сделать ошибочный вывод, что метод и селектор метода это одно и то же. После этого раздел «Как работает передача сообщений» запутывает еще больше.
Но, если я правильно понимаю, разница в том, что селектор это лишь указатель на метод, который даёт возможность использовать имя метода как аргумент функции. В то время как метод — это и есть сама функция.

«Методы с неограниченным количством аргументов вызываюся следующим синтаксисом:
[receiver undefinedNumberParameters: one, two, three, four, five, six, seven];»

А как же «nil» в конце, который указывает на завершение инициализации?

«использовать определенные в базовом классе методы как свои), названное наследованием.»

В «базовом классе» это частный случай. Корректнее было бы «в родительском классе».

«Oбъекту класса MyPrinter можно гарантированно посылать сообщения print и switchedOn…»

Нельзя. Класс MyPrinter должен сначала реализовать все required методы протокола. Разве нет?

«Свойство – это некоторое имя, доступное через указатель на объект посредством оператора точка “.”…»

Согласитесь, что это не определение.
В результате я потратил 2 дня на изучение статьи, которая подарила больше вопросов, чем ответов. Поэтому просьба подсказать, если я сделал неверные выводы.
Only those users with full accounts are able to leave comments. Log in, please.