countByEnumeratingWithState:objects:count:
메서드를 사용자 정의 클래스의 NSFastEnumeration 프로토콜에서 구현하려고합니다.ARC의 NSFastEnumeration 객체 캐스팅
지금까지 내가 내 객체를 올바르게 반복하지만, 반환되는 객체는 Objective-C 객체가 아니라 오히려 핵심 기초 동등 물입니다. 여기
을 설정하는 코드의 일부 년대 상태 -> itemsPtr :- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
objects: (id __unsafe_unretained *)buffer
count: (NSUInteger)bufferSize {
// ... skip details ...
NSLog(@"Object inside method: %@", someObject);
state->itemsPtr = (__unsafe_unretained id *)(__bridge void *)someObject;
// ... skip details ...
}
그런 다음 나는이 같은 루프 'for..in을'다른 곳에서 전화
MyCustomCollection.m
SomeOtherClass.m
MyCustomCollection *myCustomCollection = [MyCustomCollection new];
[myCustomCollection addObject:@"foo"];
for (id object in myCustomCollection) {
NSLog(@"Object in loop: %@", object);
}
콘솔 출력은 다음과 같습니다 당신이 볼 수 있듯이 개체 인쇄 미세 NSFastEnumeration 프로토콜 메서드 내
Object inside method: foo
Object in loop: __NSCFConstantString
는하지만, 즉시이 id __unsafe_unretained *
로 캐스팅됩니다 나는이 클래스를 해당 원래 목표 - C를 잃게됩니다.
솔직히 말해서이 경우에 (__unsafe_unretained id *)(__bridge void *)
캐스팅이 어떻게 작동하는지 잘 모르겠습니다. (__unsafe_unretained id *)
은 필요한 유형 항목과 일치하도록 캐스팅 된 것처럼 보입니다. (__bridge void *)
은 obj-c 세계를 CF 세계에 연결하는 데 사용되는 __bridge를 사용하여 void 유형의 포인터로 캐스팅 된 것처럼 보입니다. __bridge
에 대한 llvm docs, 당 :
There is no transfer of ownership, and ARC inserts no retain operations
올바른인가요?
제 생각에 __NSCFConstantString은 NSString의 핵심 기초입니다. 또한 ARC는 Objective-C 객체에서 CoreFoundation 객체로 연결해야한다는 것을 알고 있습니다. 왜냐하면 ARC는 후자의 메모리를 관리하는 방법을 모르기 때문입니다.
어떻게하면 'for..in'루프의 객체가 원래 유형이되도록 할 수 있습니까?
또한이 경우에는 NSString을 내 컬렉션에 추가하지만 이론적으로는 모든 개체를 지원해야합니다.
UPDATE
롭의 대답은 궤도에,하지만 난이 변경 그 이론을 테스트하기 위해 루프이에 :
객체가 동일하기 때문에 작동해야 이론적으로for (id object in myCustomCollection) {
NSString *stringObject = (NSString *)object;
NSLog(@"String %@ length: %d", stringObject, [stringObject length]);
}
하지만, 그것은 거의 물체처럼 보이는
+[__NSCFConstantString length]: unrecognized selector sent to class
가 for
반환 : 그것은이 오류와 충돌 루프는 클래스가 아니라 인스턴스입니다. 여기 뭔가 잘못되었을 수도 있습니다 ... 이것에 대한 어떤 생각?.
업데이트 2 : 솔루션은
그것은이처럼 간단합니다 CodaFi
state->itemsPtr = &someObject;
당신 말이 맞다! 내 부분에 어리석은 실수.내 C 포인터 구문을 검토 해야하는 것 같습니다. 당신이 말했듯이, 이것은 우연히 약간의 우연이 객체의 기본 구조 표현을 주어진 방식대로 작동했습니다. – nebs
'&'를 사용하면 그 두 끔찍한 캐스트도 제거 할 수 있습니다. – CodaFi
Brilliant! 왜 이것이 효과가 있는지 간단히 설명해 주시겠습니까? itemsPtr은 struct :'id __unsafe_unretained * itemsPtr'에서 이와 같이 정의됩니다. 나의 이해에서'id '는'무언가에 대한 포인터 '를 의미합니다. 그래서 우리가'__unsafe_unretained' 부분을 무시한다면 타입으로'id *'가 있습니다. 이것은'포인터를 가리키는 포인터 '가 맞습니까? 그러면 '&'는 '주소'를 의미합니다. 그래서 & someObject 할 때 그것은 객체의 메모리 주소 인 정수를 돌려줍니다. 나는 왜 & myObject가'id *'에 할당 될 수 있는지 이해할 수 없다. itemsPtr이 myObject의 주소를 보유하고있는 다른 포인터를 가리 킵니까? – nebs