সুইফটআইআই - কীভাবে পরিবেশনোবজেক্টটি ভিউ মডেলটিতে পাস করবেন?


16

আমি এমন একটি পরিবেশসংস্থান তৈরি করতে চাইছি যা ভিউ মডেল (কেবল দেখতে নয়) দ্বারা অ্যাক্সেস করা যায়।

এনভায়রনমেন্ট অবজেক্ট অ্যাপ্লিকেশন সেশন ডেটা, যেমন লগইনড, অ্যাক্সেস টোকেন ইত্যাদির উপর নজর রাখে, এই এনভায়রনঅবজেক্টস থেকে কোনও এপিআই কল করার অনুমতি দেওয়ার জন্য এই তথ্যটি ভিউ মডেলগুলিতে (বা পরিষেবা শ্রেণীর যেখানে প্রয়োজন হবে) পাঠানো হবে।

আমি ভিউ থেকে ভিউ মডেল ক্লাসের ইনিশিয়ালারের কাছে সেশন অবজেক্টে যাওয়ার চেষ্টা করেছি তবে একটি ত্রুটি পেয়েছি।

কীভাবে আমি সুইফটইউআই ব্যবহার করে ভিউ মডেলটিতে এনভায়রনমেন্ট অবজেক্টটি অ্যাক্সেস / পাস করতে পারি?

পরীক্ষার প্রকল্পের লিঙ্কটি দেখুন: https://gofile.io/?c=vgHLVx


ভিও মডেলকে ইও হিসাবে পাস করবেন না কেন?
E.Coms

শীর্ষে দেখে মনে হচ্ছে, অনেকগুলি ভিউ মডেল থাকবে, আমি যে আপলোডটি সংযুক্ত করেছি তা হ'ল একটি সরল উদাহরণ
মাইকেল

2
আমি নিশ্চিত নই কেন এই প্রশ্নটিকে নিম্নমানের করা হয়েছিল, আমিও একই ভাবছি। আমি যা করেছি তার সাথে জবাব দেব, আশা করি অন্য কেউ আরও ভাল কিছু নিয়ে আসতে পারে।
মাইকেল ওজারিয়ানস্কি

2
@ ই.কোমস আমি প্রত্যাশা করেছি যে এনভায়রনমেন্ট অবজেক্টটি সাধারণত একটি অবজেক্ট হবে। আমি একাধিক কাজ জানি, এগুলি বিশ্বব্যাপী অ্যাক্সেসযোগ্য করে তুলতে কোনও কোড গন্ধ বলে মনে হয়।
মাইকেল ওজারিয়ানস্কি

@ মিশেল আপনি কি এর সমাধান খুঁজে পেয়েছেন?
ব্রেট

উত্তর:


3

আমি ভিউমোডেল না রাখাই পছন্দ করি। (নতুন প্যাটার্নের জন্য সম্ভবত সময়?)

আমি এবং আমার RootViewকিছু শিশু দৃষ্টিভঙ্গি দিয়ে আমার প্রকল্পটি সেটআপ করেছি । আমি পরিবেশের বিষয় হিসাবে RootViewএকটি Appঅবজেক্টের সাথে আমার সেটআপ করি । ভিডমোডেল মডেলগুলিতে অ্যাক্সেসের পরিবর্তে আমার সমস্ত দর্শন অ্যাপগুলিতে ক্লাস অ্যাক্সেস করে। ভিউমোডেল বিন্যাসটি নির্ধারণের পরিবর্তে, ভিউয়ের স্তরক্রম বিন্যাসটি নির্ধারণ করে। কয়েকটি অ্যাপ্লিকেশনের জন্য অনুশীলনে এটি করা থেকে, আমি দেখতে পেয়েছি যে আমার মতামতগুলি ছোট এবং নির্দিষ্ট হয়ে রয়েছে। ওভার সরলীকরণ হিসাবে:

class App {
   @Published var user = User()

   let networkManager: NetworkManagerProtocol
   lazy var userService = UserService(networkManager: networkManager)

   init(networkManager: NetworkManagerProtocol) {
      self.networkManager = networkManager
   }

   convenience init() {
      self.init(networkManager: NetworkManager())
   }
}
struct RootView {
    @EnvironmentObject var app: App

    var body: some View {
        if !app.user.isLoggedIn {
            LoginView()
        } else {
            HomeView()
        }
    }
}
struct HomeView: View {
    @EnvironmentObject var app: App

    var body: some View {
       VStack {
          Text("User name: \(app.user.name)")
          Button(action: { app.userService.logout() }) {
             Text("Logout")
          }
       }
    }
}

আমার পূর্বরূপগুলিতে, আমি একটি সূচনা করি MockAppযা একটি সাবক্লাস App। মক অ্যাপ মকড অবজেক্টের সাহায্যে মনোনীত ইনিশিয়ালাইজারগুলি সূচনা করে। এখানে ইউজার সার্ভিসকে উপহাস করার দরকার নেই, তবে ডেটাসোর্স (যেমন নেটওয়ার্কম্যানেজারপ্রোটোকল) করে।

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            HomeView()
                .environmentObject(MockApp() as App) // <- This is needed for EnvironmentObject to treat the MockApp as an App Type
        }
    }

}

কেবল একটি নোট: আমি মনে করি এটির মতো চেইন এড়ানো ভাল app.userService.logout()userServiceকেবলমাত্র অ্যাপ্লিকেশন শ্রেণীর অভ্যন্তর থেকে ব্যক্তিগত এবং অ্যাক্সেস করা উচিত। উপরের কোডটি দেখতে এইরকম হওয়া উচিত: Button(action: { app.logout() })এবং লগআউট ফাংশনটি তখন সরাসরি কল করবে userService.logout()
প্যাভেলো 2222

@ pawello2222 এটি আরও ভাল নয়, এটি কোনও উপকার ছাড়াই কেবল মুখের প্যাটার্ন, তবে আপনি নিজের ইচ্ছামত কাজটি করতে পারেন।
মাইকেল ওজেরিয়ানস্কি

3

আপনার উচিত হবে না। এটি একটি সাধারণ ভুল ধারণা যে সুইফটুআই এমভিভিএমের সাথে সবচেয়ে ভাল কাজ করে।

এমভিভিএমের সুইফটুইতে কোনও স্থান নেই। আপনি জিজ্ঞাসা করছেন যে আপনি যদি একটি আয়তক্ষেত্রটি টানতে পারেন তবে

একটি ত্রিভুজ আকার মাপসই। এটি ফিট না।

আসুন কিছু ঘটনা এবং ধাপে ধাপে কাজ শুরু করুন:

  1. ভিউমোডেল এমভিভিএমের একটি মডেল।

  2. এমভিভিএম মান ধরণের (যেমন; জাভাতে কোনও জিনিস) বিবেচনা করে না।

  3. একটি মান ধরণের মডেল (রাজ্যবিহীন মডেল) রেফারেন্সের চেয়ে নিরাপদ বলে বিবেচিত হয়

    অপরিবর্তনীয়তা অর্থে টাইপ মডেল (রাজ্যের সাথে মডেল)।

এখন, এমভিভিএমকে আপনার এমনভাবে একটি মডেল সেট আপ করা দরকার যাতে এটি যখনই পরিবর্তিত হয়, এটি

কিছু পূর্ব নির্ধারিত উপায়ে আপডেট দেখুন view এটি বাইন্ডিং হিসাবে পরিচিত।

বাঁধাই না করে, আপনার উদ্বেগের আলাদা আলাদাকরণ হবে না, যেমন; রিফ্যাক্টরিং আউট

মডেল এবং সম্পর্কিত রাজ্যগুলি এবং এগুলি দেখার থেকে পৃথক রাখে।

এই দুটি জিনিসই বেশিরভাগ আইওএস এমভিভিএম বিকাশকারীদের ব্যর্থ হয়:

  1. আইওএসের traditionalতিহ্যগত জাভা অর্থে কোনও "বাঁধাই" ব্যবস্থা নেই।

    কিছু কেবল বাঁধাই উপেক্ষা করবে এবং একটি বস্তুকে ভিউমোডেল বলে মনে করবে

    স্বয়ংক্রিয়ভাবে সবকিছু সমাধান করে; কিছু কেভিও-ভিত্তিক আরএক্স চালু করবে, এবং

    যখন এমভিভিএম জিনিসগুলি আরও সহজ করার কথা ভাবা হয় তখন সমস্ত কিছুই জটিল করুন।

  2. রাষ্ট্রের সাথে মডেলটি খুব বিপজ্জনক

    কারণ এমভিভিএম ভিউমোডেলের উপর অত্যধিক জোর দেয়, রাষ্ট্র পরিচালনায় খুব কম

    এবং নিয়ন্ত্রণ পরিচালনার সাধারণ শাখা; বিকাশকারীদের বেশিরভাগই শেষ

    রাষ্ট্রের সাথে এমন একটি মডেল ভাবার কথা যা আপডেট দেখাতে পুনরায় ব্যবহারযোগ্য এবং and

    testable

    এই কারণেই সুইফট প্রথমে মান ধরণের প্রবর্তন করে; একটি মডেল ছাড়া

    অবস্থা.

এখন আপনার প্রশ্নের কাছে: আপনি যদি জিজ্ঞাসা করেন যে আপনার ভিউমোডেলটি পরিবেশনোবজেক্টে (ইও) অ্যাক্সেস করতে পারে?

আপনার উচিত হবে না। কারণ SwiftUI এ এমন একটি মডেল রয়েছে যা দেখার জন্য স্বয়ংক্রিয়ভাবে দেখা যায়

ইও রেফারেন্স। যেমন;

struct Model: View {
    @EnvironmentObject state: State
    // automatic binding in body
    var body: some View {...}
}

আমি আশা করি লোকেরা কীভাবে কমপ্যাক্ট এসডিকে ডিজাইন করা হয়েছে তা প্রশংসা করতে পারে।

সুইফটুইতে এমভিভিএম স্বয়ংক্রিয় হয় । আলাদা ভিউমোডেল অবজেক্টের দরকার নেই

যা ম্যানুয়ালি দেখার জন্য আবদ্ধ হয় যার কাছে এটিতে ইও রেফারেন্সের দরকার হয়।

উপরের কোড হল MVVM। যেমন; দেখার জন্য বাধ্যতামূলক একটি মডেল।

তবে কারণ মডেলটি মান ধরণের, তাই পরিবর্তিত মডেলের পরিবর্তে এবং রাজ্য হিসাবে

মডেল দেখুন, আপনি নিয়ন্ত্রণের বাইরে (উদাহরণস্বরূপ প্রোটোকল এক্সটেনশনে)।

এটি সরকারী পরিবর্তে ভাষা বৈশিষ্ট্যে ডিজাইনের প্যাটার্নটিকে আনুষ্ঠানিকভাবে আনুষ্ঠানিকভাবে SDK K

এটি প্রয়োগ করে। ফর্মের উপর পদার্থ।

আপনার সমাধানটি দেখুন, আপনাকে সিঙ্গলটন ব্যবহার করতে হবে যা মূলত বিশ্বব্যাপী। আপনি

সুরক্ষা না দিয়ে কোথাও গ্লোবাল অ্যাক্সেস করা কতটা বিপজ্জনক তা জানা উচিত

অপরিবর্তনীয়তা, যা আপনার কাছে নেই কারণ আপনাকে রেফারেন্স টাইপ মডেল ব্যবহার করতে হবে!

টি এল; ডিআর

আপনি সুইফটুইতে জাভা উপায়ে এমভিভিএম করবেন না। এবং এটি করার জন্য সুইফট-ওয়াইয়ের কোনও প্রয়োজন নেই

এটি করতে, এটি ইতিমধ্যে অন্তর্নির্মিত।

আশা করি আরও বিকাশকারী এটি দেখার কারণে এটি একটি জনপ্রিয় প্রশ্নের মতো মনে হয়েছিল like


1

নীচে সরবরাহিত পদ্ধতির যা আমার পক্ষে কাজ করে। এক্সকোড 11.1 দিয়ে শুরু অনেকগুলি সমাধানের সাথে পরীক্ষিত।

সাধারণ স্কিমা দেখার কারণে যেভাবে এনভায়রনমেন্ট অবজেক্টটি ইনজেকশন দেওয়া হয়েছিল, সে থেকেই সমস্যার উদ্ভব হয়েছিল

SomeView().environmentObject(SomeEO())

উদাহরণস্বরূপ, প্রথম তৈরি করা দৃশ্যে, দ্বিতীয় নির্মিত পরিবেশের অবজেক্টে, তৃতীয় পরিবেশের অবজেক্টে ভিউতে .োকানো হয়

সুতরাং আমাকে যদি ভিউ কনস্ট্রাক্টরে ভিউ মডেল / সেটআপ করার প্রয়োজন হয় তবে পরিবেশের অবজেক্টটি এখনও সেখানে উপস্থিত নেই।

সমাধান: সবকিছু পৃথকভাবে ভেঙে দিন এবং স্পষ্ট নির্ভরতা ইনজেকশন ব্যবহার করুন

কোডে এটি কীভাবে দেখাচ্ছে তা এখানে (জেনেরিক স্কিমা)

// somewhere, say, in SceneDelegate

let someEO = SomeEO()                            // create environment object
let someVM = SomeVM(eo: someEO)                  // create view model
let someView = SomeView(vm: someVM)              // create view 
                   .environmentObject(someEO)

এখানে কোনও বাণিজ্য বন্ধ নেই, কারণ ভিউমোডেল এবং এনভায়রনমেন্ট অবজেক্ট হ'ল ডিজাইন অনুসারে, রেফারেন্স-প্রকারগুলি (প্রকৃতপক্ষে ObservableObject), সুতরাং আমি এখানে এবং সেখানে কেবলমাত্র রেফারেন্স (ওরফে পয়েন্টার) পাস করি।

class SomeEO: ObservableObject {
}

class BaseVM: ObservableObject {
    let eo: SomeEO
    init(eo: SomeEO) {
       self.eo = eo
    }
}

class SomeVM: BaseVM {
}

class ChildVM: BaseVM {
}

struct SomeView: View {
    @EnvironmentObject var eo: SomeEO
    @ObservedObject var vm: SomeVM

    init(vm: SomeVM) {
       self.vm = vm
    }

    var body: some View {
        // environment object will be injected automatically if declared inside ChildView
        ChildView(vm: ChildVM(eo: self.eo)) 
    }
}

struct ChildView: View {
    @EnvironmentObject var eo: SomeEO
    @ObservedObject var vm: ChildVM

    init(vm: ChildVM) {
       self.vm = vm
    }

    var body: some View {
        Text("Just demo stub")
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.