(คำตอบนี้ไม่เกี่ยวกับสถาปัตยกรรมของแอป เพียงโพสต์วิธีแก้ปัญหาง่ายๆ ให้กับปัญหาของผู้เขียน)
คุณบอกว่าปุ่มของคุณแสดงถึงสถานะ 'ติดตาม' ของโมเดลของคุณ (โปรไฟล์) คุณอาจต้องการมีแบบจำลองที่จะแสดงโปรไฟล์:
class Profile {
var following : Bool = false
}
ViewController
แรกของคุณอาจมีลักษณะดังนี้:
class ProfileListViewController : UIViewController, ProfileDetailsViewControllerDelegate {
var profiles : [Profile] = [...]
func userDidChangeProfileInfo(_ profile : Profile)() {
(...)
}
}
เมื่อคุณเปิดโปรไฟล์ คุณจะเรียกสิ่งนี้ใน ProfileListViewController
ของคุณ:
func openProfileDetails(at indexPath: IndexPath) {
let profile = profiles[indexPath.row]
let detailsViewController = ProfileDetailsViewController.getInstance()
detailsViewController.profile = profile
detailsViewController.delegate = self
self.navigationController?.pushViewController(detailsViewController, animated: true)
}
ฟิลด์ delegate
เป็นโปรโตคอลที่มีลักษณะเช่นนี้และมีการนำไปใช้ในโค้ดด้านบน:
protocol ProfileDetailsViewControllerDelegate : class {
func userDidChangeProfileInfo(_ profile : Profile)
}
ProfileDetailsViewController
:
class ProfileDetailsViewController : UIViewController {
var profile: Profile?
weak var delegate : ProfileDetailsViewControllerDelegate?
func didTapFollowButton() {
profile.following = true
delegate?.userDidChangeProfileInfo(profile)
}
}
ย้อนกลับไปใน ProfileListViewController
ของคุณ delegate
วิธีการจะถูกเรียกและคุณสามารถโหลดแถวของคุณใหม่ (หรือมุมมองตารางทั้งหมดหากคุณต้องการ):
func userDidChangeProfileInfo(_ profile : Profile)() {
if let row = profiles.firstIndex(where: { $0 == profile }) {
tableView.reloadRows(at: [IndexPath(row: row, section: 0)], with: .automatic)
}
}
ถัดไปเซลล์จะถูกสร้างขึ้นใหม่ที่ดัชนีนี้ ดังนั้นจะมีการเรียกใช้เมธอด cellForRowAt
คุณสามารถตั้งค่าเซลล์ของคุณอีกครั้งตามการเปลี่ยนแปลงในโมเดลของคุณ (เปลี่ยนข้อความ สไตล์ คืนเซลล์อื่น ฯลฯ อะไรก็ตามที่ทำให้เรือของคุณลอยและเหมาะกับกรณีการใช้งานของคุณ):
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(...)
let profile = profiles[indexPath.row]
if profile.following {
cell.type = .following
} else {
cell.type = .notFollowing
}
return cell
}
เซลล์เองสามารถมีลักษณะเช่นนี้:
enum ProfileTableCellMode {
case following
case notFollowing
}
class ProfileTableCell : UITableViewCell {
@IBOutlet weak var followButton : UIButton!
var state: ProfileTableCellMode = .notFollowing { //default value
didSet {
onStateUpdated()
}
}
func onStateUpdated() {
switch state {
case .following:
followButton.setTitle("Unfollow", for: .normal)
case .notFollowing:
followButton.setTitle("Follow", for: .normal)
}
}
}
คุณสามารถข้ามการมอบหมายทั้งหมดและทำสิ่งนี้ใน ProfileListViewController
:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.tableView.reloadData()
}
ดังนั้นทั้งตารางจะรีโหลดเมื่อ ProfileListViewController
กลับมาเป็นตัวควบคุมระดับบนสุด
สิ่งที่สำคัญที่สุดที่นี่คือการแยก UI (ส่วนต่อประสานผู้ใช้) ออกจากสถานะ (รุ่น ฯลฯ ) UI ควรแสดงผล/อัปเดตตัวเองตามสถานะ และไม่ควรจัดการตรรกะทางธุรกิจใดๆ นอกเหนือจากการส่งต่อข้อความ 'ฉันถูกคลิก โปรดจัดการ' ไปยังตรรกะ
person
FruitAddict
schedule
01.10.2018