Dapatkan ke UIViewController dari UIView?

185

Apakah ada cara bawaan untuk mendapatkan dari a UIViewke miliknya UIViewController? Saya tahu Anda bisa mendapatkan dari UIViewControllerke-nya UIViewmelalui [self view]tapi saya bertanya-tanya apakah ada referensi terbalik?

bertrandom
sumber

Jawaban:

46

Karena ini sudah menjadi jawaban yang diterima sejak lama, saya merasa perlu memperbaikinya dengan jawaban yang lebih baik.

Beberapa komentar tentang kebutuhan:

  • Tampilan Anda tidak perlu mengakses controller tampilan secara langsung.
  • Pandangan sebaliknya harus independen dari pengontrol tampilan, dan dapat bekerja dalam konteks yang berbeda.
  • Jika Anda memerlukan tampilan untuk berinteraksi dengan pengontrol tampilan, cara yang disarankan, dan apa yang dilakukan Apple di seluruh Cocoa adalah dengan menggunakan pola delegasi.

Contoh cara menerapkannya adalah sebagai berikut:

@protocol MyViewDelegate < NSObject >

- (void)viewActionHappened;

@end

@interface MyView : UIView

@property (nonatomic, assign) MyViewDelegate delegate;

@end

@interface MyViewController < MyViewDelegate >

@end

Tampilan berinteraksi dengan delegasinya (seperti UITableViewhalnya, misalnya) dan tidak peduli jika diterapkan di controller tampilan atau di kelas lain yang akhirnya Anda gunakan.

Jawaban asli saya berikut: Saya tidak merekomendasikan ini, baik sisa jawaban mana akses langsung ke pengontrol tampilan tercapai

Tidak ada cara bawaan untuk melakukannya. Meskipun Anda bisa mendapatkan sekitar itu dengan menambahkan IBOutletpada UIViewdan menghubungkan ini di Interface Builder, ini tidak dianjurkan. Pandangan seharusnya tidak tahu tentang pengontrol tampilan. Sebagai gantinya, Anda harus melakukan seperti yang disarankan oleh @Phil M dan membuat protokol untuk digunakan sebagai delegasi.

hal
sumber
26
Itu saran yang sangat buruk. Anda tidak boleh merujuk pengontrol tampilan dari tampilan
Philippe Leybaert
6
@MattDiPasquale: ya, ini desain yang buruk.
Philippe Leybaert
23
@Phillipe Leybaert Saya ingin tahu pendapat Anda tentang desain terbaik untuk acara klik tombol yang harus meminta beberapa tindakan pada controller, tanpa tampilan memegang referensi ke controller. Terima kasih
Jonathon Horsman
3
@PhilippeLeybaert Contoh proyek Apple cenderung menunjukkan penggunaan fitur API tertentu. Banyak yang saya maksudkan mengorbankan desain yang baik atau yang dapat diskalakan untuk memberikan demonstrasi topik yang ringkas. Butuh waktu lama bagi saya untuk menyadari hal ini dan meskipun masuk akal, saya merasa disayangkan. Saya pikir banyak pengembang mengambil proyek pragmatis ini sebagai panduan Apple untuk praktik desain terbaik, yang saya yakin tidak.
Benjohn
11
Semua ini tentang "Anda seharusnya tidak melakukan ini" hanya itu. Jika pandangan ingin tahu tentang pengontrol tampilan, terserah programmer untuk memutuskan. Titik.
Daniel Kanaan
203

Menggunakan contoh yang diposting oleh Brock, saya memodifikasinya sehingga itu adalah kategori UIView, bukan UIViewController dan membuatnya rekursif sehingga setiap subview dapat (semoga) menemukan induk UIViewController.

@interface UIView (FindUIViewController)
- (UIViewController *) firstAvailableUIViewController;
- (id) traverseResponderChainForUIViewController;
@end

@implementation UIView (FindUIViewController)
- (UIViewController *) firstAvailableUIViewController {
    // convenience function for casting and to "mask" the recursive function
    return (UIViewController *)[self traverseResponderChainForUIViewController];
}

- (id) traverseResponderChainForUIViewController {
    id nextResponder = [self nextResponder];
    if ([nextResponder isKindOfClass:[UIViewController class]]) {
        return nextResponder;
    } else if ([nextResponder isKindOfClass:[UIView class]]) {
        return [nextResponder traverseResponderChainForUIViewController];
    } else {
        return nil;
    }
}
@end

Untuk menggunakan kode ini, tambahkan ke file kelas baru (saya beri nama saya "UIKitCategories") dan hapus data kelas ... salin antarmuka @ ke header, dan implementasi @ ke file .m. Kemudian dalam proyek Anda, # impor "UIKitCategories.h" dan gunakan dalam kode UIView:

// from a UIView subclass... returns nil if UIViewController not available
UIViewController * myController = [self firstAvailableUIViewController];
Phil M
sumber
47
Dan salah satu alasan Anda perlu mengizinkan UIView untuk mengetahui UIViewController adalah ketika Anda memiliki subkelas UIView khusus yang perlu mendorong tampilan modal / dialog.
Phil M
Luar biasa, saya harus mengakses ViewController saya untuk menampilkan popup kustom yang dibuat oleh subview
aryaxt
2
Bukankah ini praktik buruk bagi UIView untuk mendorong tampilan modal? Saya melakukan ini sekarang tetapi saya merasa itu bukan hal yang benar untuk dilakukan ..
Van Du Tran
6
Phil, tampilan kustom Anda harus memanggil metode delegasi yang mendengarkan controller melihat dan kemudian mendorong dari sana.
Malhal
9
Saya hanya suka berapa banyak pertanyaan SO yang mendapat "orang bijak", akademik, jawaban yang diterima hanya dengan beberapa poin dan jawaban kedua yang praktis, kotor dan bertentangan dengan aturan, dengan sepuluh kali poin :-)
hariseldon78
114

UIViewadalah subkelas dari UIResponder. UIRespondermenjabarkan metode -nextResponderdengan implementasi yang mengembalikan nil. UIViewmengganti metode ini, seperti yang didokumentasikan dalam UIResponder(untuk beberapa alasan, bukan dalam UIView) sebagai berikut: jika tampilan memiliki pengontrol tampilan, itu dikembalikan oleh -nextResponder. Jika tidak ada view controller, metode ini akan mengembalikan superview.

Tambahkan ini ke proyek Anda dan Anda siap untuk roll.

@interface UIView (APIFix)
- (UIViewController *)viewController;
@end

@implementation UIView (APIFix)

- (UIViewController *)viewController {
    if ([self.nextResponder isKindOfClass:UIViewController.class])
        return (UIViewController *)self.nextResponder;
    else
        return nil;
}
@end

Sekarang UIViewmemiliki metode yang berfungsi untuk mengembalikan pengontrol tampilan.

Bangsat
sumber
5
Ini hanya akan berfungsi jika tidak ada dalam rantai responden antara penerima UIViewdan penerima UIViewController. Jawaban Phil M menampilkan rekursi adalah jalan yang harus ditempuh.
Olivier
33

Saya akan menyarankan pendekatan yang lebih ringan untuk melintasi rantai responden lengkap tanpa harus menambahkan kategori pada UIView:

@implementation MyUIViewSubclass

- (UIViewController *)viewController {
    UIResponder *responder = self;
    while (![responder isKindOfClass:[UIViewController class]]) {
        responder = [responder nextResponder];
        if (nil == responder) {
            break;
        }
    }
    return (UIViewController *)responder;
}

@end
de.
sumber
22

Menggabungkan beberapa jawaban yang sudah diberikan, saya mengirimnya juga dengan implementasi saya:

@implementation UIView (AppNameAdditions)

- (UIViewController *)appName_viewController {
    /// Finds the view's view controller.

    // Take the view controller class object here and avoid sending the same message iteratively unnecessarily.
    Class vcc = [UIViewController class];

    // Traverse responder chain. Return first found view controller, which will be the view's view controller.
    UIResponder *responder = self;
    while ((responder = [responder nextResponder]))
        if ([responder isKindOfClass: vcc])
            return (UIViewController *)responder;

    // If the view controller isn't found, return nil.
    return nil;
}

@end

Kategori ini adalah bagian dari pustaka statis berkemampuan ARC yang saya kirimkan pada setiap aplikasi yang saya buat. Sudah diuji beberapa kali dan saya tidak menemukan masalah atau kebocoran.

PS: Anda tidak perlu menggunakan kategori seperti yang saya lakukan jika pandangan yang bersangkutan adalah subkelas dari Anda. Dalam kasus terakhir, cukup masukkan metode ini ke dalam subkelas Anda dan Anda siap melakukannya.

Constantino Tsarouhas
sumber
1
Ini jawaban terbaik. Tidak perlu rekursi, versi ini dioptimalkan dengan baik
zeroimpl
12

Meskipun ini secara teknis dapat diselesaikan seperti rekomendasi pgb , IMHO, ini adalah cacat desain. Tampilan tidak perlu mewaspadai pengontrol.

Ushox
sumber
Saya tidak yakin bagaimana viewController dapat diberitahu bahwa salah satu dari view-nya akan hilang dan perlu memanggil salah satu metode viewXXXAppear / viewXXXDisappear-nya.
mahboudz
2
Ini adalah ide di balik pola Pengamat. Orang yang Diobservasi (Pandangan dalam kasus ini) seharusnya tidak mengetahui Pengamatnya secara langsung. Pengamat hanya akan menerima panggilan balik yang mereka minati.
Ushox
12

Saya memodifikasi de answer sehingga saya bisa memberikan tampilan, tombol, label dll. Untuk mendapatkan orang tua itu UIViewController. Ini kode saya.

+(UIViewController *)viewController:(id)view {
    UIResponder *responder = view;
    while (![responder isKindOfClass:[UIViewController class]]) {
        responder = [responder nextResponder];
        if (nil == responder) {
            break;
        }
    }
    return (UIViewController *)responder;
}

Edit Versi Swift 3

class func viewController(_ view: UIView) -> UIViewController {
        var responder: UIResponder? = view
        while !(responder is UIViewController) {
            responder = responder?.next
            if nil == responder {
                break
            }
        }
        return (responder as? UIViewController)!
    }

Sunting 2: - Ekstensi Swift

extension UIView
{
    //Get Parent View Controller from any view
    func parentViewController() -> UIViewController {
        var responder: UIResponder? = self
        while !(responder is UIViewController) {
            responder = responder?.next
            if nil == responder {
                break
            }
        }
        return (responder as? UIViewController)!
    }
}
Varun Naharia
sumber
7

Jangan lupa bahwa Anda bisa mendapatkan akses ke pengendali tampilan root untuk jendela yang tampilannya adalah subview. Dari sana, jika Anda mis. Menggunakan pengontrol tampilan navigasi dan ingin mendorong tampilan baru ke dalamnya:

    [[[[self window] rootViewController] navigationController] pushViewController:newController animated:YES];

Anda perlu mengatur properti rootViewController dari jendela dengan benar terlebih dahulu. Lakukan ini saat pertama kali Anda membuat controller misalnya di delegasi aplikasi Anda:

-(void) applicationDidFinishLaunching:(UIApplication *)application {
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    RootViewController *controller = [[YourRootViewController] alloc] init];
    [window setRootViewController: controller];
    navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    [controller release];
    [window addSubview:[[self navigationController] view]];
    [window makeKeyAndVisible];
}
Gabriel
sumber
Tampak bagi saya bahwa sesuai dengan dokumen Apple karena [[self navigationController] view]merupakan tampilan "utama" (sub) dari jendela, rootViewControllerproperti jendela harus diatur ke navigationControlleryang mengontrol tampilan "utama" dengan segera.
adubr
6

Meskipun jawaban ini secara teknis benar, termasuk Ushox, saya pikir cara yang disetujui adalah dengan mengimplementasikan protokol baru atau menggunakan kembali yang sudah ada. Protokol melindungi pengamat dari yang diamati, seperti menempatkan slot surat di antaranya. Akibatnya, itulah yang dilakukan Gabriel melalui pemanggilan metode pushViewController; tampilan "tahu" bahwa itu adalah protokol yang tepat untuk dengan sopan meminta navigationController Anda untuk mendorong tampilan, karena viewController sesuai dengan protokol navigationController. Meskipun Anda dapat membuat protokol sendiri, cukup gunakan contoh Gabriel dan gunakan kembali protokol UINavigationController.

PapaSmurf
sumber
6

Saya menemukan situasi di mana saya memiliki komponen kecil yang ingin saya gunakan kembali, dan menambahkan beberapa kode dalam tampilan yang dapat digunakan kembali sendiri (itu sebenarnya tidak lebih dari sebuah tombol yang membuka a PopoverController).

Meskipun ini berfungsi dengan baik di iPad ( UIPopoverControllerhadiah itu sendiri, karenanya tidak perlu referensi ke a UIViewController), mendapatkan kode yang sama berfungsi berarti tiba-tiba merujuk Anda presentViewControllerdari Anda UIViewController. Agak tidak konsisten kan?

Seperti disebutkan sebelumnya, itu bukan pendekatan terbaik untuk memiliki logika di UIView Anda. Tetapi rasanya benar-benar tidak berguna untuk membungkus beberapa baris kode yang diperlukan dalam pengontrol terpisah.

Bagaimanapun, inilah solusi cepat, yang menambahkan properti baru ke UIView apa pun:

extension UIView {

    var viewController: UIViewController? {

        var responder: UIResponder? = self

        while responder != nil {

            if let responder = responder as? UIViewController {
                return responder
            }
            responder = responder?.nextResponder()
        }
        return nil
    }
}
Kevin R
sumber
5

Saya tidak berpikir itu "buruk" ide untuk mencari tahu siapa pengontrol tampilan untuk beberapa kasus. Apa yang bisa menjadi ide yang buruk adalah menyimpan referensi ke pengontrol ini karena dapat berubah seperti perubahan superviews. Dalam kasus saya, saya memiliki seorang pengambil yang melintasi rantai responden.

//.h

@property (nonatomic, readonly) UIViewController * viewController;

//.m

- (UIViewController *)viewController
{
    for (UIResponder * nextResponder = self.nextResponder;
         nextResponder;
         nextResponder = nextResponder.nextResponder)
    {
        if ([nextResponder isKindOfClass:[UIViewController class]])
            return (UIViewController *)nextResponder;
    }

    // Not found
    NSLog(@"%@ doesn't seem to have a viewController". self);
    return nil;
}
Rivera
sumber
4

Simpel do while yang paling sederhana untuk menemukan viewController.

-(UIViewController*)viewController
{
    UIResponder *nextResponder =  self;

    do
    {
        nextResponder = [nextResponder nextResponder];

        if ([nextResponder isKindOfClass:[UIViewController class]])
            return (UIViewController*)nextResponder;

    } while (nextResponder != nil);

    return nil;
}
Mohd Iftekhar Qurashi
sumber
4

Cepat 4

(lebih ringkas daripada jawaban lainnya)

fileprivate extension UIView {

  var firstViewController: UIViewController? {
    let firstViewController = sequence(first: self, next: { $0.next }).first(where: { $0 is UIViewController })
    return firstViewController as? UIViewController
  }

}

Kasus penggunaan saya yang saya perlu mengakses tampilan pertama UIViewController: Saya memiliki objek yang membungkus AVPlayer/ AVPlayerViewControllerdan saya ingin memberikan show(in view: UIView)metode sederhana yang akan AVPlayerViewControllerdimasukkan ke dalam view. Untuk itu, saya perlu untuk mengakses view's UIViewController.

kemari
sumber
3

Ini tidak menjawab pertanyaan secara langsung, tetapi membuat asumsi tentang maksud pertanyaan.

Jika Anda memiliki tampilan dan dalam tampilan itu Anda perlu memanggil metode pada objek lain, seperti katakanlah controller tampilan, Anda dapat menggunakan NSNotificationCenter sebagai gantinya.

Pertama buat string notifikasi Anda dalam file header

#define SLCopyStringNotification @"ShaoloCopyStringNotification"

Dalam panggilan view postNotificationName panggilan Anda:

- (IBAction) copyString:(id)sender
{
    [[NSNotificationCenter defaultCenter] postNotificationName:SLCopyStringNotification object:nil];
}

Kemudian di pengontrol tampilan, Anda menambahkan pengamat. Saya melakukan ini di viewDidLoad

- (void)viewDidLoad
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(copyString:)
                                                 name:SLCopyStringNotification
                                               object:nil];
}

Sekarang (juga di controller tampilan yang sama) mengimplementasikan metode copyString Anda: seperti yang digambarkan dalam pemilih @ di atas.

- (IBAction) copyString:(id)sender
{
    CalculatorResult* result = (CalculatorResult*)[[PercentCalculator sharedInstance].arrayTableDS objectAtIndex:([self.viewTableResults indexPathForSelectedRow].row)];
    UIPasteboard *gpBoard = [UIPasteboard generalPasteboard];
    [gpBoard setString:result.stringResult];
}

Saya tidak mengatakan ini adalah cara yang tepat untuk melakukan ini, sepertinya lebih bersih daripada menjalankan rantai responden pertama. Saya menggunakan kode ini untuk mengimplementasikan UIMenuController pada UITableView dan meneruskan kembali peristiwa tersebut ke UIViewController sehingga saya dapat melakukan sesuatu dengan data tersebut.

Shaolo
sumber
3

Ini tentu saja ide yang buruk dan desain yang salah, tapi saya yakin kita semua dapat menikmati solusi Swift dari jawaban terbaik yang diajukan oleh @Phil_M:

static func firstAvailableUIViewController(fromResponder responder: UIResponder) -> UIViewController? {
    func traverseResponderChainForUIViewController(responder: UIResponder) -> UIViewController? {
        if let nextResponder = responder.nextResponder() {
            if let nextResp = nextResponder as? UIViewController {
                return nextResp
            } else {
                return traverseResponderChainForUIViewController(nextResponder)
            }
        }
        return nil
    }

    return traverseResponderChainForUIViewController(responder)
}

Jika niat Anda adalah untuk melakukan hal-hal sederhana, seperti menampilkan dialog modal atau melacak data, itu tidak membenarkan penggunaan protokol. Saya pribadi menyimpan fungsi ini dalam objek utilitas, Anda dapat menggunakannya dari apa pun yang mengimplementasikan protokol UIResponder sebagai:

if let viewController = MyUtilityClass.firstAvailableUIViewController(self) {}

Semua kredit ke @Phil_M

Paul Slm
sumber
3

Mungkin saya terlambat ke sini. Tetapi dalam situasi ini saya tidak suka kategori (polusi). Saya suka seperti ini:

#define UIViewParentController(__view) ({ \
UIResponder *__responder = __view; \
while ([__responder isKindOfClass:[UIView class]]) \
__responder = [__responder nextResponder]; \
(UIViewController *)__responder; \
})
lee
sumber
3

Solusi yang lebih cepat

extension UIView {
    var parentViewController: UIViewController? {
        for responder in sequence(first: self, next: { $0.next }) {
            if let viewController = responder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}
Igor Palaguta
sumber
Saya suka jawaban ini. Saya tidak yakin itu lebih cepat. Swift lagi-lagi-tidak-bisa-memutuskan-mana-dari-banyak-paradigma-ia-ingin-menikah-ke-bahasa. Dalam hal ini, Anda memiliki demonstrasi yang bagus dari pendekatan yang lebih fungsional ( sequencebit). Jadi jika "cepat" berarti "lebih fungsional", maka saya kira itu lebih cepat.
Travis Griggs
2

Versi terbaru untuk swift 4: Terima kasih atas @Phil_M dan @ paul-slm

static func firstAvailableUIViewController(fromResponder responder: UIResponder) -> UIViewController? {
    func traverseResponderChainForUIViewController(responder: UIResponder) -> UIViewController? {
        if let nextResponder = responder.next {
            if let nextResp = nextResponder as? UIViewController {
                return nextResp
            } else {
                return traverseResponderChainForUIViewController(responder: nextResponder)
            }
        }
        return nil
    }

    return traverseResponderChainForUIViewController(responder: responder)
}
dicle
sumber
2

Versi Swift 4

extension UIView {
var parentViewController: UIViewController? {
    var parentResponder: UIResponder? = self
    while parentResponder != nil {
        parentResponder = parentResponder!.next
        if let viewController = parentResponder as? UIViewController {
            return viewController
        }
    }
    return nil
}

Contoh penggunaan

 if let parent = self.view.parentViewController{

 }
levin varghese
sumber
2

Dua solusi pada Swift 5.2 :

  • Lebih pada sisi fungsional
  • Tidak perlu returnkata kunci sekarang 🤓

Solusi 1:

extension UIView {
    var parentViewController: UIViewController? {
        sequence(first: self) { $0.next }
            .first(where: { $0 is UIViewController })
            .flatMap { $0 as? UIViewController }
    }
}

Solusi 2:

extension UIView {
    var parentViewController: UIViewController? {
        sequence(first: self) { $0.next }
            .compactMap{ $0 as? UIViewController }
            .first
    }
}
  • Solusi ini membutuhkan pengulangan melalui setiap responden terlebih dahulu, jadi mungkin bukan yang paling berkinerja.
jason z
sumber
1

Untuk jawaban Phil:

Sejalan: id nextResponder = [self nextResponder]; jika diri (UIView) bukan subview dari pandangan ViewController, jika Anda tahu hierarki diri (UIView) Anda dapat menggunakan juga: id nextResponder = [[self superview] nextResponder];...

melengkung
sumber
0

Solusi saya mungkin akan dianggap sebagai jenis palsu tetapi saya memiliki situasi yang sama dengan mayoneez (saya ingin mengalihkan pandangan sebagai tanggapan terhadap isyarat dalam EAGLView), dan saya mendapatkan pengontrol tampilan EAGL dengan cara ini:

EAGLViewController *vc = ((EAGLAppDelegate*)[[UIApplication sharedApplication] delegate]).viewController;
gulchrider
sumber
2
Silakan menulis ulang kode Anda sebagai berikut: EAGLViewController *vc = [(EAGLAppDelegate *)[UIApplication sharedApplication].delegate viewController];.
Jonathan Sterling
1
Masalahnya bukan dengan sintaks dot, tetapi dengan tipe. Di Objective C untuk mendeklarasikan objek yang Anda tulis ClassName *object- dengan tanda bintang.
adubr
Ups ... itu sebenarnya yang saya miliki, tetapi widget HTML StackOverflow sepertinya menganggap tanda bintang berarti huruf miring ... Saya mengubahnya menjadi blok kode, sekarang ditampilkan dengan benar. Terima kasih!
gulchrider
0

Saya pikir ada kasus ketika yang diamati perlu memberi tahu pengamat.

Saya melihat masalah yang sama di mana UIView dalam UIViewController merespons situasi dan pertama-tama perlu memberi tahu pengontrol tampilan induknya untuk menyembunyikan tombol kembali dan kemudian setelah selesai memberi tahu pengontrol tampilan induk bahwa ia perlu keluar dari tumpukan.

Saya telah mencoba ini dengan delegasi yang tidak berhasil.

Saya tidak mengerti mengapa ini ide yang buruk?

pengguna7865437
sumber
0

Cara mudah lain adalah memiliki kelas tampilan Anda sendiri dan menambahkan properti controller tampilan di kelas tampilan. Biasanya pengontrol tampilan membuat tampilan dan di sanalah pengontrol dapat mengatur sendiri ke properti. Pada dasarnya itu bukan mencari-cari (dengan sedikit peretasan) untuk controller, memiliki controller untuk mengatur sendiri ke tampilan - ini sederhana tetapi masuk akal karena itu adalah controller yang "mengontrol" tampilan.

mendongkrak
sumber
0

Jika Anda tidak akan mengunggah ini ke App Store, Anda juga dapat menggunakan metode pribadi UIView.

@interface UIView(Private)
- (UIViewController *)_viewControllerForAncestor;
@end

// Later in the code
UIViewController *vc = [myView _viewControllerForAncestor];

sumber
0
var parentViewController: UIViewController? {
    let s = sequence(first: self) { $0.next }
    return s.compactMap { $0 as? UIViewController }.first
}
klaudas
sumber
Meskipun kode ini dapat menjawab pertanyaan, jawaban yang baik juga harus menjelaskan apa yang dilakukan kode dan bagaimana cara memecahkan masalah.
BDL
0

Untuk mendapatkan pengontrol dari tampilan yang diberikan, seseorang dapat menggunakan rantai UIFirstResponder.

customView.target(forAction: Selector("viewDidLoad"), withSender: nil)
Adobels
sumber
-1

Jika rootViewController Anda adalah UINavigationViewController, yang dibuat di kelas AppDelegate, maka

    + (UIViewController *) getNearestViewController:(Class) c {
NSArray *arrVc = [[[[UIApplication sharedApplication] keyWindow] rootViewController] childViewControllers];

for (UIViewController *v in arrVc)
{
    if ([v isKindOfClass:c])
    {
        return v;
    }
}

return nil;}

Di mana c diperlukan kelas pengontrol tampilan.

PEMAKAIAN:

     RequiredViewController* rvc = [Utilities getNearestViewController:[RequiredViewController class]];
Ansari Awais
sumber
-5

Tidak ada jalan.

Apa yang saya lakukan adalah meneruskan pointer UIViewController ke UIView (atau warisan yang sesuai). Maaf saya tidak bisa membantu dengan pendekatan IB untuk masalah karena saya tidak percaya pada IB.

Untuk menjawab komentator pertama: kadang-kadang Anda perlu tahu siapa yang memanggil Anda karena itu menentukan apa yang dapat Anda lakukan. Misalnya dengan database Anda mungkin hanya memiliki akses baca atau baca / tulis ...

John Smith
sumber
10
Apa artinya itu - "Saya tidak percaya pada IB"? Saya sudah meluncurkannya, itu pasti ada.
marcc
5
Anda membutuhkan pemahaman yang lebih baik tentang kesenangan dan abstraksi, terutama yang berkaitan dengan bahasa Inggris. Itu berarti saya tidak suka itu.
John Smith
4
Saya tidak suka alpukat. Tapi saya yakin saya bisa membantu seseorang membuat guacamole. Itu bisa dilakukan di IB, jadi jelas jawaban Anda "tidak ada cara" salah. Apakah Anda suka IB atau tidak tidak relevan.
Kucing Feloneous