오프 문자열 하드코딩

15776 단어 SwiftiOS
Swift가 iOS의 주요 개발 언어가 된 이후 많은 좋은 프로그래밍 습관이 표준이 되었다.
안전한 디자인과 컴파일링을 할 때의 오류 검출은 당연해졌지만, 스위프트를 활용하지 않는 형 시스템은 Objective-C 시대에 남겨진 습관으로 운행 시간 오류가 되기 쉬운 부분도 있다.
이번 보도는 낡고 인터페이스가 좋지 않은 API를 현대의 스위프트 프로젝트에 어떻게 도입했는지에 대한 이야기다.
이전 API를 사용하기 전에 패키지 클래스를 확장하거나 생성해야 할 수도 있습니다.
나는 특히 UIFontNSAttributedString가 좋지 않다고 생각해서 두 개의 창고를 만들었다.
이 글을 읽을 때 첨부된 UIFont 라이브러리와 NSAttributedString 라이브러리를 참고하세요.
여기에는 다음과 같은 프로그램 라이브러리가 포함되어 있습니다.
마음에 들면 스타가 되면 즐거워요!
Attributed
UIFontComplete

예: Selector


Swift2.1 이전Selector에는 문자열만 있었는데 이 API 디자인은 두 가지 단점이 있다.
하나는 컴파일러 Selector 문자열이 실제로 존재하는 방법 이름을 검사하지 않기 때문에 존재하지 않는 방법 이름은 실행할 때 붕괴됩니다.
또 다른 문제는 방법명의 코드 보완이 작용하지 않기 때문에 오류 유형이 높을 가능성이 높다는 것이다.
Swift2.1까지Selector 사용 방법:
// Swift 2.1
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add,
                                                    target: self,
                                                    action: "addNewMemo")
다행히 스위프트 팀이 이 문제를 해결했으니 스위프트 2.2를 쓰면 더 좋다.
// Swift 2.2
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add,
                                                    target: self,
                                                    action: #selector(addNewMemo))
Swift2.2Selector에서 단순한 문자열 형식으로 바뀌었습니다.
존재하지 않는 #selector(methodName) 방법 이름 methodName 이라면, 컴파일할 때 오류를 감지할 수 있습니다.
이런 신형 덕분에 Selector계의 운행시간이 붕괴될 가능성이 사라졌다.
그리고 코드가 완성되고 방법 명칭도 나왔기 때문에 이 프로그래밍 인터페이스는 더욱 쉽게 사용할 수 있다.

예: UIFont

UIFont의 구조기는 언뜻 보기에는 간단하지만 정확한 글꼴 이름의 문자열을 입력해야 한다.
현재 구조기를 사용하여 다음과 같은 글꼴 객체를 만듭니다.
let font = UIFont(name: "Arial-BoldItalicMT", size: 12.0)!
나는 이 인터페이스가 그다지 좋지 않다고 생각한다.
아까UIFont와 같은 문제가 있습니다. 글꼴 이름의 문자열이 잘못되었어도 컴파일할 때 주의하지 않습니다.SelectorUIFontFileManager와는 달리 실행 시 iOS 표준 글꼴의 존재를 보증합니다.
iOS 표준 글꼴에 제한이 있으므로 URL 사용하는 것이 좋습니다.enum에 사용된 모든 글꼴UIFont은 정확한 글꼴 이름을 몰라도 코드 완성에 사용할 글꼴을 찾을 수 있습니다.
extension UIFont {
    /// Create a UIFont object with a `Font` enum
    public convenience init?(font: Font, size: CGFloat) {
        let fontIdentifier: String = font.rawValue
        self.init(name: fontIdentifier, size: size)
    }
}
public enum Font: String {

    // Font Family: Copperplate
    case copperplateLight = "Copperplate-Light"
    case copperplate = "Copperplate"
    case copperplateBold = "Copperplate-Bold"
    .
    .
    .
    // Font Family: Bodoni 72 Oldstyle
    case bodoniSvtyTwoOSITCTTBook = "BodoniSvtyTwoOSITCTT-Book"
    case bodoniSvtyTwoOSITCTTBold = "BodoniSvtyTwoOSITCTT-Bold"
    case bodoniSvtyTwoOSITCTTBookIt = "BodoniSvtyTwoOSITCTT-BookIt"
}
다음과 같이 발표할 수 있습니다enum.
let font = UIFont(name: .arialBoldItalicMT, size: 12.0)!
UIFont을 사용하면 코드 완성이 유효합니다.이름이 잘못되면 컴파일할 때도 오류가 발생할 수 있습니다. 예: NSAttributedString 엔움을 사용해 봤다면 불쾌한 경험이 있을 수도 있다. NSAttributedString을 만들 때 Dictionary를 사용하여 속성을 지정하지만 키 이름에 해당하는 값의 유형을 조사해야 합니다. 예를 들어, NSAttributedString과 같은 글꼴을 사용하여 빨간색 문자와 밑줄이 그어진 Chalkdust 객체를 만들 때 다음 코드가 생성됩니다. let attributes: [String: Any] = [ NSForegroundColorAttributeName: UIColor.red, NSFontAttributeName: UIFont(name: "Chalkduster", size: 24.0)!, NSUnderlineStyleAttributeName: 1, ] let text = NSAttributedString(string: "Hello", attributes: attributes) NSAttributedString의Dictionary의 유형은 attributes형이기 때문에 [String: Any]형을 썼더라도 컴파일할 때 오류를 감지할 수 없습니다.
속성이 있는 문자열에 값을 설정할 때마다 키의 표식자를 확인해야 하며, 키의 값에 대한 코드 보완도 작동하지 않기 때문에 정확한 값을 찾을 수 없습니다.
나는 이 인터페이스가 현대 API 표준과 다르기 때문에 불편한 것으로 여겨져야 한다고 생각한다.
우리가 할 수 있는 일은 이 인터페이스를 간단한 얇은 포장기로 싸는 것이다.모든 잠금 장치는 속성마다 명확한 정의 유형을 가진 모든 값을 설정하는 방법이 있습니다.
let attributes = Attributes {
    return $0.foreground(color: .red)
             .font(UIFont(name: "Chalkduster", size: 24.0)!)
             .underlineStyle(.styleSingle)
}

"Hello".attributed(with: attributes)
여기에 입력한 값을 사용하여 각 속성을 설정하는 방법을 정의했기 때문에 어떤 종류의 값을 기대하는지 정확하게 알 수 있다.NSFontAttributeName: UIColor.red마술호를 사용하지 않아도 된다.
또 밑줄 스타일이 통상적인 밑줄NSUnderlineStyleAttributeName임을 분명히 알 수 있다.
확장의 또 다른 장점으로 서로 다른 속성 단어를 포함하는 속성을 가진 문자열을 간단하게 만들 수 있다.
속성이 있는 문자열.styleSingle을 정의하는 연산자는 링크에 사용할 매우 간단한 인터페이스를 만들 수 있습니다.
예를 들어, 사용자 이름이 흰색으로 강조 표시되고 특수 문자 간격으로 빨간색 문자의 베이스를 작성하는 경우 일반+ API를 사용하여 구성할 수 있습니다.
let attributes: [String: Any] = [
    NSForegroundColorAttributeName: UIColor.red,
    NSFontAttributeName: UIFont(name: "Chalkduster", size: 14.0)!,
]

let userName: String = "@trent"
let attributedString = NSMutableAttributedString(string: "\(userName) has commented on your post.", attributes: attributes)

let nameAttributes: [String: Any] = [
    NSForegroundColorAttributeName: UIColor.white,
    NSKernAttributeName: 4.0,
]
attributedString.addAttributes(nameAttributes, range: NSRange(location: 0, length: userName.characters.count))
이 코드도 정상적으로 작동할 수 있지만 좀 불편하다.
상술한 코드를 입력하는 동안 분명히 공통된 속성 기초를 가지고 있다.글꼴과 같은 기존 속성을 제외하고는 문자열의 특정 부분에만 추가 속성을 적용하려고 합니다.
먼저 기본 속성을 성명한 다음에 기본 속성에서 파생된 명확한 속성NSAttributedString만 창설한다.
let baseAttributes = Attributes {
    return $0.foreground(color: .red)
             .font(UIFont(name: "Chalkduster", size: 24.0)!)
}

let nameAttributes = baseAttributes.foreground(color: .white)
                                   .underlineStyle(.styleSingle)
                                   .kerning(4.0)

let message = " has commented on your post.".attributed(with: baseAttributes)
let userName = "@trent".attributed(with: nameAttributes)


messageLabel.attributedText = userName + message
두 방법 모두 같은 결과를 얻을 수 있지만 후자는 더욱 간단하다.

총결산


이번에는 문자열을 통해 값을 설정하는 방법의 개선 방법을 소개했다.
유키트와 파운드레이션 등 표준적인 구조라도 사용하기 어려운 인터페이스라면 독자 포장을 만들 수 있다.
이 기사의 코드 예는 보다 간단하게 조작할 수 있는 안전한 API를 설계하는 방법의 예이지만 결코 유일한 방법은 아니다.
앞으로도 기존 API를 더 쉽게 관리하고, 기릿허브의 기존 프로젝트 등을 볼 수 있을 것으로 기대하고 있다.

좋은 웹페이지 즐겨찾기