iOS積累的零碎經常使用操做swift

記錄一些iOS學習過程當中的筆記html

iOS開發-零碎筆記

建立項目目錄結構

  1. AppDelegate.swift:生命週期及變量的定義
  2. ViewController.swift: MVC的C
  3. Assets.xcasset:放資源文件,如圖片等
  4. info.plist:配置文件
  5. xxxTest: 單元測試
  6. Products:生成的文件
  7. Main.storyboard: 視圖

快捷添加註釋

option + command + /
複製代碼

關閉軟鍵盤

關閉代碼正則表達式

textField.resignFirstResponder()
複製代碼

關閉方式1: 在Controller中重寫touchesEnded()方法,而後在這裏面關閉軟件盤,意思是點擊空白處關閉json

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    name.resignFirstResponder()
}
複製代碼

關閉方式2: 點擊下一步時,關閉軟鍵盤; Controller實現UITextFieldDelegate協議; 實現UITextFieldDelegate協議中的textFieldShouldReturn方法;swift

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}
複製代碼

UIDatePicker選擇時間後計算年齡

func calAge(by datePicker: UIDatePicker) -> Int? {
    let gregorian = NSCalendar(calendarIdentifier: .gregorian)
    let now = Date()
    let components = gregorian?.components(NSCalendar.Unit.year, from: datePicker.date, to: now, options: NSCalendar.Options.init(rawValue: 0))
    return components?.year
}
複製代碼

頁面跳轉,傳遞數據

有兩個Controller:ViewController和GalleryViewController。從ViewController跳轉到GalleryViewController。 ViewController重寫方法:prepare,該方法在頁面跳轉時會被調用,咱們須要在裏面判斷是跳轉到哪一個頁面。api

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // 須要給Segue取名
        if segue.identifier == "GoToGallery" {
            let index = beautyPicker.selectedRow(inComponent: 0)
            var imageName: String?
            switch index {
            case 0:
                imageName = "fangbingbing"
            case 1:
                imageName = "libingbing"
            case 2:
                imageName = "wangfei"
            case 3:
                imageName = "yangmi"
            case 4:
                imageName = "zhouxu"
            default:
                imageName = nil
            }

            // 獲得下一個頁面的Controller
            let vc = segue.destination as! GalleryViewController
            vc.imageName = imageName
        }
    }
複製代碼

經過圖片文件名設置圖片

beautyImage.image = UIImage(named: imageName)
複製代碼

unwind segue關閉頁面

關閉頁面後,Controller能夠得到上個頁面傳回來的值 該方法寫在前一個頁面數組

@IBAction func closedPrePage(segue: UIStoryboardSegue) {
    print("closed")
}
複製代碼

TableView下移一個狀態欄的高度解決

  1. 方法一
if #available(iOS 11.0, *) {
    tableView.contentInsetAdjustmentBehavior = .never
}
複製代碼
  1. 方法二,內容上部分區域向上偏移一個狀態欄的高度
collectionView?.contentInset.top = -UIApplication.shared.statusBarFrame.height
複製代碼

TableView 添加刷新

let refreshControl = UIRefreshControl()

// 初始化刷新
refreshControl.backgroundColor = UIColor.blue //設置刷新的背景顏色
refreshControl.attributedTitle = NSAttributedString(string: "刷新一下:\(Data())", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white]) // 設置字體顏色
refreshControl.tintColor = UIColor.green // 加載菊花顏色
refreshControl.tintAdjustmentMode = .dimmed // 色彩調整模式
refreshControl.addTarget(self, action: #selector(addcount), for: .valueChanged) //添加方法目標

// 添加該刷新
tableView.refreshControl = refreshControl
複製代碼

刷新方法緩存

@objc func addcount() {
    dataArrary.append(contentsOf: dataArrary)
    tableView.reloadData()
    refreshControl.endRefreshing()
}
複製代碼

向項目添加字體

developer.apple.com/documentati…服務器

因爲iOS的用的字體名稱並非文件名稱,而是字體自己名稱。 下面代碼搜索全部字體,而後咱們在控制檯,找到多出來的名稱。app

for family: String in UIFont.familyNames
{
    print("\(family)")
    for names: String in UIFont.fontNames(forFamilyName: family)
    {
        print("== \(names)")
    }
}
複製代碼

設置tabbar 字體和字體大小

override func viewDidLoad() {
    super.viewDidLoad()
    let appearance = UITabBarItem.appearance()
    appearance.setTitleTextAttributes([NSAttributedStringKey.font: UIFont(name: "Ubuntu-Light", size: 9)!], for: .normal)
}
複製代碼

UIButton 相關

UIButton.isEnabled = false後圖片按鈕的背景圖片被改變

UIButton.adjustsImageWhenDisabled = false
複製代碼

擴展添加圓角、邊框、邊框顏色

@IBDesignable extension UIButton {

    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
        }
        get {
            return layer.cornerRadius
        }
    }

    @IBInspectable var borderColor: UIColor? {
        set {
            guard let uiColor = newValue else { return }
            layer.borderColor = uiColor.cgColor
        }
        get {
            guard let color = layer.borderColor else { return nil }
            return UIColor(cgColor: color)
        }
    }
}
複製代碼

擴展圖片在上,文字在下

extension UIButton {
    func alignVertical(spacing: CGFloat = 6.0, imageBottom: CGFloat = 0.0) {
        guard let imageSize = self.imageView?.image?.size,
            let text = self.titleLabel?.text,
            let font = self.titleLabel?.font
            else { return }
        self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
        let labelString = NSString(string: text)
        let titleSize = labelString.size(withAttributes: [NSAttributedStringKey.font: font])
        self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: imageBottom, right: -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
    }
}
複製代碼

UITableView或UICollectionView被TabBar遮蓋

UITableView調用reloadData致使移動到列表頂部失效

UIView.animate(withDuration: 0, animations: {
    self.tableView.contentOffset = CGPoint.zero
}, completion: { _ in
    self.tableView.reloadData()
})
複製代碼

NavigationBar致使CollectionViewCell或TableViewCell偏移

self.collectionView?.contentInsetAdjustmentBehavior = .automatic
複製代碼

獲取app版本

/// 獲取版本名
let appVersion = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String

/// 獲取版本號
let versionNumber = Bundle.main.infoDictionary!["CFBundleVersion"] as? String
複製代碼

清理緩存

func clearCache() {

     // 取出cache文件夾目錄 緩存文件都在這個目錄下
     let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first

     // 取出文件夾下全部文件數組
     let fileArr = FileManager.default.subpaths(atPath: cachePath!)

     // 遍歷刪除
     for file in fileArr! {

         let path = cachePath?.appendingFormat("/\(file)")
         if FileManager.default.fileExists(atPath: path!) {

             do {
                 try FileManager.default.removeItem(atPath: path!)
             } catch {

             }
         }
     }
 }
複製代碼

打開網頁本軟件的appstore

// App Store URL.
let appStoreLink = "https://itunes.apple.com/cn/app/id1144351773?mt=8"

/* First create a URL, then check whether there is an installed app that can open it on the device. */
if let url = URL(string: appStoreLink), UIApplication.shared.canOpenURL(url) {
    // Attempt to open the URL.
    UIApplication.shared.open(url, options: [:], completionHandler: {(success: Bool) in
        if success {
            print("Launching \(url) was successful")
        }})
}
複製代碼

設置圓形展現圖像

  1. 設置UIImageView寬度和高度,假如設置爲60*60
  2. 設置運行時屬性,設置圓弧爲30(正方形邊長度一半)
  3. 勾選Clip to Bounds

UIScrollView填充到頂部(去掉狀態欄到空白間距)

  1. Content Insets 選擇Never
  2. 去掉選中的Safe Area Relative Margins

UIImage 高斯模糊擴展

extension UIImage {
    func blurred(radius: CGFloat) -> UIImage {
        let ciContext = CIContext(options: nil)
        guard let cgImage = cgImage else { return self }
        let inputImage = CIImage(cgImage: cgImage)
        guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
        ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
        ciFilter.setValue(radius, forKey: "inputRadius")
        guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
        guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
        return UIImage(cgImage: cgImage2)
    }
}
複製代碼

兩個UIImage 合併擴展

extension UIImage {

  func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
    let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
    let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
    let newSize = CGSize(width: newWidth, height: newHeight)

    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
    draw(in: CGRect(origin: CGPoint.zero, size: size))
    image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    return newImage
  }

}
複製代碼

SDWebImageView 下載圖片

  1. 方式一
img.sd_setImage(with: URL(string: "http://url"),
  placeholderImage: #imageLiteral(resourceName: "default_square")) { image, error, cacheType, url in

}
複製代碼
  1. 方式二
SDWebImageDownloader
  .shared()
  .downloadImage(with: URL(string: "http://url"),
    options: SDWebImageDownloaderOptions.init(rawValue: 0),
    progress: nil,
    completed: { image, data, error, finished in
    if finished {

    }
})
複製代碼

AVPlayerViewController 視頻播放

import AVKit
func playVideoByUrl(string: String) {
    let videoURL = URL(string: string)
    let player = AVPlayer(url: videoURL!)
    let playerViewController = AVPlayerViewController()
    playerViewController.player = player
    self.present(playerViewController, animated: true) {
        playerViewController.player!.play()
    }
}
複製代碼

爲UIImageView添加的點擊手勢無效

  1. 勾選上User Interaction Enabled
  2. 代碼中設置uiimageview.userInteractionEnabled = true

PHAsset獲取文件路徑

extension PHAsset {

    func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
        if self.mediaType == .image {
            let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
            options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
                return true
            }
            self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
                completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
            })
        } else if self.mediaType == .video {
            let options: PHVideoRequestOptions = PHVideoRequestOptions()
            options.version = .original
            PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
                if let urlAsset = asset as? AVURLAsset {
                    let localVideoUrl: URL = urlAsset.url as URL
                    completionHandler(localVideoUrl)
                } else {
                    completionHandler(nil)
                }
            })
        }
    }
}
複製代碼

UIView 相關

經過UIView獲取父UIViewController

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}
複製代碼

String 相關

html的字符串,將代碼轉成對應效果

extension String {
    var htmlToAttributedString: NSAttributedString? {
        guard let data = data(using: .utf8) else { return NSAttributedString() }
        do {
            return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
        } catch {
            return NSAttributedString()
        }
    }
    var htmlToString: String {
        return htmlToAttributedString?.string ?? ""
    }
}
複製代碼

正則表達式匹配

/// 正則表達式匹配
extension String {
    func matchingStrings(regex: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex)
            let results = regex.matches(in: self,
                                        range: NSRange(self.startIndex..., in: self))
            return results.map {
                String(self[Range($0.range, in: self)!])
            }
        } catch let error {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
}
複製代碼

Data拼接數據

extension Data {
    mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
        if let data = string.data(using: encoding) {
            append(data)
        }
    }
}
複製代碼

打亂數組順序

extension Array{
    mutating func randamArray() {
        var list = self
        for index in 0..<list.count {
            let newIndex = Int(arc4random_uniform(UInt32(list.count-index))) + index
            if index != newIndex {
                list.swapAt(index, newIndex)
            }
        }
        self = list
    }
}
複製代碼

UIImage相關

高斯模糊圖片

extension UIImage {
    func blurred(radius: CGFloat) -> UIImage {
        let ciContext = CIContext(options: nil)
        guard let cgImage = cgImage else { return self }
        let inputImage = CIImage(cgImage: cgImage)
        guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
        ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
        ciFilter.setValue(radius, forKey: "inputRadius")
        guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
        guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
        return UIImage(cgImage: cgImage2)
    }
}
複製代碼

兩張圖片疊加成一張圖片

extension UIImage {

    func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
        let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
        let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
        let newSize = CGSize(width: newWidth, height: newHeight)

        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        draw(in: CGRect(origin: CGPoint.zero, size: size))
        image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return newImage
    }

}
複製代碼

縮放圖片

extension UIImage {

    func scaled(withSize size: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
        return UIGraphicsGetImageFromCurrentImageContext()!
    }

}
複製代碼

Json相關

Json編碼

extension JSONEncoder {

    /// 將實體類轉換成Json數據
    func toJson<T: Encodable>(_ entity: T) -> String? {
        guard let encodedData = try? encode(entity) else {
            return nil
        }
        return String(data: encodedData, encoding: .utf8)
    }
}
複製代碼

Json解碼

extension JSONDecoder {
    func from<T: Decodable>(_ type: T.Type, json: String) -> T? {
        do {
            return try decode(type, from: json.data(using: .utf8)!)
        }
        catch {
            return nil
        }
    }
}
複製代碼

請求字段編碼爲字符串,形式如:key=value&key=value&key=value

extension Dictionary {
    func percentEscaped() -> String {
        return map { (key, value) in
            let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
            let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
            return escapedKey + "=" + escapedValue
            }
            .joined(separator: "&")
    }
}

extension CharacterSet {
    static let urlQueryValueAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="

        var allowed = CharacterSet.urlQueryAllowed
        allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
        return allowed
    }()
}
複製代碼

UIViewController 相關

添加子UIViewController

extension UIViewController {

    /// 添加子ViewController
    func addSubController(child: UIViewController, to: UIView? = nil) {
        addChildViewController(child)
        if let to = to {
            child.view.frame = to.frame
            to.addSubview(child.view)
        }
        else {
            child.view.frame = view.frame
            view.addSubview(child.view)
        }
        child.didMove(toParentViewController: self)
    }
}
複製代碼

移除子UIViewController

extension UIViewController {
    /// 移除子ViewController
    func removeSubController(child: UIViewController) {
        child.willMove(toParentViewController: nil)
        child.removeFromParentViewController()
        child.view.removeFromSuperview()
    }
}
複製代碼

關閉頁面

關閉當前頁面

extension UIViewController {
    /// 關閉當前頁面
    func closePage() {
        self.dismiss(animated: true, completion: nil)
    }
}
複製代碼

關閉全部頁面,除開最下級的那個頁面

extension UIViewController {
    func closeAllPage() {
        //獲取根VC
        var rootVC = self.presentingViewController
        while let parent = rootVC?.presentingViewController {
            rootVC = parent
        }
        //釋放全部下級視圖
        rootVC?.dismiss(animated: true, completion: nil)
    }
}
複製代碼

顯示和關閉菊花等待加載

extension UIViewController {
    class func displaySpinner(onView : UIView) -> UIView {
        let spinnerView = UIView.init(frame: onView.bounds)
        spinnerView.backgroundColor = UIColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5)
        let ai = UIActivityIndicatorView.init(activityIndicatorStyle: .whiteLarge)
        ai.startAnimating()
        ai.center = spinnerView.center

        DispatchQueue.main.async {
            spinnerView.addSubview(ai)
            onView.addSubview(spinnerView)
        }

        return spinnerView
    }

    class func removeSpinner(spinner :UIView) {
        DispatchQueue.main.async {
            spinner.removeFromSuperview()
        }
    }
}
複製代碼

顯示dom

let sp = UIViewController.displaySpinner(onView: self.view)
複製代碼

關閉

UIViewController.removeSpinner(spinner: sp)
複製代碼

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 { //購買成功
      if let receiptUrl = Bundle.main.appStoreReceiptURL, let receiptData = NSData(contentsOf: receiptUrl) {
          let receiptString = receiptData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
          // 對receiptString加密字符串進行驗證
      }
  }
  else if alert == .restored {

  }
  else if alert == .purchasing {

  }
  else {

  }
}
複製代碼

IAPHelper 代碼

import StoreKit

enum IAPHelperAlertType{
    case disabled
    case restored
    case purchased
    case purchasing
    case setProductIds

    func message() -> String{
        switch self {
        case .setProductIds: return "未設置產品id,請調用 fetchAvailableProducts()"
        case .disabled: return "購買已取消"
        case .restored: return "您已成功恢復購買"
        case .purchased: return "您已成功購買此商品"
        case .purchasing: return "正在購買..."
        }
    }
}


class IAPHelper: NSObject {
    static let shared = IAPHelper()

    private override init() { }

    fileprivate var productID = ""
    fileprivate var productsRequest = SKProductsRequest()
    fileprivate var productDict = [String:SKProduct]()
    fileprivate var fetchProductCompletion: (([SKProduct])->Void)?

    fileprivate var productToPurchase: SKProduct?
    var purchaseProductCompletion: ((IAPHelperAlertType, SKProduct?, SKPaymentTransaction?) -> Void)?

    // MARK: - 購買產品
    func canMakePurchases() -> Bool {  return SKPaymentQueue.canMakePayments()  }

    func purchase(id: String, completion: @escaping ((IAPHelperAlertType, SKProduct?, SKPaymentTransaction?)->Void)) {
        self.purchaseProductCompletion = completion
        self.productToPurchase = productDict[id]

        guard let product = self.productToPurchase else {
            print(IAPHelperAlertType.setProductIds.message())
            fatalError(IAPHelperAlertType.setProductIds.message())
        }

        if self.canMakePurchases() {
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().add(payment)

            print("採購產品: \(product.productIdentifier)")
            productID = product.productIdentifier
        }
        else {
            completion(.disabled, nil, nil)
        }
    }

    // MARK: - 恢復購買
    func restorePurchase(){
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()
    }

    // MARK: - 獲取可用的iap產品
    func fetchAvailableProducts(by ids: [String], completion: @escaping (([SKProduct])->Void)){
        self.fetchProductCompletion = completion
        // 把您的IAP產品id放到這裏面

        guard !ids.isEmpty else {
            print("沒有設置產品id")
            fatalError(IAPHelperAlertType.setProductIds.message())
        }

        productsRequest = SKProductsRequest(productIdentifiers: Set(ids))
        productsRequest.delegate = self
        productsRequest.start()
    }

}

extension IAPHelper: SKProductsRequestDelegate, SKPaymentTransactionObserver{
    // MARK: - 請求IAP產品
    func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {

        if (response.products.count > 0) {
            for product in response.products {
                print("product.productIdentifier = \(product.productIdentifier)")
                self.productDict[product.productIdentifier] = product
            }
            self.fetchProductCompletion?(response.products)
        }
    }

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        self.purchaseProductCompletion?(.restored, nil, nil)
    }

    // MARK:- IAP付款隊列
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        print("調用了幾回啊!!!")
        for transaction:AnyObject in transactions {
            if let trans = transaction as? SKPaymentTransaction {
                switch trans.transactionState {
                case .purchased:
                    print("產品已購買")
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    self.purchaseProductCompletion?(.purchased, self.productToPurchase, trans)
                    break

                case .failed:
                    print("產品購買失敗\(trans.error.debugDescription)")
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    self.purchaseProductCompletion?(.disabled, self.productToPurchase, trans)
                    break
                case .purchasing:
                    print("正在購買...")
                    self.purchaseProductCompletion?(.purchasing, self.productToPurchase, trans)
                    break
                case .restored:
                    print("產品已恢復購買")
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    self.purchaseProductCompletion?(.restored, self.productToPurchase, trans)
                    break

                default: break
                }
            }
        }
    }
}
複製代碼
相關文章
相關標籤/搜索