Commit 784f2c41 authored by yqz's avatar yqz

分享、评论和内购

parent b7289b40
......@@ -10,6 +10,7 @@
0496DEF32D9E3F58005B2834 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915D2D9D68AD00055CEB /* WidgetKit.framework */; };
0496DEF42D9E3F58005B2834 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915F2D9D68AD00055CEB /* SwiftUI.framework */; };
0496DEFF2D9E3F59005B2834 /* widgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0496DEF22D9E3F57005B2834 /* widgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
04E961E02DA379C400632F13 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04E961DF2DA379C400632F13 /* StoreKit.framework */; };
3A00E856852A8783E544CD7D /* Pods_PhoneManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6028F60B696E2F97EAA2325C /* Pods_PhoneManager.framework */; };
/* End PBXBuildFile section */
......@@ -42,6 +43,7 @@
0496DF042D9E3FA7005B2834 /* widgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = widgetExtension.entitlements; sourceTree = "<group>"; };
04BD915D2D9D68AD00055CEB /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
04BD915F2D9D68AD00055CEB /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
04E961DF2DA379C400632F13 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
295785B9009F20AC4C1C36C4 /* Pods-PhoneManager.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PhoneManager.debug.xcconfig"; path = "Target Support Files/Pods-PhoneManager/Pods-PhoneManager.debug.xcconfig"; sourceTree = "<group>"; };
6028F60B696E2F97EAA2325C /* Pods_PhoneManager.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PhoneManager.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8937DC9D81CEDE823C329A80 /* Pods-PhoneManager.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PhoneManager.release.xcconfig"; path = "Target Support Files/Pods-PhoneManager/Pods-PhoneManager.release.xcconfig"; sourceTree = "<group>"; };
......@@ -99,6 +101,7 @@
buildActionMask = 2147483647;
files = (
3A00E856852A8783E544CD7D /* Pods_PhoneManager.framework in Frameworks */,
04E961E02DA379C400632F13 /* StoreKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -108,6 +111,7 @@
27ECDADD9059AB5043B8E1E9 /* Frameworks */ = {
isa = PBXGroup;
children = (
04E961DF2DA379C400632F13 /* StoreKit.framework */,
6028F60B696E2F97EAA2325C /* Pods_PhoneManager.framework */,
04BD915D2D9D68AD00055CEB /* WidgetKit.framework */,
04BD915F2D9D68AD00055CEB /* SwiftUI.framework */,
......@@ -349,7 +353,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager.bswidget;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_widget_dev;
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_widget_dev1;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
......@@ -384,7 +388,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager.bswidget;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_widget_dev;
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_widget_dev1;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
......@@ -426,7 +430,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_dev1;
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_dev2;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "PhoneManager/Class/Tool/Class/OC/PhoneManager-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
......@@ -469,7 +473,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_dev1;
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_dev2;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "PhoneManager/Class/Tool/Class/OC/PhoneManager-Bridging-Header.h";
SWIFT_VERSION = 5.0;
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_idsp_unlock.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_idsp_unlock@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_idsp_unlock@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_naal_unlock.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_naal_unlock@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_naal_unlock@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_sbst_unlock.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_sbst_unlock@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_sbst_unlock@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -129,13 +129,14 @@ class HomeViewController:BaseViewController {
}else {
let vc:HomePayViewController = HomePayViewController()
HomeNoAdsViewController.show()
let nav:BaseNavViewController = BaseNavViewController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
self.navigationController?.present(nav, animated: true)
// if HomePayModel.share.isNoAd == false {
// let vc:HomePayViewController = HomePayViewController()
// let nav:BaseNavViewController = BaseNavViewController(rootViewController: vc)
// nav.modalPresentationStyle = .fullScreen
// self.navigationController?.present(nav, animated: true)
// }
}
}
}
......
//
// HomeNoAdsViewController.swift
// PhoneManager
//
// Created by edy on 2025/4/7.
//
import UIKit
class HomeNoAdsViewController: UIViewController, NoAdsStackDataSource {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
// let s = UITableView()
// s.delegate = self;
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setUI()
}
private lazy var stack:NoAdsStackView = {
let s = NoAdsStackView(3)
view.addSubview(s)
s.dataSource = self
return s
}()
private lazy var stack1:NoAdsStackView = {
let s = NoAdsStackView(1)
view.addSubview(s)
s.dataSource = self
return s
}()
private lazy var NoAdTitle: UILabel = {
let no = UILabel()
no.text = "Unlock Unlimited Access"
no.font = UIFont.boldSystemFont(ofSize: 24)
no.textAlignment = .center
no.numberOfLines = 0
no.textColor = .black
view.addSubview(no)
return no
}()
private lazy var closeBtn: UIButton = {
let close = UIButton(type: .custom)
close.setImage(UIImage(named: "home_pay_close"), for: .normal)
view.addSubview(close)
close.addTarget(self, action: #selector(closeTouch), for: .touchUpInside)
return close
}()
private lazy var pageCtrol: UIPageControl = {
let page = UIPageControl()
page.currentPageIndicatorTintColor = .colorWithHex(hexStr: "#0082FF")
page.pageIndicatorTintColor = .colorWithHex(hexStr: "#C6CEE0")
page.numberOfPages = 1
view.addSubview(page)
return page
}()
private lazy var buybut: UIButton = {
let buy = UIButton(type: .custom)
buy.backgroundColor = UIColor.colorWithHex(hexStr: "#0082FF")
buy.setTitle("Start my 7-day free trial", for: .normal)
buy.layer.cornerRadius = 8
view.addSubview(buy)
return buy
}()
private lazy var bottomContentView: UIView = {
let content = UIView()
content.layer.cornerRadius = 12;
content.layer.borderColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
content.layer.borderWidth = 1
view.addSubview(content)
let t = UILabel()
t.text = "$6.99/week, cancel anytime"
t.font = UIFont.systemFont(ofSize: 14)
t.textColor = .black
content.addSubview(t)
let b = UILabel()
b.text = "7-day FREE TRIAL"
b.font = UIFont.systemFont(ofSize: 12)
b.textColor = .colorWithHex(hexStr: "#666666")
t.snp.makeConstraints { make in
make.bottom.equalTo(content.centerY).offset(-2)
make.left.equalToSuperview().offset(10)
}
b.snp.makeConstraints { make in
make.top.equalTo(content.centerY).offset(2)
make.left.equalToSuperview().offset(10)
}
content.addSubview(b)
return content
}()
private lazy var ppBtn:UIButton = {
let sview:UIButton = UIButton()
let content:String = "Terms"
let font = UIFont.systemFont(ofSize: 12.RW(), weight: .medium)
let color = UIColor.colorWithHex(hexStr: black6Color)
sview.setTitle(content, for: .normal)
sview.setTitleColor(color, for: .normal)
sview.titleLabel?.font = font
sview.sizeToFit()
let attributes: [NSAttributedString.Key: Any] = [
.font: font,
.foregroundColor: color,
.underlineStyle: NSUnderlineStyle.single.rawValue
]
let attributedString = NSAttributedString(string: content, attributes: attributes)
sview.setAttributedTitle(attributedString, for: .normal)
// sview.addTarget(self, action: #selector(), for: .touchUpInside)
sview.sizeToFit()
return sview
}()
private lazy var restoreBtn:UIButton = {
let sview:UIButton = UIButton()
let content:String = "Restore"
let font = UIFont.systemFont(ofSize: 12.RW(), weight: .medium)
let color = UIColor.colorWithHex(hexStr: black6Color)
sview.setTitle(content, for: .normal)
sview.setTitleColor(color, for: .normal)
sview.titleLabel?.font = font
sview.sizeToFit()
let attributes: [NSAttributedString.Key: Any] = [
.font: font,
.foregroundColor: color,
.underlineStyle: NSUnderlineStyle.single.rawValue
]
let attributedString = NSAttributedString(string: content, attributes: attributes)
sview.setAttributedTitle(attributedString, for: .normal)
// sview.addTarget(self, action: #selector(), for: .touchUpInside)
sview.sizeToFit()
return sview
}()
private let data:[[String:String]] = [
["icon":"ic_idsp_unlock","t":"Instantly Detect Similar Photos"],
["icon":"ic_naal_unlock","t":"No Ads and Limits"],
["icon":"ic_sbst_unlock","t":"Save Both Storage & Time"],
]
}
extension HomeNoAdsViewController {
func NoAdsStactChildView(_ content: NoAdsStackView, _ idx: Int) -> UIView {
if content == stack {
let stackview = UIStackView()
stackview.axis = .horizontal
stackview.spacing = 10
stackview.alignment = .center
stackview.distribution = .fillProportionally
let dict = data[idx]
let icon = UIImageView(image: UIImage(named: dict["icon"] ?? ""))
stackview.addArrangedSubview(icon)
icon.snp.makeConstraints { make in
make.height.equalTo(36)
make.width.equalTo(icon.snp.height)
}
let descp = UILabel()
descp.text = dict["t"]
descp.textColor = .black
descp.font = UIFont.boldSystemFont(ofSize: 16)
stackview.addArrangedSubview(descp)
return stackview
}else if content == stack1 {
let stackview = UIStackView()
stackview.axis = .vertical
stackview.spacing = 10
stackview.alignment = .center
stackview.distribution = .fillProportionally
let label = UILabel()
label.text = "“l have a few remaining photos to \"cleanse\". Othercategories gone with great ease. So much faster than lcould do one by one!\"\nLove me now"
label.textAlignment = .center
label.numberOfLines = 0
label.textColor = .colorWithHex(hexStr: "#333333")
label.font = UIFont.boldSystemFont(ofSize: 14)
stackview.addArrangedSubview(label)
return stackview
}else{
return UIView()
}
}
private func setUI() -> Void {
closeBtn.snp.makeConstraints { make in
make.left.top.equalTo(view).inset(UIEdgeInsets(top: 35, left: 13, bottom: 0, right: 0))
}
NoAdTitle.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(20)
make.top.equalTo(closeBtn.snp.bottom).offset(22)
}
stack.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(36)
make.top.equalTo(NoAdTitle.snp.bottom).offset(24)
}
stack1.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(36)
make.top.equalTo(stack.snp.bottom).offset(50)
}
pageCtrol.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(stack1.snp.bottom).offset(15)
}
bottomContentView.snp.makeConstraints { make in
make.left.right.equalTo(buybut)
make.bottom.equalTo(buybut.snp.top).offset(-10)
make.height.equalTo(69)
}
buybut.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(15)
make.bottom.equalTo(ppBtn.snp.top).offset(-20)
make.height.equalTo(46)
}
ppBtn.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-10)
make.left.equalToSuperview().offset(15)
}
restoreBtn.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-10)
make.right.equalToSuperview().offset(15)
}
self.loadViewIfNeeded()
bottomContentView.gradient(colors: [.colorWithHex(hexStr: "#FFFFFF") , .colorWithHex(hexStr: "#E3EDFC")])
}
@objc private func closeTouch() -> Void {
self.dismiss(animated: true)
}
class func show() -> Void {
let vc = HomeNoAdsViewController()
vc.modalTransitionStyle = .crossDissolve
vc.modalPresentationStyle = .overFullScreen
guard let root = cWindow?.rootViewController else { return }
root.present(vc, animated: true)
}
}
//
// NoAdsStackView.swift
// PhoneManager
//
// Created by edy on 2025/4/7.
//
import UIKit
protocol NoAdsStackDataSource: AnyObject {
func NoAdsStactChildView(_ content:NoAdsStackView, _ idx:Int) -> UIView
}
class NoAdsStackView: UIView {
var dataSource:(any NoAdsStackDataSource)?
var numbers:Int = 0 {
didSet{
self.loadUi()
}
}
private func loadUi() -> Void {
for i in 0..<self.numbers {
guard let child = dataSource?.NoAdsStactChildView(self , i) as? UIView else { return }
stack.addArrangedSubview(child)
}
}
var spacing:CGFloat = 0 {
didSet {
stack.spacing = spacing
}
}
var axis:NSLayoutConstraint.Axis = .vertical{
didSet{
stack.axis = axis
}
}
var alignment:UIStackView.Alignment = .fill {
didSet{
stack.alignment = alignment
}
}
var distribution:UIStackView.Distribution = .fill {
didSet{
stack.distribution = distribution
}
}
private lazy var stack: UIStackView = {
let stack = UIStackView()
stack.backgroundColor = .clear
stack.spacing = 8
stack.axis = .vertical
stack.alignment = .fill
stack.distribution = .equalSpacing
addSubview(stack)
return stack
}()
convenience init(_ numbers:Int) {
self.init(frame: CGRectZero)
self.numbers = numbers;
DispatchQueue.main.async {
self.loadUi()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
stack.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//
// HomePayModel.swift
// PhoneManager
//
// Created by edy on 2025/4/7.
//
import UIKit
import StoreKit
class HomePayModel: NSObject ,SKProductsRequestDelegate ,SKPaymentTransactionObserver {
static let share:HomePayModel = HomePayModel()
var isNoAd:Bool {
get {
guard let noabd = UserDefaults.standard.object(forKey: "noabd") as? Bool else { return false }
return noabd
}
set {
UserDefaults.standard.setValue((newValue), forKey: "noabd")
NotificationCenter.default.post(name: .HelperPurchaseNotification, object: nil)
UserDefaults.standard.synchronize()
}
}
var storeCall:((_ product:SKProduct) -> Void) = { prod in }
func checkTrialStatus() -> Void {
verifyReceiptWithApple { receipt in
guard let json = receipt else {
self.refreshReceipt()
return
}
let sub = self.checkSubscriptionStatus(receiptInfo: json)
if sub.0 == true {
let extDate = sub.2
self.isNoAd = true
#if DEBUG
let s = DateFormatter()
s.dateFormat = "yyyyMMdd HHmmss"
Print("ext : %@", s.string(from: extDate ?? Date()))
#endif
}else{
self.isNoAd = false
}
}
}
func fetchProducts() {
let request = SKProductsRequest(productIdentifiers: ["com.app.phonemanager.year.member"])
request.delegate = self
request.start()
Print("获取商品信息")
}
var product:SKProduct?
/** 获取商品列表 */
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
let products = response.products
guard let product = products.first else {
return
}
DispatchQueue.main.async {
self.product = product
self.storeCall(product)
}
}
/** 购买 */
func purchase() -> Void {
guard let prod = product,
SKPaymentQueue.canMakePayments()
else { return }
let payment = SKPayment(product: prod)
SKPaymentQueue.default().add(payment)
}
/** 恢复 */
func restore() -> Void {
SKPaymentQueue.default().restoreCompletedTransactions()
}
override init() {
super.init()
SKPaymentQueue.default().add(self)
}
}
extension HomePayModel {
/** 购买回调 */
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) -> Void {
guard let transaction = transactions.first else { return }
switch transaction.transactionState {
case .purchasing:
Print("购买中...")
break
case .purchased:
Print("购买成功")
self.handlePurchased(transaction)
break
case .failed:
Print("购买失败")
SKPaymentQueue.default().finishTransaction(transaction)
break
case .restored:
Print("恢复购买")
self.restore()
break
default: break
}
}
/** 购买成功 */
private func handlePurchased(_ transaction: SKPaymentTransaction) {
checkTrialStatus()
SKPaymentQueue.default().finishTransaction(transaction)
}
func verifyReceiptWithApple(completion: @escaping (_ receipt:[String:Any]?) -> Void ) {
guard let receiptURL = Bundle.main.appStoreReceiptURL,
let receiptData = try? Data(contentsOf: receiptURL) else {
completion(nil)
return
}
let requestData: [String: Any] = [
"receipt-data": receiptData.base64EncodedString(),
"password": "3cbeb6f5ace84f5b98571263da74c192",
"exclude-old-transactions": true
]
// 2. 创建请求
let url = URL(string: "https://buy.itunes.apple.com/verifyReceipt")! // 生产环境
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: requestData)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if error != nil {
completion(nil)
return
}
guard let data = data else {
completion(nil)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
if let status = json["status"] as? Int, status == 21007 {
self.verifySandboxReceipt(receiptData: receiptData) { receipt in
completion(receipt)
}
} else {
completion(json)
}
} else {
completion(nil)
}
} catch {
completion(nil)
}
}
task.resume()
}
/** 验证收据 */
private func verifySandboxReceipt(receiptData: Data, completion: @escaping (_ receipt:[String:Any]?) -> Void) {
let base64Receipt = receiptData.base64EncodedString()
let requestData: [String: Any] = [
"receipt-data": base64Receipt,
"password": "3cbeb6f5ace84f5b98571263da74c192",
"exclude-old-transactions": true
]
let url = URL(string: "https://sandbox.itunes.apple.com/verifyReceipt")! // 沙盒环境
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: requestData)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
completion(nil)
return
}
guard let data = data else {
completion(nil)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
completion(json)
} else {
completion(nil)
}
} catch {
completion(nil)
}
}
task.resume()
}
/** 获取订阅状态 */
func checkSubscriptionStatus(receiptInfo: [String: Any]) -> (isActive: Bool, isTrial: Bool, expiresDate: Date?) {
guard let latestReceiptInfo = receiptInfo["latest_receipt_info"] as? [[String: Any]] else {
return (false, false, nil)
}
// 获取最新的订阅信息
guard let lastReceipt = latestReceiptInfo.first else {
return (false, false, nil)
}
// 解析试用期状态
let isTrial = (lastReceipt["is_trial_period"] as? String) == "true"
// 解析到期时间
var expiresDate: Date?
if let expiresDateMs = lastReceipt["expires_date_ms"] as? String,
let timeInterval = TimeInterval(expiresDateMs) {
expiresDate = Date(timeIntervalSince1970: timeInterval / 1000.0)
} else if let expiresDateString = lastReceipt["expires_date"] as? String {
let formatter = ISO8601DateFormatter()
expiresDate = formatter.date(from: expiresDateString)
}
// 检查订阅是否有效
let isActive: Bool
if let date = expiresDate {
isActive = date > Date()
} else {
isActive = false
}
return (isActive, isTrial, expiresDate)
}
/** 恢复购买 */
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) -> Void {
checkTrialStatus()
}
/** 刷新收据 */
func refreshReceipt() {
let request = SKReceiptRefreshRequest()
request.delegate = self
request.start()
}
}
extension Notification.Name {
static let HelperPurchaseNotification = Notification.Name("PhoneManagerisStore")
}
......@@ -8,6 +8,7 @@
import UIKit
import SnapKit
import Lottie
import StoreKit
class HomePayView:UIView {
......@@ -124,6 +125,7 @@ class HomePayView:UIView {
restoreBtn?.setTitle("Restore Purchase", for: .normal)
restoreBtn?.setTitleColor(UIColor.colorWithHex(hexStr: "#B3B3B3"), for: .normal)
restoreBtn?.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .regular)
restoreBtn?.addTarget(self, action: #selector(restoreTouch), for: .touchUpInside)
self.addSubview(restoreBtn!)
restoreBtn?.snp.makeConstraints { make in
......@@ -328,7 +330,7 @@ class HomePayView:UIView {
contentView2?.layer.masksToBounds = true
contentView2Title = UILabel()
contentView2Title?.text = "Cleanup Pro"
contentView2Title?.text = "Free trial enabled"
contentView2Title?.font = UIFont.systemFont(ofSize: 16, weight: .bold)
contentView2Title?.textColor = UIColor.colorWithHex(hexStr: black3Color)
self.contentView2?.addSubview(contentView2Title!)
......@@ -344,6 +346,8 @@ class HomePayView:UIView {
contentView2Switch?.onTintColor = UIColor.colorWithHex(hexStr: mColor)
contentView2Switch?.tintColor = .white
contentView2Switch?.backgroundColor = .clear
contentView2Switch?.isOn = true
contentView2Switch?.isUserInteractionEnabled = false
self.contentView2?.addSubview(contentView2Switch!)
contentView2Switch?.snp.makeConstraints { make in
......@@ -478,8 +482,6 @@ class HomePayView:UIView {
make.width.equalToSuperview().offset(-45)
})
normalContentTitle = UILabel()
normalContentTitle?.text = "Due today"
normalContentTitle?.font = UIFont.systemFont(ofSize: 12, weight: .regular)
......@@ -503,7 +505,6 @@ class HomePayView:UIView {
make.centerX.equalToSuperview()
make.right.equalToSuperview()
})
}
func playAnimationWithDelay() {
......@@ -518,9 +519,14 @@ class HomePayView:UIView {
}
}
var product : SKProduct? {
didSet{
guard let prod = product else { return }
normalContentMoney?.text = "$\(prod.price)"
}
}
@objc func closeBtnClick() {
callBack(OperStatus.close)
}
......@@ -530,18 +536,19 @@ class HomePayView:UIView {
}
@objc func touBtnClick(btn:UIButton) {
callBack(CommonPush.tou)
}
@objc func switchValueChanged(_ sender: UISwitch) {
callBack(CommonPush.swit)
}
@objc func restoreTouch() -> Void {
callBack(CommonPush.restore)
}
@objc func payButtonClick() {
callBack(CommonPush.pay)
}
}
......@@ -6,33 +6,40 @@
//
import UIKit
import StoreKit
class HomePayViewController:UIViewController {
private var homePayView:HomePayView?
private var disjunctor = false
var currentProduct:SKProduct? {
didSet {
setPrice()
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
addViews()
HomePayModel.share.fetchProducts()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
storeKeD()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
homePayView?.playAnimationWithDelay()
}
private func addViews() {
homePayView = HomePayView(frame: view.bounds)
view.addSubview(homePayView!)
homePayView?.callBack = {[weak self] status in
guard let self else {return}
......@@ -54,18 +61,49 @@ class HomePayViewController:UIViewController {
self.ppClick()
case .tou:
self.touClick()
case .pay:
self.payTouch()
break
case .swit:
self.disjunctorTouch()
break
case .restore:
self.restoreClick()
break
}
}
}
}
}
extension HomePayViewController {
private func setPrice() -> Void {
guard currentProduct != nil else { return }
homePayView?.product = currentProduct
}
private func storeKeD() -> Void {
HomePayModel.share.storeCall = {[weak self] product in
guard let self = self else { return }
self.currentProduct = product
}
}
private func disjunctorTouch() -> Void {
self.disjunctor = !self.disjunctor
setPrice()
}
private func payTouch() -> Void {
HomePayModel.share.purchase()
}
private func ppClick() {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:PrivacyPolicyWebViewController = PrivacyPolicyWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
......@@ -73,14 +111,15 @@ class HomePayViewController:UIViewController {
}
private func touClick() {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:TermOfUseWebViewController = TermOfUseWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
private func restoreClick() {
HomePayModel.share.restore()
}
}
......@@ -59,7 +59,6 @@ class SettingViewController : BaseViewController , UITableViewDelegate, UITableV
let cell : SettingViewHeaderCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewHeaderCell",for: indexPath) as! SettingViewHeaderCell
return cell
}else{
let model : SettingModel = modelData![indexPath.section]
let detailModel : RowInfoModel = model.rowInfo[indexPath.row]
......@@ -157,10 +156,36 @@ class SettingViewController : BaseViewController , UITableViewDelegate, UITableV
break
case 3:
break
case 4:
if indexPath.row == 0 { // 评分
self.review()
}else if indexPath.row == 1 { // 分享
self.PhoneShare()
}
break
default:
break
}
}
private func review() -> Void {
let reviewURLString = "itms-apps://itunes.apple.com/app/id1530333201?action=write-review"
guard let url = URL(string: reviewURLString), UIApplication.shared.canOpenURL(url) else {
return
}
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:])
}
}
private func PhoneShare() -> Void {
let items: [Any] = [ URL(string: "https://www.baidu.com")!]
let shareVc = UIActivityViewController(
activityItems: items,
applicationActivities: nil
)
present(shareVc, animated: true)
}
}
......@@ -22,6 +22,9 @@ enum CommonPush {
case pp
case tou
case swit
case pay
case restore
}
enum tabbarType {
......
......@@ -23,8 +23,5 @@ extension UIViewController {
nav.barHidden = isHidden
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment