2017-10-30 9 views
2

Swift에서는 드물지만 nil 값을 갖는 non-optional 유형의 값으로 끝나는 것이 가능합니다.Swift에서 nil에 대해 선택 사항이 아닌 값을 확인하는 가장 좋은 방법

- (NSObject * _Nonnull)someObject { 
    return nil; 
} 

또는 나쁜 스위프트 코드 :

class C {} 
let x: C? = nil 
let y: C = unsafeBitCast(x, to: C.self) 

실제로, 나는이로 실행했습니다 this question에 대한 답변에서 설명하고있는 바와 같이,이 스위프트에 다리를 나쁜 목적-C 코드에 의해 발생 될 수있다 MFMailComposeViewController API는 MessageUI입니다. 다음은 비 선택적 MFMailComposeViewController을 만들지 만 사용자가 메일에 이메일 계정을 설정하지 않은 경우, 다음 코드는 EXC_BAD_ACCESS와 충돌 :

let mailComposeViewController = MFMailComposeViewController() 
print("\(mailComposeViewController)") 

디버거 같은 mailComposeViewController의 값을 보여줍니다

을 내가 unsafeBitCast(_:to:)에 대한 documentation이 "를 말한다 있습니다

  1. :
    mailComposeViewController = (MFMailComposeViewController) 0x0000000000000000 
    

    여기 몇 가지 질문을 스위프트 타입 시스템의 보장을 깨뜨리는 것 "이라고 말하면서 Swift 문서에는 이러한 보장이 깨지거나, 언제/언제 어떻게 될 수 있는지 설명되어 있습니다.

  2. 이 케이스를 확인하는 가장 좋은, 가장 관용적 인 방법은 무엇입니까? 컴파일러는 옵션이 아니기 때문에 mailComposeViewController == nil 여부를 확인하지 않을 것입니다.
+1

메일 작성자를위한 분명한 해결책은 전자 메일을 보낼 수 있는지 먼저 확인하는 것입니다. – rmaddy

답변

3

심지어 Apple의 API조차도 API에 옵션으로 표시되지 않은 유형의 경우 nil을 반환합니다. 솔루션은 Optional에 할당하는 것입니다.

예를 들어 traitCollectionDidChange은 사실 nil 일 수 있지만 UITraitCollection을 반환했습니다. Swift는 nil의 비 선택 사항을 확인할 수 없으므로 nil을 확인할 수 없습니다.

해결 방안은 UITraitCollection?에 즉시 반환 값을 할당하고 nil에 대해을 확인하고 을 확인하는 것이 었습니다. 이런 종류의 일은 유스 케이스가 무엇이든간에 잘 작동해야합니다 (메일 예제는 유스 케이스가 아닙니다.

0

동일한 문제가 있지만 Apple 문서에서 제안을 사용합니다. 문서에서

:

메일 작성 뷰 컨트롤러를 제시하기 전에, 항상 현재의 장치가 보내기 이메일로 구성되어 있는지 확인하기 위해 canSendMail() 메서드를 호출합니다. 사용자의 기기가 이메일을 전송하도록 설정되지 않은 경우 사용자에게 알리거나 단순히 애플리케이션의 이메일 발송 기능 을 사용 중지 할 수 있습니다. canSendMail() 메서드가 false를 반환하면이 인터페이스를 사용하지 마십시오. unsafeBitCast(_:to:)의 사용을 고려

if !MFMailComposeViewController.canSendMail() { 
    print("Mail services are not available") 
    return 
} 

.

주된 문제는 포인터가 우리가 예상하는 유형을 준수 할 수있는 경우 Swift에서 값에 대한 포인터를 캐스팅합니다. 내 관점에서 볼 때 매우 위험합니다. 추락.

0

아마 실제 스위프트 포인터 타입이 할 수있는 더 좋은 방법이 있지만, 하나의 옵션은 주소에 슬쩍 수 있습니다 : (. Int 크기의 기계 단어로 설명되어 있습니다)

func isNull(_ obj: AnyObject) -> Bool { 
    let address = unsafeBitCast(obj, to: Int.self) 
    return address == 0x0 
} 

+0

이것은 꽤 일반적인 목적이 아닙니다. 값 유형 (예 : NSArray'가'[Any]'로 자동 연결됨)을 포함하여이 작업을 수행하는 방법을 잘 모르겠습니다. –