2017-05-09 12 views
0

Mac OS 10.11 이상 (Xcode 8.2.1 사용)에 대해 Swift 3 코드가 상당히 많습니다. GUI 응용 프로그램과 백그라운드 서비스가 많은 프로세스가 있습니다. 이 두 가지 모두 프레임 워크에 구현 된 사용자 정의 URLProtocol을 사용합니다 (응용 프로그램과 서비스 모두에서 가져옴). 프로토콜에 따라 에 해당하는 enum의 인스턴스가 생성되어 적절히 포착하고 처리합니다 (일반적으로 URLProtocolClient를 사용하여 요청을 시도하는 URLSession까지 던져 넣음).오류를 NSError로 변환 할 때 Swift 3 사용자 정의 URLProtocol이 충돌합니다.

  • 오류가없는 경우 앱과 서비스 모두 정상적으로 작동합니다.
  • 일 때 오류가 발생하면 앱이 정상적으로 작동합니다.
  • 오류가있는 경우 서비스는과 충돌합니다.

Error이 런타임에 의해 자동으로 NSError으로 변환 될 때 디버거를 통해 방황하는 것으로 나타났습니다. 나는이 코드를 코드에 명시 적으로 추가했다. 물론 필자는 그 라인에서 같은 충돌을 얻는다.

나는 Swift 3.1: Crash when custom error is converted to NSError to access its domain property을 보았다,하지만 여기에 적용되지 않습니다

  • 솔루션이 - (좋은 측정 및 LocalizedError)을 CustomNSErrorError을 확장하고 관련 속성을 구현 - 도움이되지 않았다.
  • domain을 획득 한 후에 충돌이 발생합니다. 내가 말할 수있는 한 그것은 나를 위해 문제가 아니었다.
  • 아마도 관련이 있습니다. 이는 Mac이 아니라 iOS에서 발생했습니다.

이미 그 문제에 대해 열거 된 해결책을 시도해 보았는데, 나는 무언가를 잃고 있습니다. 나는 이것을 어쨌든 dyld의 배짱 깊은 곳에서 일어나는 것처럼 보이지만 몇 시간 동안 아무 것도하지 않고 디버깅 해왔다.

코드 :이를 해결하기 위해이

enum CrowbarProtocolError: Error { 
    case FailedToCreateSocket; 
    case PathTooLong; 
    case NonSocketFile; 
    case SocketNotFound; 
... 
    case UnrecognizedError(errno: Int32); 
} 
extension CrowbarProtocolError: LocalizedError { 
    public var errorDescription: String? { 
     return "Some localized description" 
    } 
} 
extension CrowbarProtocolError: CustomNSError { 
    public static var errorDomain: String { 
     return "Some Domain Name" 
    } 
    public var errorCode: Int { 
     return 204 //Should be your custom error code. 
    } 
    public var errorUserInfo: [String: Any] { 
     return ["WTF": "Swift?"]; 
    } 
} 
... 
open class CrowbarUrlProtocol: URLProtocol { 
... 
    override open func startLoading() { 
     do { 
      let sockHandle = try CrowbarUrlProtocol.openSocket(); 
      let req = try buildRequestData(); 
      sockHandle.write(req); 
      NotificationCenter.default.addObserver(
       self, 
       selector: #selector(self.readCompleted), 
       name: .NSFileHandleReadToEndOfFileCompletion, 
       object: nil); 
      sockHandle.readToEndOfFileInBackgroundAndNotify(); 
     } catch let err { 
      Log.warn("CrowbarUrlProtocol request failed with error \(err)"); 
      // -- In the background service, THIS LINE CRASHES! -- 
      let err2 = err as NSError; 
      Log.warn("As NSError: \(err2)"); 
      // -- Without the explicit cast, it crashes on this line -- 
      self.client?.urlProtocol(self, didFailWithError: err); 
     } 
    } 
... 
} 

하나의 아이디어는 단지 부지에, NSError의 사용 (가능한 한 많이, 또는) 최선을 다하고 있습니다에 Error을 변환 할 필요가 결코 경우 그 NSError이면이 충돌을 일으키는 원인은 무엇이든 발생하지 않습니다. 그게 작동할지 모르겠지만 시도해 볼만한 가치가있는 것 같습니다.

답변

0

확인을 클릭하면 Swift의 런타임에 버그가있는 것 같습니다.하지만 해결 방법을 찾았습니다. 모든 항목에 NSError을 사용하십시오. Swift Error s보다는 Obj-C 코드가 관련되어 있습니다 (암시 적 캐스트를 방지하기 위해). CustomNSError을 이미 구현하고 있었기 때문에 함수를 내 Error 열거 형에 쉽게 작성하여 self.client?.urlProtocol(self, didFailWithError: err) 행에 사용했습니다.

enum CrowbarProtocolError: Error, CustomNSError { 
    case FailedToCreateSocket; 
    case PathTooLong; 
... 
    public func asNSError() -> NSError { 
     return NSError(domain: CrowbarProtocolError.errorDomain, 
        code: self.errorCode, 
        userInfo: self.errorUserInfo); 
    } 
} 
... 
open class CrowbarUrlProtocol: URLProtocol { 
... 
    override open func startLoading() { 
     do { 
      let sockHandle = try CrowbarUrlProtocol.openSocket(); 
      let req = try buildRequestData(); 
      sockHandle.write(req); 
      NotificationCenter.default.addObserver(
       self, 
       selector: #selector(self.readCompleted), 
       name: .NSFileHandleReadToEndOfFileCompletion, 
       object: nil); 
      sockHandle.readToEndOfFileInBackgroundAndNotify(); 
     } catch let err as CrowbarProtocolError { 
      Log.warn("CrowbarUrlProtocol request failed with error \(err)"); 
      self.client?.urlProtocol(self, didFailWithError: err.asNSError()); 
     } 
     catch let err { 
      Log.warn("CrowbarUrlProtocol caught non-CrowbarProtocol Error \(err)"); 
      // This would probably crash the service, but shouldn't ever happen 
      self.client?.urlProtocol(self, didFailWithError: err); 
     } 
    } 
... 
}