Jump to content

iOS Development

Оцени ову тему


Препоручена порука

А шта су + и - испред декларације метода?

 

"+" је class method (налик на, али не исто што и Java static method) за чије позивање није неопходна инстанца дате класе, већ се позива на класи директно као ”topicWithName:” из претходног поста (мада је испод хаубе чак и класа објекат у Objective-C, инстанца метакласе), а "-" је обичан instance method. Касније ћу мало више о томе.

  • Волим 1
Link to comment
Подели на овим сајтовима

Мало ми наопако да се то дефинише на интерфејсу и зове се метод класе, баш зато што није класа али добро, ствар навике. Да не расправљамо сад о овоме овде :)

Link to comment
Подели на овим сајтовима

Интерфејс класе се дефинише унутар header фајла са екстензијом .h (наследство C-a). Иако није обавезно, обично се дефинише једна класа по фајлу и фајл носи исти назив као и сама класа.

 

Све декларације иду између @interface и @end.

 

@interface ZRUMember : NSObject значи да дефинишемо класу ZRUMember која наслеђује NSObject. Сам језик вас не тера да наследите било коју класу, али у пракси свака класа наслеђује NSObject или неку од њених подкласа. На тај начин се бесплатно добија да вам објекти добро функционишу са Objective-C Runtime Library (срце језика). Све Apple-oве класе наслеђују NSObject, осим NSProxy, али ова класа имплементира NSObject protocol (protocol је практично иста ствар што и Java interface, касније ћу о њима и њиховом коришћењу), што јој омогућава да се лепо и правилно понаша. Наслеђивање од NSObject није имплицитно, увек се мора назначити.

 

Класа је изведени тип, а изведени типови се по конвеницији именују великим почетним словом. Али шта значи ово NS свуда? И зашто сам ја стављао префикс ZRU у имена класа. Зашто не само Member, Topic и Post? Objective-C нема ништа налик на namespaces или packages (да би остао строги надскуп C-a), те имена класа морају да буду јединствена. Зато име увек треба да почне двословним или трословним префиксом (ваши иницијали, почетна слова имена ваше компаније, скраћеница за име апликације итд). Apple је резервисао бројне префиксе од којих је један NS (историјски разлог). Ако се деси да две класе имају исто име, мислим да није дефинисано која од њих ће бити коришћена. Увек стављајте што јединственији префикс испред назива класе.

 

Кад смо код конвенција, оне овде имају тежу вредност него иначе. Да бисте лако и безбрижно користили одређене Apple APIs, строго пратите конвенције. Обично ништа не кошта, а добија се пуно.

Link to comment
Подели на овим сајтовима

Objective C има све примитивне типове које има и C.

 

У горњем примеру сам користио BOOL, NSInteger и NSUInteger. То су исто обични примитивни C типови. BOOL je typedef signed char и има вредности YES и NO (1 и 0). NSInteger и NSUInteger су зависно од платформе long и unsigned long односно int и unsigned int. Има пуно таквих опскурних типова који се ту и тамо појављују, али све је то само typedef неког примитивног типа, ништа фенси.

 

Сви објекти у Objective-C су allocated on the heap и приступа им се преко показивача. Овде се Objective-C разликује од C++, који дозвољава алокацију објеката on the stack. Приметите горе у примеру звездице кад год метод враћа или узима као аргумент неки објекат, док за примитивне типове нема звездица. Ево још једног примера како би се NSString објекат могао користити унутар неког метода.

//Deklaracija promenljive tipa NSString

NSString *string;



//Koriscenje promenljive string

string = @"ZRU";



//Deklaracija nove NSString promenljive i dodela vrednosti u jednoj liniji

NSString *newString = [string stringByAppendingString:@" - Zive reci utehe"];

Кога збуњују показивачи или било шта у вези са C-ом, може да прелиста ”The C Programming Language” by Dennis Ritchie.

 

Занимљив и користан тип из примера је id. id је показивач на било који објекат, нешто слично као void * у C. Уз овај тип се не користи звездица, зато што је већ садржана у дефиницији (дефиниција типа је typedef struct objc_object *id;). Пошто је Objective-C изузетно динамичан језик у коме се што је могуће више одлука одлаже до момента извршавања програма, id тип је веома користан (иако захтева већи опрез, наравно, јер одузимате компајлеру могућност да вам помогне). Осим тога, id тип је користан код колекција. NSArray, на пример, може у себе да спакује објекте било које класе, па и објекте потпуно различитих класа. Када затражите објекат на одређеној позицији, вратиће вам се id.

 

Замислите сад да правите неку игрицу са животињама и да је свака животиња описана посебном класом (неке могу да наслеђују једна од друге, али није толико битно за овај пример) и да су животиње у одређеној шуми спаковане у NSArray allForestAnimals. Желите да све животиње које могу да лете, то и ураде. Најлошија варијанта је да испитамо да ли објекат из низа припада класи за коју знамо да зна да лети.

 
for (id animal in allForestAnimals) {
    if ([animal isKindOfClass:[ZRUBird class]] || [animal isKindOfClass:[ZRUBat class]]) {
        [animal fly];
    }
}

Замислите на шта би личило кад бисмо имали 50 класа које знају да лете. Боља варијанта је дефинисати протокол ZRUFlying који декларише метод fly и захтевати од класа које желе да лете да га имплементирају.

 
for (id animal in allForestAnimals) {
    if ([animal conformsToProtocol:@protocol(ZRUFlying)]) {
        [animal fly];
    }
}

Ово је боље. Али опет, зашто захтевати да објекат имплементира протокол, кад можда ту има сто неких обавезних метода, а нама треба само fly. Можда, рецимо, у шуми постоји чувар Дејан Бићанић који има неку скаламерију за летење, али није животиња, те не имплементира ZRUFlying, који је само за животиње. Уместо тога можемо да захтевамо баш то, да објекат имплементира метод fly. Није битно уопште којој класи припада објекат. Можда је нека животиња, можда човек, можда и нека летелица. Само је важно да зна да лети.

 
for (id object in allForestObjects) {
    if ([object respondsToSelector:@selector(fly)]) {
        [object fly];
    }
}

Две напомене. Прво, овде смо користили синтаксу за брзу енумeрицију низа (for (id animal in animals)) која је додата у Objective-C. Може се користити и класична C енумерација, али је спорија. Друго, за треће решење је неопходно декларисати метод fly, најбоље у приватној имплементацији класе коју пишете (касније ћу о имплементацији класе). Ово је неопходно јер је компајлер мора да зна који тип метод враћа и које типове узима као аргументе да би добро одрадио аутоматски менаџмент над меморијом. За први и други случај то није потребно јер одговарајуће класе и протокол већ декларишу метод.

 

Као што рекох, ово није курс језика. Овде сам отишао мало унапред чисто да покажем како неке ствари изгледају, а које можда нисте срели у другим језицима. За почетак је довољно запамтити само то да је id показивач на објекат било ког типа.

Link to comment
Подели на овим сајтовима

Овако се декларишу методи.

+ (ZRUMember *)adminWithUserName:(NSString *)userName displayName:(NSString *)displayName;
- (BOOL)postMessage:(ZRUPost *)message inTopic:(ZRUTopic *)topic;

+ и - нам говоре да ли се ради о class или instance method. Class methods се позивају директно на класи, на следећи начин:

ZRUMember *theDejo = [ZRUMember adminWithUserName:@"Chuck Norris" displayName:@"Dejan Bicanic"];

Instance method се позива на конкретном објекту, инстанци класе.    

[theDejo postMessage:someMessage inTopic:someTopic];

Након + и - се наводи тип од returned value.  После тога долази назив метода са аргументима. У већини језика методи изгледају некако овако:  

postMessageInTopic(aMessage, aTopic)

Objective-C разбија име метода на онолико делова колико има аргумената. Ово је већини људи у почетку чудно, али се брзо навикнете. Предност је то што се позивање метода чита скоро као енглески језик и што се тачно види шта који аргумент представља.  

- (void)doSomething; 
- (void)doSomethingWithArgument:(ArgumentClass *)argument 
- (void)doSomethingWithArgument1:(Argument1Class *)argument1 inArgument2:(Argument2Class *)argument2

Видели сте у мом претходном посту метод који проверава да ли дати објекат имплементира одређени метод.   

if ([object respondsToSelector:@selector(fly)]) {
         [object fly];     
}

Селектор је у Objective-C терминологији просто име метода. Када напишете  

[theDejo postMessage:someMessage inTopic:someTopic];

Компајлер то преводи у нешто овако  

objc_msgSend(theDejo, @selector(postMessage:inTopic:), someMessage, someTopic);

Онда ова функција (током извршавања,  не компајлирања) тражи имплементацију метода postMessage:inTopic: Можете чак и ручно позвати objc_msgSend. То практично никада нећете радити. О овој и другим low level функцијама можете прочитати у Objective-C Runtime Reference и Objective-C Runtime Programming Guide Оно што вам хоће требати је selector. Као што рекох, selector је просто име метода које Objective-C Runtime користи да пронађе имплементацију током извршавања. Наићи ћете ту и тамо на метод који вам тражи selector као аргумент. Проследите му @selector(imeMetoda). Веома је важно обратити пажњу на то шта је заправо име метода. У нашем горњем примеру имена су редом:    

doSomething
doSomethingWithArgument:
doSomethingWithArgument1:argument2:

Ако ово сад запамтите, поштедећете себе бројних главобоља, јер нисте видели да сте додали две тачке где не треба или нисте где треба.

 

Толико о методама за сада. Следећи пут ћу објаснити properties. Properties су само пречица да бесплатно добијете декларацију и основну имплементацију accessor метода (getters и setters). Има их и у разним другим језицима.

Link to comment
Подели на овим сајтовима

Колико ти је требало да савладаш Objective-C?
Такође ме занима како си се бацио у програмирање (знам да си се бавио неком науком), колико озбиљно и сл. Једном речју - житије. :) Мада, разумем да можда и не желиш то овде да износиш.

Link to comment
Подели на овим сајтовима

Иначе, Objective-C нема стандардну библиотеку. Одакле онда долазе NSString и NSArray које смо користили у примеру? Одговор је Cocoa за OS X и Cocoa Touch за iOS. Иза ових имена се крије гомила библиотека груписаних у frameworks. NSArray NSString су део Foundation framework-a, док је све што има везе са корисничким интерфејсом у UIKit. Преглед свих framework-a и свих технологија у iOS можете наћи у iOS Technology Overview. Али откуд компајлер зна за ове framework-е, нигде нисмо написали #include ”Foundation.h”, нити било шта слично. Xcode користи precompiled headers. Када започињете нови пројекат, Xcode за вас направи фајл "ime projekta-Prefix.pch". Ево како изгледа садржај тог генерисаног фајла.

 

 
#import <Availability.h>
 
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
 
#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
#endif
 

 

Сви header-и наведени у овом фајлу се кеширају и потом аутоматски укључују у све друге фајлове током компајлирања. Пошто је Foundation неопходан у практично сваком фајлу, а UIKit бар у половини, они су по дифолту убачени. Можете додати шта год вам је потребно. Приметите да се овде користи #import уместо #include. #import ради исто што и #include, само мало софистицираније. За Objective-C фајлове увек користите #import.

 

Овде је добар тренутак да објасним @class директиву из примера. У питању је forward declaration класе. Ако се још неко сећа, написао сам следеће:

 

@class ZRUPost;
@class ZRUTopic;
@class ZRUMember;

 

Ово значи следеће: ”Драги компајлеру, веруј ми на реч да ове класе постоје. Допусти ми да их овде користим у декларацији, а ја се обавезујем да ћу ти њихове header фајлове показати у имплементацији.” У имплементацији ћемо морати да напишемо

 

 

#import "ZRUPost.h"
#import "ZRUTopic'h"
#import "ZRUMember.h"
Link to comment
Подели на овим сајтовима

  • 1 month later...
  • 6 months later...

Na iOS i OS X masovno ćete videti dve tehnike - delegation i data source. Delegation je kada objekat pošalje poruku drugom objektu (koji je njegov delegat) "hej, nešto se desilo, odluči šta treba da se uradi", a data source je objekat koji drugom objektu obezbeđuje neophodne podatke. I jedno i drugo se implementira kroz korišćenje protokola (interfejsi u Javi i C#). Dobar primer na iOS je klasa UITableView koja predstavlja jednodimenzionalnu tabelu (listu). Kada se kreira instanca ove klase, proizvoljni objekat se odabere da joj bude data source (tako što se podesi vrednost dataSource property od UITableView). I onda table view povremeno svom data source-u šalje poruke kao što su "daj mi broj sekcija", "daj mi broj redova u trećoj sekciji", "daj mi ćeliju za deseti red u osmoj sekciji". Ove poruke su zapravo metodi deklarisani u UITableViewDataSource protokolu i objekat koji je odabran da bude data source mora da ih implementira. Slično je sa delegatom. Proizvoljan objekat koji implementira UITableViewDelegate se odabere da bude delegat tabele i tabela mu onda šalje poruke tipa "kliknuto je na četvrti red u petoj sekciji". Delegat tada reaguje tako što, recimo, učita odgovarajući topic iz liste, ako se radi o aplikaciji za forum. Ovo je možda malo drugačije nego na drugim platformama. I model objekti često koriste delegiranje, ne samo views. Na primer, instance NSURLSession klase šalju svom delegatu poruke tipa "server je odgovorio i traži lozinku" ili "završen je download fajla". Kad budem pri kompu, napisaću kratak primer.

Link to comment
Подели на овим сајтовима

Придружите се разговору

Можете одговорити сада, а касније да се региструјете на Поуке.орг Ако имате налог, пријавите се сада да бисте објавили на свом налогу.

Guest
Имаш нешто да додаш? Одговори на ову тему

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Чланови који сада читају   0 чланова

    Нема регистрованих чланова који гледају ову страницу

×
×
  • Креирај ново...