এনএসবজেক্ট + লোড করুন এবং + আরম্ভ করুন - তারা কী করে?


115

আমি বিকাশকারীকে + আরম্ভকরণ বা + লোডকে ওভাররাইড করতে নেতৃত্বদানকারী পরিস্থিতিগুলি বুঝতে আগ্রহী। ডকুমেন্টেশন এটিকে পরিষ্কার করে দেয় যে উদ্দেশ্যগুলি-সি রানটাইম দ্বারা এই পদ্ধতিগুলি আপনার জন্য ডেকে আনা হয়েছে, তবে এই সমস্ত পদ্ধতির ডকুমেন্টেশন থেকে এটি পরিষ্কার clear :-)

আমার কৌতূহল অ্যাপল এর উদাহরণ কোড - এমভিসি নেটওয়ার্কিং এ দেখে আসে। তাদের মডেল শ্রেণির একটি +(void) applicationStartupপদ্ধতি রয়েছে। এটি ফাইল সিস্টেমে কিছুটা বাড়ির রক্ষণাবেক্ষণ করে, এনএসডিফাল্টস ইত্যাদি পড়েন ... এবং, এনএসবজেক্টের শ্রেণিবদ্ধ পদ্ধতিগুলি ছাঁটাই করার চেষ্টা করার পরে, মনে হচ্ছে এই দরদামীর কাজটি + বোঝায় রাখা ঠিক হবে।

আমি এমভিসি নেটওয়ার্কিং প্রকল্পটি সংশোধন করেছি, অ্যাপ ডেলিগেটে কলটি + অ্যাপ্লিকেশন স্টার্টআপে সরিয়ে দিয়েছি এবং গৃহকর্তী বিটগুলি + লোডে রেখেছি ... আমার কম্পিউটারে আগুন লাগেনি, তবে এর অর্থ এটি সঠিক নয়! আমি যে কোনও সূক্ষ্মতা, গোটচগুলি এবং কাস্টম সেটআপ পদ্ধতির কাছাকাছি যেগুলি আপনাকে বনাম + লোড বা + আরম্ভ করতে হবে কল করতে হবে তা বোঝার আশা করছি।


জন্য + লোড ডকুমেন্টেশন বলেছেন:

লোড বার্তাটি ক্লাস এবং বিভাগগুলিতে প্রেরণ করা হয় যা উভয়ই গতিশীল লোড এবং স্থিতিশীলভাবে সংযুক্ত, তবে কেবলমাত্র নতুন বোঝা শ্রেণি বা বিভাগ যদি এমন কোনও পদ্ধতি প্রয়োগ করে যা প্রতিক্রিয়া জানাতে পারে।

আপনি যদি সমস্ত শব্দের সুনির্দিষ্ট অর্থ না জানেন তবে এই বাক্যটি কালডজে এবং পার্স করা কঠিন। সাহায্য করুন!

  • "গতিশীল লোড এবং স্থিতিশীলভাবে সংযুক্ত উভয়" বলতে কী বোঝায়? কিছু গতিশীলভাবে লোড করা এবং স্থিতিশীলভাবে সংযুক্ত করা যেতে পারে, বা তারা পারস্পরিক একচেটিয়া?

  • "... নতুন লোড হওয়া শ্রেণি বা বিভাগটি এমন একটি পদ্ধতি প্রয়োগ করে যা প্রতিক্রিয়া জানাতে পারে" কোন পদ্ধতি? কীভাবে সাড়া দিন?


ইনিশিয়ালাইজেশন হিসাবে, ডকুমেন্টেশনগুলি বলে:

ইনিশিয়েল করুন এটি প্রতি ক্লাসে একবারই ডাকা হবে। আপনি যদি ক্লাসের জন্য এবং শ্রেণীর বিভাগগুলির জন্য স্বতন্ত্র সূচনা করতে চান তবে আপনার বোঝা পদ্ধতিগুলি প্রয়োগ করা উচিত।

আমি এটি বোঝাতে চাইছি, "আপনি যদি ক্লাসটি সেটআপ করার চেষ্টা করছেন ... আরম্ভ করা ব্যবহার করবেন না।" ঠিক আছে ভালো. কখন বা কেন আমি তখন আরম্ভ হবে ওভাররাইড?

উত্তর:


184

loadবার্তা

রানটাইম loadপ্রতিটি শ্রেণীর অবজেক্টে বার্তা প্রেরণ করে , খুব শীঘ্রই প্রক্রিয়াটির ঠিকানা স্পেসে শ্রেণীর অবজেক্টটি লোড হয়। যে ক্লাসগুলি প্রোগ্রামের এক্সিকিউটেবল ফাইলের অংশ, তাদের জন্য রানটাইম loadপ্রক্রিয়াটির জীবদ্দশায় খুব শীঘ্রই বার্তাটি প্রেরণ করে । ভাগ করা (গতিশীল-লোড) লাইব্রেরিতে থাকা ক্লাসগুলির জন্য, রানটাইম ভাগ করা লাইব্রেরি প্রক্রিয়াটির ঠিকানার জায়গাতে লোড হওয়ার ঠিক পরে লোড বার্তা প্রেরণ করে।

তদুপরি, রানটাইম কেবলমাত্র loadএকটি শ্রেণীর অবজেক্টে প্রেরণ করে যদি সেই শ্রেণি অবজেক্ট নিজেই loadপদ্ধতিটি প্রয়োগ করে । উদাহরণ:

@interface Superclass : NSObject
@end

@interface Subclass : Superclass
@end

@implementation Superclass

+ (void)load {
    NSLog(@"in Superclass load");
}

@end

@implementation Subclass

// ... load not implemented in this class

@end

রানটাইম ক্লাস অবজেক্টে loadবার্তা প্রেরণ করে Superclass। এটি ক্লাস অবজেক্টে বার্তাটি প্রেরণ করে না , যদিও পদ্ধতিটি উত্তরাধিকার সূত্রে প্রাপ্ত ।loadSubclassSubclassSuperclass

loadক্লাসের loadসমস্ত সুপারক্লাস অবজেক্টগুলিতে (যদি সেই সুপারক্লাস অবজেক্টগুলি বাস্তবায়িত হয় load) এবং ভাগ করা লাইব্রেরিতে আপনার লিঙ্ক করা সমস্ত শ্রেণীর অবজেক্টগুলিতে বার্তা প্রেরণের পরে রানটাইম ক্লাস অবজেক্টে বার্তা পাঠায় । কিন্তু আপনি জানেন না যে আপনার নিজস্ব নির্বাহযোগ্য অন্যান্য ক্লাসগুলি loadএখনও পেয়েছে ।

আপনার প্রক্রিয়া তার ঠিকানা জায়গাতে লোড করে এমন প্রতিটি শ্রেণি একটি loadবার্তা গ্রহণ করবে , যদি এটি loadপদ্ধতিটি প্রয়োগ করে তবে আপনার প্রক্রিয়া শ্রেণীর অন্য কোনও ব্যবহার করে কিনা তা নির্বিশেষে।

আপনি দেখতে পারেন কিভাবে রানটাইম আপ দেখায় loadএকটি বিশেষ কেস হিসাবে পদ্ধতি _class_getLoadMethodএর objc-runtime-new.mm, এবং থেকে সরাসরি এটি কল call_class_loadsমধ্যে objc-loadmethod.mm

রানটাইম loadএকই শ্রেণীর বেশ কয়েকটি বিভাগ বাস্তবায়িত হলেও, এটি লোড হওয়া প্রতিটি বিভাগের পদ্ধতিও চালায় load। এটি অস্বাভাবিক। সাধারণত, যদি দুটি বিভাগ একই শ্রেণিতে একই পদ্ধতিটি সংজ্ঞায়িত করে, তবে একটি পদ্ধতির একটি "জয়" করবে এবং ব্যবহৃত হবে এবং অন্য পদ্ধতিটি কখনই ডাকা হবে না।

initializeপদ্ধতি

রানটাইম ক্লাস অবজেক্টে বা ক্লাসের কোনও উদাহরণে initializeপ্রথম বার্তা ( loadবা ব্যতীত initialize) প্রেরণের ঠিক আগে ক্লাস অবজেক্টে পদ্ধতিটি কল করে । এই বার্তাটি সাধারণ প্রক্রিয়া ব্যবহার করে প্রেরণ করা হয়েছে, সুতরাং যদি আপনার শ্রেণিটি প্রয়োগ না করে initializeতবে ক্লাস থেকে উত্তরাধিকার সূত্রে আসে তবে আপনার শ্রেণি তার সুপারক্লাসটি ব্যবহার করবে initialize। রানটাইম initializeক্লাসের সমস্ত সুপারক্লাসগুলিতে প্রথমে পাঠিয়ে দেবে (যদি সুপারক্লাস ইতিমধ্যে প্রেরণ করা না থাকে initialize)।

উদাহরণ:

@interface Superclass : NSObject
@end

@interface Subclass : Superclass
@end

@implementation Superclass

+ (void)initialize {
    NSLog(@"in Superclass initialize; self = %@", self);
}

@end

@implementation Subclass

// ... initialize not implemented in this class

@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        Subclass *object = [[Subclass alloc] init];
    }
    return 0;
}

এই প্রোগ্রামটি আউটপুট দুটি লাইন প্রিন্ট করে:

2012-11-10 16:18:38.984 testApp[7498:c07] in Superclass initialize; self = Superclass
2012-11-10 16:18:38.987 testApp[7498:c07] in Superclass initialize; self = Subclass

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

বাস্তবায়নের আধ্যাত্মিক উপায় initializeহ'ল:

@implementation Someclass

+ (void)initialize {
    if (self == [Someclass class]) {
        // do whatever
    }
}

এই প্যাটার্নটির মূল বিষয় হ'ল Someclassযখন এটির একটি সাবক্লাস রয়েছে যা বাস্তবায়ন করে না তখন নিজেকে পুনরায় আরম্ভ করা এড়ানো initialize

রানটাইমটি initializeইন _class_initializeফাংশনে বার্তা প্রেরণ করে objc-initialize.mm। আপনি দেখতে পাচ্ছেন যে এটি objc_msgSendপ্রেরণে এটি ব্যবহার করে, এটি সাধারণ বার্তা প্রেরণার ফাংশন।

আরও পড়া

পরীক্ষা করে দেখুন মাইক অ্যাশ এর শুক্রবার Q & A- এই বিষয়ে।


25
আপনার লক্ষ্য করা উচিত যে +loadবিভাগগুলির জন্য পৃথকভাবে প্রেরণ করা হয়েছে; অর্থাৎ শ্রেণীর প্রতিটি বিভাগে নিজস্ব +loadপদ্ধতি থাকতে পারে ।
জোনাথন গ্রিনস্পান

1
এও নোট করুন যে অবিচ্ছিন্ন সত্তার বিষয়ে উল্লেখ করার কারণে, প্রয়োজনে initializeকোনও loadপদ্ধতি দ্বারা সঠিকভাবে ডাকা হবে load। এটি (অদ্ভুতভাবে, তবে সংবেদনশীলভাবে) initializeআগে দৌড়াতে পারে load! যাই হোক না কেন আমি পর্যবেক্ষণ করেছি। এটি "এবং আপনি গ্রহণের সময়কালে initialize, আপনার প্রক্রিয়াটির প্রতিটি শ্রেণি ইতিমধ্যে load(যথাযথ হলে) প্রাপ্ত হওয়া উচিত ছিল ।"
বেনজহান

5
আপনি loadপ্রথম পাবেন । আপনি এখনও চলমান initializeঅবস্থায় পেতে পারেন load
রব মায়ফ

1
@ আরবমায়ফকে কি আমাদের [সুপার ইনিশিয়ালাইজ] এবং [সুপার লোড] লাইনগুলি যুক্ত পদ্ধতিগুলির মধ্যে যুক্ত করার দরকার নেই?
দামিথ

1
এটি সাধারণত একটি খারাপ ধারণা, কারণ রানটাইম ইতিমধ্যে সেগুলি আপনার কাছে পাঠানোর আগেই এই দুটি বার্তা আপনার সমস্ত সুপার ক্লাসে পাঠিয়েছে।
রব মায়ফ

17

এর অর্থ যা +initializeকোনও বিভাগে ওভাররাইড করা হয় না , আপনি সম্ভবত কিছু ভেঙে ফেলেন।

+loadপ্রতি বর্গ বা বিভাগের যে কার্যকরী একবার বলা হয় +load, যত তাড়াতাড়ি যে বর্গ বা বিভাগের লোড করা হয়। যখন এটি "স্ট্যাটিকালি লিঙ্কড" বলবে এর অর্থ আপনার অ্যাপ্লিকেশন বাইনারিতে সংকলিত। +loadযখন আপনার অ্যাপ্লিকেশন লঞ্চ, সম্ভবত আগেই প্রবেশ এইভাবে কম্পাইল শ্রেণীর উপর পদ্ধতি মৃত্যুদন্ড কার্যকর করা হবে main()। যখন এটি "গতিশীল লোডযুক্ত" বলে, এর অর্থ প্লাগইন বান্ডিলগুলি বা একটি কলের মাধ্যমে লোড dlopen()। আপনি যদি আইওএস এ থাকেন তবে আপনি সেই ক্ষেত্রে উপেক্ষা করতে পারেন।

+initializeএই বার্তাটি পরিচালনা করার ঠিক আগে ক্লাসে কোনও বার্তা পাঠানো প্রথমবার বলে। এটি (স্পষ্টতই) কেবল একবার হয়। আপনি যদি +initializeকোনও বিভাগে ওভাররাইড করেন তবে তিনটি জিনিসের একটি ঘটবে:

  • আপনার বিভাগ বাস্তবায়ন ডাকা হয় এবং শ্রেণীর বাস্তবায়ন হয় না
  • অন্য কারও বিভাগের বাস্তবায়ন বলা হয়; আপনি লিখেছেন কিছুই না
  • আপনার বিভাগটি এখনও লোড করা হয়নি এবং এর বাস্তবায়ন কখনও কল করা হয় না।

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

বিটিডাব্লু, অন্য একটি বিষয় বিবেচনা করুন +initializeতা হ'ল যদি কেউ আপনাকে সাবক্ল্যাস করে তবে আপনি সম্ভবত আপনার ক্লাসের জন্য একবার এবং প্রতিটি সাবক্লাসের জন্য একবার ডাকবেন। আপনি যদি staticভেরিয়েবল সেট আপ করার মতো কিছু করেন তবে আপনি তার বিরুদ্ধে রক্ষা করতে চাই: হয় dispatch_once()বা পরীক্ষার মাধ্যমে self == [MyClass class]

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