iOS 6 UICollectionView – Bölüm 1/2

Apple 2010 yılında ilk iPad’i çıkardığında belki fark ettmişsinizdir. Photos uygulaması cihazla birlikte geldi. Fotoğrafları göstermek için kendine has bir arayüzü vardı.

Güzel bir grid view şeklinde fotoğrafları gösteriyordu:

Albümlerin görünümüde aşağıdaki gibi:

2 görünüm arasında ufak bir parmak hareketiyle geçiş yapabiliyoruz.

Grid view’i veya benzer arayüzleri uygulamalarımıza ekleme şansımız var. Ancak biraz kurnazlık gerekiyor. Doğru görünümü elde edebilmek için epey kod yazmak gerek. Bunun kolay bir yolu yok mu diye epey düşünmüş olabilirsiniz.

Neyseki İyi haber iOS 6 ile geldi. Apple bu sürüm ile birlikte UICollectionView isimli yeni bir sınıf duyurdu. Bu sınıf Photos uygulaması gibi arayüzleri ve geçişleri kolaylıkla yapmamızı sağlıyor. Aryıca UICollectionView’i istediğimiz gibi özelleştirebiliriz. Buna imkan tanıyor. Dilediğimizi yapma şansımız var.

Son olarak kullanıcılara verileri göstermek için oldukça güçlü bir yöntem. Bu class neredeyse UITableView class’ı kadar önemli ve yardımcıdır. UITableView ile aşınaysanız öğrenmekte zorluk çekmekeceksiniz. Ayrıca datayı kullanmak veya pattern eklemede neredeyse aynı mantıkta çalışır.

Bu makalede kendi oluşturacağımız Grid yapılı fotoğraf uygulaması ile UICollectionView‘e değinmeye çalışacağız. Sona geldiğimizde ise UICollectionView hakkında temel bilgileri almış olacağız.

UICollectionViewController’in Yapısı

Çalışmaya başlayalım. UICollectionViewController’in bazı önemli parçaları var:

Bunlara teker teker bakalım:

    1. UICollectionView – İçeriğin görüntülendiği asıl view’dır. UITableView’e çok benzerdir. Ancak view controller deki tüm alanı kullanmayabilir. Yukarıdaki ekran görüntüsünde olduğu gibi üst bölümde bir arama bölümü yer alıyor.
    2. UICollectionViewCell – UITableView içindeki UITableViewCell benzer mantıkta çalışır. Bu cell’ler ile içerik oluşturulur ve UICollectionView’e eklenir. Kod yazarak bunları oluşturabileceğimiz gibi interface builder üzerinden de cell üretebiliriz.
    3. Supplementary Views – Cell içerisindeki bilgiye ek olarak kullanıcıya vermek istediğiniz varsa supplementary view’i kullanabilirsiniz. Genelde header veya footer  olarak kullanılırlar.
    4. Decoration View – Genelde görselliği arttırmak için kullanılır. Arkaplan resimleri buna bir örnek.
      Bu incelediklerimiz görsel öğelerdi. Ek olarak görsel olmayan öğelere bakalım:
    1. UICollectionViewLayout – UICollectionView, cell oluşumu hakkında birşey bilmez. Bunu UICollectionViewLayout class’ı bunu halleder. UICollectionView içindeki her bir cell için delegasyon yapar. Arayüzler arası geçiş çalışma zamanında yapılırken UICollectionView bunu otomatik olarak halleder!
    2. UICollectionViewFlowLayout – Kendi arayüzlerimizi oluşturmak için UICollectionView altında bir subclass yaratmamız yeterldir. Sonraki yazımızda buna değineceğiz. Neyseki Apple programcılara UICollectionViewLayout adında basit bir arayüzü sunuyor. Elementleri aynı bir grid view’da olduğu gibi sıralar. Bunuda istediğiniz gibi değiştirebilirsiniz.

Detaylarına yazının sonlarında doğru ve gelecek yazıda değineceğiz. Şimdi projeyi oluşturalım.

FlickrSearch’e başlangıç

Yazının bundan sonraki bölümünde FlickrSearch adlı uygulamamızı yapacağız. Uygulama Flickr’dan arama kriterimize göre sonuçlarını getirecek ve ekranda gösterecek:

Başlamadan önce projemiz için gerekli şeyleri buradan indirin.
Hazırsanız Xcode’u çalıştırın ve yeni bir Single View Application açın.

Elimizde başlamak için basit bir UIViewController ve storyboard yeterli.

Next’e tıklayıp uygulama hakkındaki bilgileri girelim. Uygulama adı FlickrSearch, desteklenen cihaz iPad olsun. Use StoryBoard ve Use Automatic Reference Counting seçili olsun. Next’e basıp projeyi oluşturalım.

Uygulamayı çalıştırdığımızda tamamen boş bir ekran karşımızda.

Bir sonraki adım olarak indirdiğiniz resimleri projemizin içine sürükleyip bırakalım.

Tahtayı Pinleyelim

Uygulamamızın hem güzel hemde basit görünmesi için tasarımımıza başlayalım. Tasarımdan sonra UICollectionView’i ekleyeceğiz. StoryBoard’u açmadan önce birkaç tane IBOutlet IBAction ekleyelim. ViewController.m’i açıp @interface içine aşağıdakileri ekleyelim:

@interface ViewController ()
@property(nonatomic, weak) IBOutlet UIToolbar *toolbar;
@property(nonatomic, weak) IBOutlet UIBarButtonItem *shareButton;
@property(nonatomic, weak) IBOutlet UITextField *textField;
- (IBAction)shareButtonTapped:(id)sender;
@end

Ayrıca bir paylaşım buttonu eklemek için aşağıdakinide ekleyelim:

-(IBAction)shareButtonTapped:(id)sender {
    // TODO
}

Bunları sadece ViewController da görünmeleri için oluşturduk. Şimdi onları bağlayalım. MainStoryBoard.storyboard’ı açalım. Object Library ‘den bir ToolBar ekleyelim. ToolBar’ın buttonunun text’ini “Share” olarak değiştirelim. Buttonu Ctrl ile ViewController’e sürükleyelim. Açılan menuden shareButtonTapped’i seçelim. buttonu böylece az önce yazdığımız metoda bağlamış olduk.

Şimdi arama için bir label, Search box ve image view ekleyelim. image view’in image property’sini search_text.png olarak ayarlayın. Şuanda resim berbat görünüyor. Ancak bunu düzelteceğiz. mode property’sini center olarak seçin ve label’i toolbar’ın altına konumlandırın. Editor/Size to Fit Content ile resmi image view’e denkleyebiliriz.

Not: Label yerine neden image view’i kullandığımızı merak ettiyseniz, bunun nedeni farklı bir görünüm elde etmek istediğimiz içindir. İster image ister label tercih sizin.

Arama özelliğimiz için bir text field ekleyip label’in sağına hizalayalım. Border değeri varsa sıfırlayalım. Buna sonra ekleme yapacağız. Text field’i ekledikten sonra Ctrl ile ViewController’a sürükleyip bırakalım. Açılan menuden “delegate” i seçin. böylece enter’a bastığımızda klavye kaybolacak.

Search box ile sonuçları göstereceğimiz alan arasında bir çizgi çizelim. Bunun için başka bir image view ekleyelim ve doğrudan search box ve label’ın altına yerleştirelim. Image property’sini divider_bar.png olarak seçelim.
Arayüzümüz aşağıdaki gibi olmalı:

Son adım olarak IBOutlet’leri bağlayalım. ViewController’a tıklayıp sol bölümden Connections Inspector’u seçin. Oluşturduğumuz her bir IBOutlet’i uygun elemente atıyalım.

Şimdi işin eğlenceli kısmına geldi. Storyboard’u kullanarak arayüzümüzü şekillendireceğiz. ViewController.m’i açıp aşağıdaki metodu viewDidLoad event’inin altına ekleyin:

self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bg_cork.png"]];
UIImage *navBarImage = [[UIImage imageNamed:@"navbar.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(27, 27, 27, 27)];
[self.toolbar setBackgroundImage:navBarImage forToolbarPosition:UIToolbarPositionAny
barMetrics:UIBarMetricsDefault];
UIImage *shareButtonImage = [[UIImage imageNamed:@"button.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(8, 8, 8, 8)];
[self.shareButton setBackgroundImage:shareButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
UIImage *textFieldImage = [[UIImage imageNamed:@"search_field.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
[self.textField setBackground:textFieldImage];


Bu arayüzümüzü bir mantar panosu gönümünü (UIColor:colorWithPatternImage metodu ile) verdi ve toolbar, share button ve text field’in arkaplanlarını oluşturdu.
Uygulamayı çalıştıralım. Arayüzümüz aşağıdaki gibi oldu:

Çok kötü değil. Şimdi UICollectionView ile tasarıma devam edelim.

Flickr’dan fotoğrafları çekmek

Flickr son derece basit bir API ile geliştiricilere açtığı servisi sayesinde fotoğraf paylaşımı imkanı veriyor. Bu API ile fotoğraf ekleyebilir, arayabilir veya yorum yapabilirsiniz. Bu API’yi kullanmak için bir API key’imiz olması gerekiyor. Gerçek bir proje yapacaksanız buraya kayıt olmanızı öneriyorum:http://www.flickr.com/services/api/keys/apply/

Örneğimizdeki test amaçlı projelerde kullanılmak üzere Flickr’ın sunduğu ve kayıt olma zorunluluğu olmayan bir key bulunuyor.  Basit bir arama için: http://www.flickr.com/services/api/explore/?method=flickr.photos.search  adresine gidin ve sayfanın altında yer alan API key’i kopyalayın.  URL içindethe “&api_key=” ile başlayıp “&” ile biten key. Bunu bir yere not edelim.
Örneğin URL aşağıdaki gibi ise:
http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=6593783 efea8e7f6dfc6b70bc03d2afb&format=rest&api_sig=f24f4e98063a9b8ecc8b522b238 d5e2f
API key: 6593783efea8e7f6dfc6b70bc03d2afb dir.

Not: Örnek API’yi kullanacaksanız periyodik olarak değiştirildiğini unutmayın. Bu nedenle kayıt olmak daha makul 🙂

Flickr için yazdığım class’ları buradan indirebilirsiniz. İçindeki 4 dosyayı projeye dahil edelim. Eklediğimiz 2 class:

  • Flickr: API üzerinden arama yapmaya ve fotoğraflardan oluşan bir dizinin dönüşünü sağlar.
  • FlickrPhoto: Flickr’den gelen fotoğraf hakkındaki datayı verir. Gelen fotoğrafın ufak bir hali, id’si gibi bilgiler.

Kod oldukça basit. Kendi projelerinizde kullanabilirsiniz. Başlamaya hazırsanız, sonraki aşamaya yani Flickr bağlantısına geçelim.

Veri yapısının oluşturulması

Uygulamamızda yaptığımız her bir arama için yeni bir “Section” görüntülenir. Diğer bir değişle, örneğin, “ninja” ve sonrasında “pirate” diye arattığınızda “ninja” için bir section, “pirate” için de başka bir section elde ederiz.// Section table view’daki görünüm tiplerindendi hatırlarsanız

Bu gerçeleştirmek için her bir section için ayrı ayrı datayı tutan bir yapı gerekiyor. NSMutableDictionary bunun için gerçekten uygun bir çözüm olabilir. Dictionary’nin anahtarları (key) arama kriterleri iken değerler (value) ise FlickrPhoto objelerini içeren dizileri içerir. Diziyi ve dictionary’i oluşturarak başlayalım. Bizim için arama kriterlerini ve sonuçları tutacaklar. Önce ViewController.m’i açarak Flickr’la ilgili class’ları dahil edelim:

#import "Flickr.h"
#import "FlickrPhoto.h"

sonra birkaçtane property’i @interface’in altına ekleyelim:

@property(nonatomic, strong) NSMutableDictionary *searchResults;
@property(nonatomic, strong) NSMutableArray *searches;
@property(nonatomic, strong) Flickr *flickr;

viewDidLoad’ın içine aşağıdaki kodları ekleyelim: //initialization için

self.searches = [@[] mutableCopy];
self.searchResults = [@{} mutableCopy];
self.flickr = [[Flickr alloc] init];

“Searches” yapılan tüm arama kriterlerini tutacak olan dizi ve “searchResults” kritere göre arama sonuçlarını saklayacak.
Şimdi bunları nasıl göstereceğimize geçeceğiz.

İyi Sonuçlar Almak

Flickr da arama yapabilmek için API key gerekiyor. Flickr.m’ı açıp FlickrAPIKey değerini kendi key’iniz ile güncelleyin. Şöyle görünmesi gerek:

#define kFlickrAPIKey @"ca67930cac5beb26a884237fd9772402"

Artık arama yapabilmek için hazırız. ViewController.m’i açalım ve aşağıdaki kodu en alta (@end’in üstüne tabiki) ekleyelim.

#pragma mark - UITextFieldDelegate methods
- (BOOL) textFieldShouldReturn:(UITextField *)textField {
    // 1
    [self.flickr searchFlickrForTerm:textField.text completionBlock:^(NSString *searchTerm, NSArray *results, NSError *error) {
    if(results && [results count] > 0) {
        // 2
        if(![self.searches containsObject:searchTerm]) {
            NSLog(@"Found %d photos matching %@", [results count],searchTerm);
            [self.searches insertObject:searchTerm atIndex:0];
            self.searchResults[searchTerm] = results; }
            // 3
            dispatch_async(dispatch_get_main_queue(), ^{
            // Placeholder: reload collectionview data
            });
        } else { // 1
        NSLog(@"Error searching Flickr: %@", error.localizedDescription);
    } }];
    [textField resignFirstResponder];
    return YES;
}

Kullanıcı enter’a bastığında bu metod çağırılacak (daha önce view controller’da text field için deletage oluşturmuştuk).

Kodun açıklaması ise:

  1. Flickr wrapper class’ı ile arama işlemini gerçekleştiriyoruz. Arama tamamlandığında, sonuçlar arama kriterine refere edilecek şekilde ve blok halde çağırılır.
  2. İlk olarak daha önce aynı aramayı yapıp yapmadığınıza bakılır. İlk kez arıyorsanız arama kriteri “Searches” dizisine, sonuçlar “searchResults” a eklenir.
  3. Elimizde yeni çektiğimiz verilerimiz var ve arayüzümüzü güncellememiz gerekiyor. View’in ihtiyacı olan, yeni verilerle kendisini yenilemesi. Bu ara henüz bir collection view eklemedik. Bunu bir kenara not edelim.
  4. Son bölümde ise bir error aldığımızda bunun konsolda görünmesi iyi olur.

Uygulamayı çalıştıralım. örnek bir arama yapalım ve konsol ekranında çıkan sonuçlara bakalım:

2012-07-10 21:44:16.505 Flickr Search[11950:14f07] Found 18 photos matching 1337 h4x
2012-07-10 21:44:32.069 Flickr Search[11950:14f0b] Found 20 photos matching cat pix

Sonuçlar 20 ile sınırlı. Çünkü yükleme süresini azaltmak istiyoruz.

Artık elimizde verilerimiz var ve şimdi UICollectionView ile bunları görüntüleyeceğiz.

UICollectionView’i hazırlamak

Hatırlarsanız UITableView kullanırken bir veri kaynağı (data source) oluşturmaklı ve görüntülenmesi ve tetiklenecek eventleri yönetmemiz gerekiyordu.

Benzer şekilde UICollectionView kullanırken aynı şeyleri yapmamız gerekiyor. Kim neyi yapacak?

  • Veri Kaynağı (data source) (UICollectionViewDataSource) görüntülenecek verilere ilişkin bilgileri döndürür.
  • Delegate (UICollectionViewDelegate) bir cell seçildiğinde, kaldırıldığında gibi eventlerde ne olacağını söyler.

Yeni UICollectionView ile artık üçüncü bir protokolümüz daha var. Collection View’i kullanırken ona bağlı ve özel “Layout Manager”. Bu yazıda önceden hazırlanmış bir UICollectionViewFlowLayout Layout Manager kullanacağımız için UICollectionViewDelegateFlowLayout protokolü oluşturmalıyız. Bu bize layout’un çalışması ve ayarlanması için bize izin verecek.

Bu bölümde gerekli olan UICollectionViewDataSource, UICollectionViewDelegate, and UICollectionViewDelegateFlowLayout’u view controller içinde oluşturacağız.

Başlangıç olarak UICollectionViewDelegate ve UICollectionViewDataSource’u implement etmek için @interface içinde tanımlayalım.

@interface ViewController () <UITextFieldDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

Not: UICollectionViewDelegate yerine neden  UICollectionViewDelegateFlowLayout oluşturduğumuzu merak ediyorsanız cevabı şu:UICollectionViewDelegateFlowLayout, UICollectionViewDelegate’in alt protokolüdür. Bu nedenle ikisini yazmaya gerek yok.

Şimdi protokolleri implement edelim.

UICollectionViewDataSource

Veri kaynağı ile başlayalım. Aşağıdaki kodu ViewController.m’e ekleyelim:

#pragma mark - UICollectionView Datasource
// 1
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
    NSString *searchTerm = self.searches[section];
    return [self.searchResults[searchTerm] count];
}
// 2
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
    return [self.searches count];
}
// 3
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"FlickrCell " forIndexPath:indexPath];
    cell.backgroundColor = [UIColor whiteColor];
    return cell;
}
// 4
/*- (UICollectionReusableView *)collectionView:
(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    return [[UICollectionReusableView alloc] init];
}*/

Bu metodlar neler yapıyor?

  1. collectionView:numberOfItemsInSection: Section’da kaç tane cell görüneceğini söyler. Bu uygulamada her bir arama kriterinin kendi section’ı var. Önce “Searchs” dizisinde değeri arar. Sonra “resultsDictionary” de fotoğraf sonuçlarının getirir.
  2. numberOfSectionsInCollectionView: Toplam kaç tane section olacağını söyler. Tahmin ettiğiniz gibi “Searchs” dizisinin sayısı kadar.
  3. collectionView:cellForItemAtIndexPath: indeks sayısına göre istenilen cell’in gelmesini sağlar. UITableViewCell de olduğu gibi UICollectionViewCell’in standart bir yapısı yoktur. Şimdilik boş bir UICollectionViewCell döner.
  4. collectionView:viewForSupplementaryElementOfKind:atIndexPath uzun ismine rağmen oldukça basit. UICollectionView için görüntülenecek Header ve Footer’dan sorumlu view’leri döndürür. “Kind” değişkenin tipi NSString olup hangi view’i (ve class’ı tabiki) görüntüleyeceğimiz söyler.

UICollectionViewDelegate

UICollectionViewDataSource’u oluşturduk. Şimdi dikkatimizi UICollectionViewDelegate’e verelim. ViewController.m’e kodlarımızı ekleyelim:

#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    // TODO: Select Item
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
    // TODO: Deselect item
}

Şimdilik bu metodları boş bırakalım. Adında gördüğümüz gibi bir cell seçildiğinde veya seçim iptal edildiğinde tetiklenecekler. Bu arada collectionView:didDeselectItemAtIndexPath: sadece UICollectionView sadece UICollectionView çoklu seçimlere izin verdiğinde etkindir.

UICollectionViewFlowLayoutDelegate

UICollectionView aslında birleşik bir arayüzdür. Bu uygulamamızda hazır bir UICollectionViewFlowLayout kullanacağız. buda bize grid görünümü sağlayacak.
ViewController.m’a aşağıdaki kodları ekleyelim:

#pragma mark – UICollectionViewDelegateFlowLayout
// 1
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSString *searchTerm = self.searches[indexPath.section]; FlickrPhoto *photo =
    self.searchResults[searchTerm][indexPath.row];
    // 2
    CGSize retval = photo.thumbnail.size.width > 0 ? photo.thumbnail.size : CGSizeMake(100, 100);
    retval.height += 35; retval.width += 35; return retval;
}
// 3
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(50, 20, 50, 20);
}

Aslında daha fazla delegate metod ekleyebiliriz. Ancak bu 3 tanesi projemiz için gerekli.

  1. collectionView:layout:sizeForItemAtIndexPath cell’in ebatlarını layout’a söyler. Bu noktada öncelikle hangi fotoğrafa baktığımız önemli. Çünkü her fotoğrafın farklı ebatları olabilir.
  2. Dönecek boyutu anlamak için kullanılan bir operator var. Nedeni bazen sonuç olarak boş veya boy ve genişliği 0 olan sonuçlar döndüğünde görünümde boş beyaz bir resim görünebilsin.
  3. collectionView:layout:insetForSectionAtIndex: cell arasındaki boşluk, header ve footler’ları döndürür.

Artık UICollectionView ve ona bağlı tüm view’leri ekleyebiliriz.

UICollectionView ve arkadaşları

Table view gibi UICollectionView’in en önemli özelliklerinden birisi Apple’ın collection view’leri storyboard üzerinden oldukça kolay tasarlanabilmesine imkan tanıması. Sürükle bırak ile view controller’a UICollectionView ekleyebilir ve tasarımını yani UICollectionViewCell üzerinde değişikliği storyboard üzerinden yapabiliriz. Nasıl çalıştığına bakalım.

UICollectionView eklemek

Storyboard’a collection view’i eklemeden önce referans olarak atayabileceğimiz bir IBOutlet oluşturalım. @interface’e aşağıdakini ekleyelim:

@property(nonatomic, weak) IBOutlet UICollectionView *collectionView;

Şimdi storyboard’a bir collection view object sürükleyip bırakalım. Resimdeki gibi konumlandırın:

Arkaplana bir renk verip ekrandaki konumunu daha iyi görebilirsiniz.

Sonraki aşamada collection view için delegate ve dataSource’u ayarlayacağiz.Bunun için collection view’i ctrl ile view controller’a sürükleyip bırakalım ve scene inspector’dan dataSource’u seçelim. Aynısını delegate’i seçerek yapalım.

Son olarak view controller’a tıkladıktan sonra Connections Inspector’a geçelim ( Ekranda sağ üstteki tab veya View\Utilities\Show Connections Inspector’a tıklayın). collectionView property’i collection view’in içine sürükleyerek bağlantıyı tamamlayalım. Veri bağlantısından sonra 2 adımımız kaldı.

İlk olarak UICollectionView’a cell’lerin oluşumu için hangi class’ı kullanacağını söyleyeceğiz.
Aşağıdaki kodu ViewController.m içindeki viewDidLoad event’inin için yerleştirelim:

[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"FlickrCell"];

Artık collection view görünümü oluşturmak için standart UICollectionViewCell class’ını kullanacak. Daha sonra kendimiz bir class oluşturacağız.
Son adım olarak çektiğimiz verilere göre arayüzün güncellenmesini sağlayacağız. ViewController.m’de textFieldShouldReturn: deki yorum satırını silip aşağıdaki kodu ekleyelim:

[self.collectionView reloadData];

Uygulamayı çalıştırıp arama yapalım. Arama yapmamızdan sonra beyaz kutuların oluşturulduğunu görüyoruz.

Tebrikler. Collection view her bir sonuç için gerekli görünümü oluşturuyor. Ancak görüntülünecek resimler için hala birşeyler yapmamız gerek. Şimdi bunu tamamlayalım.

Kendi UICollectionViewCells’imizi oluşturalım

standart olarak UICollectionViewCell çok fazla değişikliğe açık değildir. Genelde kendi class’larımız ile bunu sağlarız.

Başlamadan önce viewDidLoad’da yazdığımız kodu yorum satırı haline getirelim:

[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"FlickrCell"];

Xcode hata verebilir ancak bunu düzelteceğiz.

Projemize yeni bir objective-c class’ı ekleyelim (File\New\File…, iOS\Cocoa Touch\Objective-C class ). adını FlickrPhotoCell koyalım ve UICollectionViewCell’in subclass’ı olarak belirleyelim. FlickrPhotoCell’de sadece UIImageView şeklinde bir subview’e sahip olacak ki Flickr’dan çekeceğimiz resimleri gösterecek. Önce class’ı düzenleyelim. Aşağıdaki kodu FlickrPhotoCell.h’e ekleyelim:

#import <QuartzCore/QuartzCore.h>
@class FlickrPhoto;
@interface FlickrPhotoCell : UICollectionViewCell
@property (nonatomic, strong) IBOutlet UIImageView *imageView;
@property (nonatomic, strong) FlickrPhoto *photo;
@end

Public olarak deklarasyon yapmamız nedeni başka class’lar görüntülenecek resime erişmek ve değişiklik yapmak isteyebileceğidir. Görünümü güncellemek için MainStoryboard.xib’i seçelim ve Interface Builder’ı açalım.
Collection View Cell’e tıklayalım ve Identity Inspector’dan class’ı FlickrPhotoCell olarak değiştirelim.

Şimdi Attributes Inspector’dan identifier’i FlickrCell olarak değiştirelim. Bunu görünümü oluştururken (cellForItemAtIndexPath) kullanacağız.

Cell’in boyutunu 300×300 pixel yapalım. Resmin boyutu otomatik olarak ayarlanacak. bir image view’i main view’e sürükleyip bırakalım. Layout’un doğru görünebilmesi için hizlamayı unutmayın. Bunu sağlamak için en az bir constraint’in olması gerekiyor.  Image view seçiliyken user constraints ikonuna tıklayın ve “Bottom Space to Superiew” i seçin.

Attributes Inspector’u açıp modu “Aspect fit” olarak değiştirelimki flickr’dan gelen fotoğraflar doğru görünsün. Sol bölümden Flickr Photo Cell’i seçip Connections Inspector’u açalım.ImageView’i bağlantıyı tamamlamak için UIImageView’e sürükleyip bırakalım.
Son adım olarak view’i iğne resmini eklemek için  kendi istediğimiz gibi değiştireceğz. Başka bir image view’i, cell’in ortasına denk gelecek şekilde yerleştirelim. Attributes Inspector’den modu “Center” ve image property’sini de pushping.png olarak seçin.  Son görünüm aşağıdaki gibi olmalı:

Artık içeriği oluşturabiliriz.

UICollectionView’a standart UICollectionViewClass yerine FlickrPhotoCell’i kullanmasını söyleyerek başlayabiliriz. ViewController.m’i açıp aşağıdaki kodu ekleyelim:

#import "FlickrPhotoCell.h"

“collectionView:cellForItemAtIndexPath” metodunu aşağıdaki gibi değiştirin:

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    FlickrPhotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"FlickrCell" forIndexPath:indexPath];
    NSString *searchTerm = self.searches[indexPath.section];
    cell.photo = self.searchResults[searchTerm]
    [indexPath.row];
    return cell;
}

İlk olarak bilmemiz gereken bu kod dizisi UICollectionViewCell yerine FlickrPhotoCell’i kullanmayı sağlar.Daha önce oluşturduğumu FlickrCell identifier ile hangi cell’i kullanacağını öğrenmiş olur. Kodun sonraki bölümü ise hangi fotoğrafları ve bunları nasıl göstereceğini belirler.

Uygulamayı çalıştıralım. Bir arama yapalım.

Arayüz istediğimize yakın bir hal aldı. Ancak hala fotoğrafları göstermiyor. Bunun nedeni UIImageView’i güncellemedik. Bunun için daha önce tanımladığımı photo property’sinin “Setter” ini override etmeliyiz. Önce aşağıdaki kodu FlickrPhotoCell.m’e ekleyelim:

#import "FlickrPhoto.h"

Sonra aşağıdaki  kodu @end’den önce ekleyelim.

-(void) setPhoto:(FlickrPhoto *)photo {
    if(_photo != photo) {
        _photo = photo;
    }
    self.imageView.image = _photo.thumbnail;
}

Uygulamamız sorunsuz çalışıyor.

Tebrikler! Fark ettiyseniz her fotoğraf kendi cell’inde gayet düzgün konumlandırılmış.  Çünkü sizeForItemAtIndexPath içinde yazdığımız kod ile cell boyutunu fotoğraftan 35 pixel fazla olarak ayarladık.

Not: Eğer görünümle ilgili bir sorun yaşıyorsanız Auto Layout’la ilgili bir problem var demektir. Kontrol etmekte fayda var.

İkinci bölümde daha fazla detaya ineceğiz.

 

Leave a Reply

Your email address will not be published. Required fields are marked *