এআরসি-সক্ষম কোডটিতে সতর্কতা "এই ব্লকে দৃ strongly়ভাবে ক্যাপচার [কোনও অবজেক্ট] চালিয়ে যাওয়া রক্ষণাবেক্ষণের চক্রকে নিয়ে যাওয়ার সম্ভাবনা রয়েছে" AR


141

এআরসি সক্ষম কোডটিতে, কোনও ব্লক-ভিত্তিক এপিআই ব্যবহার করার সময় কোনও সম্ভাব্য রক্ষণশীল চক্র সম্পর্কে একটি সতর্কতা কীভাবে ঠিক করবেন?

সতর্কবার্তা:
Capturing 'request' strongly in this block is likely to lead to a retain cycle

কোডের এই স্নিপেট দ্বারা উত্পাদিত:

ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.rawResponseData error:nil];
    // ...
    }];

সতর্কতা requestব্লকের ভিতরে থাকা অবজেক্টের ব্যবহারের সাথে যুক্ত ।


1
আপনার responseDataপরিবর্তে সম্ভবত ব্যবহার করা উচিত rawResponseData, ASIHTTPRequest ডকুমেন্টেশন চেক করুন।
0xced

উত্তর:


165

নিজেকে উত্তর:

ডকুমেন্টেশন সম্পর্কে আমার বোঝা বলছে যে কীওয়ার্ড blockব্যবহার করা এবং ব্লকের ভিতরে এটি ব্যবহার করার পরে ভেরিয়েবলটি নির্ধারণ করা ঠিক হওয়া উচিত, তবে এটি এখনও সতর্কতা দেখায়।

__block ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.responseData error:nil];
    request = nil;
// ....

    }];

আপডেট: '_ block' এর পরিবর্তে '_ দুর্বল' শব্দটি এবং একটি অস্থায়ী ভেরিয়েবল ব্যবহার করে এটি পেয়েছে :

ASIHTTPRequest *_request = [[ASIHTTPRequest alloc] initWithURL:...
__weak ASIHTTPRequest *request = _request;

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.responseData error:nil];
    // ...
    }];

আপনি যদি আইওএস 4 কেও টার্গেট করতে চান তবে এর __unsafe_unretainedপরিবর্তে ব্যবহার করুন __weak। একই আচরণ, তবে পয়েন্টারটি বস্তুটি নষ্ট হয়ে গেলে স্বয়ংক্রিয়ভাবে শিলার পরিবর্তে পয়েন্টারটি ঝুঁকিতে থাকে।


8
এআরসি ডক্সের ভিত্তিতে, আআআআসি এবং ব্লকগুলি ব্যবহার করার সময় আগের মতো আচরণ পেতে আপনার কাছে __unsafe_unretained __ block একসাথে ব্যবহার করা দরকার বলে মনে হচ্ছে।
হান্টার

4
@ সান ক্লার্কহেস: আমি যখন প্রথম দুটি লাইন একত্রিত করি তখন আমি এই সতর্কতাটি পাই: "দুর্বল ভেরিয়েবলের কাছে ধরে রাখা অবজেক্টকে বরাদ্দ করা; অবজেক্টটি নিয়োগের পরে মুক্তি দেওয়া হবে"
গিলাইউম

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

2
: আমি একটি ফলো আপ প্রশ্ন পোস্ট করেছেন stackoverflow.com/questions/8859649/...
barfoon

3
কেউ আপনাকে কী কারণে __ ব্লক এবং __Wak কীওয়ার্ডগুলি প্রয়োজন তা ব্যাখ্যা করতে পারে? আমার ধারণা এখানে একটি ধরে রাখা চক্র তৈরি হচ্ছে, তবে আমি এটি দেখতে পাচ্ছি না। এবং কীভাবে একটি অস্থায়ী পরিবর্তনশীল তৈরি করা সমস্যার সমাধান করে?
ব্যবহারকারী 798719

50

সমস্যাটি ঘটে কারণ আপনি অনুরোধের জন্য কোনও ব্লক বরাদ্দ করেছেন যার মধ্যে অনুরোধটির দৃ a় উল্লেখ রয়েছে। ব্লকটি স্বয়ংক্রিয়ভাবে অনুরোধ ধরে রাখবে, সুতরাং চক্রের কারণে আসল অনুরোধটি হ্রাস পাবে না। ধারণা তৈরী কর?

এটি কেবল অদ্ভুত কারণ আপনি অনুরোধের বিষয়টিকে __ব্লক দিয়ে ট্যাগ করছেন যাতে এটি নিজেই উল্লেখ করতে পারে। আপনি এটির পাশাপাশি একটি দুর্বল রেফারেন্স তৈরি করে এটি ঠিক করতে পারেন ।

ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...];
__weak ASIHTTPRequest *wrequest = request;

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:wrequest.rawResponseData error:nil];
    // ...
    }];

__weak ASIHTTPRequest * wrequest = অনুরোধ; আমার জন্য কাজ করে না। ত্রুটি দেওয়ার ক্ষেত্রে আমি __ block ASIHTTPRequest * blockRequest = অনুরোধ ব্যবহার করেছি;
রাম জি

13

এটি ব্লকের মধ্যে নিজেকে ধরে রাখার কারণে ঘটে। ব্লকটি স্ব থেকে অ্যাক্সেস পাবে, এবং স্ব ব্লকে উল্লেখ করা হবে। এটি একটি ধরে রাখার চক্র তৈরি করবে।

একটি দুর্বল রেফারেন্স তৈরি করে এটি সমাধান করার চেষ্টা করুন self

__weak typeof(self) weakSelf = self;

operationManager = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
[operationManager setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

    [weakSelf requestFinishWithSucessResponseObject:responseObject withAFHTTPRequestOperation:operation andRequestType:eRequestType];

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    [weakSelf requestFinishWithFailureResponseObject:error withAFHTTPRequestOperation:operation andRequestType:eRequestType];
}];
[operationManager start];

এটি সঠিক উত্তর এবং এটি হিসাবে উল্লেখ করা উচিত
বেনজামিন

6

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

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
#pragma clang diagnostic ignored "-Wgnu"

-(void)someMethod {
}

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

1
সত্যি কথা বলতে, একজনের সঠিক হওয়ার এবং সংকলকটি ভুল হওয়ার সম্ভাবনা খুব কম। সুতরাং আমি বলতে চাই যে সতর্কতাগুলি ছাড়িয়ে যাওয়া ঝুঁকিপূর্ণ ব্যবসা
ম্যাক্স ম্যাকলিউড

3

আমি যখন গিলিয়াম দ্বারা প্রদত্ত সমাধানটি চেষ্টা করি, তখন ডিবাগ মোডে সবকিছু ঠিক থাকে তবে এটি রিলিজ মোডে ক্রাশ হয়।

নোট করুন যে __weak ব্যবহার করবেন না তবে __unsafe_unretained কারণ আমার টার্গেট আইওএস 4.3।

কমপ্লেশনব্লক: "অনুরোধ" অবজেক্টে ডাকলে আমার কোড ক্র্যাশ: অনুরোধটি বাতিল করা হয়েছিল ...

সুতরাং, এই সমাধানটি ডিবাগ এবং রিলিজ দুটি ক্ষেত্রেই কাজ করে:

// Avoiding retain cycle :
// - ASIHttpRequest object is a strong property (crashs if local variable)
// - use of an __unsafe_unretained pointer towards self inside block code

self.request = [ASIHttpRequest initWithURL:...
__unsafe_unretained DataModel * dataModel = self;

[self.request setCompletionBlock:^
{
    [dataModel processResponseWithData:dataModel.request.receivedData];        
}];

আকর্ষণীয় সমাধান। আপনি কি বুঝতে পেরেছিলেন যে এটি কেন রিলিজ মোডে ক্র্যাশ করেছে এবং ডিবাগে নয়?
ভ্যালেরিও স্যান্টিনেল্লি


-6

অ্যাপল বিকাশকারী ওয়েবসাইটে ডকুমেন্টেশনটি একবার দেখুন: https://developer.apple.com/library/prerelease/ios/#docamentation/ জেনারাল / কনসেপ্টুয়াল / এআরসিপিগ্রোমিংগুইড / ইন্ট্রোডাকশন html#//apple_ref/doc/ uid / TP40011029

পৃষ্ঠার নীচে চক্র ধরে রাখার বিষয়ে একটি বিভাগ রয়েছে।

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