কোনও বস্তুর কী মান পর্যবেক্ষক সংযুক্ত রয়েছে তা আমি কীভাবে বলতে পারি


142

আপনি যদি অবজার্ভার্স অপসারণের জন্য কোনও উদ্দেশ্য সি অবজেক্টকে বলেন: একটি মূল পথ এবং সেই মূল পথটি নিবন্ধিত করা হয়নি, এটি দুঃখকে ক্র্যাক করে। পছন্দ -

'মূল কী "কেকিপাথ" এর জন্য কোনও পর্যবেক্ষককে এখান থেকে সরানো যাচ্ছে না কারণ এটি পর্যবেক্ষক হিসাবে নিবন্ধভুক্ত নয়' '

কোনও বস্তুর নিবন্ধিত পর্যবেক্ষক রয়েছে কিনা তা নির্ধারণ করার কোনও উপায় আছে, তাই আমি এটি করতে পারি

if (object has observer){
  remove observer
}
else{
  go on my merry way
}

আমি এই দৃশ্যে আইওএস 8-তে একটি পুরানো অ্যাপ্লিকেশন আপডেট করেছিলাম যেখানে একটি ভিউ কন্ট্রোলার অবনমিত হয়ে "অপসারণ করতে পারবেন না" ব্যতিক্রম ছুঁড়ে ফেলা হচ্ছে। আমি কল করে যে চিন্তা addObserver:মধ্যে viewWillAppear:এবং সঙ্গতিপূর্ণভাবেই removeObserver:মধ্যে viewWillDisappear:কল সঠিকভাবে জোড়া হয়েছে। আমাকে দ্রুত সমাধান করতে হবে তাই আমি চেষ্টা-সমাধান সমাধানটি বাস্তবায়ন করতে যাচ্ছি এবং কারণটি আরও তদন্ত করতে একটি মন্তব্য করব।
অস্থির

আমি ঠিক একই রকম কিছু নিয়ে কাজ করছি এবং আমি দেখতে পাচ্ছি যে আমার নকশাটি আরও গভীরভাবে অনুসন্ধান করা এবং এটিকে সামঞ্জস্য করা দরকার যাতে আমাকে আর পর্যবেক্ষককে অপসারণের দরকার পড়বে না।
বোগদান

এই উত্তরে প্রস্তাবিত মত বুল মান ব্যবহার করা আমার পক্ষে সবচেয়ে ভাল কাজ করেছে: stackoverflow.com/a/37641685/4833705
ল্যান্স সামেরিয়া

উত্তর:


315

আপনার অপসারণকারক কলটির চারপাশে একবার চেষ্টা করুন

@try{
   [someObject removeObserver:someObserver forKeyPath:somePath];
}@catch(id anException){
   //do nothing, obviously it wasn't attached because an exception was thrown
}

12
1+ ভাল উত্তর, আমার জন্য কাজ করেছে এবং আমি এটি আপনার রেন্ট সম্পাদনার আগে সম্মত agree
রবার্ট

25
মুছে ফেলা রেন্টের জন্য উন্নত যা আমি সম্ভবত সম্মত হই।
বেন গোটো

12
এখানে কি অন্য কোনও মার্জিত সমাধান নেই? এটি প্রতি ব্যবহারের জন্য কমপক্ষে 2 এমএস নেয় ... এটি একটি টেবিলভিউসে কল্পনা করুন
নুনস

19
ডাউনভোটেড কারণ আপনি এই কথাটি বাদ দিচ্ছেন যে এটি উত্পাদন কোডের জন্য অনিরাপদ এবং যে কোনও সময় ব্যর্থ হওয়ার সম্ভাবনা রয়েছে। ফ্রেমওয়ার্ক কোডের মাধ্যমে ব্যতিক্রম উত্থাপন কোকোতে কোনও বিকল্প নয়।
নিকোলাই রুহে

6
এই কোডটি কীভাবে সুইফট ২.১ এ ব্যবহার করবেন। do {स्वयं.প্লেয়ার আইটেমটি চেষ্টা করুন?
বিপুলক 617

37

আসল প্রশ্ন হ'ল আপনি কেন এটি পর্যবেক্ষণ করছেন কিনা তা আপনি জানেন না।

আপনি যদি পর্যবেক্ষণ করা অবজেক্টের শ্রেণিতে এটি করছেন, থামুন। যা কিছু পর্যবেক্ষণ করে তা পর্যবেক্ষণ করে চলবে বলে আশা করে। যদি আপনি পর্যবেক্ষণকারীদের বিজ্ঞপ্তিগুলি অজান্তে বাদ দেন, তবে জিনিসগুলি নষ্ট হওয়ার আশা করুন; আরও সুনির্দিষ্টভাবে, পর্যবেক্ষকের রাজ্যটি পুরানো পর্যবেক্ষণ হওয়া বস্তুর কাছ থেকে আপডেট গ্রহণ না করায় বাসি হয়ে যাওয়ার প্রত্যাশা করে।

যদি আপনি পর্যবেক্ষণকারী অবজেক্টের ক্লাসে এটি করছেন, কেবল কোন বিষয়গুলি আপনি পর্যবেক্ষণ করছেন তা কেবল মনে রাখবেন (বা আপনি যদি কেবলমাত্র কোনও একটি বিষয় পর্যবেক্ষণ করেন তবে তা পর্যবেক্ষণ করছেন কিনা)। এটি ধরে নেওয়া হচ্ছে যে পর্যবেক্ষণটি গতিশীল এবং দুটি অন্যথায়-সম্পর্কিত-অবাস্তব বস্তুর মধ্যে রয়েছে; যদি পর্যবেক্ষক পর্যবেক্ষকের মালিক হন তবে আপনি পর্যবেক্ষণটি তৈরি বা বজায় রাখার পরে কেবল পর্যবেক্ষক যুক্ত করুন এবং পর্যবেক্ষককে মুক্তি দেওয়ার আগে পর্যবেক্ষককে অপসারণ করুন।

পর্যবেক্ষক হিসাবে কোনও বস্তু যুক্ত করা এবং অপসারণ সাধারণত পর্যবেক্ষকের শ্রেণিতে হওয়া উচিত, এবং কখনও পর্যবেক্ষিত বস্তুর ক্ষেত্রে নয় in


14
কেস ব্যবহার করুন: আপনি ভিউডিডনলোড এবং ডেলোক-এ পর্যবেক্ষককে সরাতে চান। এটি তাদের দু'বার সরিয়ে দিচ্ছে এবং যদি আপনার ভিউকন্ট্রোলার কোনও মেমরির সতর্কতা থেকে লোড না করা হয় এবং তারপরে ছেড়ে দেওয়া হয় তবে ব্যতিক্রম ছুঁড়ে ফেলবে। আপনি এই পরিস্থিতিটি পরিচালনা করার পরামর্শ দিচ্ছেন কীভাবে?
বান্দেজপাটাইস

2
@ ব্যান্ডেজাপাইসা: আমার উত্তরে আমি যা বলেছিলাম তা অনেকখানি: আমি পর্যবেক্ষণ করছি কিনা তা লক্ষ্য রাখুন এবং আমি থাকলেই পর্যবেক্ষণ বন্ধ করার চেষ্টা করব stop
পিটার হোসি

41
না, এটি একটি আকর্ষণীয় প্রশ্ন নয়। আপনার এটির খোঁজ রাখা উচিত নয়; কোড প্যাথটি যেখানে যুক্ত করা হয়েছে সেখানে আপনার আঘাত হয়েছে কি না সে সম্পর্কে কোনও চিন্তা না করেই আপনি কেবলমাত্র শ্রোতাদের ডেললকে নিবন্ধভুক্ত করতে সক্ষম হবেন। এটি এনএসএনটিফিকেশন সেন্টারের অপসারণকারীর মতো কাজ করা উচিত, যা আপনার কাছে আসলে আছে বা না তা বিবেচ্য নয়। এই ব্যতিক্রমটি কেবল এমন বাগ তৈরি করছে যেখানে অন্য কোনওটির অস্তিত্ব নেই, যা খারাপ API নকশা।
গ্লেন মেইনার্ড

1
@ গ্লেনমায়নার্ড: যেমনটি আমি উত্তরে বলেছিলাম, “যদি আপনি পর্যবেক্ষকের বিজ্ঞপ্তিগুলি অজান্তেই বাদ দেন তবে আশা করি জিনিসগুলি নষ্ট হয়ে যাবে; আরও সুনির্দিষ্টভাবে, পর্যবেক্ষকের রাজ্যটি পুরানো পর্যবেক্ষণ করা বস্তুর কাছ থেকে আপডেট না পাওয়ার কারণে বাসি হয়ে যাওয়ার আশা করে। প্রতিটি পর্যবেক্ষকের নিজস্ব পর্যবেক্ষণ শেষ করা উচিত; এটি করতে ব্যর্থতা আদর্শভাবে দৃশ্যমান হওয়া উচিত।
পিটার হোসি

3
অন্যান্য কোডের পর্যবেক্ষককে অপসারণের বিষয়ে প্রশ্নের কিছুতেই কথা হয় না ।
গ্লেন মেইনার্ড

25

FWIW, [someObject observationInfo]মনে হয় nilযদি someObjectকোনও পর্যবেক্ষক না থাকে। আমি যদিও এই আচরণটি বিশ্বাস করি না, যেমনটি এটি নথিভুক্ত হয়নি। এছাড়াও, observationInfoনির্দিষ্ট পর্যবেক্ষক পেতে কীভাবে পড়তে হয় তা আমি জানি না ।


আমি কীভাবে নির্দিষ্ট পর্যবেক্ষককে পুনরুদ্ধার করতে পারি তা জানার কি আপনি কি ঘটেন? objectAtIndex:কাঙ্ক্ষিত ফলাফল দেয় না))
এম্যানটাস 25'12

1
পছন্দ করুন প্রিন্টগুলিতে এটি সূক্ষ্মভাবে প্রকাশিত হচ্ছে, তবে এটি শূন্য হওয়ার জন্য একটি পয়েন্টার। আমি এটা কিভাবে পড়া উচিত?
নীরাজ

এক্সকোডের ডিবাগিং কাগজে (শিরোনামে "ম্যাজিক" সহ কিছু) নথিভুক্ত করা হয়েছে পর্যবেক্ষণআইএনফো deb আপনি এটি দেখার চেষ্টা করতে পারেন। আমি বলতে পারি যে আপনার যদি কেউ আপনার অবজেক্টটি পর্যবেক্ষণ করছেন কিনা তা জানতে প্রয়োজন - আপনি কিছু ভুল করছেন। আপনার আর্কিটেকচার এবং যুক্তি পুনর্বিবেচনা। এটিকে কঠিন উপায়ে শিখেছি))
এমমানটাস

সূত্র:NSKeyValueObserving.h
নেফেরিয়ান ব্ল্যাক

হাস্যকরভাবে মৃত শেষের জন্য আরও 1 তবে এখনও কিছুটা সহায়ক উত্তরের জন্য
উইল ভন উলরিচ

4

এটি করার একমাত্র উপায় হ'ল আপনি কোনও পর্যবেক্ষক যুক্ত করার সময় একটি পতাকা সেট করা।


3
আপনি যে কোনও জায়গায় বিওএলগুলি দিয়ে শেষ করেছেন, আরও ভাল এখনও কেভিও র‍্যাপার অবজেক্ট তৈরি করুন যা পর্যবেক্ষককে যুক্ত করে এবং এটি সরিয়ে দেয়। এটি নিশ্চিত করতে পারে যে আপনার পর্যবেক্ষক কেবল একবারই সরানো হয়েছে। আমরা ঠিক এইভাবে একটি অবজেক্ট ব্যবহার করেছি এবং এটি কাজ করে।
বান্দেজপাটাইস

দুর্দান্ত ধারণা আপনি যদি সর্বদা পর্যবেক্ষণ না করেন।
আন্দ্রে সাইমন

4

আপনি যখন কোনও সামগ্রীতে কোনও পর্যবেক্ষক যুক্ত করেন আপনি এটিকে এটিতে যুক্ত করতে NSMutableArrayপারেন:

- (void)addObservedObject:(id)object {
    if (![_observedObjects containsObject:object]) {
        [_observedObjects addObject:object];
    }
}

আপনি যদি অবজেক্টগুলি আনবাইজ করতে চান তবে আপনি এর মতো কিছু করতে পারেন:

for (id object in _observedObjects) {
    if ([object isKindOfClass:[MyClass class]]) {
        MyClass *myObject = (MyClass *)object;
        [self unobserveMethod:myObject];
    }
}
[_observedObjects removeAllObjects];

মনে রাখবেন, আপনি যদি কোনও একটি অবজেক্টটি সংরক্ষণ না করে থাকেন তবে এটিকে _observedObjectsঅ্যারে থেকে সরান :

- (void)removeObservedObject:(id)object {
    if ([_observedObjects containsObject:object]) {
        [_observedObjects removeObject:object];
    }
}

1
যদি একাধিক থ্রেড বিশ্বে এটি ঘটে থাকে তবে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনার অ্যারেটি থ্রেডসেফ
শ্রুতিম

আপনি কোনও অবজেক্টের দৃ reference় রেফারেন্স রাখছেন, যা তালিকায় প্রতিবার যুক্ত হওয়ার পরে ধরে রাখার সংখ্যা বাড়িয়ে তুলবে এবং রেফারেন্সটি অ্যারে থেকে সরিয়ে না দেওয়া হলে তা বিচ্যুত হবে না। আমি দুর্বল উল্লেখগুলি রাখতে NSHashTable/ ব্যবহার করতে পছন্দ করব NSMapTable
অতুলখত্রি

3

আমার মতে - এটি রিটেনকাউন্ট মেকানিজমের অনুরূপ কাজ করে। আপনি নিশ্চিত হতে পারবেন না যে বর্তমান মুহূর্তে আপনার নিজের পর্যবেক্ষক রয়েছেন। এমনকি যদি আপনি যাচাই করেন: স্ব-সংরক্ষণ - ইনফো - আপনি নিশ্চিতভাবে জানতে পারবেন না যে ভবিষ্যতে আপনার কাছে পর্যবেক্ষক থাকবে / থাকবে না।

ভালো লেগেছে retainCount । হতে পারে অবজারভেশন ইনফো পদ্ধতিটি ঠিক সেই ধরণের অকেজো নয়, তবে আমি এটি কেবল ডিবাগ উদ্দেশ্যেই ব্যবহার করি।

ফলস্বরূপ - আপনাকে কেবল এটি মেমরি পরিচালনার মতো করতে হবে। যদি আপনি কোনও পর্যবেক্ষক যুক্ত করেন - আপনার যখন প্রয়োজন হবে না তখনই সরিয়ে দিন। ভিউউইল অ্যাপয়ার / ভিউউইলডিস্পিয়ার ইত্যাদি পদ্ধতি ব্যবহার করার মতো। উদাহরণ:

-(void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self addObserver:nil forKeyPath:@"" options:NSKeyValueObservingOptionNew context:nil];
}

-(void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self removeObserver:nil forKeyPath:@""];
}

এবং এটি আপনাকে কিছু নির্দিষ্ট চেকের প্রয়োজন - আপনার নিজের শ্রেণি প্রয়োগ করুন যা পর্যবেক্ষকদের একটি অ্যারে পরিচালনা করে এবং এটি আপনার চেকগুলির জন্য ব্যবহার করে।


[self removeObserver:nil forKeyPath:@""]; আগে যেতে হবে: [super viewWillDisappear:animated];
জোশুয়া হার্ট

@ জোশুয়া হার্ট কেন?
কোয়ারেজ

কারণ এটি টিয়ার ডাউন পদ্ধতি (ডেলোক)। আপনি যখন কোনও ধরণের টিয়ারডাউন পদ্ধতি ওভাররাইড করেন, তখন আপনি সুপারকে শেষ বলে call লাইক: - (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
জোশুয়া হার্ট

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

3

[someObject observationInfo]nilযদি কোন পর্যবেক্ষক না থাকে তবে ফিরে আসুন।

if ([tableMessage observationInfo] == nil)
{
   NSLog(@"add your observer");
}
else
{
  NSLog(@"remove your observer");

}

সেই অনুসারে অ্যাপল ডক্স অনুসারে: অবজারভেশন ইনফো একটি পয়েন্টার দেয় যা রিসিভারের সাথে নিবন্ধিত সমস্ত পর্যবেক্ষকের সম্পর্কে তথ্য সনাক্ত করে।
ফ্রেডেরিক


2

পর্যবেক্ষক ধাঁচের পুরো বিষয়টি হ'ল পর্যবেক্ষণ করা শ্রেণিকে "সিল করা" দেওয়া - এটি পর্যবেক্ষণ করা হচ্ছে কিনা তা জানা বা যত্ন নেওয়া না। আপনি স্পষ্টভাবে এই প্যাটার্নটি ভাঙ্গার চেষ্টা করছেন।

কেন?

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


10
তিনি জিজ্ঞাসা করছেন যে শ্রোতা এটি কিছু শুনছে কিনা তা জানতে পারে, বস্তুটি পর্যবেক্ষণ করা হচ্ছে কীভাবে এটি পর্যবেক্ষণ করা হচ্ছে কিনা তা জানতে পারে না can
গ্লেন মেইনার্ড

1

আমি সেই চেষ্টা ধরার সমাধানের ভক্ত নই তাই আমি বেশিরভাগ সময় যা করি তা হ'ল আমি এই শ্রেণীর ভিতরে একটি নির্দিষ্ট বিজ্ঞপ্তির জন্য সাবস্ক্রাইব এবং সাবস্ক্রাইব পদ্ধতি তৈরি করি। উদাহরণস্বরূপ, এই দুটি পদ্ধতি বিশ্বব্যাপী কীবোর্ড বিজ্ঞপ্তিতে অবজেক্টটিকে সাবস্ক্রাইব বা সাবস্ক্রাইব করে:

@interface ObjectA : NSObject
-(void)subscribeToKeyboardNotifications;
-(void)unsubscribeToKeyboardNotifications;
@end

এই পদ্ধতিগুলির মধ্যে আমি একটি ব্যক্তিগত সম্পত্তি ব্যবহার করি যা সাবস্ক্রিপশন অবস্থার উপর নির্ভর করে সত্য বা মিথ্যাতে সেট করা আছে:

@interface ObjectA()
@property (nonatomic,assign) BOOL subscribedToKeyboardNotification
@end

@implementation

-(void)subscribeToKeyboardNotifications {
    if (!self.subscribedToKeyboardNotification) {
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardShow:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardHide:) name:UIKeyboardWillHideNotification object:nil];
        self.subscribedToKeyboardNotification = YES;
    }
}

-(void)unsubscribeToKeyboardNotifications {
    if (self.subscribedToKeyboardNotification) {
        [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil];
        self.subscribedToKeyboardNotification = NO;
    }
}
@end

0

অ্যাডামের উত্তর ছাড়াও আমি এই জাতীয় ম্যাক্রো ব্যবহার করার পরামর্শ দিতে চাই

#define SafeRemoveObserver(sender, observer, keyPath) \
@try{\
   [sender removeObserver:observer forKeyPath:keyPath];\
}@catch(id anException){\
}

ব্যবহারের উদাহরণ

- (void)dealloc {
    SafeRemoveObserver(someObject, self, somePath);
}

1
এটি একটি ব্যতিক্রম ছুঁড়ে যে এটি ক্রেজি? কিছুই সংযুক্ত না হলে কেন এটি কিছুই করে না?
অরণ মুলহোল্যান্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.