SnapKit 16: SwiftUI dan SnapKit ga Ko'prik — SwiftUI bilsang, SnapKit'ni 10x tez o'rganasan
🧩 SnapKit — Zero to Hero
SnapKit 15: SwiftUI dan SnapKit ga Ko'prik — SwiftUI bilsang, SnapKit'ni 10x tez o'rganasan
Holat: Ushbu dars 2026-yil oktabr holatiga ko'ra tayyorlangan. Agar siz SwiftUI'ni yaxshi bilsangiz, ushbu dars sizga SnapKit (va umuman UIKit layout) qanday ishlashini SwiftUI analoglari orqali juda tez o'rganishga yordam beradi.
Mundarija
- VStack → Vertikal Layout
- HStack → Gorizontal Layout
- ZStack → Ustma-ust qo'yish (Layering)
- .padding() → inset/offset
- .frame(width:height:) → size constraints
- .background() / .overlay() → background va overlay view
- Spacer() → Bo'sh joy
- .cornerRadius / .clipShape → layer.cornerRadius
- .shadow → layer.shadow
- ScrollView → UIScrollView
- List → UITableView
- @State / Animation → Constraint Animation
- GeometryReader → layoutSubviews / bounds
- NavigationStack → UINavigationController
- KATTA AMALIY LOYIHA 1: Profil ekrani
- KATTA AMALIY LOYIHA 2: Product Card
- SwiftUI vs SnapKit: Qachon qaysi biri?
- Xulosa
- Manbalar
1. VStack → Vertikal Layout {#vstack}
SwiftUI'da elementlarni vertikal joylashtirish uchun VStack ishlatamiz. SnapKit'da buning eng yaqin ekvivalenti UIStackView(.vertical) hisoblanadi. Yoki to'liq moslashuvchanlik uchun barcha constraint'larni o'zimiz yozishimiz mumkin.
SwiftUI'da:
VStack(spacing: 16) {
Text("Salom")
Button("Bosing") {}
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
1-usul: UIStackView (Tavsiya etiladi)
import UIKit
import SnapKit
class VstackViewController: UIViewController {
let titleLabel = UILabel()
let actionButton = UIButton(type: .system)
// VStack ekvivalenti
lazy var vStack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [titleLabel, actionButton])
stack.axis = .vertical
stack.spacing = 16
stack.alignment = .center // SwiftUI'dagi VStack alignment'i kabi
return stack
}()
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = "Salom"
actionButton.setTitle("Bosing", for: .normal)
view.addSubview(vStack)
vStack.snp.makeConstraints { make in
make.center.equalToSuperview()
}
}
}
2-usul: Manual Constraints (SnapKit orqali, StackView'siz)
// Elementlarni to'g'ridan to'g'ri view'ga qo'shamiz
view.addSubview(titleLabel)
view.addSubview(actionButton)
titleLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().offset(-16) // Markazdan sal teparoqda
}
actionButton.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(titleLabel.snp.bottom).offset(16) // spacing: 16
}
2. HStack → Gorizontal Layout {#hstack}
Xuddi VStack kabi, HStack ham UIStackView yordamida (axis = .horizontal) yoki manual constraint'lar orqali amalga oshiriladi.
SwiftUI'da:
HStack(spacing: 12) {
Image(systemName: "star")
Text("Reyting")
Spacer()
Button("Ko'rish") {}
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
import UIKit
import SnapKit
class HstackViewController: UIViewController {
let iconImageView = UIImageView(image: UIImage(systemName: "star"))
let titleLabel = UILabel()
let actionButton = UIButton(type: .system)
lazy var hStack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [iconImageView, titleLabel, UIView(), actionButton])
stack.axis = .horizontal
stack.spacing = 12
stack.alignment = .center
return stack
}()
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = "Reyting"
actionButton.setTitle("Ko'rish", for: .normal)
// Spacer() vazifasini stack.arrangedSubviews ichidagi UIView() bajaradi!
// U bo'sh joyni egallaydi.
view.addSubview(hStack)
hStack.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(16)
make.centerY.equalToSuperview()
}
}
}
3. ZStack → Ustma-ust qo'yish (Layering) {#zstack}
SwiftUI'da ZStack elementlarni bir-birining ustiga qo'yadi (z-order). Oxirgi qo'shilgan element eng tepada turadi. SnapKit'da buni qilish juda oson: biz elementlarni bitta parent view'ga ketma-ket addSubview() qilamiz va hammasining chegaralarini (edges) bir xil qilib belgilaymiz.
SwiftUI'da:
ZStack {
Image("background")
LinearGradient(colors: [.black.opacity(0.5), .clear], startPoint: .bottom, endPoint: .top)
Text("Sarlavha")
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let backgroundImageView = UIImageView(image: UIImage(named: "background"))
let gradientView = UIView()
let titleLabel = UILabel()
titleLabel.text = "Sarlavha"
// 1. Qo'shish tartibi Z-ordering'ni bildiradi
// Eng birinchi qo'shilgan eng orqada bo'ladi.
view.addSubview(backgroundImageView)
view.addSubview(gradientView)
view.addSubview(titleLabel)
backgroundImageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
gradientView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
}
4. .padding() → inset/offset {#padding}
SwiftUI'da .padding() o'zi turgan joydan ichkariga joy tashlaydi. SnapKit'da esa buning uchun asosan offset() va inset() ishlatamiz.
SwiftUI'da:
Text("Salom")
.padding(16) // Barcha tarafdan
.padding(.horizontal, 20) // Faqat chap va o'ngdan
.padding(.top, 32) // Faqat tepadan
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let containerView = UIView()
let titleLabel = UILabel()
containerView.addSubview(titleLabel)
// .padding(16) ga ekvivalent:
titleLabel.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(16)
}
// .padding(.horizontal, 20) ga ekvivalent:
titleLabel.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview().inset(20)
make.top.bottom.equalToSuperview() // boshqa taraflar padding'siz
}
// .padding(.top, 32) ga ekvivalent:
titleLabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(32)
// qolganlari ...
}
Muhim:
offsetvainsetfarqi. Bottom va trailing uchunoffsetmanfiy bo'lishi kerak. Ammoinsetorqali berilsa, doim musbat son yoziladi (ichkariga siqish). JADVAL: -.padding(.top, N)=make.top.offset(N)-.padding(.bottom, N)=make.bottom.inset(N)(Yokioffset(-N)) -.padding(.leading, N)=make.leading.offset(N)-.padding(.trailing, N)=make.trailing.inset(N)(Yokioffset(-N))
5. .frame(width:height:) → size constraints {#frame}
SwiftUI'dagi .frame orqali width/height beriladi. SnapKit'da esa buning uchun width, height, va size ishlatiladi.
SwiftUI'da:
Color.red
.frame(width: 200, height: 100)
.frame(maxWidth: .infinity)
.frame(minHeight: 44)
.frame(maxWidth: 300)
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let redView = UIView()
redView.backgroundColor = .red
view.addSubview(redView)
redView.snp.makeConstraints { make in
// .frame(width: 200, height: 100)
make.size.equalTo(CGSize(width: 200, height: 100))
// yoki: make.width.equalTo(200); make.height.equalTo(100)
// .frame(maxWidth: .infinity) -> Parent'ni to'ldirish
make.width.equalToSuperview()
// .frame(minHeight: 44)
make.height.greaterThanOrEqualTo(44)
// .frame(maxWidth: 300)
make.width.lessThanOrEqualTo(300)
}
6. .background() / .overlay() → background va overlay view {#background}
SwiftUI'da element orqasiga .background() bilan, ustiga .overlay() bilan view qo'shamiz. UIKit'da .backgroundColor ishlatish mumkin yoki yana ZStack logikasiga o'xshab view'lar tartibi bilan hal qilinadi.
SwiftUI'da:
Text("Salom")
.background(Color.blue)
Text("Salom")
.background(RoundedRectangle(cornerRadius: 8).fill(.blue))
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let titleLabel = UILabel()
titleLabel.text = "Salom"
// 1-usul: Oddiy rang (Faqat shu element o'zi)
titleLabel.backgroundColor = .systemBlue
// 2-usul: Alohida View (Masalan rasm yoki gradient qo'ymoqchi bo'lsangiz)
let backgroundView = UIView()
backgroundView.backgroundColor = .systemBlue
backgroundView.layer.cornerRadius = 8
view.addSubview(backgroundView)
view.addSubview(titleLabel) // titleLabel tepada
titleLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
}
// BackgroundView titleLabel bilan bir xil o'lcham va joylashuvga ega bo'ladi
backgroundView.snp.makeConstraints { make in
make.edges.equalTo(titleLabel).inset(-8) // Atrofiga biroz padding qo'shish
}
7. Spacer() → Bo'sh joy {#spacer}
SwiftUI'da Spacer() moslashuvchan bo'sh joy yaratadi. UIKit'da buning 3 xil ekvivalenti bor.
SwiftUI'da:
HStack {
Text("Chapda")
Spacer()
Text("O'ngda")
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
a) UIView() spacer (Eng oson, UIStackView bilan):
let hStack = UIStackView(arrangedSubviews: [leftLabel, UIView(), rightLabel])
hStack.axis = .horizontal
// UIView() avtomatik bo'shliqni egallaydi.
b) UILayoutGuide (Xotira tejamkor): Agar stackView ishlatmasangiz, bo'sh UIView o'rniga UILayoutGuide ishlating, chunki u ekranda render bo'lmaydi.
let spacerGuide = UILayoutGuide()
view.addLayoutGuide(spacerGuide)
view.addSubview(leftLabel)
view.addSubview(rightLabel)
leftLabel.snp.makeConstraints { make in
make.left.equalToSuperview()
make.right.equalTo(spacerGuide.snp.left)
}
spacerGuide.snp.makeConstraints { make in
make.right.equalTo(rightLabel.snp.left)
// spacer o'ziga qarab cho'ziladi
}
rightLabel.snp.makeConstraints { make in
make.right.equalToSuperview()
}
c) Content Hugging Priority (Advanced):
view.addSubview(leftLabel)
view.addSubview(rightLabel)
// rightLabel ni o'ngga yopishtiramiz, leftLabel chapga. O'rtadagi masofa avtomatik ochiladi.
leftLabel.snp.makeConstraints { make in
make.left.equalToSuperview()
make.right.lessThanOrEqualTo(rightLabel.snp.left)
}
rightLabel.snp.makeConstraints { make in
make.right.equalToSuperview()
}
// Chapdagi label siqilmasligi uchun, o'ngdagiga ustunlik beramiz
rightLabel.setContentHuggingPriority(.required, for: .horizontal)
8. .cornerRadius / .clipShape → layer.cornerRadius {#cornerradius}
SwiftUI'da:
Image("profile")
.cornerRadius(12)
Image("profile")
.clipShape(Circle())
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let profileImageView = UIImageView(image: UIImage(named: "profile"))
profileImageView.clipsToBounds = true // SwiftUI'dagi kabi qirqilishi uchun muhim!
// .cornerRadius(12)
profileImageView.layer.cornerRadius = 12
// .clipShape(Circle()) (O'lchami 80x80 deb faraz qilsak)
profileImageView.snp.makeConstraints { make in
make.size.equalTo(80)
}
profileImageView.layer.cornerRadius = 40 // width / 2
9. .shadow → layer.shadow {#shadow}
Shadow berish SwiftUI'da juda oson, UIKit'da esa biroz ko'proq kod yoziladi.
SwiftUI'da:
Color.white
.shadow(color: .black.opacity(0.2), radius: 8, x: 0, y: 4)
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let cardView = UIView()
cardView.backgroundColor = .white
// .shadow ekvivalenti
cardView.layer.shadowColor = UIColor.black.cgColor
cardView.layer.shadowOpacity = 0.2
cardView.layer.shadowRadius = 8
cardView.layer.shadowOffset = CGSize(width: 0, height: 4)
// MUHIM: Shadow ko'rinishi uchun clipsToBounds false bo'lishi kerak!
cardView.clipsToBounds = false
10. ScrollView → UIScrollView {#scrollview}
ScrollView UIKit'da SwiftUI'ga qaraganda birmuncha murakkabroq ishlaydi, chunki unda contentSize tushunchasi bor. SnapKit bilan buni oson qilish mumkin (contentView yaratish).
SwiftUI'da:
ScrollView {
VStack {
Text("Tepa")
// ... ko'p elementlar
Text("Past")
}
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
let scrollView = UIScrollView()
let contentView = UIView() // Barcha elementlar shunga tushadi
let topLabel = UILabel()
let bottomLabel = UILabel()
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(topLabel)
contentView.addSubview(bottomLabel)
// 1. ScrollView ekranni to'ldiradi
scrollView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
// 2. ContentView ScrollView'ning content'ini belgilaydi
contentView.snp.makeConstraints { make in
make.edges.equalToSuperview() // Content hajmiga mos
make.width.equalTo(scrollView) // Vertikal scroll qilish uchun width'ni scrollView'ga tenglaymiz (X o'qida scroll yo'q)
}
// 3. Ichki elementlarni contentView ga yopishtiramiz
topLabel.snp.makeConstraints { make in
make.top.left.right.equalToSuperview().inset(20)
}
bottomLabel.snp.makeConstraints { make in
make.top.equalTo(topLabel.snp.bottom).offset(1000) // Juda uzoq
make.left.right.equalToSuperview().inset(20)
make.bottom.equalToSuperview().inset(20) // MUHIM: contentView'ning bottom'ini belgilash!
}
11. List → UITableView {#list}
SwiftUI'da List barcha ishlarni o'zi bajaradi. UIKit'da buning uchun UITableView (yoki UICollectionView) ishlatamiz.
SwiftUI'da:
List {
ForEach(items) { item in
Text(item.name)
}
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
// Controller ichida
let tableView = UITableView()
view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
// Cell dizayni
class CustomCell: UITableViewCell {
let titleLabel = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// MUHIM: Har doim contentView.addSubview ishlatiladi!
contentView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(16)
}
}
required init?(coder: NSCoder) { fatalError() }
}
12. @State / Animation → Constraint Animation {#animation}
SwiftUI'da constraint'lar o'rniga holat (State) o'zgarishi kifoya. UIKit'da biz constraint referensini saqlab, uni o'zgartiramiz va layoutIfNeeded() chaqiramiz.
SwiftUI'da:
@State var isExpanded = false
Color.blue
.frame(height: isExpanded ? 200 : 80)
.animation(.spring(), value: isExpanded)
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
import SnapKit
let boxView = UIView()
var heightConstraint: Constraint? // Constraint'ni saqlab qo'yamiz
boxView.backgroundColor = .blue
view.addSubview(boxView)
boxView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.width.equalTo(100)
// Referensni saqlash:
self.heightConstraint = make.height.equalTo(80).constraint
}
// Animatsiyani trigger qilish
@objc func toggleSize() {
let isExpanded = (boxView.bounds.height > 100)
let newHeight = isExpanded ? 80 : 200
// 1. Constraint'ni yangilash
heightConstraint?.update(offset: newHeight)
// 2. Animatsiya bilan layout'ni qayta chizish
UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8) {
self.view.layoutIfNeeded() // UIKit shu buyruq orqali animatsiya qiladi!
}
}
13. GeometryReader → layoutSubviews / bounds {#geometryreader}
GeometryReader orqali view'ning o'zini hajmini bilib, shunga qarab boshqa narsalarga o'lcham beramiz. SnapKit buni asosan multipliedBy va UIKit ning layoutSubviews funksiyasi bilan qoplaydi.
SwiftUI'da:
GeometryReader { geo in
Color.red
.frame(width: geo.size.width * 0.5) // Ekranning yarmi
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
// SnapKit usuli:
let redBox = UIView()
redBox.backgroundColor = .red
view.addSubview(redBox)
redBox.snp.makeConstraints { make in
make.height.equalTo(100)
// Ekranning (parent viewning) yarmi:
make.width.equalToSuperview().multipliedBy(0.5)
}
// Yoki aniq o'lcham kerak bo'lganda (UIKit standard):
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let parentWidth = view.bounds.width
print("Mening o'lchamim endi ma'lum: \(parentWidth)")
}
14. NavigationStack → UINavigationController {#navigationstack}
SwiftUI'da:
NavigationStack {
VStack { ... }
.navigationTitle("Asosiy")
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
// SceneDelegate yoki AppDelegate ichida:
let mainVC = MainViewController()
mainVC.title = "Asosiy"
let navController = UINavigationController(rootViewController: mainVC)
window?.rootViewController = navController
15. KATTA AMALIY LOYIHA 1: Profil ekrani {#loyiha1}
Bu yerda siz har ikki texnologiya o'rtasidagi to'liq ekvivalentlikni amalda ko'rasiz.
SwiftUI'da (qisqa va aniq):
struct ProfileView: View {
var body: some View {
ScrollView {
VStack(spacing: 16) {
Image("avatar")
.resizable()
.frame(width: 80, height: 80)
.clipShape(Circle())
Text("Azimjon")
.font(.system(size: 24, weight: .bold))
Text("iOS Dasturchi. Kod yozaman va qahva ichaman.")
.foregroundColor(.gray)
.multilineTextAlignment(.center)
.padding(.horizontal, 32)
HStack(spacing: 30) {
VStack { Text("120").bold(); Text("Posts") }
VStack { Text("4K").bold(); Text("Followers") }
VStack { Text("120").bold(); Text("Following") }
}
.padding(.top, 16)
Button(action: {}) {
Text("Edit Profile")
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.cornerRadius(8)
}
.padding(.horizontal, 32)
.padding(.top, 24)
}
.padding(.top, 40)
}
}
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz (to'liq kontrol):
import UIKit
import SnapKit
class ProfileViewController: UIViewController {
// View'larni e'lon qilish
let scrollView = UIScrollView()
let contentView = UIView()
let avatarImageView: UIImageView = {
let img = UIImageView()
img.backgroundColor = .systemGray4
img.layer.cornerRadius = 40
img.clipsToBounds = true
return img
}()
let nameLabel: UILabel = {
let lbl = UILabel()
lbl.text = "Azimjon"
lbl.font = .systemFont(ofSize: 24, weight: .bold)
return lbl
}()
let bioLabel: UILabel = {
let lbl = UILabel()
lbl.text = "iOS Dasturchi. Kod yozaman va qahva ichaman."
lbl.textColor = .gray
lbl.numberOfLines = 0
lbl.textAlignment = .center
return lbl
}()
lazy var statsStack: UIStackView = {
let postsStack = createStatStack(count: "120", title: "Posts")
let followersStack = createStatStack(count: "4K", title: "Followers")
let followingStack = createStatStack(count: "120", title: "Following")
let stack = UIStackView(arrangedSubviews: [postsStack, followersStack, followingStack])
stack.axis = .horizontal
stack.spacing = 30
stack.alignment = .center
return stack
}()
let editButton: UIButton = {
let btn = UIButton(type: .system)
btn.setTitle("Edit Profile", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.backgroundColor = .systemBlue
btn.layer.cornerRadius = 8
return btn
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupViews()
setupConstraints()
}
func createStatStack(count: String, title: String) -> UIStackView {
let countLbl = UILabel()
countLbl.text = count
countLbl.font = .boldSystemFont(ofSize: 16)
let titleLbl = UILabel()
titleLbl.text = title
titleLbl.font = .systemFont(ofSize: 14)
let stack = UIStackView(arrangedSubviews: [countLbl, titleLbl])
stack.axis = .vertical
stack.alignment = .center
return stack
}
func setupViews() {
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(avatarImageView)
contentView.addSubview(nameLabel)
contentView.addSubview(bioLabel)
contentView.addSubview(statsStack)
contentView.addSubview(editButton)
}
func setupConstraints() {
scrollView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
contentView.snp.makeConstraints { make in
make.edges.equalToSuperview()
make.width.equalTo(scrollView)
}
avatarImageView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(40)
make.centerX.equalToSuperview()
make.size.equalTo(80)
}
nameLabel.snp.makeConstraints { make in
make.top.equalTo(avatarImageView.snp.bottom).offset(16)
make.centerX.equalToSuperview()
}
bioLabel.snp.makeConstraints { make in
make.top.equalTo(nameLabel.snp.bottom).offset(16)
make.left.right.equalToSuperview().inset(32)
}
statsStack.snp.makeConstraints { make in
make.top.equalTo(bioLabel.snp.bottom).offset(32)
make.centerX.equalToSuperview()
}
editButton.snp.makeConstraints { make in
make.top.equalTo(statsStack.snp.bottom).offset(32)
make.left.right.equalToSuperview().inset(32)
make.height.equalTo(50)
make.bottom.equalToSuperview().offset(-40) // ContentView o'lchami shu yergacha!
}
}
}
16. KATTA AMALIY LOYIHA 2: Product Card {#loyiha2}
Ushbu misolda shadow va corner radiuslar qanday qilib kompleks tarzda ishlashini ko'ramiz.
SwiftUI'da:
struct ProductCard: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Color.gray // Rasm o'rni (4:3)
.aspectRatio(4/3, contentMode: .fit)
Text("AirPods Pro")
.font(.headline)
.padding(.horizontal, 12)
HStack {
Text("$249.00").bold()
Spacer()
Text("⭐️ 4.8")
}
.padding(.horizontal, 12)
Button("Add to Cart") {}
.padding()
.frame(maxWidth: .infinity)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
.padding(12)
}
.background(Color.white)
.cornerRadius(12)
.shadow(color: .black.opacity(0.1), radius: 10, y: 5)
.padding()
}
}
Endi xuddi shu layout'ni SnapKit yordamida qilamiz:
import UIKit
import SnapKit
class ProductCardView: UIView {
let productImageView = UIImageView()
let titleLabel = UILabel()
let priceLabel = UILabel()
let ratingLabel = UILabel()
let addButton = UIButton(type: .system)
override init(frame: CGRect) {
super.init(frame: frame)
setupStyle()
setupViews()
setupConstraints()
}
required init?(coder: NSCoder) { fatalError() }
private func setupStyle() {
backgroundColor = .white
layer.cornerRadius = 12
// Shadow configuration
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.1
layer.shadowRadius = 10
layer.shadowOffset = CGSize(width: 0, height: 5)
clipsToBounds = false
productImageView.backgroundColor = .systemGray5
productImageView.layer.cornerRadius = 12
productImageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
productImageView.clipsToBounds = true
titleLabel.text = "AirPods Pro"
titleLabel.font = .systemFont(ofSize: 17, weight: .semibold)
priceLabel.text = "$249.00"
priceLabel.font = .boldSystemFont(ofSize: 16)
ratingLabel.text = "⭐️ 4.8"
ratingLabel.font = .systemFont(ofSize: 14)
addButton.setTitle("Add to Cart", for: .normal)
addButton.backgroundColor = .systemBlue
addButton.setTitleColor(.white, for: .normal)
addButton.layer.cornerRadius = 8
}
private func setupViews() {
addSubview(productImageView)
addSubview(titleLabel)
addSubview(priceLabel)
addSubview(ratingLabel)
addSubview(addButton)
}
private func setupConstraints() {
productImageView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
// Aspect ratio 4:3 -> height = width * 0.75
make.height.equalTo(productImageView.snp.width).multipliedBy(0.75)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(productImageView.snp.bottom).offset(12)
make.left.right.equalToSuperview().inset(12)
}
priceLabel.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(8)
make.left.equalToSuperview().inset(12)
}
ratingLabel.snp.makeConstraints { make in
make.centerY.equalTo(priceLabel)
make.right.equalToSuperview().inset(12)
make.left.greaterThanOrEqualTo(priceLabel.snp.right).offset(8)
}
addButton.snp.makeConstraints { make in
make.top.equalTo(priceLabel.snp.bottom).offset(16)
make.left.right.bottom.equalToSuperview().inset(12)
make.height.equalTo(44)
}
}
}
17. SwiftUI vs SnapKit: Qachon qaysi biri? {#qachon}
Ikkala yondashuvning ham o'z kuchli va zaif tomonlari bor. Quyidagi jadval qachon qaysi birini tanlash haqida:
| Mezon | SwiftUI | SnapKit (UIKit) | Izoh |
|---|---|---|---|
| Tezlik | ✅ Juda tez | ⚠️ O'rtacha | SwiftUI yordamida UI ni tezroq terish mumkin, chunki u deklarativ. |
| Kontrol | ⚠️ Kamroq | ✅ To'liq | SnapKit (UIKit) da har bir pixel, constraint'lar va view ierarxiyasi ustidan to'liq nazorat bor. |
| Performance | ⚠️ O'rtacha | ✅ Yuqori | UIKit framework'i past darajali bo'lgani uchun, ayniqsa ro'yxatlar va murakkab layoutlarda barqarorroq ishlashi mumkin. |
| Animatsiya | ✅ Oson | ✅ Murakkab | SwiftUI da oddiy animatsiyalar juda oson, ammo murakkab va interaktiv animatsiyalar uchun UIKit qulay. |
| Versiya (Legacy) | ❌ iOS 13+ (Asosan 15+) | ✅ iOS 12+ (Eski versiyalar) | Eski proyektlar (Legacy code) asosan UIKit da. SnapKit esa uning eng yaxshi yordamchisi. |
| Ishga Joylashish | ⚠️ Yaxshi | ✅ Yuqori Talab | Ko'pgina katta va mavjud proyektlar hamon UIKit/SnapKit ga asoslangan. Ikkalasini ham bilish katta ustunlik. |
Xulosa {#xulosa}
Agar siz SwiftUI ni bilsangiz, UIKit da UI qanday qurilishini tasavvur qilish ancha osonlashadi. SnapKit bu - UIKit constraint'larini SwiftUI singari intuitiv qilib beruvchi vositadir. SwiftUI'dagi VStack, HStack lar UIKit'da UIStackView va SnapKit ning moslashuvchan funksiyalari orqali xuddi shunday amalga oshiriladi. Eng asosiysi - ikkala freymvork ortidagi "layout mantiqi" (masofa, joylashuv, o'lchamlar) deyarli bir xil, faqat sintaksis farq qiladi xolos.