Akses elemen viewController sebelumnya dengan tagnya

Dalam skenario saya, saya perlu mengakses tombol dengan tag tertentu dari viewController sebelumnya jika tombol itu ada. Tombol itu akan ditempatkan di sel tampilan tabel yang digunakan kembali.

Saya ingin mengubah teks tombol itu dari tampilan saat ini. Saya berpikir untuk mengirim data dengan Pusat Pemberitahuan tetapi mungkin ada beberapa viewController yang dipisahkan ke tampilan saat ini jadi itu bukan cara yang baik.

Mencoba dengan satu

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    
    }
}

Ada bantuan?


person Utku Dalmaz    schedule 01.10.2018    source sumber
comment
Sudahkah Anda mempertimbangkan untuk menerapkan prepForSegue dan meneruskan tombol ini dalam metode ini?   -  person efimovdk    schedule 01.10.2018
comment
Saya sudah menggunakan prepForSegue. Bisakah Anda menunjukkan kepada saya cara menggunakan tombol yang diteruskan dalam tampilan saat ini?   -  person Utku Dalmaz    schedule 01.10.2018
comment
@UtkuDalmaz itulah yang dilakukan oleh jawaban yang diposting, kecuali bahwa jawaban tersebut tidak menggunakan logika storyboard. Saya tahu mengapa ini mendapat banyak suara negatif ketika satu-satunya orang yang merespons salah di baris pertamanya dan telah memberikan solusi untuk mengubah arsitektur Anda. Apakah Anda memahami jawaban yang diposting?   -  person Rakesha Shastri    schedule 01.10.2018
comment
@RakeshaShastri ya saya mengerti. tapi saya tidak tahu mengapa ada banyak suara negatif   -  person Utku Dalmaz    schedule 01.10.2018
comment
@UtkuDalmaz apakah Anda mencobanya?   -  person Rakesha Shastri    schedule 01.10.2018
comment
Tadinya saya akan mencoba tetapi suara negatif membuat saya berhenti sebenarnya. apakah ada cara lain untuk mencapai ini btw?   -  person Utku Dalmaz    schedule 01.10.2018
comment
@UtkuDalmaz bahkan saya ingin tahu apakah ada cara yang lebih baik. Jadi saya akan meninggalkan jawaban saya di sana untuk seseorang yang akan menjelaskan kepada saya mengapa jawaban itu salah.   -  person Rakesha Shastri    schedule 01.10.2018
comment
Apa yang diwakili oleh tombol Anda? Beberapa negara bagian?   -  person FruitAddict    schedule 01.10.2018
comment
@FruitAddict itu adalah tombol ikuti. pengguna dapat mengikuti pengguna lain dengan tombol itu. Namun mereka juga dapat membuka profil pengguna dan mengikuti di sana, tetapi saya perlu mengubah tombol itu ketika pengguna mengikuti pada tampilan profil. itu masalah saya.   -  person Utku Dalmaz    schedule 01.10.2018
comment
izinkan saya memposting jawaban saya   -  person FruitAddict    schedule 01.10.2018
comment
@UtkuDalmaz menurut saya masalahnya adalah saya langsung menyimpan dan mengakses properti pengontrol tampilan alih-alih menggunakan protokol. Jawaban terbaru akan menjadi versi yang lebih baik dari jawaban saya, yang pada akhirnya melakukan hal yang sama, namun lebih bersih.   -  person Rakesha Shastri    schedule 01.10.2018


Jawaban (1)


(jawaban ini bukan tentang arsitektur aplikasi, hanya memposting solusi sederhana untuk masalah penulis)

Anda mengatakan bahwa tombol Anda mewakili status 'ikuti' model Anda (Profil). Anda mungkin ingin memiliki model yang mewakili profil:

class Profile {
    var following : Bool = false
}

ViewController pertama Anda mungkin akan terlihat seperti ini:

class ProfileListViewController : UIViewController, ProfileDetailsViewControllerDelegate {
    var profiles : [Profile] = [...]

    func userDidChangeProfileInfo(_ profile : Profile)() {
        (...)
    }
}

Saat Anda membuka profil, Anda akan memanggil sesuatu seperti ini di ProfileListViewController Anda:

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)
}

bidang delegate adalah protokol yang terlihat seperti ini dan diimplementasikan dalam kode di atas:

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)
   }
}

kembali ke ProfileListViewController Anda, metode delegate akan dipanggil dan Anda dapat memuat ulang baris Anda (atau seluruh tampilan tabel jika Anda mau):

func userDidChangeProfileInfo(_ profile : Profile)() {
    if let row = profiles.firstIndex(where: { $0 == profile }) {
        tableView.reloadRows(at: [IndexPath(row: row, section: 0)], with: .automatic)
    }
}

Selanjutnya sel akan dibuat ulang pada indeks ini sehingga metode cellForRowAt akan dipanggil. Anda dapat mengatur sel Anda lagi berdasarkan perubahan pada model Anda (mengubah teks, gaya, mengembalikan sel yang berbeda, dll, apa pun yang sesuai dengan keinginan Anda dan sesuai dengan kasus penggunaan Anda):

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

}

Sel itu sendiri bisa terlihat seperti ini:

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)

        }
    }

}

Anda juga dapat melewati semua hal pendelegasian dan langsung melakukan hal seperti ini di ProfileListViewController:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.tableView.reloadData()
}

Jadi seluruh tabel dimuat ulang ketika ProfileListViewController kembali menjadi pengontrol teratas.

Hal terpenting di sini adalah memisahkan UI (antarmuka pengguna) dari status (model, dll). UI harus merender/memperbarui dirinya sendiri berdasarkan status dan tidak boleh menangani logika bisnis apa pun selain meneruskan 'saya diklik, tolong tangani' ke logika tersebut.

person FruitAddict    schedule 01.10.2018
comment
Ya ampun, saya rasa saya akan memilih cara viewDidAppear :) terima kasih atas infonya. - person Utku Dalmaz; 01.10.2018
comment
Ya, mendelegasikan adalah cara yang lebih 'jelas' dalam melakukan sesuatu tetapi untuk kasus penggunaan sederhana Anda dapat memuat ulang semuanya berdasarkan negara bagian. Yang penting dari postingan saya ini, tunggu dulu biar saya update postingannya - person FruitAddict; 01.10.2018
comment
Saya menerapkan cara protokol dan itu berfungsi dengan baik. terima kasih - person Utku Dalmaz; 01.10.2018