func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
hideActivity()
let products = response.products
if products.count > 0{
let controller = HAPurchaseViewController.instantiate() // crashes here
controller.categories = dataManager.paidCategories()
controller.products = products
self.navigationController?.pushViewController(controller, animated: true)
}
else{
DispatchQueue.main.async { [weak self] in
let alertController = UIAlertController(title: "Oops!", message: "Unable to load or products not found, please try again later", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default)
alertController.addAction(okAction)
self?.present(alertController, animated: true)
}
}
}
此扩展程序适用于其他任何地方,除非我使用它加载我的应用内购买视图控制器。
import Foundation
import UIKit
protocol Storyboarded {
static func instantiate() -> Self
}
extension Storyboarded where Self: UIViewController {
static func instantiate() -> Self {
let id = String(describing: self)
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
if #available(iOS 13.0, *) {
return storyboard.instantiateViewController(identifier: id) as! Self // App crash here when loading storyboard
} else {
return storyboard.instantiateViewController(withIdentifier: id) as! Self
}
}
static func value() -> Self {
return UIViewController() as! Self
}
}
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIViewController initWithCoder:] > PID: 13525, TID: 4347723, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0
Backtrace:
根据SO的建议,我更新了代码
extension Storyboarded where Self: UIViewController {
static func instantiate() -> Self {
DispatchQueue.main.async {
let id = String(describing: self)
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
if #available(iOS 13.0, *) {
return storyboard.instantiateViewController(identifier: id) as! Self
} else {
return storyboard.instantiateViewController(withIdentifier: id) as! Self
}
}
}
static func value() -> Self {
return UIViewController() as! Self
}
}
答案 0 :(得分:1)
问题出在这里:
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
// ... this is a background thread!
}
所以此时你不能做任何涉及接口的事情,而不进入主线程。您实际上已经在第二部分这样做了:
hideActivity()
let products = response.products
if products.count > 0{
let controller = HAPurchaseViewController.instantiate()
controller.categories = dataManager.paidCategories()
controller.products = products
self.navigationController?.pushViewController(controller, animated: true)
}
else{
// LOOK! You are already doing it here
DispatchQueue.main.async { [weak self] in
let alertController = UIAlertController(title: "Oops!", message: "Unable to load or products not found, please try again later", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default)
alertController.addAction(okAction)
self?.present(alertController, animated: true)
}
}
嗯?所以在第一部分做同样的事情!
hideActivity()
let products = response.products
if products.count > 0{
DispatchQueue.main.async { [weak self] in
let controller = HAPurchaseViewController.instantiate()
controller.categories = dataManager.paidCategories()
controller.products = products
self?.navigationController?.pushViewController(controller, animated: true)
}
} else {
DispatchQueue.main.async { [weak self] in
let alertController = UIAlertController(title: "Oops!", message: "Unable to load or products not found, please try again later", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default)
alertController.addAction(okAction)
self?.present(alertController, animated: true)
}
}