একটি পদ্ধতি থেকে নতুন তৈরি করা অবজেক্ট ফেরত দেওয়ার জন্য অটোরলেজ পুলগুলির প্রয়োজন। যেমন কোড এই টুকরা বিবেচনা:
- (NSString *)messageOfTheDay {
return [[NSString alloc] initWithFormat:@"Hello %@!", self.username];
}
পদ্ধতিতে তৈরি স্ট্রিংটির একটির একটি ধরে রাখা গণনা থাকবে। এখন কে মুক্তির সাথে এই গণনা বজায় রাখবে?
পদ্ধতি নিজেই? সম্ভব নয়, এটি তৈরি করা বস্তুটি ফিরিয়ে দিতে হবে, সুতরাং এটি ফিরে আসার আগে এটি প্রকাশ করা উচিত নয়।
পদ্ধতিটির আহ্বায়ক? কলার কোনও অবজেক্টের পুনরুদ্ধার করার প্রত্যাশা রাখে না যার মুক্তি প্রয়োজন, পদ্ধতির নামটি বোঝায় না যে কোনও নতুন অবজেক্ট তৈরি হয়েছে, কেবল এটি বলে যে কোনও বস্তু ফিরে এসেছে এবং এই প্রত্যাবর্তিত অবজেক্টটি নতুন হতে পারে একটি রিলিজের প্রয়োজন তবে এটি হতে পারে ভাল একটি বিদ্যমান এক না যে না। পদ্ধতিটি কী ফিরিয়ে দেয় তা এমনকি কিছু অভ্যন্তরীণ অবস্থার উপরও নির্ভর করতে পারে, সুতরাং কলার জানতে পারে না যে এটি object বস্তুটি ছেড়ে দিতে হবে এবং এটির যত্ন নেওয়া উচিত নয়।
যদি ফোনকারীকে সর্বদা কনভেনশনের মাধ্যমে ফিরে আসা সমস্ত অবজেক্ট প্রকাশ করতে হয়, তবে নতুনভাবে তৈরি হওয়া প্রতিটি বস্তুটি কোনও পদ্ধতি থেকে ফিরে আসার আগে সর্বদা তা ধরে রাখতে হবে এবং যদি এটি সুযোগের বাইরে চলে যায় তবে এটি কলারের দ্বারা ছেড়ে দেওয়া উচিত, যদি না এটি আবার ফিরে আসে। এটি অনেক ক্ষেত্রে অত্যন্ত অদক্ষ হতে পারে কারণ কলার সর্বদা ফিরে আসা অবজেক্টটি প্রকাশ না করলে অনেক ক্ষেত্রে রক্ষণ গণনাগুলি পরিবর্তন করা সম্পূর্ণভাবে এড়ানো যায় can
এজন্য সেখানে অটোরিলেজ পুল রয়েছে, সুতরাং প্রথম পদ্ধতিটি বাস্তবে পরিণত হবে
- (NSString *)messageOfTheDay {
NSString * res = [[NSString alloc] initWithFormat:@"Hello %@!", self.username];
return [res autorelease];
}
autorelease
কোনও বস্তুতে কল করা এটি অটোরিলিজ পুলে যুক্ত করে, তবে এর অর্থ কী? ঠিক আছে, এটির অর্থ আপনার সিস্টেমকে বলার অর্থ " আমি চাই যে আপনি আমার জন্য সেই বস্তুটি মুক্তি দিন তবে পরবর্তী সময়ে এখন নয়; এটির একটি পুনরুদ্ধার দ্বারা ভারসাম্য বজায় রাখা দরকার অন্যথায় স্মৃতি ফাঁস হবে তবে আমি নিজেই এটি করতে পারি না এই মুহুর্তে, যেহেতু আমার বর্তমান সুযোগ ছাড়িয়ে বেঁচে থাকার জন্য আমার প্রয়োজন হবে এবং আমার কলকারী আমার পক্ষে এটিও করবে না, এটি করার দরকার নেই এর কোনও জ্ঞান নেই So সুতরাং এটি আপনার পুলটিতে যুক্ত করুন এবং একবার আপনি এটি পরিষ্কার করে ফেলুন once পুল, আমার জন্য আমার উদ্দেশ্য পরিষ্কার করুন। "
এআরসি দিয়ে কম্পাইলার আপনার জন্য সিদ্ধান্ত নেয় কখন কোন বস্তু ধরে রাখা যায়, কখন কোন বস্তুটি প্রকাশ করা যায় এবং কখন এটি একটি স্বতঃগ্রহীতা পুলে যুক্ত করা হয় তবে এখনও স্মৃতি ফাঁস না করে পদ্ধতিতে নতুনভাবে নির্মিত বস্তুগুলিকে ফিরিয়ে দিতে সক্ষম হওয়ার জন্য এটি অটোরলেজ পুলের উপস্থিতি প্রয়োজন। অ্যাপল জেনারেটড কোডটিতে সবেমাত্র কিছু নিফটি অপ্টিমাইজেশন করেছে যা কখনও কখনও রানটাইম চলাকালীন অটোরলেজ পুলগুলি মুছে ফেলবে। এই অপ্টিমাইজেশনের প্রয়োজন হয় যে, কলার এবং কলি উভয়ই এআরসি ব্যবহার করছেন (মনে রাখবেন এআরসি এবং নন-এআরসি মিশ্রণ আইনী এবং আনুষ্ঠানিকভাবে সমর্থনযোগ্য) এবং যদি বাস্তবে এটি ঘটে তবে কেবল রানটাইমেই জানা যায়।
এই আরসি কোডটি বিবেচনা করুন:
// Callee
- (SomeObject *)getSomeObject {
return [[SomeObject alloc] init];
}
// Caller
SomeObject * obj = [self getSomeObject];
[obj doStuff];
সিস্টেমটি যে কোডটি উত্পন্ন করে, তা নিম্নলিখিত কোডগুলির মতো আচরণ করতে পারে (এটি নিরাপদ সংস্করণ যা আপনাকে নিখরচায় এআরসি এবং নন-এআরসি কোডের মিশ্রণ করতে দেয়):
// Callee
- (SomeObject *)getSomeObject {
return [[[SomeObject alloc] init] autorelease];
}
// Caller
SomeObject * obj = [[self getSomeObject] retain];
[obj doStuff];
[obj release];
(কলারে থাকা রক্ষণ / রিলিজটি কেবল একটি প্রতিরক্ষামূলক সুরক্ষা বজায় রাখা দরকার, এটি কঠোরভাবে প্রয়োজন হয় না, কোডটি ছাড়াই পুরোপুরি সঠিক হবে)
বা এটি রান কোডের সময় এআরসি ব্যবহার করার জন্য উভয়কেই সনাক্ত করা যায় সে ক্ষেত্রে এটি এই কোডটির মতো আচরণ করতে পারে:
// Callee
- (SomeObject *)getSomeObject {
return [[SomeObject alloc] init];
}
// Caller
SomeObject * obj = [self getSomeObject];
[obj doStuff];
[obj release];
আপনি দেখতে পাচ্ছেন, অ্যাপল অ্যাটোরোলিলিজকে সরিয়ে দেয়, এভাবে পুলটি নষ্ট হয়ে যাওয়ার পরে বিলম্বিত বস্তু প্রকাশের পাশাপাশি সুরক্ষা বজায় রাখে। কীভাবে এটি সম্ভব এবং পর্দার আড়ালে আসলে কী চলছে সে সম্পর্কে আরও জানতে, এই ব্লগ পোস্টটি দেখুন।
এখন আসল প্রশ্ন: কেন একটি ব্যবহার করবে @autoreleasepool
?
বেশিরভাগ বিকাশকারীদের জন্য, এই কোডটি তাদের কোডটিতে ব্যবহারের জন্য কেবল একটি কারণ বাকি আছে এবং তা হল প্রযোজ্য যেখানে মেমরির পদচিহ্নগুলি ছোট রাখা। যেমন এই লুপ বিবেচনা:
for (int i = 0; i < 1000000; i++) {
// ... code ...
TempObject * to = [TempObject tempObjectForData:...];
// ... do something with to ...
}
ধরে নিন যে প্রতিটি কল tempObjectForData
একটি নতুন তৈরি করতে পারেTempObject
কলই যা স্বতঃপ্রণোদিতভাবে ফিরে আসে। লুপটি এই টেম্পোর অবজেক্টগুলির এক মিলিয়ন তৈরি করবে যা সমস্ত বর্তমান অটোরিলেপপুলে সংগ্রহ করা হয় এবং কেবল একবার পুলটি ধ্বংস হয়ে গেলে সমস্ত টেম্পের অবজেক্টগুলিও ধ্বংস হয়ে যায়। যতক্ষণ না ঘটে ততক্ষণ আপনার কাছে মেমরির মধ্যে এই এক মিলিয়ন টেম্পের জিনিস রয়েছে।
আপনি যদি এর পরিবর্তে কোডটি লিখেন:
for (int i = 0; i < 1000000; i++) @autoreleasepool {
// ... code ...
TempObject * to = [TempObject tempObjectForData:...];
// ... do something with to ...
}
তারপরে ফর-লুপটি চলার সময় একটি নতুন পুল তৈরি হয় এবং প্রতিটি লুপ পুনরাবৃত্তির শেষে ধ্বংস হয়। লুপটি দশ মিলিয়ন বার চালানো সত্ত্বেও সর্বাধিক একটি টেম্পের অবজেক্ট যেকোন সময় স্মৃতিতে ঝুলতে থাকে।
অতীতে, থ্রেডগুলি পরিচালনা করার সময় নিজেকে প্রায়শই অটোরিলেজপুলগুলি পরিচালনা করতে হত (যেমন ব্যবহার করা NSThread
) কেবল মূল থ্রেডে স্বয়ংক্রিয়ভাবে একটি কোকো / ইউআইকিট অ্যাপ্লিকেশনটির জন্য একটি অটোরিলেজ পুল রয়েছে। তবুও এটি আজ অনেক উত্তরাধিকার হিসাবে সম্ভবত আপনি শুরু করতে থ্রেড ব্যবহার করবেন না। আপনি জিসিডি DispatchQueue
বা এর ব্যবহার করতেন NSOperationQueue
এবং এই দু'টিই আপনার জন্য একটি শীর্ষ স্তরের অটোরলেজ পুল পরিচালনা করে যা একটি ব্লক / টাস্ক চালানোর আগে তৈরি হয়েছিল এবং এটির সাথে একবার হয়ে গেলে এটি ধ্বংস হয়ে যায়।