Iphone için programlamayı öğrenirken deneyimlerimi bu blogda paylaşacağım.

Friday, 30 October 2009

Dinamik olarak bir objenin property lerine erişim

Runtime sırasında bir objective c objesinin property lerine erişmek , değerler set etmek mümkün. Örneğin bir object ' in column1 adlı bir property si olsun.

Bu property ye değer set etmek için self.column1= deger  diyerek bir değer atayabilirsiniz.

Bunu yapmanın bir başka yolu ise şöyle


[self setValue: deger forKey:@"column1"];


Değeri okumak için ise



 id *value = [self valueForKey:@"column1"]; 







Mesajın Selector yoluyla yollanması

Objective C deki Selector mekanizması ile bir mesajı (metod çağrısını) asenkron olarak istediğiniz bir delay ' den sonra çağırabilirsiniz. Selector ' lar C deki Function Pointer lara benziyor.

-(void) showButton {
--
}

gibi bir metodunuz varsa bu metod için selector ' i

@selector(showButton) şeklinde oluşturmak mümkün.

Bu metodun parametleri olsaydı örneğin

-(void) showButton:(id) view action:(NSString*) action {
}

selector şu şekilde olurdu. @selector(showButton:id:action)

Çağrılmasına gelince



[self performSelector:@selector(showButton) 
            withObject:nil 
            afterDelay:.5]; 

afterDelay ile gecikmeyi veriyorsunuz. İşlem belirtilen saniye süresince bekledikten sonra çağrılıyor. 

Bundle ' dan herhangi bir dosyanın path'ini almak

Diyelim ki bir uygulama içindeki bir dosyanın path ' ine ihtiyacınız var. Örneğin bir wav uzantılı bir dosya. Dosyanın path ' ini alan başka bir api kullanıyorsunuz.

Path bilgisinin almak için aşağıdaki kod yeterli olacaktır.


NSString *path = [[NSBundle mainBundle] pathForResource:@"ornek" ofType:@"wav"]; 


Bu projedeki ornek.wav dosyasinin yerini döndürecektir. 

UIPickerViewDelegate ' dan View veya NSString döndürmek

UIPickerViewDelegate, UIPickerView bileşeni tarafından delege işlemlerle ilgili mesajları alan bileşendir. Genellikle bu metodlar controller ' da UIPickerViewDelegate protokolunu uygulanmasıyla yer alır.

UIPickerViewDelegate UIPickerView ' un kaç bölümden (component) oluşacağı, her bölümde kaç eleman olacağını ve elemanlarla ilgili dataları aldığı metodlar barındırır.

Picker içinde gösterilecek bilgi View veya NSString* olarak verilebilir. Bunun için 2 ayrı metod var. UIView döndüren metodu eğer image göstermek istiyorsanız kullanabilirsiniz.





- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component {
    return [pickerData objectAtIndex:row];
}

-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row  forComponent:(NSInteger)component reusingView:(UIView *)view {
 return [imageViewArray objectAtIndex:row]İ
}


NSArray oluştururken

NSArray oluştururken en çok yaptığım hata initWithObjects ile elemanlarını verirken nil vermemek son eleman olarak.  Örneğin aşağıdaki tanım runtime ' da hataya neden oluyor.


NSArray *imageArray = [[NSArray alloc] initWithObjects: appleView,barView,cherryView,lemonView,sevenView];


Doğrusu sevenView dan sonra nil eklemek


NSArray *imageArray = [[NSArray allocinitWithObjects: appleView,barView,cherryView,lemonView,sevenView,nil];

Monday, 26 October 2009

IPhone uygulamalarında kullanılabilecek button imageları

IPhone SDK de eksik olan şeylerden biri Round Rect Button ' lar için kullanılabilecek image lar.  Çoğu uygulamanın güzel görünmesini sağlayan bu tür image ' lar oluyor.

http://www.glyphish.com/ adresinde geniş bir button image kütüphanesi bulabilir ve ücretsiz kullanabilirsiniz...

XCode ' da .h ile .m arası geçiş için

XCode ' da verimlilik düşmanı durumlardan biri bir Objective C class ' ının interface ' i (.h uzantılı dosya) ile implementation'i (.m uzantılı dosya) arasında geçişlerde mouse kullanıyor olmak.

.h ile .m uzantılı dosya arasında geçiş yapmak için kısa yol tuşu Alt + Cmd + Yukarı Ok tuşu. Interface  Implementation arası geçişleri yapıyor.

Friday, 23 October 2009

Elle Action eklemek

Diyelim ki myButton adlı bir UIButton objeniz var. Bu objenin içinde touch uop event i gerçekleştiği zaman buttonAction metodunun çağrılmasını istiyorsunuz. Interface Builder kullanıyorsanız bu binding otomatik IBAction ile gerçekleşir.

Bunun için gerekli kod

[myButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];

Thursday, 22 October 2009

TextField ve Klavyeyi kapatma

Ekranda bir textfield varken, textfield üstünde touch event oluştuğunda textfield firstResponder durumuna gelir ve klavye açılır.

Klavyenin kapatılması için [textField resignFirstResponder] mesajının yollanması gerekir. Bu mesaj ile klavye kapatılır.

İyi bir kullanıcı deneyimi için bu mesaj hem klavyede Return tuşuna click lendiği zaman hemde ekranda herhangi bir yere touch işlemi yapıldığı zaman yollanmalıdır.

Bu işlem için textField ' in delegate inde aşağıdaki metod eklenmelidir.


-(BOOL)textFieldShouldReturn:(UITextField*) theTextField {
if (theTextField == textField) {
[textField resignFirstResponder];

}
return YES;
}

Bu metodun eklendiği class (genellikle ViewController veya View) UITextFieldDelegate protokolünü uyguluyor olmalıdır.


View ' da herhangi bir yere touch işlemi yapıldığında klavyenin kapatılması için ise aşağıdaki metod gereklidir.


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch * touch = [touches anyObject];
    if(touch.phase == UITouchPhaseBegan) {
        [self.textField resignFirstResponder];
    }
}

Xcode için bazı tuş kombinasyonları

Satır silmek için Ktrl+A ile satırın başına gidin ve Ktrl+K ile silin.
Satırı kopyalamak için Ktrl+A ile satırın başına gidin ve Shift + Alt Ok ile satırı seçin. Command C ve Command Y ile kopyalayın.

IPhone Simulator ile dikkat edilecek bir nokta

Xcode ile birlikte gelen IPhone simulator ' ü gerçek bir emülator değil. Gerçek aygıt üstünde bulunan hafıza kısıtları gibi kısıtlara sahip değil. Kötü sürprizlerle karşılaşmamak için mutlaka kısa aralıklarla gerçek aygıt üstünde uygulamayı test etmek gerekli.

Implementation ' dan Interface ' e kısa yol

XCode  , Cmd e basılı tutarak Mouse la Class isminin üstüne click lediğinizde Interface ' in tanımlandığı satıra gider.

Option Double Click ise Class hakkındaki Dokümantasyonu açar.

Wednesday, 21 October 2009

First Responder

Motion Event, Action Event(button click), Edit Event(Copy paste,type) tipinde Event ' ler meydana geldiği zaman First Responder statüsüne sahip View bu event ' den haberdar edilir. First Responder statüsüne sahii View canBecomeFirstResponder mesajına YES cevabını vermelidir. Ayrıca view becomeFirstResponder mesajını yollamalıdır. 

Eğer First Responder yukarda sayılan event ' i işlemezse Responder Zincirindeki bir sonraki Responder a event i iletir. Bu iletim işleyecek View bulunana kadar veya UIApplication ' a ulaşana kadar devam eder.

View Touch Events almak istemiyorsa

Önceki yazıda anlattığım Hit Test View ve Event işleyiciyi bulma sürecine herhangi bir View katılmak istemiyorsa userInterActionEnabled özelliğini NO ya çekebilir. Bu özelliğin varsayılan değeri YES dir. NO iken Touch Event leri bu view işlemez.

Touch Events

Kullanıcı ekrana dokunduğu zaman Touch event oluşturulur. Bu event ' ile hangi View tarafından işlem yapılacağını anlamak için sistem Hit-Test View işlemine başlar. En yukardaki View ' dan başlayarak Touch Event ' in hangi View içinde gerçekleştiğini bulmaya çalışır. Touch event ' in meydana geldiği en alttaki View Hit-Test View dur.

İşlem yapacak View ' un bulunması için HitTest View dan başlanır. Bu View da event handler kod varsa çalıştırılır. Yoksa Controller ' ında var mı diye bakılır ve varsa çalıştırılır. Yoksa zincirdeki bir sonraki halkaya yani bir üstteki View için aynı adımlar tekrarlanır. Eğer hiçbir View oluşan Event ' i işlemiyorsa UIWindow  ve UIApplication ' a kadar işlem ilerler.

Thursday, 15 October 2009

Xcode ile çalışırken dokümantasyona ulaşmak için bir ipucu

Xcode ile çalışırken kodun içinde kullandığınız herhangi bir class ' ın veya metodun dokümantasyonuna ulaşmak isterseniz bunun kısa yolu Alt tuşuna basılı tutup class ' ın üstüne  çift click lemeniz.

 Örneğin UIApplication üstünde bu işlemi yaparsanız UIApplication ' ın class reference dokümanı açılacaktır. initWithFrame metodu üstüne yaparsanız initWithFrame yönteminin dokümantasyonu açılacaktır.

View Hiyerarşisi

IPhone için yazılan bir uygulama kullanıcı arayüzünü UIWindow adlı class ' ın içinde gösterir. IPhone uygulamaları tek Window ' dan oluşur. Bu Window ' un içinde çizilen arayüz bileşenleri yani View bileşenleri değişir.  İster kullanıcıdan input almak ister bilgi göstermek amaçlı olsun tüm bileşenler UIView class ' ından extend eder.  UIWindow ' da aslında bir UIView bileşenidir.

UIView hiyerarşini aşağıdaki diyagram gösteriyor. Farklı amaçlar için arayüz bileşenleri mevcut. Programcı bunları özelleştirebileceği gibi UIView ' dan extend edip tamamen farklı bir bileşende yazabilir.



UIView class ' ları alt view olarak başka bir UIView class ' ını barındırabilir. Tüm window çizilirken parent UIView dan başlayarak tüm hiyerarşi ekrana çizdirilir. Her bileşenin drawRect metodu çağrılır. Eğer alt view ' ları organize etmek istiyorsa (requireslayout ) ile layoutSubviews adlı metodun yazılması gerekir.

IPhone OS bir optimizasyon olarak her view ' un görünüşünü bitmap olarak cache ' ler. Bu sayede eğer görünümde değişiklik yoksa tekrar çizim yaptırılmadan cache lenmiş görüntü kullanılır. Avantaj hız, dezavantaj ise memory kullanımının artışıdır.  Bu nedenle sürekli yeni view bileşenleri yaratan uygulamalar problemlerle karşılaşabilir.

Tuesday, 13 October 2009

IPhone uygulaması kapanırken

Başlangıçta neler oluyor yazdım. Peki kapanışta neler oluyor?


IPhone aynı anda sadece tek bir uygulama çalıştırabilen bir platform. Örneğin gelen bir telefon , o an çalışan uygulamanın kapanmasına yol açıyor. Fakat kullanıcı uygulamayı tekrar açtığında kaldığı yerden devam edebilmeli.


Uygulamanın kapanması için 5 sn lik bir süre var. Uygulamanın son durumunu kaydedebilmesi için 5 sn.
Bu süre aşıldığı durumda IPhone uygulamayı öldürüyor. Bu nedenle uygulama kapanıyor mesajını aldığınızda çok çabul biçimde uygulama state'ini temizlemek ve kaydetmek şart.

Bir iphone uygulaması başlarken neler oluyor?

İlk yazı olarak IPhone uygulamasının başlangıç aşamasında hangi adımlardan geçiliyor konusunda bugün okuduklarımı özetleyeyim istiyorum.


Kullanıcı iphone ' da uygulamalarından birini seçip çalıştırdığında uygulamanın main metodu çağrılır. Bu projede main.m dosyası içinde bulunan ve aşağıdaki kod parçasından oluşan kısımdır.


int main(int argc, char *argv[]) {
  
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}


Bu kod parçasında yapılan 2 önemli iş var. Biri bellek yönetimi için AutoReleasePool ' un oluşturulması. Diğeri de uygulamayı başlatacak olan UIApplicationMain metod çağrısının yapılması. 


UIApplicationMain ' in 4 parametresi var. Argc ve Argv yi anlamak kolay. Argc uygulama başlatılırken kullanılan parametre sayısı, argv is char* array olarak bu parametreler.  


Diğer 2 parametre ne ile ilgili? 3. parametre UIApplication sınıfının ismini alıyor. Bu örnekte nil olduğu için UIApplication kullanılacaktır. Fakat uygulamanıza özel UIApplication ' ın alt sınıfını oluşturduysanız ismi burada verilmeli. 4. parametrede benzer biçimde Application Delegate ' in ismi. 


UIApplicationMain çağrısından sonra parametrelere göre UIApplication ve UIApplicationDelegate implementasyonları seçiliyor. UIApplication ' a delegate olarak seçilen UIApplicationDelegate objesi veriliyor. Bu sayede uygulama aktif hale geldi, uygulama kapanacak gibi haberler alındığında işlemler yapacaksak bunları delegate class'ının içine yazıyoruz.  Aşağıda bu haberler UIApplication tarafından yollandığında ne yapılacağı delegate da yer alacak aşağıdaki metodlarda yazılıyor. 

- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(@"Application is active");
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSLog(@"Application has finished launching");
    [window makeKeyAndVisible];
}


- (void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"Application will terminate");
}


Akışın diagramı




Bundan sonra info.plist okunuyor ve Main Nib dosyası olarak bir giriş varsa bu Nib dosyası okunuyor ve nib ten görsel bileşenler oluşturuluyor.  Uygulamanın ana penceresi mesela. window makeKeyandVisible çağrısı ile ana pencere ekranda görünür hale geliyor. 


Bundan sonra uygulama kullanıcıdan gelecek input ' ları beklemeye başlıyor. Kullanıcının ekran üstündeki hareketlerinden UIEvent ve UITouch gibi objeler oluşturuluyor ve bu input lar bir Queue yapısına giriyor. 


NSRunLoop bu Queue yapısında tutulan input ' ları izliyor ve bunları sırayla alıp uygulamaya kullanıcı 100,200 lokasyonuna clickledi haberini veriyor.


Uygulamada UIResponder ' in alt nesneleri bu haberleri işleyebiliyor.  UIView ve alt nesneleri UIResponser ' dan extend ediyor. Click bir butonun üstündeyse o an First Responder olarak butona haber gidiyor ve bu event ' e karşılık buton bir işlem gerçekleştirilebiliyor örneğin bir videoyu oynatmaya başlıyor. 


Aynı döngü kullanıcıdan yeni event ' ler geldikçe devam ediyor. Eğer First Responder event ile ilgilenmiyorsa event bir üstteki Responder ' a yollanıyor. Bir üstteki ilgilenmiyorsa o responder'in üstü şeklinde ilerlemeye devam ediyor. Bu tüm kontrolleri içeren View ve Window nesnelerine kadar ilerleyebiliyor.


NSRunloop işlem gerçekleştirildiği sırada uyuma moduna geçiyor. İşlem bitirdiğinde uyanıp Queue'da yeni event ' ler varsa bunların aynı şekilde işlenmesini sağlıyor . 


Ta ki uygulama kapanana kadar...