iPhone Kursu 3. Ders: TableViewController
Malumunuz iki hafta önce Gelişim Platformu bünyesinde 60 saatlik iPhone Uygulama Geliştirme eğitime başladık. Kursda gördüğümüz konuları dilim döndüğünce burada paylaşmaya çalışıyorum. Konular ilerleyip karmaşıklaştıkça detayları paylaşmak daha yorucu olacağından şimdiden affınızı rica ediyorum.
Bu dersimizde ViewController’ları gördük. Bir kaç tanesine değindik, TableViewController ve Navigation Controller üzerinde denemeler yaptık. Diğer derslerde controller’lara devam edeceğiz.
iPhone için yazılan uygulamalar MVC (Model, View, Controller) prensibine dayanır. Kabaca ifade edersek; Model yapıları veritabanı ile olan alışverişi, View yapıları uygulamanın görsel kısımlarını oluşturur. Controller’lar ise bu ikisini koordine eden yapılardır.
MVC’nin View ayağı yani uygulamanın görsel kısmı Xcode’un yardımcı programlarından Interface Builder’de oluşturulur. Tabi bu şart değildir. Uygulamanızdaki görsel öğelerini doğrudan kodda oluşturabilirsiniz.
Interface Builder’da iPhone için tasarlanmış pek çok nesne bulunmaktadır. Bunlar Label, TextField, Button, Image gibi klasik öğelerin yanısıra içine bunları alabilen View, hazır tablo yapısı sunan TableView, tab yapısını oluşturan TabBar, sayfalar arasında hiyerarşik bir düzen ile ilerlemeyi sağlayan Navigation Bar gibi gelişmiş nesnelerden oluşur. İşte bu son saydıklarım, içine başka nesneler alabilen yapılardır ve birer Controller ile kontrol edilirler.
Custom View
Örneğin içine Label, TextField ve button gibi çeşitli nesneler yerleştirmek istediğimiz bir uygulama ekranı planlıyorsak bu nesneleri bir View (Custom View) içine koymamız gerekiyor. Objective C delegate mantığıyla çalışır. Yani kullanılan nesneye ait fonksiyonlar önceden belirlenmiştir, sadece bunlar aktif hale getirilerek içine kodlar yazılır. Bu fonksiyonlar yeri ve zamanı geldiğinde kendiliğinden çalışır. Fonksiyonları harekete geçirmek için ekstra kod yazılmaz. İşte nesnenin sahip olduğu fonksiyonlar Controller’lar üzerinde bulunur.
Hemen soldaki resimde sağ üst kutuda görüldüğü üzere ekranımızda bir tane View nesnesi ve onun içerisinde Label, TextField ve Button nesneleri bulunmaktadır. Yine aynı resimde Xcode ekranında görüldüğü üzere bu ekran bir ViewController ile kontrol edilmektedir. Bu custom view yapısı table gibi çok özel bir nesne olmadığından önceden belirlenmiş fonksiyonları çok fazla değil. Özel amaçlı fonksiyonu bulunmuyor. Klasik viewDidLoad, didReceiveMemoryWarning, ViewDidUnload ve dealloc fonksiyonları mevcut. Bu bir önceki dersde yaptığımız HelloWorld uygulamasıdır. Hatırlarsanız o uygulamayı yapmaya başlarken taslak olarak “view based application” seçeneğini seçmiştik. Bunu seçince view ile ilgili bu yukarıda saydığımız fonksiyonlar hazır olarak kodun içerisinde geliyorlar. Bize düşen amacımıza uygun olan fonksiyonun yorum satırlarını kaldırmak ve içine gerekli kod parçalarını yazmak.
Yine geçen dersde hatırlayacağımız gibi bu ekranda bir buton vardı ve o butona tıklandığında text alanına yazılan yazı formun üstündeki label alanında görülüyordu. Butonun bu şimdi uydurduğumuz işi yapması önceden planlanan bir şey olmadığı için uygulamamız içinde bu iş için gerekli fonksiyon hazır gelmiyor. Adı üstünde “Custom View”. Biz amacımıza göre kendimiz oluşturuyoruz. İşte butona basınca çalışacak fonksiyon bize özel bir kod olacağından kendimiz yazıyoruz. Önce .h dosyasına tanımını yazıyoruz ve sonra .m dosyasında fonksiyonu ve içeriğini kodluyoruz. Bu fonksiyonun söz konusu butona basılınca çalışacağını da önceki dersden hatırlayacağımız üzere Interface Builder’da belirtiyoruz.
Table View
iPhone uygulamalarında belki de en çok kullanılan nesne bir Table View nesnesidir. Table View en genel manada sol kısmında bir resim, orta kısmında büyük bir başlık ve küçük puntolarla deneme amaçlı metinler, en sonda da küçük bir butoncuğun bulunduğu, parmakla yukarı aşağı kaydırılabilen çok kullanışlı bir yapıdır. Tabi bu saydılarımın hepsi olmak zorunda değildir. Yukarıdaki örneklerde resimli ve resimsiz klasik Table View’lar görülmektedir.
Table View’lar XML’den yahut dizilerden (array) veri alabilirler. Custom View’ların içerisinde kullanılabilirler. Yukarıda üçüncü resimde gördüğünüz üzere gruplandırılabilirler. Ayrıca uzun listelerde kolay hareket edebilmek için indexleme özelliği vardır (yine üçüncü resim).
Örneğimize başlamak için “View Based Application” taslağıyla yeni bir proje oluşturalım ve nib (.xib) dosyamızı Interface Builder’da açıp Library’den içine bir tane TableView nesnesi koyalım.
View’ımızın içindeki öğeleri gösteren küçük pencereden Table View’a tıklayarak inspector’dan Delegate ve DataSource bağlantılarını tutup küçük penceredeki File’s Owner’a sürükleyelim.
Table View nesnesini yönetmek için Table View’in hazır fonksiyonlarını barındıran bir controller’a ihtiyacımız vardır. Eğer uygulamamıza başlarken “Navigation-based Application” taslağını seçmişseniz bu taslağın kodları TableView yapısını içerecek şekilde hazır olarak gelir.
Eğer bu örneğimizde olduğu gibi View Based Application taslağı ile projenizi başlatmışsanız TableView fonksiyonlarına en kısa yoldan kavuşmak için şu yöntemi kullanabilirsiniz:
- Xcode üzerinden proje ana klasörüne sağ tıklayıp yeni bir dosya (Add New File) seçeniğini işaretleyin. Karşınıza çıkacak pencereden UIViewControllerSubClass’ı seçin, şablonların hemen altındaki UITableViewControllerSubclass seçeneğini mutlaka işaretleyin.
- Dosya adı olarak herhangi bir şey verin (nasılsa içindeki fonksiyonları kopyalayıp dosyaları atacağız).
- Yeni oluşan .m dosyasını açıp içerisindeki TableView için elzem olan şu üç fonksiyonu kopyalayıp kendi controller dosyamıza yapıştırın:
– (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
– (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
– (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
numberOfSectionsInTable:
Bu fonksiyon söz konusu TableView’da kaç farklı grup oluşacağı bilgisini döndürür. Manuel değer girebildiğimiz gibi amacımıza yönelik olarak bir dizinin eleman sayısını da geri döndürebiliriz.
numberOfRowsInSection:
Bu fonksiyon TableView’in kaç satırdan oluşacağının bilgisini döndürür. Elle sabit bir değer döndürebileceğimiz gibi eğer bir diziyi basıyorsak dizinin boyutunu [arrDizi count] şeklinde döndürebiliriz.
cellForRowAtIndexPath:
Bu fonksiyon TableView’in her satırı için çalışan fonksiyondur.
Aşağıdaki kod parçası tek gruplu, 5 satırlı bir tablo oluşturup her satıra “Satır” diye yazı yazmasını sağlar.
– (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 4;
}// Customize the appearance of table view cells.
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *CellIdentifier = @”Cell”;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}// Configure the cell…
cell.textLabel.text=@”Satır”;
return cell;}
Örneğin her satıra satır numarasını yazdırmak istiyorsak alt kısımdaki cell.textLabel.text=@”Satır” yerine
cell.textLabel.text=[NSString stringWithFormat:@”%d”, indexPath.row];
ifadesini koymalıyız.
Burada indexPath objesi cellForRowAtIndexPath fonksiyonun bir parametresidir ve bu objenin row property’sinde satırın indis numarası (0,1,2,3…) tutulmaktadır. Integer bir değer olduğu için stringWithFormat fonksiyonu ile stringe çevirilmektedir.
Eğer Table View’in içini bir dizideki datalarla doldurmak istiyorsak controller kodumuzda çok küçük değişiklikler yapmamız kafi.
Öncelikle Controller’ımızın header dosyasında (.h dosyası) dizimizi tanımlamalıyız:
@interface Ders3ViewController : UIViewController {
NSArray *arrListe;
}
Sonra Controller’ımızın kendi dosyasında (.m dosyası) yer alan ve yorum satırlarıyla pasif halde turan viewDidLoad fonksiyonu aktif hale getirilip burada dizinin içi doldurulur.
– (void)viewDidLoad {
[super viewDidLoad];arrListe=[[NSArray alloc] initWithObjects:@”Ali”, @”Veli”, @”Ayse”,nil];
}
Dizinin son elemanının “nil” olmasına dikkat edin. Objective C’de dizilerin son elemanı nil olmak zorundadır.
Şimdi yine aynı dosyadaki Table View’e mahsus fonksiyonları şu şekilde güncellemeliyiz:
– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
//return 4;
return [arrListe count]; //dizinin boyu ne kadarsa o geri dönüyor
}// Customize the appearance of table view cells.
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *CellIdentifier = @”Cell”;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}// Configure the cell…
//cell.textLabel.text=@”Satır”;
//cell.textLabel.text=[NSString stringWithFormat:@”%d”, indexPath.row];cell.textLabel.text=[arrListe objectAtIndex:indexPath.row];
//indexPath.row sirayla 0,1,2 aliyor…}
return cell;
}
Koyu yazılmış kısım sayesinde Table View’a ait numberOfRowsInSection fonksiyonu her satır için çalıştıkça arrListe dizisinin elemanları sırayla hücrenin textLabel değeri olarak setlenecektir.
Netice aşağıdaki gibi olacaktır. Örnek kodu buradan indirebilirsiniz.
Bu konudaki hiç bir noktayı atlamadan anlatmışsınız. Tebrikler 🙂
Teşekkürler Hocam 🙂
Bunu windowbased uygulama olarak gelistirebilir miyiz? yada windowsbasedin sinirlari nelerdir? cunku xcode 4 de daha kolay geldi windowbased gelistirmek.