iOS积累的零碎常用操作swift

绝地灬酷狼 2022-10-01 05:50 400阅读 0赞

记录一些iOS学习过程中的笔记

iOS开发-零碎笔记

创建项目目录结构

  1. AppDelegate.swift:生命周期及变量的定义
  2. ViewController.swift: MVC的C
  3. Assets.xcasset:放资源文件,如图片等
  4. info.plist:配置文件
  5. xxxTest: 单元测试
  6. Products:生成的文件
  7. Main.storyboard: 视图

快捷添加注释

  1. option + command + /
  2. 复制代码

关闭软键盘

关闭代码

  1. textField.resignFirstResponder()
  2. 复制代码

关闭方式1: 在Controller中重写touchesEnded()方法,然后在这里面关闭软件盘,意思是点击空白处关闭

  1. override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
  2. name.resignFirstResponder()
  3. }
  4. 复制代码

关闭方式2: 点击下一步时,关闭软键盘; Controller实现UITextFieldDelegate协议; 实现UITextFieldDelegate协议中的textFieldShouldReturn方法;

  1. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  2. textField.resignFirstResponder()
  3. return true
  4. }
  5. 复制代码

UIDatePicker选择时间后计算年龄

  1. func calAge(by datePicker: UIDatePicker) -> Int? {
  2. let gregorian = NSCalendar(calendarIdentifier: .gregorian)
  3. let now = Date()
  4. let components = gregorian?.components(NSCalendar.Unit.year, from: datePicker.date, to: now, options: NSCalendar.Options.init(rawValue: 0))
  5. return components?.year
  6. }
  7. 复制代码

页面跳转,传递数据

有两个Controller:ViewController和GalleryViewController。从ViewController跳转到GalleryViewController。 ViewController重写方法:prepare,该方法在页面跳转时会被调用,我们需要在里面判断是跳转到哪个页面。

  1. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  2. // 需要给Segue取名
  3. if segue.identifier == "GoToGallery" {
  4. let index = beautyPicker.selectedRow(inComponent: 0)
  5. var imageName: String?
  6. switch index {
  7. case 0:
  8. imageName = "fangbingbing"
  9. case 1:
  10. imageName = "libingbing"
  11. case 2:
  12. imageName = "wangfei"
  13. case 3:
  14. imageName = "yangmi"
  15. case 4:
  16. imageName = "zhouxu"
  17. default:
  18. imageName = nil
  19. }
  20. // 得到下一个页面的Controller
  21. let vc = segue.destination as! GalleryViewController
  22. vc.imageName = imageName
  23. }
  24. }
  25. 复制代码

通过图片文件名设置图片

  1. beautyImage.image = UIImage(named: imageName)
  2. 复制代码

unwind segue关闭页面

关闭页面后,Controller可以获得上个页面传回来的值 该方法写在前一个页面

  1. @IBAction func closedPrePage(segue: UIStoryboardSegue) {
  2. print("closed")
  3. }
  4. 复制代码

TableView下移一个状态栏的高度解决

  1. 方法一

    if #available(iOS 11.0, *) {

    1. tableView.contentInsetAdjustmentBehavior = .never

    }
    复制代码

  2. 方法二,内容上部分区域向上偏移一个状态栏的高度

    collectionView?.contentInset.top = -UIApplication.shared.statusBarFrame.height
    复制代码

TableView 添加刷新

  1. let refreshControl = UIRefreshControl()
  2. // 初始化刷新
  3. refreshControl.backgroundColor = UIColor.blue //设置刷新的背景颜色
  4. refreshControl.attributedTitle = NSAttributedString(string: "刷新一下:\(Data())", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white]) // 设置字体颜色
  5. refreshControl.tintColor = UIColor.green // 加载菊花颜色
  6. refreshControl.tintAdjustmentMode = .dimmed // 色彩调整模式
  7. refreshControl.addTarget(self, action: #selector(addcount), for: .valueChanged) //添加方法目标
  8. // 添加该刷新
  9. tableView.refreshControl = refreshControl
  10. 复制代码

刷新方法

  1. @objc func addcount() {
  2. dataArrary.append(contentsOf: dataArrary)
  3. tableView.reloadData()
  4. refreshControl.endRefreshing()
  5. }
  6. 复制代码

向项目添加字体

developer.apple.com/documentati…

由于iOS的用的字体名称并不是文件名称,而是字体本身名称。 下面代码搜索所有字体,然后我们在控制台,找到多出来的名称。

  1. for family: String in UIFont.familyNames
  2. {
  3. print("\(family)")
  4. for names: String in UIFont.fontNames(forFamilyName: family)
  5. {
  6. print("== \(names)")
  7. }
  8. }
  9. 复制代码

设置tabbar 字体和字体大小

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. let appearance = UITabBarItem.appearance()
  4. appearance.setTitleTextAttributes([NSAttributedStringKey.font: UIFont(name: "Ubuntu-Light", size: 9)!], for: .normal)
  5. }
  6. 复制代码

UIButton 相关

UIButton.isEnabled = false后图片按钮的背景图片被改变

  1. UIButton.adjustsImageWhenDisabled = false
  2. 复制代码

扩展添加圆角、边框、边框颜色

  1. @IBDesignable extension UIButton {
  2. @IBInspectable var borderWidth: CGFloat {
  3. set {
  4. layer.borderWidth = newValue
  5. }
  6. get {
  7. return layer.borderWidth
  8. }
  9. }
  10. @IBInspectable var cornerRadius: CGFloat {
  11. set {
  12. layer.cornerRadius = newValue
  13. }
  14. get {
  15. return layer.cornerRadius
  16. }
  17. }
  18. @IBInspectable var borderColor: UIColor? {
  19. set {
  20. guard let uiColor = newValue else { return }
  21. layer.borderColor = uiColor.cgColor
  22. }
  23. get {
  24. guard let color = layer.borderColor else { return nil }
  25. return UIColor(cgColor: color)
  26. }
  27. }
  28. }
  29. 复制代码

扩展图片在上,文字在下

  1. extension UIButton {
  2. func alignVertical(spacing: CGFloat = 6.0, imageBottom: CGFloat = 0.0) {
  3. guard let imageSize = self.imageView?.image?.size,
  4. let text = self.titleLabel?.text,
  5. let font = self.titleLabel?.font
  6. else { return }
  7. self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
  8. let labelString = NSString(string: text)
  9. let titleSize = labelString.size(withAttributes: [NSAttributedStringKey.font: font])
  10. self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: imageBottom, right: -titleSize.width)
  11. let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
  12. self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
  13. }
  14. }
  15. 复制代码

UITableView或UICollectionView被TabBar遮盖

UITableView调用reloadData导致移动到列表顶部失效

  1. UIView.animate(withDuration: 0, animations: {
  2. self.tableView.contentOffset = CGPoint.zero
  3. }, completion: { _ in
  4. self.tableView.reloadData()
  5. })
  6. 复制代码

NavigationBar导致CollectionViewCell或TableViewCell偏移

  1. self.collectionView?.contentInsetAdjustmentBehavior = .automatic
  2. 复制代码

获取app版本

  1. /// 获取版本名
  2. let appVersion = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String
  3. /// 获取版本号
  4. let versionNumber = Bundle.main.infoDictionary!["CFBundleVersion"] as? String
  5. 复制代码

清理缓存

  1. func clearCache() {
  2. // 取出cache文件夹目录 缓存文件都在这个目录下
  3. let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
  4. // 取出文件夹下所有文件数组
  5. let fileArr = FileManager.default.subpaths(atPath: cachePath!)
  6. // 遍历删除
  7. for file in fileArr! {
  8. let path = cachePath?.appendingFormat("/\(file)")
  9. if FileManager.default.fileExists(atPath: path!) {
  10. do {
  11. try FileManager.default.removeItem(atPath: path!)
  12. } catch {
  13. }
  14. }
  15. }
  16. }
  17. 复制代码

打开网页本软件的appstore

  1. // App Store URL.
  2. let appStoreLink = "https://itunes.apple.com/cn/app/id1144351773?mt=8"
  3. /* First create a URL, then check whether there is an installed app that can open it on the device. */
  4. if let url = URL(string: appStoreLink), UIApplication.shared.canOpenURL(url) {
  5. // Attempt to open the URL.
  6. UIApplication.shared.open(url, options: [:], completionHandler: {(success: Bool) in
  7. if success {
  8. print("Launching \(url) was successful")
  9. }})
  10. }
  11. 复制代码

设置圆形展示图像

  1. 设置UIImageView宽度和高度,假如设置为60*60
  2. 设置运行时属性,设置圆弧为30(正方形边长度一半)
  3. 勾选Clip to Bounds

UIScrollView填充到顶部(去掉状态栏到空白间距)

  1. Content Insets 选择Never
  2. 去掉选中的Safe Area Relative Margins

UIImage 高斯模糊扩展

  1. extension UIImage {
  2. func blurred(radius: CGFloat) -> UIImage {
  3. let ciContext = CIContext(options: nil)
  4. guard let cgImage = cgImage else { return self }
  5. let inputImage = CIImage(cgImage: cgImage)
  6. guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
  7. ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
  8. ciFilter.setValue(radius, forKey: "inputRadius")
  9. guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
  10. guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
  11. return UIImage(cgImage: cgImage2)
  12. }
  13. }
  14. 复制代码

两个UIImage 合并扩展

  1. extension UIImage {
  2. func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
  3. let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
  4. let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
  5. let newSize = CGSize(width: newWidth, height: newHeight)
  6. UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
  7. draw(in: CGRect(origin: CGPoint.zero, size: size))
  8. image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
  9. let newImage = UIGraphicsGetImageFromCurrentImageContext()!
  10. UIGraphicsEndImageContext()
  11. return newImage
  12. }
  13. }
  14. 复制代码

SDWebImageView 下载图片

  1. 方式一

    img.sd_setImage(with: URL(string: “http://url“),
    placeholderImage: #imageLiteral(resourceName: “default_square”)) { image, error, cacheType, url in

    }
    复制代码

  2. 方式二

    SDWebImageDownloader
    .shared()
    .downloadImage(with: URL(string: “http://url“),

    1. options: SDWebImageDownloaderOptions.init(rawValue: 0),
    2. progress: nil,
    3. completed: { image, data, error, finished in
    4. if finished {
    5. }

    })
    复制代码

AVPlayerViewController 视频播放

  1. import AVKit
  2. func playVideoByUrl(string: String) {
  3. let videoURL = URL(string: string)
  4. let player = AVPlayer(url: videoURL!)
  5. let playerViewController = AVPlayerViewController()
  6. playerViewController.player = player
  7. self.present(playerViewController, animated: true) {
  8. playerViewController.player!.play()
  9. }
  10. }
  11. 复制代码

为UIImageView添加的点击手势无效

  1. 勾选上User Interaction Enabled
  2. 代码中设置uiimageview.userInteractionEnabled = true

PHAsset获取文件路径

  1. extension PHAsset {
  2. func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
  3. if self.mediaType == .image {
  4. let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
  5. options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
  6. return true
  7. }
  8. self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
  9. completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
  10. })
  11. } else if self.mediaType == .video {
  12. let options: PHVideoRequestOptions = PHVideoRequestOptions()
  13. options.version = .original
  14. PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
  15. if let urlAsset = asset as? AVURLAsset {
  16. let localVideoUrl: URL = urlAsset.url as URL
  17. completionHandler(localVideoUrl)
  18. } else {
  19. completionHandler(nil)
  20. }
  21. })
  22. }
  23. }
  24. }
  25. 复制代码

UIView 相关

通过UIView获取父UIViewController

  1. extension UIView {
  2. var parentViewController: UIViewController? {
  3. var parentResponder: UIResponder? = self
  4. while parentResponder != nil {
  5. parentResponder = parentResponder!.next
  6. if let viewController = parentResponder as? UIViewController {
  7. return viewController
  8. }
  9. }
  10. return nil
  11. }
  12. }
  13. 复制代码

String 相关

html的字符串,将代码转成对应效果

  1. extension String {
  2. var htmlToAttributedString: NSAttributedString? {
  3. guard let data = data(using: .utf8) else { return NSAttributedString() }
  4. do {
  5. return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
  6. } catch {
  7. return NSAttributedString()
  8. }
  9. }
  10. var htmlToString: String {
  11. return htmlToAttributedString?.string ?? ""
  12. }
  13. }
  14. 复制代码

正则表达式匹配

  1. /// 正则表达式匹配
  2. extension String {
  3. func matchingStrings(regex: String) -> [String] {
  4. do {
  5. let regex = try NSRegularExpression(pattern: regex)
  6. let results = regex.matches(in: self,
  7. range: NSRange(self.startIndex..., in: self))
  8. return results.map {
  9. String(self[Range($0.range, in: self)!])
  10. }
  11. } catch let error {
  12. print("invalid regex: \(error.localizedDescription)")
  13. return []
  14. }
  15. }
  16. }
  17. 复制代码

Data拼接数据

  1. extension Data {
  2. mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
  3. if let data = string.data(using: encoding) {
  4. append(data)
  5. }
  6. }
  7. }
  8. 复制代码

打乱数组顺序

  1. extension Array{
  2. mutating func randamArray() {
  3. var list = self
  4. for index in 0..<list.count {
  5. let newIndex = Int(arc4random_uniform(UInt32(list.count-index))) + index
  6. if index != newIndex {
  7. list.swapAt(index, newIndex)
  8. }
  9. }
  10. self = list
  11. }
  12. }
  13. 复制代码

UIImage相关

高斯模糊图片

  1. extension UIImage {
  2. func blurred(radius: CGFloat) -> UIImage {
  3. let ciContext = CIContext(options: nil)
  4. guard let cgImage = cgImage else { return self }
  5. let inputImage = CIImage(cgImage: cgImage)
  6. guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
  7. ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
  8. ciFilter.setValue(radius, forKey: "inputRadius")
  9. guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
  10. guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
  11. return UIImage(cgImage: cgImage2)
  12. }
  13. }
  14. 复制代码

两张图片叠加成一张图片

  1. extension UIImage {
  2. func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
  3. let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
  4. let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
  5. let newSize = CGSize(width: newWidth, height: newHeight)
  6. UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
  7. draw(in: CGRect(origin: CGPoint.zero, size: size))
  8. image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
  9. let newImage = UIGraphicsGetImageFromCurrentImageContext()!
  10. UIGraphicsEndImageContext()
  11. return newImage
  12. }
  13. }
  14. 复制代码

缩放图片

  1. extension UIImage {
  2. func scaled(withSize size: CGSize) -> UIImage {
  3. UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
  4. defer { UIGraphicsEndImageContext() }
  5. draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
  6. return UIGraphicsGetImageFromCurrentImageContext()!
  7. }
  8. }
  9. 复制代码

Json相关

Json编码

  1. extension JSONEncoder {
  2. /// 将实体类转换成Json数据
  3. func toJson<T: Encodable>(_ entity: T) -> String? {
  4. guard let encodedData = try? encode(entity) else {
  5. return nil
  6. }
  7. return String(data: encodedData, encoding: .utf8)
  8. }
  9. }
  10. 复制代码

Json解码

  1. extension JSONDecoder {
  2. func from<T: Decodable>(_ type: T.Type, json: String) -> T? {
  3. do {
  4. return try decode(type, from: json.data(using: .utf8)!)
  5. }
  6. catch {
  7. return nil
  8. }
  9. }
  10. }
  11. 复制代码

请求字段编码为字符串,形式如:key=value&key=value&key=value

  1. extension Dictionary {
  2. func percentEscaped() -> String {
  3. return map { (key, value) in
  4. let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
  5. let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
  6. return escapedKey + "=" + escapedValue
  7. }
  8. .joined(separator: "&")
  9. }
  10. }
  11. extension CharacterSet {
  12. static let urlQueryValueAllowed: CharacterSet = {
  13. let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
  14. let subDelimitersToEncode = "!$&'()*+,;="
  15. var allowed = CharacterSet.urlQueryAllowed
  16. allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
  17. return allowed
  18. }()
  19. }
  20. 复制代码

UIViewController 相关

添加子UIViewController

  1. extension UIViewController {
  2. /// 添加子ViewController
  3. func addSubController(child: UIViewController, to: UIView? = nil) {
  4. addChildViewController(child)
  5. if let to = to {
  6. child.view.frame = to.frame
  7. to.addSubview(child.view)
  8. }
  9. else {
  10. child.view.frame = view.frame
  11. view.addSubview(child.view)
  12. }
  13. child.didMove(toParentViewController: self)
  14. }
  15. }
  16. 复制代码

移除子UIViewController

  1. extension UIViewController {
  2. /// 移除子ViewController
  3. func removeSubController(child: UIViewController) {
  4. child.willMove(toParentViewController: nil)
  5. child.removeFromParentViewController()
  6. child.view.removeFromSuperview()
  7. }
  8. }
  9. 复制代码

关闭页面

关闭当前页面

  1. extension UIViewController {
  2. /// 关闭当前页面
  3. func closePage() {
  4. self.dismiss(animated: true, completion: nil)
  5. }
  6. }
  7. 复制代码

关闭所有页面,除开最下级的那个页面

  1. extension UIViewController {
  2. func closeAllPage() {
  3. //获取根VC
  4. var rootVC = self.presentingViewController
  5. while let parent = rootVC?.presentingViewController {
  6. rootVC = parent
  7. }
  8. //释放所有下级视图
  9. rootVC?.dismiss(animated: true, completion: nil)
  10. }
  11. }
  12. 复制代码

显示和关闭菊花等待加载

  1. extension UIViewController {
  2. class func displaySpinner(onView : UIView) -> UIView {
  3. let spinnerView = UIView.init(frame: onView.bounds)
  4. spinnerView.backgroundColor = UIColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5)
  5. let ai = UIActivityIndicatorView.init(activityIndicatorStyle: .whiteLarge)
  6. ai.startAnimating()
  7. ai.center = spinnerView.center
  8. DispatchQueue.main.async {
  9. spinnerView.addSubview(ai)
  10. onView.addSubview(spinnerView)
  11. }
  12. return spinnerView
  13. }
  14. class func removeSpinner(spinner :UIView) {
  15. DispatchQueue.main.async {
  16. spinner.removeFromSuperview()
  17. }
  18. }
  19. }
  20. 复制代码

显示

  1. let sp = UIViewController.displaySpinner(onView: self.view)
  2. 复制代码

关闭

  1. UIViewController.removeSpinner(spinner: sp)
  2. 复制代码

IAP 内购

使用

  1. 除代码外的内购准备工序已OK
  2. 获取产品数据:通过IAPHelper.shared.fetchAvailableProducts从苹果服务器获取所有传入的产品id的产品信息,传入的参数是产品的id字符串数组
  3. 支付:IAPHelper.shared.purchase(id: id),id是产品id

    IAPHelper.shared.purchase(id: selectItem!.product_id) {alert, product, transaction in
    if alert == .purchased { //购买成功

    1. if let receiptUrl = Bundle.main.appStoreReceiptURL, let receiptData = NSData(contentsOf: receiptUrl) {
    2. let receiptString = receiptData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    3. // 对receiptString加密字符串进行验证
    4. }

    }
    else if alert == .restored {

    }
    else if alert == .purchasing {

    }
    else {

    }
    }
    复制代码

IAPHelper 代码

  1. import StoreKit
  2. enum IAPHelperAlertType{
  3. case disabled
  4. case restored
  5. case purchased
  6. case purchasing
  7. case setProductIds
  8. func message() -> String{
  9. switch self {
  10. case .setProductIds: return "未设置产品id,请调用 fetchAvailableProducts()"
  11. case .disabled: return "购买已取消"
  12. case .restored: return "您已成功恢复购买"
  13. case .purchased: return "您已成功购买此商品"
  14. case .purchasing: return "正在购买..."
  15. }
  16. }
  17. }
  18. class IAPHelper: NSObject {
  19. static let shared = IAPHelper()
  20. private override init() { }
  21. fileprivate var productID = ""
  22. fileprivate var productsRequest = SKProductsRequest()
  23. fileprivate var productDict = [String:SKProduct]()
  24. fileprivate var fetchProductCompletion: (([SKProduct])->Void)?
  25. fileprivate var productToPurchase: SKProduct?
  26. var purchaseProductCompletion: ((IAPHelperAlertType, SKProduct?, SKPaymentTransaction?) -> Void)?
  27. // MARK: - 购买产品
  28. func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() }
  29. func purchase(id: String, completion: @escaping ((IAPHelperAlertType, SKProduct?, SKPaymentTransaction?)->Void)) {
  30. self.purchaseProductCompletion = completion
  31. self.productToPurchase = productDict[id]
  32. guard let product = self.productToPurchase else {
  33. print(IAPHelperAlertType.setProductIds.message())
  34. fatalError(IAPHelperAlertType.setProductIds.message())
  35. }
  36. if self.canMakePurchases() {
  37. let payment = SKPayment(product: product)
  38. SKPaymentQueue.default().add(self)
  39. SKPaymentQueue.default().add(payment)
  40. print("采购产品: \(product.productIdentifier)")
  41. productID = product.productIdentifier
  42. }
  43. else {
  44. completion(.disabled, nil, nil)
  45. }
  46. }
  47. // MARK: - 恢复购买
  48. func restorePurchase(){
  49. SKPaymentQueue.default().add(self)
  50. SKPaymentQueue.default().restoreCompletedTransactions()
  51. }
  52. // MARK: - 获取可用的iap产品
  53. func fetchAvailableProducts(by ids: [String], completion: @escaping (([SKProduct])->Void)){
  54. self.fetchProductCompletion = completion
  55. // 把您的IAP产品id放到这里面
  56. guard !ids.isEmpty else {
  57. print("没有设置产品id")
  58. fatalError(IAPHelperAlertType.setProductIds.message())
  59. }
  60. productsRequest = SKProductsRequest(productIdentifiers: Set(ids))
  61. productsRequest.delegate = self
  62. productsRequest.start()
  63. }
  64. }
  65. extension IAPHelper: SKProductsRequestDelegate, SKPaymentTransactionObserver{
  66. // MARK: - 请求IAP产品
  67. func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
  68. if (response.products.count > 0) {
  69. for product in response.products {
  70. print("product.productIdentifier = \(product.productIdentifier)")
  71. self.productDict[product.productIdentifier] = product
  72. }
  73. self.fetchProductCompletion?(response.products)
  74. }
  75. }
  76. func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
  77. self.purchaseProductCompletion?(.restored, nil, nil)
  78. }
  79. // MARK:- IAP付款队列
  80. func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
  81. print("调用了几次啊!!!")
  82. for transaction:AnyObject in transactions {
  83. if let trans = transaction as? SKPaymentTransaction {
  84. switch trans.transactionState {
  85. case .purchased:
  86. print("产品已购买")
  87. SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
  88. self.purchaseProductCompletion?(.purchased, self.productToPurchase, trans)
  89. break
  90. case .failed:
  91. print("产品购买失败\(trans.error.debugDescription)")
  92. SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
  93. self.purchaseProductCompletion?(.disabled, self.productToPurchase, trans)
  94. break
  95. case .purchasing:
  96. print("正在购买...")
  97. self.purchaseProductCompletion?(.purchasing, self.productToPurchase, trans)
  98. break
  99. case .restored:
  100. print("产品已恢复购买")
  101. SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
  102. self.purchaseProductCompletion?(.restored, self.productToPurchase, trans)
  103. break
  104. default: break
  105. }
  106. }
  107. }
  108. }
  109. }
  110. 复制代码

转载于:https://juejin.im/post/5c90f6adf265da610a56e43b

发表评论

表情:
评论列表 (有 0 条评论,400人围观)

还没有评论,来说两句吧...

相关阅读