MVVM vs The Composable Architecture (TCA)
نمطان معماريان من الأكثر شيوعًا في iOS وجهًا لوجه: MVVM التقليدي مقابل TCA الوظيفي (functional) من Point-Free. كيف تختار المعمارية الصحيحة؟
مستقبل Apple: تصريحي، تفاعلي، متعدد المنصات
إطار عمل قوي وناضج، اجتاز اختبار 15 عامًا من المعارك
| الفئة | SwiftUI | UIKit |
|---|---|---|
| الأداء | 8/10 | 10/10 |
| سهولة التعلّم | 8/10 | 5/10 |
| النظام البيئي | 8/10 | 9/10 |
| المجتمع | 8/10 | 9/10 |
| سوق العمل | 8/10 | 9/10 |
| الاستدامة المستقبلية | 10/10 | 6/10 |
// SwiftUI - بطاقة ملف تعريف المستخدم
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 ? "إلغاء المتابعة" : "متابعة") {
withAnimation(.spring(response: 0.3)) {
isFollowing.toggle()
}
}
.buttonStyle(.bordered)
.tint(isFollowing ? .gray : .blue)
}
}
.padding()
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}// UIKit - بطاقة ملف تعريف المستخدم
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 = "متابعة"
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، يُفضَّل SwiftUI للمشاريع الجديدة؛ فكل استثمار Apple يتجه إلى هذا الاتجاه. لكن المتطلبات المخصصة المعقدة، أو دعم ما دون iOS 13، أو قاعدة كود قديمة كبيرة، تجعل UIKit لا يزال ضروريًا. النهج المثالي: جرّب SwiftUI أولًا، وادمج مكوّن UIKit عبر UIViewRepresentable عند الحاجة.
احصل على استشارة مجانيةنعم. يمكنك تضمين عرض SwiftUI داخل UIKit عبر UIHostingController، وتضمين عرض UIKit داخل SwiftUI عبر UIViewRepresentable. النهج الهجين شائع في المشاريع الكبيرة.