Commit 83f33d9f authored by shenyong's avatar shenyong

订阅增加类型获取,新增年费会员

parent 855a80da
...@@ -135,20 +135,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -135,20 +135,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private func setupDefault() { private func setupDefault() {
IAPManager.share.checkSubscriptionState { isSubscribed, expiresDate in
Print("是否内购---",isSubscribed)
}
NetStatusManager.manager.startNet { status in NetStatusManager.manager.startNet { status in
switch status { switch status {
case .NoNet: case .NoNet:
break break
case .WIFI,.WWAN: case .WIFI,.WWAN:
break
if (PhotoAndVideoMananger.mananger.allAssets.count == 0) {
PhotoAndVideoMananger.mananger.setAssets()
}
} }
} }
......
...@@ -28,9 +28,23 @@ extension AppDelegate{ ...@@ -28,9 +28,23 @@ extension AppDelegate{
switch shortcutItem.type { switch shortcutItem.type {
case "com.app.phonemanager.iap.distance": case "com.app.phonemanager.iap.distance":
// 执行相应操作 // 执行相应操作
let vc = PayDistanceViewController() IAPManager.share.showYearPage = true
if IAPManager.share.isHotLaunch{
// 热启动走这里
switch IAPManager.share.subscriptionType {
case .none,.week:
let vc:PayDistanceViewController = PayDistanceViewController()
let nav:BaseNavViewController = BaseNavViewController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
guard let rt = UIViewController.topMostViewController() else { return }
rt.present(nav, animated: true)
default:
let vc : PayCompletedViewController = PayCompletedViewController()
guard let rt = UIViewController.topMostViewController() else { return }
vc.modalPresentationStyle = .fullScreen vc.modalPresentationStyle = .fullScreen
GETCURRENTNAV()?.present(vc, animated: false) rt.present(vc, animated: true)
}
}
completionHandler(true) completionHandler(true)
default: default:
completionHandler(false) completionHandler(false)
......
...@@ -37,6 +37,15 @@ enum IAPError: Error { ...@@ -37,6 +37,15 @@ enum IAPError: Error {
} }
} }
// 添加一个枚举来表示订阅类型
enum SubscriptionType {
case none
case week
case year
case lifetime
}
// MARK: - IAPManager // MARK: - IAPManager
class IAPManager: NSObject { class IAPManager: NSObject {
...@@ -87,10 +96,23 @@ class IAPManager: NSObject { ...@@ -87,10 +96,23 @@ class IAPManager: NSObject {
} }
} }
// 是否展示优惠订阅
var showYearPage:Bool = false
// 是否热启动
var isHotLaunch:Bool = false
// 订阅状态
var subscriptionType:SubscriptionType = .none{
didSet{
isSubscribed = subscriptionType != .none
}
}
// MARK: - Initialization // MARK: - Initialization
private override init() { private override init() {
super.init() super.init()
SKPaymentQueue.default().add(self) SKPaymentQueue.default().add(self)
} }
deinit { deinit {
...@@ -133,31 +155,56 @@ extension IAPManager { ...@@ -133,31 +155,56 @@ extension IAPManager {
// 检查订阅信息 // 检查订阅信息
/// - Parameter completion: 回调闭包,返回订阅状态和到期时间 /// - Parameter completion: 回调闭包,返回订阅状态和到期时间
func checkSubscriptionState(completion: @escaping (_ isSubscribed: Bool, _ expiresDate: Date?) -> Void) { // func checkSubscriptionState(completion: @escaping (_ isSubscribed: Bool, _ expiresDate: Date?) -> Void) {
// verifyReceiptWithApple { result in
// switch result {
// case .success(let receipt):
// // 打印完整收据信息,方便调试
// //print("收据信息:\(receipt)")
// let status = self.checkSubscriptionStatus(receiptInfo: receipt)
// DispatchQueue.main.async {
// completion(status.isActive, status.expiresDate)
// // 更新本地订阅状态
// self.isSubscribed = status.isActive
// #if DEBUG
// if let expDate = status.expiresDate {
// let formatter = DateFormatter()
// formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
// Print("订阅状态:\(status.isActive ? "已订阅" : "未订阅"),到期时间:\(formatter.string(from: expDate))")
// }
// #endif
// }
//
// case .failure(_):
// // 处理错误情况
// self.refreshReceipt()
// completion(false, nil)
// }
// }
// }
// 修改回调方法,增加订阅类型参数
func checkSubscriptionState(completion: @escaping (_ isSubscribed: Bool, _ subscriptionType: SubscriptionType, _ expiresDate: Date?) -> Void) {
verifyReceiptWithApple { result in verifyReceiptWithApple { result in
switch result { switch result {
case .success(let receipt): case .success(let receipt):
// 打印完整收据信息,方便调试
//print("收据信息:\(receipt)")
let status = self.checkSubscriptionStatus(receiptInfo: receipt) let status = self.checkSubscriptionStatus(receiptInfo: receipt)
DispatchQueue.main.async { DispatchQueue.main.async {
completion(status.isActive, status.expiresDate) completion(status.isActive, status.subscriptionType, status.expiresDate)
// 更新本地订阅状态
self.isSubscribed = status.isActive self.isSubscribed = status.isActive
self.subscriptionType = status.subscriptionType
#if DEBUG #if DEBUG
if let expDate = status.expiresDate { if let expDate = status.expiresDate {
let formatter = DateFormatter() let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
Print("订阅状态:\(status.isActive ? "已订阅" : "未订阅"),到期时间:\(formatter.string(from: expDate))") Print("订阅状态:\(status.isActive ? "已订阅" : "未订阅")订阅类型:\(status.subscriptionType)到期时间:\(formatter.string(from: expDate))")
} }
#endif #endif
} }
case .failure(_): case .failure(_):
// 处理错误情况
self.refreshReceipt() self.refreshReceipt()
completion(false, nil) completion(false, .none, nil)
} }
} }
} }
...@@ -440,7 +487,7 @@ extension IAPManager: SKPaymentTransactionObserver { ...@@ -440,7 +487,7 @@ extension IAPManager: SKPaymentTransactionObserver {
/** 恢复购买 */ /** 恢复购买 */
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
// 刷新订阅状态 // 刷新订阅状态
checkSubscriptionState { [weak self] isSubscribed, expiresDate in checkSubscriptionState { [weak self] isSubscribed,type,expiresDate in
guard let self = self else { return } guard let self = self else { return }
// 更新恢复购买的结果 // 更新恢复购买的结果
if isSubscribed { if isSubscribed {
...@@ -468,7 +515,57 @@ extension IAPManager: SKPaymentTransactionObserver { ...@@ -468,7 +515,57 @@ extension IAPManager: SKPaymentTransactionObserver {
extension IAPManager{ extension IAPManager{
func checkSubscriptionStatus(receiptInfo: [String: Any]) -> (isActive: Bool, isTrial: Bool, expiresDate: Date?) { // func checkSubscriptionStatus(receiptInfo: [String: Any]) -> (isActive: Bool, isTrial: Bool, expiresDate: Date?) {
// // 首先检查 in_app 购买记录
// if let receipt = receiptInfo["receipt"] as? [String: Any],
// let inAppPurchases = receipt["in_app"] as? [[String: Any]] {
// // 检查是否存在永久商品购买记录
// let hasLifetimePurchase = inAppPurchases.contains { purchase in
// return purchase["product_id"] as? String == ProductID.lifetimeMember
// }
//
// if hasLifetimePurchase {
// print("检测到永久商品购买记录")
// return (true, false, nil)
// }
// }
//
// // 如果没有永久商品,继续检查订阅
// guard let latestReceiptInfo = receiptInfo["latest_receipt_info"] as? [[String: Any]] else {
// print("没有找到任何购买记录")
// return (false, false, nil)
// }
//
// // 按过期时间排序,确保获取最新的订阅记录
// let sortedReceipts = latestReceiptInfo.sorted { receipt1, receipt2 in
// let date1 = getExpiryDate(from: receipt1) ?? Date.distantPast
// let date2 = getExpiryDate(from: receipt2) ?? Date.distantPast
// return date1 > date2
// }
//
// guard let lastReceipt = sortedReceipts.first else {
// return (false, false, nil)
// }
//
// // 解析试用期状态
// let isTrial = (lastReceipt["is_trial_period"] as? String) == "true"
//
// // 获取过期时间
// let expiresDate = getExpiryDate(from: lastReceipt)
// let isActive = expiresDate?.compare(Date()) == .orderedDescending
//
// #if DEBUG
// if let expDate = expiresDate {
// let formatter = DateFormatter()
// formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
// print("订阅状态:\(isActive ? "已订阅" : "未订阅"),到期时间:\(formatter.string(from: expDate))")
// }
// #endif
//
// return (isActive, isTrial, expiresDate)
// }
func checkSubscriptionStatus(receiptInfo: [String: Any]) -> (isActive: Bool, isTrial: Bool, subscriptionType: SubscriptionType, expiresDate: Date?) {
// 首先检查 in_app 购买记录 // 首先检查 in_app 购买记录
if let receipt = receiptInfo["receipt"] as? [String: Any], if let receipt = receiptInfo["receipt"] as? [String: Any],
let inAppPurchases = receipt["in_app"] as? [[String: Any]] { let inAppPurchases = receipt["in_app"] as? [[String: Any]] {
...@@ -479,14 +576,14 @@ extension IAPManager{ ...@@ -479,14 +576,14 @@ extension IAPManager{
if hasLifetimePurchase { if hasLifetimePurchase {
print("检测到永久商品购买记录") print("检测到永久商品购买记录")
return (true, false, nil) return (true, false, .lifetime, nil)
} }
} }
// 如果没有永久商品,继续检查订阅 // 如果没有永久商品,继续检查订阅
guard let latestReceiptInfo = receiptInfo["latest_receipt_info"] as? [[String: Any]] else { guard let latestReceiptInfo = receiptInfo["latest_receipt_info"] as? [[String: Any]] else {
print("没有找到任何购买记录") print("没有找到任何购买记录")
return (false, false, nil) return (false, false, .none, nil)
} }
// 按过期时间排序,确保获取最新的订阅记录 // 按过期时间排序,确保获取最新的订阅记录
...@@ -497,7 +594,7 @@ extension IAPManager{ ...@@ -497,7 +594,7 @@ extension IAPManager{
} }
guard let lastReceipt = sortedReceipts.first else { guard let lastReceipt = sortedReceipts.first else {
return (false, false, nil) return (false, false, .none, nil)
} }
// 解析试用期状态 // 解析试用期状态
...@@ -507,15 +604,21 @@ extension IAPManager{ ...@@ -507,15 +604,21 @@ extension IAPManager{
let expiresDate = getExpiryDate(from: lastReceipt) let expiresDate = getExpiryDate(from: lastReceipt)
let isActive = expiresDate?.compare(Date()) == .orderedDescending let isActive = expiresDate?.compare(Date()) == .orderedDescending
#if DEBUG // 确定订阅类型
if let expDate = expiresDate { let productId = lastReceipt["product_id"] as? String
let formatter = DateFormatter() let subscriptionType: SubscriptionType
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" switch productId {
print("订阅状态:\(isActive ? "已订阅" : "未订阅"),到期时间:\(formatter.string(from: expDate))") case ProductID.weekMember:
subscriptionType = .week
case ProductID.yearMember:
subscriptionType = .year
case ProductID.lifetimeMember:
subscriptionType = .lifetime
default:
subscriptionType = .none
} }
#endif
return (isActive, isTrial, expiresDate) return (isActive, isTrial, subscriptionType, expiresDate)
} }
// 辅助方法:解析过期时间 // 辅助方法:解析过期时间
......
//
// IAPPageManager.swift
// PhoneManager
//
// Created by edy on 2025/5/19.
//
import Foundation
struct IAPPageManager{
func showIAPPage(){
}
}
...@@ -137,9 +137,14 @@ class PhotoManager{ ...@@ -137,9 +137,14 @@ class PhotoManager{
private func requestAuthorization(){ private func requestAuthorization(){
// 获取基础数据 // 获取基础数据
requestAuthorization {[weak self] _ in requestAuthorization {[weak self] permission in
guard let weakSelf = self else { return } guard let weakSelf = self else { return }
if permission{
weakSelf.getBaseAssetGroup() weakSelf.getBaseAssetGroup()
}else{
weakSelf.clearLocalData()
}
} }
} }
...@@ -748,6 +753,10 @@ extension PhotoManager{ ...@@ -748,6 +753,10 @@ extension PhotoManager{
} }
} }
func clearLocalData(){
}
func removeAssets(withIdentifiers identifiers: [String], from assets: [AssetModel]) -> [AssetModel] { func removeAssets(withIdentifiers identifiers: [String], from assets: [AssetModel]) -> [AssetModel] {
let identifierSet = Set(identifiers) let identifierSet = Set(identifiers)
......
...@@ -14,8 +14,12 @@ class HomeViewController:BaseViewController { ...@@ -14,8 +14,12 @@ class HomeViewController:BaseViewController {
private var isShowCharge:Bool = false private var isShowCharge:Bool = false
private var canShowIAP:Bool = false
var homeView:HomeView? var homeView:HomeView?
fileprivate func junmToModule(_ cIndex: Int, _ self: HomeViewController) { fileprivate func junmToModule(_ cIndex: Int, _ self: HomeViewController) {
switch cIndex { switch cIndex {
...@@ -185,6 +189,15 @@ class HomeViewController:BaseViewController { ...@@ -185,6 +189,15 @@ class HomeViewController:BaseViewController {
func loadLaunchView(){ func loadLaunchView(){
let luanch = HomeLaunchView(frame: CGRect(x: 0, y: 0, width: ScreenW, height: ScreenH)) let luanch = HomeLaunchView(frame: CGRect(x: 0, y: 0, width: ScreenW, height: ScreenH))
luanch.show() luanch.show()
luanch.disMissBlock = {[weak self] in
guard let weakSelf = self else { return }
guard UserDef.shard.isShowLanding else{
return
}
weakSelf.showIAPVC()
}
if !UserDef.shard.isShowLanding{ if !UserDef.shard.isShowLanding{
let Ssoryboard = UIStoryboard(name: "PermissionVC", bundle: nil) let Ssoryboard = UIStoryboard(name: "PermissionVC", bundle: nil)
...@@ -192,9 +205,47 @@ class HomeViewController:BaseViewController { ...@@ -192,9 +205,47 @@ class HomeViewController:BaseViewController {
self.navigationController?.pushViewController(current, animated: false) self.navigationController?.pushViewController(current, animated: false)
} }
} }
NotificationCenter.default.addObserver(forName: .guidePageClose, object: nil, queue: nil) {[weak self] _ in
guard let weakSelf = self else { return }
weakSelf.showIAPVC()
}
}
func showIAPVC(){
IAPManager.share.isHotLaunch = true
IAPManager.share.checkSubscriptionState { isSubscribed,type,expiresDate in
Print("是否内购---",isSubscribed)
if IAPManager.share.showYearPage{
//按钮启动
switch type {
case .none,.week:
let vc:PayDistanceViewController = PayDistanceViewController()
let nav:BaseNavViewController = BaseNavViewController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
self.present(nav, animated: true)
case .lifetime,.year:
let vc : PayCompletedViewController = PayCompletedViewController()
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true)
}
}else{
// 正常启动
if !isSubscribed{
DispatchQueue.main.async {
if !IAPManager.share.showYearPage{
HomePayViewController.show {
NotificationManager().configNotifications()
}
}
}
}
}
}
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
...@@ -215,6 +266,21 @@ class HomeViewController:BaseViewController { ...@@ -215,6 +266,21 @@ class HomeViewController:BaseViewController {
homeView?.viewModel.reloadTrashAndKeep() homeView?.viewModel.reloadTrashAndKeep()
} }
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.barHidden = false
// 开启定时器
Singleton.shared.startCountdown {}
if !isShowCharge {
NotificationManager().configNotifications()
return
}
}
} }
extension HomeViewController { extension HomeViewController {
...@@ -272,11 +338,3 @@ extension HomeViewController { ...@@ -272,11 +338,3 @@ extension HomeViewController {
} }
} }
// 遵守转场代理协议
extension HomeViewController: UIViewControllerTransitioningDelegate {
// 返回自定义的消失动画对象
func animationController(forDismissed dismissedController: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return FadeOutTransition()
}
}
...@@ -60,10 +60,10 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -60,10 +60,10 @@ class HomeCollectionViewHeader : UICollectionReusableView {
self.addSubview(self.permissionView) self.addSubview(self.permissionView)
self.permissionView.snp.makeConstraints { make in self.permissionView.snp.makeConstraints { make in
make.top.equalTo(self.progressBar.snp.bottom).offset(-92) make.top.equalTo(progressBar.snp.bottom).offset(10)
make.left.equalToSuperview().offset(-22) make.left.equalToSuperview().offset(-22)
make.right.equalToSuperview().offset(22) make.right.equalToSuperview().offset(22)
make.height.equalTo(449) make.height.equalTo(340)
} }
...@@ -206,6 +206,7 @@ class CustomProgressBar: UIView { ...@@ -206,6 +206,7 @@ class CustomProgressBar: UIView {
progressLayer.frame = CGRect(x: 0, y: 0, width: ScreenW-48, height: 10) progressLayer.frame = CGRect(x: 0, y: 0, width: ScreenW-48, height: 10)
progressLayer.cornerRadius = 5 progressLayer.cornerRadius = 5
progressLayer.masksToBounds = true progressLayer.masksToBounds = true
updateProgress()
} }
......
...@@ -404,7 +404,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -404,7 +404,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
if PhotoManager.shared.permissionStatus == .authorized{ if PhotoManager.shared.permissionStatus == .authorized{
return CGSize(width: self.collectionView.width, height: 76 + (self.homeNavView?.height ?? 0)) return CGSize(width: self.collectionView.width, height: 76 + (self.homeNavView?.height ?? 0))
}else{ }else{
return CGSize(width: self.collectionView.width, height: 404) return CGSize(width: self.collectionView.width, height: 450)
} }
} }
return CGSize.zero return CGSize.zero
......
...@@ -24,6 +24,7 @@ class NewGuideViewController: UIViewController { ...@@ -24,6 +24,7 @@ class NewGuideViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.transitioningDelegate = self
configUI() configUI()
startTimer() startTimer()
} }
...@@ -97,10 +98,11 @@ class NewGuideViewController: UIViewController { ...@@ -97,10 +98,11 @@ class NewGuideViewController: UIViewController {
// // 显示 window // // 显示 window
// cWindow?.makeKeyAndVisible() // cWindow?.makeKeyAndVisible()
self.navigationController?.popToRootViewController(animated: false)
self.navigationController?.popToRootViewController(animated: false)
UserDef.shard.isShowLanding = true UserDef.shard.isShowLanding = true
UserDef.shard.saveUserDefToSandBox() UserDef.shard.saveUserDefToSandBox()
NotificationCenter.default.post(name: .guidePageClose, object: nil)
} }
deinit{ deinit{
...@@ -147,3 +149,10 @@ extension NewGuideViewController:UICollectionViewDelegate,UICollectionViewDataSo ...@@ -147,3 +149,10 @@ extension NewGuideViewController:UICollectionViewDelegate,UICollectionViewDataSo
} }
} }
extension NewGuideViewController: UIViewControllerTransitioningDelegate {
func animationController(forDismissed dismissedController: UIViewController) -> UIViewControllerAnimatedTransitioning? {
// pop 时触发消失动画(等同于 popToRootViewController)
return FadeOutPopTransition()
}
}
...@@ -10,6 +10,8 @@ import Lottie ...@@ -10,6 +10,8 @@ import Lottie
class HomeLaunchView:UIView { class HomeLaunchView:UIView {
var disMissBlock:(() ->Void)?
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.frame = frame self.frame = frame
...@@ -62,6 +64,7 @@ class HomeLaunchView:UIView { ...@@ -62,6 +64,7 @@ class HomeLaunchView:UIView {
}completion: { _ in }completion: { _ in
self.removeFromSuperview() self.removeFromSuperview()
} }
self.disMissBlock?()
}) })
} }
......
...@@ -102,10 +102,6 @@ class HomePayView:UIView { ...@@ -102,10 +102,6 @@ class HomePayView:UIView {
let animationView = LottieAnimationView(name: "iapAnimation") let animationView = LottieAnimationView(name: "iapAnimation")
animationView.loopMode = .loop animationView.loopMode = .loop
// animationView.animationSpeed = -1.0
// animationView.layer.cornerRadius = 8
// animationView.contentMode = .scaleAspectFill
// animationView.clipsToBounds = true
return animationView return animationView
}() }()
...@@ -115,6 +111,7 @@ class HomePayView:UIView { ...@@ -115,6 +111,7 @@ class HomePayView:UIView {
super.init(frame: frame) super.init(frame: frame)
setupUI() setupUI()
setPayAnime()
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -162,63 +159,6 @@ class HomePayView:UIView { ...@@ -162,63 +159,6 @@ class HomePayView:UIView {
titleLabel2?.sizeToFit() titleLabel2?.sizeToFit()
// photoImage = UIImageView(image: UIImage(named: "img_photos_start"))
// self.addSubview(photoImage)
//
// photoImage.snp.makeConstraints { make in
// make.top.equalTo(titleLabel2!.snp.bottom).offset(38.RH())
// make.left.equalTo(48.RW())
// make.size.equalTo(64.RW())
// }
//
// icloudImage = UIImageView(image: UIImage(named: "img_file_guide"))
// self.addSubview(icloudImage)
//
// icloudImage.snp.makeConstraints { make in
// make.left.equalTo(photoImage.snp.right).offset(24.RW())
// make.centerY.equalTo(photoImage)
// make.size.equalTo(64.RW())
// }
//
// photoLabel = UILabel()
// photoLabel?.text = "403"
// photoLabel?.backgroundColor = UIColor.colorWithHex(hexStr: "#EB4545")
// photoLabel?.font = UIFont.scaledSystemFont(ofSize: 10, weight: .bold)
// photoLabel?.textAlignment = .center
// photoLabel?.textColor = .white
// photoLabel?.layer.cornerRadius = 12.RW()
// photoLabel?.layer.masksToBounds = true
// self.addSubview(photoLabel!)
//
// photoLabel?.snp.makeConstraints { make in
// make.top.equalTo(photoImage.snp.top).offset(-12)
// make.right.equalTo(photoImage.snp.right).offset(12)
// make.size.equalTo(24.RW())
// }
//
// photoLabel?.sizeToFit()
//
// icloudLabel = UILabel()
// icloudLabel?.text = "217"
// icloudLabel?.textAlignment = .center
// icloudLabel?.font = UIFont.scaledSystemFont(ofSize: 10, weight: .bold)
// icloudLabel?.backgroundColor = UIColor.colorWithHex(hexStr: "#EB4545")
// icloudLabel?.textColor = .white
// icloudLabel?.layer.cornerRadius = 12.RW()
// icloudLabel?.layer.masksToBounds = true
// self.addSubview(icloudLabel!)
//
// icloudLabel?.snp.makeConstraints { make in
// make.top.equalTo(icloudImage.snp.top).offset(-12)
// make.right.equalTo(icloudImage.snp.right).offset(12)
// make.size.equalTo(24.RW())
// }
//
// icloudLabel?.sizeToFit()
//
self.addSubview(animationView) self.addSubview(animationView)
playAnimationWithDelay() playAnimationWithDelay()
...@@ -228,27 +168,6 @@ class HomePayView:UIView { ...@@ -228,27 +168,6 @@ class HomePayView:UIView {
make.width.equalTo(285.RW()) make.width.equalTo(285.RW())
make.height.equalTo(142.RW()) make.height.equalTo(142.RW())
} }
//
// let analysis = UILabel()
// analysis.text = "Analysis completed"
// analysis.textColor = UIColor.colorWithHex(hexStr: "#B3B3B3")
// analysis.font = UIFont.scaledSystemFont(ofSize: 14, weight: .bold)
// addSubview(analysis)
// analysis.snp.makeConstraints { make in
// make.left.equalTo(animationView.snp.left)
// make.top.equalTo(animationView.snp.bottom).offset(8)
// }
//
// memSize = UILabel()
// memSize.text = "100%"
// memSize.textColor = UIColor.colorWithHex(hexStr: "#B3B3B3")
// memSize.font = UIFont.scaledSystemFont(ofSize: 14, weight: .bold)
// addSubview(memSize)
// memSize.snp.makeConstraints { make in
// make.right.equalTo(animationView.snp.right)
// make.top.equalTo(animationView.snp.bottom).offset(8)
// }
appleLabel = UILabel() appleLabel = UILabel()
appleLabel?.text = " Secured with Apple" appleLabel?.text = " Secured with Apple"
...@@ -341,49 +260,6 @@ class HomePayView:UIView { ...@@ -341,49 +260,6 @@ class HomePayView:UIView {
} }
// if let url = Bundle.main.url(forResource: "iap", withExtension: "gif"),
// let data = try? Data(contentsOf: url) {
// let animatedImage = FLAnimatedImage(animatedGIFData: data)
// let imageView = FLAnimatedImageView()
// imageView.animatedImage = animatedImage
// imageView.startAnimating()
// addSubview(imageView)
//
// imageView.snp.makeConstraints { make in
// make.centerX.equalToSuperview()
// make.top.equalTo(titleLabel2!.snp.bottom).offset(40)
// make.width.equalTo(285.RW())
// make.height.equalTo(142.RW())
// }
// }
// let gifImageView = UIImageView()
// gifImageView.contentMode = .scaleAspectFit
// addSubview(gifImageView)
// gifImageView.snp.makeConstraints { make in
// make.centerX.equalToSuperview()
// make.top.equalTo(titleLabel2!.snp.bottom).offset(40)
// make.width.equalTo(285.RW())
// make.height.equalTo(142.RW())
// }
//
// // 从 Bundle 加载 GIF 文件
// guard let gifImage = try? UIImage(gifName: "iap.gif") else {
// print("Failed to load GIF")
// return
// }
//
// gifImageView.setGifImage(gifImage, loopCount: -1)
// gifImageView.startAnimatingGif()
// gifImageView.startAnimatingGif()
// // 设置 GIF 到 ImageView 并开始播放
// do {
// try gifImageView.setGifImage(gifImage, loopCount: 0) // 0 表示无限循环
// } catch {
// print("Error setting GIF: \(error)")
// }
} }
func playAnimationWithDelay() { func playAnimationWithDelay() {
...@@ -553,45 +429,6 @@ class HomePayView:UIView { ...@@ -553,45 +429,6 @@ class HomePayView:UIView {
make.height.equalTo(110.RH()) make.height.equalTo(110.RH())
} }
// let freespace = UILabel()
// freespace.font = UIFont.scaledSystemFont(ofSize: 12, weight: .bold)
// freespace.text = "FREE SPACE"
// freespace.textColor = UIColor.colorWithHex(hexStr: "#B3B3B3")
// addSubview(freespace)
//
// sizeLabel = UILabel()
// sizeLabel.text = "54.2 GB"
// sizeLabel.textColor = UIColor.colorWithHex(hexStr: black3Color)
// sizeLabel.font = UIFont.scaledSystemFont(ofSize: 12, weight: .bold)
// addSubview(sizeLabel)
//
// freespace.snp.makeConstraints { make in
// make.left.equalTo(icloudImage!.snp.right).offset(24.RW())
// make.top.equalTo(titleLabel2!.snp.bottom).offset(42)
// make.height.equalTo(17.RW())
// }
//
// sizeLabel.snp.makeConstraints { make in
// make.top.equalTo(freespace.snp.bottom).offset(0)
// make.left.equalTo(icloudImage!.snp.right).offset(24)
// make.height.equalTo(39.RW())
// }
//
// let fullText = FileTool().formatBytes(FileTool().getStorageInfo(for: .free) ?? 0 )
// // 创建一个可变的富文本字符串
// let attributedString = NSMutableAttributedString(string: fullText)
// // 设置前半部分(动态数值)的范围
// let regularFont = UIFont.scaledSystemFont(ofSize: 28, weight: .bold) // 设置常规字体大小
// attributedString.addAttribute(.font, value: regularFont, range: NSRange.init(location: 0,length:fullText.count-2))
//
// // 设置“GB”部分的范围并将字体大小设置为12
// let smallFont = UIFont.scaledSystemFont(ofSize: 12, weight: .bold) // 设置字体大小为12
// attributedString.addAttribute(.font, value: smallFont, range:NSRange.init(location: fullText.count-2, length: 2))
//
// // 将富文本赋值给UILabel
// sizeLabel.attributedText = attributedString
payDueView.snp.makeConstraints { make in payDueView.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
make.top.equalTo(tipsView.snp.bottom).offset(90.RH()) make.top.equalTo(tipsView.snp.bottom).offset(90.RH())
......
//
// PayDistanceAnimaeView.swift
// PhoneManager
//
// Created by edy on 2025/5/19.
//
import UIKit
class PayDistanceAnimaeView: UIView {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
...@@ -11,20 +11,20 @@ ...@@ -11,20 +11,20 @@
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="EwM-B0-fXo" customClass="PMPermissionView" customModule="PhoneManager" customModuleProvider="target"> <view contentMode="scaleToFill" id="EwM-B0-fXo" customClass="PMPermissionView" customModule="PhoneManager" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="543" height="449"/> <rect key="frame" x="0.0" y="0.0" width="470" height="337"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_queshengtu" translatesAutoresizingMaskIntoConstraints="NO" id="qhV-IF-vsx"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_queshengtu" translatesAutoresizingMaskIntoConstraints="NO" id="qhV-IF-vsx">
<rect key="frame" x="177" y="100" width="189" height="189"/> <rect key="frame" x="140.66666666666666" y="0.0" width="188.99999999999997" height="189"/>
</imageView> </imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Access permission is required to start scan" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ci8-h6-fiE"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Access permission is required to start scan" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ci8-h6-fiE">
<rect key="frame" x="5" y="297" width="533" height="20"/> <rect key="frame" x="5" y="197" width="460" height="20"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Phone Manager We need access to all the photos in your photo library" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e8v-Xy-wvP"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Phone Manager We need access to all the photos in your photo library" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e8v-Xy-wvP">
<rect key="frame" x="109" y="320" width="325" height="38.333333333333314"/> <rect key="frame" x="72.666666666666686" y="220" width="325" height="38.333333333333314"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="325" id="7Q3-fW-f7G"/> <constraint firstAttribute="width" constant="325" id="7Q3-fW-f7G"/>
</constraints> </constraints>
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fRi-wi-J8I"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fRi-wi-J8I">
<rect key="frame" x="177" y="371.33333333333331" width="189" height="46"/> <rect key="frame" x="140.66666666666666" y="271.33333333333331" width="188.99999999999997" height="46"/>
<color key="backgroundColor" red="0.0" green="0.50980392159999999" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.50980392159999999" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="46" id="2ml-bk-VZ7"/> <constraint firstAttribute="height" constant="46" id="2ml-bk-VZ7"/>
...@@ -59,14 +59,14 @@ ...@@ -59,14 +59,14 @@
<constraint firstItem="ci8-h6-fiE" firstAttribute="leading" secondItem="Z86-W8-437" secondAttribute="leading" constant="5" id="2pS-Hl-sgb"/> <constraint firstItem="ci8-h6-fiE" firstAttribute="leading" secondItem="Z86-W8-437" secondAttribute="leading" constant="5" id="2pS-Hl-sgb"/>
<constraint firstItem="ci8-h6-fiE" firstAttribute="centerX" secondItem="qhV-IF-vsx" secondAttribute="centerX" id="Fv3-iO-5BI"/> <constraint firstItem="ci8-h6-fiE" firstAttribute="centerX" secondItem="qhV-IF-vsx" secondAttribute="centerX" id="Fv3-iO-5BI"/>
<constraint firstItem="e8v-Xy-wvP" firstAttribute="centerX" secondItem="ci8-h6-fiE" secondAttribute="centerX" id="OZD-Bq-U2s"/> <constraint firstItem="e8v-Xy-wvP" firstAttribute="centerX" secondItem="ci8-h6-fiE" secondAttribute="centerX" id="OZD-Bq-U2s"/>
<constraint firstItem="qhV-IF-vsx" firstAttribute="top" secondItem="EwM-B0-fXo" secondAttribute="top" constant="100" id="fx5-wC-f0q"/> <constraint firstItem="qhV-IF-vsx" firstAttribute="top" secondItem="EwM-B0-fXo" secondAttribute="top" id="fx5-wC-f0q"/>
<constraint firstItem="fRi-wi-J8I" firstAttribute="top" secondItem="e8v-Xy-wvP" secondAttribute="bottom" constant="13" id="jys-rP-uUI"/> <constraint firstItem="fRi-wi-J8I" firstAttribute="top" secondItem="e8v-Xy-wvP" secondAttribute="bottom" constant="13" id="jys-rP-uUI"/>
<constraint firstItem="e8v-Xy-wvP" firstAttribute="top" secondItem="ci8-h6-fiE" secondAttribute="bottom" constant="3" id="tgi-kq-3Ap"/> <constraint firstItem="e8v-Xy-wvP" firstAttribute="top" secondItem="ci8-h6-fiE" secondAttribute="bottom" constant="3" id="tgi-kq-3Ap"/>
<constraint firstItem="ci8-h6-fiE" firstAttribute="top" secondItem="qhV-IF-vsx" secondAttribute="bottom" constant="8" id="uKW-kw-KCJ"/> <constraint firstItem="ci8-h6-fiE" firstAttribute="top" secondItem="qhV-IF-vsx" secondAttribute="bottom" constant="8" id="uKW-kw-KCJ"/>
<constraint firstItem="Z86-W8-437" firstAttribute="trailing" secondItem="ci8-h6-fiE" secondAttribute="trailing" constant="5" id="wMs-cZ-eGL"/> <constraint firstItem="Z86-W8-437" firstAttribute="trailing" secondItem="ci8-h6-fiE" secondAttribute="trailing" constant="5" id="wMs-cZ-eGL"/>
</constraints> </constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="295.41984732824426" y="-329.22535211267609"/> <point key="canvasLocation" x="239.69465648854961" y="-368.66197183098592"/>
</view> </view>
</objects> </objects>
<resources> <resources>
......
...@@ -34,3 +34,31 @@ class FadeOutTransition: NSObject, UIViewControllerAnimatedTransitioning { ...@@ -34,3 +34,31 @@ class FadeOutTransition: NSObject, UIViewControllerAnimatedTransitioning {
} }
} }
} }
// 自定义转场动画(用于 pop 时的渐隐效果)
class FadeOutPopTransition: NSObject, UIViewControllerAnimatedTransitioning {
// 动画时长
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3 // 0.3秒渐隐
}
// 执行动画
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// 获取当前视图控制器(即将消失的控制器)
guard let fromVC = transitionContext.viewController(forKey: .from),
let toVC = transitionContext.viewController(forKey: .to) else { return }
// 将目标控制器(RootViewController)的视图添加到容器视图
transitionContext.containerView.addSubview(toVC.view)
// 渐隐动画:当前控制器视图透明度从 1 降到 0
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
fromVC.view.alpha = 0
}) { (_) in
// 动画完成后,标记转场结束
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
...@@ -15,4 +15,8 @@ extension NSNotification.Name { ...@@ -15,4 +15,8 @@ extension NSNotification.Name {
//监听拿到基本相册资源 //监听拿到基本相册资源
static let getBaseAssetsSuccess: NSNotification.Name = NSNotification.Name(rawValue: "getBaseAssetsSuccess") static let getBaseAssetsSuccess: NSNotification.Name = NSNotification.Name(rawValue: "getBaseAssetsSuccess")
//首次打开引导页关闭
static let guidePageClose: NSNotification.Name = NSNotification.Name(rawValue: "guidePageClose")
} }
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