속성을 포함하는 Objective-C 프로토콜을 어떻게 처리합니까?
Objective-C 프로토콜의 사용은 다음과 같은 방식으로 사용됩니다.
@protocol MyProtocol <NSObject>
@required
@property (readonly) NSString *title;
@optional
- (void) someMethod;
@end
서브클래스가 확장되는 구체적인 슈퍼클래스를 쓰는 대신 사용되는 형식을 본 적이 있습니다.문제는 이 프로토콜을 준수한다면 직접 속성을 합성할 필요가 있느냐는 것입니다.슈퍼클래스를 확장하는 경우 대답은 '아니오'입니다.그럴 필요는 없습니다.하지만 프로토콜이 준수해야 하는 속성은 어떻게 처리해야 할까요?
제가 이해하기로는 이러한 속성을 필요로 하는 프로토콜에 부합하는 개체의 헤더 파일에 인스턴스 변수를 선언해야 합니다.그렇다면, 우리는 그것들이 단지 지침의 원칙이라고 가정할 수 있을까요?즉, 필요한 방법은 동일하지 않습니다.컴파일러는 프로토콜에 나열된 필수 메서드를 제외했다는 이유로 사용자의 솜방망이질을 할 것입니다.하지만 부동산에 숨겨진 이야기는 무엇일까요?
다음은 컴파일 오류를 생성하는 예입니다(참고:현재 문제에 반영되지 않은 코드를 삭제했습니다.
마이프로토콜
@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
통해 에 대해 모든 에게 해당 입니다.anObject
. 한 객체가 특정할 수 속성 입니다.프로토콜은 실제가 아니며 변수나 메서드 자체가 없습니다. 프로토콜은 참조를 보유한 개체가 특정 방식으로 프로토콜을 사용할 수 있도록 클래스에 대한 특정 속성 집합을 설명할 뿐입니다.
즉, 프로토콜에 부합하는 클래스에서는 객체가 제대로 작동하는지 확인하기 위해 모든 작업을 수행해야 합니다.
@property
★★★★★★★★★★★★★★★★★」@synthesize
핵심에는 코드를 생성하는 두 가지 메커니즘이 있습니다. @property
는, 그 속성명에 대해서 getter(및/또는 setter) 메서드가 있다고 하는 것입니다. ★★★★★★★★★★★★★★★★★.@property
변수(에는 시스템 내의 저장 변수를 추가해야 )만 충분합니다.@sythesize
단할 수 합니다.) , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , . .
다음은 완벽하게 작동하는 프로토콜 정의의 예입니다.
@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
당신이 정말로 해야 할 일은 단지 떨어뜨리는 것이다.
@synthesize title;
모든 준비가 되어 있어야 합니다.클래스 인터페이스에 속성을 넣는 것과 같은 방법으로 동작합니다.
편집:
보다 구체적으로 이 작업을 수행할 수 있습니다.
@synthesize title = _title;
이것은 xcode의 자동 합성이 자동 합성을 사용하는 경우 속성 및 ivar를 생성하는 방법과 일치합니다. 따라서 클래스에 프로토콜 및 클래스의 속성이 있으면 일부 ivar가 가독성에 영향을 줄 수 있는 다른 형식을 가지지 않습니다.
이름 속성을 선언하는 MyProtocol과 이 프로토콜을 준수하는 MyClass가 있다고 가정합니다.
주목할 만한 것
MyClass의 식별자 속성은 getter, setter 및 backing _identifier 변수를 선언하고 생성합니다.
이름 속성은 MyClass의 헤더에 getter, setter가 있다고만 선언합니다.getter, setter 구현 및 백업 변수를 생성하지 않습니다.
프로토콜에 의해 이미 선언된 이름 속성을 다시 선언할 수 없습니다.이렇게 하면 오류가 발생합니다.
@interface MyClass () // Class extension @property (nonatomic, strong) NSString *name; @end
프로토콜에서 속성을 사용하는 방법
따라서 해당 이름 속성에 MyClass를 사용하려면 다음 중 하나를 수행해야 합니다.
속성을 다시 선언합니다(AppDelegate.h는 이렇게 합니다).
@interface MyClass : NSObject <MyProtocol> @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *identifier; @end
자신을 통합하다
@implementation MyClass @synthesize name; @end
예: 2개의 클래스(Person 및 Serial)에서 Viewer 서비스를 사용해야 합니다.Viewer Protocol을 준수해야 합니다.viewerTypeOfDescription은 속성 서브스크라이버 클래스가 준수해야 하는 필수 속성입니다.
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;
}
변수 anObject는 TestProtocolsViewController 클래스 정의에 정의되어 있어야 하며 프로토콜은 해당 변수가 있어야 함을 알려줍니다.
컴파일러 오류는 변수가 존재하지 않는다는 사실을 알려주고 있습니다.@properties는 결국 도우미일 뿐입니다.
언급URL : https://stackoverflow.com/questions/844678/how-to-handle-objective-c-protocols-that-contain-properties
'programing' 카테고리의 다른 글
목록에서 여러 인덱스를 동시에 제거하려면 어떻게 해야 합니까? (0) | 2023.04.14 |
---|---|
Bash 함수에서 부울 반환 (0) | 2023.04.14 |
Swift 컴파일러 오류: 문자열 연결 시 "표현이 너무 복잡함" (0) | 2023.04.14 |
Swift 배열에서 요소의 합계를 찾는 중 (0) | 2023.04.14 |
버전 vs X코드 내장 (0) | 2023.04.09 |