Swift uzantısı örneği


82

Başlangıçta böyle bir şeyi nasıl yapacağımı bilmek istiyordum

UIColor.myCustomGreen

böylece kendi renklerimi tanımlayabilir ve bunları uygulamamda kullanabilirim.

Daha önce uzantılar üzerinde çalışmıştım ve muhtemelen onları problemimi çözmek için kullanabileceğimi düşündüm, ancak uzantıları nasıl kuracağımı tam olarak hatırlayamadım. "Swift uzantısı" için bu yazının yazıldığı sırada Google'da arama yapmak, dokümantasyon , birkaç uzun öğretici ve oldukça yardımcı olmayan bir Stack Overflow sorusuyla sonuçlandı .

Yani cevaplar orada, ancak dokümanlar ve öğreticilerde biraz araştırma yapmak gerekiyor. Stack Overflow'a bazı daha iyi arama anahtar kelimeleri eklemek ve uzantıların nasıl kurulduğuna dair hızlı bir tazeleme sağlamak için bu soruyu ve aşağıdaki cevabı yazmaya karar verdim.

Özellikle bilmek istedim:

  • Uzantılar nerede bulunur (dosya ve adlandırma kuralı)?
  • Uzantı sözdizimi nedir?
  • Birkaç basit yaygın kullanım örneği nelerdir?

Yanıtlar:


173

Bir uzantı oluşturmak

Dosya> Yeni> Dosya ...> iOS> Kaynak> Swift Dosyası ile yeni bir swift dosyası ekleyin . Ona ne istersen diyebilirsin.

Genel adlandırma kuralı buna TypeName + NewFunctionality.swift adını vermektir .

görüntü açıklamasını buraya girin

Örnek 1 - Double

Çift + Dönüşümler.swift

import Swift // or Foundation

extension Double {

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

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

Kullanım:

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

Örnek 2 - String

Dize + Kısayollar. Swift

import Swift // or Foundation

extension String {

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

Kullanım:

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

İşte bazı daha yaygın Stringuzantılar.

Örnek 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)
    }
}

Ayrıca buraya bakın .

Kullanım:

view.backgroundColor = UIColor.customGreen

görüntü açıklamasını buraya girin

Notlar

  • Bir uzantı tanımladığınızda, tıpkı yerleşik sınıf işlevleri gibi uygulamanızın herhangi bir yerinde kullanılabilir.
  • İşlev veya özellik sözdiziminin tam olarak nasıl görünmesi gerektiğinden emin değilseniz, Optionbenzer bir yerleşik yönteme + tıklayabilirsiniz. Örneğin, Option+ tıkladığımda UIColor.greenColorbeyanın olduğunu görüyorum class func greenColor() -> UIColor. Bu bana özel yöntemimi nasıl oluşturacağım konusunda iyi bir ipucu veriyor.
  • Uzantılar için Apple Belgeleri
  • Objective-C'de uzantılar kategoriler olarak bilinir.

2
neden UIColor classişlevi tanımlamak için kullanılırken String değil?
JZAU

5
@jacky, işlevin önündeki 'class' anahtar sözcüğü onu bir Örnek Yönteminin aksine statik bir Tür Yöntemi yapar. Bu şekilde, özel rengi elde etmek için UIColor'u kullanmak zorunda kalmazsınız. Daha fazla ayrıntı için bu yanıta bakın: stackoverflow.com/a/31630431/3681880
Suragch

bu beni bugün kapsayacak, ancak benzersiz uzantıları, yani sınıf hayvanı, uzatma ineği, uzatma kedisi, uzatma köpeği nasıl yaparsınız?
Lorne K

2
@LorneK, Bana alt sınıflamadan bahsediyormuşsunuz gibi geliyor . Bir uzantı, yalnızca mevcut bir sınıf türüne ek işlevler veya yöntemler ekler. Bir karşılaştırma için bu makaleye de bakın .
Suragch

Xcode'un uzantı yöntemlerini anında almayabileceğini ve çağrılarınızı çözülmemiş olarak kabul edebileceğini unutmamak gerekir. Bir yapının tetiklenmesi bunu otomatik olarak yapar! Zor.
Akash Agarwal

9

Bunu bazı yeni uzantı yöntemlerini deneyin:

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!
  }
}

Tarih

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
  }
}

Bu işlevleri çağırmak:

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 örneği:

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
    }
}

Sizin durumunuzda, orijinal UITextField'ı genişletmek yerine UITextField'den miras alınan yeni bir sınıf oluşturmayı tercih ederim. Daha fazla esneklik sağlar. Aynı uygulamada metin alanlarım için farklı stiller kullanmak istersem ne olur? Uzantılar, genel olarak orijinal sınıfa eklenir.
Michal Cichon

4

Metnin altını çiz UITextField

İşlevde kullanılır ViewDidLoad()

firstNametext.underlined(0.5)

Uzantı

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 }
    }
}

Selam! Stackoverflow'a hoş geldiniz! Stackoverflow ile ilgili iyi cevaplar, genellikle yanlarında bir çeşit açıklamaya sahip olacaktır. Bir sonraki soruyu yanıtladığınızda düşünmeniz gereken bir şey!
Qwerty

@Qwerty, açıklaması vardı ama kod gibi biçimlendirilmişti. Yeniden biçimlendirdim.
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"
    }

}

Kullanım :

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

Umarım farkın ne olduğunu anlarsın. Class func ile başlayan Function'dan biri sadece func ile başlayan diğeri . hangisini beğendiğinizi kullanabilirsiniz.


uikit'i içe aktardığımda hata veriyor, yanlış bir şey mi yapıyorum?
Nabeel Khan

0

En iyi uzantı ve kullanışlılık başlatıcı örneklerinden biri:

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

Aşağıdaki şekillerde kullanabilirsiniz:

  1. Aktiviteyi başlatın Gösterge

    let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge, color: .gray,  placeInTheCenterOf: view)
    
  2. Aktivite göstergesini canlandırmaya başlayın

    activityIndicator.startAnimating()
    
  3. Aktivite göstergesini canlandırmayı durdur

    activityIndicator.stopAnimating()
    

0

Marka kılavuzlarında olduğu gibi belirli bir tonda bir renk kullanmayı seviyorsanız: 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)
    }
}

Kodunuzda

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

0

İşte UITableView'daki hücrelerle çalışan göz alıcı bir animasyon efektinin bir uzantı örneği. Siz UITableView'da gezinirken her hücre bir nokta kaynağından normal boyuta büyür. Animasyon zamanlamasını istediğiniz gibi ayarlayın.

Kaydırma sırasında her hücre biraz zaman aşımıyla göründüğünden, etki güzelce dalgalanıyor! Efekti gösteren bu 15 saniyelik klibe bakın: 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)

    }
}

Uzantıyı kullanmak için, aşağıda gösterildiği gibi hücreye hücreye döndürülmeden hemen önce bir çağrı yaparsınız:


            cell.growCellDuringPresentation(thisCell: cell)
            return cell

Bir koleksiyon görünümü için hücreleri döndürürken aynı yöntemin çalıştığını unutmayın.

Sunum sırasında hücreleri döndürmesi dışında tam olarak aynı şekilde çalışan bir uzantı:


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)

    }
}

Benzer şekilde adlandırılır:


            cell.rotateCellDuringPresentation(thisCell: cell)
            return cell

Hücreleri X yönünde çeviren aynı satırlar boyunca bir uzantı.


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)

    }
}

Benzer şekilde adlandırılır:


            cell.translateCellDuringPresentation(thisCell: cell)
            return cell
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.