2011-01-12 1 views
7

iPhoneView에 코드가있어 UIView 하위 클래스에서 모든 하위 뷰가 제거됩니다. 다음과 같이 보입니다.UIView.subviews와 [NSView 하위 뷰] 사이의 동작 차이

NSArray* subViews = self.subviews; 
for(UIView *aView in subViews) { 
    [aView removeFromSuperview]; 
} 

잘 작동합니다.

NSArray* subViews = [self subviews]; 
for(NSView *aView in subViews) { 
    [aView removeFromSuperview]; 
} 

완전히 작동하지 않습니다 : 나는 거의 (NSView의 서브 클래스에서) 맥 OS X 응용 프로그램에서 같은 일을 시도 할 때까지 사실, 정말에게 많은 생각을 포기하지 않았다. 특히, 런타임에,이 얻을 :

*** Collection <NSCFArray: 0x1005208a0> was mutated while being enumerated. 

난과 같이 그 일을 결국 : 괜찮아요

NSArray* subViews = [[self subviews] copy]; 
for(NSView *aView in subViews) { 
    [aView removeFromSuperview]; 
} 
[subViews release]; 

합니다. 그렇다고해서 iPhone에서 작동하는 이유는 무엇입니까? 복사 속성이 지정 될 때

@property(nonatomic,readonly,copy) NSArray *subviews; 

내 첫번째 생각은, 어쩌면 @ synthesize'd 게터 사본을 반환되었다

파단은 복사 속성입니다. The doc은 setter에 대한 복사의 의미에 대해 명확하지만 getters (또는 적어도 분명하지 않음)에 대한 두 가지 방법으로는 보이지 않습니다. 그리고 실제로, 내 자신의 몇 가지 테스트를 수행,이 분명히 사건되지 않는 것 같습니다. 어떤 점이 좋을까요, 몇 가지 이유로 사본을 반환하는 것이 문제가 될 것이라고 생각합니다.

그래서 위의 코드는 iPhone에서 어떻게 작동합니까? NSView 분명히 subview 실제 배열에 대한 포인터를 반환하고 아마도 UIView 않습니다. 아마도 그것은 UIView의 구현 세부 사항 일뿐입니다.

아무도 통찰력을 제공 할 수 있습니까?

답변

13

이것은 -[NSView subviews]의 버그입니다. 나는 스노우 레오파드 (Snow Leopard)를 위해 고쳐 졌다고 맹세했지만 아직 어떤 증거도 찾을 수 없다.

다행히 모든 하위 뷰를 제거하는 간단한 방법이있다 :

[self setSubviews:[NSArray array]]; 
+3

그것은 거의 버그 @ 마이크입니다. [someNSView subviews]는 서브 뷰 배열에 대한 포인터를 반환하는 반면 [someUIView subviews]는 해당 배열의 복사본을 반환합니다. 이것이 iOS에서 제대로 작동하는 이유입니다. – jackal

2

예, 애플이 그것을 구현 한 것입니다. Mac에서는 하위 뷰가 뷰에 사용 된 실제 (변경 가능한) 배열을 반환하므로 뷰를 추가하거나 제거하는 동안 빠른 열거 형을 사용할 수 없습니다. reverseObjectEnumerator를 사용하려면 다음을 수행 할 수 있습니다. 일반 열거자를 사용하지 마십시오. 하위보기가 제거 된 항목을 대체하도록 위로 이동하면 하위보기를 건너 뛸 수 있습니다. 하지만 iOS에서는 애플이이 문제를 깨닫고 자동으로 사본을 돌려줌으로써 문제를 해결 한 것으로 보인다. 속성 선언은 설정 방법 만 설명하지만 사과는 getter도 복사하도록 선택했습니다. 사용

while([self.subviews count] > 0){ 
    [[self.subviews objectAtindex:0] removeFromSuperview]; 
} 

희망이 도움