Search code examples
iosswiftprotocols

Passing optional @objc enum type into @objc protocol


I'm trying to create an optional function in @objc protocol, The documentType is @objc enum as well. But I'm getting this error:

Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C

My source code:

@objc enum DocumentType: Int {
    case pdf
    case png
}

@objc protocol ImageDocumentEditorProtocol: class {
    @objc optional func imageDocumentEditorDidCancel(documentType: DocumentType?)
}

How can I solve this issue? Thanks


Solution

  • Objective-C doesn't have optional enums. Enums must be non-optional. Classes can be optional, not enums :(

    One workaround is to add a case:

    @objc enum DocumentType: Int {
        case pdf
        case png
        case none
    }
    

    And use the non-optional type DocumentType instead.

    Of course, this makes non-optional DocumentTypes non-representable. To represent both optional and non-optional DocumentTypes, you would need two types:

    @objc enum DocumentType: Int {
        case pdf
        case png
        
        func asOptionalDocumentType() -> OptionalDocumentType {
            switch self {
            case .pdf: return .pdf
            case .png: return .png
            }
        }
    }
    
    extension Optional where Wrapped == DocumentType {
        func asOptionalDocumentType() -> OptionalDocumentType {
            self?.asOptionalDocumentType() ?? .none
        }
    }
    
    @objc enum OptionalDocumentType: Int, ExpressibleByNilLiteral {
        
        case pdf
        case png
        case none
        
        func asDocumentType() -> DocumentType? {
            switch self {
            case .pdf: return .pdf
            case .png: return .png
            case .none: return nil
            }
        }
        
        init(nilLiteral: ()) {
            self = .none
        }
    }
    

    I have added conversion methods to make it easy to convert between them, but they are not technically needed.