সংক্ষিপ্ত উত্তর
self
সরাসরি অ্যাক্সেস করার পরিবর্তে , আপনাকে এমন কোনও রেফারেন্স থেকে ধরে রাখা হবে যা পরোক্ষভাবে ব্যবহার করা উচিত। আপনি যদি স্বয়ংক্রিয় রেফারেন্স গণনা (এআরসি) ব্যবহার না করে থাকেন তবে আপনি এটি করতে পারেন:
__block MyDataProcessor *dp = self;
self.progressBlock = ^(CGFloat percentComplete) {
[dp.delegate myAPI:dp isProcessingWithProgress:percentComplete];
}
__block
শব্দ চিহ্ন ভেরিয়েবল যে ব্লক ভিতরে পরিবর্তন করা যাবে (আমরা যে কাজ করছি) কিন্তু তারা স্বয়ংক্রিয়ভাবে যখন ব্লক বজায় রাখা হয় অপরিবর্তিত রাখা নেই (যতক্ষণ না আপনি এআরসি ব্যবহার করছেন)। আপনি যদি এটি করেন, আপনার অবশ্যই নিশ্চিত হওয়া উচিত যে মাইডাটাপ্রসেসর ইনস্ট্যান্স প্রকাশ হওয়ার পরে অন্য কোনও কিছুই ব্লকটি কার্যকর করার চেষ্টা করছে না। (আপনার কোডের কাঠামো দেওয়া, এটি কোনও সমস্যা হওয়া উচিত নয়)) আরও পড়ুন__block
।
আপনি যদি এআরসি ব্যবহার করে থাকেন তবে __block
পরিবর্তনের শব্দার্থবিদ্যা এবং রেফারেন্স ধরে রাখা হবে , এক্ষেত্রে আপনার __weak
পরিবর্তে এটি ঘোষণা করা উচিত ।
দীর্ঘ উত্তর
ধরা যাক আপনার এইরকম কোড ছিল:
self.progressBlock = ^(CGFloat percentComplete) {
[self.delegate processingWithProgress:percentComplete];
}
এখানে সমস্যা হ'ল স্ব ব্লকের একটি রেফারেন্স ধরে রাখছেন; ইতোমধ্যে ব্লকের অবশ্যই তার প্রতিনিধিদের সম্পত্তি আনতে এবং প্রতিনিধিটিকে একটি পদ্ধতি প্রেরণের জন্য স্ব সম্পর্কিত একটি রেফারেন্স বজায় রাখতে হবে। যদি আপনার অ্যাপ্লিকেশানের অন্য সমস্ত কিছু এই অবজেক্টের জন্য তার রেফারেন্স প্রকাশ করে তবে এর ধরে রাখার গণনা শূন্য হবে না (কারণ ব্লকটি এটি দেখিয়েছে) এবং ব্লকটি কোনও ভুল করছে না (কারণ বস্তুটি এটি দেখিয়েছে) এবং তাই অবজেক্টের জুড়ি গাদা মধ্যে ফাঁস হবে, মেমরি দখল করে কিন্তু একটি ডিবাগার ছাড়াই চিরতরে অ্যাক্সেসযোগ্য। মর্মান্তিক, সত্যিই।
পরিবর্তে এটি করে সহজেই এই কেসটি ঠিক করা যায়:
id progressDelegate = self.delegate;
self.progressBlock = ^(CGFloat percentComplete) {
[progressDelegate processingWithProgress:percentComplete];
}
এই কোডটিতে স্ব ব্লকটি ধরে রাখছে, ব্লকটি প্রতিনিধিটিকে ধরে রাখছে, এবং কোনও চক্র নেই (এখান থেকে দৃশ্যমান; প্রতিনিধি আমাদের বস্তু ধরে রাখতে পারে তবে এটি এখন আমাদের হাতের বাইরে)। এই কোডটি একইভাবে কোনও ফাঁস হওয়ার ঝুঁকিপূর্ণ হবে না, কারণ ব্লকটি তৈরি হওয়ার সময় প্রতিনিধি সম্পত্তিটির মান ক্যাপচার করা হয়, যখন এটি কার্যকর হয় তখন সন্ধান করার পরিবর্তে তাকাতে হবে। একটি পার্শ্ব প্রতিক্রিয়া হ'ল, যদি আপনি এই ব্লকটি তৈরি হওয়ার পরে প্রতিনিধি পরিবর্তন করেন তবে ব্লকটি এখনও পুরানো প্রতিনিধিকে আপডেট বার্তা প্রেরণ করবে। এটি হওয়ার সম্ভাবনা রয়েছে কিনা তা আপনার আবেদনের উপর নির্ভর করে।
এমনকি যদি আপনি সেই আচরণে শান্ত ছিলেন, আপনি এখনও নিজের ক্ষেত্রে সেই কৌশলটি ব্যবহার করতে পারবেন না:
self.dataProcessor.progress = ^(CGFloat percentComplete) {
[self.delegate myAPI:self isProcessingWithProgress:percentComplete];
};
এখানে আপনি self
পদ্ধতি কলটিতে সরাসরি প্রতিনিধিটির কাছে যাচ্ছেন, সুতরাং আপনাকে এটি কোনও জায়গায় .ুকতে হবে। ব্লকের ধরণের সংজ্ঞাটির উপরে যদি আপনার নিয়ন্ত্রণ থাকে, তবে পরামিতি হিসাবে ডেলিগেটকে ব্লকের মধ্যে স্থান দেওয়া ভাল হবে:
self.dataProcessor.progress = ^(MyDataProcessor *dp, CGFloat percentComplete) {
[dp.delegate myAPI:dp isProcessingWithProgress:percentComplete];
};
এই সমাধানটি ধরে রাখার চক্র এড়ানো এবং সর্বদা বর্তমান প্রতিনিধিকে কল করে।
আপনি যদি ব্লকটি পরিবর্তন করতে না পারেন তবে আপনি এটির সাথে ডিল করতে পারেন । একটি বজায় রাখা চক্র হ'ল সতর্কতা, ত্রুটি নয়, এটি হ'ল তারা আপনার অ্যাপ্লিকেশনটির জন্য অযথা ডুমস বানান না। যদি MyDataProcessor
ব্লক মুক্তি যখন অপারেশন সম্পূর্ণ হলে, আগে তার পিতা বা মাতা এটা মুক্তি চেষ্টা করবে সক্ষম হয়, চক্র ভাঙ্গা হবে এবং সবকিছু সঠিকভাবে পরিষ্কার করা হবে না। যদি আপনি এটি সম্পর্কে নিশ্চিত হতে পারেন, তবে সঠিক জিনিসটি #pragma
হ'ল কোডের সেই ব্লকের জন্য সতর্কতাগুলি দমন করতে একটি ব্যবহার করা উচিত । (অথবা প্রতি-ফাইল সংকলক পতাকা ব্যবহার করুন But তবে পুরো প্রকল্পের জন্য সতর্কতাটি অক্ষম করবেন না))
উপরোক্ত অনুরূপ কৌশল ব্যবহার করে আপনি কোনও রেফারেন্সকে দুর্বল বা অপ্রস্তুত ঘোষণা করে এবং ব্লকটিতে এটি ব্যবহার করতে পারেন। উদাহরণ স্বরূপ:
__weak MyDataProcessor *dp = self; // OK for iOS 5 only
__unsafe_unretained MyDataProcessor *dp = self; // OK for iOS 4.x and up
__block MyDataProcessor *dp = self; // OK if you aren't using ARC
self.progressBlock = ^(CGFloat percentComplete) {
[dp.delegate myAPI:dp isProcessingWithProgress:percentComplete];
}
উপরের তিনটিই আপনাকে ফলাফলটি ধরে না রেখে রেফারেন্স দেবে, যদিও তারা সকলেই কিছুটা আলাদাভাবে আচরণ করে: __weak
অবজেক্টটি প্রকাশিত হলে রেফারেন্সটি শূন্য করার চেষ্টা করবে; __unsafe_unretained
আপনাকে অবৈধ পয়েন্টার দিয়ে চলে যাবে; __block
প্রকৃতপক্ষে অন্য মাত্রার ইন্ডিয়ারেশন যুক্ত করবে এবং আপনাকে ব্লকের মধ্যে থেকে রেফারেন্সের মানটি পরিবর্তন করতে দেবে (এই ক্ষেত্রে অপ্রাসঙ্গিক, যেহেতু dp
অন্য কোথাও ব্যবহার করা হয়নি)।
কোন কোডটি আপনি পরিবর্তন করতে পারবেন এবং কী কী পারবেন না তার উপর সবচেয়ে ভাল নির্ভর করবে। তবে আশা করি এটি আপনাকে কীভাবে এগিয়ে যেতে হবে সে সম্পর্কে কিছু ধারণা দিয়েছে।