MVVM vs The Composable Architecture (TCA)
iOS'ta en popüler iki mimari pattern karşı karşıya: geleneksel MVVM ile Point-Free'nin fonksiyonel TCA'sı. Doğru mimariyi nasıl seçersiniz?
Apple'ın geleceği: deklaratif, reaktif, cross-platform
15 yıllık savaş testi geçirmiş, güçlü ve olgun framework
// SwiftUI - Kullanıcı profil kartı
import SwiftUI
struct ProfileCard: View {
@StateObject private var viewModel = ProfileViewModel()
@State private var isFollowing = false
var body: some View {
VStack(alignment: .leading, spacing: 16) {
HStack {
AsyncImage(url: viewModel.user.avatarURL) { image in
image.resizable().scaledToFill()
} placeholder: {
ProgressView()
}
.frame(width: 64, height: 64)
.clipShape(Circle())
VStack(alignment: .leading) {
Text(viewModel.user.name)
.font(.headline)
Text(viewModel.user.title)
.font(.subheadline)
.foregroundStyle(.secondary)
}
Spacer()
Button(isFollowing ? "Takipten Çık" : "Takip Et") {
withAnimation(.spring(response: 0.3)) {
isFollowing.toggle()
}
}
.buttonStyle(.bordered)
.tint(isFollowing ? .gray : .blue)
}
}
.padding()
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}// UIKit - Kullanıcı profil kartı
import UIKit
class ProfileCardViewController: UIViewController {
private let avatarImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleAspectFill
iv.clipsToBounds = true
iv.layer.cornerRadius = 32
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
private let nameLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .headline)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private lazy var followButton: UIButton = {
var config = UIButton.Configuration.bordered()
config.title = "Takip Et"
let btn = UIButton(configuration: config)
btn.addTarget(self, action: #selector(followTapped), for: .touchUpInside)
btn.translatesAutoresizingMaskIntoConstraints = false
return btn
}()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
loadUserData()
}
private func setupUI() {
view.addSubview(avatarImageView)
view.addSubview(nameLabel)
view.addSubview(followButton)
NSLayoutConstraint.activate([
avatarImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
avatarImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
avatarImageView.widthAnchor.constraint(equalToConstant: 64),
avatarImageView.heightAnchor.constraint(equalToConstant: 64)
])
}
@objc private func followTapped() {
UIView.animate(withDuration: 0.3) {
self.followButton.alpha = 0.5
} completion: { _ in
UIView.animate(withDuration: 0.3) { self.followButton.alpha = 1 }
}
}
}2025 itibarıyla yeni projeler için SwiftUI tercih edilmeli; Apple'ın tüm yatırımı bu yönde. Ancak karmaşık özel gereksinimler, iOS 13 altı destek veya büyük legacy kod tabanı varsa UIKit zorunlu olmaya devam ediyor. İdeal yaklaşım: SwiftUI önce dene, gerektiğinde UIViewRepresentable ile UIKit bileşeni embed et.
Ücretsiz Danışmanlık AlEvet. UIHostingController ile SwiftUI view'ı UIKit içine, UIViewRepresentable ile UIKit view'ı SwiftUI içine gömebilirsiniz. Büyük projelerde hibrit yaklaşım yaygındır.