সুইফট কম্বাইনে @ প্রকাশিত ব্যবহার করে গণিত বৈশিষ্ট্যের সমতুল্য?


20

অপরিহার্য সুইফটে, অনুলিপি অবস্থা ছাড়াই ডেটাতে সুবিধাজনক অ্যাক্সেস সরবরাহের জন্য গণিত বৈশিষ্ট্যগুলি ব্যবহার করা সাধারণ।

ধরা যাক এমভিসি ব্যবহারের জন্য আমি এই ক্লাসটি তৈরি করেছি:

class ImperativeUserManager {
    private(set) var currentUser: User? {
        didSet {
            if oldValue != currentUser {
                NotificationCenter.default.post(name: NSNotification.Name("userStateDidChange"), object: nil)
                // Observers that receive this notification might then check either currentUser or userIsLoggedIn for the latest state
            }
        }
    }

    var userIsLoggedIn: Bool {
        currentUser != nil
    }

    // ...
}

আমি যদি কম্বাইনের সাথে যেমন একটি প্রতিক্রিয়াশীল সমতুল্য তৈরি করতে চাই, যেমন সুইফটুআইয়ের সাথে ব্যবহারের জন্য, আমি সহজেই @Publishedসঞ্চিত বৈশিষ্ট্যগুলিতে Publisherএস উত্পাদন করতে যোগ করতে পারি, তবে গুণিত বৈশিষ্ট্যের জন্য নয়।

    @Published var userIsLoggedIn: Bool { // Error: Property wrapper cannot be applied to a computed property
        currentUser != nil
    }

আমি চিন্তা করতে পারে বিভিন্ন workarounds আছে। আমি পরিবর্তে আমার গণিত সম্পত্তি সঞ্চয় করতে এবং এটি আপডেট রাখতে পারি।

বিকল্প 1: সম্পত্তি পর্যবেক্ষক ব্যবহার করে:

class ReactiveUserManager1: ObservableObject {
    @Published private(set) var currentUser: User? {
        didSet {
            userIsLoggedIn = currentUser != nil
        }
    }

    @Published private(set) var userIsLoggedIn: Bool = false

    // ...
}

বিকল্প 2: Subscriberআমার নিজস্ব শ্রেণিতে একটি ব্যবহার :

class ReactiveUserManager2: ObservableObject {
    @Published private(set) var currentUser: User?
    @Published private(set) var userIsLoggedIn: Bool = false

    private var subscribers = Set<AnyCancellable>()

    init() {
        $currentUser
            .map { $0 != nil }
            .assign(to: \.userIsLoggedIn, on: self)
            .store(in: &subscribers)
    }

    // ...
}

যাইহোক, এই workarounds গণিত বৈশিষ্ট্য হিসাবে মার্জিত নয়। তারা সদৃশ অবস্থায় থাকে এবং তারা উভয় সম্পত্তি একই সাথে আপডেট করে না।

Publisherকম্বাইনে একটি গণনা করা সম্পত্তিতে যুক্ত করার উপযুক্ত সমতুল্য কী হবে ?



1
গুণিত বৈশিষ্ট্য হ'ল ধরণের বৈশিষ্ট্য যা উত্পন্ন বৈশিষ্ট্য। তাদের মান নির্ভরশীলের মানগুলির উপর নির্ভর করে। একা এই কারণেই, এটি বলা যেতে পারে যে এগুলি কখনই কোনও অভিনয় করার মতো নয় ObservableObject। আপনি অন্তর্নিহিতভাবে ধরে নিয়েছেন যে কোনও ObservableObjectবস্তুর পারস্পরিক দক্ষতা থাকতে হবে যা সংজ্ঞা অনুসারে গণিত সম্পত্তির ক্ষেত্রে নয় ।
নাঈম

আপনি এই একটি সমাধান খুঁজে পেয়েছেন? আমি ঠিক একই পরিস্থিতিতে আছি, আমি রাষ্ট্র এড়াতে চাই এবং এখনও প্রকাশ করতে সক্ষম হতে পারি
এরটস্প্পা

উত্তর:


2

ডাউন স্ট্রিম ব্যবহার সম্পর্কে কীভাবে?

lazy var userIsLoggedInPublisher: AnyPublisher = $currentUser
                                          .map{$0 != nil}
                                          .eraseToAnyPublisher()

এই ভাবে, সাবস্ক্রিপশন আপস্ট্রিম থেকে উপাদান পাবেন, তারপর আপনি ব্যবহার করতে পারেন sinkবা assignকরতে didSetধারণা।


2

আপনি যে সম্পত্তিটি ট্র্যাক করতে চান তার সাবস্ক্রাইব করে নতুন প্রকাশক তৈরি করুন।

@Published var speed: Double = 88

lazy var canTimeTravel: AnyPublisher<Bool,Never> = {
    $speed
        .map({ $0 >= 88 })
        .eraseToAnyPublisher()
}()

তারপরে আপনি এটিকে আপনার @Publishedসম্পত্তির মতো পর্যবেক্ষণ করতে সক্ষম হবেন ।

private var subscriptions = Set<AnyCancellable>()


override func viewDidLoad() {
    super.viewDidLoad()

    sourceOfTruthObject.$canTimeTravel.sink { [weak self] (canTimeTravel) in
        // Do something…
    })
    .store(in: &subscriptions)
}

সরাসরি সম্পর্কিত নয় তবুও দরকারী, আপনি সেই সাথে একাধিক বৈশিষ্ট্য ট্র্যাক করতে পারেন combineLatest

@Published var threshold: Int = 60

@Published var heartData = [Int]()

/** This publisher "observes" both `threshold` and `heartData`
 and derives a value from them.
 It should be updated whenever one of those values changes. */
lazy var status: AnyPublisher<Status,Never> = {
    $threshold
       .combineLatest($heartData)
       .map({ threshold, heartData in
           // Computing a "status" with the two values
           Status.status(heartData: heartData, threshold: threshold)
       })
       .receive(on: DispatchQueue.main)
       .eraseToAnyPublisher()
}()

0

আপনি আপনার পর্যবেক্ষণযোগ্য অবজেক্টে একটি পাসথ্রু সাবজেক্টটি ঘোষণা করবেন :

class ReactiveUserManager1: ObservableObject {

    //The PassthroughSubject provides a convenient way to adapt existing imperative code to the Combine model.
    var objectWillChange = PassthroughSubject<Void,Never>()

    [...]
}

আর didSet আপনার এর (willSet ভালো হতে পারে) @Published Var আপনি যদি একটি পদ্ধতি নামক ব্যবহার করবে পাঠান ()

class ReactiveUserManager1: ObservableObject {

    //The PassthroughSubject provides a convenient way to adapt existing imperative code to the Combine model.
    var objectWillChange = PassthroughSubject<Void,Never>()

    @Published private(set) var currentUser: User? {
    willSet {
        userIsLoggedIn = currentUser != nil
        objectWillChange.send()
    }

    [...]
}

আপনি এটি ডাব্লুডাব্লুডিসি ডেটা ফ্লো টকটিতে চেক করতে পারেন


আপনার সম্মিলন
নিকোলা লরিতানো

এটি নিজের প্রশ্নের 1 বিকল্প থেকে কীভাবে আলাদা ?
নাঈম

অপশন 1 তে কোনও পাসথ্রু সাবজেক্ট নেই
নিকোলা লরিতানো

ঠিক আছে, আমি আসলে যা চেয়েছিলাম তা ছিল না। @Publishedমোড়ক এবং PassthroughSubjectউভয়ই এই প্রসঙ্গে একই উদ্দেশ্য পরিবেশন করে। আপনি কী লিখেছেন এবং ওপি আসলে কী অর্জন করতে চেয়েছিল তাতে মনোযোগ দিন। আপনার সমাধানটি কী বিকল্পটি 1 এর বিকল্প হিসাবে আরও ভাল বিকল্প হিসাবে কাজ করে ?
নাঈম

0

স্ক্যান ( : :) ক্লোজারের দ্বারা প্রত্যাবর্তিত সর্বশেষ মান সহ বদ্ধমূল হিসাবে বর্তমান উপাদান সরবরাহ করে আপস্ট্রিম প্রকাশকের কাছ থেকে উপাদানগুলিকে রূপান্তর করে।

আপনি সর্বশেষ এবং বর্তমান মান পেতে স্ক্যান () ব্যবহার করতে পারেন। উদাহরণ:

@Published var loading: Bool = false

init() {
// subscriber connection

 $loading
        .scan(false) { latest, current in
                if latest == false, current == true {
                    NotificationCenter.default.post(name: NSNotification.Name("userStateDidChange"), object: nil) 
        }
                return current
        }
         .sink(receiveValue: { _ in })
         .store(in: &subscriptions)

}

উপরের কোডটি এর সমান: (কম সংযুক্ত)

  @Published var loading: Bool = false {
            didSet {
                if oldValue == false, loading == true {
                    NotificationCenter.default.post(name: NSNotification.Name("userStateDidChange"), object: nil)
                }
            }
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.