เข้าถึงองค์ประกอบ viewController ก่อนหน้าด้วยแท็ก

ในสถานการณ์ของฉัน ฉันต้องเข้าถึงปุ่มที่มีแท็กเฉพาะจาก viewController ก่อนหน้า หากมีปุ่มนั้นอยู่ ปุ่มนั้นจะอยู่ในเซลล์มุมมองตารางที่ใช้ซ้ำ

ฉันต้องการเปลี่ยนข้อความของปุ่มนั้นจากมุมมองปัจจุบัน ฉันคิดว่าจะส่งข้อมูลด้วยศูนย์การแจ้งเตือน แต่อาจมี viewController หลายตัวที่แยกออกจากมุมมองปัจจุบัน ดังนั้นจึงไม่ใช่วิธีที่ดี

พยายามด้วยอันหนึ่ง

override func didMove(toParentViewController parent: UIViewController?) {
    super.didMove(toParentViewController: parent)

    if parent == self.navigationController?.parent {
        //check if previous viewController has the button and access it    
    }
}

ความช่วยเหลือใด ๆ ?


person Utku Dalmaz    schedule 01.10.2018    source แหล่งที่มา
comment
คุณได้พิจารณาใช้ PreparForSegue และส่งต่อปุ่มนี้ในวิธีนี้แล้วหรือยัง?   -  person efimovdk    schedule 01.10.2018
comment
ฉันใช้ PreparForSegue อยู่แล้ว คุณช่วยแสดงวิธีใช้ปุ่มที่ส่งผ่านในมุมมองปัจจุบันได้ไหม   -  person Utku Dalmaz    schedule 01.10.2018
comment
@UtkuDalmaz นั่นคือสิ่งที่คำตอบที่โพสต์ทำยกเว้นว่าจะไม่ได้ใช้ตรรกะสตอรี่บอร์ด ฉันรู้ว่าเหตุใดจึงถูกลดระดับลงอย่างมากในเมื่อมีเพียงคนเดียวที่ตอบกลับผิดในบรรทัดแรกของเขา และได้ให้แนวทางแก้ไขตามแนวทางการเปลี่ยนแปลงสถาปัตยกรรมของคุณ คุณเข้าใจคำตอบที่โพสต์หรือไม่?   -  person Rakesha Shastri    schedule 01.10.2018
comment
@RakeshaShastri ใช่ฉันเข้าใจแล้ว แต่ฉันไม่รู้ว่าทำไมมันถึงมี downvotes มากมายขนาดนั้น   -  person Utku Dalmaz    schedule 01.10.2018
comment
@UtkuDalmaz คุณได้ลองแล้วหรือยัง?   -  person Rakesha Shastri    schedule 01.10.2018
comment
ฉันจะพยายามแต่การโหวตลงทำให้ฉันหยุดจริงๆ มีวิธีอื่นอีกไหมที่จะบรรลุเป้าหมายนี้?   -  person Utku Dalmaz    schedule 01.10.2018
comment
@UtkuDalmaz แม้ว่าฉันจะอยากรู้ว่ามีวิธีที่ดีกว่านี้หรือไม่ ดังนั้นฉันจะทิ้งคำตอบไว้ที่นั่นเพื่อให้ใครสักคนอธิบายให้ฉันฟังว่าทำไมมันถึงผิด   -  person Rakesha Shastri    schedule 01.10.2018
comment
ปุ่มของคุณแสดงถึงอะไร? บางรัฐ?   -  person FruitAddict    schedule 01.10.2018
comment
@FruitAddict มันเป็นปุ่มติดตาม ผู้ใช้สามารถติดตามผู้ใช้รายอื่นด้วยปุ่มนั้น แต่พวกเขาสามารถไปที่โปรไฟล์ผู้ใช้และติดตามที่นั่นแทนได้ แต่ฉันจำเป็นต้องเปลี่ยนปุ่มนั้นเมื่อผู้ใช้ติดตามในมุมมองโปรไฟล์ นั่นคือปัญหาของฉัน   -  person Utku Dalmaz    schedule 01.10.2018
comment
ให้ฉันโพสต์คำตอบของฉัน   -  person FruitAddict    schedule 01.10.2018
comment
@UtkuDalmaz ฉันคิดว่าปัญหาคือฉันจัดเก็บโดยตรงและเข้าถึงคุณสมบัติของตัวควบคุมมุมมองแทนที่จะใช้โปรโตคอล คำตอบล่าสุดจะเป็นคำตอบของฉันในเวอร์ชันที่ดีกว่า ซึ่งสุดท้ายแล้วก็จะเหมือนเดิม แต่สะอาดกว่า   -  person Rakesha Shastri    schedule 01.10.2018


คำตอบ (1)


(คำตอบนี้ไม่เกี่ยวกับสถาปัตยกรรมของแอป เพียงโพสต์วิธีแก้ปัญหาง่ายๆ ให้กับปัญหาของผู้เขียน)

คุณบอกว่าปุ่มของคุณแสดงถึงสถานะ 'ติดตาม' ของโมเดลของคุณ (โปรไฟล์) คุณอาจต้องการมีแบบจำลองที่จะแสดงโปรไฟล์:

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
comment
โอ้พระเจ้า ฉันคิดว่าฉันจะเลือกวิธี viewDidAppear :) ขอบคุณสำหรับข้อมูล - person Utku Dalmaz; 01.10.2018
comment
ใช่ การมอบหมายเป็นวิธีที่ 'ชัดเจน' ในการทำสิ่งต่าง ๆ แต่สำหรับกรณีการใช้งานทั่วไป คุณสามารถโหลดซ้ำทุกอย่างตามสถานะได้ สิ่งสำคัญจากโพสต์ของฉันคือรอให้ฉันอัปเดตโพสต์ก่อน - person FruitAddict; 01.10.2018
comment
ฉันใช้วิธีโปรโตคอลและมันใช้งานได้ดี ขอบคุณ - person Utku Dalmaz; 01.10.2018