Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
P
PhoneManager
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Yang
PhoneManager
Commits
4ae9f650
Commit
4ae9f650
authored
Apr 18, 2025
by
CZ1004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
广告接入
parent
feb0a33c
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
823 additions
and
126 deletions
+823
-126
Contents.json
PhoneManager/Assets.xcassets/Adv/Contents.json
+6
-0
Contents.json
...ager/Assets.xcassets/Adv/ic_ad_pop.imageset/Contents.json
+23
-0
ic_ad_pop.png
...ager/Assets.xcassets/Adv/ic_ad_pop.imageset/ic_ad_pop.png
+0
-0
ic_ad_pop@2x.png
...r/Assets.xcassets/Adv/ic_ad_pop.imageset/ic_ad_pop@2x.png
+0
-0
ic_ad_pop@3x.png
...r/Assets.xcassets/Adv/ic_ad_pop.imageset/ic_ad_pop@3x.png
+0
-0
Contents.json
...ger/Assets.xcassets/Adv/ic_gift_ad.imageset/Contents.json
+23
-0
ic_gift_ad.png
...er/Assets.xcassets/Adv/ic_gift_ad.imageset/ic_gift_ad.png
+0
-0
ic_gift_ad@2x.png
...Assets.xcassets/Adv/ic_gift_ad.imageset/ic_gift_ad@2x.png
+0
-0
ic_gift_ad@3x.png
...Assets.xcassets/Adv/ic_gift_ad.imageset/ic_gift_ad@3x.png
+0
-0
Contents.json
...xcassets/Adv/icon_close_pop_purple.imageset/Contents.json
+23
-0
icon_close_pop_purple.png
.../icon_close_pop_purple.imageset/icon_close_pop_purple.png
+0
-0
icon_close_pop_purple@2x.png
...on_close_pop_purple.imageset/icon_close_pop_purple@2x.png
+0
-0
icon_close_pop_purple@3x.png
...on_close_pop_purple.imageset/icon_close_pop_purple@3x.png
+0
-0
Contents.json
...s.xcassets/Charge/img_bj_battery 1.imageset/Contents.json
+0
-0
img_bj_battery.png
...ssets/Charge/img_bj_battery 1.imageset/img_bj_battery.png
+0
-0
img_bj_battery@2x.png
...ts/Charge/img_bj_battery 1.imageset/img_bj_battery@2x.png
+0
-0
img_bj_battery@3x.png
...ts/Charge/img_bj_battery 1.imageset/img_bj_battery@3x.png
+0
-0
AdvManager.swift
PhoneManager/Class/Session/Advertisement/AdvManager.swift
+0
-84
AdvViewController.swift
...nager/Class/Session/Advertisement/AdvViewController.swift
+0
-32
AdvTipDeleteController.swift
...ion/Advertisement/Controller/AdvTipDeleteController.swift
+290
-0
AdvTipSelectController.swift
...ion/Advertisement/Controller/AdvTipSelectController.swift
+217
-0
AdvManager.swift
...ager/Class/Session/Advertisement/Manager/AdvManager.swift
+141
-0
HomeInfoViewController.swift
...lass/Session/Home/Controller/HomeInfoViewController.swift
+20
-3
HomeViewController.swift
...er/Class/Session/Home/Controller/HomeViewController.swift
+19
-0
NetStatusManager.swift
.../Class/Tool/Class/NetStatusManager/NetStatusManager.swift
+0
-2
GlobalConfig.swift
PhoneManager/Class/Tool/Common/GlobalConfig.swift
+14
-0
Singleton.swift
PhoneManager/Class/Tool/Singleton/Singleton.swift
+47
-5
No files found.
PhoneManager/Assets.xcassets/Adv/Contents.json
0 → 100644
View file @
4ae9f650
{
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
PhoneManager/Assets.xcassets/Adv/ic_ad_pop.imageset/Contents.json
0 → 100644
View file @
4ae9f650
{
"images"
:
[
{
"filename"
:
"ic_ad_pop.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"filename"
:
"ic_ad_pop@2x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"filename"
:
"ic_ad_pop@3x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
PhoneManager/Assets.xcassets/Adv/ic_ad_pop.imageset/ic_ad_pop.png
0 → 100644
View file @
4ae9f650
865 Bytes
PhoneManager/Assets.xcassets/Adv/ic_ad_pop.imageset/ic_ad_pop@2x.png
0 → 100644
View file @
4ae9f650
1.62 KB
PhoneManager/Assets.xcassets/Adv/ic_ad_pop.imageset/ic_ad_pop@3x.png
0 → 100644
View file @
4ae9f650
2.2 KB
PhoneManager/Assets.xcassets/Adv/ic_gift_ad.imageset/Contents.json
0 → 100644
View file @
4ae9f650
{
"images"
:
[
{
"filename"
:
"ic_gift_ad.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"filename"
:
"ic_gift_ad@2x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"filename"
:
"ic_gift_ad@3x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
PhoneManager/Assets.xcassets/Adv/ic_gift_ad.imageset/ic_gift_ad.png
0 → 100644
View file @
4ae9f650
17.8 KB
PhoneManager/Assets.xcassets/Adv/ic_gift_ad.imageset/ic_gift_ad@2x.png
0 → 100644
View file @
4ae9f650
52.3 KB
PhoneManager/Assets.xcassets/Adv/ic_gift_ad.imageset/ic_gift_ad@3x.png
0 → 100644
View file @
4ae9f650
84.6 KB
PhoneManager/Assets.xcassets/Adv/icon_close_pop_purple.imageset/Contents.json
0 → 100644
View file @
4ae9f650
{
"images"
:
[
{
"filename"
:
"icon_close_pop_purple.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"filename"
:
"icon_close_pop_purple@2x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"filename"
:
"icon_close_pop_purple@3x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
PhoneManager/Assets.xcassets/Adv/icon_close_pop_purple.imageset/icon_close_pop_purple.png
0 → 100644
View file @
4ae9f650
1.34 KB
PhoneManager/Assets.xcassets/Adv/icon_close_pop_purple.imageset/icon_close_pop_purple@2x.png
0 → 100644
View file @
4ae9f650
2.87 KB
PhoneManager/Assets.xcassets/Adv/icon_close_pop_purple.imageset/icon_close_pop_purple@3x.png
0 → 100644
View file @
4ae9f650
3.33 KB
PhoneManager/Assets.xcassets/
img_bj_battery
.imageset/Contents.json
→
PhoneManager/Assets.xcassets/
Charge/img_bj_battery 1
.imageset/Contents.json
View file @
4ae9f650
File moved
PhoneManager/Assets.xcassets/
img_bj_battery
.imageset/img_bj_battery.png
→
PhoneManager/Assets.xcassets/
Charge/img_bj_battery 1
.imageset/img_bj_battery.png
View file @
4ae9f650
File moved
PhoneManager/Assets.xcassets/
img_bj_battery
.imageset/img_bj_battery@2x.png
→
PhoneManager/Assets.xcassets/
Charge/img_bj_battery 1
.imageset/img_bj_battery@2x.png
View file @
4ae9f650
File moved
PhoneManager/Assets.xcassets/
img_bj_battery
.imageset/img_bj_battery@3x.png
→
PhoneManager/Assets.xcassets/
Charge/img_bj_battery 1
.imageset/img_bj_battery@3x.png
View file @
4ae9f650
File moved
PhoneManager/Class/Session/Advertisement/AdvManager.swift
deleted
100644 → 0
View file @
feb0a33c
//
// AdvManager.swift
// PhoneManager
//
// Created by edy on 2025/4/17.
//
import
Foundation
import
GoogleMobileAds
import
UserMessagingPlatform
class
AdvManager
:
NSObject
,
FullScreenContentDelegate
{
static
let
shared
:
AdvManager
=
AdvManager
()
var
rewardedInterstitialAd
:
RewardedInterstitialAd
?
/// 能请求广告
var
canRequestAds
:
Bool
{
return
ConsentInformation
.
shared
.
canRequestAds
}
// 是否有权限
var
isPrivacyOptionsRequired
:
Bool
{
return
ConsentInformation
.
shared
.
privacyOptionsRequirementStatus
==
.
required
}
/// 初始化SDK
func
initAdertisementSDK
()
{
// Initialize the Google Mobile Ads SDK.
MobileAds
.
shared
.
start
()
// Request an ad.
Task
{
await
self
.
loadRewardedInterstitialAd
()
}
}
func
loadRewardedInterstitialAd
()
async
{
do
{
rewardedInterstitialAd
=
try
await
RewardedInterstitialAd
.
load
(
with
:
"ca-app-pub-3940256099942544/6978759866"
,
request
:
Request
())
rewardedInterstitialAd
?
.
fullScreenContentDelegate
=
self
}
catch
{
print
(
"Failed to load rewarded interstitial ad with error:
\(
error
.
localizedDescription
)
"
)
}
}
/// 开始显示
/// - Parameter completed: 准备完成后回调
func
showRewardedInterstitialAd
(
vc
:
UIViewController
)
{
guard
let
ad
=
self
.
rewardedInterstitialAd
else
{
print
(
"Ad wasn't ready"
)
return
}
ad
.
present
(
from
:
vc
)
{
let
reward
=
ad
.
adReward
print
(
"Reward received with currency
\(
reward
.
amount
)
, amount
\(
reward
.
amount
.
doubleValue
)
"
)
}
}
// MARK: - GADFullScreenContentDelegate
func
adWillPresentFullScreenContent
(
_
ad
:
FullScreenPresentingAd
)
{
print
(
"Ad did present full screen content."
)
}
func
ad
(
_
ad
:
FullScreenPresentingAd
,
didFailToPresentFullScreenContentWithError
error
:
Error
)
{
print
(
"Ad failed to present full screen content with error
\(
error
.
localizedDescription
)
."
)
self
.
rewardedInterstitialAd
=
nil
}
func
adDidDismissFullScreenContent
(
_
ad
:
FullScreenPresentingAd
)
{
print
(
"Ad did dismiss full screen content."
)
self
.
rewardedInterstitialAd
=
nil
// Task {
// await self.loadRewardedInterstitialAd()
// }
}
}
PhoneManager/Class/Session/Advertisement/AdvViewController.swift
deleted
100644 → 0
View file @
feb0a33c
//
// AdvViewController.swift
// PhoneManager
//
// Created by edy on 2025/4/17.
//
import
Foundation
import
GoogleMobileAds
import
GoogleMobileAds
class
AdvViewController
:
UIViewController
{
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
}
override
func
viewDidAppear
(
_
animated
:
Bool
)
{
super
.
viewDidAppear
(
animated
)
AdvManager
.
shared
.
showRewardedInterstitialAd
(
vc
:
self
)
}
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
super
.
viewWillAppear
(
animated
)
self
.
view
.
isUserInteractionEnabled
=
true
}
}
PhoneManager/Class/Session/Advertisement/Controller/AdvTipDeleteController.swift
0 → 100644
View file @
4ae9f650
//
// AdvTipDeleteController.swift
// PhoneManager
//
// Created by edy on 2025/4/18.
//
import
Foundation
enum
TipDeleteType
{
case
deletePhotosMore
case
deletePhotoOne
case
deleteVideosMore
case
deleteVideoOne
}
struct
AdvTipModel
{
let
titleText
:
String
let
detailTitleText
:
String
let
showLessButton
:
Bool
let
deleteMoreText
:
String
let
deleteLessText
:
String
init
(
titleText
:
String
,
detailTitleText
:
String
,
showLessButton
:
Bool
,
deleteMoreText
:
String
,
deleteLessText
:
String
)
{
self
.
titleText
=
titleText
self
.
detailTitleText
=
detailTitleText
self
.
showLessButton
=
showLessButton
self
.
deleteMoreText
=
deleteMoreText
self
.
deleteLessText
=
deleteLessText
}
}
class
AdvTipDeleteController
:
BaseViewController
{
var
deleteType
:
TipDeleteType
?
// getOtherInfoByType()
var
dataSource
:
[
AssetModel
]?
// UIView.transition(with: self.collectionView, duration: 0.3, options: .transitionCrossDissolve, animations: {
// self.collectionView.reloadData()
// }, completion: nil)
var
tipDeleteModel
:
AdvTipModel
?
// {
// didSet{
// DispatchQueue.main.async {
// self.tipTitle.text = self.tipDeleteModel.titleText
// self.tipDetailTitle.text = self.tipDeleteModel.detailTitleText
// self.deleteMoreButton.setTitle(self.tipDeleteModel.deleteMoreText, for: .normal)
// self.deleteLessButton.setTitle(self.tipDeleteModel.deleteLessText, for: .normal)
// }
// }
// }
lazy
var
shadowView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0
,
blue
:
0
,
alpha
:
0.5000
)
return
view
}()
lazy
var
tipView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
.
white
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
12
return
view
}()
lazy
var
closeButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
setImage
(
UIImage
(
named
:
"icon_close_pop_purple"
),
for
:
.
normal
)
view
.
addTarget
(
self
,
action
:
#selector(
closeButtonAction
)
,
for
:
.
touchUpInside
)
return
view
}()
lazy
var
tipTitle
:
UILabel
=
{
let
view
=
UILabel
()
view
.
numberOfLines
=
0
view
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
view
.
textColor
=
UIColor
(
red
:
0.1
,
green
:
0.1
,
blue
:
0.1
,
alpha
:
1
)
return
view
}()
lazy
var
tipDetailTitle
:
UILabel
=
{
let
view
=
UILabel
()
view
.
numberOfLines
=
0
view
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
regular
)
view
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
return
view
}()
lazy
var
collectionView
:
UICollectionView
=
{
let
layout
=
UICollectionViewFlowLayout
()
layout
.
scrollDirection
=
.
horizontal
layout
.
minimumInteritemSpacing
=
8
layout
.
minimumLineSpacing
=
0
let
collectionView
=
UICollectionView
(
frame
:
.
zero
,
collectionViewLayout
:
layout
)
collectionView
.
dataSource
=
self
collectionView
.
delegate
=
self
collectionView
.
register
(
ImageCell
.
self
,
forCellWithReuseIdentifier
:
ImageCell
.
reuseIdentifier
)
collectionView
.
showsHorizontalScrollIndicator
=
false
collectionView
.
backgroundColor
=
.
clear
return
collectionView
}()
lazy
var
deleteMoreButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
view
.
setTitleColor
(
.
white
,
for
:
.
normal
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
24
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
return
view
}()
lazy
var
deleteLessButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
backgroundColor
=
.
clear
view
.
setTitleColor
(
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
),
for
:
.
normal
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
24
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
return
view
}()
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
self
.
view
.
addSubview
(
shadowView
)
self
.
shadowView
.
addSubview
(
self
.
tipView
)
self
.
tipView
.
addSubview
(
self
.
closeButton
)
self
.
tipView
.
addSubview
(
self
.
tipTitle
)
self
.
tipView
.
addSubview
(
self
.
tipDetailTitle
)
self
.
tipView
.
addSubview
(
self
.
collectionView
)
self
.
tipView
.
addSubview
(
self
.
deleteMoreButton
)
self
.
tipView
.
addSubview
(
self
.
deleteLessButton
)
self
.
shadowView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
top
.
bottom
.
equalToSuperview
()
}
self
.
tipView
.
snp
.
makeConstraints
{
make
in
make
.
center
.
equalToSuperview
()
make
.
width
.
equalTo
(
345
)
make
.
height
.
equalTo
(
410
)
}
self
.
closeButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
20
)
make
.
right
.
equalTo
(
-
20
)
make
.
width
.
height
.
equalTo
(
28
)
}
self
.
tipTitle
.
snp
.
makeConstraints
{
make
in
make
.
centerX
.
equalToSuperview
()
make
.
width
.
equalTo
(
229
)
make
.
height
.
equalTo
(
56
)
make
.
top
.
equalToSuperview
()
.
offset
(
52
)
}
self
.
tipDetailTitle
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
tipTitle
.
snp
.
bottom
)
.
offset
(
8
)
make
.
width
.
equalTo
(
305
)
make
.
height
.
equalTo
(
40
)
make
.
centerX
.
equalToSuperview
()
}
self
.
collectionView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
equalToSuperview
()
make
.
top
.
equalTo
(
self
.
tipDetailTitle
.
snp
.
bottom
)
.
offset
(
16
)
make
.
height
.
equalTo
(
104
)
}
self
.
deleteMoreButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
collectionView
.
snp
.
bottom
)
.
offset
(
16
)
make
.
width
.
equalTo
(
305
)
make
.
height
.
equalTo
(
48
)
make
.
centerX
.
equalToSuperview
()
}
self
.
deleteMoreButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
deleteMoreButton
.
snp
.
bottom
)
.
offset
(
4
)
make
.
width
.
equalTo
(
305
)
make
.
height
.
equalTo
(
48
)
make
.
centerX
.
equalToSuperview
()
}
}
}
class
ImageCell
:
UICollectionViewCell
{
static
let
reuseIdentifier
=
"ImageCell"
let
imageView
:
UIImageView
=
{
let
imageView
=
UIImageView
()
imageView
.
contentMode
=
.
scaleAspectFill
imageView
.
clipsToBounds
=
true
imageView
.
layer
.
cornerRadius
=
12
return
imageView
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
contentView
.
addSubview
(
imageView
)
imageView
.
frame
=
contentView
.
bounds
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
extension
AdvTipDeleteController
:
UICollectionViewDataSource
,
UICollectionViewDelegateFlowLayout
{
func
getOtherInfoByType
()
{
// 首先获取第一个button显示的内容
let
photosCount
=
self
.
dataSource
!.
count
>
25
?
25
:
self
.
dataSource
?
.
count
let
deleteButtonTitle
=
"Delete
\(
String
(
describing
:
photosCount
)
)
Duplicates"
switch
self
.
deleteType
{
case
.
deletePhotosMore
:
self
.
tipDeleteModel
=
AdvTipModel
.
init
(
titleText
:
"Watch a rewarded ad to delete photos"
,
detailTitleText
:
"You need to watch an ad to delete 25 photos with the free version."
,
showLessButton
:
true
,
deleteMoreText
:
deleteButtonTitle
,
deleteLessText
:
"Delete Only 5 Photos"
)
case
.
deletePhotoOne
:
self
.
tipDeleteModel
=
AdvTipModel
.
init
(
titleText
:
"Watch a rewarded ad to delete photos"
,
detailTitleText
:
"You need to watch an ad to delete 25 photos with the free version."
,
showLessButton
:
false
,
deleteMoreText
:
deleteButtonTitle
,
deleteLessText
:
""
)
case
.
deleteVideosMore
:
self
.
tipDeleteModel
=
AdvTipModel
.
init
(
titleText
:
"Watch a rewarded ad to delete videos"
,
detailTitleText
:
"You need to watch an ad to delete 25 videos with the free version."
,
showLessButton
:
true
,
deleteMoreText
:
deleteButtonTitle
,
deleteLessText
:
"Delete Only 5 Photos"
)
case
.
deleteVideoOne
:
self
.
tipDeleteModel
=
AdvTipModel
.
init
(
titleText
:
"Watch a rewarded ad to delete videos"
,
detailTitleText
:
"You need to watch an ad to delete 25 videos with the free version."
,
showLessButton
:
false
,
deleteMoreText
:
deleteButtonTitle
,
deleteLessText
:
""
)
case
.
none
:
self
.
tipDeleteModel
=
AdvTipModel
.
init
(
titleText
:
""
,
detailTitleText
:
""
,
showLessButton
:
false
,
deleteMoreText
:
deleteButtonTitle
,
deleteLessText
:
""
)
}
}
func
collectionView
(
_
collectionView
:
UICollectionView
,
numberOfItemsInSection
section
:
Int
)
->
Int
{
return
dataSource
!.
count
}
func
collectionView
(
_
collectionView
:
UICollectionView
,
cellForItemAt
indexPath
:
IndexPath
)
->
UICollectionViewCell
{
let
cell
=
collectionView
.
dequeueReusableCell
(
withReuseIdentifier
:
ImageCell
.
reuseIdentifier
,
for
:
indexPath
)
as!
ImageCell
cell
.
imageView
.
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
self
.
dataSource
!
[
indexPath
.
item
]
.
localIdentifier
)
return
cell
}
func
collectionView
(
_
collectionView
:
UICollectionView
,
layout
collectionViewLayout
:
UICollectionViewLayout
,
sizeForItemAt
indexPath
:
IndexPath
)
->
CGSize
{
return
CGSize
(
width
:
104
,
height
:
104
)
}
@objc
func
closeButtonAction
(){
self
.
dismiss
(
animated
:
false
)
}
}
PhoneManager/Class/Session/Advertisement/Controller/AdvTipSelectController.swift
0 → 100644
View file @
4ae9f650
//
// AdvTipSelectController.swift
// PhoneManager
//
// Created by edy on 2025/4/18.
//
import
Foundation
enum
TipSelectType
{
case
selectTypeCompressVideo
case
selectTypeCompressPhoto
case
selectTypeSetAnimation
}
struct
AdvTipSelectModel
{
let
titleText
:
String
let
detailTitleText
:
String
let
deleteMoreText
:
String
let
deleteLessText
:
String
init
(
titleText
:
String
,
detailTitleText
:
String
,
deleteMoreText
:
String
,
deleteLessText
:
String
)
{
self
.
titleText
=
titleText
self
.
detailTitleText
=
detailTitleText
self
.
deleteMoreText
=
deleteMoreText
self
.
deleteLessText
=
deleteLessText
}
}
class
AdvTipSelectController
:
UIViewController
{
@MainActor
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
var
selectType
:
TipSelectType
{
didSet
{
getOtherInfoByType
()
}
}
var
tipSelectModel
:
AdvTipSelectModel
{
didSet
{
DispatchQueue
.
main
.
async
{
self
.
tipTitle
.
text
=
self
.
tipSelectModel
.
titleText
self
.
tipDetailTitle
.
text
=
self
.
tipSelectModel
.
detailTitleText
self
.
firstButton
.
setTitle
(
self
.
tipSelectModel
.
deleteMoreText
,
for
:
.
normal
)
self
.
secondButton
.
setTitle
(
self
.
tipSelectModel
.
deleteLessText
,
for
:
.
normal
)
}
}
}
lazy
var
shadowView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0
,
blue
:
0
,
alpha
:
0.5000
)
return
view
}()
lazy
var
tipView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
.
white
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
12
return
view
}()
lazy
var
closeButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
setImage
(
UIImage
(
named
:
"icon_close_pop_purple"
),
for
:
.
normal
)
view
.
addTarget
(
self
,
action
:
#selector(
closeButtonAction
)
,
for
:
.
touchUpInside
)
return
view
}()
lazy
var
logoView
:
UIImageView
=
{
let
view
=
UIImageView
()
view
.
image
=
UIImage
(
named
:
"ic_gift_ad"
)
return
view
}()
lazy
var
tipTitle
:
UILabel
=
{
let
view
=
UILabel
()
view
.
numberOfLines
=
0
view
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
view
.
textColor
=
UIColor
(
red
:
0.1
,
green
:
0.1
,
blue
:
0.1
,
alpha
:
1
)
return
view
}()
lazy
var
tipDetailTitle
:
UILabel
=
{
let
view
=
UILabel
()
view
.
numberOfLines
=
0
view
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
regular
)
view
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
return
view
}()
lazy
var
firstButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
view
.
setTitleColor
(
.
white
,
for
:
.
normal
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
24
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
return
view
}()
lazy
var
secondButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
backgroundColor
=
.
clear
view
.
setTitleColor
(
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
),
for
:
.
normal
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
24
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
return
view
}()
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
self
.
view
.
addSubview
(
shadowView
)
self
.
shadowView
.
addSubview
(
self
.
tipView
)
self
.
tipView
.
addSubview
(
self
.
closeButton
)
self
.
tipView
.
addSubview
(
self
.
logoView
)
self
.
tipView
.
addSubview
(
self
.
tipTitle
)
self
.
tipView
.
addSubview
(
self
.
tipDetailTitle
)
self
.
tipView
.
addSubview
(
self
.
firstButton
)
self
.
tipView
.
addSubview
(
self
.
secondButton
)
self
.
shadowView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
top
.
bottom
.
equalToSuperview
()
}
self
.
tipView
.
snp
.
makeConstraints
{
make
in
make
.
center
.
equalToSuperview
()
make
.
width
.
equalTo
(
345
)
make
.
height
.
equalTo
(
432
)
}
self
.
closeButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
20
)
make
.
right
.
equalTo
(
-
20
)
make
.
width
.
height
.
equalTo
(
28
)
}
self
.
logoView
.
snp
.
makeConstraints
{
make
in
make
.
centerX
.
equalToSuperview
()
make
.
top
.
equalTo
(
52
)
make
.
width
.
equalTo
(
197
)
make
.
height
.
equalTo
(
126
)
}
self
.
tipTitle
.
snp
.
makeConstraints
{
make
in
make
.
centerX
.
equalToSuperview
()
make
.
width
.
equalTo
(
229
)
make
.
height
.
equalTo
(
56
)
make
.
top
.
equalTo
(
self
.
logoView
.
snp
.
bottom
)
.
offset
(
16
)
}
self
.
tipDetailTitle
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
tipTitle
.
snp
.
bottom
)
.
offset
(
8
)
make
.
width
.
equalTo
(
305
)
make
.
height
.
equalTo
(
40
)
make
.
centerX
.
equalToSuperview
()
}
self
.
firstButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
tipDetailTitle
.
snp
.
bottom
)
.
offset
(
16
)
make
.
width
.
equalTo
(
305
)
make
.
height
.
equalTo
(
48
)
make
.
centerX
.
equalToSuperview
()
}
self
.
secondButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
firstButton
.
snp
.
bottom
)
.
offset
(
4
)
make
.
width
.
equalTo
(
305
)
make
.
height
.
equalTo
(
48
)
make
.
centerX
.
equalToSuperview
()
}
}
}
extension
AdvTipSelectController
{
func
getOtherInfoByType
()
{
switch
self
.
selectType
{
case
.
selectTypeCompressVideo
:
self
.
tipSelectModel
=
AdvTipSelectModel
.
init
(
titleText
:
"Watch a rewarded ad to compress your video"
,
detailTitleText
:
"You need to watch an ad to compress your video with the free version."
,
deleteMoreText
:
"Compress"
,
deleteLessText
:
"Cancel"
)
case
.
selectTypeCompressPhoto
:
self
.
tipSelectModel
=
AdvTipSelectModel
.
init
(
titleText
:
"Watch a rewarded ad to compress your photo"
,
detailTitleText
:
"You need to watch an ad to compress your photo with the free version."
,
deleteMoreText
:
"Compress"
,
deleteLessText
:
"Cancel"
)
case
.
selectTypeSetAnimation
:
self
.
tipSelectModel
=
AdvTipSelectModel
.
init
(
titleText
:
"Watch a rewarded ad to set Pro Animations"
,
detailTitleText
:
"You need to watch an ad to set amazing animations that are unlimited for pro users."
,
deleteMoreText
:
"Set Animation"
,
deleteLessText
:
"Cancel"
)
}
}
@objc
func
closeButtonAction
(){
self
.
view
.
removeFromSuperview
()
}
}
PhoneManager/Class/Session/Advertisement/Manager/AdvManager.swift
0 → 100644
View file @
4ae9f650
//
// AdvManager.swift
// PhoneManager
//
// Created by edy on 2025/4/17.
//
import
Foundation
import
GoogleMobileAds
import
UserMessagingPlatform
class
AdvManager
:
NSObject
,
FullScreenContentDelegate
{
static
let
shared
:
AdvManager
=
AdvManager
()
// 激励插页广告
var
rewardedInterstitialAd
:
RewardedInterstitialAd
?
// 插页广告
var
interstitial
:
InterstitialAd
?
/// 默认每日免费删除次数
let
defaultFreeTimes
:
Int
=
3
/// 广告策略 第一次可删除5张,第二次可删除5张,第三次可删除4张
let
advDeleteResouceDic
:
[
Int
:
Int
]
=
[
3
:
5
,
2
:
5
,
1
:
4
]
// 进入页面之后30秒
var
advTimeAfterInAPP
:
Int
=
30
var
timer
:
Timer
?
/// 能请求广告
var
canRequestAds
:
Bool
{
return
ConsentInformation
.
shared
.
canRequestAds
}
// 是否有权限
var
isPrivacyOptionsRequired
:
Bool
{
return
ConsentInformation
.
shared
.
privacyOptionsRequirementStatus
==
.
required
}
/// 初始化SDK
func
initAdertisementSDK
()
{
// Initialize the Google Mobile Ads SDK.
MobileAds
.
shared
.
start
()
// Request an ad.
Task
{
// 同时load两个广告内容
await
self
.
loadInterstitial
()
await
self
.
loadRewardedInterstitialAd
()
}
}
/// 获取激励插页广告
func
loadRewardedInterstitialAd
()
async
{
do
{
rewardedInterstitialAd
=
try
await
RewardedInterstitialAd
.
load
(
with
:
"ca-app-pub-3940256099942544/6978759866"
,
request
:
Request
())
rewardedInterstitialAd
?
.
fullScreenContentDelegate
=
self
}
catch
{
print
(
"Failed to load rewarded interstitial ad with error:
\(
error
.
localizedDescription
)
"
)
}
}
/// 获取单纯的插页广告
fileprivate
func
loadInterstitial
()
async
{
do
{
interstitial
=
try
await
InterstitialAd
.
load
(
// fixme: 需要更改这个值
with
:
"ca-app-pub-3940256099942544/4411468910"
,
request
:
Request
())
interstitial
?
.
fullScreenContentDelegate
=
self
}
catch
{
print
(
"Failed to load interstitial ad with error:
\(
error
.
localizedDescription
)
"
)
}
}
/// 开始显示
/// - Parameter completed: 准备完成后回调
func
showRewardedInterstitialAd
(
vc
:
UIViewController
)
{
guard
let
ad
=
self
.
rewardedInterstitialAd
else
{
// 这里如果还没有,则弹出框
let
alert
=
UIAlertController
(
title
:
nil
,
message
:
"Ad wasn't ready"
,
preferredStyle
:
.
alert
)
vc
.
present
(
alert
,
animated
:
true
,
completion
:
nil
)
// 1 秒后关闭弹窗
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
alert
.
dismiss
(
animated
:
true
,
completion
:
nil
)
}
return
}
ad
.
present
(
from
:
vc
)
{}
}
/// 开始显示
/// - Parameter completed: 准备完成后回调
func
showInterstitialAd
(
vc
:
UIViewController
)
{
guard
let
ad
=
self
.
interstitial
else
{
self
.
showRewardedInterstitialAd
(
vc
:
vc
)
return
}
ad
.
present
(
from
:
vc
)
}
// MARK: - GADFullScreenContentDelegate
func
adWillPresentFullScreenContent
(
_
ad
:
FullScreenPresentingAd
)
{
print
(
"Ad did present full screen content."
)
}
func
ad
(
_
ad
:
FullScreenPresentingAd
,
didFailToPresentFullScreenContentWithError
error
:
Error
)
{
print
(
"Ad failed to present full screen content with error
\(
error
.
localizedDescription
)
."
)
self
.
rewardedInterstitialAd
=
nil
}
func
adDidDismissFullScreenContent
(
_
ad
:
FullScreenPresentingAd
)
{
print
(
"Ad did dismiss full screen content."
)
self
.
rewardedInterstitialAd
=
nil
// 广告结束之后缓存新的
Task
{
// 同时load两个广告内容
await
self
.
loadInterstitial
()
await
self
.
loadRewardedInterstitialAd
()
}
// 更新值
updateAdvStrategyValue
()
}
/// 广告结束之后重置策略信息
func
updateAdvStrategyValue
()
{
// 设置第二次等待时间15秒,15秒之内点击任何菜单不弹广告
AdvManager
.
shared
.
advTimeAfterInAPP
=
15
Singleton
.
shared
.
startCountdown
{}
}
}
PhoneManager/Class/Session/Home/Controller/HomeInfoViewController.swift
View file @
4ae9f650
...
...
@@ -58,7 +58,6 @@ class HomeInfoViewController:BaseViewController {
sview
.
deleteCallBack
=
{
[
weak
self
]
array
in
guard
let
self
=
self
else
{
return
}
let
deleteOp
:((
Any
)
->
Void
)
=
{[
weak
self
]
imgs
in
if
let
cA
=
imgs
as?
[
AssetModel
]
{
var
tempStringArray
:
[
String
]
=
[]
...
...
@@ -92,14 +91,25 @@ class HomeInfoViewController:BaseViewController {
}
}
func
popAdvertisement
(
array
:[
AssetModel
]){
// 跳弹窗
let
vc
:
AdvTipDeleteController
=
AdvTipDeleteController
()
// fixme:继续广告逻辑
}
if
HomePayModel
.
share
.
isNoAd
==
false
{
if
self
.
type
==
.
duplicates
{
// 重复
// 重复
if
self
.
type
==
.
duplicates
{
HomePayViewController
.
show
{
deleteOp
(
array
)
}
}
else
if
self
.
type
==
.
similar
{
// 相似
}
else
if
self
.
type
==
.
similar
{
// 相似
HomeNoAdsViewController
.
show
{
deleteOp
(
array
)
}
...
...
@@ -129,6 +139,13 @@ class HomeInfoViewController:BaseViewController {
super
.
init
(
nibName
:
nil
,
bundle
:
nil
)
}
/// 弹出广告
func
popAdverTisement
(){
if
AdvManager
.
shared
.
advTimeAfterInAPP
<=
0
{
AdvManager
.
shared
.
showInterstitialAd
(
vc
:
self
)
}
}
// 由于继承自 UIViewController,必须实现这个必需的构造器
required
init
?(
coder
:
NSCoder
)
{
super
.
init
(
coder
:
coder
)
...
...
PhoneManager/Class/Session/Home/Controller/HomeViewController.swift
View file @
4ae9f650
...
...
@@ -58,6 +58,9 @@ class HomeViewController:BaseViewController {
homeView
?
.
titleCallBack
=
{[
weak
self
]
model
,
type
in
guard
let
self
else
{
return
}
self
.
popAdverTisement
()
DispatchQueue
.
main
.
async
{
let
vc
:
HomeInfoViewController
=
HomeInfoViewController
(
ids
:
model
.
assets
,
type
:
type
,
titleText
:
model
.
folderName
)
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
...
...
@@ -66,6 +69,7 @@ class HomeViewController:BaseViewController {
homeView
?
.
otherItemCallBack
=
{[
weak
self
]
model
,
otherItemRow
in
guard
let
self
else
{
return
}
self
.
popAdverTisement
()
if
otherItemRow
==
0
{
DispatchQueue
.
main
.
async
{
let
vc
:
HomeVideoDetailController
=
HomeVideoDetailController
(
model
:
model
)
...
...
@@ -102,12 +106,16 @@ class HomeViewController:BaseViewController {
}
}
homeView
?
.
indexCallBack
=
{[
weak
self
]
index
in
guard
let
self
else
{
return
}
if
let
cIndex
=
index
as?
Int
{
// 先走广告策略
popAdverTisement
()
switch
cIndex
{
case
0
:
...
...
@@ -146,6 +154,14 @@ class HomeViewController:BaseViewController {
}
/// 弹出广告
func
popAdverTisement
(){
if
AdvManager
.
shared
.
advTimeAfterInAPP
<=
0
{
AdvManager
.
shared
.
showInterstitialAd
(
vc
:
self
)
}
}
override
func
addViews
()
{
...
...
@@ -233,6 +249,9 @@ class HomeViewController:BaseViewController {
}
}
}
// 开启定时器
Singleton
.
shared
.
startCountdown
{}
}
// 重复图片
...
...
PhoneManager/Class/Tool/Class/NetStatusManager/NetStatusManager.swift
View file @
4ae9f650
...
...
@@ -27,9 +27,7 @@ class NetStatusManager: NSObject {
monitor
.
pathUpdateHandler
=
{
path
in
if
path
.
status
==
.
satisfied
{
Print
(
"网络连接正常"
)
if
path
.
isExpensive
{
self
.
currentStatus
=
.
WWAN
netStatus
(
.
WWAN
)
...
...
PhoneManager/Class/Tool/Common/GlobalConfig.swift
0 → 100644
View file @
4ae9f650
//
// GlobalConfig.swift
// PhoneManager
//
// Created by edy on 2025/4/18.
//
import
Foundation
struct
GlobalConfig
{
/// 广告SDK的KEY
static
let
advSDKKey
=
"ca-app-pub-3940256099942544/4411468910"
}
PhoneManager/Class/Tool/Singleton/Singleton.swift
View file @
4ae9f650
...
...
@@ -16,13 +16,55 @@ class Singleton {
var
resourceModel
:
[
ResourceModel
]
=
[]
// 当日的免费次数
var
advFreeTimes
:
Int
=
{
// 获取存储的时间
let
saveTime
=
UserDefaults
.
standard
.
object
(
forKey
:
"saveTime"
)
if
saveTime
==
nil
{
UserDefaults
.
standard
.
set
(
Date
(),
forKey
:
"saveTime"
)
UserDefaults
.
standard
.
set
(
AdvManager
.
shared
.
defaultFreeTimes
,
forKey
:
"saveAdvTimes"
)
return
AdvManager
.
shared
.
defaultFreeTimes
}
else
{
// 判断时间是不是同一天
let
calendar
=
Calendar
.
current
let
isSameDay
=
calendar
.
isDate
(
saveTime
as!
Date
,
inSameDayAs
:
Date
())
if
isSameDay
{
// 如果是同一天
var
times
=
UserDefaults
.
standard
.
object
(
forKey
:
"saveAdvTimes"
)
as!
Int
if
times
>
0
{
// 如果免费次数大于0
times
=
times
-
1
UserDefaults
.
standard
.
set
(
times
,
forKey
:
"saveAdvTimes"
)
}
// 如果等于0 那啥也不做
return
times
}
else
{
// 如果不是同一天,重置次数
UserDefaults
.
standard
.
set
(
Date
(),
forKey
:
"saveTime"
)
UserDefaults
.
standard
.
set
(
AdvManager
.
shared
.
defaultFreeTimes
,
forKey
:
"saveAdvTimes"
)
return
AdvManager
.
shared
.
defaultFreeTimes
}
}
}()
// 进入页面之后30秒
var
thirtySecondsAfterInAPP
:
Bool
=
false
func
startCountdown
(
completion
:
@escaping
()
->
Void
)
{
AdvManager
.
shared
.
timer
=
Timer
.
scheduledTimer
(
withTimeInterval
:
1
,
repeats
:
true
)
{
[
weak
self
]
_
in
guard
self
!=
nil
else
{
return
}
if
AdvManager
.
shared
.
advTimeAfterInAPP
>
0
{
AdvManager
.
shared
.
advTimeAfterInAPP
-=
1
}
else
{
AdvManager
.
shared
.
timer
?
.
invalidate
()
completion
()
}
}
}
func
stopCountdown
()
{
AdvManager
.
shared
.
timer
?
.
invalidate
()
}
// 广告(当上一次广告结束之后需要重新请求下下次广告的内容)
var
rewardedInterstitialAd
:
RewardedInterstitialAd
?
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment