SwiftUI - दृश्य में नेविगेशन हार्डकोडेड से कैसे बचें?


33

मैं एक बड़े, उत्पादन के लिए तैयार स्विफ्टयूआई ऐप के लिए आर्किटेक्चर करने की कोशिश करता हूं। मैं हर समय उसी समस्या में चल रहा हूं जो स्विफ्टयूआई में एक प्रमुख डिजाइन दोष की ओर इशारा करती है।

फिर भी कोई भी मुझे पूरी तरह से काम करने, उत्पादन के लिए तैयार जवाब नहीं दे सका।

पुन: प्रयोज्य दृश्य कैसे करें SwiftUIजिसमें नेविगेशन शामिल है?

जैसा कि SwiftUI NavigationLinkदृढ़ता से यह देखने के लिए बाध्य है कि यह केवल इस तरह से संभव नहीं है कि यह बड़े एप्स में भी हो। NavigationLinkउन छोटे नमूना ऐप्स में काम करता है, हाँ - लेकिन जैसे ही आप एक ऐप में कई दृश्यों का पुन: उपयोग करना चाहते हैं। और शायद मॉड्यूल सीमाओं पर भी पुन: उपयोग। (जैसे: आईओएस, वॉचओएस, आदि में पुन: उपयोग करना ...)

डिज़ाइन की समस्या: नेवीगेशनलिंक को व्यू में हार्डकोड किया गया है।

NavigationLink(destination: MyCustomView(item: item))

लेकिन अगर इस दृश्य को NavigationLinkपुन: प्रयोज्य किया जाना चाहिए तो मैं गंतव्य को हार्डकोड नहीं कर सकता । एक तंत्र होना चाहिए जो गंतव्य प्रदान करता है। मैंने इसे यहाँ पूछा और काफी अच्छा जवाब मिला, लेकिन अभी भी पूरा जवाब नहीं मिला:

SwiftUI MVVM समन्वयक / राउटर / नेविगेशनलिंक

विचार गंतव्य लिंक को पुन: प्रयोज्य दृश्य में इंजेक्ट करने का था। आम तौर पर यह विचार काम करता है लेकिन दुर्भाग्य से यह वास्तविक उत्पादन एप्स के लिए नहीं है। जैसे ही मेरे पास कई पुन: प्रयोज्य स्क्रीन हैं मैं तार्किक समस्या में चला जाता हूं कि एक पुन: प्रयोज्य दृश्य ( ViewA) को पूर्व-निर्धारित दृश्य-गंतव्य ( ViewB) की आवश्यकता होती है। लेकिन क्या होगा अगर ViewBएक पूर्वनिर्मित दृश्य-गंतव्य की भी आवश्यकता है ViewC? मैं बनाने के लिए की आवश्यकता होगी ViewBइस तरह से कि में पहले से ही ViewCपहले से ही में इंजेक्ट किया जाता है ViewBइससे पहले कि मैं इंजेक्षन ViewBमें ViewA। और इसी तरह .... लेकिन जैसा कि उस समय जो डेटा पास करना है वह उपलब्ध नहीं है, पूरा निर्माण विफल है।

मेरे पास एक और विचार था कि Environmentगंतव्य के लिए इंजेक्शन लगाने के लिए निर्भरता इंजेक्शन तंत्र का उपयोग किया जाए NavigationLink। लेकिन मुझे लगता है कि इसे कम या ज्यादा हैक के रूप में माना जाना चाहिए न कि बड़े ऐप्स के लिए स्केलेबल समाधान। हम पर्यावरण को मूल रूप से हर चीज के लिए इस्तेमाल करेंगे। लेकिन क्योंकि पर्यावरण का उपयोग केवल व्यूज़ के अंदर ही किया जा सकता है (अलग कोऑर्डिनेटरों या ViewModels में नहीं) यह फिर से मेरी राय में अजीब निर्माण करेगा।

व्यापार तर्क की तरह (उदाहरण के लिए मॉडल कोड) और दृश्य को भी अलग करना होगा नेविगेशन और दृश्य को अलग करना होगा (जैसे समन्वयक पैटर्न) UIKitयह संभव है क्योंकि हम देखने के लिए UIViewControllerऔर UINavigationControllerपीछे पहुंचते हैं। UIKit'sएमवीसी के पास पहले से ही यह समस्या थी कि वह इतनी अवधारणाओं को मिटा देता था कि वह "मॉडल-व्यू-कंट्रोलर" के बजाय मजेदार नाम "मैसिव-व्यू-कंट्रोलर" बन जाता था। अब इसी तरह की समस्या जारी है, SwiftUIलेकिन मेरी राय में इससे भी बदतर। नेविगेशन और दृश्य दृढ़ता से युग्मित होते हैं और इन्हें डिकोड नहीं किया जा सकता है। इसलिए यदि उनके पास नेविगेशन है तो पुन: प्रयोज्य दृश्य करना संभव नहीं है। इसे हल करना संभव था, UIKitलेकिन अब मैं इसमें एक समाधान नहीं देख सकताSwiftUI। दुर्भाग्य से Apple ने हमें इस तरह की वास्तु संबंधी समस्याओं को हल करने के लिए स्पष्टीकरण नहीं दिया। हमें सिर्फ कुछ छोटे सैंपल एप्स मिले।

मैं गलत साबित होना पसंद करूंगा। कृपया मुझे एक साफ ऐप डिज़ाइन पैटर्न दिखाएं जो बड़े उत्पादन के लिए तैयार ऐप्स के लिए इसे हल करता है।

अग्रिम में धन्यवाद।


अद्यतन: यह इनाम कुछ ही मिनटों में समाप्त हो जाएगा और दुर्भाग्य से अभी भी कोई भी काम करने का उदाहरण देने में सक्षम नहीं था। लेकिन मैं इस समस्या को हल करने के लिए एक नया इनाम शुरू करूंगा अगर मुझे कोई अन्य समाधान नहीं मिल रहा है और इसे यहां लिंक कर सकता हूं। उनके महान योगदान के लिए सभी को धन्यवाद!


1
माना! मैंने कई महीनों पहले "फीडबैक असिस्टेंट" में इसके लिए एक अनुरोध किया था, अभी तक कोई प्रतिक्रिया नहीं: gist.github.com/Sajjon/b7edb4cc11bcb6462f4e28dc170be245
सज्जन

@ साजन धन्यवाद! मैं Apple को भी लिखने का इरादा रखता हूं, चलो देखते हैं कि क्या मुझे प्रतिक्रिया मिलती है।
डार्कियो

1
इस बारे में Apple को एक पत्र लिखा। आइए देखें कि क्या हमें रिप्सन मिलता है।
Darko

1
अच्छा! यह WWDC के दौरान अब तक का सबसे अच्छा प्रेजेंट होगा!
सज्जनों

जवाबों:


10

बंद करने की जरूरत है!

struct ItemsView<Destination: View>: View {
    let items: [Item]
    let buildDestination: (Item) -> Destination

    var body: some View {
        NavigationView {
            List(items) { item in
                NavigationLink(destination: self.buildDestination(item)) {
                    Text(item.id.uuidString)
                }
            }
        }
    }
}

मैंने स्विफ्टयू में प्रतिनिधि पैटर्न को बंद करने के साथ बदलने के बारे में एक पोस्ट लिखा। https://swiftwithmajid.com/2019/11/06/the-power-of-closures-in-swiftui/


बंद एक अच्छा विचार है, धन्यवाद! लेकिन यह एक गहरी दृष्टि पदानुक्रम में कैसा लगेगा? कल्पना कीजिए कि मेरे पास एक नेवीगेशन व्यू है जो 10 स्तरों को गहराई से बताता है, विस्तार से, विस्तार से, विस्तार से, आदि ...
Darko

मैं आपको केवल तीन स्तरों के कुछ सरल उदाहरण कोड को गहरा दिखाने के लिए आमंत्रित करना चाहूंगा।
डार्को

7

मेरा विचार बहुत ज्यादा Coordinatorऔर Delegateपैटर्न का एक संयोजन होगा । सबसे पहले, एक Coordinatorवर्ग बनाएँ :


struct Coordinator {
    let window: UIWindow

      func start() {
        var view = ContentView()
        window.rootViewController = UIHostingController(rootView: view)
        window.makeKeyAndVisible()
    }
}

SceneDelegateउपयोग करने के लिए अनुकूल करें Coordinator:

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            let coordinator = Coordinator(window: window)
            coordinator.start()
        }
    }

अंदर ContentView, हमारे पास यह है:


struct ContentView: View {
    var delegate: ContentViewDelegate?

    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: delegate!.didSelect(Item())) {
                    Text("Destination1")
                }
            }
        }
    }
}

हम ContenViewDelegateप्रोटोकॉल को इस तरह परिभाषित कर सकते हैं :

protocol ContentViewDelegate {
    func didSelect(_ item: Item) -> AnyView
}

जहाँ Itemबस एक संरचना है जो पहचानने योग्य है, कुछ और भी हो सकती है (जैसे किसी तत्व की आईडी जैसे TableViewUIKit में)

अगला कदम इस प्रोटोकॉल को अपनाना है Coordinatorऔर उस दृश्य को पास करें जिसे आप प्रस्तुत करना चाहते हैं:

extension Coordinator: ContentViewDelegate {
    func didSelect(_ item: Item) -> AnyView {
        AnyView(Text("Returned Destination1"))
    }
}

यह अब तक मेरे ऐप्स में अच्छी तरह से काम कर रहा है। मुझे उम्मीद है यह मदद करेगा।


नमूना कोड के लिए धन्यवाद। मैं तुम्हें Text("Returned Destination1")कुछ करने के लिए बदलने के लिए आमंत्रित करना चाहूंगा MyCustomView(item: ItemType, destinationView: View)। ताकि MyCustomViewकुछ डेटा और गंतव्य को भी इंजेक्ट किया जा सके। आप इसे कैसे हल करेंगे?
Darko

आप घोंसले के शिकार की समस्या में भाग लेते हैं जिसका वर्णन मैं अपनी पोस्ट में करता हूं। अगर मैं गलत हूं कृपया मुझे सही। मूल रूप से यह दृष्टिकोण काम करता है यदि आपके पास एक पुन: प्रयोज्य दृश्य है और पुन: प्रयोज्य दृश्य में नेविगेशनलिंक के साथ एक और पुन: प्रयोज्य दृश्य नहीं है। जो काफी सरल उपयोग-मामला है, लेकिन बड़े ऐप्स के पैमाने पर नहीं है। (जहां लगभग हर दृश्य पुन: प्रयोज्य है)
डार्को

यह अत्यधिक इस बात पर निर्भर करता है कि आप अपने ऐप पर निर्भरता और उनके प्रवाह का प्रबंधन कैसे करते हैं। यदि आपको एक ही स्थान पर निर्भरता हो रही है, जैसा कि आपको IMO (रचना रूट के रूप में भी जाना जाता है), आपको इस समस्या में नहीं चलना चाहिए।
निकोला मतिजेविक

एक प्रोटोकॉल के रूप में एक दृश्य के लिए मेरे सभी निर्भरता को परिभाषित करने के लिए मेरे लिए क्या काम करता है। रचना जड़ में प्रोटोकॉल के अनुरूप जोड़ें। समन्वयक को निर्भरता पास करें। समन्वयक से उन्हें इंजेक्ट करें। सिद्धांत रूप में, आपको तीन से अधिक मापदंडों के साथ समाप्त होना चाहिए, अगर ठीक से कभी नहीं किया जाता है dependenciesऔर destination
निकोला मतिजेविक

1
मैं एक ठोस उदाहरण देखना पसंद करूंगा। जैसा कि मैंने पहले ही उल्लेख किया है, चलो शुरू करते हैं Text("Returned Destination1")। क्या होगा अगर यह एक होने की जरूरत है MyCustomView(item: ItemType, destinationView: View)। आप वहां क्या इंजेक्शन लगाने जा रहे हैं? मुझे लगता है कि निर्भरता इंजेक्शन, ढीले युग्मन के माध्यम से प्रोटोकॉल, और समन्वयकों के साथ साझा निर्भरताएं। यह सब समस्या नहीं है - यह आवश्यक घोंसले के शिकार है। धन्यवाद।
डार्कहो

2

मेरे साथ कुछ ऐसा होता है जब आप कहते हैं:

लेकिन क्या होगा अगर ViewB को भी एक पूर्व-निर्धारित दृश्य-गंतव्य ViewC की आवश्यकता है? मुझे ViewB को पहले से ही इस तरह बनाना होगा कि ViewC को ViewA में इंजेक्ट करने से पहले ViewC को पहले से ViewB में इंजेक्ट किया जा सके। और इसी तरह .... लेकिन जैसा कि उस समय जो डेटा पास करना है वह उपलब्ध नहीं है, पूरा निर्माण विफल है।

यह बिल्कुल सच नहीं है। विचारों की आपूर्ति करने के बजाय, आप अपने पुन: प्रयोज्य घटकों को डिजाइन कर सकते हैं ताकि आप आपूर्ति को बंद कर सकें जो मांग पर विचारों की आपूर्ति करता है।

इस तरह, जो मांग पर ViewB का उत्पादन बंद करता है, वह एक बंद के साथ आपूर्ति कर सकता है जो मांग पर ViewC का उत्पादन करता है, लेकिन विचारों का वास्तविक निर्माण ऐसे समय में हो सकता है जब आपके लिए आवश्यक प्रासंगिक जानकारी उपलब्ध हो।


लेकिन इस तरह के the क्लोजर-ट्री ’का निर्माण वास्तविक विचारों से अलग कैसे है? प्रदान करने वाली समस्या हल हो जाएगी, लेकिन आवश्यक घोंसले के शिकार नहीं। मैं एक क्लोजर बनाता हूं जो एक दृश्य बनाता है - ठीक है। लेकिन उस क्लोजर में मुझे पहले से ही अगले क्लोजर के निर्माण की आवश्यकता होगी। और आखिरी में अगला। आदि ... लेकिन शायद मैं आपको गलत समझ रहा हूं। कुछ कोड उदाहरण से मदद मिलेगी। धन्यवाद।
Darko

2

यहां असीम रूप से ड्रिलिंग करने और अगले विवरण के लिए अपने डेटा को प्रोग्रामेटिक रूप से बदलने का एक मजेदार उदाहरण है

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var navigationManager: NavigationManager

    var body: some View {
        NavigationView {
            DynamicView(viewModel: ViewModel(message: "Get Information", type: .information))
        }
    }
}

struct DynamicView: View {
    @EnvironmentObject var navigationManager: NavigationManager

    let viewModel: ViewModel

    var body: some View {
        VStack {
            if viewModel.type == .information {
                InformationView(viewModel: viewModel)
            }
            if viewModel.type == .person {
                PersonView(viewModel: viewModel)
            }
            if viewModel.type == .productDisplay {
                ProductView(viewModel: viewModel)
            }
            if viewModel.type == .chart {
                ChartView(viewModel: viewModel)
            }
            // If you want the DynamicView to be able to be other views, add to the type enum and then add a new if statement!
            // Your Dynamic view can become "any view" based on the viewModel
            // If you want to be able to navigate to a new chart UI component, make the chart view
        }
    }
}

struct InformationView: View {
    @EnvironmentObject var navigationManager: NavigationManager
    let viewModel: ViewModel

    // Customize your  view based on more properties you add to the viewModel
    var body: some View {
        VStack {
            VStack {
                Text(viewModel.message)
                .foregroundColor(.white)
            }
            .frame(width: 300, height: 300)
            .background(Color.blue)


            NavigationLink(destination: navigationManager.destination(forModel: viewModel)) {
                Text("Navigate")
            }
        }
    }
}

struct PersonView: View {
    @EnvironmentObject var navigationManager: NavigationManager
    let viewModel: ViewModel

    // Customize your  view based on more properties you add to the viewModel
    var body: some View {
        VStack {
            VStack {
                Text(viewModel.message)
                .foregroundColor(.white)
            }
            .frame(width: 300, height: 300)
            .background(Color.red)
            NavigationLink(destination: navigationManager.destination(forModel: viewModel)) {
                Text("Navigate")
            }
        }
    }
}

struct ProductView: View {
    @EnvironmentObject var navigationManager: NavigationManager
    let viewModel: ViewModel

    // Customize your  view based on more properties you add to the viewModel
    var body: some View {
        VStack {
            VStack {
                Text(viewModel.message)
                    .foregroundColor(.white)
            }
            .frame(width: 300, height: 300)
            .background(Color.green)
            NavigationLink(destination: navigationManager.destination(forModel: viewModel)) {
                Text("Navigate")
            }
        }
    }
}

struct ChartView: View {
    @EnvironmentObject var navigationManager: NavigationManager
    let viewModel: ViewModel

    var body: some View {
        VStack {
            VStack {
                Text(viewModel.message)
                    .foregroundColor(.white)
            }
            .frame(width: 300, height: 300)
            .background(Color.green)
            NavigationLink(destination: navigationManager.destination(forModel: viewModel)) {
                Text("Navigate")
            }
        }
    }
}

struct ViewModel {
    let message: String
    let type: DetailScreenType
}

enum DetailScreenType: String {
    case information
    case productDisplay
    case person
    case chart
}

class NavigationManager: ObservableObject {
    func destination(forModel viewModel: ViewModel) -> DynamicView {
        DynamicView(viewModel: generateViewModel(context: viewModel))
    }

    // This is where you generate your next viewModel dynamically.
    // replace the switch statement logic inside with whatever logic you need.
    // DYNAMICALLY MAKE THE VIEWMODEL AND YOU DYNAMICALLY MAKE THE VIEW
    // You could even lead to a view with no navigation link in it, so that would be a dead end, if you wanted it.
    // In my case my "context" is the previous viewMode, by you could make it something else.
    func generateViewModel(context: ViewModel) -> ViewModel {
        switch context.type {
        case .information:
            return ViewModel(message: "Serial Number 123", type: .productDisplay)
        case .productDisplay:
            return ViewModel(message: "Susan", type: .person)
        case .person:
            return ViewModel(message: "Get Information", type: .chart)
        case .chart:
            return ViewModel(message: "Chart goes here. If you don't want the navigation link on this page, you can remove it! Or do whatever you want! It's all dynamic. The point is, the DynamicView can be as dynamic as your model makes it.", type: .information)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
        .environmentObject(NavigationManager())
    }
}

-> कुछ व्यू आपको केवल एक प्रकार के व्यू को वापस करने के लिए मजबूर करते हैं।
Darko

एन्वायर्नमेंट ऑबजेक्ट के साथ निर्भरता इंजेक्शन समस्या के एक हिस्से को हल करता है। लेकिन: यूआई फ्रेमवर्क में कुछ महत्वपूर्ण और महत्वपूर्ण इतना जटिल होना चाहिए ...?
Darko

मेरा मतलब है - अगर निर्भरता इंजेक्शन इसके लिए एकमात्र समाधान है तो मैं अनिच्छा से इसे स्वीकार करूंगा। लेकिन यह वास्तव में गंध होगा ...
Darko

1
मैं यह नहीं देखता कि आप अपने ढांचे के उदाहरण के साथ इसका उपयोग क्यों नहीं कर सकते। यदि आप एक ऐसे फ्रेमवर्क के बारे में बात कर रहे हैं जो एक अज्ञात दृश्य की कल्पना करता है तो मैं कल्पना करूंगा कि यह कुछ दृश्य वापस कर सकता है। मुझे भी आश्चर्य नहीं होगा अगर किसी नेविगेशनलिंक के अंदर कोई भी दृश्य वास्तव में ऐसा नहीं है जो कि बच्चे के वास्तविक लेआउट से पूरी तरह से अलग होने के बाद से प्रीफ हिट का बड़ा हिस्सा है। मैं हालांकि कोई विशेषज्ञ नहीं हूं, लेकिन इसका परीक्षण करना होगा। नमूना कोड के लिए हर किसी से पूछने के बजाय जहां वे आपकी आवश्यकताओं को पूरी तरह से समझ नहीं सकते हैं, आप यूआईकिट नमूना क्यों नहीं लिखते हैं और अनुवाद के लिए पूछते हैं?
जसग्रेगोरी

1
यह डिज़ाइन मूल रूप से काम करता है (UIKit) ऐप है। मॉडल उत्पन्न होते हैं जो अन्य मॉडल से लिंक करते हैं। एक केंद्रीय प्रणाली निर्धारित करती है कि उस मॉडल के लिए क्या vc लोड किया जाना चाहिए और फिर पैरेंट vc इसे स्टैक पर धकेलता है।
जसोन्ग्रेगोरी

2

मैं SwiftUI में एक MVP + समन्वयक दृष्टिकोण बनाने पर एक ब्लॉग पोस्ट श्रृंखला लिख ​​रहा हूं जो उपयोगी हो सकती है:

https://lascorbe.com/posts/2020-04-27-MVPCoordinators-SwiftUI-part1/

पूरा प्रोजेक्ट जीथब पर उपलब्ध है: https://github.com/Lascorbe/SwiftUI-MVP-Coordatorator

मैं इसे करने की कोशिश कर रहा हूं जैसे कि यह स्केलेबिलिटी के मामले में एक बड़ा ऐप होगा। मुझे लगता है कि मैंने नेविगेशन समस्या को सुलझा लिया है, लेकिन मुझे अभी भी यह देखना है कि गहरी लिंकिंग कैसे करनी है, जो कि मैं वर्तमान में काम कर रहा हूं। मुझे उम्मीद है यह मदद करेगा।


वाह, यह बहुत अच्छा है, धन्यवाद! आपने स्विफ्टयूआई में समन्वयक को लागू करने पर काफी अच्छा काम किया। NavigationViewरूट व्यू बनाने का आइडिया शानदार है। यह अब तक का सबसे उन्नत स्विफ्टयूआई समन्वयक कार्यान्वयन है जिसे मैंने अब तक देखा है।
डार्को

मैं आपको सिर्फ इसलिए पुरस्कार देना चाहूंगा क्योंकि आपका समन्वयक समाधान वास्तव में बहुत अच्छा है। मेरे पास एकमात्र समस्या है - यह वास्तव में मेरे द्वारा वर्णित समस्या को संबोधित नहीं करता है। यह अपघटित करता है NavigationLinkलेकिन यह एक नए युग्मित निर्भरता का परिचय देकर ऐसा करता है। MasterViewअपने उदाहरण में पर निर्भर नहीं है NavigationButtonMasterViewएक स्विफ्ट पैकेज में रखने की कल्पना करें - यह अब संकलित नहीं करेगा क्योंकि प्रकार NavigationButtonअज्ञात है। इसके अलावा, मैं यह नहीं देखता कि कैसे नेस्टेड पुन: प्रयोज्य की समस्या Viewsइसके द्वारा हल हो जाएगी?
डार्को

मुझे गलत होने में खुशी होगी, और अगर मैं हूं तो कृपया मुझे समझाएं। भले ही इनाम कुछ ही मिनटों में निकल जाए, लेकिन मुझे उम्मीद है कि मैं आपको किसी तरह अंक प्रदान कर सकता हूं। (पहले कभी नहीं किया था, लेकिन मुझे लगता है कि मैं सिर्फ एक नए के साथ एक अनुवर्ती सवाल बना सकता हूँ?)
Darko

1

यह एक पूरी तरह से शीर्ष-ऑफ-द-माई-हेड उत्तर है, इसलिए संभवत: बकवास हो जाएगा, लेकिन मुझे हाइब्रिड दृष्टिकोण का उपयोग करने के लिए लुभाया जाएगा।

एक एकल समन्वयक वस्तु से गुजरने के लिए पर्यावरण का उपयोग करें - इसे नेविगेशनकोऑर्डिनेटर कहते हैं।

अपने पुन: प्रयोज्य विचारों को किसी प्रकार के पहचानकर्ता को दें जो गतिशील रूप से सेट हो। यह पहचानकर्ता क्लाइंट एप्लिकेशन के वास्तविक उपयोग के मामले और नेविगेशन पदानुक्रम के अनुरूप सिमेंटिक जानकारी देता है।

गंतव्य दृश्य के लिए नेवीगेशन कॉर्डिनेटर को फिर से प्रयोग करने योग्य विचार क्वेरी करें, उनके पहचानकर्ता और उस दृश्य प्रकार के पहचानकर्ता को पास करना जो वे नेविगेट कर रहे हैं।

यह नेविगेशनकोऑर्डिनेटर को एकल इंजेक्शन बिंदु के रूप में छोड़ता है, और यह एक गैर-दृश्य ऑब्जेक्ट है जिसे दृश्य पदानुक्रम के बाहर एक्सेस किया जा सकता है।

सेटअप के दौरान आप इसे देखने के लिए सही दृश्य वर्गों को पंजीकृत कर सकते हैं, किसी प्रकार के पहचानकर्ताओं के साथ मेल खाने के लिए जो इसे रनटाइम पर पारित किया गया है। गंतव्य पहचानकर्ता के साथ मिलान के रूप में सरल कुछ मामलों में काम कर सकता है। या मेजबान और गंतव्य पहचानकर्ताओं की एक जोड़ी के खिलाफ मिलान।

अधिक जटिल मामलों में आप एक कस्टम नियंत्रक लिख सकते हैं जो अन्य एप्लिकेशन-विशिष्ट जानकारी को ध्यान में रखता है।

चूंकि यह पर्यावरण के माध्यम से इंजेक्ट किया जाता है, कोई भी दृश्य किसी भी बिंदु पर डिफ़ॉल्ट नेवीगेशन कोऑर्डिनेटर को ओवरराइड कर सकता है और इसके उप-साक्षात्कार के लिए एक अलग आपूर्ति कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.