swift中常用扩展
UIKit+Extension.swift
//
// UIKit+Extension.swift
// News
//
// Created by 杨蒙 on 2017/12/12.
// Copyright © 2017年 hrscy. All rights reserved.
//
import UIKit
import CoreText
protocol StoryboardLoadable {}
extension StoryboardLoadable where Self: UIViewController {
/// 提供 加载方法
static func loadStoryboard() -> Self {
return UIStoryboard(name: "\(self)", bundle: nil).instantiateViewController(withIdentifier: "\(self)") as! Self
}
}
protocol NibLoadable {}
extension NibLoadable {
static func loadViewFromNib() -> Self {
return Bundle.main.loadNibNamed("\(self)", owner: nil, options: nil)?.last as! Self
}
}
extension UILabel {
/// 设置问答的内容
func setSeparatedLinesFrom(_ attributedString: NSMutableAttributedString, hasImage: Bool) {
// 通过 CoreText 创建字体
let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
// 段落样式
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
// 为富文本添加属性
attributedString.addAttributes([kCTFontAttributeName as NSAttributedStringKey: ctFont, NSAttributedStringKey.paragraphStyle: paragraphStyle], range: NSRange(location: 0, length: attributedString.length))
// 通过 CoreText 创建 frameSetter
let frameSetter = CTFramesetterCreateWithAttributedString(attributedString)
// 创建路径
let path = CGMutablePath()
// 为路径添加一个 frame
path.addRect(CGRect(x: 0, y: 0, width: width, height: CGFloat(MAXFLOAT)))
// 通过 CoreText 创建 frame
let frame = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attributedString.length), path, nil)
// 获取当前 frame 中的每一行的内容
let lines: NSArray = CTFrameGetLines(frame)
let attributedStrings = NSMutableAttributedString()
// 遍历
for (index, line) in lines.enumerated() {
// 将 line 转成 CTLine
// 获取每一行的范围
let lineRange = CTLineGetStringRange(line as! CTLine)
// 将 lineRange 转成 NSRange
let range = NSRange(location: lineRange.location, length: lineRange.length)
// 当前的内容
let currentAttributedString = NSMutableAttributedString(attributedString: attributedString.attributedSubstring(from: range))
if hasImage { // 如果有图片,就把第四行替换
if index == 3 && currentAttributedString.length >= 18 {
replaceContent(currentAttributedString)
}
} else { // 如果没有图片,就把第六行替换
if index == 5 && currentAttributedString.length >= 18 {
replaceContent(currentAttributedString)
}
}
attributedStrings.append(currentAttributedString)
}
attributedText = attributedStrings
}
/// 替换内容
private func replaceContent(_ currentAttributedString: NSMutableAttributedString) {
currentAttributedString.replaceCharacters(in: NSRange(location: currentAttributedString.length - 8, length: 8), with: NSAttributedString(string: "...全文\n", attributes: [.foregroundColor: UIColor.blueFontColor()]))
}
}
extension UITextView {
/// 设置 UITextView 富文本内容
func setAttributedText(emoji: Emoji) {
// 如果输入是空表情
if emoji.isEmpty { return }
// 如果输入是删除表情
if emoji.isDelete { deleteBackward(); return }
// 创建附件
let attachment = NSTextAttachment()
attachment.image = UIImage(named: emoji.png)
// 当前字体的大小
let currentFont = font!
// 附件的大小
attachment.bounds = CGRect(x: 0, y: -4, width: currentFont.lineHeight, height: currentFont.lineHeight)
// 根据附件,创建富文本
let attributedImageStr = NSAttributedString(attachment: attachment)
// 获取当前的光标的位置
let range = selectedRange
// 设置富文本
let mutableAttributedText = NSMutableAttributedString(attributedString: attributedText)
mutableAttributedText.replaceCharacters(in: range, with: attributedImageStr)
attributedText = mutableAttributedText
// 将字体的大小重置
font = currentFont
// 光标 + 1
selectedRange = NSRange(location: range.location + 1, length: 0)
}
}
extension UIView {
/// x
var x: CGFloat {
get { return frame.origin.x }
set(newValue) {
var tempFrame: CGRect = frame
tempFrame.origin.x = newValue
frame = tempFrame
}
}
/// y
var y: CGFloat {
get { return frame.origin.y }
set(newValue) {
var tempFrame: CGRect = frame
tempFrame.origin.y = newValue
frame = tempFrame
}
}
/// height
var height: CGFloat {
get { return frame.size.height }
set(newValue) {
var tempFrame: CGRect = frame
tempFrame.size.height = newValue
frame = tempFrame
}
}
/// width
var width: CGFloat {
get { return frame.size.width }
set(newValue) {
var tempFrame: CGRect = frame
tempFrame.size.width = newValue
frame = tempFrame
}
}
/// size
var size: CGSize {
get { return frame.size }
set(newValue) {
var tempFrame: CGRect = frame
tempFrame.size = newValue
frame = tempFrame
}
}
/// centerX
var centerX: CGFloat {
get { return center.x }
set(newValue) {
var tempCenter: CGPoint = center
tempCenter.x = newValue
center = tempCenter
}
}
/// centerY
var centerY: CGFloat {
get { return center.y }
set(newValue) {
var tempCenter: CGPoint = center
tempCenter.y = newValue
center = tempCenter;
}
}
}
protocol RegisterCellFromNib {}
extension RegisterCellFromNib {
static var identifier: String { return "\(self)" }
static var nib: UINib? { return UINib(nibName: "\(self)", bundle: nil) }
}
extension UITableView {
/// 注册 cell 的方法
func ym_registerCell<T: UITableViewCell>(cell: T.Type) where T: RegisterCellFromNib {
if let nib = T.nib { register(nib, forCellReuseIdentifier: T.identifier) }
else { register(cell, forCellReuseIdentifier: T.identifier) }
}
/// 从缓存池池出队已经存在的 cell
func ym_dequeueReusableCell<T: UITableViewCell>(indexPath: IndexPath) -> T where T: RegisterCellFromNib {
return dequeueReusableCell(withIdentifier: T.identifier, for: indexPath) as! T
}
}
extension UICollectionView {
/// 注册 cell 的方法
func ym_registerCell<T: UICollectionViewCell>(cell: T.Type) where T: RegisterCellFromNib {
if let nib = T.nib { register(nib, forCellWithReuseIdentifier: T.identifier) }
else { register(cell, forCellWithReuseIdentifier: T.identifier) }
}
/// 从缓存池池出队已经存在的 cell
func ym_dequeueReusableCell<T: UICollectionViewCell>(indexPath: IndexPath) -> T where T: RegisterCellFromNib {
return dequeueReusableCell(withReuseIdentifier: T.identifier, for: indexPath) as! T
}
/// 注册头部
func ym_registerSupplementaryHeaderView<T: UICollectionReusableView>(reusableView: T.Type) where T: RegisterCellFromNib {
// T 遵守了 RegisterCellOrNib 协议,所以通过 T 就能取出 identifier 这个属性
if let nib = T.nib {
register(nib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: T.identifier)
} else {
register(reusableView, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: T.identifier)
}
}
/// 获取可重用的头部
func ym_dequeueReusableSupplementaryHeaderView<T: UICollectionReusableView>(indexPath: IndexPath) -> T where T: RegisterCellFromNib {
return dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: T.identifier, for: indexPath) as! T
}
}
extension UIImageView {
/// 设置图片圆角
func circleImage() {
/// 建立上下文
UIGraphicsBeginImageContextWithOptions(self.frame.size, false, 0)
/// 获取当前上下文
let ctx = UIGraphicsGetCurrentContext()
/// 添加一个圆,并裁剪
ctx?.addEllipse(in: self.bounds)
ctx?.clip()
/// 绘制图像
self.draw(self.bounds)
/// 获取绘制的图像
let image = UIGraphicsGetImageFromCurrentImageContext()
/// 关闭上下文
UIGraphicsEndImageContext()
DispatchQueue.global().async {
self.image = image
}
}
}
extension UIColor {
// self.init(red: <#T##CGFloat#>, green: <#T##CGFloat#>, blue: <#T##CGFloat#>, alpha: <#T##CGFloat#>)
convenience init(r: CGFloat, g: CGFloat, b: CGFloat, alpha: CGFloat = 1.0) {
self.init(displayP3Red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: alpha)
}
/// 背景灰色 f8f9f7
class func globalBackgroundColor() -> UIColor {
return UIColor(r: 248, g: 249, b: 247)
}
/// 背景红色
class func globalRedColor() -> UIColor {
return UIColor(r: 196, g: 73, b: 67)
}
/// 字体蓝色
class func blueFontColor() -> UIColor {
return UIColor(r: 72, g: 100, b: 149)
}
/// 背景灰色 132
class func grayColor132() -> UIColor {
return UIColor(r: 132, g: 132, b: 132)
}
/// 背景灰色 232
class func grayColor232() -> UIColor {
return UIColor(r: 232, g: 232, b: 232)
}
/// 夜间字体背景灰色 113
class func grayColor113() -> UIColor {
return UIColor(r: 113, g: 113, b: 113)
}
/// 夜间背景灰色 37
class func grayColor37() -> UIColor {
return UIColor(r: 37, g: 37, b: 37)
}
/// 灰色 210
class func grayColor210() -> UIColor {
return UIColor(r: 210, g: 210, b: 210)
}
}
Foundation+Extension.swift
//
// Foundation+Extension.swift
// News
//
// Created by 杨蒙 on 2017/12/12.
// Copyright © 2017年 hrscy. All rights reserved.
//
import UIKit
extension String {
/// 计算文本的高度
func textHeight(fontSize: CGFloat, width: CGFloat) -> CGFloat {
return self.boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: fontSize)], context: nil).size.height
}
}
extension TimeInterval {
// 把秒数转换成时间的字符串
func convertString() -> String {
// 把获取到的秒数转换成具体的时间
let createDate = Date(timeIntervalSince1970: self)
// 获取当前日历
let calender = Calendar.current
// 获取日期的年份
let comps = calender.dateComponents([.year, .month, .day, .hour, .minute, .second], from: createDate, to: Date())
// 日期格式
let formatter = DateFormatter()
// 判断当前日期是否为今年
guard createDate.isThisYear() else {
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return formatter.string(from: createDate)
}
// 是否是前天
if createDate.isBeforeYesterday() {
formatter.dateFormat = "前天 HH:mm"
return formatter.string(from: createDate)
} else if createDate.isToday() || createDate.isYesterday() {
// 判断是否是今天或者昨天
if comps.hour! >= 1 {
return String(format: "%d小时前", comps.hour!)
} else if comps.minute! >= 1 {
return String(format: "%d分钟前", comps.minute!)
} else {
return "刚刚"
}
} else {
formatter.dateFormat = "MM-dd HH:mm"
return formatter.string(from: createDate)
}
}
}
extension Int {
func convertString() -> String {
guard self >= 10000 else {
return String(describing: self)
}
return String(format: "%.1f万", Float(self) / 10000.0)
}
/// 将秒数转成字符串
func convertVideoDuration() -> String {
// 格式化时间
if self == 0 { return "00:00" }
let hour = self / 3600
let minute = (self / 60) % 60
let second = self % 60
if hour > 0 { return String(format: "%02d:%02d:%02d", hour, minute, second) }
return String(format: "%02d:%02d", minute, second)
}
}
extension Date {
/// 判断当前日期是否为今年
func isThisYear() -> Bool {
// 获取当前日历
let calender = Calendar.current
// 获取日期的年份
let yearComps = calender.component(.year, from: self)
// 获取现在的年份
let nowComps = calender.component(.year, from: Date())
return yearComps == nowComps
}
/// 是否是昨天
func isYesterday() -> Bool {
// 获取当前日历
let calender = Calendar.current
// 获取日期的年份
let comps = calender.dateComponents([.year, .month, .day], from: self, to: Date())
// 根据头条显示时间 ,我觉得可能有问题 如果comps.day == 0 显示相同,如果是 comps.day == 1 显示时间不同
// 但是 comps.day == 1 才是昨天 comps.day == 2 是前天
// return comps.year == 0 && comps.month == 0 && comps.day == 1
return comps.year == 0 && comps.month == 0 && comps.day == 0
}
/// 是否是前天
func isBeforeYesterday() -> Bool {
// 获取当前日历
let calender = Calendar.current
// 获取日期的年份
let comps = calender.dateComponents([.year, .month, .day], from: self, to: Date())
//
// return comps.year == 0 && comps.month == 0 && comps.day == 2
return comps.year == 0 && comps.month == 0 && comps.day == 1
}
/// 判断是否是今天
func isToday() -> Bool {
// 日期格式化
let formatter = DateFormatter()
// 设置日期格式
formatter.dateFormat = "yyyy-MM-dd"
let dateStr = formatter.string(from: self)
let nowStr = formatter.string(from: Date())
return dateStr == nowStr
}
}