Kaip naudoti MVC architektūrą, kad išvengtumėte kontrolerio perkrovos?
sobes.tech AI
Atsakymas iš AI
MVC (Model-View-Controller) iOS dažnai sukelia "stambius" valdiklius dėl jų verslo logikos ir vaizdo logikos išdėstymo. Šią problemą galima spręsti naudojant šiuos požiūrius:
-
Vaizdo logikos perkėlimas į View: Sukurti specialius
UIViewarba lentelės/kolekcijos langelius, kurie atsakingi už duomenų rodymą ir pagrindinių naudotojo veiksmų (pavyzdžiui, mygtukų paspaudimų) apdorojimą. Valdiklis tik konfigūruoja View su reikiamais duomenimis.class MyCustomView: UIView { private let label = UILabel() override init(frame: CGRect) { super.init(frame: frame) addSubview(label) // constraints ir kt. } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(with text: String) { label.text = text } // UIControlEvents įvykių apdorojimas, pvz., naudojant addTarget } -
Verslo logikos perkėlimas į Model arba atskirus Service Object'us: Sukurti klases, atsakingas už konkrečias operacijas (pvz., tinklo, duomenų bazės, duomenų validacijos darbai). Valdiklis deleguoja šių užduočių vykdymą šiems objektams.
class UserService { func fetchUsers(completion: @escaping ([User]?, Error?) -> Void) { // tinklo užklausos logika } } class ProfileViewController: UIViewController { private let userService = UserService() override func viewDidLoad() { super.viewDidLoad() userService.fetchUsers { users, error in // UI atnaujinimas pagal gautus duomenis arba klaidą } } } -
Naudojant Data Source ir Delegate Protocols: Įgyvendinti
UITableViewDataSource,UICollectionViewDataSource,UITableViewDelegate,UICollectionViewDelegateprotokolus atskiruose klasėse, o ne pačiame valdiklyje. Valdiklis tik turės šių klasių egzempliorius.class UsersTableViewDataSource: NSObject, UITableViewDataSource { private var users: [User] = [] func update(users: [User]) { self.users = users } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return users.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath) let user = users[indexPath.row] cell.textLabel?.text = user.name return cell } } class UsersViewController: UIViewController { @IBOutlet weak var tableView: UITableView! private let dataSource = UsersTableViewDataSource() override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = dataSource // Duomenų įkėlimas ir perdavimas į dataSource.update(users:) } } -
Coordinator Pattern taikymas: Sukurti atskirus objektus, atsakingus už navigaciją tarp ekranų. Valdikliai žino tik tai, kad reikia pereiti prie kito žingsnio, bet nežino, kuris valdiklis bus kitas.
protocol AppCoordinator: AnyObject { func start() func showUserDetails(user: User) } class MainAppCoordinator: AppCoordinator { private let navigationController: UINavigationController init(navigationController: UINavigationController) { self.navigationController = navigationController } func start() { let usersVC = UsersViewController() // nustatyti delegatus, dataSource ir kt. navigationController.pushViewController(usersVC, animated: false) } func showUserDetails(user: User) { let userDetailsVC = UserDetailsViewController(user: user) navigationController.pushViewController(userDetailsVC, animated: true) } }
Šie požiūriai leidžia sumažinti valdiklio apkrovą, padaryti jį "plonesnį" ir sutelkti dėmesį į View gyvavimo ciklo valdymą ir sąveiką tarp Model ir View, o ne į visos programos logikos vykdymą.