Swift 확장 예제


82

원래 이렇게 만드는 법을 알고 싶었어요

UIColor.myCustomGreen

나만의 색상을 정의하고 앱 전체에서 사용할 수 있도록했습니다.

나는 이전에 확장 기능을 공부했고 아마 내 문제를 해결하는 데 사용할 수 있다고 생각했지만 확장 기능을 설정하는 방법을 정확히 기억할 수 없었습니다. 이 글을 쓰는 시점에서 Google에서 "Swift 확장"을 검색하면 문서 , 몇 가지자습서 및 다소 도움이되지 않는 Stack Overflow 질문이 나타납니다 .

그래서 답은 거기에 있지만 문서와 튜토리얼을 파헤쳐 야합니다. 이 질문과 다음 답변을 작성하여 Stack Overflow에 더 나은 검색 키워드를 추가하고 확장이 설정되는 방법에 대한 빠른 복습을 제공하기로 결정했습니다.

구체적으로 알고 싶었습니다.

  • 확장자는 어디에 있습니까 (파일 및 명명 규칙)?
  • 확장 구문은 무엇입니까?
  • 몇 가지 간단한 일반적인 사용 예는 무엇입니까?

답변:


172

확장 만들기

File> New> File ...> iOS> Source> Swift File 로 새 swift 파일을 추가합니다 . 원하는대로 부를 수 있습니다.

일반적인 명명 규칙은 TypeName + NewFunctionality.swift 라고 부르는 것 입니다.

여기에 이미지 설명 입력

예 1- Double

Double + Conversions.swift

import Swift // or Foundation

extension Double {

    func celsiusToFahrenheit() -> Double {
        return self * 9 / 5 + 32
    }

    func fahrenheitToCelsius() -> Double {
        return (self - 32) * 5 / 9
    }
}

용법:

let boilingPointCelsius = 100.0
let boilingPointFarenheit = boilingPointCelsius.celsiusToFahrenheit()
print(boilingPointFarenheit) // 212.0

예 2- String

String + Shortcuts.swift

import Swift // or Foundation

extension String {

    func replace(target: String, withString: String) -> String {
        return self.replacingOccurrences(of: target, with: withString)
    }
}

용법:

let newString = "the old bike".replace(target: "old", withString: "new")
print(newString) // "the new bike"

다음 은 몇 가지 일반적인 String확장입니다.

예 3- UIColor

UIColor + CustomColor.swift

import UIKit

extension UIColor {

    class var customGreen: UIColor {
        let darkGreen = 0x008110
        return UIColor.rgb(fromHex: darkGreen)
    }

    class func rgb(fromHex: Int) -> UIColor {

        let red =   CGFloat((fromHex & 0xFF0000) >> 16) / 0xFF
        let green = CGFloat((fromHex & 0x00FF00) >> 8) / 0xFF
        let blue =  CGFloat(fromHex & 0x0000FF) / 0xFF
        let alpha = CGFloat(1.0)

        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
    }
}

여기도 참조 하십시오 .

용법:

view.backgroundColor = UIColor.customGreen

여기에 이미지 설명 입력

메모

  • 확장을 정의하면 내장 된 클래스 함수처럼 앱의 어느 곳에서나 사용할 수 있습니다.
  • 함수 또는 속성 구문이 정확히 어떻게 표시되어야하는지 확실하지 않은 경우 Option유사한 기본 제공 메서드를 + 클릭 할 수 있습니다 . 예를 들어 Option+ 클릭하면 UIColor.greenColor선언이 class func greenColor() -> UIColor. 그것은 내 사용자 지정 방법을 설정하는 방법에 대한 좋은 단서를 제공합니다.
  • 확장에 대한 Apple 문서
  • Objective-C에서 확장은 카테고리로 알려져 있습니다.

2
UIColor가 class함수를 정의 하는 데 사용하지만 String은 사용하지 않는 이유는 무엇입니까?
JZAU

5
@jacky, 함수 앞의 'class'키워드는 인스턴스 메서드가 아닌 정적 형식 메서드로 만듭니다. 이렇게하면 사용자 지정 색상을 얻기 위해 UIColor를 인스턴스화 할 필요가 없습니다. 자세한 내용은 다음 답변을 참조하십시오. stackoverflow.com/a/31630431/3681880
Suragch

오늘은이 내용이 저를 다루 겠지만, 클래스 동물, 확장 소, 확장 고양이, 확장 개와 같은 고유 확장을 어떻게 수행합니까?
Lorne K

2
@LorneK, 당신이 서브 클래 싱 에 대해 이야기하는 것처럼 들립니다 . 확장은 기존 클래스 유형에 추가 기능이나 메서드를 추가 할뿐입니다. 비교를 위해이 기사 도 참조하십시오 .
Suragch

xcode가 즉시 확장 메서드를 픽업하지 않고 호출이 해결되지 않은 것으로 간주 할 수 있다는 점에 유의할 가치가 있습니다. 빌드를 트리거하면 자동으로 수행됩니다! 교활한.
Akash Agarwal

9

새로운 확장 방법을 시도해보십시오.

UIColor

extension UIColor{
 //get new color from rgb value
  class func RGB(_ red:CGFloat , andGreenColor green:CGFloat, andBlueColor blue:CGFloat, withAlpha alpha:CGFloat) -> UIColor
  {
    let color = UIColor(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
    return color
  }
}

 //return color from comma separated string of RGB paramater
  convenience init(rgbString :String, alpha:CGFloat = 1.0){
    let arrColor = rgbString.components(separatedBy: ",")
    let red:CGFloat = CGFloat(NumberFormatter().number(from: arrColor[0])!)
    let green:CGFloat = CGFloat(NumberFormatter().number(from: arrColor[1])!)
    let blue:CGFloat = CGFloat(NumberFormatter().number(from: arrColor[2])!)
    self.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
  }

  //return color from hexadecimal value
  //let color2 = UIColor(rgbHexaValue: 0xFFFFFFFF)
  convenience init(rgbHexaValue: Int, alpha: CGFloat = 1.0) {
    self.init(red:  CGFloat((rgbHexaValue >> 16) & 0xFF), green: CGFloat((rgbHexaValue >> 8) & 0xFF), blue: CGFloat(rgbHexaValue & 0xFF), alpha: alpha)
  }
}

UITextField

extension UITextField{

//set cornerRadius
  func cornerRadius(){
    self.layoutIfNeeded()
    self.layer.cornerRadius = self.frame.height / 2
    self.clipsToBounds = true
  }

  //set bordercolor
  func borderColor(){
      self.layer.borderColor = TEXTFIELD_BORDER_COLOR.cgColor
      self.layer.borderWidth = 1.0
  }

  //set borderWidth
  func borderWidth(size:CGFloat){
    self.layer.borderWidth = size
  }

  //check textfield is blank
  func blank() -> Bool{
    let strTrimmed = self.text!.trim()//get trimmed string
    if(strTrimmed.characters.count == 0)//check textfield is nil or not ,if nil then return false
    {
      return true
    }
    return false
  }

  //set begginning space - left space
  func setLeftPadding(paddingValue:CGFloat) {
    let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: paddingValue, height: self.frame.size.height))
    self.leftViewMode = .always
    self.leftView = paddingView
  }

  //set end of space
  func setRightPadding(paddingValue:CGFloat){
    let paddingView = UIView(frame: CGRect(x: (self.frame.size.width - paddingValue), y: 0, width: paddingValue, height: self.frame.size.height))
    self.rightViewMode = .always
    self.rightView = paddingView
  }
}

UIFont

extension UIFont{
 // Returns a scaled version of UIFont
  func scaled(scaleFactor: CGFloat) -> UIFont {
    let newDescriptor = fontDescriptor.withSize(fontDescriptor.pointSize * scaleFactor)
    return UIFont(descriptor: newDescriptor, size: 0)
  }
}

UIImage

public enum ImageFormat {
  case PNG
  case JPEG(CGFloat)
}


extension UIImage {
  //convert image to base64 string
  func toBase64() -> String {
    var imageData: NSData
    switch format {
    case .PNG: imageData = UIImagePNGRepresentation(self)! as NSData
    case .JPEG(let compression): imageData = UIImageJPEGRepresentation(self, compression)! as NSData
    }
    return imageData.base64EncodedString(options: .lineLength64Characters)
  }

  //convert string to image
  class func base64ToImage(toImage strEncodeData: String) -> UIImage {
    let dataDecoded  = NSData(base64Encoded: strEncodeData, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
    let image = UIImage(data: dataDecoded as Data)
    return image!
  }

  //Function for store file/Image into local directory. If image is already on the directory then first remove it and replace new image/File on that location
  func storedFileIntoLocal(strImageName:String) -> String{
    var strPath = ""
    let documentDirectory1 = NSString.init(string: String.documentDirectory())
    let imageName:String = strImageName + ".png"
    let imagePath = documentDirectory1.appendingPathComponent(imageName)
    strPath = imagePath
    let fileManager = FileManager.default
    let isExist = fileManager.fileExists(atPath: String.init(imagePath))
    if(isExist == true)
    {
      do {
        try fileManager.removeItem(atPath: imagePath as String)//removing file if exist
        // print("Remove success")
      } catch {
        print(error)
      }
    }
    let imageData:Data = UIImageJPEGRepresentation(self, 0.5)!
    do {
      try imageData.write(to: URL(fileURLWithPath: imagePath as String), options: .atomic)
    } catch {
      print(error)
      strPath = "Failed to cache image data to disk"
      return strPath
    }

    return strPath
  }


  //function for resize image
  func resizeImage(targetSize: CGSize) -> UIImage {
    let size = self.size

    let widthRatio  = targetSize.width  / self.size.width
    let heightRatio = targetSize.height / self.size.height

    // Figure out what our orientation is, and use that to form the rectangle
    var newSize: CGSize
    if(widthRatio > heightRatio) {
      newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
      //                        newSize = size
      newSize = CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
    }

    // This is the rect that we've calculated out and this is what is actually used below
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

    // Actually do the resizing to the rect using the ImageContext stuff
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    self.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
  }
}

데이트

let YYYY_MM_DD_HH_MM_SS_zzzz = "yyyy-MM-dd HH:mm:ss +zzzz"
let YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"
let DD_MM_YYYY = "dd-MM-yyyy"
let MM_DD_YYYY = "MM-dd-yyyy"
let YYYY_DD_MM = "yyyy-dd-MM"
let YYYY_MM_DD_T_HH_MM_SS = "yyyy-MM-dd'T'HH:mm:ss"

extension Date{

  //convert string to date
  static func convertStringToDate(strDate:String, dateFormate strFormate:String) -> Date{
    let dateFormate = DateFormatter()
    dateFormate.dateFormat = strFormate
    dateFormate.timeZone = TimeZone.init(abbreviation: "UTC")
    let dateResult:Date = dateFormate.date(from: strDate)!

    return dateResult
  }

  //Function for old date format to new format from UTC to local
  static func convertDateUTCToLocal(strDate:String, oldFormate strOldFormate:String, newFormate strNewFormate:String) -> String{
    let dateFormatterUTC:DateFormatter = DateFormatter()
    dateFormatterUTC.timeZone = NSTimeZone(abbreviation: "UTC") as TimeZone!//set UTC timeZone
    dateFormatterUTC.dateFormat = strOldFormate //set old Format
    if let oldDate:Date = dateFormatterUTC.date(from: strDate)  as Date?//convert date from input string
    {
      dateFormatterUTC.timeZone = NSTimeZone.local//set localtimeZone
      dateFormatterUTC.dateFormat = strNewFormate //make new dateformatter for output format
      if let strNewDate:String = dateFormatterUTC.string(from: oldDate as Date) as String?//convert dateInUTC into string and set into output
      {
        return strNewDate
      }
      return strDate
    }
    return strDate
  }

  //Convert without UTC to local
  static func convertDateToLocal(strDate:String, oldFormate strOldFormate:String, newFormate strNewFormate:String) -> String{
    let dateFormatterUTC:DateFormatter = DateFormatter()
    //set local timeZone
    dateFormatterUTC.dateFormat = strOldFormate //set old Format
    if let oldDate:Date = dateFormatterUTC.date(from: strDate) as Date?//convert date from input string
    {
      dateFormatterUTC.timeZone = NSTimeZone.local
      dateFormatterUTC.dateFormat = strNewFormate //make new dateformatter for output format
      if let strNewDate = dateFormatterUTC.string(from: oldDate as Date) as String?//convert dateInUTC into string and set into output
      {
        return strNewDate
      }
      return strDate
    }
    return strDate
  }

  //Convert Date to String
  func convertDateToString(strDateFormate:String) -> String{
      let dateFormatter = DateFormatter()
      dateFormatter.dateFormat = strDateFormate
      let strDate = dateFormatter.string(from: self)
//      dateFormatter = nil
      return strDate
  }


  //Convert local to utc
  static func convertLocalToUTC(strDate:String, oldFormate strOldFormate:String, newFormate strNewFormate:String) -> String{
    let dateFormatterUTC:DateFormatter = DateFormatter()
    dateFormatterUTC.timeZone = NSTimeZone.local as TimeZone!//set UTC timeZone
    dateFormatterUTC.dateFormat = strOldFormate //set old Format
    if let oldDate:Date = dateFormatterUTC.date(from: strDate)  as Date?//convert date from input string
    {
      dateFormatterUTC.timeZone = NSTimeZone.init(abbreviation: "UTC")! as TimeZone//set localtimeZone
      dateFormatterUTC.dateFormat = strNewFormate //make new dateformatter for output format
      if let strNewDate:String = dateFormatterUTC.string(from: oldDate as Date) as String?//convert dateInUTC into string and set into output
      {
        return strNewDate
      }
      return strDate
    }
    return strDate
  }

  //Comparison two date
  static func compare(date:Date, compareDate:Date) -> String{
    var strDateMessage:String = ""
    let result:ComparisonResult = date.compare(compareDate)
    switch result {
    case .orderedAscending:
      strDateMessage = "Future Date"
      break
    case .orderedDescending:
      strDateMessage = "Past Date"
      break
    case .orderedSame:
      strDateMessage = "Same Date"
      break
    default:
      strDateMessage = "Error Date"
      break
    }
    return strDateMessage
  }
}

이 함수 호출 :

let color1 = UIColor.RGB(100.0, andGreenColor: 200.0, andBlueColor: 300.0, withAlpha: 1.0)
let color2 = UIColor.init(rgbHexaValue: 800000, alpha: 1.0)
let color3 = UIColor.init(rgbString: ("100.0,200.0,300.0", alpha: 1.0)

self.txtOutlet.cornerRadius()
self.txtOutlet.borderColor()
self.txtOutlet.setLeftPadding(paddingValue: 20.0)
self.txtOutlet.setRightPadding(paddingValue: 20.0)

let yourScaledFont = self.dependentView.font.scaled(scaleFactor: n as! CGFloat)
let base64String = (image?.toBase64(format: ImageFormat.PNG))!
let resultImage = UIImage.base64ToImage(toImage: base64String)
let path = yourImage.storedFileIntoLocal(strImageName: "imagename")

6

Swift 3.0 예제 :

extension UITextField 
{    

    func useUnderline() {
        let border = CALayer()
        let borderWidth = CGFloat(1.0)
        border.borderColor = UIColor.lightGray.cgColor
        border.frame = CGRect(origin: CGPoint(x: 0,y :self.frame.size.height - borderWidth), size: CGSize(width: self.frame.size.width, height: self.frame.size.height))
        border.borderWidth = borderWidth
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true
    }
}

귀하의 경우에는 원래 UITextField를 확장하는 대신 UITextField에서 상속 된 새 클래스를 만드는 것이 좋습니다. 더 많은 유연성을 제공합니다. 동일한 앱에서 텍스트 필드에 다른 스타일을 사용하려면 어떻게해야합니까? 확장은 원래 클래스에 전역 적으로 추가됩니다.
Michal Cichon

4

밑줄 텍스트 UITextField

기능에 사용 ViewDidLoad()

firstNametext.underlined(0.5)

신장

extension UITextField {

    func underlined(_ size:Double){
        let border = CALayer()
        let width = CGFloat(size)
        border.borderColor = UIColor.red.cgColor
        border.frame = CGRect(x: 0, y: self.frame.size.height - width, 
        width:  self.frame.size.width, height: self.frame.size.height)
        border.borderWidth = width
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true }
    }
}

안녕하세요! stackoverflow에 오신 것을 환영합니다! stackoverflow에 대한 좋은 답변은 일반적으로 그와 함께 일종의 설명이 있습니다. 다음에 질문에 답할 때 생각할만한 것입니다!
Qwerty

@Qwerty, 설명이 있었지만 코드처럼 형식화되었습니다. 다시 포맷했습니다.
Suragch

3

UIColor + util.swift

import UIKit


extension UIColor{


    class func getCustomBlueColor() -> UIColor
    {
        return UIColor(red:0.043, green:0.576 ,blue:0.588 , alpha:1.00)
    }

    func getNameofColour() ->String
    {
        return "myOrange"
    }

}

사용법 :

NSLog("\(UIColor.getCustomBlueColor())")
let color=UIColor(red:0.043, green:0.576 ,blue:0.588 , alpha:1.00);
NSLog(color.getNameofColour())

차이점이 무엇인지 이해하시기 바랍니다. func 클래스로 시작하는 Function 중 하나는 func 만 시작하는 다른 함수 입니다. 당신이 좋아하는 것을 사용할 수 있습니다.


uikit을 가져올 때 오류가 발생합니다. 뭔가 잘못하고 있습니까?
Nabeel Khan

0

확장 및 편의 이니셜 라이저의 가장 좋은 예 중 하나 :

 extension UIActivityIndicatorView {
    convenience init(activityIndicatorStyle: UIActivityIndicatorViewStyle, color: UIColor, placeInTheCenterOf parentView: UIView) {
    self.init(activityIndicatorStyle: activityIndicatorStyle)
    center = parentView.center
    self.color = color
    parentView.addSubview(self)
  }
}

다음과 같은 방법으로 사용할 수 있습니다.

  1. activityIndicator 초기화

    let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge, color: .gray,  placeInTheCenterOf: view)
    
  2. 활동 표시기 애니메이션 시작

    activityIndicator.startAnimating()
    
  3. 활동 표시기 애니메이션 중지

    activityIndicator.stopAnimating()
    

0

브랜드 매뉴얼에 사용 된 것과 같은 특정 색조의 색상을 사용하려는 경우 : Swift 4.2 + xcode 9.4.1.

extension UIColor {
    func withTint(tint: CGFloat)->UIColor {

        var tint = max(tint, 0)
        tint = min(tint, 1)
        /* Collect values of sender */
        var r : CGFloat = 0
        var g : CGFloat = 0
        var b : CGFloat = 0
        var a : CGFloat = 0
        self.getRed(&r, green: &g, blue: &b, alpha: &a)

        /* Calculate the tint */
        r = r+(1-r)*(1-tint)
        g = g+(1-g)*(1-tint)
        b = b+(1-b)*(1-tint)
        a = 1

        return UIColor.init(red: r, green: g, blue: b, alpha: a)
    }
}

코드에서

let redWithTint = UIColor.red.withTint(tint: 0.4)

0

다음은 UITableView의 셀에서 작동하는 눈길을 끄는 애니메이션 효과의 확장 예제입니다. UITableView를 스크롤하면 각 셀이 포인트 소스에서 일반 크기로 커집니다. 원하는대로 애니메이션 타이밍을 조정합니다.

스크롤하는 동안 각 셀이 약간의 시간차로 나타나기 때문에 효과가 멋지게 파급됩니다! 효과를 보여주는 15 초 클립을 참조하십시오. https://www.youtube.com/watch?v=BVeQpno56wU&feature=youtu.be


extension UITableViewCell {

    func growCellDuringPresentation(thisCell : UITableViewCell) {

        thisCell.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)

        UIView.animate(withDuration: TimeInterval(0.35), delay: 0.0, options: UIView.AnimationOptions.allowUserInteraction,   animations: {

            thisCell.transform = CGAffineTransform(scaleX: 1, y: 1)

        }, completion: nil)

    }
}

확장을 사용하려면 아래와 같이 셀이 cellForRowAt에서 반환되기 직전에 호출을합니다.


            cell.growCellDuringPresentation(thisCell: cell)
            return cell

컬렉션 뷰에 대해 셀을 반환 할 때도 이와 동일한 방법이 작동합니다.

다음은 프레젠테이션 중에 셀을 회전한다는 점을 제외하면 정확히 동일하게 작동하는 확장입니다.


extension UITableViewCell {

    func rotateCellDuringPresentation(thisCell : UITableViewCell) {

        thisCell.transform = CGAffineTransform(rotationAngle: .pi)

        UIView.animate(withDuration: TimeInterval(0.35), delay: 0.0, options: UIView.AnimationOptions.allowUserInteraction,   animations: {

            thisCell.transform = CGAffineTransform(rotationAngle: 0)

        }, completion: nil)

    }
}

비슷하게 호출됩니다.


            cell.rotateCellDuringPresentation(thisCell: cell)
            return cell

다음은 X 방향으로 셀을 변환하는 동일한 선을 따른 확장입니다.


extension UITableViewCell {

    func translateCellDuringPresentation(thisCell : UITableViewCell) {

        thisCell.layer.transform = CATransform3DMakeTranslation(-300, 0, 0)

        UIView.animate(withDuration: TimeInterval(0.5), delay: 0.0, options: UIView.AnimationOptions.allowUserInteraction,   animations: {

            thisCell.layer.transform = CATransform3DMakeTranslation(0, 0, 0)

        }, completion: nil)

    }
}

비슷하게 호출됩니다.


            cell.translateCellDuringPresentation(thisCell: cell)
            return cell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.