অবজেক্টিভ-সি-তে আমি শ্রেণি-স্তরের বৈশিষ্ট্যগুলি কীভাবে ঘোষণা করব?


205

হতে পারে এটি সুস্পষ্ট, তবে আমি জানি না কীভাবে উদ্দেশ্য-সি-তে শ্রেণীর সম্পত্তি ঘোষণা করা যায়।

আমার প্রতি ক্লাসে একটি অভিধানে ক্যাশ করা দরকার এবং এটি কীভাবে ক্লাসে রাখা যায় তা ভাবতে হবে।

উত্তর:


190

উদ্দেশ্য-সিতে বৈশিষ্ট্যের একটি নির্দিষ্ট অর্থ রয়েছে তবে আমি মনে করি যে আপনি এমন কিছু বোঝাচ্ছেন যা একটি স্ট্যাটিক ভেরিয়েবলের সমতুল্য? যেমন ফু সব ধরণের জন্য শুধুমাত্র একটি উদাহরণ?

অবজেক্টিভ-সি-তে শ্রেণীর কার্যাবলী ঘোষণা করতে আপনি এর পরিবর্তে + উপসর্গটি ব্যবহার করেন - সুতরাং আপনার প্রয়োগটি এমন কিছু দেখাচ্ছে:

// Foo.h
@interface Foo {
}

+ (NSDictionary *)dictionary;

// Foo.m
+ (NSDictionary *)dictionary {
  static NSDictionary *fooDict = nil;
  if (fooDict == nil) {
    // create dict
  }
  return fooDict;
}

23
এটা কী ঠিক? অভিধান পদ্ধতির প্রথম লাইনটি সর্বদা প্রতিবারই অভিধানটিকে পুনঃনির্মাণ করার ফলস্বরূপ fooDict সেট করবে না?
পাপিলনউকে


59
লাইন স্থিতিশীল এনএসডি অভিধান * fooDict = শূন্য; শুধুমাত্র একবার মৃত্যুদন্ড কার্যকর করা হবে! এমনকি একাধিকবার বলা পদ্ধতিতে, কীওয়ার্ড স্ট্যাটিকের সাথে ঘোষণাপত্রটি (এবং এই উদাহরণটিতে সূচনাও দেওয়া হয়) যদি এই নামের সাথে কোনও স্থির পরিবর্তনশীল উপস্থিত থাকে তবে তা উপেক্ষা করা হবে।
বাইনারি

3
@ বেনসি.আর. লেগিগেরো হ্যাঁ, একেবারে। .-Accessor সিনট্যাক্স উদ্দেশ্য সি এ সম্পত্তি বাঁধা নয়, এটা শুধু একটা কম্পাইল-ইন শর্টকাট কোনো পদ্ধতির জন্য যে কোনো args গ্রহণ ছাড়াই আয় কিছু। এই ক্ষেত্রে আমি এটি পছন্দ করবো- .ক্লায়েন্ট কোডটি কোনও কিছু পেতে চায়, কোনও ক্রিয়া সম্পাদন করে না (এমনকি বাস্তবায়ন কোডটি একবারে কিছু তৈরি করতে পারে বা পার্শ্ব-প্রতিক্রিয়া ক্রিয়াকলাপ সম্পাদন করে) এমন কোনও ব্যবহারের জন্য আমি ব্যক্তিগতভাবে বাক্য গঠন পছন্দ করি । ভারী ব্যবহারের .সিনট্যাক্সের ফলে আরও পঠনযোগ্য কোডও পাওয়া যায়: […]ফেচগুলি .পরিবর্তে সিনট্যাক্স ব্যবহার করার সময় এর উপস্থিতি অর্থের কিছু গুরুত্বপূর্ণ হয়ে ওঠে ।
স্লিপ ডি থম্পসন

4
অ্যালেক্স নোলাস্কো এর উত্তর কটাক্ষপাত আছে, বর্গ বৈশিষ্ট্য Xcode 8 মুক্তির পর পাওয়া যায়: stackoverflow.com/a/37849467/6666611
n3wbie

112

আমি এই সমাধানটি ব্যবহার করছি:

@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end

@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end

এবং আমি এটি সিঙ্গলটন প্যাটার্নের প্রতিস্থাপন হিসাবে অত্যন্ত দরকারী বলে মনে করি।

এটি ব্যবহার করতে, ডট স্বরলিপি দিয়ে কেবল আপনার ডেটা অ্যাক্সেস করুন:

Model.value = 1;
NSLog(@"%d = value", Model.value);

3
এটা সত্যিই দুর্দান্ত। কিন্তু পৃথিবীতে selfশ্রেণিক পদ্ধতির অভ্যন্তরের অর্থ কী?
টড লেহম্যান


6
কেন দরকার হবে @synchronized?
ম্যাট ক্যান্টোর

1
এটি আসলে বেশ দুর্দান্ত যে এটি কাজ করে। আপনি নিজের শ্রেণীর স্তরের বৈশিষ্ট্যগুলি সত্যিকারের মতো কাজ করতে পারেন। আমি অনুমান করি যে স্বয়ংসম্পূর্ণ সিঙ্ক্রোনাইজ করা আপনার সম্পত্তি ঘোষণায় 'পারমাণবিক' ব্যবহারের সমতুল্য এবং যদি আপনি 'নন্যাটমিক' সংস্করণ চান তবে বাদ দেওয়া যেতে পারে? এছাড়াও আমি আপেল দ্বারা ডিফল্ট হিসাবে '_' দিয়ে ব্যাকিং ভেরিয়েবলের নামকরণ বিবেচনা করব এবং গেটার / সেটার থেকে সেলফের মূল্য স্থিত করে / সেট করার পরেও পাঠযোগ্যতার উন্নতি করাই অসীম পুনরাবৃত্তি ঘটায়। আমার মতে এটি সঠিক উত্তর।
পিটার Segerblom

3
এটি দুর্দান্ত, তবে ... 10 লাইন কোডের জন্য কেবল 1 স্থির সদস্য তৈরি করতে হবে? কি হ্যাক। অ্যাপলকে এটিকে কেবল একটি বৈশিষ্ট্য তৈরি করা উচিত।
জন হেন্কেল

92

যেমনটি ডাব্লুডাব্লুডিসি 2016 / এক্সকোড 8 তে দেখা গেছে ( এলএলভিএম অধিবেশন @ 5: 05 এ নতুন কী ) শ্রেণীর বৈশিষ্ট্যগুলি নীচে ঘোষণা করা যেতে পারে

@interface MyType : NSObject
@property (class) NSString *someString;
@end

NSLog(@"format string %@", MyType.someString);

নোট করুন যে শ্রেণীর বৈশিষ্ট্যগুলি কখনই সংশ্লেষিত হয় না

@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end

8
এটি সম্ভবত স্পষ্ট করে দেওয়া উচিত যে এটি কেবলমাত্র অ্যাকসেসর ঘোষণার জন্য চিনি। যেমনটি আপনি উল্লেখ করেছেন, সম্পত্তিটি সংশ্লেষিত নয়: ক ( staticপরিবর্তনশীল) এখনও ঘোষিত এবং ব্যবহার করতে হবে এবং পদ্ধতিগুলি যেমন তারা আগে ছিল তেমন স্পষ্টভাবে প্রয়োগ করা হয়েছে। ডট সিনট্যাক্স ইতিমধ্যে ইতিমধ্যে কাজ করেছে। সর্বোপরি, এটি সত্যের চেয়ে বড় চুক্তির মতো মনে হচ্ছে।
jscs

6
বড় ব্যাপারটি হ'ল এর অর্থ হ'ল আপনি () ব্যবহার না করেই সুইফট কোড থেকে সিঙ্গলেটগুলি অ্যাক্সেস করতে পারেন এবং প্রত্যয়টি প্রকারটি কনভেনশন দ্বারা মুছে ফেলা হয়েছে। উদাহরণস্বরূপ XYZMyClass.shared (সুইফট 3) XYZMyClass.sharedMyClass () এর পরিবর্তে
রায়ান

এটি থ্রেডকে নিরাপদ দেখাচ্ছে না। এটি যদি আপনার কোডের বিভিন্ন থ্রেড থেকে রূপান্তরিত হতে পারে তবে আমি নিশ্চিত করব যে আপনি এটি তৈরি করার সম্ভাব্য রেস শর্তটি পরিচালনা করেছেন।
হাসিবোট

গ্রাহকদের ক্লাস করার জন্য একটি দুর্দান্ত পরিষ্কার ইন্টারফেস তবে এটি এখনও অনেক কাজ। একটি স্ট্যাটিক ব্লক দিয়ে এটি চেষ্টা করে দেখে খুব মজা লাগেনি। আসলে স্ট্যাটিক ব্যবহার করা অনেক সহজ ছিল।
Departamento বি


63

আপনি যদি শ্রেণি-স্তরের সমতুল্য সন্ধান করছেন @property, তবে উত্তরটি "এরকম কিছুই নেই"। তবে মনে রাখবেন @property, যাইহোক, কেবল সিনট্যাকটিক চিনি; এটি কেবল যথাযথ-নামযুক্ত অবজেক্ট পদ্ধতি তৈরি করে।

আপনি ক্লাসের পদ্ধতিগুলি তৈরি করতে চান যা স্থির ভেরিয়েবলগুলিতে অ্যাক্সেস করে যা অন্যরা যেমন বলেছে, কেবল কিছুটা আলাদা সিনট্যাক্স রয়েছে।


এমনকি চিন্তার বৈশিষ্ট্যগুলি সিনট্যাকটিক এটি [মাইক্লাস ক্লাস] এর পরিবর্তে মাইক্লাস.ক্লাসের মতো স্টাফের জন্য ডট সিনট্যাক্স ব্যবহার করতে সক্ষম হওয়া ভাল হবে।
জাকির জার্মান

4
@ জ্যাকিমারম্যান আপনি পারবেন! UIDevice.currentDevice.identifierForVendorআমার জন্য কাজ কর.
টিসি।

1
@tc। ধন্যবাদ! এখন মূর্খতা পূরণ। কোনও কারণে, আমি নিশ্চিত ছিলাম যে আমি অতীতে চেষ্টা করেছিলাম কিন্তু এটি কার্যকর হয়নি। কোনও সুযোগেই কি এটি একটি নতুন বৈশিষ্ট্য?
জাকি জার্মান

1
@ জাকিগারম্যান এটি ক্লাস পদ্ধতিগুলির জন্য কমপক্ষে এক বা দুই বছর কাজ করেছে। আমি বিশ্বাস করি যে যদি গ্রাহক / সেটার পদ্ধতিগুলি প্রত্যাশিত ধরণের থাকে তবে এটি সর্বদা উদাহরণ পদ্ধতিগুলির জন্য কাজ করে।
টিসি।

21

এটি করার একটি থ্রেড নিরাপদ উপায়:

// Foo.h
@interface Foo {
}

+(NSDictionary*) dictionary;

// Foo.m
+(NSDictionary*) dictionary
{
  static NSDictionary* fooDict = nil;

  static dispatch_once_t oncePredicate;

  dispatch_once(&oncePredicate, ^{
        // create dict
    });

  return fooDict;
}

এই সম্পাদনাগুলি নিশ্চিত করে যে fooDict কেবল একবার তৈরি হয়েছিল।

অ্যাপলের ডকুমেন্টেশন থেকে : "প্রেরণ_অনস - কোনও অ্যাপ্লিকেশনটির আজীবন একবার এবং একবারে একটি ব্লক অবজেক্ট কার্যকর করে।"


3
স্থিতিশীল এনএসডি অভিধানটি + (এনএসডি অভিধান *) অভিধানের প্রথম লাইনে আরম্ভ করা যেহেতু প্রেরণ_অনস কোডটি কি অপ্রাসঙ্গিক নয় এবং যেহেতু এটি স্থিতিশীল তা কেবল একবারেই আরম্ভ করা হবে?
jcpennypincher

@jcpennypincher একই লাইনে অভিধান আরম্ভ করতে তার স্ট্যাটিক ঘোষণা নিম্নলিখিত কম্পাইলার এরর উৎপাদ চেষ্টা করা হচ্ছে: Initializer element is not a compile-time constant
জর্জ ডাব্লুএস

@ জর্জিডব্লিউএস আপনি কেবল সেই ত্রুটিটি পাচ্ছেন কারণ আপনি এটি কোনও ফাংশনের ফলাফলের জন্য শুরু করার চেষ্টা করছেন (বরাদ্দ এবং আরআইডি ফাংশনগুলি)। আপনি যদি এটি শূন্য করতে আরম্ভ করেন, এবং তারপরে if (obj == nil) যোগ করুন এবং সেখানে আরম্ভ করুন, আপনি ভাল থাকবেন।
রব

1
রব, এটি থ্রেড নিরাপদ নয়। এখানে উপস্থাপিত কোডটি সেরা।
ইয়ান ওলম্যান

আমার এই উত্তরটি সবচেয়ে ভাল লেগেছে, কারণ এটি সম্পূর্ণ এবং থ্রেড নিরাপদ - তবে এটি কেবল প্রয়োগের সাথেই আরও ভালভাবে ডিল করে, যখন অপের প্রশ্নটি শ্রেণিক সম্পত্তি ঘোষণার বিষয়ে ছিল - তাদের বাস্তবায়ন নয় (যার বাস্তবায়নের সাথে কোনও সম্পর্ক নেই)। যাই হোক ধন্যবাদ.
মোটি শ্নের

11

এক্সকোড 8 অবজেক্টিভ-সি এখন শ্রেণীর বৈশিষ্ট্যগুলিকে সমর্থন করে:

@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end

যেহেতু শ্রেণীর বৈশিষ্ট্যগুলি কখনই সংশ্লেষিত হয় না আপনাকে নিজের প্রয়োগটি লিখতে হবে।

@implementation MyClass
static NSUUID*_identifier = nil;

+ (NSUUID *)identifier {
  if (_identifier == nil) {
    _identifier = [[NSUUID alloc] init];
  }
  return _identifier;
}
@end

আপনি শ্রেণীর নামের উপর সাধারণ ডট বাক্য গঠন ব্যবহার করে শ্রেণীর বৈশিষ্ট্যগুলি অ্যাক্সেস করতে পারেন:

MyClass.identifier;

7

বৈশিষ্ট্যগুলির কেবলমাত্র বস্তুগুলিতে মান থাকে, শ্রেণিগুলিতে নয়।

আপনার যদি শ্রেণীর সমস্ত বস্তুর জন্য কিছু সঞ্চয় করতে হয় তবে আপনাকে একটি বৈশ্বিক চলক ব্যবহার করতে হবে। আপনি এটি staticবাস্তবায়ন ফাইলে ঘোষণা করে আড়াল করতে পারেন ।

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

আরেকটি বিকল্প হ'ল একটি উত্সর্গীকৃত শ্রেণীর একটি অবজেক্ট তৈরি করা যা আপনার 'শ্রেণি' অভিধান এবং এই অভিধানের সাথে সম্পর্কিত সমস্ত সামগ্রীর একটি সেট উভয় সমন্বয়ে গঠিত। এটি NSAutoreleasePoolকোকোয়াদের মতো ।


7

এক্সকোড 8 থেকে শুরু করে আপনি বার্বির উত্তর অনুসারে শ্রেণীর সম্পত্তি বৈশিষ্ট্যটি ব্যবহার করতে পারেন ।

যাইহোক, বাস্তবায়নে, আপনাকে আইভারের পরিবর্তে স্থির পরিবর্তনশীল ব্যবহার করে শ্রেণীর সম্পত্তি জন্য শ্রেণি প্রাপ্ত এবং সেটার উভয়ই সংজ্ঞায়িত করতে হবে।

Sample.h

@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end

Sample.m

@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
   if (_sharedSample==nil) {
      [Sample setSharedSample:_sharedSample];
   }
   return _sharedSample;
}

+ (void)setSharedSample:(Sample *)sample {
   _sharedSample = [[Sample alloc]init];
}
@end

2

আপনার যদি অনেকগুলি স্তরের স্তরের বৈশিষ্ট্য থাকে তবে একটি সিঙ্গলটন প্যাটার্ন ক্রমযুক্ত হতে পারে। এটার মতো কিছু:

// Foo.h
@interface Foo

+ (Foo *)singleton;

@property 1 ...
@property 2 ...
@property 3 ...

@end

এবং

// Foo.m

#import "Foo.h"

@implementation Foo

static Foo *_singleton = nil;

+ (Foo *)singleton {
    if (_singleton == nil) _singleton = [[Foo alloc] init];

    return _singleton;
}

@synthesize property1;
@synthesize property2;
@synthesise property3;

@end

এখন আপনার শ্রেণি-স্তরের বৈশিষ্ট্যগুলিতে অ্যাক্সেস করুন:

[Foo singleton].property1 = value;
value = [Foo singleton].property2;

4
এই একক বাস্তবায়ন থ্রেড নিরাপদ নয়, এটি ব্যবহার করবেন না
ক্লিফেভার

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

এটি dispatch_onceএখানে ব্যবহার করা বেশ সহজ হবে ।
ইয়ান ম্যাকডোনাল্ড

পিও ঘোষণাপত্রে একটি উত্তর চেয়েছিল, বাস্তবায়ন নয় - এবং প্রস্তাবিত বাস্তবায়নও অসম্পূর্ণ (থ্রেড-নিরাপদ নয়)।
মোটি শ্নের

-3

[এই সমাধানটি সহজ করার চেষ্টা করুন] আপনি একটি সুইফ্ট শ্রেণিতে একটি স্ট্যাটিক ভেরিয়েবল তৈরি করতে পারেন তারপরে যেকোন উদ্দেশ্য-সি শ্রেণি থেকে কল করতে পারেন।


1
ওপি সুইফটে স্থিতিশীল সম্পত্তি কীভাবে তৈরি করবেন তা জিজ্ঞাসা করেনি, এটি তার সমস্যার সমাধান করে না।
নাথান এফ।

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