বৈশিষ্ট্যযুক্ত অবজেক্টিভ-সি প্রোটোকল কীভাবে পরিচালনা করবেন?


131

আমি উদ্দেশ্যমূলক-সি প্রোটোকলগুলির ব্যবহারগুলি নীচের মতো কোনও ফ্যাশনে ব্যবহার করতে দেখেছি:

@protocol MyProtocol <NSObject>

@required

@property (readonly) NSString *title;

@optional

- (void) someMethod;

@end

আমি এই ফর্ম্যাটটি একটি কংক্রিট সুপারক্লাস লেখার পরিবর্তে ব্যবহার করেছি যা সাবক্লাসগুলি প্রসারিত হয়। প্রশ্নটি হল, আপনি যদি এই প্রোটোকলটি মানেন তবে আপনার নিজের বৈশিষ্ট্যগুলি সংশ্লেষ করার দরকার আছে কি? যদি আপনি একটি সুপারক্লাস প্রসারিত করেন তবে উত্তরটি অবশ্যই হ'ল, আপনার দরকার নেই। কিন্তু কোনও প্রোটোকলের সাথে সঙ্গতিপূর্ণ এমন বৈশিষ্ট্যগুলির সাথে কীভাবে व्यवहार করা যায়?

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

এখানে একটি উদাহরণ যা সংকলন ত্রুটি উত্পন্ন করে (দ্রষ্টব্য: আমি কোডটি ছাঁটাই করেছি যা সমস্যাটির প্রতিফলন ঘটেনি):

MyProtocol.h

@protocol MyProtocol <NSObject>

@required
@property (nonatomic, retain) id anObject;

@optional

TestProtocolsViewController.h

- (void)iDoCoolStuff;

@end

#import <MyProtocol.h>

@interface TestProtocolsViewController : UIViewController <MyProtocol> {

}

@end

TestProtocolsViewController.m

#import "TestProtocolsViewController.h"

@implementation TestProtocolsViewController
@synthesize anObject; // anObject doesn't exist, even though we conform to MyProtocol.

- (void)dealloc {
    [anObject release]; //anObject doesn't exist, even though we conform to MyProtocol.
    [super dealloc];
}

@end     

উত্তর:


135

প্রোটোকল কেবল প্রোটোকলের মাধ্যমে আপনার ক্লাস সম্পর্কে জানে এমন প্রত্যেককে বলছে, সম্পত্তি anObjectথাকবে। প্রোটোকলগুলি বাস্তব নয়, এগুলির নিজস্ব কোনও ভেরিয়েবল বা পদ্ধতি নেই - তারা কেবলমাত্র আপনার শ্রেণীর বিষয়ে সত্য এমন একটি নির্দিষ্ট বৈশিষ্ট্যের বিবরণ বর্ণনা করে যাতে রেফারেন্স সম্বলিত অবজেক্টগুলি সেগুলিকে নির্দিষ্ট উপায়ে ব্যবহার করতে পারে।

এর অর্থ হল আপনার ক্লাসে যা আপনার প্রোটোকলের সাথে সামঞ্জস্যপূর্ণ, আনোবজেক্টের কাজ নিশ্চিত করার জন্য আপনাকে সবকিছু করতে হবে।

@propertyএবং @synthesizeহৃদয় এ দুটি প্রক্রিয়া যা আপনার জন্য কোড উত্পন্ন করে। @propertyকেবল এই সম্পত্তিটির নামের জন্য একটি গেটর (এবং / অথবা সেটার) পদ্ধতি থাকবে বলে দিচ্ছে। এই দিনগুলিতে @propertyসিস্টেম দ্বারা আপনার জন্য তৈরি পদ্ধতি এবং স্টোরেজ ভেরিয়েবল (আপনার সংযুক্তি ব্যবহার করতে হবে @sythesize) যথেষ্ট যথেষ্ট । তবে আপনার ভেরিয়েবলটি অ্যাক্সেস করতে এবং সঞ্চয় করতে কিছু থাকতে হবে।


80
একটি প্রোটোকলে সংজ্ঞায়িত বৈশিষ্ট্যগুলির জন্য, আধুনিক রানটাইমে আপনার এখনও একটি "@ সায়েন্টাইজাইজ" প্রয়োজন, বা অটো-সংশ্লেষণ পেতে আপনাকে আপনার ইন্টারফেস সংজ্ঞাতে "@ প্রপার্টি" নকল করতে হবে।
জেফ্রি হ্যারিস

@ জেফরিহরিস সুইফটে একই কি হবে ??
করণ অ্যালাঙ্গত

@ করণআলাঙ্গাত - সুইফটে sy @ সায়েন্টেসাইজ করার মতো কোনও জিনিস নেই, তবে ওবজেসির মতো আপনাকেও এমন একটি শ্রেণিতে সম্পত্তি ঘোষণা করা দরকার যা প্রোটোকলের সাথে সামঞ্জস্য করার দাবি করে। সুইফটে আপনি একটি বিভাগ তৈরি করতে পারেন যা কোনও ফাংশনটির ডিফল্ট বাস্তবায়ন সংজ্ঞায়িত করে, তবে আমি যতক্ষণ বলতে সক্ষম হয়েছি আপনি কোনও প্রোটোকলের জন্য ডিফল্ট সম্পত্তি রাখতে পারবেন না।
কেন্ডল হেলস্টেটার জেলনার

31

এখানে আমার উদাহরণ যা নিখুঁতভাবে কাজ করে, প্রোটোকলের সংজ্ঞা সবার আগে:

@class ExampleClass;

@protocol ExampleProtocol

@required

// Properties
@property (nonatomic, retain) ExampleClass *item;

@end

নীচে এই প্রোটোকলকে সমর্থন করে এমন কোনও শ্রেণীর কার্যকারী উদাহরণ রয়েছে:

#import <UIKit/UIKit.h>
#import "Protocols.h"

@class ExampleClass;

@interface MyObject : NSObject <ExampleProtocol> {

    // Property backing store
    ExampleClass        *item;

}


@implementation MyObject

// Synthesize properties
@synthesize item;

@end

14

সত্যিই আপনাকে যা করতে হবে তা হ'ল একটি

@synthesize title;

আপনার বাস্তবায়নের ক্ষেত্রে এবং আপনার প্রস্তুত হওয়া উচিত। এটি ঠিক আপনার শ্রেণি ইন্টারফেসে সম্পত্তি রাখার মতো কাজ করে।

সম্পাদনা:

আপনি আরও বিশেষভাবে এটি করতে চাইতে পারেন:

@synthesize title = _title;

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


1
আপনি কি সম্পূর্ণ নিশ্চিত? আমার একটি প্রোটোকলে একটি setচ্ছিক সম্পত্তি সেট আছে, এবং যখন আমি কেবলমাত্র এটি একটি কংক্রিট শ্রেণিতে সৃজন করি যা সেই প্রোটোকলের সাথে সঙ্গতিপূর্ণ হয় - আমি এটি একটি অঘোষিত ভেরিয়েবল দাবি করে একটি সংকলক ত্রুটি পেয়েছি। কোনও টাইপস নিশ্চিত হয়নি।
Coocoo4Cocoa 4

আমি alচ্ছিক বৈশিষ্ট্য সম্পর্কে নিশ্চিত নই, তবে ম্যারেক্সের মতো একটি জিনিস আমি উল্লেখ করতে ভুলে গেছি তা হল এটির পরিবর্তনশীল শিরোনামের নামকরণ করে, বা @ সায়েন্টেসাইজ শিরোনাম = মাইন্সট্যান্সভার বলে আপনাকে একটি সদস্য ভেরিয়েবলের সাথে বেঁধে রাখতে হবে;
কেভলার

2
আপনি যদি আধুনিক রান সময়টি ব্যবহার করেন, @ সংশ্লেষ করা আপনার যা দরকার তা হ'ল, অন্তর্নিহিত আইভারগুলি আপনার জন্য তৈরি করা হবে। আপনি যদি 32-বিট x86 টার্গেট করে থাকেন তবে আপনি উল্লিখিত সংকলক ত্রুটিটি পেয়ে যাবেন কারণ আপনি উত্তরাধিকার রানটাইমটিকে টার্গেট করছেন।
জেফ্রি হ্যারিস 21

1
এক্সকোড ৪.৪-এ স্বয়ংক্রিয় সংশ্লেষ প্রবর্তিত হয়েছিল, তবে গ্রাহাম লি-র একটি টুইট অনুসারে , এটি প্রোটোকলে ঘোষিত বৈশিষ্ট্যগুলিকে আবরণ করে না। সুতরাং আপনাকে এখনও সেই বৈশিষ্ট্যগুলি ম্যানুয়ালি সংশ্লেষিত করতে হবে।
cbowns

এটি একটি দুর্দান্ত বিষয়, বুঝতে পারিনি যে যোগ synthesizeকরা যথেষ্ট ছিল। শান্ত!
ড্যান রোজনস্টার্ক

9

আমার প্রবন্ধটি প্রোটোকল-এ নিবন্ধটি দেখুন

মনে করুন আমার কাছে মাইপ্রোটোকল রয়েছে যা একটি নামের সম্পত্তি ঘোষণা করে এবং এই প্রোটোকলের সাথে সঙ্গতিপূর্ণ মাইক্লাস

বিষয়গুলি লক্ষণীয়

  1. মাইক্লাসে শনাক্তকারী সম্পত্তি গিটার, সেটার এবং ব্যাকিং _ অ্যান্টিফায়ার ভেরিয়েবল ঘোষণা করে এবং উত্পন্ন করে
  2. নামের বৈশিষ্ট্যটি কেবলমাত্র ঘোষণা করে যে মাইক্লাসের শিরোনামে একটি গিটার, সেটার রয়েছে has এটি গিটার, সেটার বাস্তবায়ন এবং ব্যাকিং ভেরিয়েবল উত্পন্ন করে না।
  3. প্রোটোকল দ্বারা এটি ইতিমধ্যে ঘোষিত হিসাবে আমি এই নামের সম্পত্তিটি পুনরায় ঘোষনা করতে পারি না। এটি একটি ত্রুটি চিৎকার করবে

    @interface MyClass () // Class extension
    
    @property (nonatomic, strong) NSString *name;
    
    @end

প্রোটোকলে কীভাবে সম্পত্তি ব্যবহার করবেন

সুতরাং যে নাম সম্পত্তি সঙ্গে মাইক্র্লাস ব্যবহার করতে, আমাদের হয় হয়

  1. সম্পত্তি আবার ঘোষণা করুন (AppDelegate.h এইভাবে করে)

    @interface MyClass : NSObject <MyProtocol>
    
    @property (nonatomic, strong) NSString *name;
    
    @property (nonatomic, strong) NSString *identifier;
    
    @end
  2. সংশ্লেষ করা

    @implementation MyClass
    
    @synthesize name;
    
    @end

তালিকার মধ্যে নেস্টেড কোড ব্লকগুলিকে প্রতি লাইনে আটটি স্পেস দিয়ে ইন্টেন্ট করা দরকার। এটি মার্কডাউন সিনট্যাক্সের অপেক্ষাকৃত অজানা অদ্ভুততা। আমি আপনার জন্য আপনার উত্তর সম্পাদনা করেছি।
BoltClock

1

প্রোটোকল আর্কিটেকচার

উদাহরণ: ২ টি শ্রেণি (ব্যক্তি এবং সিরিয়াল) দর্শকের ব্যবহারের পরিষেবা চায় ... এবং অবশ্যই ভিউয়ারপ্রোটোকলের সাথে সঙ্গতিপূর্ণ হবে। ভিউয়ারটাইপঅফডেসক্রিপশন হ'ল বাধ্যতামূলক সম্পত্তি গ্রাহক শ্রেণীর সাথে সঙ্গতিপূর্ণ হতে হবে।

typedef enum ViewerTypeOfDescription {
    ViewerDataType_NSString,
    ViewerDataType_NSNumber,
} ViewerTypeOfDescription;

@protocol ViewerProtocol
@property ViewerTypeOfDescription viewerTypeOfDescription;
- (id)initConforming;
- (NSString*)nameOfClass;
- (id)dataRepresentation;
@end

@interface Viewer : NSObject
+ (void) printLargeDescription:(id <ViewerProtocol>)object;
@end

@implementation Viewer
+ (void) printLargeDescription:(id <ViewerProtocol>)object {
    NSString *data;
    NSString *type;
    switch ([object viewerTypeOfDescription]) {
        case ViewerDataType_NSString: {
            data=[object dataRepresentation];
            type=@"String";
            break;
        }
        case ViewerDataType_NSNumber: {
            data=[(NSNumber*)[object dataRepresentation] stringValue];
            type=@"Number";
            break;
        }
        default: {
            data=@"";
            type=@"Undefined";
            break;
        }
    }
    printf("%s [%s(%s)]\n",[data cStringUsingEncoding:NSUTF8StringEncoding],
           [[object nameOfClass] cStringUsingEncoding:NSUTF8StringEncoding],
           [type cStringUsingEncoding:NSUTF8StringEncoding]);
}
@end


/* A Class Person */

@interface Person : NSObject <ViewerProtocol>
@property NSString *firstname;
@property NSString *lastname;
@end

@implementation Person
// >>
@synthesize viewerTypeOfDescription;
// <<
@synthesize firstname;
@synthesize lastname;
// >>
- (id)initConforming {
    if (self=[super init]) {
        viewerTypeOfDescription=ViewerDataType_NSString;
    }
    return self;
}
- (NSString*)nameOfClass {
    return [self className];
}
- (NSString*) dataRepresentation {
    if (firstname!=nil && lastname!=nil) {
        return [NSString stringWithFormat:@"%@ %@", firstname, lastname];
    } else if (firstname!=nil) {
        return [NSString stringWithFormat:@"%@", firstname];
    }
    return [NSString stringWithFormat:@"%@", lastname];
}
// <<
@end



/* A Class Serial */

@interface Serial : NSObject <ViewerProtocol>
@property NSInteger amount;
@property NSInteger factor;
@end

@implementation Serial
// >>
@synthesize viewerTypeOfDescription;
// <<
@synthesize amount;
@synthesize factor;
// >>
- (id)initConforming {
    if (self=[super init]) {
        amount=0; factor=0;
        viewerTypeOfDescription=ViewerDataType_NSNumber;
    }
    return self;
}
- (NSString*)nameOfClass {
    return [self className];
}
- (NSNumber*) dataRepresentation {
    if (factor==0) {
        return [NSNumber numberWithInteger:amount];
    } else if (amount==0) {
        return [NSNumber numberWithInteger:0];
    }
    return [NSNumber numberWithInteger:(factor*amount)];
}
// <<
@end




int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Person *duncan=[[Person alloc]initConforming];
        duncan.firstname=@"Duncan";
        duncan.lastname=@"Smith";

        [Viewer printLargeDescription:duncan];

        Serial *x890tyu=[[Serial alloc]initConforming];
        x890tyu.amount=1564;

        [Viewer printLargeDescription:x890tyu];

        NSObject *anobject=[[NSObject alloc]init];

        //[Viewer printLargeDescription:anobject];
        //<< compilator claim an issue the object does not conform to protocol

    }
    return 0;
}

সাবক্লাসিংয়ের উপরে প্রোটোকল উত্তরাধিকারের সাথে অন্য একটি উদাহরণ

typedef enum {
    LogerDataType_null,
    LogerDataType_int,
    LogerDataType_string,
} LogerDataType;

@protocol LogerProtocol
@property size_t numberOfDataItems;
@property LogerDataType dataType;
@property void** data;
@end

@interface Loger : NSObject
+ (void) print:(id<LogerProtocol>)object;
@end

@implementation Loger
+ (void) print:(id<LogerProtocol>)object {
    if ([object numberOfDataItems]==0) return;
    void **data=[object data];
    for (size_t i=0; i<[object numberOfDataItems]; i++) {
        switch ([object dataType]) {
            case LogerDataType_int: {
                printf("%d\n",(int)data[i]);
            break;
            }
            case LogerDataType_string: {
                printf("%s\n",(char*)data[i]);
                break;
            }
            default:
            break;
        }
    }
}
@end


// A Master Class

@interface ArrayOfItems : NSObject  <LogerProtocol>
@end

@implementation ArrayOfItems
@synthesize dataType;
@synthesize numberOfDataItems;
@synthesize data;
- (id)init {
    if (self=[super init]) {
        dataType=LogerDataType_null;
        numberOfDataItems=0;
    }
    return self;
}
@end

// A SubClass

@interface ArrayOfInts : ArrayOfItems
@end

@implementation ArrayOfInts
- (id)init {
    if (self=[super init]) {
        self.dataType=LogerDataType_int;
    }
    return self;
}
@end

// An other SubClass

@interface ArrayOfStrings : ArrayOfItems
@end

@implementation ArrayOfStrings
- (id)init {
    if (self=[super init]) {
        self.dataType=LogerDataType_string;
    }
    return self;
}
@end


int main(int argc, const char * argv[])
{

    @autoreleasepool {

        ArrayOfInts *arr=[[ArrayOfInts alloc]init];
        arr.data=(void*[]){(int*)14,(int*)25,(int*)74};
        arr.numberOfDataItems=3;

        [Loger print:arr];

        ArrayOfStrings *arrstr=[[ArrayOfStrings alloc]init];
        arrstr.data=(void*[]){(char*)"string1",(char*)"string2"};
        arrstr.numberOfDataItems=2;

        [Loger print:arrstr];

    }
    return 0;
}

0

ভেরিয়েবল, অ্যানোবজেক্ট আপনার টেস্টপ্রোটোকলভিউ কনট্রোলার ক্লাস সংজ্ঞাতে সংজ্ঞায়িত করা দরকার, প্রোটোকলটি আপনাকে জানিয়ে দিচ্ছে যে এটি থাকা উচিত।

সংকলক ত্রুটিগুলি আপনাকে সত্য বলছে - ভেরিয়েবলের অস্তিত্ব নেই। @ প্রপার্টিগুলি সর্বোপরি কেবল সহায়ক।

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