Recently, I have sorted out some small tools in the practice of Swift project. Today, I will sneak them out and expose them to the sun. If there are mistakes, please kindly point them out to make progress and learn together

  • Picture downloader: using the download method in Kingfisher to achieve the batch download of pictures, in order to pass in the picture URL, according to the original order out
/ / images are downloaded callback resultArr: the status of each image download resultImageArr: picture typealias BWImageDownloadCompletionHandle = (_ resultArr: [BWImageDownloadModel]) - > Void / / single image download callback typealias BWSingleImagDownloadCompletionHadnle = (_ imageModel: BWImageDownloadModel) -> Void /// Image data download tool class BWImageDownloadManager: NSObject {staticletShared = BWImageDownloadManager() /// -parameters: /// -sourceImageUrls: Image link data /// - completionHadle: callback open func asyncDownloadImageWith(sourceImageUrls: [String], completionHadle: @ escaping BWImageDownloadCompletionHandle) {/ / create scheduling groupletDispatchGroup: dispatchGroup = dispatchgroup.init () // Create a concurrent queuelet concurrentQueue: DispatchQueue = DispatchQueue.init(label: "", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: Model var resultImageDic = Dictionary<Int, BWImageDownloadModel>.init()if sourceImageUrls.count > 0 {
            for (index, url) in sourceImageUrls.enumerated() {
                var imageUrl: String = url
                if imageUrl.contains("") {/ / remove the Spaces imageUrl = imageUrl urlPath replacingOccurrences (of:"", with: ""} / /if imageUrl.count <= 0 {
//                   assert(false."The url passed cannot be an empty string.") / /} / / to encode the url imageUrl = imageUrl urlStringEncodingByURLQueryAllowed () dispatchGroup. Enter () concurrentQueue. Async {  ImageDownloader.default.downloadImage(with: URL(string: imageUrl)! , retrieveImageTask: nil, options: nil, progressBlock: { (a, b)in
                        
                    }) { (image, error, url, imageData) in
                        iferror ! = nil { BWLog("\(index) image link \(imageUrl) failed to download \(error!) ")}letimageModel = self.initDownloadImageModel(image: image, error: error, url: url, imageData: ResultImageDic [index] = imageModel dispatchgroup.leave ()}} }} // wait for the thread to notify dispatchgroup.notify (queue: dispatchqueue.main) {var resultImageArr = Array<BWImageDownloadModel>.init()for (index,_) in sourceImageUrls.enumerated() { resultImageArr.append(resultImageDic[index]!) } completionHadle(resultImageArr)}} /// -parameters: /// -source/// - completionHandle: callback open func downloadSingleImageWith(sourceImageUrl: String? , completionHandle: @escaping BWSingleImagDownloadCompletionHadnle) { var imageUrl =sourceImageUrl ?? ""
        if imageUrl.contains("") {/ / remove the Spaces imageUrl = imageUrl urlPath replacingOccurrences (of:"", with: ""} // Encode the link imageUrl =sourceImageUrl! .urlStringEncodingByURLQueryAllowed() ImageDownloader.default.downloadImage(with: URL(string: imageUrl)! , retrieveImageTask: nil, options: nil, progressBlock: { (a, b)in
            
        }) { (image, error, url, imageData) in
            letimageModel = self.initDownloadImageModel(image: image, error: error, url: url, imageData: ImageData) completionHandle(imageModel)}} // Create the imageModel internal func initDownloadImageModel(image: UIImage? , error: NSError? , url: URL? , imageData: Data?) -> BWImageDownloadModel {let imageModel = BWImageDownloadModel.init()
        imageModel.image = image
        imageModel.error = error
        imageModel.url = url
        imageModel.imageData = imageData
        returnImageModel} extension BWImageDownloadManager {// Kingfisher clear all cache open funcclearImageCache() {// Clear the disk cache self.clearDiskCache() // Clear the network cache self.clearMemoryCache() Or more than the hard disk limit the size of the self. ClearExpiredDiskCache ()} / / / to empty the hard disk cache open funcclearDiskCache() {KingfisherManager. Shared. Cache. ClearDiskCache ()} / / / empty web caching open funcclearMemoryCache() {KingfisherManager. Shared. Cache. ClearMemoryCache ()} / / / empty expired or limit the size of the cache more than hard disk open funcclearExpiredDiskCache() {KingfisherManager. Shared. Cache. CleanExpiredDiskCache ()}} / / / images are downloaded model class BWImageDownloadModel: NSObject { var image: UIImage? var error: NSError? var url: URL? var imageData: Data? }Copy the code
  • HUD: SVProgressHUD is a simple package for SVProgressHUD. It is a simple package for SVProgressHUD. After importing SVProgressHUD, the ICONS for each state are not available from the Bundle. The default status ICONS in the tool are usually not used, but are reconfigured according to the UI design
/// HUD basic configuration open class funcconfigProgressHUD() {SVProgressHUD. SetMinimumDismissTimeInterval (1.2) SVProgressHUD. SetShouldTintImages (false) / / stop rendering images to be gaudy SVProgressHUD setCornerRadius (5)} / / / display loaded HUD open class funcshowLoadding() { SVProgressHUD.setForegroundColor(UIColor.white) SVProgressHUD.setBackgroundColor(UIColor.black) Svprogresshud.show ()} hide HUD delay 0.4s to avoid good network status. Open class funchiddenLoadding() { DispatchQueue.main.asyncAfter(deadline: .now()+0.4) {svProgresshud. dismiss()}} /// /// -parameter hint: open class onlyShowHint(hint: String) { SVProgressHUD.setForegroundColor(UIColor.white) SVProgressHUD.setBackgroundColor(UIColor.black) // Add SVProgressHUD to the SVProgressHUD sourcesetInfoImage nonnull image parameters into a nullable SVProgressHUD. SetInfoImage (UIImage. Init (named:""ShowInfo (withStatus: hint)} /// /// -parameter hint: Open class func showErrorWithHint(_ hint: String) { SVProgressHUD.setForegroundColor(UIColor.white) SVProgressHUD.setBackgroundColor(UIColor.black) SVProgressHUD.setErrorImage(UIImage.init(named:"HUD_Error")?? Uiimage.init ()) svProgresshud. showError(withStatus: hint)} /// /// Open Class func showSuccessWithHint(_ hint: String) { SVProgressHUD.setForegroundColor(UIColor.white) SVProgressHUD.setBackgroundColor(UIColor.black) SVProgressHUD.setSuccessImage(UIImage.init(named:"HUD_Success")?? UIImage.init()) SVProgressHUD.showSuccess(withStatus: hint) }Copy the code
  • Secondary encapsulation of Alamofire: This has been written about in previous articles, but I won’t write more about it. Go straight through your portal

  • Data archive and unfile

/// /// -parameters: /// -targetData: archive data /// -path: archive path class func keyedArchiver(targetData: Any, path: String) {if path.isEmpty {
            NSLog("Current path does not exist")
            return
        }
        let localPath: String = self.archiveLocalPath(path: path)
        NSKeyedArchiver.archiveRootObject(targetData, toFile: localPath); /// /// /// -parameter path: storage path /// - Returns: unfile data class func keyedUnArchiver(path: String) -> Any {let localPath: String = self.archiveLocalPath(path: path)
        let objc: AnyObject = NSKeyedUnarchiver.unarchiveObject(withFile: localPath) as AnyObject
        returnObjc} /// Path of the local storage /// /// -parameter path: incoming path /// - Returns: Returns the complete path class func archiveLocalPath(path: String) -> String {let documentPath: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) [0]let localPath: String = String.init(format: "% @ / % @", documentPath,path)
        NSLog("Save to local path: %@".localPath)
        return localPath
    }
Copy the code
  • Custom UITextView and UITextField implementation input word limit Swift version code post is a bit long directly simple link to go Swift version this is an extension of the earlier OC version also post a bar OC version

  • Simple to HandyJson some data to model or model to data method to do a little simple package, easy to HandyJson revision and update, their own projects can as little as possible to move some knife,Kingfisher also has a similar package, here will not post Kingfisher corresponding code

Class BWJsonUtil<T: HandyJSON>: NSObject {/// jsonDic -> model /// /// - Parameter jsonDic: // - static func modelFromJsonDic(_ jsonDic: [String: Any]) -> T? {if jsonDic.count == 0 {
            BWLog("The incoming JSON dictionary is empty")
            return nil
        }
        returnJSONDeserializer<T>. DeserializeFrom (dict: jsonDic)} /// jsonDic -> custom model /// /// - Parameters: /// - jsonDic: Json String /// - designatedPath: route /// - Returns: custom model static func modelFromJsonDic(_ jsonDic: [String:) static func modelFromJsonDic(_ jsonDic: [String:) Any], designatedPath: String) -> T? {returnJSONDeserializer<T>.deserializeFrom(dict: jsonDic, designatedPath: /// /// -parameter jsonArr: json array /// - Returns: Static func modelArrayFromJsonArray(_ jsonArr: [Any]) -> [T]? {if jsonArr.isEmpty == true {
            BWLog("The incoming JSON array is empty")
            return nil
        }
        returnJSONDeserializer<T>.deserializeModelArrayFrom(array: jsonArr) as? [T] } /// jsonString -> model /// - Parameters: Static func modelFromJsonString(_ jsonString: String) -> T? {static func modelFromJsonString(_ jsonString: String) -> T? {if jsonString == "" || jsonString.count == 0 {
            BWLog("The incoming JSON string is empty");
            return nil
        }
        returnJSONDeserializer<T>.deserializeFrom(json: jsonString) } /// JsonString -> model /// /// - Parameters: /// - jsonString: JsonString // - designatedPath: route /// - Returns: static func modelFromJsonString(_ jsonString: String, designatedPath: String) -> T? {returnJSONDeserializer<T>.deserializeFrom(json: jsonString, designatedPath: DesignatedPath)} /// json string -> custom model array /// -parameters: /// -jsonString: json string /// -modelType: Static func modelArrayFromJsonString(_ jsonString: String) -> [T]? {static func modelArrayFromJsonString(_ jsonString: String) -> [T]?if jsonString == "" || jsonString.count == 0 {
            BWLog("The incoming JSON string is empty")
            return nil
        }
        returnJSONDeserializer<T>.deserializeModelArrayFrom(json: JsonString) as? [T]} /// /// -parameters: // -jsonString: json string // -DesignatedPath: Static func modelArrayFromJsonString(_ jsonString: String, designatedPath: String) -> [T]? {static func modelArrayFromJsonString(_ jsonString: String, designatedPath: String) -> [T]?returnJSONDeserializer<T>.deserializeModelArrayFrom(json: jsonString, designatedPath: [T]} static func jsonStringFromModel(_ model:) static func jsonStringFromModel(_ model:) T?) -> String {if model == nil {
            BWLog("The model passed in is nil.")
            return ""
        }
        return(model? .toJSONString())! } // static func jsonDicFromModel(_ model: T?) {// static func jsonDicFromModel(_ model: T?); -> [String: Any] {if model == nil {
            BWLog("The model passed in is nil.")
            return[:]}return (model?.toJSON())!
    }
}
Copy the code
  • Three linkage address picker: in the previous article has also been exhibited, not separate paste code, go directly to you

  • I would like to say that I would like to retrieve all the items I would like to retrieve. I would like to retrieve all the items I would like to retrieve

Extension UIView {/// addclosure: addclosure: addclosure: addclosure: addclosure: addclosure: addclosure: addclosure: addclosure ConstraintMaker) -> Void) {self.snp.makeconstraints (closure)} New constraint public func remakeConstraints(_ closure: (_ make:) ConstraintMaker) - > Void) {self. SNP. RemakeConstraints (closure)} / / / / / / update constraints - Parameter closure: New constraint public func updateConstraints(_ closure: (_ make:) ConstraintMaker) -> Void) { self.snp.updateConstraints(closure) } }Copy the code
  • Hide and show the bottom line of navigation bar & Hide and show the bottom line of UIToolBar
Extension UINavigationBar {// Hide the bottom of the navigation bar line funchideBottomHairline() {
        letbottomImageV = hairlineImageViewInNavigationBar(view: self) bottomImageV? .isHidden =true} // Display the bottom line of the navigation bar funcshowBottomHairLine() {
        letbottomImageV = hairlineImageViewInNavigationBar(view: self) bottomImageV? .isHidden =false} / / find the navigation bar at the bottom of the thread private func hairlineImageViewInNavigationBar (view: UIView) - > UIImageView? {ifView. isKind(of: uiImageView.self) && view.height <= 1.0 {return view as? UIImageView
        }
        for subView in view.subviews {
            if let imageView = hairlineImageViewInNavigationBar(view: subView) {
                return imageView
            }
        }
        returnNil}} extension UIToolbar {// Hide funchideHairline() {
        lettoolBarImageView = hairlinImageViewInToolBar(view: self) toolBarImageView? .isHidden =true} // show funcshowHairline() {
        lettoolBarImageView = hairlinImageViewInToolBar(view: self) toolBarImageView? .isHidden =false
    }
    
    private func hairlinImageViewInToolBar(view: UIView) -> UIImageView? {
        ifView. isKind(of: uiImageView.self) && view.height <= 1.0 {return view as? UIImageView
        }
        for subView in view.subviews {
            if let imageView = hairlinImageViewInToolBar(view: subView) {
                return imageView
            }
        }
        return nil
    }
}
Copy the code
  • Easy use of MJRefresh: Extends the UIScrollView method
Extension UIScrollView {/// add refresh header /// /// -parameter handle: refresh event /// - Returns: Refresh head @ discardableResult / / ignore the return value of warning the public func bw_addRefreshHeaderWithHandle (_ handle: @escaping () -> Void) -> MJRefreshStateHeader {let header: MJRefreshStateHeader = MJRefreshStateHeader.init(refreshingBlock: handle)
        header.stateLabel.font = BWSystemRegularFont(fontSize: 14)
        header.stateLabel.textColor = color999999
        self.mj_header = header
        returnself.mj_header as! /// /// -parameter handle: refresh event /// - Returns: Refresh the tail @ discardableResult public func bw_addPagingRefreshFooterWithHandle (_ handle: @escaping () -> Void) -> MJRefreshAutoNormalFooter {let footer: MJRefreshAutoNormalFooter = MJRefreshAutoNormalFooter.init(refreshingBlock: handle)
        footer.stateLabel.font = BWSystemRegularFont(fontSize: 14)
        footer.stateLabel.textColor = color999999
        self.mj_footer = footer
        returnself.mj_footer as! MJRefreshAutoNormalFooter} / / / add a refresh tail / / / / / / - Parameters: / / / - notice: there is no more data hint text / / / - handle: Refresh event / / / - Returns: refresh tail @ discardableResult public func bw_addPagingRefreshFooterWithNotice (_ notice: String, handle: @escaping () -> Void) -> MJRefreshAutoNormalFooter {let footer = self.bw_addPagingRefreshFooterWithHandle(handle)
        footer.setTitle(notice, for: MJRefreshState.noMoreData)
        returnFooter} /// start refreshing funcbw_startRefreshing() {
        ifself.mj_header ! = nil { self.mj_header.beginRefreshing() }ifself.mj_footer ! = nil { self.mj_footer.isHidden =true} // Avoid the offset and scrolling problem of self. setContentOffset(CGPoint. Zero, animated:false} // finish refreshing funcbw_endRefreshing() {
        ifself.mj_header ! = nil { self.mj_header.endRefreshing() }ifself.mj_footer ! = nil { self.mj_footer.resetNoMoreData() self.mj_footer.isHidden =false}} // no more data funcbw_pagingRefreshNoMoreData() {
        ifself.mj_footer ! = nil { self.mj_footer.endRefreshingWithNoMoreData() } } }Copy the code
  • Retrieves all parameters and their values in the Url: returned as a key:value dictionary
Extention String {/// Get all parameters of the URL /// /// - Returns: Func allUrlParams() -> Dictionary<String, Any> {var urlString: String = self var Dictionary: Dictionary = [String: Any]()ifUrlString. Count > 0 {/ / url encoding to remove links that exist in special characters urlString = urlString. AddingPercentEncoding (withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!let urlComponents: NSURLComponents = NSURLComponents.init(string: urlString)!
            let urlQuerys: Array = urlComponents.queryItems!
            for items:URLQueryItem in urlQuerys {
                let value = items.value
                dictionary[items.name] = value ?? ""}}return dictionary
    }
}
Copy the code
  • String extension methods:
/// /// - Returns: func validatePostalcode() -> Bool {let nameRegEx: String = "^[0-8]\\d{5}(? ! \\d)$"
        returnSelf. isMatchsRegualExp(string: nameRegEx)} /// /// - Returns: func validateUrl() -> Bool {self.isMatchsRegualExp(string: nameRegEx)}let nameRegEx: String = "^((http)|(https))+:[^\\s]+\\.[^\\s]*$"
        returnSelf. isMatchsRegualExp(string: nameRegEx)} Func validateIdentifyCard() -> Bool {let nameRegEx: String = "^(\\d{14}|\\d{17})(\\d|[xX])$"
        returnSelf. isMatchsRegualExp(string: nameRegEx)} /// /// - Returns: func validateEmailAddress() -> Bool {self.isMatchsRegualExp(string: nameRegEx)}let nameRegEx: String = "[A Za - z0-9. + - _ %] + @ [A - Za - z0-9. -] + \ \ [A Za - z] {2, 4}"
        returnSelf. isMatchsRegualExp(string: nameRegEx)} Func validateMobilNumber() -> Bool {/** * Mobile number * mobile: 134 [0 to 8], 135136137138139150151157158159182187188170, 5 * unicom: 130131132152155156185186170 9 * telecom: 9153180189170 * 133134 / / * * * China mobile: China Mobile 11 * 134-8 0 and 3, 135136137138139150151157158159182187188170 5 12 * /let CM: String = "^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d|705)\\d{7}$"/ * * 15 * China Unicom: China Unicom 16 * 130131132152155156185186170 September 17 * /let CU: String = "^1((3[0-2]|5[256]|8[56])\\d|709)\\d{7}$"/ * * * 20 China Telecom, China Telecom, 21 * 133134, 9153180189170, 22 * /let CT: String = "^1((33|53|8[09])\\d|349|700)\\d{7}$"/ * * 25 * mainland fixed-line and PHS 26 * area code: 010020021022023024025027028029 * number 27: seven or eight 28 * /let PHS: String = "^ 0 (10 (0-5789) | | 2 \ \ d {3}) \ \ d {7, 8} $"
        if self.isMatchsRegualExp(string: CM) == true || self.isMatchsRegualExp(string: CU) == true || self.isMatchsRegualExp(string: CT) == true || self.isMatchsRegualExp(string: PHS) {
            return true
        }
        return false} /// predicate filter /// -parameter string: checked string func isMatchsRegualExp(string: string) -> Bool {let predicate: NSPredicate = NSPredicate.init(format: "SELF MATCHES %@", string)
        returnpredicate.evaluate(with: The self)} / / / to encode a url To prevent the identification of Chinese or other special characters cannot be public func urlStringEncodingByURLQueryAllowed () - > String {let urlString: String = self
        returnurlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! } / / / avoidfloat/// /// - Returns: double func doubleFromDecimalString() -> double {let num: Double = Double(self)!
        let string: String = String(format: "%lf", num)
        returnNsdecimalnumber.init (string: string).doubleValue} /// Double string rounding /// /// - Returns: Func decimalStringFromRound() -> String {let roundUp: NSDecimalNumberHandler = NSDecimalNumberHandler.init(roundingMode: .plain, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
        var number: NSDecimalNumber = NSDecimalNumber.init(string: self)
        number = number.rounding(accordingToBehavior: roundUp)
        let roundString: String = String(format: "%.2f", number.doubleValue)
        return roundString
    }  
Copy the code
  • Easily set the position and gap of UIButton image and text
/// /// -left: image on left /// -right: image on right /// -top: image on top /// -bottom: image on bottom enum BWButtonImagePosition {case left
    case right
    case top
    case/// Set the position of the image and the spacing between the image and the text (if using layout, call the parent view layoutIfNeeded) /// /// -parameters: Func buttonImagePosition(_ positon: BWButtonImagePosition, spacing: CGFloat) {// Image view width and heightletimageWidth = self.imageView? .width ?? 0.0letimageHeight = self.imageView? .height ?? 0.0 / / text Here don't use (self titleLabel. Bounds. Size. The width of 0)lettitleWidth = self.titleLabel? .text? .boundingRectWithSize(self.size, font: self.titleFont ?? BWSystemRegularFont(fontSize: 17)).width ?? 0.0lettitleHeight = self.titleLabel? .text? .boundingRectWithSize(self.size, font: self.titleFont ?? BWSystemRegularFont(fontSize: 17)).height ?? 0.0 // The X/Y offset in the center of the imageletImageOffsetX = (imageWidth + titleWidth) / 2.0 - imageWidth / 2.0;letImageOffsetY = imageHeight / 2.0 + spacing / 2.0; // Title center X/Y offsetletWidth = imageWidth + titleWidth / 2.0letHalfWidth = (imageWidth + titleWidth) / 2.0let titleOffsetX = width - halfWidth
        let titleOffsetY = titleHeight / 2 - spacing / 2
        
        switch positon {
        caseSelf. imageEdgeInsets = UIEdgeInsets. Init (top: 0, left: -spacing / 2.0, bottom: 0, right: Self. titleEdgeInsets = uiedGeInsets. init(top: 0, left: 0, bottom: 0, right: -spacing / 2.0)caseSelf. imageEdgeInsets = UIEdgeInsets. Init (top: 0, left: titleWidth + 2.0, bottom: 0, right: 0) -(titleWidth + spacing / 2.0)) self.titleEdgeInsets = UIEdgeInsets. Init (top: 0, left: 0) self.titleEdgeInsets = UIEdgeInsets. -(imageWidth + spacing / 2.0), bottom: 0, right: (imageWidth + spacing / 2.0)caseSelf. imageEdgeInsets = uiedGeInsets. init(top: -(imageOffsetY + 2.0), left: imageOffsetX, bottom: TitleEdgeInsets = UIEdgeInsets. Init (top: UIEdgeInsets) self.titleEdgeInsets = UIEdgeInsets. TitleOffsetY + spacing / 2.0, left: -titleOffsetX, bottom: -(titleOffsetY + spacing / 2.0), right: titleOffsetXcaseSelf. imageEdgeInsets = uiedGeInsets. init(top: imageOffsetY + 2.0, left: imageOffsetX, bottom: -(imageOffsetY + spacing / 2.0), right: -imageoffsetx) self.titleEdgeInsets = UIEdgeInsets. Init (top: -(titleOffsetY + spacing / 2.0), left: -titleoffsetx, bottom: titleOffsetY + spacing / 2.0, right: titleOffsetX)}}}Copy the code
  • The click to expand the UIControl class and its subclasses returns 44*44
Override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { var bounds: CGRect = self.bounds; // If the original heat area is less than 44x44, enlarge the heat area, otherwise keep the original size unchangedletWidthDelta: CGFloat = Max (44.0-bounds.size. Width, 0)letHeightDelta: CGFloat = Max (44.0 - bounds.size. Height, 0); Bounds = bounds. InsetBy (dx: -0.5*widthDelta, dy: -0.5*heightDelta)let isContain: Bool = bounds.contains(point)
        returnisContain; }}Copy the code
  • It’s easy to set images for each state of UIButton
// extension UIButton {//MARK: set the image /// set the image in normal state with the default image /// -parameter URL: Image links | local image name func bw_setImageForNormal (url: String? { self.bw_setImageWith(url: url,for: normal)} / / / the pictures with the default Settings selected condition / / / - Parameter url: image links | local image name func bw_setImageForSelected (url: String? { self.bw_setImageWith(url: url,for: selected)} / / / set the highlighted state picture / / / - Parameter with the default image url: image links | local image name func bw_setImageForHighlighted (url: String?) { self.bw_setImageWith(url: url,for: highlighted)} / / / set the disabled state picture / / / - Parameter with the default image url: image links | local image name func bw_setImageForDisabled (url: String? { self.bw_setImageWith(url: url,for: disabled)} / / / set up under the normal state of photo / / / - Parameters: / / / - url: image links | local picture name / / / - placeholderImage: Func bw_setImageForNormal(URL: String? , placeholderImage: UIImage?) { self.bw_setImageWith(url: url,for}}}}}}}}}}}}}}} Image links | local picture name / / / - placeholderImage: placeholder figure func bw_setImageForSelected (url: String? , placeholderImage: UIImage?) { self.bw_setImageWith(url: url,for} // set button-down on error message: /// -parameters: /// -url: Image links | local picture name / / / - placeholderImage: placeholder figure func bw_setImageForHighlighted (url: String? , placeholderImage: UIImage?) { self.bw_setImageWith(url: url,for:.highlighted, metagimage: metagimage)} // set up the disabled state of the image /// -parameters: /// / -url: Image links | local picture name / / / - placeholderImage: placeholder figure func bw_setImageForDisabled (url: String, placeholderImage: UIImage?) { self.bw_setImageWith(url: url,for: disabled, placeholderImage: placeholderImage)} / / / / / / / / / - the Parameters for the image: / / / - url: image links | local picture name / / / - state: State func bw_setImageWith(url: String? .for state: UIControl.State) {
        self.bw_setImageWith(url: url, for: state, placeholderImage: defaultPlaceholderImage)} / / / / / / / / / - the Parameters for the image: / / / - url: image links | local picture name / / / - state: Func bw_setImageWith(url: String? .for state: UIControl.State,  placeholderImage: UIImage?) {
        ifurl == nil || url? .count == 0 {self.setImage(defaultPlaceholderImage,for: state)
            return
        }
        ifurl? .contains("http") = =trueSelf.kf.setimage (with: URL(string: URL!)) {// net image self.kf.setimage (with: URL(string: URL!)) .for: state) self.kf.setImage(with: URL(string: url!) .for: state, placeholder: placeholderImage)
        } else{// Local image (it is possible that the URL is only the path of the image, this situation needs to be processed again (OC is the method of loading images through the Runtime, add the judgment of the image URL, For image urls that lack host manually concatenate host to make the full image path)) self.setimage (UIImage(named: URL!) .for: state)}} //MARK: set background image /// set background image in normal state with default image /// -parameter url: Image links | local image name func bw_setBackgroundImageForNormal (url: String? { self.bw_setBackgroundImageWith(url: url,for: normal)} / / / with default Settings selected state image background picture / / / - Parameter url: image links | local image name func bw_setBackgroundImageForSelected (url: String?) { self.bw_setBackgroundImageWith(url: url,for// set highlighted state with default image in the background image /// -parameter url:.selected)} Image links | local image name func bw_setBackgroundImageForHighlighted (url: String? { self.bw_setBackgroundImageWith(url: url,for:.highlighted)} /// set the background image with default image in disabled state /// -parameter URL: Image links | local image name func bw_setBackgroundImageForDisabled (url: String? { self.bw_setBackgroundImageWith(url: url,for: disabled)} / / / set the background picture under the normal state / / / - Parameters: / / / - url: image links | local picture name / / / - placeholderImage: Placeholder figure func bw_setBackgroundImageForNormal (url: String? , placeholderImage: UIImage?) { self.bw_setBackgroundImageWith(url: url,for}}}}}}}}}}}}}}}}} Image links | local picture name / / / - placeholderImage: placeholder figure func bw_setBackgroundImageForSelected (url: String? , placeholderImage: UIImage?) { self.bw_setBackgroundImageWith(url: url,for} // set button-down in error message: /// -parameters: /// Image links | local picture name / / / - placeholderImage: placeholder figure func bw_setBackgroundImageForHighlighted (url: String? , placeholderImage: UIImage?) { self.bw_setBackgroundImageWith(url: url,for:.highlighted, metagimage: metagimage)} :.highlighted, metagimage: metagimage)} Image links | local picture name / / / - placeholderImage: placeholder figure func bw_setBackgroundImageForDisabled (url: String? , placeholderImage: UIImage?) { self.bw_setBackgroundImageWith(url: url,for} // -parameters: /// -parameters: // -url: Image links | local picture name / / / - state: a state func bw_setBackgroundImageWith (url: String? .for state: UIControl.State) {
        self.bw_setBackgroundImageWith(url: url, for}} /// /// - Parameters: /// - url: Image links | local picture name / / / - state: state / / / - placeholderImage: placeholder images func bw_setBackgroundImageWith (url: String? .for state: UIControl.State, placeholderImage: UIImage?) {
        ifurl == nil || url? .count == 0 {self.setBackgroundImage(defaultPlaceholderImage,for: state)
            return
        }
        ifurl? .contains("http") = =true{/ / network image self. Kf. SetBackgroundImage (with: URL (string: URL!) .for: state, placeholder: placeholderImage)
        } else{// Local image self.setBackgroundImage(UIImage(named: URL!)) .for: state)
        }
    }
}
Copy the code
  • Some extension methods of UIImage
/// /// -parameter color: color /// - Returns: Open class func imageWithColor(color: UIColor) -> UIImage? {letThe rect: CGRect = CGRect. Init (0.0 x: y: 0.0, width: 1.0, height: 1.0) UIGraphicsBeginImageContext (the rect. Size);if let context: CGContext = UIGraphicsGetCurrentContext() {
            context.setFillColor(color.cgColor);
            context.fill(rect);
            
            let image: UIImage? = UIGraphicsGetImageFromCurrentImageContext() ?? nil;
            UIGraphicsEndImageContext()
            return image
        }
        return/// /// -parameter color: color /// - Returns: open func imageWithTintColor(color: UIColor) -> UIImage? { UIGraphicsBeginImageContextWithOptions(self.size,false, self.scale);
        if let context: CGContext = UIGraphicsGetCurrentContext() {context.translateby (x: 0, y: self.size. Height) context.scaleby (x: 1.0, y: self.size. Height) {context.scaleby (x: 1.0, y: self.size. 1.0) context. SetBlendMode (CGBlendMode. Normal)let rect: CGRect = CGRect.init(x: 0, y: 0, width: self.size.width, height: self.size.height)
            context.clip(to: rect)
            color.setFill()
            context.fill(rect)
            let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext() ?? nil;
            UIGraphicsEndImageContext();
            return newImage;
        }
        returnOpen func imageColorFrom(point: CGPoint) -> UIColor? {if point.x < 0 || point.x > self.size.width || point.y < 0 || point.y > self.size.height {
            return nil
        }
        letprovider = self.cgImage! .dataProviderletproviderData = provider! .datalet data = CFDataGetBytePtr(providerData)
        
        let numOfComponets: CGFloat = 4
        let pixelData = Int(((self.size.width * point.y) + point.x) * numOfComponets)
         
        letr = CGFloat(data! [pixelData]) / 255.0letg = CGFloat(data! [pixelData + 1]) / 255.0letb = CGFloat(data! [pixelData + 2]) / 255.0leta = CGFloat(data! [pixelData + 3]) / 255.0returnUicolor. init(red: r, green: g, blue: b, alpha: a)} Open func imageByScalingToSize(targetSize: CGSize) -> UIImage? {let sourceImage: UIImage = self;
        var newImage: UIImage? = nil;
        let imageSize: CGSize = sourceImage.size;
        let width = imageSize.width;
        let height = imageSize.height;
        let targetWidth = targetSize.width;
        lettargetHeight = targetSize.height; Var scaleFactor: CGFloat = 0.0; var scaledWidth = targetWidth; var scaledHeight = targetHeight; Var thumbnailPoint = cgPoint.init (x: 0.0, y: 0.0);if imageSize.equalTo(targetSize) == false {
            let widthFactor: CGFloat = CGFloat(targetWidth / width);
            let heightFactor: CGFloat = CGFloat(targetHeight / height);
            if widthFactor < heightFactor {
                scaleFactor = widthFactor;
            } else {
                scaleFactor = heightFactor;
                scaledWidth  = width * scaleFactor;
                scaledHeight = height * scaleFactor;
            }
            // center the image
            if(widthFactor < heightFactor) {thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; }else if(widthFactor > heightFactor) {thumbnailPoint.x = (targetwidth-ScaledWidth) * 0.5; } } // this is actually the interesting part: UIGraphicsBeginImageContext(targetSize); var thumbnailRect: CGRect = CGRect.zero; thumbnailRect.origin = thumbnailPoint; thumbnailRect.size.width = scaledWidth; thumbnailRect.size.height = scaledHeight;sourceImage.draw(in: thumbnailRect)
        newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        returnnewImage ; }}Copy the code
  • UIView convert UIImage
Extension UIView {/// Convert the image to the original size /// /// - Returns: Open func transformToImage() -> UIImage {self.layoutSubviews() UIGraphicsBeginImageContextWithOptions(self.size,false, 0.0);
        self.layer.render(in: UIGraphicsGetCurrentContext()!)
        letimage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! ; UIGraphicsEndImageContext();returnimage; }}Copy the code
  • The UIView class uses UIBezierPath to draw the rounded corners of each position, and you can set the rounded corners separately
/ / / add the rounded / / / / / / - Parameter cornerRadii: rounded size open func addAllRoundingCornersWithRadii (cornerRadii: CGSize) { self.addBezierPathCorner(roundingCorners: UIRectCorner.allCorners, cornerRadii: CornerRadii)} /// /// -parameters: /// - roundingCorners: // roundingCorners: // - radii: Open func addBezierPathCorner(roundingCorners: UIRectCorner, cornerRadii radii: CGSize) {ifsuperview ! = nil { superview? .layoutIfNeeded() }let bezierPath: UIBezierPath = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: roundingCorners, cornerRadii: radii)
        let shapeLayer: CAShapeLayer = CAShapeLayer.init()
        shapeLayer.frame = self.bounds
        shapeLayer.path = bezierPath.cgPath
        self.layer.mask = shapeLayer
    }
Copy the code
  • UIView adds four shaded edges, and you can choose the shaded edges
public enum BWShadowPosition {
    case top
    case bottom
    case left
    case right
    case common
    caseOpacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity: opacity /// -position: add shadow position open func shadowPathWithColor(_ color: UIColor, opacity: CGFloat? , radius: CGFloat, offset: CGSize? , width: CGFloat, position: BWShadowPosition) {ifself.superview ! = nil { self.superview? .layoutifneeded ()} // Avoid shadows being cut hidden self.layer.maskstobounds =falseSelf.layer.shadowColor = color.cgColor // shadowOpacity defaults to 0 self.layer.shadowOpacity = Float(opacity?? 0.0) // The default is (0,-3) self.layer.shadowoffset = offset?? Cgsize. init(width: 0, height: -3) // The default shadow radius is 3 self.layer.cornerradius = radius var shadowRect = cgrect.zerolet originX: CGFloat = 0
        let originY: CGFloat = 0
        let sizeWidth: CGFloat = self.width
        let sizeHeight: CGFloat = self.height
        switch position {
        case .top: do{shadowRect = cgRect.init (x: originX, y: originy-width / 2.0, width: sizeWidth, height: width)}case .left: do{shadowRect = cgRect.init (x: originx-width / 2.0, y: originY, width: width, height: sizeHeight)}case .bottom: do{shadowRect = cgRect.init (x: originY, y: sizeheight-width / 2.0, width: sizeWidth, height: width)}case .right: do{shadowRect = cgRect.init (x: sizewidth-width / 2.0, y: originY, width: width, height: sizeHeight)}case .common: do{shadowRect = cgRect.init (x: originx-width / 2.0, y: 2, width: sizeWidth+width, height: sizeHeight +width / 2.0)}case .around: do{shadowRect = cgrect. init(x: originx-width / 2.0, y: originy-width / 2.0, width: sizeWidth + width, height: sizeHeight + width) } }let bezierPath: UIBezierPath = UIBezierPath.init(rect: shadowRect)
        self.layer.shadowPath = bezierPath.cgPath
    }
Copy the code
  • Easily get & set frame properties
extension UIView {
    
    
    public var x: CGFloat {
        set {
            var rect: CGRect = self.frame
            rect.origin.x = newValue
            self.frame = rect
        }
        get {
            return self.frame.origin.x
        }
    }
    public var y: CGFloat {
        set {
            var rect: CGRect = self.frame
            rect.origin.y = newValue
            self.frame = rect
        }
        get {
            return self.frame.origin.y
        }
    }
    public var maxX: CGFloat {
        set {
            self.x = newValue - self.width
        }
        get {
            return self.frame.maxX
        }
    }
    public var maxY: CGFloat {
        set {
            self.y = newValue - self.height
        }
        get {
            return self.frame.maxY
        }
    }
    public var width: CGFloat {
        set {
            var rect: CGRect = self.frame
            rect.size.width = newValue
            self.frame = rect
        }
        get {
            return self.frame.size.width
        }
    }
    public var height: CGFloat {
        set {
            var rect: CGRect = self.frame
            rect.size.height = newValue
            self.frame = rect
        }
        get {
            return self.frame.size.height
        }
    }
    public var centerX: CGFloat {
        set {
            var center: CGPoint = self.center
            center.x = newValue
            self.center = center
        }
        get {
            return self.center.x
        }
    }
    public var centerY: CGFloat {
        set {
            var center: CGPoint = self.center
            center.y = newValue
            self.center = center
        }
        get {
            return self.center.y
        }
    }
    public var size: CGSize {
        set {
            var rect: CGRect = self.frame
            rect.size = newValue
            self.frame = rect
        }
        get {
            return self.frame.size
        }
    }
}
Copy the code
  • NSMutableAttributedString related simple packaging
typealias attributeString = String

public enum BWStrikethroughStyle {
    caseUnderline // underlinecaseStrikethrough line in the / /} the extension String {/ / / in the String to add line | underline / / / / / / - Parameters: / / / - color: color / / / - graphics.linestyle: Style / / / - Returns: in the line | underline public func addLineAttribteString (color: UIColor, graphics.linestyle: BWStrikethroughStyle) -> NSMutableAttributedString { switch lineStyle {case .underline: do {
            return self.underlineAttributeString(color: color)
            }
        case .strikethrough: do {
            returnSelf. StrikethroughAttributeString (color: color)}}} / / / to add color#999999/ / / / / / - Returns: line in public func strikethroughAttributeStringForColor999999 () - > NSMutableAttributedString {return self.strikethroughAttributeString(color: UIColor.init(hexColorString: "# 999999"))} / / / add the marking / / / / / / - Parameter color: marking color / / / - Returns: NSMutableAttributedString public func strikethroughAttributeString(color: UIColor) -> NSMutableAttributedString {let strikethroughAttributeString : NSMutableAttributedString = NSMutableAttributedString.init(string: self)
        strikethroughAttributeString.addAttribute(.strikethroughStyle, value: NSNumber.init(value: 1), range: NSRange.init(location: 0, length: strikethroughAttributeString.length))
        strikethroughAttributeString.addAttribute(.strikethroughColor, value: color, range: NSRange.init(location: 0, length: strikethroughAttributeString.length))
        returnStrikethroughAttributeString} / / / add the underline / / / / / / - Parameter color: underline color / / / - Returns: Underline the public func underlineAttributeString (color: UIColor) - > NSMutableAttributedString {let underlineAttributeString : NSMutableAttributedString = NSMutableAttributedString.init(string: self)
        underlineAttributeString.addAttribute(.underlineStyle, value: NSNumber.init(value: 1), range: NSRange.init(location: 0, length: underlineAttributeString.length))
        underlineAttributeString.addAttribute(.underlineColor, value: color, range: NSRange.init(location: 0, length: underlineAttributeString.length))
        returnUnderlineAttributeString}} extension String {/// /// - Parameters: // - imageName: picture name // - bounds: Picture bounds / / / - Returns: rich text with image is public func appendingAttributeStringImageWithImageName (_ imageName: String, bounds: CGRect) -> NSMutableAttributedString {letAttributeString: NSMutableAttributedString = NSMutableAttributedString init (string: self) / / image processinglet attachImage: NSTextAttachment = NSTextAttachment.init()
        attachImage.image = UIImage.init(named: imageName)
        attachImage.bounds = bounds
        letattachAttributeString: NSAttributedString = NSAttributedString.init(attachment: AttachImage attachTeString. Append (attachAttributeString)returnAttributeString} /// string to insert image /// /// -parameters: /// -imagename: imageName /// -bounds: picture bounds /// -index: Insert the subscript / / / Returns: take pictures rich text public func insertAttributeStringImageWithImageName (_ imageName: String, bounds: CGRect, index: Int) -> NSMutableAttributedString {letAttributeString: NSMutableAttributedString = NSMutableAttributedString init (string: self) / / image processinglet attachImage: NSTextAttachment = NSTextAttachment.init()
        attachImage.image = UIImage.init(named: imageName)
        attachImage.bounds = bounds
        letattachAttributeString: NSAttributedString = NSAttributedString.init(attachment: Attach (attachImage, at: index)return attributeString
    }
}
Copy the code
  • Easy to generate UIColor, support hexadecimal and RGB colors
Extension UIColor {/// the hexadecimal color c is converted to UIColor /// /// -parameter hexColorString: hexadecimal color convenience init(hexColorString: String) {let hexString = hexColorString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        let scanner = Scanner(string: hexString)
        
        if hexString.hasPrefix("#") {
            scanner.scanLocation = 1;
        }
        
        var color: UInt32 = 0
        scanner.scanHexInt32(&color);
        
        let mask = 0x000000FF
        let r = Int(color >> 16) & mask
        let g = Int(color >> 8) & mask
        letb = Int(color) & mask self.init(red:CGFloat(r), green:CGFloat(g), /// simple RGB color constructor default transparency is 1 /// /// -parameters: /// -red: red color value // -green: green color value // -blue: The following table shows the values of the following table. The following table shows the values of the following table. The following table shows the values of the following table. Alpha blue: 1)} / / simple/RGB color constructor / / / / / / - Parameters: / / / - r: / / / red color values - g: green color value / / / b: / / / - alpha blue color values: Transparency 0~1 Convenience init(r: CGFloat, g: CGFloat, B: CGFloat, alpha: CGFloat) {letRed = CGFloat(r) / 255.0letGreen = CGFloat(g) / 255.0letBlue = CGFloat(b) / 255.0 self.init(red: red, green: green, blue: blue, alpha: alpha)}}Copy the code
  • NSCode related
//MARK: NSCoder /// CGPoint->String /// /// - Parameter point: point /// - Returns: String public func BWStringFromPoint(_ point: CGPoint) -> String {return NSCoder.string(for: point) } /// CGVector -> String /// /// - Parameter vector: vector /// - Returns: Public func BWStringFromVector(_ vector: CGVector) -> String {return NSCoder.string(for: vector)} /// CGSize -> String /// /// - Parameter size: size /// - Returns: String public func BWStringFromSize(_ size: CGSize) -> String {return NSCoder.string(for: size)} /// CGRect -> String /// /// -parameter rect: rect /// - Returns: String public func BWStringFromRect(_ rect: CGRect) -> String {return NSCoder.string(for: rect) } /// CGAffineTransform -> String /// /// - Parameter transform: transform /// - Returns: Public func BWStringFromTransform(_ transform: CGAffineTransform) -> String {return NSCoder.string(for: transform) } /// UIEdgeInsets -> String /// /// - Parameter insets: insets /// - Returns: String public func BWStringFromInsets(_ insets: UIEdgeInsets) -> String {return NSCoder.string(for: insets) } /// NSDirectionalEdgeInsets -> String /// /// - Parameter insets: insets /// - Returns: @available(iOS 11.0, *) public func BWStringFromInsets(_ insets: NSDirectionalEdgeInsets) -> String {return NSCoder.string(for: insets) } /// UIOffset -> String /// /// - Parameter offset: offset /// - Returns: String public func BWStringFromOffset(_ offset: UIOffset) -> String {return NSCoder.string(for: offset)} /// String -> CGPoint /// /// -parameter String: String /// - Returns: point public func BWPointFromString(_ string: String) -> CGPoint {return NSCoder.cgPoint(forPublic func BWVectorFromString(_ string:)} /// string -> CGVector // -parameter string: string public func BWVectorFromString(_ string:) String) -> CGVector {return NSCoder.cgVector(for/// -parameter string: string public func BWSizeFromString(_ string: string) -> CGSize {return NSCoder.cgSize(forWrectfromstring (_ string: string) -> CGRect {return NSCoder.cgRect(for} /// string -> CGAffineTransform /// -parameter String: string public func BWTransformFromString(_ string: String) -> CGAffineTransform {return NSCoder.cgAffineTransform(for} /// string -> UIEdgeInsets /// -parameter String: string public func BWEdgInsetFromString(_ string: string) String) -> UIEdgeInsets {return NSCoder.uiEdgeInsets(for: string) } /// String -> NSDirectionalEdgeInsets /// - Parameter string: String @ the available (iOS 11.0. *) public func BWDirectionalEdgeInsetsFromString (_ string, string) - > NSDirectionalEdgeInsets {return NSCoder.nsDirectionalEdgeInsets(for} /// string -> UIOffset /// -parameter string: string public func BWOffsetFromString(_ string: string) String) -> UIOffset {return NSCoder.uiOffset(for: string)
}
Copy the code
  • Print relevant
//MARK: DEBUG prints func BWLog(_ items: Any... , file: String =#file, funcName: String = #function, lineNum: Int = #line) {
    #if DEBUG
    let separator: String = ""
    let terminator: String = "\n"
    let date = Date.init()
    let filenime = (file as NSString).lastPathComponent
    print("\n\(date) \(filenime)[\(lineNum)] method:\(funcName)")
    var i = 0
    let j = items.count
    for item inItems {I += 1 // key: // When there are more than one argument to be printed, use the tri operator to determine the actual value of the terminator // -separator: a string to be printed between each item. The default is a single space (""). // -terminator: string to be printed after all items are printed. The default is the newline character \n ("\n").print(item, terminator: i == j ? Terminator: separator)} // Print a blank line.print(a)#endif
}
Copy the code

So far, these are some small summaries of my recent practice of learning Swift and using Swift project. Welcome to refer to the content of my girlfriend’s circle of friends last night: Just like sunflower, face the sun, try to grow, keep true colors, not arrogant or impetuous. I hope I can learn more happily and make more progress in the future. Come on, come on, come on. [KeepFighting][KeepFighting][KeepFighting]

Ps: Inadvertently scattered a handful of dog food, you eat and drink good 😃😃😃😃