2013-07-20 5 views
0

먼저, 나는 어제 다른 방식으로이 질문을했다. 더 많은 실험을 한 후에도 나는 왜 "왜"에 관해서는 여전히 불명확하다. 내가 뭘해야하는지 이해하지만 무슨 일이 일어나고 있는지 분명히하고 싶다. 여기에 내가 깨끗한 슬레이트, 단일보기 응용 프로그램을 시작하여 간단하게 AppDelegate에에 다음 NSLog를 추가 해요 시나리오 ...다음과 같은 메시지가 나타나면 왜 타이 캐스팅해야합니까?

...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    NSLog(@"%@",[self.window.rootViewController description]); 

    return YES; 
} 

위의 반환

<ViewController: 0x17e7dbf0> 

지금이다, "TestViewController"(UIViewController 유형의) 새 클래스를 만들고 스토리 보드의 컨트롤러에 할당하면 위의 NSLog는

<TestViewController: 0x146594c0> 
을 반환합니다.

내 질문은 "이전 설명에"TestViewController "유형의 rootViewController가 표시되면 왜 (TestViewController *)를 형변환해야합니까? 나는이 작업을 수행 할 수없는 이유 ... 대신

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    TestViewController *tvc = self.window.rootViewController; 
    return YES; 
} 

...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    TestViewController *tvc = (TestViewController*)self.window.rootViewController; 
    return YES; 
} 

내가 여기에 안개를 정리하고 싶습니다. 어떤 퍼즐 조각이 빠졌습니까?

도움 주셔서 감사합니다.

답변

0

구체적이고 상속 계층을 위아래로 작업하는 것입니다. 이 경우 rootViewController에서

UIViewController *,하지만 당신은 서브 클래스 참조 ( TestViewController *)가되고 싶어요. 컴파일러는이를 보장 할 수 없으므로 캐스트해야합니다. 캐스트는 기본적으로 런타임에 컴파일러가 작동한다는 것을 약속합니다.

다른 말로하면 rootViewControllerTestViewController *이지만 수퍼 클래스 참조 (UIViewController *)가되기를 원합니다. 이 경우 컴파일러는 사실을 보장 할 수있는 충분한 정보를 가지고 있으므로 캐스팅 할 필요가 없습니다.

1

두 번째 경우에는 컴파일러에게 더 잘 알고 있다고 말합니다. 반환 유형 self.window.rootViewControllerUIViewController 포인터입니다. 하지만 그 포인터를 TestViewController 유형의 포인터에 할당하려고합니다. 캐스트가 없으면 컴파일러는 적절한 할당이 아니라고 경고합니다. 캐스트를 넣으면 컴파일러에게 "신뢰 해 -보기 컨트롤러가 실제로 TestViewController이라는 것을 알고 있습니다."라고 말합니다. 물론 그것이 틀렸다는 것이 밝혀지면 런타임 중에 문제가 생길 수도 있고 없을 수도 있습니다.

첫 번째 경우 앱이 실행될 때 실제 클래스의 출력이 표시됩니다. description 메서드는 개체의 실제 클래스 이름과 해당 주소를 메모리에 반환합니다.

두 경우는 실제로 서로 관련이 없습니다.

0

컴파일러는 런타임 유형에 대해 잭을 알지 못하기 때문에. 컴파일 시간 유형에 대해서만 알고 있습니다. Objective-C는 다형성을 지원하는 동적 언어이므로 유형이 T 인 것으로 선언 된 객체는 실제로 T 일 필요는 없습니다. 또한 T의 하위 클래스가 될 수도 있습니다.

이것은 정확히 귀하의 경우에 발생합니다. self.window.rootViewControllerUIViewController 유형으로 선언되었으므로 TestViewController의 하위 클래스가 아닙니다. (다른 방법이 있다고 생각합니다.) 명시 적 유형 변환이 필요하지만 은 컴파일러를 속일 필요가 있습니다.

캐스트는 정말 것이다 (하지만, 그들은 C에서 다른 유형의 경우 "흥미로운"부작용이있을 수 있습니다) 떨어져 컴파일러 경고를 침묵에서 객체 목표 - C의 맥락에서 무엇을 수행하고 코드 하지 않습니다 캐스트없이 잘 작동합니다.

+0

왜 downvote? –

+0

먼저 확인해주세요. 도움을 주신 모든 분들께 감사드립니다. 이 권리가 있는지 알려주지. 이것은 컴파일러를 만족시키는 것입니다 (런타임까지 유형에 대해 무엇을하고 싶은지를 알지 못함). 컴파일러를 행복하게 유지하기 위해 @Class 전달 선언과 다르지 않습니다. 그게 옳은가? – user2502232

+0

@ user2502232 예, 그런 것 같습니다. –