1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003 |
- //
- // PQCommonMethodUtil.swift
- // PQSpeed
- //
- // Created by lieyunye on 2020/5/29.
- // Copyright © 2020 BytesFlow. All rights reserved.
- //
- import AdSupport
- import Alamofire
- import Foundation
- import KeychainAccess
- import Kingfisher
- import KingfisherWebP
- import Photos
- import Toast_Swift
- import RealmSwift
- import UIKit
- /// Home文件地址
- public let homeDirectory = NSHomeDirectory()
- /// docdocumens文件地址
- public let documensDirectory = homeDirectory + "/Documents"
- /// library文件地址
- public let libraryDirectory = homeDirectory + "/Library"
- /// 本地存储资源地址
- public let resourceDirectory = documensDirectory + "/Resource"
- /// 播放视频缓冲本地沙河目录
- public let videoCacheDirectory = resourceDirectory + "/VideoCache"
- /// 相册视频导出到本地沙河目录
- public let photoLibraryDirectory = resourceDirectory + "/PhotoLibrary/"
- /// 背景音乐导出到本地沙河目录
- public let bgMusicDirectory = resourceDirectory + "/BGMusic/"
- /// 网络视频素材下载到本地沙河目录
- public let downloadDirectory = resourceDirectory + "/Download/"
- /// 网络图片、GIF 素材下载到本地沙河目录
- public let downloadImagesDirectory = resourceDirectory + "/DownloadImages/"
- /// 临时缓存本地沙河目录地址
- public let tempDirectory = resourceDirectory + "/Temp/"
- /// 导出声音的本地沙盒目录v
- public let exportAudiosDirectory = resourceDirectory + "/ExportAudios/"
- /// 导出合成视频的本地沙盒目录
- public let exportVideosDirectory = resourceDirectory + "/ExportVideos/"
- // 版本构建号
- public let versionCode = "\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? "1")"
- // 版本号
- public let versionName = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "1.0.0")"
- /// 创建目录文件
- /// - Returns: <#description#>
- public func createDirectory(path: String) {
- let fileManager = FileManager.default
- if !fileManager.fileExists(atPath: path) {
- try? fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
- }
- }
- /// 判断文件夹是否存在
- /// - Parameter dicPath:文件夹 目录
- public func directoryIsExists(dicPath: String) -> Bool {
- BFLog(message: " dir path is: \(dicPath)")
- var directoryExists = ObjCBool(false)
- let fileExists = FileManager.default.fileExists(atPath: dicPath, isDirectory: &directoryExists)
- return fileExists && directoryExists.boolValue
- }
- /// 判断文件是否存在
- /// - Parameter filepath: 文件目录
- public func fileIsExists(filePath: String) -> Bool {
- BFLog(message: "file path is: \(filePath)")
- let fileExists = FileManager.default.fileExists(atPath: filePath)
- return fileExists
- }
- /// 创建沙河文件地址
- /// - Parameter url: 原地址
- /// - Returns: <#description#>
- public func createFilePath(url: String) -> Bool {
- let fileManager = FileManager.default
- if !fileManager.fileExists(atPath: url) {
- let isFinished = fileManager.createFile(atPath: url, contents: nil, attributes: nil)
- return isFinished
- }
- return true
- }
- public func cIPHONE_X() -> Bool {
- guard #available(iOS 11.0, *) else {
- return false
- }
- let isX = (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0) > 0
- return isX
- }
- /// 给按钮/imageView加载网络图片
- ///
- /// - Parameters:
- /// - url: 网络url
- /// - mainView: 需要加载的视图
- public func netImage(url: String, mainView: Any, placeholder: UIImage = UIImage.moduleImage(named: "placehold_image", moduleName: "BFCommonKit") ?? UIImage()) {
- if mainView is UIImageView {
- (mainView as! UIImageView).kf.setImage(with: URL(string: url), placeholder: placeholder, options: url.suffix(5) == ".webp" ? [.processor(WebPProcessor.default), .cacheSerializer(WebPSerializer.default)] : nil, progressBlock: { _, _ in
- }) { _ in
- }
- } else if mainView is UIButton {
- (mainView as! UIButton).kf.setImage(with: URL(string: url), for: .normal, placeholder: placeholder, options: url.suffix(5) == ".webp" ? [.processor(WebPProcessor.default), .cacheSerializer(WebPSerializer.default)] : nil, progressBlock: { _, _ in
- }) { _ in
- }
- }
- }
- /** 获取Kingfisher缓存的图片的data */
- public func kf_imageCacheData(originUrl: String) -> Data? {
- let diskCachePath = ImageCache.default.cachePath(forKey: originUrl)
- let data = try? Data(contentsOf: URL(fileURLWithPath: diskCachePath))
- return data
- }
- /** 获取Kingfisher缓存的图片 */
- public func kf_imageCacheImage(originUrl: String, completeHandle: @escaping (_ image: UIImage?, _ error: Error?) -> Void) {
- ImageCache.default.retrieveImageInDiskCache(forKey: originUrl, options: [.cacheOriginalImage]) { result in
- DispatchQueue.main.async {
- switch result {
- case let .success(image):
- completeHandle(image, nil)
- case let .failure(error):
- completeHandle(nil, error)
- }
- }
- }
- }
- public func bf_getRootViewController() -> UIViewController? {
- guard let window = UIApplication.shared.delegate?.window else {
- return nil
- }
- return window!.rootViewController
- }
- public func bf_getCurrentViewController() -> UIViewController? {
- var currentVC = bf_getRootViewController()
- if currentVC == nil {
- return nil
- }
-
- let runloopFind = true
- while runloopFind {
- if let vc = currentVC!.presentedViewController {
- currentVC = vc
- }else {
- if currentVC is UINavigationController {
- currentVC = (currentVC as! UINavigationController).visibleViewController
- }else if currentVC is UITabBarController {
- currentVC = (currentVC as! UITabBarController).selectedViewController
- }else {
- break
- }
- }
- }
- return currentVC
- }
- /** 打印
- type = 1 : 胡志强
- type = 2 :王成
- type = 3 : 文伟伟
-
- */
- public func BFLog<T>( _ type : Int = 0, _ file:String = #file, _ line:Int = #line, message: T) {
- let dateFmt = DateFormatter()
- dateFmt.dateFormat = "HH:mm:ss:SSSS"
- let file = (file as NSString).lastPathComponent;
- let msg = "\(file) (L:\(line)) \(message)"
- if type == 0{
- // BuglyLog.level(.warn, logs: msg)
- print("\(dateFmt.string(from: Date())) \(msg)")
- }
- #if DEBUG
- if type == 1 {
- print("hhz-\(dateFmt.string(from: Date())) \(msg)");
- }else if type == 2 {
- print("ak-\(dateFmt.string(from: Date())) \(msg)");
- }else if type == 3 {
- print("ww-\(dateFmt.string(from: Date())) \(msg)");
- }
-
- #endif
-
- }
- // MARK: 获取公共参数
- public func commonParams() -> [String: Any] {
- let model = UIDevice.current.model
- let systemName = UIDevice.current.systemName
- let systemVersion = UIDevice.current.systemVersion
- let localizedModel = UIDevice.current.localizedModel
- let machineInfo: [String: Any] = [
- "model": model, "system": systemName + " " + systemVersion, "brand": localizedModel, "platform": "iOS", "networkType": networkStatus(), "clientIp": ipAddress(),
- ]
- var commParams: [String: Any] = [
- "appVersionCode": versionCode,
- "versionCode": versionCode,
- "system": systemName + " " + systemVersion,
- "systemVersion": systemName + " " + systemVersion,
- "appType": PQBFConfig.shared.appType,
- "appId": PQBFConfig.shared.appId,
- "machineCode": getMachineCode(),
- "networkType": networkStatus(),
- "ipAddress": ipAddress(),
- "clientTimestamp": Int64(Date().timeIntervalSince1970 * 1000),
- "platform": "iOS",
- "versionName": versionName,
- "mid": getMachineCode(),
- "machineInfo": dictionaryToJsonString(machineInfo) ?? "",
- "requestId": getUniqueId(desc: "requestId"),
- "idfa": ASIdentifierManager.shared().advertisingIdentifier.uuidString,
- "idfv": UIDevice.current.identifierForVendor?.uuidString ?? "",
- "sessionId": PQBFConfig.shared.sessionId,
- "subSessionId": PQBFConfig.shared.subSessionId ?? PQBFConfig.shared.sessionId,
- ]
- if PQBFConfig.shared.token != nil, (PQBFConfig.shared.token?.count ?? 0) > 0 {
- commParams["token"] = PQBFConfig.shared.token ?? ""
- }
- if PQBFConfig.shared.loginUid != nil, (PQBFConfig.shared.loginUid?.count ?? 0) > 0 {
- commParams["loginUid"] = PQBFConfig.shared.loginUid ?? ""
- commParams["uid"] = PQBFConfig.shared.loginUid ?? ""
- }
- if PQBFConfig.shared.deviceToken != nil, (PQBFConfig.shared.deviceToken?.count ?? 0) > 0 {
- commParams["deviceToken"] = PQBFConfig.shared.deviceToken ?? ""
- }
- return commParams
- }
- /// 获取网络状态
- /// - Returns: <#description#>
- public func networkStatus() -> String {
- let status = NetworkReachabilityManager(host: "www.baidu.com")?.status
- var statusStr: String!
- switch status {
- case .unknown:
- statusStr = "NETWORK_UNKNOWN"
- case .notReachable:
- statusStr = "NETWORK_NO"
- case .reachable(.cellular):
- statusStr = "4G/5G"
- case .reachable(.ethernetOrWiFi):
- statusStr = "Wi-Fi"
- default:
- statusStr = "NETWORK_UNKNOWN"
- }
- return statusStr
- }
- /// 判断是否有网
- /// - Returns: <#description#>
- public func isNetConnected() -> Bool {
- return NetworkReachabilityManager(host: "www.baidu.com")?.status == .reachable(.cellular) || NetworkReachabilityManager(host: "www.baidu.com")?.status == .reachable(.ethernetOrWiFi)
- }
- /// 获取ip地址
- /// - Returns: <#description#>
- public func ipAddress() -> String {
- var addresses = [String]()
- var ifaddr: UnsafeMutablePointer<ifaddrs>?
- if getifaddrs(&ifaddr) == 0 {
- var ptr = ifaddr
- while ptr != nil {
- let flags = Int32(ptr!.pointee.ifa_flags)
- var addr = ptr!.pointee.ifa_addr.pointee
- if (flags & (IFF_UP | IFF_RUNNING | IFF_LOOPBACK)) == (IFF_UP | IFF_RUNNING) {
- if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
- var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
- if getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0 {
- if let address = String(validatingUTF8: hostname) {
- addresses.append(address)
- }
- }
- }
- }
- ptr = ptr!.pointee.ifa_next
- }
- freeifaddrs(ifaddr)
- }
- return addresses.first ?? "0.0.0.0"
- }
- /// 生成唯一ID / 分享跟冷启动
- /// - Parameter desc: <#desc description#>
- /// - Returns: <#description#>
- public func getUniqueId(desc: String) -> String {
- let timeStr: String = "\(Date().timeIntervalSince1970)"
- let uuid: String = getMachineCode()
- let code: String = "\(arc4random_uniform(1_000_000_000))"
- let uniqueId = (timeStr + desc + uuid + code).md5.md5
- BFLog(message: "生成唯一码:desc = \(desc),timeStr = \(timeStr),uuid = \(uuid),code = \(code),uniqueId = \(uniqueId)")
- return uniqueId
- }
- // MARK: 字典转字符串
- public func dictionaryToJsonString(_ dic: [String: Any]) -> String? {
- BFLog(message: "dictionaryToJsonString = \(dic)")
- if !JSONSerialization.isValidJSONObject(dic) {
- return ""
- }
- guard let data = try? JSONSerialization.data(withJSONObject: dic, options: []) else {
- return ""
- }
- BFLog(message: "dictionaryToJsonString - data = \(data)")
- let str = String(data: data, encoding: String.Encoding.utf8)
- BFLog(message: "dictionaryToJsonString - str = \(String(describing: str))")
- return str
- }
- // MARK: 字符串转字典
- public func jsonStringToDictionary(_ str: String) -> [String: Any]? {
- if str.count <= 0 {
- return [:]
- }
- let data = str.data(using: String.Encoding.utf8)
- if data == nil || (data?.count ?? 0) <= 0 {
- return [:]
- }
- if let dict = try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] {
- return dict
- }
- return [:]
- }
- // MARK: 字符串转数组
- public func jsonStringToArray(_ str: String) -> [[String: String]]? {
- let data = str.data(using: String.Encoding.utf8)
- if let array = try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [[String: String]] {
- return array
- }
- return nil
- }
- /// 数组转为string
- /// - Parameter array: <#array description#>
- /// - Returns: <#description#>
- public func arrayToJsonString(_ array: [Any]) -> String {
- if !JSONSerialization.isValidJSONObject(array) {
- BFLog(message: "无法解析String")
- return ""
- }
- let data: NSData! = try? JSONSerialization.data(withJSONObject: array, options: []) as NSData?
- let JSONString = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue)
- return JSONString! as String
- }
- /// jsonString转为数组
- /// - Parameter jsonString: <#jsonString description#>
- /// - Returns: <#description#>
- public func jsonStringToArray(jsonString: String) -> [Any]? {
- let data = jsonString.data(using: String.Encoding.utf8)
- if data == nil {
- return nil
- }
- if let array = try? JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [Any] {
- return array
- }
- return nil
- }
- /// 计算字符串大小
- /// - Parameters:
- /// - text: <#text description#>
- /// - font: <#font description#>
- /// - size: <#size description#>
- /// - Returns: <#description#>
- public func sizeWithText(attributedText: NSMutableAttributedString? = nil, text: String, font: UIFont, size: CGSize) -> CGSize {
- let option = NSStringDrawingOptions.usesLineFragmentOrigin
- if attributedText != nil {
- let rect: CGRect = attributedText?.boundingRect(with: size, options: option, context: nil) ?? CGRect(origin: CGPoint.zero, size: size)
- return rect.size
- } else {
- let attributes = [NSAttributedString.Key.font: font]
- let rect: CGRect = text.boundingRect(with: size, options: option, attributes: attributes, context: nil)
- return rect.size
- }
- }
- /// 根据行数计算字符串大小
- /// - Parameters:
- /// - text: <#text description#>
- /// - numberOfLines: <#numberOfLines description#>
- /// - font: <#font description#>
- /// - maxSize: <#maxSize description#>
- /// - Returns: <#description#>
- public func sizeTextFits(attributedText: NSMutableAttributedString?, text: String?, numberOfLines: Int, font: UIFont, maxSize: CGSize) -> CGSize {
- var newSize: CGSize = CGSize(width: 0, height: 0)
- let label = UILabel(frame: CGRect.zero)
- label.font = font
- label.numberOfLines = numberOfLines
- if attributedText != nil {
- label.attributedText = attributedText
- } else {
- label.text = text
- }
- newSize = label.sizeThatFits(maxSize)
- return newSize
- }
- public func textNumberOfLines(text: String, font: UIFont, maxSize _: CGSize) -> Int {
- let label = UILabel(frame: CGRect.zero)
- label.font = font
- label.numberOfLines = 0
- label.text = text
- return label.numberOfLines
- }
- /// 生成渐变色
- /// - Parameters:
- /// - size: <#size description#>
- /// - endPoint: <#endPoint description#>
- /// - startColor: <#startColor description#>
- /// - endColor: <#endColor description#>
- /// - Returns: <#description#>
- public func gradientColor(size: CGSize, endPoint: CGPoint, startColor: UIColor, endColor: UIColor) -> UIColor {
- let gradientLayer = CAGradientLayer()
- gradientLayer.frame = CGRect(origin: CGPoint(), size: size)
- gradientLayer.startPoint = CGPoint.zero
- gradientLayer.endPoint = endPoint
- gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
- UIGraphicsBeginImageContext(size)
- gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
- let image = UIGraphicsGetImageFromCurrentImageContext()!
- return UIColor(patternImage: image)
- }
- /// 获取设备ID
- /// - Returns: <#description#>
- public func getMachineCode() -> String {
- let userInfo: [String: Any]? = jsonStringToDictionary(UserDefaults.standard.string(forKey: cUserInfoStorageKey) ?? "")
- if userInfo != nil && ((userInfo?.keys.contains("isVirtualUser") ?? false) && !(userInfo?["isVirtualUser"] is NSNull) && ((userInfo?["isVirtualUser"] as? Bool) ?? false)) && ((userInfo?.keys.contains("mid") ?? false) && !(userInfo?["mid"] is NSNull)) {
- BFLog(message: "虚拟账号mid:\("\(userInfo?["mid"] ?? "")")")
- return "\(userInfo?["mid"] ?? "")"
- }
- let keychain = Keychain(service: "com.piaoquan.pqspeed")
- var uuid: String = keychain["machineCode"] ?? ""
- if uuid.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
- uuid = NSUUID().uuidString
- keychain["machineCode"] = uuid
- }
- BFLog(message: "正式账号mid:\(uuid)")
- return uuid
- }
- /// 显示加载中视图
- /// - Parameters:
- /// - superView: <#superView description#>
- /// - msg: <#msg description#>
- /// - Returns: <#description#>
- public func cShowHUB(superView: UIView?, msg: String?) {
- var sty : ToastStyle = ToastManager.shared.style
- sty.messageAlignment = .center
- DispatchQueue.main.async {
- if superView == nil {
- if msg == nil {
- UIApplication.shared.keyWindow?.makeToastActivity(.center)
- } else {
- UIApplication.shared.keyWindow?.makeToast(msg, duration: 3.0, position: .center, style: sty)
- }
- } else {
- if msg == nil {
- superView!.makeToastActivity(.center)
- } else {
- superView!.makeToast(msg, duration: 3.0, position: .center,style: sty)
- }
- }
- }
- }
- /// 隐藏加载中视图
- /// - Parameter superView: <#superView description#>
- /// - Returns: <#description#>
- public func cHiddenHUB(superView: UIView?) {
- DispatchQueue.main.async {
- if superView == nil {
- UIApplication.shared.keyWindow?.hideAllToasts()
- UIApplication.shared.keyWindow?.hideToastActivity()
- } else {
- superView!.hideAllToasts()
- superView?.hideToastActivity()
- }
- }
- }
- /// 获取存储值
- /// - Parameter key: key description
- /// - Returns: description
- public func getUserDefaults(key: String) -> Any? {
- return UserDefaults.standard.object(forKey: key)
- }
- /// 存储数据
- /// - Parameters:
- /// - key: key description
- /// - value: value description
- /// - Returns: description
- public func saveUserDefaults(key: String, value: String) {
- UserDefaults.standard.set(value, forKey: key)
- UserDefaults.standard.synchronize()
- }
- /// 存储数据带版本号
- /// - Parameters:
- /// - key: <#key description#>
- /// - value: <#value description#>
- public func saveUserDefaultsToJson(key: String, value: Any) {
- UserDefaults.standard.set(dictionaryToJsonString([key: value, "appVersionCode": versionCode, "versionName": versionName]), forKey: key)
- UserDefaults.standard.synchronize()
- }
- /// 获取数据带版本号
- /// - Parameter key: <#key description#>
- /// - Returns: <#description#>
- public func getUserDefaultsForJson(key: String) -> Any? {
- let jsonStr = UserDefaults.standard.object(forKey: key)
- if jsonStr != nil {
- return jsonStringToDictionary(jsonStr as! String)?[key]
- }
- return UserDefaults.standard.object(forKey: key)
- }
- /// 清空数据
- /// - Parameters:
- /// - key: key description
- /// - value: value description
- /// - Returns: description
- public func removeUserDefaults(key: String) {
- UserDefaults.standard.removeObject(forKey: key)
- UserDefaults.standard.synchronize()
- }
- /// 存储数据
- /// - Parameters:
- /// - key: key description
- /// - value: value description
- /// - Returns: description
- public func saveUserDefaults(key: String, value: Any) {
- UserDefaults.standard.set(value, forKey: key)
- UserDefaults.standard.synchronize()
- }
- /// 保存自定义model as NSArray 当 OBJ 是数组时不能使用 Array 要使用 NSArray
- /// - Parameter object: <#object description#>
- /// - Parameter key: <#key description#>
- public func saveCustomObject(customObject object: NSCoding, key: String) {
- let encodedObject = NSKeyedArchiver.archivedData(withRootObject: object)
- UserDefaults.standard.set(encodedObject, forKey: key)
- UserDefaults.standard.synchronize()
- BFLog(message: "保存自定义类成功 key is \(key) \(encodedObject.count)")
- }
- /// 取自定义model
- /// - Parameter key: <#key description#>
- public func getCustomObject(forKey key: String) -> AnyObject? {
- let decodedObject = UserDefaults.standard.object(forKey: key) as? Data
- if decodedObject == nil {
- BFLog(message: "key is \(key) decodedObject is nil")
- }
- if let decoded = decodedObject {
- let object = NSKeyedUnarchiver.unarchiveObject(with: decoded as Data)
- return object as AnyObject?
- }
- return nil
- }
- /// 添加通知
- /// - Parameters:
- /// - observer: <#observer description#>
- /// - aSelectorName: <#aSelectorName description#>
- /// - aName: <#aName description#>
- /// - anObject: <#anObject description#>
- /// - Returns: <#description#>
- public func addNotification(_ observer: Any, selector aSelectorName: Selector, name aName: String, object anObject: Any?) {
- PQNotification.addObserver(observer, selector: aSelectorName, name: NSNotification.Name(rawValue: aName), object: anObject)
- }
- /// 发送通知
- /// - Parameter aName: <#aName description#>
- /// - Returns: <#description#>
- public func postNotification(name aName: String, userInfo: [AnyHashable: Any]? = nil) {
- PQNotification.post(name: NSNotification.Name(aName), object: nil, userInfo: userInfo)
- }
- /// 获取是否打开推送
- /// - Parameter completeHander: <#completeHander description#>
- /// - Returns: <#description#>
- public func pushNotificationIsOpen(completeHander: ((_ isOpen: Bool) -> Void)?) {
- if #available(iOS 10.0, *) {
- UNUserNotificationCenter.current().getNotificationSettings { setttings in
- completeHander!(setttings.authorizationStatus == .authorized)
- }
- } else {
- completeHander!(UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false)
- }
- }
- /// 发送上传本地推送
- /// - Parameter isSuccess: 是否上传成功
- /// - Returns: <#description#>
- public func sendUploadNotification(isSuccess: Bool) {
- let title: String = isSuccess ? "上传完成了!" : "上传失败了!"
- let body: String = isSuccess ? "请点击发布,完成上传。否则,您的视频可能丢失" : "快来看看怎么了?"
- sendLocalNotification(title: title, body: body)
- }
- /// 发送本地推送
- /// - Parameters:
- /// - title: 标题
- /// - body: 内容
- /// - Returns: <#description#>
- public func sendLocalNotification(title: String, body: String) {
- // 设置推送内容
- if #available(iOS 10.0, *) {
- let content = UNMutableNotificationContent()
- content.title = title
- content.body = body
- content.badge = 1
- // 设置通知触发器
- let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
- // 设置请求标识符
- let requestIdentifier = getUniqueId(desc: "notification\(title)")
- // 设置一个通知请求
- let request = UNNotificationRequest(identifier: requestIdentifier,
- content: content, trigger: trigger)
- // 将通知请求添加到发送中心
- UNUserNotificationCenter.current().add(request) { error in
- if error == nil {
- print("Time Interval Notification scheduled: \(requestIdentifier)")
- }
- }
- } else {
- // Fallback on earlier versions
- let notification = UILocalNotification()
- notification.alertBody = body
- notification.alertTitle = title
- notification.applicationIconBadgeNumber = 1
- notification.fireDate = Date(timeIntervalSinceNow: 0)
- UIApplication.shared.scheduledLocalNotifications = [notification]
- }
- }
- /// 打开应用设置
- public func openAppSetting() {
- if UIApplication.shared.canOpenURL(URL(string: UIApplication.openSettingsURLString)!) {
- UIApplication.shared.openURL(URL(string: UIApplication.openSettingsURLString)!)
- }
- }
- /// dns解析
- /// - Parameter hostUrl: speed.piaoquantv.com /
- /// - Returns: <#description#>
- public func parseDNS(hostUrl: String) -> [String: Any]? {
- let host: CFHost? = CFHostCreateWithName(nil, hostUrl as CFString).takeRetainedValue()
- let start = CFAbsoluteTimeGetCurrent()
- var success: DarwinBoolean = false
- var addressList: [String] = Array<String>.init()
- var addresses: NSArray?
- if CFHostStartInfoResolution(host!, .addresses, nil) {
- addresses = (CFHostGetAddressing(host!, &success)?.takeUnretainedValue())
- }
- if success == true {
- for case let theAddress as NSData in addresses! {
- var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
- if getnameinfo(theAddress.bytes.assumingMemoryBound(to: sockaddr.self), socklen_t(theAddress.length),
- &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0
- {
- let numAddress = String(cString: hostname)
- addressList.append("\(hostUrl)/\(numAddress)")
- }
- }
- }
- let end = CFAbsoluteTimeGetCurrent()
- let duration = end - start
- BFLog(message: "duration = \(duration)")
- BFLog(message: "addressList = \(addressList)")
- if addressList.count > 0 {
- return ["dnsResult": arrayToJsonString(addressList), "duration": duration * 1000, "hostName": hostUrl, "networkType": networkStatus()]
- } else {
- return nil
- }
- }
- /// 获取当前日期
- /// - Returns: <#description#>
- public func systemCurrentDate() -> String {
- let dateFormatter = DateFormatter()
- dateFormatter.dateFormat = "YYYY-MM-dd"
- return dateFormatter.string(from: Date())
- }
- /// 时间戳转日期
- /// - Parameter timeInterval: <#timeInterval description#>
- /// - Returns: <#description#>
- public func timeIntervalToDateString(timeInterval: TimeInterval) -> String {
- let date = Date(timeIntervalSince1970: timeInterval)
- let dateFormatter = DateFormatter()
- dateFormatter.dateFormat = "yyyy年MM月dd日"
- return dateFormatter.string(from: date)
- }
- public func updateTimeToCurrenTime(timeInterval: TimeInterval) -> String {
- //获取当前的时间戳
- let currentTime = Date().timeIntervalSince1970
- // print(currentTime, timeInterval, "sdsss")
- //时间戳为毫秒级要 / 1000, 秒就不用除1000,参数带没带000
- // let timeSta:TimeInterval = TimeInterval(timeInterval / 1000)
- // 时间差
- let reduceTime: TimeInterval = currentTime - timeInterval
- // 时间差小于60秒
- if reduceTime < 60 {
- return "刚刚"
- }
- // 时间差大于一分钟小于60分钟内
- let mins = Int(reduceTime / 60)
- if mins < 60 {
- return "\(mins)分钟前"
- }
- let hours = Int(reduceTime / 3600)
- if hours < 24 {
- return "\(hours)小时前"
- }
- // let days = Int(reduceTime / 3600 / 24)
- // if days < 30 {
- // return "\(days)天前"
- // }
- // 不满足上述条件---或者是未来日期-----直接返回日期
- let date = NSDate(timeIntervalSince1970: timeInterval)
- let dfmatter = DateFormatter()
- // yyyy-MM-dd HH:mm:ss
- dfmatter.dateFormat = "yyyy年M月d日 HH:mm"
- var dfmatterStr = dfmatter.string(from: date as Date)
- let currentDF = DateFormatter()
- // yyyy-MM-dd HH:mm:ss
- currentDF.dateFormat = "yyyy"
- let currentDFStr = currentDF.string(from: Date())
- if dfmatterStr.hasPrefix(currentDFStr) {
- dfmatterStr.removeFirst(currentDFStr.count + 1)
- }
- return dfmatterStr
- }
- /// 判断字符串或者字典是否为空
- /// - Parameter object: <#object description#>
- /// - Returns: <#description#>
- public func isEmpty(object: Any?) -> Bool {
- if object == nil {
- return true
- }
- if object is String {
- return (object as! String).count <= 0
- }
- if object is [String: Any] {
- return (object as! [String: Any]).keys.count <= 0
- }
- return false
- }
- public func isEmptyObject(object: Any?) -> Bool {
- if object == nil {
- return true
- }
- if object is String {
- return object == nil || ((object as? String)?.count ?? 0) <= 0
- }
- if object is [String: Any] {
- return object == nil || ((object as? [String: Any])?.keys.count ?? 0) <= 0
- }
- // if object is List<Object> {
- // return object == nil || ((object as? List<Object>)?.count ?? 0) <= 0
- // }
- return false
- }
- /// <#Description#>
- /// - Parameter string: <#string description#>
- /// - Returns: <#description#>
- public func isIncludeChineseIn(string: String) -> Bool {
- for (_, value) in string.enumerated() {
- if value >= "\u{4E00}", value <= "\u{9FA5}" {
- return true
- }
- }
- return false
- }
- /// 获取文件内容的MD5
- /// - Parameters:
- /// - path: 地址
- /// - data: data
- /// - Returns: <#description#>
- public func contentMD5(path: String? = nil, data _: Data? = nil) -> String? {
- if path == nil || (path?.count ?? 0) <= 0 || !FileManager.default.fileExists(atPath: path ?? "") {
- BFLog(message: "生成内容md5值:地址错误或者不存在\(String(describing: path))")
- return ""
- }
- let att = try? FileManager.default.attributesOfItem(atPath: path ?? "")
- let size = Int64(att?[FileAttributeKey.size] as! UInt64)
- if size <= 0 {
- BFLog(message: "生成内容md5值:文件大小为0\(size)")
- return ""
- }
-
- let hash: String = PQBridgeObject.base64Md5(forFilePath: path ?? "")
- BFLog(message: "生成内容md5值:contentMD5 = \(hash)")
- return hash
- }
- /// 自适应宽
- /// - Parameters:
- /// - width: <#width description#>
- /// - baseWidth: <#baseWidth description#>
- /// - Returns: <#description#>
- public func adapterWidth(width: CGFloat, baseWidth: CGFloat = 375) -> CGFloat {
- return width / baseWidth * cScreenWidth
- }
- /// 自适应高
- /// - Parameters:
- /// - height: <#height description#>
- /// - baseHeight: <#baseHeight description#>
- /// - Returns: <#description#>
- public func adapterHeight(height: CGFloat, baseHeight: CGFloat = 812) -> CGFloat {
- return height / baseHeight * cScreenHeigth
- }
- /// 检测URL
- /// - Parameter url: <#url description#>
- /// - Returns: <#description#>
- public func isValidURL(url: String?) -> Bool {
- if url == nil || (url?.count ?? 0) <= 4 || (!(url?.hasPrefix("http") ?? false) && !(url?.hasPrefix("https") ?? false)) {
- return false
- }
- return true
- }
- /// 相册数据按创建时间排序
- public var creaFetchOptions: PHFetchOptions = {
- let fetchOptions = PHFetchOptions()
- fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
- return fetchOptions
- }()
- /// 相册数据按修改时间排序
- public var modiFetchOptions: PHFetchOptions = {
- let fetchOptions = PHFetchOptions()
- fetchOptions.sortDescriptors = [NSSortDescriptor(key: "modificationDate", ascending: false)]
- return fetchOptions
- }()
- /// 获取本地素材
- public var avAssertOptions: [String: Any]? = {
- [AVURLAssetPreferPreciseDurationAndTimingKey: NSNumber(value: true)]
- }()
- /// 播放动画图
- public var playGifImages: [UIImage] = {
- var gifImages = Array<UIImage>.init()
- for i in 0 ... 44 {
- gifImages.append(UIImage(named: "\(i).png")!)
- }
- return gifImages
- }()
- /// 压缩图片
- /// - Parameter image: <#image description#>
- /// -
- /// - Returns: <#description#>
- public func zipImage(image: UIImage?, size: Int) -> Data? {
- var data = image?.pngData()
- var dataKBytes = Int(data?.count ?? 0) / 1000
- var maxQuality = 0.9
- while dataKBytes > size, maxQuality > 0.01 {
- maxQuality = maxQuality - 0.01
- data = image?.jpegData(compressionQuality: CGFloat(maxQuality))
- dataKBytes = (data?.count ?? 0) / 1000
- }
- return data
- }
- /// 压缩图片到指定大小
- /// - Parameters:
- /// - image: <#image description#>
- /// - maxLength: <#maxLength description#>
- /// - cyles: <#cyles description#>
- /// - Returns: <#description#>
- public func zipImageQuality(image: UIImage, maxLength: NSInteger, cyles: Int = 6) -> Data {
- var compression: CGFloat = 1
- var data = image.jpegData(compressionQuality: compression)!
- if data.count < maxLength {
- return data
- }
- var max: CGFloat = 1
- var min: CGFloat = 0
- var bestData: Data = data
- for _ in 0 ..< cyles {
- compression = (max + min) / 2
- data = image.jpegData(compressionQuality: compression)!
- if Double(data.count) < Double(maxLength) * 0.9 {
- min = compression
- bestData = data
- } else if data.count > maxLength {
- max = compression
- } else {
- bestData = data
- break
- }
- }
- return bestData
- }
- public func resetImgSize(sourceImage: UIImage, maxImageLenght: CGFloat, maxSizeKB: CGFloat) -> Data {
- var maxSize = maxSizeKB
- var maxImageSize = maxImageLenght
- if maxSize <= 0.0 {
- maxSize = 1024.0
- }
- if maxImageSize <= 0.0 {
- maxImageSize = 1024.0
- }
- // 先调整分辨率
- var newSize = CGSize(width: sourceImage.size.width, height: sourceImage.size.height)
- let tempHeight = newSize.height / maxImageSize
- let tempWidth = newSize.width / maxImageSize
- if tempWidth > 1.0, tempWidth > tempHeight {
- newSize = CGSize(width: sourceImage.size.width / tempWidth, height: sourceImage.size.height / tempWidth)
- } else if tempHeight > 1.0, tempWidth < tempHeight {
- newSize = CGSize(width: sourceImage.size.width / tempHeight, height: sourceImage.size.height / tempHeight)
- }
- UIGraphicsBeginImageContext(newSize)
- sourceImage.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
- let newImage = UIGraphicsGetImageFromCurrentImageContext()
- UIGraphicsEndImageContext()
- var imageData = newImage!.jpegData(compressionQuality: 1.0)
- var sizeOriginKB: CGFloat = CGFloat((imageData?.count)!) / 1024.0
- // 调整大小
- var resizeRate = 0.9
- while sizeOriginKB > maxSize, resizeRate > 0.1 {
- imageData = newImage!.jpegData(compressionQuality: CGFloat(resizeRate))
- sizeOriginKB = CGFloat((imageData?.count)!) / 1024.0
- resizeRate -= 0.1
- }
- return imageData!
- }
- /// 获取开屏广告图
- /// - Returns: <#description#>
- public func getLaunchImage() -> UIImage {
- var lauchImg: UIImage!
- var viewOrientation: String!
- let viewSize = UIScreen.main.bounds.size
- let orientation = UIApplication.shared.statusBarOrientation
- if orientation == .landscapeLeft || orientation == .landscapeRight {
- viewOrientation = "Landscape"
- } else {
- viewOrientation = "Portrait"
- }
- let imgsInfoArray = Bundle.main.infoDictionary!["UILaunchImages"]
- for dict: [String: String] in imgsInfoArray as! Array {
- let imageSize = NSCoder.cgSize(for: dict["UILaunchImageSize"]!)
- if __CGSizeEqualToSize(imageSize, viewSize), viewOrientation == dict["UILaunchImageOrientation"]! as String {
- lauchImg = UIImage(named: dict["UILaunchImageName"]!)
- }
- }
- return lauchImg
- }
- public func currentBundlePath() -> Bundle?{
- // var associateBundleURL = Bundle.main.url(forResource: "Frameworks", withExtension: nil)
- // associateBundleURL = associateBundleURL?.appendingPathComponent("BFFramework")
- // associateBundleURL = associateBundleURL?.appendingPathExtension("framework")
- //
- // if associateBundleURL == nil {
- // print("获取bundle失败")
- // return nil
- // }
- // let associateBunle = Bundle(url: associateBundleURL!)
- let associateBundleURL = Bundle.main.url(forResource: "BFFramework_Resources", withExtension: "bundle")
- if associateBundleURL == nil {
- return nil
- }
- return Bundle(url: associateBundleURL!)
- }
|