উদ্দেশ্য-সিতে কেবল পাঠযোগ্য সম্পত্তি?


94

আমি এইভাবে আমার ইন্টারফেসে একটি পঠনযোগ্য সম্পত্তি ঘোষণা করেছি:

 @property (readonly, nonatomic, copy) NSString* eventDomain;

হতে পারে আমি বৈশিষ্ট্যগুলি ভুল বুঝাবুঝি, কিন্তু আমি ভেবেছিলাম যে আপনি যখন এটি হিসাবে ঘোষণা করেন তখন আপনি readonlyবাস্তবায়ন ( .m) ফাইলের অভ্যন্তরে উত্পন্ন সেটারটি ব্যবহার করতে পারেন তবে বাহ্যিক সত্ত্বাগুলি মান পরিবর্তন করতে পারে না। এই এই প্রশ্নটি যা ঘটেছিল তা বলে। সেই আচরণটাই আমার পরে। যাইহোক, যখন eventDomainআমার init পদ্ধতির ভিতরে সেট করতে স্ট্যান্ডার্ড সেটার বা ডট সিনট্যাক্স ব্যবহার করার চেষ্টা করা হচ্ছে তখন এটি আমাকে একটি unrecognized selector sent to instance.ত্রুটি দেয় । অবশ্যই আমি @synthesizeসম্পত্তি আইএন। এটি এটির মতো ব্যবহার করার চেষ্টা করছেন:

 // inside one of my init methods
 [self setEventDomain:@"someString"]; // unrecognized selector sent to instance error

তাহলে আমি কি readonlyকোনও সম্পত্তির ঘোষণাকে ভুল বুঝাব? অথবা অন্য কিছু ঘটছে না?

উত্তর:


118

আপনাকে সংকলকটি বলতে হবে যে আপনিও একটি সেটার চান। একটি সাধারণ উপায় এটা করা হয় বর্গ এক্সটেনশন .m ফাইলে:

@interface YourClass ()

@property (nonatomic, copy) NSString* eventDomain;

@end

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

4
আমি লক্ষ্য করেছি যে শ্রেণীর যে বর্গের উত্তরাধিকারসূত্রে ক্লাস এক্সটেনশন বৈশিষ্ট্য রয়েছে সেগুলি তাদের দেখতে পাবে না। অর্থাৎ উত্তরাধিকার কেবলমাত্র বাহ্যিক ইন্টারফেস দেখতে পারে। নিশ্চিত?
যোগেভ শেলি

5
এটি বেশ ন্যায্য বাবু নয়। এটি ভিন্ন হতে পারে তবে এটি "নামবিহীন বিভাগ" হিসাবে পরিচিত
ম্যাক্সগ্যাব্রিয়েল

4
এটি কি পাবলিক ইন্টারফেসে অপের প্রাথমিক ঘোষণার পাশাপাশি? অর্থ, এই শ্রেণীর বর্ধন ঘোষণাপত্রটি কি প্রাথমিক ঘোষণাকে ওভাররাইড করে .h? অন্যথায় আমি দেখতে পাচ্ছি না যে এটি কীভাবে একটি সর্বজনীন সেটারটিকে প্রকাশ করবে। ধন্যবাদ
ম্যাডব্রেকস

4
@ ম্যাডব্রেকস এটি অতিরিক্ত, তবে এটি .m ফাইলের মধ্যে রয়েছে। সুতরাং সংকলকটি class শ্রেণীর জন্য এটি পাঠ্য রচনা করতে জানে, তবে বাহ্যিক ব্যবহার এখনও প্রত্যাশার মতো কেবল পাঠযোগ্যভাবে সীমাবদ্ধ।
Eiko

38

আইকো এবং অন্যরা সঠিক উত্তর দিয়েছিলেন।

এখানে একটি সহজ উপায়: সরাসরি ব্যক্তিগত সদস্যের ভেরিয়েবল অ্যাক্সেস করুন।

উদাহরণ

হেডার .h ফাইলটিতে:

@property (strong, nonatomic, readonly) NSString* foo;

এমএম ফাইল বাস্তবায়নে:

// inside one of my init methods
self->_foo = @"someString"; // Notice the underscore prefix of var name.

এটাই, এটাই আপনার দরকার। কোন ঝাঁকুনি নেই, গোলমাল নেই।

বিশদ

এক্সকোড ৪.৪ এবং এলএলভিএম সংকলক ৪.০ (এক্সকোড ৪.৪-এ নতুন বৈশিষ্ট্য ) হিসাবে, আপনার অন্যান্য উত্তরে আলোচিত কাজগুলি নিয়ে গণ্ডগোলের দরকার নেই:

  • synthesizeশব্দ
  • একটি পরিবর্তনশীল ঘোষণা
  • এম। এম ফাইল প্রয়োগের ক্ষেত্রে সম্পত্তি পুনরায় ঘোষণা করা।

সম্পত্তি ঘোষণার পরে foo , আপনি অনুমান করতে পারেন Xcode আন্ডারস্কোর একটি উপসর্গ নামে একটি বেসরকারি সদস্য পরিবর্তনশীল যোগ করেনি: _foo

সম্পত্তিটি ঘোষিত হলে readwrite, এক্সকোড নামের একটি গেটর পদ্ধতি fooএবং একটি সেটারের নাম উত্পন্ন করে setFoo। আপনি ডট স্বরলিপি ব্যবহার করার সময় এই পদ্ধতিগুলি স্পষ্টতই ডাকা হয় (আমার অবজেক্ট.মিমেদোদ)। সম্পত্তিটি ঘোষণা করা readonlyহলে কোনও সেটার উত্পন্ন হয় না। এর অর্থ আন্ডারস্কোর সহ নামকরণ করা ব্যাকিং ভেরিয়েবল না নিজেই কেবল পঠনযোগ্য। দ্যreadonly অর্থ হ'ল কোনও সেটার পদ্ধতি সংশ্লেষিত হয়নি, এবং তাই কোনও মান নির্ধারণের জন্য ডট স্বরলিপি ব্যবহার করে একটি সংকলক ত্রুটির সাথে ব্যর্থ হয়। ডট স্বরলিপি ব্যর্থ হয়েছে কারণ সংকলকটি আপনাকে অস্তিত্ব নেই এমন কোনও পদ্ধতি (সেটটার) কল করতে বাধা দেয়।

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

ব্যবহার self->করা অবজেক্ট / ইনস্ট্যান্সের সদস্য ভেরিয়েবল অ্যাক্সেস করার একটি উপায়। আপনি এটি বাদ দিতে সক্ষম হতে পারেন এবং কেবলমাত্র ভের নামটি ব্যবহার করতে পারেন। তবে আমি স্ব + তীর ব্যবহার পছন্দ করি কারণ এটি আমার কোডকে স্ব-ডকুমেন্টিং করে। আপনি যখন দেখতে পাবেন তখন self->_fooঅস্পষ্টতা ছাড়াই যা _fooএই উদাহরণে সদস্য পরিবর্তনশীল।


উপায় দ্বারা, অনুকূল এবং সরাসরি ivar এক্সেস বনাম সম্পত্তি accessors কনস আলোচনা ঠিক ড পড়ব চিন্তাশীল চিকিত্সার ধরনের ম্যাট Neuberg এর প্রোগ্রামিং আইওএস বই। আমি এটি পড়তে এবং পুনরায় পড়তে খুব সহায়ক বলে মনে করেছি।


4
সম্ভবত আপনার যুক্ত করা উচিত যে কোনও ব্যক্তির সরাসরি কোনও সদস্যের পরিবর্তনশীল অ্যাক্সেস করা উচিত নয় (তার শ্রেণি ছাড়াই)! এটি করা ওওপি (তথ্য গোপন করা) লঙ্ঘন।
রয়েছে

4
@ এইচএস সঠিক, এখানকার পরিস্থিতিটি ব্যক্তিগতভাবে সদস্য শ্রেণীর স্থির করে দিচ্ছে যা এই শ্রেণীর বাইরে থেকে দেখা যায় না। যে মূল পোস্টার প্রশ্নের সমগ্র বিন্দু: যেমন একটি সম্পত্তি ঘোষণা readonlyযাতে কোন অন্য বর্গ এটা সেট করতে পারেন।
বাসিল বাউরক

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

@ বাসিলবার্ক "দৃistence়তা" প্রশ্নে সহায়ক সম্পাদনার জন্য আপনাকে অনেক ধন্যবাদ!
ঘোস্টটিক

36

পঠনযোগ্য বৈশিষ্ট্যগুলির সাথে কাজ করার জন্য আমি অন্য উপায়টি হ'ল ব্যাকিং স্টোর নির্দিষ্ট করার জন্য @ সায়েন্টেসাইজ ব্যবহার করা। উদাহরণ স্বরূপ

@interface MyClass

@property (readonly) int whatever;

@end

তারপরে বাস্তবায়নে

@implementation MyClass

@synthesize whatever = m_whatever;

@end

আপনার পদ্ধতিগুলি তখন সেট করতে পারে m_whatever, কারণ এটি সদস্যের পরিবর্তনশীল।


গত কয়েকদিনে আমি আরও একটি আকর্ষণীয় জিনিস বুঝতে পেরেছি যে আপনি কেবল পাঠযোগ্য বৈশিষ্ট্যগুলি তৈরি করতে পারেন যা সাবক্লাসগুলির দ্বারা লিখিতযোগ্য যেমন:

(শিরোলেখ ফাইলটিতে)

@interface MyClass
{
    @protected
    int m_propertyBackingStore;
}

@property (readonly) int myProperty;

@end

তারপরে, বাস্তবায়নে

@synthesize myProperty = m_propertyBackingStore;

এটি শিরোনাম ফাইলটিতে ঘোষণাপত্রটি ব্যবহার করবে, সুতরাং সাবক্লাসগুলি তার পাঠ্যতা বজায় রেখে সম্পত্তিটির মান আপডেট করতে পারে।

যদিও ডেটা লুকানো এবং এনক্যাপসুলেশনের ক্ষেত্রে সামান্য আফসোস।


4
আপনি বর্ণিত প্রথম উপায়ে গ্রহণযোগ্য উত্তরের চেয়ে লেনদেন করা সহজ। কেবলমাত্র একটি "@ সন্নিবেশিত foo1, foo2, foo3;" .m এ, এবং সব ভাল।
sudo

20

আইওএস ডক্সে বিদ্যমান শ্রেণিগুলি অনুকূলিতকরণ দেখুন ।

পঠনযোগ্য ইঙ্গিত করে যে সম্পত্তিটি কেবল পঠনযোগ্য। আপনি যদি কেবল পঠনযোগ্য নির্দিষ্ট করে থাকেন তবে @ সংকরণে কেবলমাত্র একটি গিটার পদ্ধতি প্রয়োজন। আপনি যদি বাস্তবায়ন ব্লকে @ সংশ্লেষ ব্যবহার করেন তবে কেবলমাত্র প্রাপ্তির পদ্ধতিটি সংশ্লেষিত হবে। তদতিরিক্ত, আপনি যদি বিন্দু সিনট্যাক্স ব্যবহার করে কোনও মান নির্ধারণের চেষ্টা করেন তবে আপনি একটি সংকলক ত্রুটি পাবেন।

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


9

আপনি অন্য প্রশ্নের ভুল বোঝাবুঝি করছেন। এই প্রশ্নে এখানে শ্রেণিবদ্ধকরণ রয়েছে, যা ঘোষণা করা হয়েছে:

@interface MYShapeEditorDocument ()
@property (readwrite, copy) NSArray *shapesInOrderBackToFront;
@end

সেটাই ক্লাসের প্রয়োগের মধ্যে কেবল সেটারটি দৃশ্যমান। তাই যেমন ইকো বলেছেন, আপনাকে ক্লাসের সম্প্রসারণের ঘোষণা করতে হবে এবং সংজ্ঞাদাতাকে কেবল শ্রেণীর মধ্যেই একটি সেটার উত্পন্ন করতে বলতে সম্পত্তি সম্পত্তি ঘোষণাকে ওভাররাইড করতে হবে।


5

সবচেয়ে সংক্ষিপ্ত সমাধানটি হ'ল:

মাইক্লাস

@interface MyClass {

  int myProperty;

}

@property (readonly) int myProperty;

@end

মাইক্লাস

@implementation MyClass

@synthesize myProperty;

@end

2

যদি কোনও সম্পত্তি কেবলমাত্র পাঠ্য হিসাবে সংজ্ঞায়িত করা হয় তবে এর অর্থ হ'ল কার্যকরভাবে কোনও সেটার হবে যা শ্রেণিতে অভ্যন্তরীণভাবে বা অন্য শ্রেণীর বাইরের থেকে ব্যবহার করা যেতে পারে। (উদাহরণস্বরূপ: যদি আপনি তা বোঝাতে পারেন তবে আপনার কেবল "গেটর" থাকবে))

এর শব্দগুলি থেকে আপনি একটি সাধারণ পঠন / লেখার সম্পত্তিটি ব্যক্তিগত হিসাবে চিহ্নিত করতে চান যা আপনার ইন্টারফেস ফাইলটিতে শ্রেণি ভেরিয়েবলটিকে ব্যক্তিগত হিসাবে সেট করে আপনি অর্জন করতে পারেন:

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