development

선택적 문자열 확장을 추가하는 방법은 무엇입니까?

big-blog 2020. 12. 6. 21:48
반응형

선택적 문자열 확장을 추가하는 방법은 무엇입니까?


다음과 같이 문자열 확장을 만들 수 있습니다.

extension String {
   func someFunc -> Bool { ... }
}

하지만 선택적 문자열에 적용하려면 어떻게해야합니까?

var optionalString :String? = ""
optionalString!.someFunc() /* String? does not have a member someFunc */

Swift 3.1에서는 선택적 값에 확장을 추가 할 수도 있습니다.

extension Optional where Wrapped == String {
  var isBlank: Bool {
    return self?.isBlank ?? true
  }
}

다음과 같이 할 수 있습니다.

protocol OptionalType { typealias A; var opt: A? { get } }
extension Optional: OptionalType { var opt: A? { return self } }

protocol StringType { var get: String { get } }
extension String: StringType { var get: String { return self } }

extension Optional where Wrapped: StringType {
  func getOrElse(s: String) -> String {
    return self.opt?.get ?? s
  }
}

과:

let optStr: String? = nil
optStr.getOrElse("hello world")

그 이유는 당신은 제한 할 수 없습니다 Optional또는 String그들이이기 때문에 그 문제입니다 struct. 각각에 대해 의사 프로토콜을 만들면 이제 원하는대로 제한 할 수 있습니다.

저는 스위프트가 초보자가 배우기 도록 많은 것을 포기 했거나 언어가 아직 충분히 성숙하지 않은 것 같습니다.


그에 대한 확장 OptionalString

Swift 3부터는 확장 메서드를 선택 사항으로 직접 제한 할 수 없습니다 String. Daniel Shin의 답변이 설명하는 것처럼 프로토콜로 동등한 결과를 얻을 수 있습니다.

그러나 모든 유형의 Optional에 확장 메서드를 만들 수 있으며 String반환 값 이있는 몇 가지 유용한 메서드를 찾았습니다 . 이러한 확장은 값을 콘솔에 로깅하는 데 유용합니다. String가능한 nil을 빈 문자열로 바꾸고 싶을 때 선택 사항 에 asStringOrEmpty ()를 사용했습니다 .

extension Optional {
    func asStringOrEmpty() -> String {
        switch self {
            case .some(let value):
                return String(describing: value)
            case _:
                return ""
        }
    }

    func asStringOrNilText() -> String {
        switch self {
            case .some(let value):
                return String(describing: value)
            case _:
                return "(nil)"
        }
    }
}

사용 예 :

var booleanValue: Bool?
var stringValue: String?
var intValue: Int?

print("booleanValue: \(booleanValue.asStringOrNilText())")
print("stringValue: \(stringValue.asStringOrNilText())")
print("intValue: \(intValue.asStringOrNilText())")

booleanValue = true
stringValue = "text!"
intValue = 41

print("booleanValue: \(booleanValue.asStringOrNilText())")
print("stringValue: \(stringValue.asStringOrNilText())")
print("intValue: \(intValue.asStringOrNilText())")

콘솔 출력 :

booleanValue: (nil)
stringValue: (nil)
intValue: (nil)

booleanValue: true
stringValue: text!
intValue: 41

 

Optional nil 포인터와 다름

이러한 확장은 an Optional이 nil 포인터와 다르다는 것을 보여줍니다 . OptionalA는 enum특정 유형 (의 Wrapped그것 함을 의미 또는 값을 포함하지 않는다). Optional값을 포함하지 않아도 "컨테이너" 에 확장을 작성할 수 있습니다 .

Swift 선택적 선언에서 발췌

enum Optional<Wrapped> : ExpressibleByNilLiteral {

    /// The absence of a value.
    case none

    /// The presence of a value, stored as `Wrapped`.
    case some(Wrapped)

    ...
}

코드에서 값의 부재는 일반적으로 nil명시적인 것보다는 리터럴을 사용하여 작성됩니다..none enumeration case.


extension Optional where Wrapped == String {
var isNil: Bool {
    return self == nil
}

The above answer(written by @Vlad Hatko) works fine but in swift 4 there are some issues, so I changed it to this.


Swift 4.1에서 Optional is ambiguous for type lookup in this context빌드 오류가 발생했습니다. 수정하려면 Swift 네임 스페이스를 유형에 명시 적으로 추가해야합니다.

extension Swift.Optional where Wrapped == String {
    var isBlank: Bool {
        return self?.isBlank ?? true
    }
}

업데이트 : Swift 2 이상에서 작동하는 해결 방법은 다음을 참조하십시오.Daniel Shin’s answer


선택적 문자열은 그 자체가 유형이 아니므로 선택적 유형에 대한 확장을 만들 수 없습니다. Swift에서 an OptionalNone이거나 Some값을 래핑 할 수있는 열거 형 (약간의 구문 설탕 포함)입니다 . String 메서드를 사용하려면 optionalString. 이를 위해 선택적 체인을 쉽게 사용할 수 있습니다.

optionalString?.someFunc()

If optionalString is not nil, someFunc will be called on it. An alternative (less concise) way of doing this is to use optional binding to establish whether or not optionalString has a value before trying to call the method:

if let string = optionalString {
    string.someFunc()    // `string` is now of type `String` (not `String?`)
}

In your example from the comments below, you needn't nest multiple if statements, you can check if the optional string is an empty string in a single if:

if optionalString?.isEmpty == true {
    doSomething()
}

This works because the expression optionalString?.isEmpty returns an optional Bool (i.e. true, false or nil). So doSomething() will only be called if optionalString is not nil, and if that string is empty.

Another alternative would be:

if let string = optionalString where string.isEmpty {
    doSomethingWithEmptyString(string)
}

Since Xcode 9.3, you can use this slight modification of @Vladyslav's answer:

extension Optional where Wrapped == String {

    var isEmpty: Bool {
        return self?.isEmpty ?? true
    }

}

found some trick swift 3

class A{
    var name:String!;
    init(_ name:String?){
        self.name = name;
    }
}

extension Optional where Wrapped == String {
    func compareText(_ other:String?)->Bool{
        switch (self,other){
        case let(a?,b?):
            return a < b;
        case (nil,_):
            return true;
        default:
            return false;
        }
    }
}

let words:[A] = [A("a"),A(nil),A("b"),A("c"),A(nil)];

// let sorted = words.sorted{ 0.name.compareText($1.name) }
// trick
let sorted = words.sorted{ ($0.name as String?).compareText($1.name) }

print(sorted.map{$0.name});

참고URL : https://stackoverflow.com/questions/29462953/how-to-add-an-optional-string-extension

반응형