IOS开发Swift——开发小知识(持续更新)

如有错误,请指正!谢谢!

侵权删!(部分转载)

1.PHAsset获取本地视频的url

PHCachingImageManager().requestAVAsset(forVideo: asset, options:nil, resultHandler: { (asset, audioMix, info)in

          let  avAsset = asset as? AVURLAsset
          print(asset?.url)
})

2.手势冲突

moreTap.require(toFail: singleTap)
//优先检测singleTap,若singleTap检测不到,或检测失败,则检测moreTap,检测成功后,触发方法
singleTap.require(toFail: moreTap)
//优先检测moreTap,若moreTap检测不到,或检测失败,则检测singleTap,检测成功后,触发方法

原文链接:https://blog.csdn.net/a645258072/article/details/72896196

3.UITableViewCell UIButton不响应点击事件

cell.contentView.addSubview:(button)

4.ableViewCell取消点击方法与取消点击高亮状态

//取消触发点击方法
self.tableView.allowsSelection = false

//取消点击高亮
cell.selectionStyle = .none

5.UITableView 禁止滑动

tableView.isScrollEnabled = false

6.根据cell里的子控件来获取cell,以UIbutton为例

func superUITableViewCell(of : UIButton) -> TableViewCell?{
        for view in sequence(first: of.superview, next: { $0?.superview }) {
            if let cell = view as? TableViewCell {
                return cell
            }
        }
        return nil
    }

7.收起/聚焦键盘

//收起键盘
//方法1
textField.resignFirstResponder()

//方法2
UIApplication.shared.keyWindow?.endEditing(true)

ios13弃用keyWindow,可以用
self.view.endEditing(true)

//聚焦输入框
textField.becomeFirstResponder()

8.管理Placeholder的文本属性(包括字体、颜色、大小)

textField.attributedPlaceholder = NSAttributedString(string: __("文本内容"),
                                                        attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15),
                                                                     NSAttributedString.Key.foregroundColor: UIColor.init(hex: 0x000000,alpha: 0.5)])

9.textfield文本距离边框的距离设置

 let leftView = UIView.init(frame:CGRect.init(x:0, y: 0, width:12, height: 20))
                leftView.backgroundColor = .clear
 let textField = UITextField()
   


textField.leftViewMode = .always    //此句代码较容易忽略
textField.leftView = leftView

//清空按钮的设置
textField.clearButtonMode = .whileEditing

10.sqlite更新blob类型数据

let sql = "update \(name) set coverPhoto=cast((?) as blob) where id=\(id)"
let db = SQLiteManager.shareManger().db
db.executeUpdate(sql, withArgumentsIn: [coverPhoto as Data])

//主要是
cast((?) as blob) 与 [coverPhoto as Data] 表明存入数据类型和发过来的数据类型
//cast(xxx as 类型).    convert(xxx,类型)

11.获取字典的key或者value

 Array(listArray[num].keys)[0]
 Array(listArray[num].values)[0]

12.相册图片资源获取

//申请权限 
PHPhotoLibrary.requestAuthorization({ (status) in
            if status != .authorized {
                DispatchQueue.main.async {
//                    self.navigationController?.popViewController(animated: true)
                }
                
            }else{
            // 列出所有系统的智能相册
            let smartOptions = PHFetchOptions()
            let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum,
                                                                      subtype: .albumRegular,
                                                                      options: smartOptions)
            self.convertCollection(collection: smartAlbums)
            
            //列出所有用户创建的相册
            let userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
            self.convertCollection(collection: userCollections
                                   as! PHFetchResult<PHAssetCollection>)
            
            //相册按包含的照片数量排序(降序)
            self.items.sort { (item1, item2) -> Bool in
                return item1.fetchResult.count > item2.fetchResult.count
            }
            
            //异步加载表格数据,需要在主线程中调用reloadData() 方法
            DispatchQueue.main.async{
                if self.items.count == 0{
                    
                }else{

                }
               
            }
        }
        })




 //转化处理获取到的相簿
    private func convertCollection(collection:PHFetchResult<PHAssetCollection>){
        
        for i in 0..<collection.count{
            //获取出但前相簿内的图片
            let resultsOptions = PHFetchOptions()
            resultsOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate",
                                                               ascending: false)]
            let c = collection[i]
            let assetsFetchResult = PHAsset.fetchAssets(in: c , options: resultsOptions)
            //没有图片的空相簿不显示
            if assetsFetchResult.count > 0{
                let title = titleOfAlbumForChinse(title: c.localizedTitle)
                items.append(AlbumItem(title: title,
                                       fetchResult: assetsFetchResult))
            }
        }
        
    }



//相册名转化
   private func titleOfAlbumForChinse(title:String?) -> String? {
        if title == "Slo-mo" {
            return __("慢动作")
        } else if title == "Recently Added" {
            return __("最近添加")
        } else if title == "Favorites" {
            return __("个人收藏")
        } else if title == "Recently Deleted" {
            return __("最近删除")
        } else if title == "Videos" {
            return __("视频")
        } else if title == "All Photos" {
            return __("所有照片")
        } else if title == "Selfies" {
            return __("自拍")
        } else if title == "Screenshots" {
            return __("屏幕快照")
        } else if title == "Camera Roll" {
            return __("相机胶卷")
        }
        return title
    }

13.相册资源缩略图获取

self.imageManager.requestImage(for: assetObject, targetSize: assetGridThumbnailSize,
                                                                  contentMode: PHImageContentMode.aspectFit,
                                                                  options: nil) { (image, nfo) in
                                    (photoThumbnail = image?.pngData())
                                }

详细链接:Swift - 使用PhotoKit获取照片1(获取所有照片缩略图、原图及其信息)

14.相册视频移出

let option = PHVideoRequestOptions()
option.version = PHVideoRequestOptionsVersion.current
option.deliveryMode = PHVideoRequestOptionsDeliveryMode.automatic
                                        
let manager = PHImageManager.default()
manager.requestExportSession(forVideo: assetObject, options: option, exportPreset: AVAssetExportPresetPassthrough) {exportSession, info in
let videoPath = URL(fileURLWithPath: toURLPath)
if let session = exportSession{
    session.outputURL = videoPath
    session.outputFileType = session.supportedFileTypes.first
                                                session.exportAsynchronously(completionHandler: {
    switch session.status {
        case .failed:
            print("移出失败")
            break
        case .completed:
            print("移出成功")
            break
                                                        
        default:
            break                                    
    } 
}

15.加入缓存

lazy var imageCache:SDImageCache = {
    let cache = SDImageCache()
    return cache
}()


let imageId = String(indexPath.row)
if let cacheImage = imageCache.imageFromMemoryCache(forKey: imageId){
    cell.photoImageView.image = cacheImage
}else{
    DispatchQueue.main.async { [self] in
        let url = photoUrl
        print(url)
        cell.photoImageView.sd_setImage(with: url.toURL(), completed: nil)
        self.imageCache.storeImage(toMemory: cell.photoImageView.image, forKey: imageId)
    }
    LLog("无缓存", imageId)
}

16.关于HEIC/HEIF图片检测与转化为JPG图片

import Photos

var isHEIC = false
let resources = PHAssetResource.assetResources(for: asset)
for resource in resources {
    let uti = resource.uniformTypeIdentifier
    if uti == "public.heic" || uti == "public.heif" {
        isHEIC = true
        break
    }
}

PHImageManager.default().requestImageData(for: asset, options: nil) { (imageData, dataUTI, orientation, info) in
    if isHEIC {  // 如果是 HEIC 图片
        guard let imageData = imageData,
            let ciImage = CIImage(data: imageData),
            let colorSpace = ciImage.colorSpace else { return }
        let context = CIContext()
        guard let jpgData = context.jpegRepresentation(of: ciImage, colorSpace: colorSpace, options: [:]),
            let jpgImage = UIImage(data: jpgData) else { return }
            // 将原图片替换为 jpgImage
    } else {  // 如果不是 HEIC 图片
        // 继续使用原图片
    }
}

详细链接:掘金

17.检测图片是否属于iCloud,并弹窗提示

let selectedAsset = assets[indexPath.item]
            
let resourceArray = PHAssetResource.assetResources(for: selectedAsset)
let value = resourceArray.last?.value(forKey: "locallyAvailable")
var isLocal: Bool = false
if value is NSNumber {
    let number: NSNumber = value as! NSNumber
    isLocal = number.boolValue
}
            
if !isLocal {
    let alert = UIAlertController(title: nil, message: __("该照片储存在iCloud中,请下载到系统相册"), preferredStyle: .alert)
    let cancelAction = UIAlertAction(title: __("取消"), style: .default, handler: nil)
    alert.addAction(cancelAction)
    self.present(alert, animated: true, completion: nil)
    return
}

18.ipad多任务方向支持被拒

UIRequiresFullScreen键添加到 Xcode 项目Info.plist文件并应用布尔值YES

https://stackoverflow.com/questions/32559724/ipad-multitasking-support-requires-these-orientations

19.进入页面自动聚焦输入栏

view.textfield.becomeFirstResponder()

20.实况图片的本地存储与读取

//存入文件夹
var isHEIC = false
let resources = PHAssetResource.assetResources(for: assetObject)
for resource in resources {
    let uti = resource.uniformTypeIdentifier
    if uti == "public.heic" || uti == "public.heif" {
       isHEIC = true
       break
    }
}

PHImageManager.default().requestImageData(for: assetObject, options: nil) { (imageData, dataUTI, orientation, info) in
     if isHEIC {
        try! imageData!.write(to: URL(fileURLWithPath:documentPath+"/"+fileUrl+filename))
                                        
     }else{
      
     }
}


//读取
let suffix = photoDatas[firstNum].photoUrl.extension
//extension 是获取后缀名的扩展

if suffix == ".HEIC" || suffix == ".HEIF"{
    do{
        let data = try Data(contentsOf: URL(fileURLWithPath: photoUrl))
        let image = UIImage(data: data)
        previewImageView.image = image
    } catch{
        print("ERROR")
    }
}else{
}

21.慢动作视频的后缀名获取失败

let fileName = avAsset?.url.lastPathComponent ?? "MP4"//一定要给好备选项,不要强解析

22.让某view一直在最上面显示

view.layer.zPosition = .greatestFiniteMagnitude


(父)self.view.bringSubviewToFront(view)(子)

23.从后台切换到前台,或者锁屏后开启唤醒

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()    
 
        NotificationCenter.default.addObserver(self,selector:
        #selector(applicationDidBecomeActive),name:
        UIApplication.didBecomeActiveNotification, object: nil)

    }

    @objc func applicationDidBecomeActive(notification: NSNotification) {
        // Application is back in the foreground

        print("applicationDidBecomeActive")
    }

}

链接:https://blog.csdn.net/zgpeace/article/details/107833217

24.获取鼠标点击处位置

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //获取点击的坐标位置
            for touch:AnyObject in touches {
                let t:UITouch = touch as! UITouch
                print(t.location(in: self))
            }
        }

链接:macos - 在Swift中获取鼠标坐标 - IT工具网

25.获取视图在父元素里的位置

//获取self.cView在self.sView的坐标,size是self.CView;

        let crect2 = self.sView?.convert((self.cView?.frame)!, from: self.cView);


//获取self.cView在self.sView的坐标,size是self.CView;
        let crect = self.cView?.convert((self.cView?.frame)!, to: self.sView);

26.获取当前视图的父视图或父控制器

//获取当前视图所在导航控制器
    func currentNavViewController() -> UINavigationController? {
        var n = next
        while n != nil {
            if n is UINavigationController {
                return n as? UINavigationController
            }
            n = n?.next
        }
        return nil
    }

链接:swift 、OC 获取Controller或者View的方法 总结 - 代码先锋网

27.根据关键字过滤数组

//开头关键字
let array = ["asd","fff","aaa","sad"]
let filteredArray = array.filter(){
    return $0.hasPrefix("a")
}

//包含关键字
let array = ["aaa","asd","dd"]
let filteredArray = array.filter(){
    return $0.rangeOfString("a") != nil
}

链接:Swift - 使用闭包筛选过滤数据元素

28.NotificationCente,通知的发送与监听

//设定通知并发送
let notificationName = Notification.Name("sublineNotifiction")
NotificationCenter.default.post(name: notificationName, object: self, userInfo: ["direction":content])


//通知接受并处理
let notificationName = Notification.Name("sublineNotifiction")
NotificationCenter.default.addObserver(self, selector: #selector(setsubline(notification: )), name: notificationName, object: nil)

@objc func setsubline(notification:Notification){
        let userInfo = notification.userInfo as! [String: AnyObject]
        let direct = userInfo["direction"]!
}

//如果不需要的话,记得把相应的通知注册给取消,避免内存浪费或崩溃
deinit {
        NotificationCenter.default.removeObserver(self)
    }

链接:Swift - 使用NotificationCenter发送通知,接收通知

29.UserDefaults的使用(不是ground)

//Setting.swift
struct ProjectKeys{
    static let quickSaveTime = "quickSaveTime"
}

let defaults = UserDefaults.standard

struct Setting{
    static var quickSaveTime:Int{
        set{
            defaults.set(newValue,forKey: ProjectKeys.quickSaveTime)
        }
        get {
            return defaults.integer(forKey: ProjectKeys.quickSaveTime)
        }
    }
    
}


//初始化
 UserDefaults.standard.register(defaults: ["quickSaveTime":1])

//使用
Setting.quickSaveTime = 0

30.tableView section header 的样式设置

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        guard let header = view as? UITableViewHeaderFooterView else { return }
        header.textLabel?.textColor = UIColor.black
        header.textLabel?.font = UIFont.systemFont(ofSize:16 ,weight:.black)
        header.textLabel?.frame = header.frame
        header.textLabel?.textAlignment = .center
        
    }

链接:如何更改UITableView Section Header的字体大小? - 问答 - 云+社区 - 腾讯云

31.view的部分圆角设置

lazy var backView: UIView = {
        let view = UIView()
        view.layer.maskedCorners = CACornerMask(rawValue: CACornerMask.layerMinXMinYCorner.rawValue | CACornerMask.layerMaxXMinYCorner.rawValue)
        view.layer.cornerRadius = 15
        view.clipsToBounds = true
        view.backgroundColor = .white
        return view
    }()

32.coredata的封装使用

class Message{
    var id:Int32?
    var message:String?
    
    init(id:Int32?,message:String){
        self.id = id
        self.message = message
    }
}
///添加数据
public func addData(id:Int32,message:String)
{
    // 用來操作 Core Data 的常數
    let moc = (UIApplication.shared.delegate
               as! AppDelegate).persistentContainer.viewContext
    let myEntityName = "MessageData"
    // insert
    let student =
    NSEntityDescription.insertNewObject(
        forEntityName: myEntityName, into: moc)
    as! MessageData
    
    student.id = id
    student.message = message
    do {
        try moc.save()
        print("success")
    } catch {
        fatalError("\(error)")
    }
}


/// 查询数据
func queryData() -> [Message]
{
    //获取管理的数据上下文 对象
    var dataArr:[Message] = []
    let app = UIApplication.shared.delegate as! AppDelegate
    let fetchRequest = NSFetchRequest<MessageData>(entityName:"MessageData")
    let context = app.persistentContainer.viewContext
    //设置查询条件
    //        let predicate = NSPredicate(format: "")
    //        fetchRequest.predicate = predicate
    
    //查询操作
    do {
        let fetchedObjects = try context.fetch(fetchRequest)
        
        //遍历查询的结果
        for info in fetchedObjects{
            //                print("id=\(info.id)")
            //                print("username=\(info.message ?? "")")
            dataArr.append(Message(id: info.id, message: info.message!))
            
        }
    }
    catch {
        fatalError("不能保存:\(error)")
    }
    
    return dataArr
}

/// 修改数据操作
func modifyData(id:Int32, message:String)
{
    //获取管理的数据上下文 对象
    let app = UIApplication.shared.delegate as! AppDelegate
    let fetchRequest = NSFetchRequest<MessageData>(entityName:"MessageData")
    let context = app.persistentContainer.viewContext
    
    //设置查询条件
    let predicate = NSPredicate(format: "id= '\(id)' ", "")
    fetchRequest.predicate = predicate
    
    //查询操作
    do {
        let fetchedObjects = try context.fetch(fetchRequest)
        
        //遍历查询的结果
        for info in fetchedObjects{
            //修改密码
            info.message = message
            //重新保存
            try context.save()
        }
    }
    catch {
        fatalError("不能保存:\(error)")
    }
}

/// 删除数据操作
func deleteData(id:Int32)
{
    let app = UIApplication.shared.delegate as! AppDelegate
    let fetchRequest = NSFetchRequest<MessageData>(entityName:"MessageData")
    let context = app.persistentContainer.viewContext
    
    //设置查询条件
    let predicate = NSPredicate(format: "id= '\(id)' ", "")
    fetchRequest.predicate = predicate
    
    //查询操作
    do {
        let fetchedObjects = try context.fetch(fetchRequest)
        
        //遍历查询的结果
        for info in fetchedObjects{
            //删除对象
            context.delete(info)
        }
        
        //重新保存-更新到数据库
        try! context.save()
    }
    catch {
        fatalError("不能保存:\(error)")
    }
}

链接:Swift - 使用Core Data进行数据持久化存储    swift3.0:CoreData的使用 - 尚码园

Core Data · Swift 起步走。      Swift CoreData的使用 - 简书     [IOS开发]CoreData条件查询之NSPredicate应用 - 简书

33. UITextView 的 Placeholder 扩展


import Foundation

import UIKit

fileprivate var kTextViewPlaceholderLabel : Int = 0x2019_00
fileprivate var kTextViewPlaceholder      : Int = 0x2019_01
fileprivate var kTextViewPlaceholderColor : Int = 0x2019_02
fileprivate var kTextViewPlaceholderFont  : Int = 0x2019_03
fileprivate var kTextViewPlaceholderKeys  : Int = 0x2019_04

extension UITextView {

    /// 占位符
    var x_placeholder: String {
        get {
            if let placeholder = objc_getAssociatedObject(self, &kTextViewPlaceholder) as? String {
                return placeholder
            } else {
                return ""
            }
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholder, newValue, .OBJC_ASSOCIATION_RETAIN)
            x_placeholderLabel.text = newValue
        }
    }

    /// 占位符颜色
    var x_placeholderColor: UIColor {
        get {
            if let placeholderColor = objc_getAssociatedObject(self, &kTextViewPlaceholderColor) as? UIColor {
                return placeholderColor
            } else {
                return UIColor(hex: 0xC4C4C4)
            }
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderColor, newValue, .OBJC_ASSOCIATION_RETAIN)
            x_placeholderLabel.textColor = newValue
        }
    }

    /// 占位符字体
    var x_placeholderFont: UIFont {
        get {
            if let placeholderFont = objc_getAssociatedObject(self, &kTextViewPlaceholderColor) as? UIFont {
                return placeholderFont
            } else {
                return UIFont.systemFont(ofSize: 14)
            }
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderColor, newValue, .OBJC_ASSOCIATION_RETAIN)
            x_placeholderLabel.font = newValue
        }
    }

    /// 占位符 标签
    @IBInspectable var x_placeholderLabel: UILabel {
        get {
            var _placeholderLabel = UILabel()
            if let label = objc_getAssociatedObject(self, &kTextViewPlaceholderLabel) as? UILabel {
                _placeholderLabel = label
            } else {
                objc_setAssociatedObject(self, &kTextViewPlaceholderLabel, _placeholderLabel, .OBJC_ASSOCIATION_RETAIN)
            }

            addPlaceholderLabelToSuperView(label: _placeholderLabel)

            return _placeholderLabel
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderLabel, newValue, .OBJC_ASSOCIATION_RETAIN)
            addPlaceholderLabelToSuperView(label: newValue)
        }
    }

    /// 是否需要添加占位符到父视图
    fileprivate var x_placeHolderNeedAddToSuperView: Bool {
        get {
            if let isAdded = objc_getAssociatedObject(self, &kTextViewPlaceholderKeys) as? Bool {
                return isAdded
            }
            return true
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderKeys, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    /// 添加占位符到父视图
    ///
    /// - Parameter label: 占位符 标签
    fileprivate func addPlaceholderLabelToSuperView(label: UILabel) {

        guard x_placeHolderNeedAddToSuperView else { return }
        x_placeHolderNeedAddToSuperView = false

        NotificationCenter.default.addObserver(self, selector: #selector(x_textChange(noti:)), name: UITextView.textDidChangeNotification, object: nil)

        addSubview(label)
        label.snp.makeConstraints { (make) in
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: 8, left: 6, bottom: 0, right: 0))
        }
    }

    /// 编辑事件
    @objc fileprivate func x_textChange(noti: NSNotification) {
        let isEmpty = text.isEmpty
        print("text:\(String(describing: text))\nisEmpty:\(isEmpty)")
        x_placeholderLabel.text = isEmpty ? x_placeholder : ""
        x_placeholderLabel.isHidden = !isEmpty
    }
}

链接:Swift UITextView Placeholder Extension - 掘金

34.防止block的循环引用,

 guard let `self` = self else {return}

35.随机数

arc4random_uniform(11)//0...11

func rndm(min: Int, max: Int) -> Int {
    if max < min {
        fatalError("The max value should be greater than the min value.")
    }
    if min == max {
        return min
    }
    return Int(arc4random_uniform(UInt32((max - min) + 1))) + min
}
rndm(min: 1, max: 6) //dice roll

链接:

随机数

Swift中的随机数 - 知乎

36.字符串操作

        let str = "Hello";
               
        //截取某字符串的前3个字符串
        let sub1 = str.prefix(3)
        //截取某字符串的后3个字符串
        let sub2 = str.suffix(3)
        
        //通过获取字素位来截取字符串
        let index1 = str.index(str.endIndex, offsetBy: -3)
        let sub3 = str[index1..<str.endIndex]
        
        //截取字符串的第1个字符到第4个字符范围的字符串
        let index2 = str.index(str.startIndex, offsetBy: 1)
        let index3 = str.index(str.startIndex, offsetBy: 3)
        let sub4 = str[index2...index3]
        
        //只截取字符串的一个字素,返回值是Character类型
        let character = str[str.index(str.startIndex, offsetBy: 3, limitedBy: str.endIndex)!]
        print("character = \(String(character))")
        
        //返回一个可选类型的范围:Range<String.Index>
        //lowerBound不包含e    upperBound包含e
        let range = str.range(of: "e")!       
        let s = str[str.startIndex..<range.lowerBound]


        //替换一段内容,两个参数:替换的范围和用来替换的内容
        str.replaceSubrange(start...end, with: "new")
        //替换一段内容,有返回值,两个参数:要替换的内容和用来替换的内容
        let reStr = h.replacingOccurrences(of: "Hello", with: "H")

链接:Swift-字符串截取、替换、插入_SSY_1992的博客-CSDN博客_swift 字符串 替换

37. UIButton设置圆角和边框及边框颜色

链接:https://my.oschina.net/huqiji/blog/3027302

38.tableview的左滑菜单

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        
        let deleteAction = UIContextualAction(style: .normal, title: __("")) { (action, sourceView, completionHandler) in
            print("delete")
            let id = self.information[indexPath.item].id
            
            self.quickAlter(id: id!)
            completionHandler(true)
        }
        let copyAction = UIContextualAction(style: .normal, title: __("")) { (action, sourceView, completionHandler) in
            print("copy")
            let message = self.information[indexPath.item].message
            UIPasteboard.general.string = message
            
            self.toastLabel.isHidden = false
            Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false) { timer in
                self.toastLabel.isHidden = true
                timer.invalidate()
            }
            completionHandler(true)
        }
        let editAction = UIContextualAction(style: .normal, title: __("")) { (action, sourceView, completionHandler) in
            print("edit")
            Setting.quickSaveTime = 2
//            self.quickMessageView.saveButton.setTitle(<#T##title: String?##String?#>, for: <#T##UIControl.State#>)
            self.quickMessageView.isHidden = false
            self.quickMessageView.quickTextView.text = self.information[indexPath.item].message
            self.quickMessageView.quickTextView.x_placeholder = ""
            self.quickMessageView.quickTextView.x_placeholderLabel.isHidden = true
            self.quickMessageView.quickTextView.becomeFirstResponder()
            self.clickID = self.information[indexPath.item].id!
            completionHandler(true)
        }
        
        //            deleteAction.backgroundColor = self.tableView.backgroundColor
        deleteAction.image = UIImage(named: "delete")
        deleteAction.backgroundColor = UIColor(hex: 0xF6F6F6)
        copyAction.image = UIImage(named: "copy")
        copyAction.backgroundColor = UIColor(hex: 0xF6F6F6)
        editAction.image = UIImage(named: "edit")
        editAction.backgroundColor = UIColor(hex: 0xF6F6F6)
        
        let config = UISwipeActionsConfiguration(actions: [deleteAction,editAction,copyAction])
        
        // 取消拉动长后自动删除
        config.performsFirstActionWithFullSwipe = false
        
        return config
    }

39:alterview的封装

class AlterView: UIView{
    
    var clickCancel:(() -> Void)?
    var clickSetting:(() -> Void)?
    
    lazy var alterView: UIView = {
        let view = UIView()
        view.layer.cornerRadius = 10
        view.backgroundColor = .white
        return view
    }()
    
    lazy var titleLable: UILabel = {
        let label = UILabel()
        label.text = __("暂无内容")
        label.font = UIFont.systemFont(ofSize: 16, weight: .black)
        return label
    }()
    
    lazy var describLabel: UILabel = {
        let label = UILabel()
        label.text = __("是否进入快捷回复中设置")
        label.font = UIFont.systemFont(ofSize: 14)
        return label
    }()
    
    lazy var cancelButton: UIButton = {
        let button = UIButton()
        button.setTitle(__("取消"), for: .normal)
        button.setTitleColor(UIColor(hex:0x007AFF), for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        button.addTarget(self, action: #selector(cnacel), for: .touchUpInside)
        button.layer.borderWidth = 0.5
        return button
    }()
    
    lazy var settingButton: UIButton = {
        let button = UIButton()
        button.setTitle(__("去设置"), for: .normal)
        button.setTitleColor(UIColor(hex:0x007AFF), for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .black)
        button.addTarget(self, action: #selector(gosetting), for: .touchUpInside)
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUP()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension AlterView{
    func setUP(){
        
        addSubview(alterView)
        
        alterView.addSubviews(titleLable, describLabel, cancelButton, settingButton)
        
        alterView.snp.makeConstraints { make in
            make.width.equalTo(270)
            make.height.equalTo(140)
            make.center.equalToSuperview()
        }
        
        titleLable.snp.makeConstraints { make in
            make.top.equalToSuperview().inset(19)
            make.centerX.equalToSuperview()
        }
        
        describLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLable.snp.bottom).offset(15)
            make.centerX.equalToSuperview()
        }
        
        cancelButton.snp.makeConstraints { make in
            make.left.bottom.equalToSuperview()
            make.width.equalTo(135)
            make.height.equalTo(44)
        }
        
        settingButton.snp.makeConstraints { make in
            make.right.bottom.equalToSuperview()
            make.width.equalTo(135)
            make.height.equalTo(44)
        }
    }
}

extension AlterView{
    @objc func gosetting(){
        clickSetting!()
    }
    
    @objc func cnacel(){
        clickCancel!()
    }
}

40.禁止自动旋转

// 禁止自动旋转
    override var shouldAutorotate : Bool {
        return false
    }

41.横竖渐变

extension CAGradientLayer {
    //获取彩虹渐变层
    func rainbowLayer() -> CAGradientLayer {
        //定义渐变的颜色
        let gradientColors = [UIColor(hex: 0x000000, alpha: 1).cgColor,
                              UIColor(hex: 0x000000, alpha: 0).cgColor]
         
        //定义每种颜色所在的位置
        let gradientLocations:[NSNumber] = [0.0, 1.0]
         
        //创建CAGradientLayer对象并设置参数
        self.colors = gradientColors
        self.locations = gradientLocations
         
        //设置渲染的起始结束位置
        self.startPoint = CGPoint(x: 0, y: 0)
        self.endPoint = CGPoint(x: 0, y: 1)
         
        return self
    }
    
    func signViewLayer() -> CAGradientLayer {
        //定义渐变的颜色
        let gradientColors = [UIColor(hex: 0xF2D9B6, alpha: 1).cgColor,
                              UIColor(hex: 0xF2BB6D, alpha: 1).cgColor]
         
        //定义每种颜色所在的位置
        let gradientLocations:[NSNumber] = [0.0, 1.0]
         
        //创建CAGradientLayer对象并设置参数
        self.colors = gradientColors
        self.locations = gradientLocations
         
        //设置渲染的起始结束位置
        self.startPoint = CGPoint(x: 0, y: 0)
        self.endPoint = CGPoint(x: 1, y: 0)
         
        return self
    }
}


//应用
        let gradientLayer = CAGradientLayer().rainbowLayer()
        //设置彩虹渐变层的frame,并插入view的layer
        gradientLayer.frame = self.navView.frame
        self.navView.layer.insertSublayer(gradientLayer, at: 0)

42.导航栏设置

//标题颜色
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white]
        
//背景颜色
navigationController?.navigationBar.barTintColor = UIColor(red: 66/256.0, green: 176/256.0, blue: 216/256.0, alpha: 1)
        
//是否透明
navigationController?.navigationBar.isTranslucent = false

//是否显隐
navigationController?.navigationBar.isHidden = false

43.label行间距

//通过富文本来设置行间距
let paraph = NSMutableParagraphStyle()

//将行间距设置为28
paraph.lineSpacing = 20
        
//样式属性集合
let attributes = [NSFontAttributeName:UIFont.systemFont(ofSize: 15),NSParagraphStyleAttributeName: paraph]
        
label.attributedText = NSAttributedString(string: str, attributes: attributes)

链接: Swift - 设置UILabel、UITextView的文字行间距

44.label下划线

label2.attributedText = NSAttributedString(string: text, attributes: [NSAttributedStringKey.underlineStyle : 1])

链接: 创建一个带下划线的UILabel - 简书

45.系统语言类型获取

 let preferredLang = Bundle.main.preferredLocalizations.first! as NSString

链接: swift 获取当前系统语言 - 简书

46.分享弹窗


let content = URL(string: "https://apps.apple.com")

let activityVC = UIActivityViewController(activityItems: [content as Any], applicationActivities: nil)

if UIDevice.current.userInterfaceIdiom == .pad {
            if let wppc = activityVC.popoverPresentationController {
                wppc.sourceView = UIView()
            }
        }
      
//分享弹窗拉下后执行
activityVC.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
     if completed {
         Marketing.shared.didShareRT()
      }
   }

present(activityVC, animated: true, completion: nil)
 

47.阴影设置

//设置视图边框宽度        
view.layer.borderWidth = width        
//设置边框颜色        
view.layer.borderColor = bColor.cgColor        
//设置边框圆角        
view.layer.cornerRadius = radius        
//设置阴影颜色        
view.layer.shadowColor = sColor.cgColor        
//设置透明度        
view.layer.shadowOpacity = opacity        
//设置阴影半径        
view.layer.shadowRadius = radius        
//设置阴影偏移量        
view.layer.shadowOffset = offset

链接: Swift-视图阴影篇 - 简书 

48.相册权限与设置跳转封装


import Foundation
import Photos
import Toolkit

class AssetLibrary {
    
}

// MARK: - Permission
extension AssetLibrary {
    static func requestPermissions(_ authorizedBlock: @escaping () -> Swift.Void) {
        //相册
        let currentStatus = PHPhotoLibrary.authorizationStatus()
        switch currentStatus {
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization({ (status) in
                if status == .authorized {
                    DispatchQueue.main.async(execute: {
                        authorizedBlock()
                    })
                }
            })
        case .authorized:
            authorizedBlock()
        case .denied:
            let message = String(format: __("我们无权访问图片库,请更改隐私设置"), Util.appName())
            let title = __("无法访问相册")
            AssetLibrary.presentAskPermissionAlert(message: message, title: title)
            
        case .restricted:
            break
        case .limited:
            break
        @unknown default:
            fatalError()
        }
    }
    
    private static func presentAskPermissionAlert(message: String,title: String) {
        
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        
        alert.addAction(UIAlertAction(title:  __("取消"), style: .cancel, handler: nil))
        alert.addAction(UIAlertAction(title: __("去设置"), style: .default, handler: { (_) in
//            UIApplication.shared.openURL(URL(string: UIApplication.openSettingsURLString)!)
            UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
        }))
        
        Util.topViewController().present(alert, animated: true, completion: nil)
    }
    
    static func image(asset: PHAsset,
                       size: CGSize,
                       scale: CGFloat = UIScreen.main.scale,
                       resultHandler: @escaping (UIImage?, [AnyHashable : Any]?) -> Void)
     {
         let options = PHImageRequestOptions()
         options.deliveryMode = .opportunistic
         let retinaSize = CGSize(width: size.width * scale, height: size.height * scale)
         PHImageManager.default().requestImage(for: asset,
                                               targetSize: retinaSize,
                                               contentMode: .aspectFill,
                                               options: options,
                                               resultHandler:
         { (image, info) in
             DispatchQueue.main.async {
                 resultHandler(image, info)
             }
         })
     }
}

49.UIColor -> Int

extension UIColor  {
    var hexa: Int {
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
        getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        return Int(alpha * 255) << 24
             + Int(red   * 255) << 16
             + Int(green * 255) << 8
             + Int(blue  * 255)
    }
}

50.网络判定



import Foundation
import UIKit
import Alamofire

enum ReachabilityStatus{
   
   case notReachable
   case unknown
   case ethernetOrWiFi
   case wwan

}

class RLHTTPManage: NSObject {
   
   static let rlHttpManage = RLHTTPManage()
   func netWorkReachability(reachabilityStatus: @escaping(ReachabilityStatus)->Void){
       
       let manager = NetworkReachabilityManager.init()
       manager!.startListening { (status) in

           //wifi
           if status == NetworkReachabilityManager.NetworkReachabilityStatus.reachable(.ethernetOrWiFi){
               
               
               print("------.wifi")
                reachabilityStatus(.ethernetOrWiFi)
               
           }
           //不可用
           if status == NetworkReachabilityManager.NetworkReachabilityStatus.notReachable{
               
                 print("------没网")
               reachabilityStatus(.notReachable)
               
           }
           //未知
           if status == NetworkReachabilityManager.NetworkReachabilityStatus.unknown{

               print("------未知")
               reachabilityStatus(.unknown)
           }

           //蜂窝
           if status == NetworkReachabilityManager.NetworkReachabilityStatus.reachable(.cellular){
                      
                print("------蜂窝")
               reachabilityStatus(.wwan)
           }
       }
   }
}

51.图片质量优化


extension UIImage {
    
    func normalized() -> UIImage  {
        if (self.imageOrientation == UIImage.Orientation.up) {
            return self;
        }
        
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
        let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        self.draw(in: rect)
        
        if let normalizedImage = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return normalizedImage
        } else {
            return self
        }
    }
    
    func resizeImage() -> UIImage? {
        
        let originalImg = self
        //prepare constants
        let width = originalImg.size.width
        let height = originalImg.size.height
        let scale = width/height
        
        var sizeChange = CGSize()
        
        if width <= 1280 && height <= 1280 { //a,圖片寬或者高均小於或等於1280時圖片尺寸保持不變,不改變圖片大小
            return originalImg
        }else if width > 1280 || height > 1280 {//b,寬或者高大於1280,但是圖片寬度高度比小於或等於2,則將圖片寬或者高取大的等比壓縮至1280
            
            if scale <= 2 && scale >= 1 {
                let changedWidth:CGFloat = 1280
                let changedheight:CGFloat = changedWidth / scale
                sizeChange = CGSize(width: changedWidth, height: changedheight)
                
            }else if scale >= 0.5 && scale <= 1 {
                
                let changedheight:CGFloat = 1280
                let changedWidth:CGFloat = changedheight * scale
                sizeChange = CGSize(width: changedWidth, height: changedheight)
                
            }else if width > 1280 && height > 1280 {//寬以及高均大於1280,但是圖片寬高比大於2時,則寬或者高取小的等比壓縮至1280
                
                if scale > 2 {//高的值比較小
                    
                    let changedheight:CGFloat = 1280
                    let changedWidth:CGFloat = changedheight * scale
                    sizeChange = CGSize(width: changedWidth, height: changedheight)
                    
                }else if scale < 0.5{//寬的值比較小
                    
                    let changedWidth:CGFloat = 1280
                    let changedheight:CGFloat = changedWidth / scale
                    sizeChange = CGSize(width: changedWidth, height: changedheight)
                    
                }
            }else {//d, 寬或者高,只有一個大於1280,並且寬高比超過2,不改變圖片大小
                return originalImg
            }
        }
        
        UIGraphicsBeginImageContext(sizeChange)
        
        //draw resized image on Context
        originalImg.draw(in: CGRect(x: 0, y: 0, width: sizeChange.width, height: sizeChange.height))
        
        //create UIImage
        let resizedImg = UIGraphicsGetImageFromCurrentImageContext()
        
        UIGraphicsEndImageContext()
        
        return resizedImg
        
    }
    
}


//使用
image.normalized().resizeImage()

52.使view在controller上

self.navigationController?.view.addSubview(view)
self.view.bringSubviewToFront(view)//把操作层也放到最上面


   if #available(iOS 13, *) {
        UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.addSubview(retainView)
   } else {
        UIApplication.shared.keyWindow!.addSubview(retainView)
   }

53.UIView的自适应高度

//主要原理便是给予UIView里最后一个元素的bottom与UIView的关系

54.label文本不同颜色设置

 func textColorChange(labelObject:InputView, text:String){
        // 1. 获取 StoryBoard 中 Label 的原有属性
        let attributes = labelObject.titleLabel.attributedText!.attributes(at: 1, effectiveRange: NSRangePointer(bitPattern: 0))
        
        // 2. 创建新的可编辑的字符对象
        let mString = NSMutableAttributedString(string: text,
                                                attributes: attributes)
        
        // 3. 在生成的 NSMutableAttributedString 对象中修改前两位的颜色
        mString.setAttributes(
            [NSAttributedString.Key.foregroundColor : UIColor.red],
            range: NSRange(location: 0, length: 1)
        )
        
        // 4. 修改后面剩余字符的颜色
        mString.setAttributes(
            [NSAttributedString.Key.foregroundColor : UIColor(hex: 0x666666)],
            range: NSRange(location: 1, length: mString.string.count - 1)
        )
        // 5. 把修改好的 NSMutableAttributedString 重新赋值给 Label
        labelObject.titleLabel.attributedText = mString
    }

Swift 修改字符串的范围颜色 NSAttributedString NSMutableAttributedString_十月ooOO的博客-CSDN博客

55.自定义类型转json文本,json转对象


import Foundation


public protocol CGYJSON {
    func toJSONModel() -> AnyObject?
    func toJSONString() -> String?
}

extension CGYJSON {
    public func toJSONModel() -> AnyObject? {
        let mirror = Mirror(reflecting: self)
        guard mirror.children.count > 0 else {
            return self as? AnyObject
        }
        var result: [String: AnyObject] = [:]
        var superClss = mirror.superclassMirror()
        while superClss != nil {
            for case let (label?, value) in superClss!.children {
                if let jsonValue = value as? CGYJSON {
                    result[label] = jsonValue.toJSONModel()
                }
            }
            superClss = superClss?.superclassMirror()
        }
        for case let (label?, value) in mirror.children {
            if let jsonValue = value as? CGYJSON {
                result[label] = jsonValue.toJSONModel()
            }
        }
        return result
    }
    
    public func toJSONString() -> String? {
        guard let jsonModel = self.toJSONModel() else {
            return nil
        }
        let data = try? NSJSONSerialization.dataWithJSONObject(jsonModel, options: [])
        let str = NSString(data: data!, encoding: NSUTF8StringEncoding)
        return str as? String
    }
}

extension Optional: CGYJSON {
    public func toJSONModel() -> AnyObject? {
        if let _self = self {
            if let value = _self as? CGYJSON {
                return value.toJSONModel()
            }
        }
        return NSNull()
    }
}

extension Array: CGYJSON {
    public func toJSONModel() -> AnyObject? {
        var results: [AnyObject] = []
        for item in self {
            if let ele = item as? CGYJSON {
                if let eleModel = ele.toJSONModel() {
                    results.append(eleModel)
                }
            }
        }
        return results
    }
}

extension Dictionary: CGYJSON {
    public func toJSONModel() -> AnyObject? {
        var results: [String: AnyObject] = [:]
        for (key, value) in self {
            if let key = key as? String {
                if let value = value as? CGYJSON {
                    if let valueModel = value.toJSONModel() {
                        results[key] = valueModel
                        continue
                    }
                } else if let value = value as? AnyObject {
                    results[key] = value
                    continue
                }
                results[key] = NSNull()
            }
        }
        return results
    }
}

extension NSDate: CGYJSON {
    public func toJSONModel() -> AnyObject? {
        let dateFormat = NSDateFormatter()
        dateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
        return dateFormat.stringFromDate(self)
    }
}

extension String: CGYJSON {}
extension Int: CGYJSON {}
extension Int8: CGYJSON {}
extension Int16: CGYJSON {}
extension Int32: CGYJSON {}
extension Int64: CGYJSON {}
extension UInt: CGYJSON {}
extension UInt8: CGYJSON {}
extension UInt16: CGYJSON {}
extension UInt32: CGYJSON {}
extension UInt64: CGYJSON {}
extension Bool: CGYJSON {}
extension Float: CGYJSON {}
extension Double: CGYJSON {}



//js json转对象
var json = JSON.parse(str);
var json = eval("(" + str + ")");
var json = (new Function("return " + str))();





 链接:https://github.com/Chakery/JSONExample

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值