Skip to content

vincent-k-sm/MKFoundation

Repository files navigation

MKFoundation

소개

  • 개인 프로젝트에서 공통으로 사용되는 Colorset 을 포함, UI Component를 프레임워크화 합니다
  • Colorset에는 다크모드, 라이트 모드를 대응하는 Asset을 포함합니다
example_video.mov

Requirements

Platform Minimum Swift Version Installation Status
iOS 13.0+ / macOS 11.0+ 5.0 Swift Package Manager, Manual Fully Tested

Installation

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler.

Once you have your Swift package set up, adding MKFoundation as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
    .package(url: "https://github.com/vincent-k-sm/MKFoundation", .upToNextMajor(from: "1.0.3"))
]

Manually

If you prefer not to use any of the aforementioned dependency managers, you can integrate MKFoundation into your project manually.

Embedded Framework

  • Open up Terminal, cd into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:

    $ git init
  • Add MKFoundation as a git submodule by running the following command:

    $ git submodule add https://github.com/vincent-k-sm/MKFoundation

    After download We Suggest Remove Example Folder When Embed

  • Click on the + button under th Frameworks, Libraries, and Embedded Content

  • Click on the Add Other and Select in MKFoundation folder

  • Drag the MKFoundation folder into the Project Navigator of your application's Xcode project.

    It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.

  • And that's it!


Features


Buttons

ButtonTypes

public enum ButtonTypes: CaseIterable {
    case red
    case orange
    case yellow
    case green
    case blue
    case pink
    case purple
    case dark
    case primary
    case white
    case grey
}

ButtonSizes

public enum ButtonSize: CaseIterable {
    case medium
    case small
    
    var style: ButtonSizeModel {
        switch self {
            case .medium:
                let model = ButtonSizeModel(height: 48.0)
                return model

            case .small:
                let model = ButtonSizeModel(height: 44.0)
                return model
                
        }
    }
}

Button Methods

  • setBackgroundColor
    • 버튼 배경색을 지정합니다
func setBackgroundColor(
    _ color: UIColor,
    for state: UIControl.State
) {

  • alignTextBelow
    • 버튼 내 이미지와 타이틀 간의 간격을 조정합니다
      • (iOS 15에서 추가된 UIButton.Configuration 은 향 후 대응 예정입니다)
func alignTextBelow(
    spacing: CGFloat = 2.0
) {

  • updateTitleText
    • Foundation으로 Title 없이 설정한 버튼의 Title만 Update하고자 하는 경우 사용할 수 있습니다
      • 내부에서 SetTitle에 자동으로 처리하도록 개선이 필요합니다
 func updateTitleText(
     text: String,
     status: [UIControl.State] = [.normal, .selected, .disabled, .highlighted]
 ) {

  • setButtonLayout
    • 버튼 타입 및 Constants 에 따라 버튼 레이아웃을 세팅합니다
    • Types
    • Size
func setButtonLayout(
    title: String = "",
    size: ButtonSize,
    primaryType: ButtonTypes,
    outline: Bool = false
) {

Button Use Case

  • ButtonListViewController
lazy var mkButton: UIButton = {
    let v = UIButton()
    v.setTitle("Button", for: .normal)
    return v
}()
-----------------------------------------
self.mkButton
    .setButtonLayout(
        title: "지정할 Title을 입력하세요",
        size: .medium,
        primaryType: buttonType,
        outline: self.isOutLine
    )

Colors

Color Methods

  • Colors 는 Autogen Code 입니다
  • Source/ 내 Assets.xcassets 파일의 Colors 폴더을 참조하여 자동으로 enum이 생성됩니다
run 
- cd Scripts
- sh gen_colorset.sh

  • setColorSet
    • 생성된 Colorset 을 기준으로 UIColor를 반환합니다
static func setColorSet(_  colorRawValue: Colors) -> UIColor {
    var color: UIColor = .black
    color = UIColor(named: colorRawValue.rawValue, in: Bundle.module, compatibleWith: nil)!
    return color
}

Asset Colors

  • 상기 Autogen을 통해 생성되는 코드는 아래와 같습니다
public enum Colors: String {
    case background
    case background_elevated
    ...
}

예시 이미지

Color Use Case

self.view.backgroundColor = UIColor.setColorSet(.background)

TextView

TextView Types

  • Text View 의 타입을 지정합니다
    • outline 과 fill 로 설정할 수 있으며 fill 은 배경색과 함께 옅은 outline으로 설정됩니다
public enum TextViewTypes: CaseIterable {
    case outLine
    case fill
}

TextView Status

@objc public enum TextViewStatus: Int, CaseIterable {
    case normal // 기본 상태
    case activate // Focused 상태
    case error // 에러
    case disabled // 비 활성화
}

TextView Options

/// 텍스트 뷰를 구성하는 값을 적용합니다
/// - Parameters:
/// - textViewHeight: Textview 높이를 고정하는 경우 사용됩니다
/// - placeHolder: placeholer text
/// - limitCount: 최대 글자 수
/// - autoLimitCountErrorMessage: 최대 글자수 도달 시 해당 메시지로 에러가 설정됩니다
/// - title: 텍스트 필드 제목 영역 입니다 적용 시 최대 높이가 변경됩니다
/// - helperText: 하단 설명 영역입니다 적용 시 최대 높이가 변경됩니다
/// - counter: 상단 카운트 설정 여부입니다 적용 시 최대 높이가 변경됩니다
/// - doneAccessory : 키보드의 닫기 버튼을 추가합니다
/// - clearAccessory : 텍스트 뷰를 클리어하는 버튼이 사용됩니다
public struct MKTextViewOptions {
    public var textViewHeight: CGFloat = 0.0
    public var inputType: TextViewTypes = .outLine
    public var placeHolder: String = ""
    public var limitCount: Int = 0
    public var autoLimitCountErrorMessage: String? = nil
    public var title: String? = nil
    public var helperText: String? = nil
    public var counter: Bool = false
    public var doneAccessory: Bool = false
    public var clearAccessory: Bool = false
}

TextView Delegate

@objc public protocol MKTextViewDelegate: AnyObject {

    /// An textView did count limitted
    /// - Parameter textView: The MKTextView that textView was called in
    /// - Parameter status: textView status - textViewStatus
    /// - important : Trigger Only Limit Count is Not 0
    @objc optional func textViewLimitted(_ textView: MKTextView, limitted: Bool)

    /// An textView did change Status
    /// - Parameter textView: The MKTextView that textView was called in
    /// - Parameter status: textView status - textViewStatus
    @objc optional func textViewStatusDidChange(_ textView: MKTextView, status: TextViewStatus)

    /// An textView did change Text
    /// - Parameter textView: The MKTextView that textView was called in
    /// - Parameter text: textView text
    @objc optional func textViewTextDidChange(_ textView: MKTextView, text: String)

    /// An textView DidBeginEditing
    /// - Parameter textView: The MKTextView that textView was called in
    @objc optional func textViewTextDidBeginEditing(_ textView: MKTextView)

    /// An textView textViewTextDidEndEditing
    /// - Parameter textView: The MKTextView that textView was called in
    @objc optional func textViewTextDidEndEditing(_ textView: MKTextView)
}

TextView UseCase

  • TextView를 Tableview에서 활용하는 경우 높이값에 따라 UITableView.automaticDimension 이 필요한 경우를 위해 Configure 시 tableview를 추가할 수 있습니다

  • Configure TextView

/* class MKTextView */ 
func configure(
    option: MKTextViewOptions,
    tableView: UITableView? = nil,
    customToolbar: Bool = false
) {
/* initialize TextView*/
lazy var mkTextView: MKTextView = {
    let v = MKTextView()
    return v
}()
....
/* Set TextView Options */
let option = MKTextViewOptions(
    inputType: .outLine,
    placeHolder: "TextView PlaceHolder",
    limitCount: 10,
    autoLimitCountErrorMessage: "Text is Limitted",
    title: "Title + Counter + Limit Description",
    helperText: "description for TextView",
    counter: true
)
....
/* Configure to TextView*/
mkTextView.configure(option: op, tableView: tableView)

TextField

Textfield Types

  • Text Field 의 타입을 지정합니다
    • outline 과 fill 로 설정할 수 있으며 fill 은 배경색과 함께 옅은 outline으로 설정됩니다
public enum TextFieldTypes: CaseIterable {
    case outLine
    case fill
}

Textfield Status

@objc public enum TextFieldStatus: Int, CaseIterable {
    case normal // 기본 상태
    case activate // Focused 상태
    case error // 에러
    case disabled // 비 활성화
}

Textfield Options

/// 텍스트 필드를 구성하는 값을 적용합니다
/// - Parameters:
/// - placeHolder: placeholer text
/// - limitCount: 최대 글자 수
/// - autoLimitCountErrorMessage: 최대 글자수 도달 시 해당 메시지로 에러가 설정됩니다
/// - title: 텍스트 필드 제목 영역 입니다 적용 시 최대 높이가 변경됩니다
/// - helperText: 하단 설명 영역입니다 적용 시 최대 높이가 변경됩니다
/// - counter: 상단 카운트 설정 여부입니다 적용 시 최대 높이가 변경됩니다
/// - leadingIcon : 좌측 이미지 심볼을 적용합니다 이미지가 있는 경우 레이아웃이 변경됩니다
public struct MKTextFieldOptions {
    public var inputType: TextFieldTypes = .outLine
    public var placeHolder: String = ""
    public var limitCount: Int = 0
    public var autoLimitCountErrorMessage: String? = nil
    public var title: String? = nil
    public var helperText: String? = nil
    public var counter: Bool = false
    public var leadingIcon: UIImage? = nil
}

Textfield Delegate

@objc public protocol MKTextViewDelegate: AnyObject {

    /// override Textfield
    @objc optional func textFieldShouldReturn(_ textField: MKTextField) -> Bool
    @objc optional func textFieldShouldClear(_ textField: MKTextField) -> Bool

    /// An textfield did count limitted
    /// - Parameter textField: The MKTextField that textfield was called in
    /// - Parameter status: textfield status - TextfieldStatus
    /// - important : Trigger Only Limit Count is Not 0
    @objc optional func textFieldLimitted(_ textField: MKTextField, limitted: Bool)

    // An textfield did change Status
    /// - Parameter textField: The MKTextField that textfield was called in
    /// - Parameter status: textfield status - TextfieldStatus
    @objc optional func textFieldStatusDidChange(_ textField: MKTextField, status: TextFieldStatus)

    /// An textfield did change Text
    /// - Parameter textField: The MKTextField that textfield was called in
    /// - Parameter text: textfield text
    @objc optional func textFieldTextDidChange(_ textField: MKTextField, text: String)

    /// An textfield DidBeginEditing
    /// - Parameter textField: The MKTextField that textfield was called in
    @objc optional func textFieldTextDidBeginEditing(_ textField: MKTextField)

    /// An textfield textFieldTextDidEndEditing
    /// - Parameter textField: The MKTextField that textfield was called in
    @objc optional func textFieldTextDidEndEditing(_ textField: MKTextField
}

Textfield UseCase

  • TextView를 Tableview에서 활용하는 경우 높이값에 따라 UITableView.automaticDimension 이 필요한 경우를 위해 Configure 시 tableview를 추가할 수 있습니다

  • Configure TextField

/* class MKTextField */ 
func configure(
    option: MKTextFieldOptions,
    tableView: UITableView? = nil
) {
/* initialize TextField*/
lazy var mkTextField: MKTextField = {
    let v = MKTextField()
    return v
}()
....
/* Set MKTextField Options */
let option = MKTextFieldOptions(
    inputType: .outLine,
    placeHolder: "TextField PlaceHolder",
    limitCount: 100,
    autoLimitCountErrorMessage: nil,
    title: "Title With Description + Counter",
    helperText: "description for TextField",
    leadingIcon: UIImage(named: "ic_search") ?? nil,
    counter: true
)
....
/* Configure to TextField*/
mkTextField.configure(option: option, tableView: tableView)

SelectBox

SelectBox Types

  • SelectBox 의 타입을 지정합니다
    • outline 과 fill 로 설정할 수 있으며 fill 은 배경색과 함께 옅은 outline으로 설정됩니다
public enum SelectBoxTypes: CaseIterable {
    case outLine
    case fill
}

SelectBox Status

@objc public enum SelectBoxStatus: Int, CaseIterable {
    case normal // 기본 상태
    case activate // Focused 상태
    case error // 에러
    case disabled // 비 활성화
}

SelectBox Options

/// 셀렉트 박스 를 구성하는 값을 적용합니다
/// - Parameters:
/// - placeHolder: placeholer text
/// - title: 필드 제목 영역 입니다 적용 시 최대 높이가 변경됩니다
/// - helperText: 하단 설명 영역입니다 적용 시 최대 높이가 변경됩니다
public struct MKSelectBoxOptions {
    public var inputType: SelectBoxTypes = .outLine
    public var placeHolder: String = ""
    public var title: String? = nil
    public var helperText: String? = nil
}

SelectBox Delegate

public protocol MKSelectBoxDelegate: AnyObject {
    // Select box Selected
    /// - Parameter selectBox: The MKSelectBox that selectBox was called in
    func didSelected(_ selectBox: MKSelectBox)

    // Select box didChangeStatus
    /// - Parameter selectBox: The MKSelectBox that selectBox was called in
    /// - Parameter status: selectBox status - SelectBoxStatus
    func didChangeStatus(_ selectBox: MKSelectBox, status: SelectBoxStatus)
}

SelectBox UseCase

  • TextView를 Tableview에서 활용하는 경우 높이값에 따라 UITableView.automaticDimension 이 필요한 경우를 위해 Configure 시 tableview를 추가할 수 있습니다

  • Configure SelectBox

/* class MKSelectBox */ 
func configure(
    option: MKSelectBoxOptions,
    tableView: UITableView? = nil
) {
/* initialize SelectBox*/
lazy var mkSelectBox: MKSelectBox = {
    let v = MKSelectBox()
    return v
}()
....
/* Set MKSelectBox Options */
let option = MKSelectBoxOptions(
    inputType: .outLine,
    placeHolder: "Select box PlaceHolder",
    title: "Title With Description",
    helperText: "description for select box"
)
....
/* Configure to TextField*/
mkSelectBox.configure(option: option, tableView: tableView)

Switch

Switch Constants

public  struct  SwitchConstants {
    /// 길이
    static  var viewWidth: CGFloat = 48
    /// 높이
    static  var viewHeight: CGFloat = 28
    /// 애니메이션 시간
    static  var animateDuration: CGFloat = 0.25
    /// 버튼 높이
    static  var circleHeight: CGFloat = 24
    /// 버튼 길이
    static  var circleWidth: CGFloat = 24
    /// 활성화 + 켜졌을 경우 배경 색
    static  var enableOnBackgroundColor: UIColor = UIColor.setColorSet(.purple500)
    /// 활성화 + 꺼졌을 경우 배경 색
    static  var enableOffBackgroundColor: UIColor = UIColor.setColorSet(.grey100)
    /// 비 활성화 + 켜졌을 경우 배경 색
    static  var disableOnBackgroundColor: UIColor = UIColor.setColorSet(.grey300)
    /// 비 활성화 + 꺼졌을 경우 배경 색
    static  var disableOffBackgroundColor: UIColor = UIColor.setColorSet(.grey300)
}

Switch Delegate

public protocol SwitchDelegate: AnyObject {
    func isOnValueChange(switch: MKSwitch, isOn: Bool)
}

Switch Usecase

  • Disabled 상태에서는 isOn statusreturn 됩니다
/* class MKSwitch: UIView */
--- 
/// set switch status
public func setSwitch(isOn: Bool)

/// set isEnabled
public var isEnabled: Bool = true

/// initialize switch
lazy var mkSwitch: MKSwitch = {
    let v = MKSwitch()
    return v
}()

CheckBox

CheckBox Options

/// 체크박스를 구성하는 값을 적용합니다
/// - Parameters:
/// - text : 컨텐츠 내용
/// - isEnabled : enable 여부를 설정합니다
/// - textColor : 제목 색상 (title Label에 직접 접근하여 변경할 수 있습니다)
/// - isOn: On/Off Status
public struct MKCheckBoxOptions {
    public var text: String? = nil
    public var isEnabled: Bool = true
    public var textColor: Colors = .text_primary
    public var isOn: Bool = false
}

CheckBox Delegate

public protocol MKCheckBoxDelegate: AnyObject {
    func didSelected(_ selectBox: MKCheckBox)
    func didChangeStatus(_ selectBox: MKCheckBox, status: Bool)
}

CheckBox Usecase

/// initialize Checkbox
lazy var mkCheckBox: MKCheckBox = {
    let v = MKCheckBox()
    return v
}()

/// set checkbox options
let option = MKCheckBoxOptions(
    text: "enabled + isOn",
    isEnabled: true,
    textColor: .text_primary,
    isOn: true
)

/// configure
mkCheckBox.configure(option: option)


Todo

  • alignTextBelow
    • iOS 15에서 추가된 UIButton.Configuration 대응
  • updateTitleText
    • 내부에서 SetTitle에 자동으로 처리하도록 개선 필요
  • 각 Foundation 의 속성값을 유동적으로 조정할 수 있도록 enum 에서 struct 로 변경