ios dev kangwook.

iOS) 각종 Extensions 소소한 팁 (2) 본문

iOS

iOS) 각종 Extensions 소소한 팁 (2)

kangwook 2024. 5. 13. 16:49

오늘은 저번에 이어서 UIKit 관련된 Extensions를 좀 활용해볼까 한다.

은근 유용한 함수들이 많으니 응용해서 잘 써보도록 하자


1. UILabel

일단 소개하기에 앞서, 텍스트를 강조하기 위한 EmphasizedText라는 구조체를 만들었다.

struct EmphasizedText {
    var text: String
    var font: UIFont
    var color: UIColor
}

이 EmphasizedText는 text와 font, color라는 property를 가지고 있고 이를 활용해 라벨의 Text를 조정할 예정이다.

먼저 applyEmphasizedText라는 함수이다.

extension UILabel {
    func applyEmphasizedText(fullText: String, textColor: UIColor, emphasizedTexts: [EmphasizedText]) {
        self.textColor = textColor
        self.text = fullText

        let attributedString = NSMutableAttributedString(string: fullText)

        for emphasizedText in emphasizedTexts {
            let attributes: [NSAttributedString.Key: Any] = [
                .font: emphasizedText.font,
                .foregroundColor: emphasizedText.color
            ]

            let range = (fullText as NSString).range(of: emphasizedText.text)
            attributedString.addAttributes(attributes, range: range)
        }

        self.attributedText = attributedString
    }
}

이 함수는 라벨의 텍스트에 강조하고 싶은 텍스트를 파라미터에 넣음으로써, 해당 라벨의 fullText중 emphasizedTexts만 폰트나 색이 다르게 설정될 수 있도록 해준다.

예를 들어

let fullText = "Hello World"
let emphasizedText = EmphasizedText(text: "Hello", font: UIFont.boldSystemFont(ofSize: 20), color: UIColor.red)

let label = UILabel()
label.applyEmphasizedText(fullText: fullText, textColor: UIColor.blue, emphasizedTexts: [emphasizedText])

이런식으로 하면 Hello라는 텍스트만 강조되어 boldSystemFont, 20pt의 빨간색으로 바뀌어서 라벨에 적용되게 된다.

이게 은근히 유용하다. 참고로 emphasizedText는 "배열"로 여러 부분을 강조하고 싶으면 여러 emphasizedText를 넣으면 된다.


2.  UIColor, CGColor

여기는 왜 한 번에 묶었냐면 똑같기 때문에 묵었다.

color같은 경우에 그냥 UIColor내부적으로도 초기화할 때 rgb값으로 사용할 수 있게 되어있긴 하지만 조금 더 쉽게 사용할 수 있는 방법을 소개하려고 한다. (간단함)

extension UIColor {
    static func rgb(r red: CGFloat, g green: CGFloat, b blue: CGFloat, a alpha: CGFloat = 1.0) -> UIColor {
        return UIColor.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
    }
}

그리고 UIView의 border색을 정할때나 뭐 가끔 cgcolor를 사용할 때가 있는데, 그 때도 귀찮으니까 그냥 만들어주자

extension CGColor {
    static func rgb(r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat = 1.0) -> CGColor {
        return UIColor.rgb(r: r, g: g, b: b, a: a).cgColor
    }
}

이렇게 하면 그냥 rgb값을 입력만 하면되서 엄~청 편리하다.


3. UIApplication

이건 그냥 많이 쓰진 않고 가끔씩 쓰는데, 가장 위에있는 뷰컨에 대한 확인 필요할 때 사용한다

class func topViewController(controller: UIViewController? = UIApplication.shared.windows.first?.rootViewController) -> UIViewController? {
    if let navigationController = controller as? UINavigationController {
        return topViewController(controller: navigationController.visibleViewController)
    }
    if let tabController = controller as? UITabBarController {
        if let selected = tabController.selectedViewController {
            return topViewController(controller: selected)
        }
    }
    if let presented = controller?.presentedViewController {
        return topViewController(controller: presented)
    }
    return controller
}

아 class func으로 한 이유는 그냥.. UIApplication자체에서 바로 사용하기 위해서다. 그냥 나 편하려고 만든거라 너무 뭐라하진 마세요 ㅎ


4. UIButton

위에 있는 UILabel에서 적용한 Emphasized Text와 비슷한 맥락인데, 이건 그냥 버튼 타이틀에 밑줄을 추가하는 함수이다.

사실, UILabel에도 적용할 수 있도록 만들어주는게 베스트인데 일단 그냥 이것만 필요해서 UIButton에 적용시켜 놓은 상태이다.

func setUnderline(fullText: String,
                  textColor: UIColor,
                  underlineText: String,
                  underlineStyle: NSUnderlineStyle = .single,
                  font: UIFont) {
    let font = font
    
    let attributedStr = NSMutableAttributedString(string: fullText)
    
    let attribute: [NSAttributedString.Key: Any] = [
        .font: font,
        .foregroundColor: textColor,
        .underlineStyle: underlineStyle.rawValue,
    ]
    
    attributedStr.addAttributes(attribute,
                                range: (fullText as NSString).range(of: underlineText))
    
    self.setAttributedTitle(attributedStr,
                            for: .normal)
}

5. UIViewController

여긴 이제 indicator를 보여주거나, 숨기는 함수들 뿐만 아니라 push와 present에 대한 함수도 새로 만들었는데, indicator와 같은 custom이 필요한(개인이나 회사에 맞춘) 부분들은 제외하고 범용적으로 쓸 수 있는 부분에 대해서 설명할 예정이다.

extension UIViewController {
    func makeNavigationController() -> UINavigationController {
        let navVC = UINavigationController.init(rootViewController: self)
        navVC.navigationBar.isHidden = true
        return navVC
    }
    
    public func push(next viewController: UIViewController, hideTab: Bool = false) {
        guard let nav = self.navigationController else {
            print("페이지 전환 실패 : navigationController is nil")
            return
        }

        viewController.hidesBottomBarWhenPushed = hideTab
        nav.pushViewController(viewController, animated: true)
    }
    
    public func present(next viewController: UIViewController, style: UIModalPresentationStyle = .overFullScreen, animated: Bool = true, completion: (() -> ())? = nil) {
        viewController.modalPresentationStyle = style
        present(viewController, animated: animated, completion: completion)
    }
    
    func popViewController() {
        if self.navigationController != nil {
            self.navigationController?.popViewController(animated: true)
        } else {
            self.dismiss(animated: true)
        }
    }
 }

1. 첫 번째 함수는 ViewController를 navigation controller로 만들어주는 함수다. 나같은 경우는 navigation bar를 안쓰는 디자인이다 보니까 저기 isHidden = true로 설정했지만, 이건 각자 입맛대로 설정하면 된다. 어떤 뷰컨트롤러의 경우 present를 하고 push를 해야하는 상황이 발생하는데, 이 때 navigation controller가 아니면 push가 되지 않으니, 그럴 때 유용하게 사용할 수 있는 함수라고 할 수 있다.

 

2. 두 번째랑 세 번째 함수는 push와 present에 대해서 조금 더 편하게 사용하기 위해 만든 함수다. 일단, 나 같은 경우의 present할 때 overFullScreen을 기본으로 사용하기 때문에, default값을 정해준 모습이고 나머지는 뭐 각자 입맛대로 설정하면 된다. 이렇게 되면 push와 present를 사용할때 내 기준 훨씬 간편하게 조금 더 일관되게(?) 사용할 수 있다.(기존 push할때 솔직히 귀찮았잖아요..)

 

3. 마지막은 popViewController()인데 정확히 말하면 popOrDismissViewController()가 맞다. 지금 보니까 조금의 수정이 필요한 것 같긴 하지만... 일단은 저 방식으로 일괄적으로 처리할 수 있다.

 

이 함수들은 꽤나 유용하게 사용하고 있고, 어떤 동작에 대해 일괄적으로 보일 수 있게해서 유용하다고 생각한다.


뭐 이정도가 있는데, 사실 이거 말고도 소개를 안한 함수들도 많긴하다. 하지만 그 함수들은 내가 개발하는 앱에 초점이 맞춰져 있고, 범용적이지 않다고 생각해서 생략했다.

다음 포스트는 아마... protocol에 대해서 좀 다루면서 유용하게 사용할 수 있는 protocol이 뭐가있을까에 대한 고찰이 주된 내용일 거 같다.

여튼 빠이

Comments