UICollectionView, iOS için UIKit'in güçlü bir bileşenidir ve nesne koleksiyonlarını ızgaralar, listeler ve özel düzenler olarak görüntülemeyi yönetir. UITableView'un aksine, UICollectionView tek bir sütunla sınırlı değildir: UICollectionViewLayout aracılığıyla öğelerin isteğe bağlı konumlandırılmasını destekler. UICollectionView'in özünü, FlowLayout ve CompositionalLayout'un nasıl çalıştığını ve Swift'te özel hücrelerin nasıl oluşturulacağını açıklıyoruz. IT Sectr'da galeriler, kataloglar ve ilan panoları için UICollectionView kullanıyoruz. Tablolarla karşılaştırma için UITableView hakkındaki makaleyi okuyun.
Önemli Noktalar
UICollectionView, iOS 6'da (2012) tanıtılan UIKit çerçevesinin bir sınıfıdır. UICollectionViewLayout nesnesi tarafından yönetilen esnek bir düzende hücrelerin (UICollectionViewCell) sıralı bir koleksiyonunu görüntüler. UICollectionView, UITableView (listeler) ile aynı sorunu çözer ancak öğelerin isteğe bağlı konumlandırılmasıyla: ızgaralar, atlıkarıncalar, mozaikler, kaskadlar.
Mimari UICollectionView MVC deseni üzerine inşa edilmiştir: veriler DataSource'ta, düzen UICollectionViewLayout'da, davranış UICollectionViewDelegate'da. Bu ayrım, veri kodunu değiştirmeden düzenleri değiştirmeye olanak tanır. Apple'a (WWDC 2025) göre, App Store ilk 100'deki iOS uygulamalarının %72'si içerik görüntülemek için UICollectionView kullanır. CollectionView, iOS 6'dan itibaren çok sütunlu düzenleri destekler ve iOS 13'ten itibaren karmaşık bölümler için CompositionalLayout almıştır.
UICollectionView, UITableView'e benzer şekilde yeniden kullanılabilir hücre havuzu (reuse queue) kullanır. dequeueReusableCell(withReuseIdentifier:for:) yöntemi, havuzdan bir hücre döndürür veya havuz boşsa yeni bir tane oluşturur. UITableView'un aksine, UICollectionViewCell'de tüm alt görünümleri eklemeniz gereken yerleşik bir contentView bulunur — bunları doğrudan hücreye eklemeyin, çünkü contentView doğru seçim ve düzenleme animasyonundan sorumludur.
UICollectionViewFlowLayout — iOS 6'dan beri çalışan standart düzendir. Hücre boyutu, kaydırma yönü, minimum boşluklar ve bölümleri yapılandırma olanağıyla öğeleri satırlar (flow) halinde düzenler. UICollectionViewCompositionalLayout — düzeni blokların birleşimiyle tanımlayan modern düzen (iOS 13+): grup → bölüm → düzen, burada her grup yatay, dikey veya özel olabilir.
| Parametre | UICollectionViewFlowLayout | UICollectionViewCompositionalLayout |
|---|---|---|
| Minimum sürüm | iOS 6 | iOS 13 |
| Karmaşık düzenler | Yalnızca basit ızgara veya liste | Farklı düzenler, gruplar, atlıkarıncalar içeren bölümler |
| Uyarlanabilirlik | Temsilci boyutu aracılığıyla | NSCollectionLayoutDimension.fractionalWidth/Height |
| Performans | Tüm görünür öğeleri işler | Tembel bölüm oluşturma |
| iPad desteği | Manuel uyarlama gerektirir | fractionalWidth ile uyarlanabilir gruplar |
| Uygulama karmaşıklığı | Düşük (5–10 satır) | Orta (15–30 satır) |
// FlowLayout ile Temel UICollectionView
class ViewController: UIViewController {
private var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumInteritemSpacing = 8
layout.minimumLineSpacing = 12
layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
layout.itemSize = CGSize(width: view.frame.width - 32, height: 100)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "cell")
collectionView.dataSource = self
view.addSubview(collectionView)
}
}
// DataSource
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int { 20 }
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
as! CustomCell
cell.configure(with: "Item \(indexPath.row)")
return cell
}
}
Apple tavsiyesi (WWDC 2025): yeni projeler için CompositionalLayout kullanın. Uyarlanabilir düzenler için daha fazla yetenek sunar, UICollectionView.Representable aracılığıyla UIKit ve SwiftUI ile daha iyi çalışır ve otomatik boyutlu bölüm başlıklarını destekler. FlowLayout'u, aynı hücrelerden oluşan bir ızgaraya ve iOS 12 ve altı minimum sürüme sahip basit ekranlar için kullanın.
UICollectionViewCell — UICollectionView hücreleri için temel sınıf. Her hücre contentView (ana kapsayıcı), backgroundView (varsayılan arka plan), selectedBackgroundView (seçili arka plan) içerir. Hücrenin görünümünü contentView içinde yapılandırın — asla doğrudan UICollectionViewCell'e alt görünüm eklemeyin.
// Yapılandırmalı Özel Hücre
class ProductCell: UICollectionViewCell {
private let imageView = UIImageView()
private let titleLabel = UILabel()
private let priceLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
contentView.addSubview(imageView)
contentView.addSubview(titleLabel)
contentView.addSubview(priceLabel)
// Auto Layout kısıtlamaları
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: contentView.topAnchor),
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
titleLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8),
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
priceLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
priceLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8)
])
}
func configure(with product: Product) {
imageView.image = UIImage(named: product.imageName)
titleLabel.text = product.title
priceLabel.text = product.price
}
}
UICollectionViewDelegate, seçim, vurgulama, bağlam menüleri ve yeniden sıralamayı işlemek için yöntemler sağlar. UITableView'un aksine, UICollectionViewDelegate yalnızca öğe dokunuşlarını değil, aynı zamanda uzun basmayı (UIContextMenuInteraction aracılığıyla bağlam menüsü) da kontrol etmeye olanak tanır. Dokunuşları işlemek için collectionView(_:didSelectItemAt:) uygulayın — seçim animasyonu tamamlandığında çağrılır.
UICollectionViewDiffableDataSource — iOS 13'te tanıtılan UICollectionViewDataSource'un tür güvenli bir yedeğidir. cellForItemAt aracılığıyla manuel hücre yönetimi yerine, DiffableDataSource NSDiffableDataSourceSnapshot kullanır — eski ve yeni durum arasındaki farkı otomatik olarak hesaplayan ve değişiklikleri canlandıran bir veri durumu anlık görüntüsü.
// Bölümlerle DiffableDataSource
enum Section {
case featured, recommended, categories
}
class ModernDataSource: UIViewController {
private var dataSource: UICollectionViewDiffableDataSource<Section, Product>!
override func viewDidLoad() {
super.viewDidLoad()
configureDataSource()
applyInitialSnapshot()
}
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<ProductCell, Product> { cell, _, product in
cell.configure(with: product)
}
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) {
collectionView, indexPath, product in
collectionView.dequeueConfiguredReusableCell(
using: cellRegistration, for: indexPath, item: product
)
}
}
private func applyInitialSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Product>()
snapshot.appendSections([.featured, .recommended, .categories])
snapshot.appendItems(featuredProducts, toSection: .featured)
snapshot.appendItems(recommendedProducts, toSection: .recommended)
snapshot.appendItems(categories, toSection: .categories)
dataSource.apply(snapshot, animatingDifferences: true)
}
// Otomatik animasyonla güncelleme
func updateProducts(_ products: [Product]) {
var snapshot = dataSource.snapshot()
snapshot.deleteItems(snapshot.itemIdentifiers)
snapshot.appendItems(products)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
DiffableDataSource'un avantajları: (1) otomatik animasyon — insert, delete, reload varsayılan animasyonla gerçekleşir; (2) tür güvenliği — bölümler ve öğeler türlenmiştir, çalışma zamanı çökmeleri yerine derleme hataları; (3) Snapshot — durum anlık görüntüsü kaydedilebilir, geri alınabilir, karşılaştırılabilir; (4) performans — DiffableDataSource, minimum değişiklik kümesini hesaplamak için Hellier algoritmasını kullanır. Apple (WWDC 2024), tüm yeni UICollectionView'ler için DiffableDataSource önerir ve eski DataSource'u yalnızca iOS 12 ve öncesi için kullanır.
UICollectionViewLayout — koleksiyon öğelerinin konumlandırılmasını tamamen kontrol eden soyut bir sınıftır. FlowLayout ve CompositionalLayout uygun değilse (örneğin, dairesel düzen, sarmal, diyagram), UICollectionViewLayout'un bir alt sınıfını oluşturun ve düzen hazırlama yöntemlerini geçersiz kılın.
// Özel dairesel düzen
class CircularLayout: UICollectionViewLayout {
private var attributesCache: [UICollectionViewLayoutAttributes] = []
private let radius: CGFloat = 120
override func prepare() {
super.prepare()
attributesCache.removeAll()
guard let collectionView else { return }
let count = collectionView.numberOfItems(inSection: 0)
let center = CGPoint(x: collectionView.bounds.midX, y: collectionView.bounds.midY)
for i in 0..<count {
let indexPath = IndexPath(item: i, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
let angle = (CGFloat(i) / CGFloat(count)) * 2 * .pi
attributes.center = CGPoint(
x: center.x + radius * cos(angle),
y: center.y + radius * sin(angle)
)
attributes.size = CGSize(width: 60, height: 60)
attributesCache.append(attributes)
}
}
override var collectionViewContentSize: CGSize {
collectionView?.bounds.size ?? .zero
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
attributesCache.filter { $0.frame.intersects(rect) }
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
attributesCache[indexPath.item]
}
}
Performans: özel bir UICollectionViewLayout, prepare() içinde nitelikleri önbelleğe almalı ve layoutAttributesForItem(at:) içinde O(1)'de döndürmelidir. 1000+ öğeli koleksiyonlar için shouldInvalidateLayout(forBoundsChange:) aracılığıyla artımlı önbellek güncellemeleri kullanın — bu, kaydırma sırasında tüm düzenin yeniden hesaplanmasını önler. Apple (WWDC 2023), özel düzenler yerine CompositionalLayout önerir: sıfırdan düzen yazmaya gerek kalmadan senaryoların %95'ini kapsar.
UITableView ve UICollectionView, listeleri görüntülemek için iki ana UIKit bileşenidir. UITableView daha basittir ve tek sütunlu listeler için tasarlanmıştır. UICollectionView daha esnektir ve herhangi bir düzeni destekler. Aralarındaki seçim, verilerin görsel yapısına ve gereken özelleştirmeye bağlıdır.
| Parametre | UITableView | UICollectionView |
|---|---|---|
| Düzen | Yalnızca dikey liste | Liste, ızgara, kaskad, atlıkarınca, özel |
| Karmaşıklık | Düşük (basit DataSource) | Orta (Layout + DataSource + Delegate) |
| Varsayılan hücre | 4 stil (basic, subtitle, value1, value2) | Yalnızca boş (contentView ile özel) |
| Düzenleme modu | Yerleşik (delete, move, insert) | Manuel uygulama gerektirir |
| Header/Footer | Yerleşik (viewForHeaderInSection) | Supplementary views aracılığıyla |
| Performans | Listeler için yüksek | Herhangi bir düzen için yüksek |
| iOS 6+ | iOS 2'den beri kullanılabilir | iOS 6'dan beri kullanılabilir |
Pratik kural: ekran basit bir satır listesiyse (ayarlar, kişiler, menü) UITableView kullanın. Ekran bir ızgara, yatay kaydırma, atlıkarınca, farklı hücre boyutları veya karmaşık gruplama gerektiriyorsa UICollectionView kullanın. iOS 14'ten itibaren UITableView da UICollectionLayoutListConfiguration aracılığıyla CompositionalLayout desteği almıştır ve her iki bileşenin avantajlarını birleştirmeye olanak tanır.
Sıkça Sorulan Sorular
UICollectionViewFlowLayout'da scrollDirection = .horizontal ayarlayın. CompositionalLayout için uyarlanabilir grup genişliği için fractionalWidth ile NSCollectionLayoutSize kullanın. Yatay kaydırma, atlıkarıncalar, galeriler ve kategoriler için iyidir. Sayfalamalı kaydırma için collectionView.isPagingEnabled = true ayarlayın veya itemSize = bounds.width ile UICollectionViewFlowLayout kullanın.
Kontrol edin: (1) hücre register(_:forCellWithReuseIdentifier:) ile kaydedilmiş, (2) DataSource öğe sayısı > 0 döndürüyor, (3) hücre doğru reuseIdentifier ile kuyruktan alınmış, (4) itemSize sıfır değil (FlowLayout için). Tipik bir hata, hücrelerin yüksekliğini sıfır yapan itemSize = CGSize.zero'dur. itemSize'ı açıkça ayarlayın veya temsilci collectionView(_:layout:sizeForItemAt:) uygulayın.
FlowLayout için: layout.minimumInteritemSpacing (bir satırdaki öğeler arası) ve layout.minimumLineSpacing (satırlar arası). CompositionalLayout için: NSCollectionLayoutGroup.interItemSpacing ve grup/bölümde contentInsets. sectionInset, bölümün dış kenar boşluklarını ayarlar. Safe Area'nın doğru işlenmesi için sectionInsetReference = .fromContentInset kullanın.
Grup animasyonları için performBatchUpdates kullanın: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }. Güvenli ve animasyonlu güncellemeler için UICollectionViewDiffableDataSource kullanın: dataSource.apply(snapshot, animatingDifferences: true) çağırın — tüm değişiklikler manuel insert/delete olmadan otomatik olarak hesaplanır ve uygulanır.
SwiftUI'da UICollectionView'in karşılıkları LazyVGrid ve LazyHGrid'dir (iOS 14+). SwiftUI Grid yazması daha basittir (bildirimsel sözdizimi) ancak 500+ öğe ve düzen özelleştirme için UICollectionView'in gerisinde kalır. Karmaşık koleksiyonlar için UIViewRepresentable aracılığıyla UICollectionView kullanın. IT Sectr projelerinde kataloglar ve galeriler için UICollectionView'ı, basit ekranlar için SwiftUI Grid'i seçiyoruz.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun