B面1.1.1 优化以及功能扩展
This commit is contained in:
parent
130fefd189
commit
d3d3da4f6e
@ -232,11 +232,18 @@
|
|||||||
CBC2D6F82BFDF3D800E17703 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6F72BFDF3D800E17703 /* Assets.xcassets */; };
|
CBC2D6F82BFDF3D800E17703 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6F72BFDF3D800E17703 /* Assets.xcassets */; };
|
||||||
CBC2D6FB2BFDF3D800E17703 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6FA2BFDF3D800E17703 /* Base */; };
|
CBC2D6FB2BFDF3D800E17703 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6FA2BFDF3D800E17703 /* Base */; };
|
||||||
CBC2D7D42BFDF4B900E17703 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */; };
|
CBC2D7D42BFDF4B900E17703 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */; };
|
||||||
|
CBC3F2B22C3E76160075DC74 /* MPPositive_AdModelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */; };
|
||||||
CBC81FBA2C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */; };
|
CBC81FBA2C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */; };
|
||||||
CBC81FBC2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */; };
|
CBC81FBC2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */; };
|
||||||
|
CBD344DA2C3FACB30095F18F /* MPPositive_JsonGenres.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD344D92C3FACB30095F18F /* MPPositive_JsonGenres.swift */; };
|
||||||
|
CBD344DC2C3FCA270095F18F /* MPPositive_GridModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD344DB2C3FCA270095F18F /* MPPositive_GridModel.swift */; };
|
||||||
|
CBD344DE2C3FD8230095F18F /* MPPositive_GridViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD344DD2C3FD8230095F18F /* MPPositive_GridViewModel.swift */; };
|
||||||
CBD4570D2C2EC38400CE766D /* AppTrackingTransparency.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBD4570C2C2EC38400CE766D /* AppTrackingTransparency.framework */; };
|
CBD4570D2C2EC38400CE766D /* AppTrackingTransparency.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBD4570C2C2EC38400CE766D /* AppTrackingTransparency.framework */; };
|
||||||
CBD5CAFD2C3BE9A90001E315 /* MP_MarQueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD5CAFC2C3BE9A90001E315 /* MP_MarQueeLabel.swift */; };
|
CBD5CAFD2C3BE9A90001E315 /* MP_MarQueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD5CAFC2C3BE9A90001E315 /* MP_MarQueeLabel.swift */; };
|
||||||
CBDAC60E2C2BE1B6008B8D34 /* MPPositive_ChooseNewPlayListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDAC60D2C2BE1B6008B8D34 /* MPPositive_ChooseNewPlayListTableViewCell.swift */; };
|
CBDAC60E2C2BE1B6008B8D34 /* MPPositive_ChooseNewPlayListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDAC60D2C2BE1B6008B8D34 /* MPPositive_ChooseNewPlayListTableViewCell.swift */; };
|
||||||
|
CBDBDDF22C40C40900767F0B /* MPPositive_GridLoadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDBDDF12C40C40900767F0B /* MPPositive_GridLoadViewModel.swift */; };
|
||||||
|
CBDBDDF42C40D03F00767F0B /* MPPositive_SearchGrideCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDBDDF32C40D03F00767F0B /* MPPositive_SearchGrideCollectionViewCell.swift */; };
|
||||||
|
CBDBDDF62C40FFC600767F0B /* MPPositive_GrideMoodViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDBDDF52C40FFC600767F0B /* MPPositive_GrideMoodViewController.swift */; };
|
||||||
CBF3AEDA2C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF3AED92C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift */; };
|
CBF3AEDA2C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF3AED92C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@ -465,11 +472,18 @@
|
|||||||
CBC2D6FA2BFDF3D800E17703 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
CBC2D6FA2BFDF3D800E17703 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
CBC2D6FC2BFDF3D800E17703 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
CBC2D6FC2BFDF3D800E17703 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
|
CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_AdModelModel.swift; sourceTree = "<group>"; };
|
||||||
CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSinglesTableViewCell.swift; sourceTree = "<group>"; };
|
CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSinglesTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSingleCollectionViewCell.swift; sourceTree = "<group>"; };
|
CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSingleCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
CBD344D92C3FACB30095F18F /* MPPositive_JsonGenres.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_JsonGenres.swift; sourceTree = "<group>"; };
|
||||||
|
CBD344DB2C3FCA270095F18F /* MPPositive_GridModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_GridModel.swift; sourceTree = "<group>"; };
|
||||||
|
CBD344DD2C3FD8230095F18F /* MPPositive_GridViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_GridViewModel.swift; sourceTree = "<group>"; };
|
||||||
CBD4570C2C2EC38400CE766D /* AppTrackingTransparency.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppTrackingTransparency.framework; path = System/Library/Frameworks/AppTrackingTransparency.framework; sourceTree = SDKROOT; };
|
CBD4570C2C2EC38400CE766D /* AppTrackingTransparency.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppTrackingTransparency.framework; path = System/Library/Frameworks/AppTrackingTransparency.framework; sourceTree = SDKROOT; };
|
||||||
CBD5CAFC2C3BE9A90001E315 /* MP_MarQueeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_MarQueeLabel.swift; sourceTree = "<group>"; };
|
CBD5CAFC2C3BE9A90001E315 /* MP_MarQueeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_MarQueeLabel.swift; sourceTree = "<group>"; };
|
||||||
CBDAC60D2C2BE1B6008B8D34 /* MPPositive_ChooseNewPlayListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_ChooseNewPlayListTableViewCell.swift; sourceTree = "<group>"; };
|
CBDAC60D2C2BE1B6008B8D34 /* MPPositive_ChooseNewPlayListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_ChooseNewPlayListTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
CBDBDDF12C40C40900767F0B /* MPPositive_GridLoadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_GridLoadViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
CBDBDDF32C40D03F00767F0B /* MPPositive_SearchGrideCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_SearchGrideCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
CBDBDDF52C40FFC600767F0B /* MPPositive_GrideMoodViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_GrideMoodViewController.swift; sourceTree = "<group>"; };
|
||||||
CBF3AED92C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_PlayListsShowTypeView.swift; sourceTree = "<group>"; };
|
CBF3AED92C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_PlayListsShowTypeView.swift; sourceTree = "<group>"; };
|
||||||
EE70E1FE424F9A64CCD389DD /* Pods-relax.offline.mp3.music.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-relax.offline.mp3.music.debug.xcconfig"; path = "Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music.debug.xcconfig"; sourceTree = "<group>"; };
|
EE70E1FE424F9A64CCD389DD /* Pods-relax.offline.mp3.music.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-relax.offline.mp3.music.debug.xcconfig"; path = "Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
@ -686,6 +700,7 @@
|
|||||||
children = (
|
children = (
|
||||||
CBAFCA322C0A10500054500E /* MPPositive_JsonBrowse.swift */,
|
CBAFCA322C0A10500054500E /* MPPositive_JsonBrowse.swift */,
|
||||||
CBBAF8CC2C339CF200B3C838 /* MPPositive_JsonCharts.swift */,
|
CBBAF8CC2C339CF200B3C838 /* MPPositive_JsonCharts.swift */,
|
||||||
|
CBD344D92C3FACB30095F18F /* MPPositive_JsonGenres.swift */,
|
||||||
CBAFCA302C0A10500054500E /* MPPositive_JsonArtist.swift */,
|
CBAFCA302C0A10500054500E /* MPPositive_JsonArtist.swift */,
|
||||||
CBAFCA312C0A10500054500E /* MPPositive_JsonArtistMore.swift */,
|
CBAFCA312C0A10500054500E /* MPPositive_JsonArtistMore.swift */,
|
||||||
CBAFCA332C0A10500054500E /* MPPositive_JsonListAlbum.swift */,
|
CBAFCA332C0A10500054500E /* MPPositive_JsonListAlbum.swift */,
|
||||||
@ -705,7 +720,9 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CBAFCA3D2C0A10500054500E /* MPPositive_ArtistHeaderModel.swift */,
|
CBAFCA3D2C0A10500054500E /* MPPositive_ArtistHeaderModel.swift */,
|
||||||
|
CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */,
|
||||||
CBAFCA3E2C0A10500054500E /* MPPositive_BrowseItemModel.swift */,
|
CBAFCA3E2C0A10500054500E /* MPPositive_BrowseItemModel.swift */,
|
||||||
|
CBD344DB2C3FCA270095F18F /* MPPositive_GridModel.swift */,
|
||||||
CBAFCA3F2C0A10500054500E /* MPPositive_CollectionArtistModel.swift */,
|
CBAFCA3F2C0A10500054500E /* MPPositive_CollectionArtistModel.swift */,
|
||||||
CBAFCA402C0A10500054500E /* MPPositive_CollectionListModel.swift */,
|
CBAFCA402C0A10500054500E /* MPPositive_CollectionListModel.swift */,
|
||||||
CBAFCA412C0A10500054500E /* MPPositive_CollectionSongModel.swift */,
|
CBAFCA412C0A10500054500E /* MPPositive_CollectionSongModel.swift */,
|
||||||
@ -727,6 +744,7 @@
|
|||||||
CBAFCA492C0A10500054500E /* MPPositive_ArtistViewModel.swift */,
|
CBAFCA492C0A10500054500E /* MPPositive_ArtistViewModel.swift */,
|
||||||
CBAFCA4A2C0A10500054500E /* MPPositive_BrowseItemViewModel.swift */,
|
CBAFCA4A2C0A10500054500E /* MPPositive_BrowseItemViewModel.swift */,
|
||||||
CBAFCA4B2C0A10500054500E /* MPPositive_BrowseModuleListViewModel.swift */,
|
CBAFCA4B2C0A10500054500E /* MPPositive_BrowseModuleListViewModel.swift */,
|
||||||
|
CBD344DD2C3FD8230095F18F /* MPPositive_GridViewModel.swift */,
|
||||||
CBAFCA4C2C0A10500054500E /* MPPositive_CollectionArtistViewModel.swift */,
|
CBAFCA4C2C0A10500054500E /* MPPositive_CollectionArtistViewModel.swift */,
|
||||||
CBAFCA4D2C0A10500054500E /* MPPositive_CollectionListViewModel.swift */,
|
CBAFCA4D2C0A10500054500E /* MPPositive_CollectionListViewModel.swift */,
|
||||||
CBAFCA4E2C0A10500054500E /* MPPositive_CollectionSongViewModel.swift */,
|
CBAFCA4E2C0A10500054500E /* MPPositive_CollectionSongViewModel.swift */,
|
||||||
@ -751,6 +769,7 @@
|
|||||||
CBAFCA5A2C0A10500054500E /* MPPositive_PlayerLoadViewModel.swift */,
|
CBAFCA5A2C0A10500054500E /* MPPositive_PlayerLoadViewModel.swift */,
|
||||||
CBAFCA5B2C0A10500054500E /* MPPositive_RecommendLoadViewModel.swift */,
|
CBAFCA5B2C0A10500054500E /* MPPositive_RecommendLoadViewModel.swift */,
|
||||||
CBAFCA5C2C0A10500054500E /* MPPositive_SearchResultsLoadViewModel.swift */,
|
CBAFCA5C2C0A10500054500E /* MPPositive_SearchResultsLoadViewModel.swift */,
|
||||||
|
CBDBDDF12C40C40900767F0B /* MPPositive_GridLoadViewModel.swift */,
|
||||||
);
|
);
|
||||||
path = LoadViewModels;
|
path = LoadViewModels;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -825,6 +844,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CBAFCA752C0A10500054500E /* MPPositive_SearchViewController.swift */,
|
CBAFCA752C0A10500054500E /* MPPositive_SearchViewController.swift */,
|
||||||
|
CBDBDDF52C40FFC600767F0B /* MPPositive_GrideMoodViewController.swift */,
|
||||||
CBAFCA742C0A10500054500E /* MPPositive_SearchResultShowViewController.swift */,
|
CBAFCA742C0A10500054500E /* MPPositive_SearchResultShowViewController.swift */,
|
||||||
);
|
);
|
||||||
path = "Search(搜索页)";
|
path = "Search(搜索页)";
|
||||||
@ -909,6 +929,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CBAFCA9E2C0A10500054500E /* MPPositive_SearchTagCollectionViewCell.swift */,
|
CBAFCA9E2C0A10500054500E /* MPPositive_SearchTagCollectionViewCell.swift */,
|
||||||
|
CBDBDDF32C40D03F00767F0B /* MPPositive_SearchGrideCollectionViewCell.swift */,
|
||||||
CBAFCA9D2C0A10500054500E /* MPPositive_SearchSuggestionsView.swift */,
|
CBAFCA9D2C0A10500054500E /* MPPositive_SearchSuggestionsView.swift */,
|
||||||
CBAFCA9A2C0A10500054500E /* MPPositive_SearchResultsShowView.swift */,
|
CBAFCA9A2C0A10500054500E /* MPPositive_SearchResultsShowView.swift */,
|
||||||
CBAFCA982C0A10500054500E /* MPPositive_SearchResultPreviewShowView.swift */,
|
CBAFCA982C0A10500054500E /* MPPositive_SearchResultPreviewShowView.swift */,
|
||||||
@ -1353,6 +1374,7 @@
|
|||||||
CBAFCB652C0A10500054500E /* MPPositive_HomeListThirdCollectionViewCell.swift in Sources */,
|
CBAFCB652C0A10500054500E /* MPPositive_HomeListThirdCollectionViewCell.swift in Sources */,
|
||||||
CBAFCB472C0A10500054500E /* MPPositive_LoveArtistsViewController.swift in Sources */,
|
CBAFCB472C0A10500054500E /* MPPositive_LoveArtistsViewController.swift in Sources */,
|
||||||
CBAFCAF62C0A10500054500E /* InstanceFromNib.swift in Sources */,
|
CBAFCAF62C0A10500054500E /* InstanceFromNib.swift in Sources */,
|
||||||
|
CBD344DE2C3FD8230095F18F /* MPPositive_GridViewModel.swift in Sources */,
|
||||||
CBAFCB622C0A10500054500E /* MPPositive_HomeListFirstCollectionViewCell.swift in Sources */,
|
CBAFCB622C0A10500054500E /* MPPositive_HomeListFirstCollectionViewCell.swift in Sources */,
|
||||||
CBAFCB112C0A10500054500E /* MP_PlayerManager.swift in Sources */,
|
CBAFCB112C0A10500054500E /* MP_PlayerManager.swift in Sources */,
|
||||||
CBAFCB582C0A10500054500E /* MPPositive_LibraryTableViewCell.swift in Sources */,
|
CBAFCB582C0A10500054500E /* MPPositive_LibraryTableViewCell.swift in Sources */,
|
||||||
@ -1365,12 +1387,14 @@
|
|||||||
CBAFCB632C0A10500054500E /* MPPositive_HomeListFourthCollectionViewCell.swift in Sources */,
|
CBAFCB632C0A10500054500E /* MPPositive_HomeListFourthCollectionViewCell.swift in Sources */,
|
||||||
CB1E3B682C23E09100071DEA /* MPPositive_CustomVideoModel.swift in Sources */,
|
CB1E3B682C23E09100071DEA /* MPPositive_CustomVideoModel.swift in Sources */,
|
||||||
CBAFCB3E2C0A10500054500E /* MPPositive_PlayerLoadViewModel.swift in Sources */,
|
CBAFCB3E2C0A10500054500E /* MPPositive_PlayerLoadViewModel.swift in Sources */,
|
||||||
|
CBD344DC2C3FCA270095F18F /* MPPositive_GridModel.swift in Sources */,
|
||||||
CBC81FBA2C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift in Sources */,
|
CBC81FBA2C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift in Sources */,
|
||||||
CBAFCB252C0A10500054500E /* MPPositive_CollectionArtistModel.swift in Sources */,
|
CBAFCB252C0A10500054500E /* MPPositive_CollectionArtistModel.swift in Sources */,
|
||||||
CBAFCB702C0A10500054500E /* MPPositive_SearchResultShowTableViewCell.swift in Sources */,
|
CBAFCB702C0A10500054500E /* MPPositive_SearchResultShowTableViewCell.swift in Sources */,
|
||||||
CBAFCB662C0A10500054500E /* MPPositive_HomeShowTableViewCell.swift in Sources */,
|
CBAFCB662C0A10500054500E /* MPPositive_HomeShowTableViewCell.swift in Sources */,
|
||||||
CBAFCB352C0A10500054500E /* MPPositive_ListAlbumListViewModel.swift in Sources */,
|
CBAFCB352C0A10500054500E /* MPPositive_ListAlbumListViewModel.swift in Sources */,
|
||||||
CBAFCB7C2C0A10500054500E /* MPSideA_NavigationController.swift in Sources */,
|
CBAFCB7C2C0A10500054500E /* MPSideA_NavigationController.swift in Sources */,
|
||||||
|
CBDBDDF62C40FFC600767F0B /* MPPositive_GrideMoodViewController.swift in Sources */,
|
||||||
CBAFCB932C0A10500054500E /* MPSideA_PlayerViewController.swift in Sources */,
|
CBAFCB932C0A10500054500E /* MPSideA_PlayerViewController.swift in Sources */,
|
||||||
CBAFCB512C0A10500054500E /* MPPositive_SearchResultShowViewController.swift in Sources */,
|
CBAFCB512C0A10500054500E /* MPPositive_SearchResultShowViewController.swift in Sources */,
|
||||||
CBAFCB4C2C0A10500054500E /* MPPositive_ListShowViewController.swift in Sources */,
|
CBAFCB4C2C0A10500054500E /* MPPositive_ListShowViewController.swift in Sources */,
|
||||||
@ -1441,12 +1465,14 @@
|
|||||||
CBAFCB832C0A10500054500E /* MPSideA_DeleteViewController.swift in Sources */,
|
CBAFCB832C0A10500054500E /* MPSideA_DeleteViewController.swift in Sources */,
|
||||||
CBAFCAF22C0A10500054500E /* String.swift in Sources */,
|
CBAFCAF22C0A10500054500E /* String.swift in Sources */,
|
||||||
CBAFCB0E2C0A10500054500E /* MP_HUD.swift in Sources */,
|
CBAFCB0E2C0A10500054500E /* MP_HUD.swift in Sources */,
|
||||||
|
CBD344DA2C3FACB30095F18F /* MPPositive_JsonGenres.swift in Sources */,
|
||||||
CB0033F02C290AC200B18FD3 /* MPPositive_CustomPlayListViewModel.swift in Sources */,
|
CB0033F02C290AC200B18FD3 /* MPPositive_CustomPlayListViewModel.swift in Sources */,
|
||||||
CBAFCB4B2C0A10500054500E /* MPPositive_HomeViewController.swift in Sources */,
|
CBAFCB4B2C0A10500054500E /* MPPositive_HomeViewController.swift in Sources */,
|
||||||
CBAFCB2A2C0A10500054500E /* MPPositive_SearchSuggestionItemModel.swift in Sources */,
|
CBAFCB2A2C0A10500054500E /* MPPositive_SearchSuggestionItemModel.swift in Sources */,
|
||||||
CBAFCB372C0A10500054500E /* MPPositive_RecommendListViewModel.swift in Sources */,
|
CBAFCB372C0A10500054500E /* MPPositive_RecommendListViewModel.swift in Sources */,
|
||||||
CBAFCB282C0A10500054500E /* MPPositive_DownloadItemModel.swift in Sources */,
|
CBAFCB282C0A10500054500E /* MPPositive_DownloadItemModel.swift in Sources */,
|
||||||
CBAFCB152C0A10500054500E /* MPSideA_MediaCenterManager.swift in Sources */,
|
CBAFCB152C0A10500054500E /* MPSideA_MediaCenterManager.swift in Sources */,
|
||||||
|
CBDBDDF22C40C40900767F0B /* MPPositive_GridLoadViewModel.swift in Sources */,
|
||||||
CBAFCAEB2C0A10500054500E /* relax.offline.mp3.xcdatamodeld in Sources */,
|
CBAFCAEB2C0A10500054500E /* relax.offline.mp3.xcdatamodeld in Sources */,
|
||||||
CBAFCB192C0A10500054500E /* MPPositive_JsonBrowse.swift in Sources */,
|
CBAFCB192C0A10500054500E /* MPPositive_JsonBrowse.swift in Sources */,
|
||||||
CBAFCB912C0A10500054500E /* MPSideA_HomeViewController.swift in Sources */,
|
CBAFCB912C0A10500054500E /* MPSideA_HomeViewController.swift in Sources */,
|
||||||
@ -1468,6 +1494,7 @@
|
|||||||
CBAFCB442C0A10500054500E /* MPPositive_PresentationController.swift in Sources */,
|
CBAFCB442C0A10500054500E /* MPPositive_PresentationController.swift in Sources */,
|
||||||
CB0968752C2121410045E55B /* GADTSmallTemplateView.m in Sources */,
|
CB0968752C2121410045E55B /* GADTSmallTemplateView.m in Sources */,
|
||||||
CBAFCB9B2C0A10500054500E /* MPSideA_CenterTableViewCell.swift in Sources */,
|
CBAFCB9B2C0A10500054500E /* MPSideA_CenterTableViewCell.swift in Sources */,
|
||||||
|
CBC3F2B22C3E76160075DC74 /* MPPositive_AdModelModel.swift in Sources */,
|
||||||
CBAFCB412C0A10500054500E /* MPPositive_BaseViewController.swift in Sources */,
|
CBAFCB412C0A10500054500E /* MPPositive_BaseViewController.swift in Sources */,
|
||||||
CBAFCB4E2C0A10500054500E /* MPPositive_PlayerListShowViewController.swift in Sources */,
|
CBAFCB4E2C0A10500054500E /* MPPositive_PlayerListShowViewController.swift in Sources */,
|
||||||
CBAFCB8B2C0A10500054500E /* MPSideA_ServiceViewController.swift in Sources */,
|
CBAFCB8B2C0A10500054500E /* MPSideA_ServiceViewController.swift in Sources */,
|
||||||
@ -1499,6 +1526,7 @@
|
|||||||
CBAFCB532C0A10500054500E /* MPPositive_BottomShowView.swift in Sources */,
|
CBAFCB532C0A10500054500E /* MPPositive_BottomShowView.swift in Sources */,
|
||||||
CBF3AEDA2C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift in Sources */,
|
CBF3AEDA2C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift in Sources */,
|
||||||
CBC2D6EC2BFDF3D700E17703 /* AppDelegate.swift in Sources */,
|
CBC2D6EC2BFDF3D700E17703 /* AppDelegate.swift in Sources */,
|
||||||
|
CBDBDDF42C40D03F00767F0B /* MPPositive_SearchGrideCollectionViewCell.swift in Sources */,
|
||||||
CBAFCB322C0A10500054500E /* MPPositive_CollectionListViewModel.swift in Sources */,
|
CBAFCB322C0A10500054500E /* MPPositive_CollectionListViewModel.swift in Sources */,
|
||||||
CBC81FBC2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift in Sources */,
|
CBC81FBC2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift in Sources */,
|
||||||
CBAFCB812C0A10500054500E /* MPSideA_CenterViewController.swift in Sources */,
|
CBAFCB812C0A10500054500E /* MPSideA_CenterViewController.swift in Sources */,
|
||||||
|
|||||||
@ -25,6 +25,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
private var backgroundEntryTime:Date?
|
private var backgroundEntryTime:Date?
|
||||||
//B面
|
//B面
|
||||||
private var positiceVC:MPPositive_TabBarController!
|
private var positiceVC:MPPositive_TabBarController!
|
||||||
|
//推送要求
|
||||||
|
private let notificationHandler = NotificationHandler()
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
//请求通知权限
|
//请求通知权限
|
||||||
UNUserNotificationCenter.current()
|
UNUserNotificationCenter.current()
|
||||||
@ -34,8 +36,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
print("Users are not allowed to be notified of messages.")
|
print("Users are not allowed to be notified of messages.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//切换通知代理
|
||||||
|
UNUserNotificationCenter.current().delegate = notificationHandler
|
||||||
//广告默认ID
|
//广告默认ID
|
||||||
coreAdMosIDs()
|
coreDefaultValues()
|
||||||
ActiveDaysCalculation()
|
ActiveDaysCalculation()
|
||||||
//FireBase初始化
|
//FireBase初始化
|
||||||
FirebaseApp.configure()
|
FirebaseApp.configure()
|
||||||
@ -82,56 +86,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
//响应后台控制
|
//响应后台控制
|
||||||
UIApplication.shared.beginReceivingRemoteControlEvents()
|
UIApplication.shared.beginReceivingRemoteControlEvents()
|
||||||
}
|
}
|
||||||
//存储修改值
|
|
||||||
func coreAdMosIDs() {
|
|
||||||
if UserDefaults.standard.string(forKey: "OpenICEID") == nil {
|
|
||||||
print("第一次启动,添加广告ID")
|
|
||||||
//存入默认开屏冷启动广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/5575463023", forKey: "OpenICEID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "OpenHOSTID") == nil {
|
|
||||||
//存入默认开屏热启动广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/5575463023", forKey: "OpenHOSTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "SearchINSERTID") == nil {
|
|
||||||
//存入默认搜索插页广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/4411468910", forKey: "SearchINSERTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "SearchNATIVEID") == nil {
|
|
||||||
//存入默认搜索原生广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/3986624511", forKey: "SearchNATIVEID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "PlayerINSERTID") == nil {
|
|
||||||
//存入默认播放插页广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/4411468910", forKey: "PlayerINSERTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "SwitchINSERTID") == nil {
|
|
||||||
//存入默认切歌插页广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/4411468910", forKey: "SwitchINSERTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "LoadINSERTID") == nil {
|
|
||||||
//存入默认下载插页广告ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/4411468910", forKey: "LoadINSERTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "LibraryINSERTID") == nil {
|
|
||||||
//存入默认曲库插页ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/4411468910", forKey: "LibraryINSERTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "LibraryNATIVEID") == nil {
|
|
||||||
//存入默认曲库原生ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/3986624511", forKey: "LibraryNATIVEID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "GlobalINSERTID") == nil {
|
|
||||||
//存入默认全局备用插页ID
|
|
||||||
UserDefaults.standard.set("ca-app-pub-3940256099942544/4411468910", forKey: "GlobalINSERTID")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "ClientVersion") == nil {
|
|
||||||
UserDefaults.standard.set("1.20240618.01.00", forKey: "ClientVersion")
|
|
||||||
}
|
|
||||||
if UserDefaults.standard.string(forKey: "PlayerVersion") == nil {
|
|
||||||
UserDefaults.standard.set("6.18.1", forKey: "PlayerVersion")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//活跃天数计算
|
//活跃天数计算
|
||||||
private func ActiveDaysCalculation() {
|
private func ActiveDaysCalculation() {
|
||||||
//判断是否存在活跃天数组
|
//判断是否存在活跃天数组
|
||||||
@ -279,6 +233,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func adManagerDidShowInterstitial() {
|
||||||
|
window?.rootViewController?.setNeedsStatusBarAppearanceUpdate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
///访问appDelegate
|
///访问appDelegate
|
||||||
let accessAppdelegate = ( UIApplication.shared.delegate as! AppDelegate)
|
let accessAppdelegate = ( UIApplication.shared.delegate as! AppDelegate)
|
||||||
|
///在应用内展示通知
|
||||||
|
class NotificationHandler: NSObject, UNUserNotificationCenterDelegate {
|
||||||
|
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
||||||
|
willPresent notification: UNNotification,
|
||||||
|
withCompletionHandler completionHandler:
|
||||||
|
@escaping (UNNotificationPresentationOptions) -> Void) {
|
||||||
|
completionHandler([.alert, .sound, .badge])
|
||||||
|
|
||||||
|
// 如果不想显示某个通知,可以直接用空 options 调用 completionHandler:
|
||||||
|
// completionHandler([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
</array>
|
</array>
|
||||||
<key>GADApplicationIdentifier</key>
|
<key>GADApplicationIdentifier</key>
|
||||||
<string>ca-app-pub-3940256099942544~1458002511</string>
|
<string>ca-app-pub-1371732277241593~3881310073</string>
|
||||||
<key>SKAdNetworkItems</key>
|
<key>SKAdNetworkItems</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Five-Star Review" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ChX-fu-2sj">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Five-Star Review" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ChX-fu-2sj">
|
||||||
<rect key="frame" x="59" y="90" width="164.5" height="24"/>
|
<rect key="frame" x="59" y="90" width="164.5" height="24"/>
|
||||||
<fontDescription key="fontDescription" type="system" weight="heavy" pointSize="20"/>
|
<fontDescription key="fontDescription" type="system" weight="heavy" pointSize="20"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="lt'd be awesomeif you wrote us a 5 star review" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iz5-RV-Ild">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="lt'd be awesomeif you wrote us a 5 star review" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iz5-RV-Ild">
|
||||||
|
|||||||
@ -102,6 +102,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
}else {
|
}else {
|
||||||
//停止计时器
|
//停止计时器
|
||||||
timer.isPaused = true
|
timer.isPaused = true
|
||||||
|
MP_AnalyticsManager.shared.launch_progress_endAction()
|
||||||
//判断是否具备广告
|
//判断是否具备广告
|
||||||
if adShowBlock != nil {
|
if adShowBlock != nil {
|
||||||
adShowBlock!()
|
adShowBlock!()
|
||||||
@ -129,27 +130,11 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
}
|
}
|
||||||
//拉取广告
|
//拉取广告
|
||||||
MP_AdMobManager.shared.loadMoreAdMobs()
|
MP_AdMobManager.shared.loadMoreAdMobs()
|
||||||
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] ad in
|
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] (ad, isOpen) in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
//将广告事件传递闭包赋值
|
//将广告事件传递闭包赋值
|
||||||
adShowBlock = {
|
adShowBlock = {
|
||||||
DispatchQueue.main.async {
|
self.adPresent(ad: ad, isOpen: isOpen)
|
||||||
//修改插页总开关状态
|
|
||||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
|
||||||
MP_AdMobManager.shared.isShowingOpenAd = true
|
|
||||||
//覆盖并实现代理
|
|
||||||
ad.fullScreenContentDelegate = self
|
|
||||||
do{
|
|
||||||
try ad.canPresent(fromRootViewController: self)
|
|
||||||
ad.present(fromRootViewController: self)
|
|
||||||
}catch{
|
|
||||||
print("开屏广告展示失败,失败原因:\(error)")
|
|
||||||
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
|
||||||
MP_AdMobManager.shared.completeOpenAdBlock!()
|
|
||||||
}
|
|
||||||
accessAppdelegate.setAudioSupport()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//进入过B面
|
//进入过B面
|
||||||
@ -180,27 +165,11 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
if open {
|
if open {
|
||||||
//开关检测为通过,以下发ID刷新广告
|
//开关检测为通过,以下发ID刷新广告
|
||||||
MP_AdMobManager.shared.loadMoreAdMobs()
|
MP_AdMobManager.shared.loadMoreAdMobs()
|
||||||
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] ad in
|
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] (ad,isOpen) in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
//将广告事件传递闭包赋值
|
//将广告事件传递闭包赋值
|
||||||
adShowBlock = {
|
adShowBlock = {
|
||||||
DispatchQueue.main.async {
|
self.adPresent(ad: ad, isOpen: isOpen)
|
||||||
//修改插页总开关状态
|
|
||||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
|
||||||
MP_AdMobManager.shared.isShowingOpenAd = true
|
|
||||||
//覆盖并实现代理
|
|
||||||
ad.fullScreenContentDelegate = self
|
|
||||||
do{
|
|
||||||
try ad.canPresent(fromRootViewController: self)
|
|
||||||
ad.present(fromRootViewController: self)
|
|
||||||
}catch{
|
|
||||||
print("开屏广告展示失败,失败原因:\(error)")
|
|
||||||
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
|
||||||
MP_AdMobManager.shared.completeOpenAdBlock!()
|
|
||||||
}
|
|
||||||
accessAppdelegate.setAudioSupport()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//根据ip值确定进入那个页面
|
//根据ip值确定进入那个页面
|
||||||
@ -278,27 +247,11 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
}else {
|
}else {
|
||||||
//开关检测未通过,以默认ID刷新广告
|
//开关检测未通过,以默认ID刷新广告
|
||||||
MP_AdMobManager.shared.loadMoreAdMobs()
|
MP_AdMobManager.shared.loadMoreAdMobs()
|
||||||
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] ad in
|
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] (ad,isOpen) in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
//将广告事件传递闭包赋值
|
//将广告事件传递闭包赋值
|
||||||
adShowBlock = {
|
adShowBlock = {
|
||||||
DispatchQueue.main.async {
|
self.adPresent(ad: ad, isOpen: isOpen)
|
||||||
//修改插页总开关状态
|
|
||||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
|
||||||
MP_AdMobManager.shared.isShowingOpenAd = true
|
|
||||||
//覆盖并实现代理
|
|
||||||
ad.fullScreenContentDelegate = self
|
|
||||||
do{
|
|
||||||
try ad.canPresent(fromRootViewController: self)
|
|
||||||
ad.present(fromRootViewController: self)
|
|
||||||
}catch{
|
|
||||||
print("开屏广告展示失败,失败原因:\(error)")
|
|
||||||
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
|
||||||
MP_AdMobManager.shared.completeOpenAdBlock!()
|
|
||||||
}
|
|
||||||
accessAppdelegate.setAudioSupport()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print("ALog")
|
print("ALog")
|
||||||
@ -330,13 +283,52 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//广告弹出
|
||||||
|
private func adPresent(ad: GADFullScreenPresentingAd, isOpen:Bool) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
//修改插页总开关状态
|
||||||
|
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
||||||
|
MP_AdMobManager.shared.isShowingOpenAd = true
|
||||||
|
if isOpen {
|
||||||
|
let new = ad as? GADAppOpenAd
|
||||||
|
//覆盖并实现代理
|
||||||
|
new?.fullScreenContentDelegate = self
|
||||||
|
do{
|
||||||
|
try new?.canPresent(fromRootViewController: self)
|
||||||
|
new?.present(fromRootViewController: self)
|
||||||
|
}catch{
|
||||||
|
print("开屏广告展示失败,失败原因:\(error)")
|
||||||
|
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
||||||
|
MP_AdMobManager.shared.completeOpenAdBlock!()
|
||||||
|
}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
let new = ad as? GADInterstitialAd
|
||||||
|
//覆盖并实现代理
|
||||||
|
new?.fullScreenContentDelegate = self
|
||||||
|
do{
|
||||||
|
try new?.canPresent(fromRootViewController: self)
|
||||||
|
new?.present(fromRootViewController: self)
|
||||||
|
}catch{
|
||||||
|
print("开屏广告展示失败,失败原因:\(error)")
|
||||||
|
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
||||||
|
MP_AdMobManager.shared.completeOpenAdBlock!()
|
||||||
|
}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
||||||
//覆盖型广告将要将要展示
|
//覆盖型广告将要将要展示
|
||||||
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = true
|
||||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction()
|
MP_AnalyticsManager.shared.cold_ads_showSuccessAction()
|
||||||
}
|
}
|
||||||
//覆盖型广告已经消失
|
//覆盖型广告已经消失
|
||||||
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
//当前启动页,展示广告一定是开屏广告
|
//当前启动页,展示广告一定是开屏广告
|
||||||
if switchBlock != nil {
|
if switchBlock != nil {
|
||||||
switchBlock!()
|
switchBlock!()
|
||||||
@ -344,10 +336,15 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
||||||
MP_AdMobManager.shared.completeOpenAdBlock!()
|
MP_AdMobManager.shared.completeOpenAdBlock!()
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//覆盖型广告加载出错
|
//覆盖型广告加载出错
|
||||||
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
MP_AnalyticsManager.shared.cold_ads_showFailureAction(error.localizedDescription)
|
MP_AnalyticsManager.shared.cold_ads_showFailureAction(error.localizedDescription)
|
||||||
//当前启动页,展示广告一定是开屏广告
|
//当前启动页,展示广告一定是开屏广告
|
||||||
if switchBlock != nil {
|
if switchBlock != nil {
|
||||||
@ -356,6 +353,10 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
if MP_AdMobManager.shared.completeOpenAdBlock != nil {
|
||||||
MP_AdMobManager.shared.completeOpenAdBlock!()
|
MP_AdMobManager.shared.completeOpenAdBlock!()
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,18 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
//MARK: - Color扩展
|
//MARK: - Color扩展
|
||||||
extension UIColor {
|
extension UIColor {
|
||||||
|
convenience init?(string: UInt64, alpha: CGFloat = 1.0) {
|
||||||
|
// 1. 将值转换为 8 位十六进制颜色值
|
||||||
|
let hexValue = string >> 8
|
||||||
|
// 2. 将 8 位十六进制值转换为 RGB 值
|
||||||
|
let red = CGFloat((hexValue >> 16) & 0xFF) / 255.0
|
||||||
|
let green = CGFloat((hexValue >> 8) & 0xFF) / 255.0
|
||||||
|
let blue = CGFloat((hexValue) & 0xFF) / 255.0
|
||||||
|
|
||||||
|
// 3. 使用 UIColor 构造方法创建颜色对象
|
||||||
|
self.init(red: red, green: green, blue: blue, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
/// String -> UIColor
|
/// String -> UIColor
|
||||||
convenience init(hex: String,alpha:CGFloat? = 1) {
|
convenience init(hex: String,alpha:CGFloat? = 1) {
|
||||||
let string = hex.trimmingCharacters(in: .whitespacesAndNewlines)
|
let string = hex.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
|||||||
@ -113,6 +113,8 @@ extension NotificationCenter{
|
|||||||
case download_progress_source
|
case download_progress_source
|
||||||
///b面歌曲下载结束
|
///b面歌曲下载结束
|
||||||
case dowload_end_source
|
case dowload_end_source
|
||||||
|
///b面搜索页模块更新
|
||||||
|
case search_gride_reload
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import AppTrackingTransparency
|
|||||||
import AdSupport
|
import AdSupport
|
||||||
import MessageUI
|
import MessageUI
|
||||||
import MarqueeLabel
|
import MarqueeLabel
|
||||||
|
import UserNotifications
|
||||||
@_exported import JXSegmentedView
|
@_exported import JXSegmentedView
|
||||||
@_exported import JXPagingView
|
@_exported import JXPagingView
|
||||||
//给JXPagingListContainerView添加extension,表示遵从JXSegmentedViewListContainer的协议
|
//给JXPagingListContainerView添加extension,表示遵从JXSegmentedViewListContainer的协议
|
||||||
@ -70,6 +71,135 @@ let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")!
|
|||||||
let serviceUrl:URL = .init(string: "https://musiclax.mystrikingly.com/terms")!
|
let serviceUrl:URL = .init(string: "https://musiclax.mystrikingly.com/terms")!
|
||||||
|
|
||||||
//MARK: - 全局变量与方法
|
//MARK: - 全局变量与方法
|
||||||
|
//存储默认配置值
|
||||||
|
func coreDefaultValues() {
|
||||||
|
if UserDefaults.standard.object(forKey: "OpenICEID") == nil {
|
||||||
|
print("第一次启动,添加广告ID")
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/2126815630", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/8500652294", ad: "AdMob", type: .Open),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/4561407280", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 0, identifier: "ca-app-pub-1371732277241593/1926543650", ad: "AdMob", type: .Open)]) {
|
||||||
|
//存入默认开屏冷启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "OpenICEID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "OpenHOSTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/9262752398", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/6536516707", ad: "AdMob", type: .Open),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/9239018894", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 0, identifier: "ca-app-pub-1371732277241593/3299335073", ad: "AdMob", type: .Open)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "OpenHOSTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "SearchINSERTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/5323507386", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/6877962328", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/4251798981", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 0, identifier: "ca-app-pub-1371732277241593/8622500865", ad: "AdMob", type: .Insert)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "SearchINSERTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "SearchNATIVEID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/5674216970", ad: "AdMob", type: .Native)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "SearchNATIVEID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "PlayerINSERTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/9569874154", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/8256792481", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/8031261896", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 0, identifier: "ca-app-pub-1371732277241593/4182802216", ad: "AdMob", type: .Insert)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "PlayerINSERTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "SwitchINSERTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4990165586", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/5247485769", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/1050920574", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 0, identifier: "ca-app-pub-1371732277241593/8439981117", ad: "AdMob", type: .Insert)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "SwitchINSERTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "LoadINSERTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4335559460", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/2398278378", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/3107763383", ad: "AdMob", type: .Insert)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "LoadINSERTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "LibraryINSERTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4607022200", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 2, identifier: "ca-app-pub-1371732277241593/3104538158", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 1, identifier: "ca-app-pub-1371732277241593/8931897131", ad: "AdMob", type: .Insert),
|
||||||
|
.init(level: 0, identifier: "ca-app-pub-1371732277241593/5298812459", ad: "AdMob", type: .Insert)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "LibraryINSERTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "LibraryNATIVEID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4683255855", ad: "AdMob", type: .Native)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "LibraryNATIVEID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "GlobalINSERTID") == nil {
|
||||||
|
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/9449223728", ad: "AdMob", type: .Insert)]) {
|
||||||
|
//存入默认开屏热启动广告ID
|
||||||
|
UserDefaults.standard.set(array, forKey: "GlobalINSERTID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//更多内容操作
|
||||||
|
if UserDefaults.standard.string(forKey: "ClientVersion") == nil {
|
||||||
|
UserDefaults.standard.set("1.20240618.01.00", forKey: "ClientVersion")
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.string(forKey: "PlayerVersion") == nil {
|
||||||
|
UserDefaults.standard.set("6.18.1", forKey: "PlayerVersion")
|
||||||
|
}
|
||||||
|
if UserDefaults.standard.object(forKey: "NotificationBodyTexts") == nil {
|
||||||
|
UserDefaults.standard.set(["✅ Enjoy your favorite offline music.Your new playlist is ready! Enjoy your favorite offline music.",
|
||||||
|
"🕛 Now is the time to enjoy non-stop music!",
|
||||||
|
"🚀 Boost your day with new offline music selections!",
|
||||||
|
"🎵 Ready for a music adventure? Download latest tracks for offline fun!",
|
||||||
|
"❤️ Your favorite songs are available for offline playback now.",
|
||||||
|
"😍 New recommendations tailored for you. Add them to your library.",
|
||||||
|
"👉 Touch the music journey, start now!",
|
||||||
|
"🔥 Summer hits ready for download. Enjoy offline!",
|
||||||
|
"🙌 Your music, your way. 💎💎💎",
|
||||||
|
"💡 Discover today's music,enjoy the moment!"
|
||||||
|
], forKey: "NotificationBodyTexts")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///将广告模型组转为Data
|
||||||
|
func coreAdModelforJson(_ array:[MPPositive_AdModelModel]) -> Data? {
|
||||||
|
guard array.isEmpty != true else {return nil}
|
||||||
|
do{
|
||||||
|
let jsonData = try JSONEncoder().encode(array)
|
||||||
|
return jsonData
|
||||||
|
}catch {
|
||||||
|
//编译失败
|
||||||
|
print("用户默认广告配置设置失败,失败原因:\(error.localizedDescription)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///将data转为广告模型组
|
||||||
|
func jsonforCoreAdModel(_ data:Data) -> [MPPositive_AdModelModel]? {
|
||||||
|
do{
|
||||||
|
let array:[MPPositive_AdModelModel] = try JSONDecoder().decode([MPPositive_AdModelModel].self, from: data)
|
||||||
|
return array
|
||||||
|
}catch{
|
||||||
|
//编译失败
|
||||||
|
print("用户默认广告配置设置失败,失败原因:\(error.localizedDescription)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///总事件闭包
|
///总事件闭包
|
||||||
typealias ActionBlock = () -> Void?
|
typealias ActionBlock = () -> Void?
|
||||||
///A面全局模态弹出类型
|
///A面全局模态弹出类型
|
||||||
@ -246,7 +376,7 @@ func saveLoadVideoItem(_ song:MPPositive_SongItemModel, completion:(() -> Void)?
|
|||||||
item.videoId = song.videoId
|
item.videoId = song.videoId
|
||||||
item.relatedID = song.relatedID
|
item.relatedID = song.relatedID
|
||||||
//保存下载数据
|
//保存下载数据
|
||||||
MPPositive_DownloadItemModel.save(true)
|
MPPositive_DownloadItemModel.save()
|
||||||
completion?()
|
completion?()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
//更新数据库
|
//更新数据库
|
||||||
@ -257,3 +387,51 @@ func saveLoadVideoItem(_ song:MPPositive_SongItemModel, completion:(() -> Void)?
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///发布通知
|
||||||
|
func scheduleDailyNotifications() {
|
||||||
|
UNUserNotificationCenter.current().getNotificationSettings {
|
||||||
|
settings in
|
||||||
|
switch settings.authorizationStatus {
|
||||||
|
case .authorized:
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
guard let texts = UserDefaults.standard.object(forKey: "NotificationBodyTexts") as? [String], texts.isEmpty != true else {return}
|
||||||
|
// 获取通知中心
|
||||||
|
let center = UNUserNotificationCenter.current()
|
||||||
|
//创建通知内容,通知只具备body
|
||||||
|
let firstContent = UNMutableNotificationContent()
|
||||||
|
firstContent.title = ""
|
||||||
|
firstContent.body = texts.randomElement() ?? ""
|
||||||
|
firstContent.sound = UNNotificationSound.default
|
||||||
|
//设置触发器-每日上午10点
|
||||||
|
var firstDateComponents = DateComponents()
|
||||||
|
firstDateComponents.hour = 10
|
||||||
|
let firstTrigger = UNCalendarNotificationTrigger(dateMatching: firstDateComponents, repeats: true)
|
||||||
|
//创建通知内容,通知只具备body
|
||||||
|
let secondContent = UNMutableNotificationContent()
|
||||||
|
secondContent.title = ""
|
||||||
|
secondContent.body = texts.randomElement() ?? ""
|
||||||
|
secondContent.sound = UNNotificationSound.default
|
||||||
|
//设置触发器-每日下午2点
|
||||||
|
var secondDateComponents = DateComponents()
|
||||||
|
secondDateComponents.hour = 14
|
||||||
|
let secondTrigger = UNCalendarNotificationTrigger(dateMatching: secondDateComponents, repeats: true)
|
||||||
|
//创建通知请求
|
||||||
|
let firstRequest = UNNotificationRequest(identifier: "relax.offline.mp3.morningNotification", content: firstContent, trigger: firstTrigger)
|
||||||
|
let secondRequest = UNNotificationRequest(identifier: "relax.offline.mp3.afternoonNotification", content: secondContent, trigger: secondTrigger)
|
||||||
|
// 将通知请求添加到通知中心
|
||||||
|
center.add(firstRequest) { error in
|
||||||
|
if let error = error {
|
||||||
|
print("更新上午通知失败,失败原因: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
center.add(secondRequest) { error in
|
||||||
|
if let error = error {
|
||||||
|
print("更新下午通知失败,失败原因: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -79,7 +79,22 @@ extension MP_CoreDataOperationDelegate {
|
|||||||
/// 查询全部实体 (异步)
|
/// 查询全部实体 (异步)
|
||||||
/// - Parameter completion: 查询完成后回调,在主线程执行
|
/// - Parameter completion: 查询完成后回调,在主线程执行
|
||||||
static func fetchAll(completion: @escaping ([ManagedObject]) -> Void) {
|
static func fetchAll(completion: @escaping ([ManagedObject]) -> Void) {
|
||||||
fetch(predicate: nil, completion: completion)
|
let fetchRequest = ManagedObject.fetchRequest
|
||||||
|
// 使用 perform 方法异步执行查询
|
||||||
|
MP_CoreDataHandlerManager.shared.context.perform {
|
||||||
|
do {
|
||||||
|
let results = try MP_CoreDataHandlerManager.shared.context.fetch(fetchRequest)
|
||||||
|
// 回到主线程调用 completion 闭包
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
completion(results)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print("Failed to fetch \(ManagedObject.entityName): \(error)")
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
completion([]) // 查询失败,返回空数组
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// 从表删除实体
|
/// 从表删除实体
|
||||||
/// - Parameter object: 指定的实体
|
/// - Parameter object: 指定的实体
|
||||||
@ -93,6 +108,10 @@ extension MP_CoreDataOperationDelegate {
|
|||||||
|
|
||||||
/// 表执行保存
|
/// 表执行保存
|
||||||
static func save(_ isBackTheard:Bool = false) {
|
static func save(_ isBackTheard:Bool = false) {
|
||||||
MP_CoreDataHandlerManager.shared.saveContext()
|
if isBackTheard {
|
||||||
|
MP_CoreDataHandlerManager.shared.saveContextInBackground()
|
||||||
|
}else {
|
||||||
|
MP_CoreDataHandlerManager.shared.saveContext()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
static let shared = MP_AdMobManager()
|
static let shared = MP_AdMobManager()
|
||||||
private let sharedInstance = GADMobileAds.sharedInstance()
|
private let sharedInstance = GADMobileAds.sharedInstance()
|
||||||
///广告总开关
|
///广告总开关
|
||||||
private var openAdStatus:Bool = false
|
private var openAdStatus:Bool = true
|
||||||
///广告过期时间(50分钟)
|
///广告过期时间(50分钟)
|
||||||
private let expirationTime:TimeInterval = 3000
|
private let expirationTime:TimeInterval = 3000
|
||||||
|
|
||||||
@ -64,6 +64,7 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
guard let self = self, interstitialSwitch == true else {return}
|
guard let self = self, interstitialSwitch == true else {return}
|
||||||
//销毁现在的开屏广告实例
|
//销毁现在的开屏广告实例
|
||||||
appOpenAd = nil
|
appOpenAd = nil
|
||||||
|
appInterstitialAd = nil
|
||||||
isShowingOpenAd = false
|
isShowingOpenAd = false
|
||||||
loadOpenAdTime = nil
|
loadOpenAdTime = nil
|
||||||
//关闭插页广告开关
|
//关闭插页广告开关
|
||||||
@ -216,36 +217,36 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
///更新ID
|
///更新ID
|
||||||
func reloadAdMobIDs() {
|
func reloadAdMobIDs() {
|
||||||
//更新所有广告ID
|
//更新所有广告ID
|
||||||
if let str = UserDefaults.standard.string(forKey: "OpenICEID") {
|
if let data = UserDefaults.standard.object(forKey: "OpenICEID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
print("成功提取ID")
|
print("成功提取ID")
|
||||||
OpenICEID = str
|
OpenICEID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "OpenHOSTID") {
|
if let data = UserDefaults.standard.object(forKey: "OpenHOSTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
OpenHOSTID = str
|
OpenHOSTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "SearchINSERTID") {
|
if let data = UserDefaults.standard.object(forKey: "SearchINSERTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
SearchINSERTID = str
|
SearchINSERTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "SearchNATIVEID") {
|
if let data = UserDefaults.standard.object(forKey: "SearchNATIVEID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
SearchNATIVEID = str
|
SearchNATIVEID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "PlayerINSERTID") {
|
if let data = UserDefaults.standard.object(forKey: "PlayerINSERTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
PlayerINSERTID = str
|
PlayerINSERTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "SwitchINSERTID") {
|
if let data = UserDefaults.standard.object(forKey: "SwitchINSERTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
SwitchINSERTID = str
|
SwitchINSERTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "LoadINSERTID") {
|
if let data = UserDefaults.standard.object(forKey: "LoadINSERTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
LoadINSERTID = str
|
LoadINSERTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "LibraryINSERTID") {
|
if let data = UserDefaults.standard.object(forKey: "LibraryINSERTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
LibraryINSERTID = str
|
LibraryINSERTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "LibraryNATIVEID") {
|
if let data = UserDefaults.standard.object(forKey: "LibraryNATIVEID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
LibraryNATIVEID = str
|
LibraryNATIVEID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
if let str = UserDefaults.standard.string(forKey: "GlobalINSERTID") {
|
if let data = UserDefaults.standard.object(forKey: "GlobalINSERTID") as? Data, let array = jsonforCoreAdModel(data) {
|
||||||
GlobalINSERTID = str
|
GlobalINSERTID = array.sorted(by: {$0.level > $1.level})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
///加载更多广告
|
///加载更多广告
|
||||||
@ -318,9 +319,9 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
|
|
||||||
//MARK: - 开屏
|
//MARK: - 开屏
|
||||||
//开屏冷启动广告ID
|
//开屏冷启动广告ID
|
||||||
private var OpenICEID:String!
|
private var OpenICEID:[MPPositive_AdModelModel] = []
|
||||||
//开屏热启动广告ID
|
//开屏热启动广告ID
|
||||||
private var OpenHOSTID:String!
|
private var OpenHOSTID:[MPPositive_AdModelModel] = []
|
||||||
//开屏广告类型
|
//开屏广告类型
|
||||||
enum OpenType:Int {
|
enum OpenType:Int {
|
||||||
//冷启动
|
//冷启动
|
||||||
@ -336,8 +337,10 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//开屏广告实例
|
//应用开屏广告实例
|
||||||
private var appOpenAd:GADAppOpenAd?
|
private var appOpenAd:GADAppOpenAd?
|
||||||
|
//应用插页广告实例
|
||||||
|
private var appInterstitialAd:GADInterstitialAd?
|
||||||
//是否正在加载广告
|
//是否正在加载广告
|
||||||
private var isLoadingOpenAd:Bool = false
|
private var isLoadingOpenAd:Bool = false
|
||||||
//是否正在展示广告
|
//是否正在展示广告
|
||||||
@ -358,8 +361,26 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
var completeOpenAdBlock:(() -> Void)?
|
var completeOpenAdBlock:(() -> Void)?
|
||||||
|
|
||||||
///异步加载开屏广告
|
///异步加载开屏广告
|
||||||
func loadOpenAd(_ type:OpenType,completion: @escaping (Bool) -> Void) {
|
func loadOpenAd(_ type:OpenType, level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
//检索是否超过了对应的id组的阶级数量
|
||||||
|
var item:MPPositive_AdModelModel
|
||||||
|
switch type {
|
||||||
|
case .ICE:
|
||||||
|
guard level <= (OpenICEID.count-1) else {
|
||||||
|
print("冷启动广告组已经全部加载失败,停止继续加载")
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item = OpenICEID[level]
|
||||||
|
case .HOST:
|
||||||
|
guard level <= (OpenHOSTID.count-1) else {
|
||||||
|
print("热启动广告组已经全部加载失败,停止继续加载")
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item = OpenHOSTID[level]
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingOpenAd || isOpenAdAvailable() {
|
if isLoadingOpenAd || isOpenAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -367,35 +388,54 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingOpenAd = true
|
isLoadingOpenAd = true
|
||||||
var UUID:String
|
//判断需要生成什么广告
|
||||||
switch type {
|
if item.type == .Open {
|
||||||
case .ICE:
|
//生成开屏广告
|
||||||
UUID = OpenICEID
|
// 使用 GADAppOpenAd 的 load 方法和一个completion handler来加载广告
|
||||||
case .HOST:
|
GADAppOpenAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
UUID = OpenHOSTID
|
DispatchQueue.main.async { [weak self] in
|
||||||
}
|
guard let self = self else { return }
|
||||||
// 使用 GADAppOpenAd 的 load 方法和一个completion handler来加载广告
|
if let error = error {
|
||||||
GADAppOpenAd.load(withAdUnitID: UUID, request: GADRequest()) { ad, error in
|
print("加载开屏广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
DispatchQueue.main.async { [weak self] in
|
self.isLoadingOpenAd = false
|
||||||
guard let self = self else { return }
|
loadOpenAd(type, level: level+1, completion: completion)
|
||||||
if let error = error {
|
} else {
|
||||||
print("加载开屏广告失败,失败原因: \(error.localizedDescription)")
|
self.appOpenAd = ad
|
||||||
self.isLoadingOpenAd = false
|
self.isLoadingOpenAd = false
|
||||||
completion(false)
|
//实现代理
|
||||||
} else {
|
self.appOpenAd?.fullScreenContentDelegate = self
|
||||||
self.appOpenAd = ad
|
//更新加载时间
|
||||||
self.isLoadingOpenAd = false
|
self.loadOpenAdTime = Date()
|
||||||
//实现代理
|
completion(true)
|
||||||
self.appOpenAd?.fullScreenContentDelegate = self
|
}
|
||||||
//更新加载时间
|
|
||||||
self.loadOpenAdTime = Date()
|
|
||||||
completion(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else if item.type == .Insert {
|
||||||
|
//生成插页广告
|
||||||
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if let error = error {
|
||||||
|
print("加载开屏广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
|
self.isLoadingOpenAd = false
|
||||||
|
loadOpenAd(type, level: level+1, completion: completion)
|
||||||
|
} else {
|
||||||
|
self.appInterstitialAd = ad
|
||||||
|
self.isLoadingOpenAd = false
|
||||||
|
//实现代理
|
||||||
|
self.appInterstitialAd?.fullScreenContentDelegate = self
|
||||||
|
//更新加载时间
|
||||||
|
self.loadOpenAdTime = Date()
|
||||||
|
completion(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
completion(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
///开屏广告展示
|
///开屏广告展示
|
||||||
func showOpenAdIfAvailable(_ type:OpenType, completion:((GADAppOpenAd) -> Void)?) {
|
func showOpenAdIfAvailable(_ type:OpenType, completion:((_ T:GADFullScreenPresentingAd, _ isOpen:Bool) -> Void)?) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||||
guard !interstitialSwitch, !isShowingOpenAd else { return }
|
guard !interstitialSwitch, !isShowingOpenAd else { return }
|
||||||
@ -415,10 +455,33 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
MP_AnalyticsManager.shared.hot_ads_chanceAction()
|
MP_AnalyticsManager.shared.hot_ads_chanceAction()
|
||||||
}
|
}
|
||||||
//当开屏广告确定有值后展示
|
//当开屏广告确定有值后展示
|
||||||
if let ad = appOpenAd {
|
if let ad = (appOpenAd) {
|
||||||
//传递加载完成事件
|
//传递加载完成事件
|
||||||
if let block = completion {
|
if let block = completion {
|
||||||
block(ad)
|
block(ad, true)
|
||||||
|
}else {
|
||||||
|
isShowingOpenAd = true
|
||||||
|
interstitialSwitch = true
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
do{
|
||||||
|
try ad.canPresent(fromRootViewController: nil)
|
||||||
|
ad.present(fromRootViewController: nil)
|
||||||
|
|
||||||
|
}catch{
|
||||||
|
print("开屏广告展示失败,失败原因:\(error)")
|
||||||
|
if completeOpenAdBlock != nil {
|
||||||
|
completeOpenAdBlock!()
|
||||||
|
}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if let ad = (appInterstitialAd) {
|
||||||
|
//传递加载完成事件
|
||||||
|
if let block = completion {
|
||||||
|
block(ad, false)
|
||||||
}else {
|
}else {
|
||||||
isShowingOpenAd = true
|
isShowingOpenAd = true
|
||||||
interstitialSwitch = true
|
interstitialSwitch = true
|
||||||
@ -447,14 +510,14 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
}
|
}
|
||||||
///查询是否有开屏广告
|
///查询是否有开屏广告
|
||||||
func isOpenAdAvailable() -> Bool {
|
func isOpenAdAvailable() -> Bool {
|
||||||
return appOpenAd != nil && wasAdexpirationTime(loadOpenAdTime)
|
return (appOpenAd != nil || appInterstitialAd != nil) && wasAdexpirationTime(loadOpenAdTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - 搜索
|
//MARK: - 搜索
|
||||||
//搜索插页广告ID
|
//搜索插页广告ID
|
||||||
private var SearchINSERTID:String!
|
private var SearchINSERTID:[MPPositive_AdModelModel] = []
|
||||||
//搜索原生广告ID
|
//搜索原生广告ID
|
||||||
private var SearchNATIVEID:String!
|
private var SearchNATIVEID:[MPPositive_AdModelModel] = []
|
||||||
///搜索插页广告
|
///搜索插页广告
|
||||||
private var searchInterstitialAd:GADInterstitialAd?
|
private var searchInterstitialAd:GADInterstitialAd?
|
||||||
///是否正在加载搜索插页广告
|
///是否正在加载搜索插页广告
|
||||||
@ -492,9 +555,11 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
let multipleAdOptions = GADMultipleAdsAdLoaderOptions()
|
let multipleAdOptions = GADMultipleAdsAdLoaderOptions()
|
||||||
//加载一条,每次即使结束后重新刷新数据
|
//加载一条,每次即使结束后重新刷新数据
|
||||||
multipleAdOptions.numberOfAds = 1
|
multipleAdOptions.numberOfAds = 1
|
||||||
searchAdLoader = GADAdLoader(adUnitID: SearchNATIVEID, rootViewController: vc, adTypes: [.native], options: [multipleAdOptions])
|
if let first = SearchNATIVEID.first, first.type == .Native {
|
||||||
searchAdLoader?.delegate = self
|
searchAdLoader = GADAdLoader(adUnitID: first.identifier, rootViewController: vc, adTypes: [.native], options: [multipleAdOptions])
|
||||||
searchAdLoader?.load(GADRequest())
|
searchAdLoader?.delegate = self
|
||||||
|
searchAdLoader?.load(GADRequest())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
///将加载的搜索原生广告添加到页面中
|
///将加载的搜索原生广告添加到页面中
|
||||||
func layoutSearchNativeAd(in containerView: UIView) {
|
func layoutSearchNativeAd(in containerView: UIView) {
|
||||||
@ -541,8 +606,16 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
//异步加载搜索插页广告
|
//异步加载搜索插页广告
|
||||||
func loadSearchInterstitialAd(completion: @escaping (Bool) -> Void) {
|
func loadSearchInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
guard level <= (SearchINSERTID.count-1) else {
|
||||||
|
print("搜索插页广告组已经全部加载失败,停止继续加载")
|
||||||
|
//开始加载全局插页
|
||||||
|
loadGlobalInterstitialAd { status in
|
||||||
|
completion(status)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingSearchInterstitialAd || isSearchInterstitialAdAvailable() {
|
if isLoadingSearchInterstitialAd || isSearchInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -550,17 +623,15 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingSearchInterstitialAd = true
|
isLoadingSearchInterstitialAd = true
|
||||||
|
let item = SearchINSERTID[level]
|
||||||
//加载搜索插页广告
|
//加载搜索插页广告
|
||||||
GADInterstitialAd.load(withAdUnitID: SearchINSERTID, request: GADRequest()) { ad, error in
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("加载搜索插页广告失败,失败原因: \(error.localizedDescription)")
|
print("加载搜索插页广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
self.isLoadingSearchInterstitialAd = false
|
self.isLoadingSearchInterstitialAd = false
|
||||||
//开始加载全局插页
|
loadSearchInterstitialAd(level+1, completion: completion)
|
||||||
loadGlobalInterstitialAd { status in
|
|
||||||
completion(status)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.searchInterstitialAd = ad
|
self.searchInterstitialAd = ad
|
||||||
self.isLoadingSearchInterstitialAd = false
|
self.isLoadingSearchInterstitialAd = false
|
||||||
@ -628,7 +699,7 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
|
|
||||||
//MARK: - 播放
|
//MARK: - 播放
|
||||||
//播放插页广告ID
|
//播放插页广告ID
|
||||||
private var PlayerINSERTID:String!
|
private var PlayerINSERTID:[MPPositive_AdModelModel] = []
|
||||||
///播放插页广告
|
///播放插页广告
|
||||||
var playInterstitialAd:GADInterstitialAd?
|
var playInterstitialAd:GADInterstitialAd?
|
||||||
///是否正在加载播放插页广告
|
///是否正在加载播放插页广告
|
||||||
@ -640,8 +711,16 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
///播放广告处理闭包
|
///播放广告处理闭包
|
||||||
var completePlayInterstitialAdBlock:(() -> Void)?
|
var completePlayInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载播放插页广告
|
//异步加载播放插页广告
|
||||||
func loadPlayInterstitialAd(completion: @escaping (Bool) -> Void) {
|
func loadPlayInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
guard level <= (PlayerINSERTID.count-1) else {
|
||||||
|
print("播放插页广告组已经全部加载失败,停止继续加载")
|
||||||
|
//开始加载全局插页
|
||||||
|
loadGlobalInterstitialAd { status in
|
||||||
|
completion(status)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingPlayInterstitialAd || isPlayInterstitialAdAvailable() {
|
if isLoadingPlayInterstitialAd || isPlayInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -649,16 +728,15 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingPlayInterstitialAd = true
|
isLoadingPlayInterstitialAd = true
|
||||||
|
let item = PlayerINSERTID[level]
|
||||||
//加载播放插页广告
|
//加载播放插页广告
|
||||||
GADInterstitialAd.load(withAdUnitID: PlayerINSERTID, request: GADRequest()) { ad, error in
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("加载播放插页广告失败,失败原因: \(error.localizedDescription)")
|
print("加载播放插页广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
self.isLoadingPlayInterstitialAd = false
|
self.isLoadingPlayInterstitialAd = false
|
||||||
loadGlobalInterstitialAd { status in
|
loadPlayInterstitialAd(level+1, completion: completion)
|
||||||
completion(status)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.playInterstitialAd = ad
|
self.playInterstitialAd = ad
|
||||||
self.isLoadingPlayInterstitialAd = false
|
self.isLoadingPlayInterstitialAd = false
|
||||||
@ -727,7 +805,7 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
|
|
||||||
//MARK: - 切歌
|
//MARK: - 切歌
|
||||||
//切歌插页广告ID
|
//切歌插页广告ID
|
||||||
private var SwitchINSERTID:String!
|
private var SwitchINSERTID:[MPPositive_AdModelModel] = []
|
||||||
///切歌插页广告
|
///切歌插页广告
|
||||||
var switchInterstitialAd:GADInterstitialAd?
|
var switchInterstitialAd:GADInterstitialAd?
|
||||||
///是否正在加载切歌插页广告
|
///是否正在加载切歌插页广告
|
||||||
@ -739,8 +817,16 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
///切歌广告处理闭包
|
///切歌广告处理闭包
|
||||||
var completeSwitchInterstitialAdBlock:(() -> Void)?
|
var completeSwitchInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载切歌插页广告
|
//异步加载切歌插页广告
|
||||||
func loadSwitchInterstitialAd(completion: @escaping (Bool) -> Void) {
|
func loadSwitchInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
guard level <= (SwitchINSERTID.count-1) else {
|
||||||
|
print("切歌插页广告组已经全部加载失败,停止继续加载")
|
||||||
|
//开始加载全局插页
|
||||||
|
loadGlobalInterstitialAd { status in
|
||||||
|
completion(status)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingSwitchInterstitialAd || isSwitchInterstitialAdAvailable() {
|
if isLoadingSwitchInterstitialAd || isSwitchInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -748,16 +834,15 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingSwitchInterstitialAd = true
|
isLoadingSwitchInterstitialAd = true
|
||||||
|
let item = SwitchINSERTID[level]
|
||||||
//加载播放插页广告
|
//加载播放插页广告
|
||||||
GADInterstitialAd.load(withAdUnitID: SwitchINSERTID, request: GADRequest()) { ad, error in
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("加载切歌插页广告失败,失败原因: \(error.localizedDescription)")
|
print("加载切歌插页广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
self.isLoadingSwitchInterstitialAd = false
|
self.isLoadingSwitchInterstitialAd = false
|
||||||
loadGlobalInterstitialAd { status in
|
loadSwitchInterstitialAd(level+1, completion: completion)
|
||||||
completion(status)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.switchInterstitialAd = ad
|
self.switchInterstitialAd = ad
|
||||||
self.isLoadingSwitchInterstitialAd = false
|
self.isLoadingSwitchInterstitialAd = false
|
||||||
@ -825,7 +910,7 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
|
|
||||||
//MARK: - 下载
|
//MARK: - 下载
|
||||||
//下载插页广告ID
|
//下载插页广告ID
|
||||||
private var LoadINSERTID:String!
|
private var LoadINSERTID:[MPPositive_AdModelModel] = []
|
||||||
///下载插页广告
|
///下载插页广告
|
||||||
var loadInterstitialAd:GADInterstitialAd?
|
var loadInterstitialAd:GADInterstitialAd?
|
||||||
///是否正在加载下载插页广告
|
///是否正在加载下载插页广告
|
||||||
@ -837,8 +922,16 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
///下载广告处理闭包
|
///下载广告处理闭包
|
||||||
var completeLoadInterstitialAdBlock:(() -> Void)?
|
var completeLoadInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载下载插页广告
|
//异步加载下载插页广告
|
||||||
func loadLoadInterstitialAd(completion: @escaping (Bool) -> Void) {
|
func loadLoadInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
guard level <= (LoadINSERTID.count-1) else {
|
||||||
|
print("下载插页广告组已经全部加载失败,停止继续加载")
|
||||||
|
//开始加载全局插页
|
||||||
|
loadGlobalInterstitialAd { status in
|
||||||
|
completion(status)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingLoadInterstitialAd || isLoadInterstitialAdAvailable() {
|
if isLoadingLoadInterstitialAd || isLoadInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -846,16 +939,15 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingLoadInterstitialAd = true
|
isLoadingLoadInterstitialAd = true
|
||||||
|
let item = LoadINSERTID[level]
|
||||||
//加载下载插页广告
|
//加载下载插页广告
|
||||||
GADInterstitialAd.load(withAdUnitID: LoadINSERTID, request: GADRequest()) { ad, error in
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("加载下载插页广告失败,失败原因: \(error.localizedDescription)")
|
print("加载下载插页广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
self.isLoadingLoadInterstitialAd = false
|
self.isLoadingLoadInterstitialAd = false
|
||||||
loadGlobalInterstitialAd { status in
|
loadLoadInterstitialAd(level+1, completion: completion)
|
||||||
completion(status)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.loadInterstitialAd = ad
|
self.loadInterstitialAd = ad
|
||||||
self.isLoadingLoadInterstitialAd = false
|
self.isLoadingLoadInterstitialAd = false
|
||||||
@ -922,9 +1014,9 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
}
|
}
|
||||||
//MARK: - 曲库
|
//MARK: - 曲库
|
||||||
//曲库插页ID
|
//曲库插页ID
|
||||||
private var LibraryINSERTID:String!
|
private var LibraryINSERTID:[MPPositive_AdModelModel] = []
|
||||||
//曲库原生ID
|
//曲库原生ID
|
||||||
private var LibraryNATIVEID:String!
|
private var LibraryNATIVEID:[MPPositive_AdModelModel] = []
|
||||||
///曲库插页广告
|
///曲库插页广告
|
||||||
private var libraryInterstitialAd:GADInterstitialAd?
|
private var libraryInterstitialAd:GADInterstitialAd?
|
||||||
///是否正在加载曲库插页广告
|
///是否正在加载曲库插页广告
|
||||||
@ -967,10 +1059,12 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
let multipleAdOptions = GADMultipleAdsAdLoaderOptions()
|
let multipleAdOptions = GADMultipleAdsAdLoaderOptions()
|
||||||
//加载一条,每次即使结束后重新刷新数据
|
//加载一条,每次即使结束后重新刷新数据
|
||||||
multipleAdOptions.numberOfAds = 2
|
multipleAdOptions.numberOfAds = 2
|
||||||
libraryAdLoader = GADAdLoader(adUnitID: LibraryNATIVEID, rootViewController: vc, adTypes: [.native], options: [multipleAdOptions])
|
if let first = LibraryNATIVEID.first, first.type == .Native {
|
||||||
libraryAdLoader?.delegate = self
|
libraryAdLoader = GADAdLoader(adUnitID: first.identifier, rootViewController: vc, adTypes: [.native], options: [multipleAdOptions])
|
||||||
libraryAdLoader?.load(GADRequest())
|
libraryAdLoader?.delegate = self
|
||||||
libraryNativeAds = []
|
libraryAdLoader?.load(GADRequest())
|
||||||
|
libraryNativeAds = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
///将加载的搜索原生广告添加到页面中
|
///将加载的搜索原生广告添加到页面中
|
||||||
func layoutLibraryNativeAd(in containerView: UIView, index:Int) {
|
func layoutLibraryNativeAd(in containerView: UIView, index:Int) {
|
||||||
@ -1047,8 +1141,16 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return Date().timeIntervalSince(date) < refreshLibraryTimes
|
return Date().timeIntervalSince(date) < refreshLibraryTimes
|
||||||
}
|
}
|
||||||
//异步加载曲库插页广告
|
//异步加载曲库插页广告
|
||||||
func loadLibraryInterstitialAd(completion: @escaping (Bool) -> Void) {
|
func loadLibraryInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
guard level <= (LibraryINSERTID.count-1) else {
|
||||||
|
print("曲库插页广告组已经全部加载失败,停止继续加载")
|
||||||
|
//开始加载全局插页
|
||||||
|
loadGlobalInterstitialAd { status in
|
||||||
|
completion(status)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingLibraryInterstitialAd || isLibraryInterstitialAdAvailable() {
|
if isLoadingLibraryInterstitialAd || isLibraryInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -1056,16 +1158,15 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingLibraryInterstitialAd = true
|
isLoadingLibraryInterstitialAd = true
|
||||||
|
let item = LibraryINSERTID[level]
|
||||||
//加载曲库插页广告
|
//加载曲库插页广告
|
||||||
GADInterstitialAd.load(withAdUnitID: LibraryINSERTID, request: GADRequest()) { ad, error in
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("加载曲库插页广告失败,失败原因: \(error.localizedDescription)")
|
print("加载曲库插页广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
self.isLoadingLibraryInterstitialAd = false
|
self.isLoadingLibraryInterstitialAd = false
|
||||||
loadGlobalInterstitialAd { status in
|
loadLibraryInterstitialAd(level+1, completion: completion)
|
||||||
completion(status)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.libraryInterstitialAd = ad
|
self.libraryInterstitialAd = ad
|
||||||
self.isLoadingLibraryInterstitialAd = false
|
self.isLoadingLibraryInterstitialAd = false
|
||||||
@ -1135,7 +1236,7 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
|
|
||||||
//MARK: - 全局
|
//MARK: - 全局
|
||||||
//全局备用插页ID
|
//全局备用插页ID
|
||||||
private var GlobalINSERTID:String!
|
private var GlobalINSERTID:[MPPositive_AdModelModel] = []
|
||||||
///全局插页广告
|
///全局插页广告
|
||||||
private var globalInterstitialAd:GADInterstitialAd?
|
private var globalInterstitialAd:GADInterstitialAd?
|
||||||
///是否正在加载全局插页广告
|
///是否正在加载全局插页广告
|
||||||
@ -1147,8 +1248,13 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
///全局广告处理闭包
|
///全局广告处理闭包
|
||||||
var completeGlobalInterstitialAdBlock:(() -> Void)?
|
var completeGlobalInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载全局插页广告
|
//异步加载全局插页广告
|
||||||
func loadGlobalInterstitialAd(completion: @escaping (Bool) -> Void) {
|
func loadGlobalInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {return}
|
||||||
|
guard level <= (GlobalINSERTID.count-1) else {
|
||||||
|
print("全局插页广告组已经全部加载失败,停止继续加载")
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingGlobalInterstitialAd || isGlobalInterstitialAdAvailable() {
|
if isLoadingGlobalInterstitialAd || isGlobalInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -1156,14 +1262,15 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoadingGlobalInterstitialAd = true
|
isLoadingGlobalInterstitialAd = true
|
||||||
|
let item = GlobalINSERTID[level]
|
||||||
//加载全局插页广告
|
//加载全局插页广告
|
||||||
GADInterstitialAd.load(withAdUnitID: GlobalINSERTID, request: GADRequest()) { ad, error in
|
GADInterstitialAd.load(withAdUnitID: item.identifier, request: GADRequest()) { ad, error in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("加载全局插页广告失败,失败原因: \(error.localizedDescription)")
|
print("加载全局插页广告失败,失败原因: \(error.localizedDescription),已下调广告ID等级,重新加载")
|
||||||
self.isLoadingGlobalInterstitialAd = false
|
self.isLoadingGlobalInterstitialAd = false
|
||||||
completion(false)
|
loadGlobalInterstitialAd(level+1, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
self.globalInterstitialAd = ad
|
self.globalInterstitialAd = ad
|
||||||
self.isLoadingGlobalInterstitialAd = false
|
self.isLoadingGlobalInterstitialAd = false
|
||||||
@ -1220,12 +1327,13 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
||||||
//覆盖型广告将要将要展示
|
//覆盖型广告将要将要展示
|
||||||
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
if ad === appOpenAd {//开屏广告
|
// UIApplication.shared.isStatusBarHidden = true
|
||||||
print("当前展示的广告是开屏广告,广告ID--\(appOpenAd?.adUnitID ?? "")")
|
if ad === appOpenAd || ad === appInterstitialAd {//开屏广告
|
||||||
|
print("当前展示的广告是开屏广告,广告ID--\(appOpenAd != nil ? (appOpenAd?.adUnitID ?? ""):(appInterstitialAd?.adUnitID ?? ""))")
|
||||||
//判断是冷启动还是热启动
|
//判断是冷启动还是热启动
|
||||||
if appOpenAd?.adUnitID == OpenICEID {
|
if OpenICEID.contains(where: {($0.identifier == (appOpenAd?.adUnitID ?? "") || $0.identifier == (appInterstitialAd?.adUnitID ?? ""))}) {
|
||||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction()
|
MP_AnalyticsManager.shared.cold_ads_showSuccessAction()
|
||||||
}else if appOpenAd?.adUnitID == OpenHOSTID {
|
}else if OpenHOSTID.contains(where: {($0.identifier == (appOpenAd?.adUnitID ?? "") || $0.identifier == (appInterstitialAd?.adUnitID ?? ""))}) {
|
||||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction()
|
MP_AnalyticsManager.shared.hot_ads_showSuccessAction()
|
||||||
}
|
}
|
||||||
}else if ad === searchInterstitialAd {//搜索插页广告
|
}else if ad === searchInterstitialAd {//搜索插页广告
|
||||||
@ -1249,10 +1357,11 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
}
|
}
|
||||||
//覆盖型广告已经消失
|
//覆盖型广告已经消失
|
||||||
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
//更新插页广告展示时间
|
//更新插页广告展示时间
|
||||||
interstitialDate = Date()
|
interstitialDate = Date()
|
||||||
if ad === appOpenAd {//开屏广告
|
if ad === appOpenAd || ad === appInterstitialAd {//开屏广告
|
||||||
print("当前消失的广告是开屏广告,广告ID--\(appOpenAd?.adUnitID ?? "")")
|
print("当前消失的广告是开屏广告,广告ID--\(appOpenAd != nil ? (appOpenAd?.adUnitID ?? ""):(appInterstitialAd?.adUnitID ?? ""))")
|
||||||
//执行开屏广告完成事件包
|
//执行开屏广告完成事件包
|
||||||
if completeOpenAdBlock != nil {
|
if completeOpenAdBlock != nil {
|
||||||
completeOpenAdBlock!()
|
completeOpenAdBlock!()
|
||||||
@ -1294,18 +1403,23 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
completeGlobalInterstitialAdBlock!()
|
completeGlobalInterstitialAdBlock!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//覆盖型广告加载出错
|
//覆盖型广告加载出错
|
||||||
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
//更新插页广告展示时间
|
//更新插页广告展示时间
|
||||||
interstitialDate = Date()
|
interstitialDate = Date()
|
||||||
if ad === appOpenAd {//开屏广告
|
if ad === appOpenAd || ad === appInterstitialAd {//应用开屏广告
|
||||||
print("开屏广告展示时出错,广告ID--\(appOpenAd?.adUnitID ?? ""),具体错误原因:\(error.localizedDescription)")
|
print("开屏广告展示时出错,广告ID--\(appOpenAd != nil ? (appOpenAd?.adUnitID ?? ""):(appInterstitialAd?.adUnitID ?? "")),具体错误原因:\(error.localizedDescription)")
|
||||||
//判断是冷启动还是热启动
|
//判断是冷启动还是热启动
|
||||||
if appOpenAd?.adUnitID == OpenICEID {
|
if OpenICEID.contains(where: {($0.identifier == (appOpenAd?.adUnitID ?? "") || $0.identifier == (appInterstitialAd?.adUnitID ?? ""))}) {
|
||||||
MP_AnalyticsManager.shared.cold_ads_showFailureAction(error.localizedDescription)
|
MP_AnalyticsManager.shared.cold_ads_showFailureAction(error.localizedDescription)
|
||||||
}else if appOpenAd?.adUnitID == OpenHOSTID {
|
}else if OpenHOSTID.contains(where: {($0.identifier == (appOpenAd?.adUnitID ?? "") || $0.identifier == (appInterstitialAd?.adUnitID ?? ""))}) {
|
||||||
MP_AnalyticsManager.shared.hot_ads_showFailureAction(error.localizedDescription)
|
MP_AnalyticsManager.shared.hot_ads_showFailureAction(error.localizedDescription)
|
||||||
}
|
}
|
||||||
if completeOpenAdBlock != nil {
|
if completeOpenAdBlock != nil {
|
||||||
@ -1350,7 +1464,11 @@ class MP_AdMobManager: NSObject, GADFullScreenContentDelegate, GADNativeAdLoader
|
|||||||
completeGlobalInterstitialAdBlock!()
|
completeGlobalInterstitialAdBlock!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//MARK: - GADNativeAdLoaderDelegate
|
//MARK: - GADNativeAdLoaderDelegate
|
||||||
// 原生广告已展示。
|
// 原生广告已展示。
|
||||||
|
|||||||
@ -23,6 +23,8 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
private let app_crash:String = "app_crash"
|
private let app_crash:String = "app_crash"
|
||||||
//启动页曝光
|
//启动页曝光
|
||||||
private let launch_pv:String = "launch_pv"
|
private let launch_pv:String = "launch_pv"
|
||||||
|
//启动页计时结束点
|
||||||
|
private let launch_progress_end:String = "launch_progress_end"
|
||||||
//跳转页面动作
|
//跳转页面动作
|
||||||
private let jump_event:String = "jump_event"
|
private let jump_event:String = "jump_event"
|
||||||
//A面首页曝光
|
//A面首页曝光
|
||||||
@ -63,6 +65,8 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
private let player_b_downloadfailure_error = "player_b_downloadfailure_error"
|
private let player_b_downloadfailure_error = "player_b_downloadfailure_error"
|
||||||
//B面搜索曝光
|
//B面搜索曝光
|
||||||
private let search_pv = "search_pv"
|
private let search_pv = "search_pv"
|
||||||
|
//B面搜索心情流派模块点击
|
||||||
|
private let grid_mood_click = "grid_mood_click"
|
||||||
//搜索SUG曝光
|
//搜索SUG曝光
|
||||||
private let search_sug_show = "search_sug_show"
|
private let search_sug_show = "search_sug_show"
|
||||||
//点击sug结果
|
//点击sug结果
|
||||||
@ -114,14 +118,23 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
print("更新了插页广告时长间隔")
|
print("更新了插页广告时长间隔")
|
||||||
}
|
}
|
||||||
//更新广告ID设置
|
//更新广告ID设置
|
||||||
// if let content = self.remoteConfig.configValue(forKey: "adMobIDs").jsonValue as? [String:String] {
|
if let adTextIDs = self.remoteConfig.configValue(forKey: "adMobLevelIDs").jsonValue as? [String:[[String:Any]]] {
|
||||||
// //对所有广告ID进行更新
|
//对所有广告ID组进行更新
|
||||||
// for (key, value) in content {
|
for (key, values) in adTextIDs {
|
||||||
// UserDefaults.standard.setValue(value, forKey: key)
|
var array:[MPPositive_AdModelModel] = []
|
||||||
// }
|
values.forEach { value in
|
||||||
// print("更新了所有广告ID")
|
if let level = value["level"] as? Int, let identifier = value["identifier"] as? String, let ad = value["ad"] as? String, let item = value["type"] as? String, let type = MPPositive_AdModelType(rawValue: item) {
|
||||||
// MP_AdMobManager.shared.reloadAdMobIDs()
|
array.append(.init(level: level, identifier: identifier, ad: ad, type: type))
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
//将array转为jsonData
|
||||||
|
if let data = coreAdModelforJson(array) {
|
||||||
|
UserDefaults.standard.set(data, forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("更新了所有广告ID")
|
||||||
|
MP_AdMobManager.shared.reloadAdMobIDs()
|
||||||
|
}
|
||||||
//更新版本数据设置
|
//更新版本数据设置
|
||||||
if let versionData = self.remoteConfig.configValue(forKey: "dataVersion").jsonValue as? [String:String] {
|
if let versionData = self.remoteConfig.configValue(forKey: "dataVersion").jsonValue as? [String:String] {
|
||||||
//对数据进行更新
|
//对数据进行更新
|
||||||
@ -131,6 +144,17 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
print("更新了所有版本数据")
|
print("更新了所有版本数据")
|
||||||
MP_NetWorkManager.shared.reloadVersion()
|
MP_NetWorkManager.shared.reloadVersion()
|
||||||
}
|
}
|
||||||
|
//更新通知内容
|
||||||
|
if let notificationBodyTexts = self.remoteConfig.configValue(forKey: "notificationBodyTexts").jsonValue as? [String:[String]] {
|
||||||
|
//对数据进行更新
|
||||||
|
for (key, value) in notificationBodyTexts {
|
||||||
|
UserDefaults.standard.setValue(value, forKey: key)
|
||||||
|
}
|
||||||
|
print("更新了通知文本数据")
|
||||||
|
//更新通知
|
||||||
|
scheduleDailyNotifications()
|
||||||
|
}
|
||||||
|
|
||||||
let js = self.remoteConfig.configValue(forKey: "openStatus").jsonValue as! [String:Any]
|
let js = self.remoteConfig.configValue(forKey: "openStatus").jsonValue as! [String:Any]
|
||||||
let value = js["versionCode"] as! String
|
let value = js["versionCode"] as! String
|
||||||
if value == app_Version {
|
if value == app_Version {
|
||||||
@ -186,6 +210,10 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
func launch_pvAction(){
|
func launch_pvAction(){
|
||||||
Analytics.logEvent(launch_pv, parameters: nil)
|
Analytics.logEvent(launch_pv, parameters: nil)
|
||||||
}
|
}
|
||||||
|
///启动页进度结束时间
|
||||||
|
func launch_progress_endAction() {
|
||||||
|
Analytics.logEvent(launch_progress_end, parameters: nil)
|
||||||
|
}
|
||||||
///跳转事件
|
///跳转事件
|
||||||
func jump_eventAction(_ side:String, reason:String) {
|
func jump_eventAction(_ side:String, reason:String) {
|
||||||
Analytics.logEvent(jump_event, parameters: ["side":side,
|
Analytics.logEvent(jump_event, parameters: ["side":side,
|
||||||
@ -339,6 +367,10 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
func search_pvAction(){
|
func search_pvAction(){
|
||||||
Analytics.logEvent(search_pv, parameters: nil)
|
Analytics.logEvent(search_pv, parameters: nil)
|
||||||
}
|
}
|
||||||
|
///B面搜索心情流派模块点击
|
||||||
|
func grid_mood_clickAction(_ mood:String) {
|
||||||
|
Analytics.logEvent(grid_mood_click, parameters: ["mood":mood])
|
||||||
|
}
|
||||||
///搜索SUG曝光
|
///搜索SUG曝光
|
||||||
func search_sug_showAction(){
|
func search_sug_showAction(){
|
||||||
Analytics.logEvent(search_sug_show, parameters: nil)
|
Analytics.logEvent(search_sug_show, parameters: nil)
|
||||||
|
|||||||
@ -27,14 +27,24 @@ class MP_CoreDataHandlerManager {
|
|||||||
}
|
}
|
||||||
return container
|
return container
|
||||||
}()
|
}()
|
||||||
//托管(映射)对象空间
|
//主线程托管(映射)对象空间
|
||||||
var context: NSManagedObjectContext {
|
var context: NSManagedObjectContext {
|
||||||
return persistentContainer.viewContext
|
return persistentContainer.viewContext
|
||||||
}
|
}
|
||||||
//后台托管对象空间
|
// 全局后台托管对象空间
|
||||||
var backgroundContext: NSManagedObjectContext {
|
var backgroundContext: NSManagedObjectContext{
|
||||||
return persistentContainer.newBackgroundContext()
|
return persistentContainer.newBackgroundContext()
|
||||||
}
|
}
|
||||||
|
private init() {
|
||||||
|
// 在应用启动或合适的地方设置监听
|
||||||
|
NotificationCenter.default.addObserver(self,
|
||||||
|
selector: #selector(mergeChangesFromBackgroundContext),
|
||||||
|
name: .NSManagedObjectContextDidSave,
|
||||||
|
object: nil)
|
||||||
|
}
|
||||||
|
deinit{
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
}
|
||||||
//主线程保存对象空间
|
//主线程保存对象空间
|
||||||
func saveContext() {
|
func saveContext() {
|
||||||
//线程安全
|
//线程安全
|
||||||
@ -47,41 +57,42 @@ class MP_CoreDataHandlerManager {
|
|||||||
try context.save()
|
try context.save()
|
||||||
} catch {
|
} catch {
|
||||||
//保存失败
|
//保存失败
|
||||||
let nserror = error as NSError
|
print("数据库更新失败,错误详情:\(error.localizedDescription)")
|
||||||
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// //检索对象空间是否进行了更新
|
|
||||||
// if context.hasChanges {
|
|
||||||
// //线程安全
|
|
||||||
// context.perform {
|
|
||||||
// [weak self] in
|
|
||||||
// guard let self = self else {return}
|
|
||||||
// do {
|
|
||||||
// //保存对象空间
|
|
||||||
// try context.save()
|
|
||||||
// } catch {
|
|
||||||
// //保存失败
|
|
||||||
// let nserror = error as NSError
|
|
||||||
// fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
//后台保存
|
///后台保存对象空间
|
||||||
func saveContextInBackground() {
|
func saveContextInBackground() {
|
||||||
|
|
||||||
backgroundContext.perform {
|
backgroundContext.perform {
|
||||||
[weak self] in
|
[weak self] in
|
||||||
guard let self = self else {return}
|
guard let self = self else { return }
|
||||||
if backgroundContext.hasChanges {
|
if backgroundContext.hasChanges {
|
||||||
do {
|
do {
|
||||||
try backgroundContext.save()
|
try backgroundContext.save()
|
||||||
|
// 后台保存成功后发送通知
|
||||||
|
NotificationCenter.default.post(name: .NSManagedObjectContextDidSave, object: backgroundContext)
|
||||||
} catch {
|
} catch {
|
||||||
// 处理错误,比如记录错误日志
|
// 记录错误信息,而不是打印
|
||||||
print("后台保存失败: \(error), \(error.localizedDescription)")
|
let nserror = error as NSError
|
||||||
|
// 这里可以使用日志系统记录错误
|
||||||
|
// 例如:self.logError(nserror)
|
||||||
|
print("后台保存失败: \(nserror), \(nserror.userInfo)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@objc func mergeChangesFromBackgroundContext(notification: Notification) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// 从通知中获取上下文
|
||||||
|
guard let backgroundContext = notification.object as? NSManagedObjectContext else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 合并更改
|
||||||
|
self.context.perform {
|
||||||
|
self.context.mergeChanges(fromContextDidSave: notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,11 +68,11 @@ class MP_NetWorkManager: NSObject {
|
|||||||
private var playerVersion:String!
|
private var playerVersion:String!
|
||||||
///禁止接入IP信息组
|
///禁止接入IP信息组
|
||||||
private let banIPs:[String] = [
|
private let banIPs:[String] = [
|
||||||
// "CN",
|
"CN",
|
||||||
// "HK",
|
"HK",
|
||||||
// "TW",
|
"TW",
|
||||||
// "JP",
|
"JP",
|
||||||
// "KR"
|
"KR"
|
||||||
]
|
]
|
||||||
///允许访问的区域Code(对部分内容进行塞选)
|
///允许访问的区域Code(对部分内容进行塞选)
|
||||||
private let codes:[String] = [
|
private let codes:[String] = [
|
||||||
@ -657,6 +657,105 @@ extension MP_NetWorkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///请求模块数据
|
||||||
|
func requestGenres(_ completion:@escaping (([MPPositive_GridViewModel]) -> Void)) {
|
||||||
|
//拼接出browse路径
|
||||||
|
let path = header+point+browse
|
||||||
|
//设置url
|
||||||
|
guard let url = URL(string: path) else {
|
||||||
|
print("Url is Incorrect")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//设置参数
|
||||||
|
let parameters:[String:Any] = [
|
||||||
|
"browseId": "FEmusic_moods_and_genres",
|
||||||
|
"prettyPrint":"false",
|
||||||
|
"context":[
|
||||||
|
"client":[
|
||||||
|
//web端
|
||||||
|
"clientName": "WEB_REMIX",
|
||||||
|
//当前访问版本(日期值)
|
||||||
|
"clientVersion": clientVersion,
|
||||||
|
"platform":"MOBILE",
|
||||||
|
//语言
|
||||||
|
"hl":Language_first_local,
|
||||||
|
//地址
|
||||||
|
"gl":locaton ?? ""
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
requestPostGenres(url, parameters: parameters) { array in
|
||||||
|
completion(array)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///请求模块数据
|
||||||
|
private func requestPostGenres(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_GridViewModel]) -> Void)) {
|
||||||
|
//发送post请求
|
||||||
|
MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonGenres.self) { [weak self] (response) in
|
||||||
|
guard let self = self else {return}
|
||||||
|
switch response.result {
|
||||||
|
case .success(let value):
|
||||||
|
if let contents = value.contents?.singleColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents {
|
||||||
|
let array = parsingGenres(contents)
|
||||||
|
completion(array)
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
// 请求失败,处理错误
|
||||||
|
handleError(url, error: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///请求模块详情数据
|
||||||
|
func requestMoodDetails(_ browseId:String, params:String, completion:@escaping (([MPPositive_BrowseModuleListViewModel]) -> Void)) {
|
||||||
|
//拼接出browse路径
|
||||||
|
let path = header+point+browse
|
||||||
|
//设置url
|
||||||
|
guard let url = URL(string: path) else {
|
||||||
|
print("Url is Incorrect")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//设置参数
|
||||||
|
let parameters:[String:Any] = [
|
||||||
|
"browseId": browseId,
|
||||||
|
"params":params,
|
||||||
|
"prettyPrint":"false",
|
||||||
|
"context":[
|
||||||
|
"client":[
|
||||||
|
//web端
|
||||||
|
"clientName": "WEB_REMIX",
|
||||||
|
//当前访问版本(日期值)
|
||||||
|
"clientVersion": clientVersion,
|
||||||
|
"platform":"MOBILE",
|
||||||
|
//语言
|
||||||
|
"hl":Language_first_local,
|
||||||
|
//地址
|
||||||
|
"gl":locaton ?? ""
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
requestPostMoodDetails(url, parameters: parameters) { array in
|
||||||
|
completion(array)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///请求模块详情数据
|
||||||
|
private func requestPostMoodDetails(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_BrowseModuleListViewModel]) -> Void)) {
|
||||||
|
MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonBrowses.self) { [weak self] (response) in
|
||||||
|
guard let self = self else {return}
|
||||||
|
switch response.result {
|
||||||
|
case .success(let value):
|
||||||
|
//解析结构体
|
||||||
|
let tab = value.contents?.singleColumnBrowseResultsRenderer?.tabs?[0]
|
||||||
|
if let content = tab?.tabRenderer?.content {
|
||||||
|
let array = parsingMoodDetails(content)
|
||||||
|
completion(array)
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
print("Failed to parse browses content")
|
||||||
|
// 请求失败,处理错误
|
||||||
|
handleError(url, error: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - 请求列表专辑下一部分
|
//MARK: - 请求列表专辑下一部分
|
||||||
///请求Next列表(优先于Player)
|
///请求Next列表(优先于Player)
|
||||||
@ -1673,7 +1772,64 @@ extension MP_NetWorkManager {
|
|||||||
return (nil,nil)
|
return (nil,nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///解析模块数据_Genres
|
||||||
|
private func parsingGenres(_ contents:[JsonGenres.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content]) -> [MPPositive_GridViewModel] {
|
||||||
|
var array:[MPPositive_GridViewModel] = []
|
||||||
|
contents.forEach { content in
|
||||||
|
if let items = content.gridRenderer?.items {
|
||||||
|
items.forEach { item in
|
||||||
|
if let text = item.musicNavigationButtonRenderer?.buttonText?.runs?.first?.text, let leftStripeColor = item.musicNavigationButtonRenderer?.solid?.leftStripeColor, let browseId = item.musicNavigationButtonRenderer?.clickCommand?.browseEndpoint?.browseId, let params = item.musicNavigationButtonRenderer?.clickCommand?.browseEndpoint?.params {
|
||||||
|
let gride = MPPositive_GridModel(title: text, stringColor: leftStripeColor, browseId: browseId, params: params)
|
||||||
|
array.append(.init(gride))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
///解析模块详情数据_Mood
|
||||||
|
private func parsingMoodDetails(_ content:JsonBrowses.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content) -> [MPPositive_BrowseModuleListViewModel] {
|
||||||
|
//获取预览结构体中需要的数据(模块标题;歌曲信息:封面路径,音乐标题,歌手姓名,列表id和视频id)
|
||||||
|
var browses:[MPPositive_BrowseModuleListViewModel] = []
|
||||||
|
//循环获取音乐内容
|
||||||
|
content.sectionListRenderer?.contents?.forEach({ content in
|
||||||
|
//该循环获取预览模块内容,生成一个预览模型接收数据
|
||||||
|
let browse = MPPositive_BrowseModuleListViewModel()
|
||||||
|
if let musicCarouselShelfRenderer = content.musicCarouselShelfRenderer {
|
||||||
|
browse.title = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.text
|
||||||
|
//循环音乐内容组
|
||||||
|
musicCarouselShelfRenderer.contents?.forEach({ content in
|
||||||
|
//设置标题、歌手、专辑/列表
|
||||||
|
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||||
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
|
browse.items.append(.init(item))
|
||||||
|
}
|
||||||
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||||
|
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if browse.items.isEmpty != true {
|
||||||
|
browses.append(browse)
|
||||||
|
}
|
||||||
|
}else if let gridRenderer = content.gridRenderer {
|
||||||
|
browse.title = gridRenderer.header?.gridHeaderRenderer?.title?.runs?.first?.text
|
||||||
|
gridRenderer.items?.forEach({ content in
|
||||||
|
//设置标题、歌手、专辑/列表
|
||||||
|
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
|
||||||
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
|
browse.items.append(.init(item))
|
||||||
|
}
|
||||||
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||||
|
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if browse.items.isEmpty != true {
|
||||||
|
browses.append(browse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return browses
|
||||||
|
}
|
||||||
/// 解析播放器_Player
|
/// 解析播放器_Player
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - player: player库
|
/// - player: player库
|
||||||
|
|||||||
@ -310,15 +310,21 @@ class MP_PlayerManager:NSObject{
|
|||||||
print("当前音乐-\(loadPlayer?.currentVideo?.title ?? "") 已经准备好播放")
|
print("当前音乐-\(loadPlayer?.currentVideo?.title ?? "") 已经准备好播放")
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
print("当前音乐-\(loadPlayer?.currentVideo?.title ?? "") 未做好准备播放,失败原因是\(loadPlayer?.currentVideo?.resourcePlayerItem.error?.localizedDescription ?? "")")
|
if let currentVideo = loadPlayer?.currentVideo {
|
||||||
MP_AnalyticsManager.shared.player_b_failure_errorAction(loadPlayer?.currentVideo?.song.videoId ?? "", videoname: loadPlayer?.currentVideo?.title ?? "", artistname: loadPlayer?.currentVideo?.song.shortBylineText ?? "", error: loadPlayer?.currentVideo?.resourcePlayerItem.error?.localizedDescription ?? "Failed to buffer data")
|
print("当前音乐-\(currentVideo.title ?? "") 未做好准备播放,失败原因是\(currentVideo.resourcePlayerItem.error?.localizedDescription ?? "")")
|
||||||
if loadPlayer?.currentVideo?.isKVO == true {
|
MP_AnalyticsManager.shared.player_b_failure_errorAction(currentVideo.song.videoId ?? "", videoname: currentVideo.title ?? "", artistname: currentVideo.song.shortBylineText ?? "", error: currentVideo.resourcePlayerItem.error?.localizedDescription ?? "Failed to buffer data")
|
||||||
suspendTimer()
|
if loadPlayer?.currentVideo?.isKVO == true {
|
||||||
loadPlayer?.currentVideo?.isKVO = false
|
suspendTimer()
|
||||||
//重新配置数据
|
loadPlayer?.currentVideo?.isKVO = false
|
||||||
loadPlayer?.remakeImproveData {
|
statusObservation?.invalidate()
|
||||||
[weak self] in
|
loadedTimeRangesObservation?.invalidate()
|
||||||
self?.play()
|
playbackLikelyToKeepUpObservation?.invalidate()
|
||||||
|
errorObservation?.invalidate()
|
||||||
|
//重新配置数据
|
||||||
|
loadPlayer?.remakeImproveData {
|
||||||
|
[weak self] in
|
||||||
|
self?.play()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,15 +140,19 @@ struct JsonBrowses: Codable {
|
|||||||
}
|
}
|
||||||
///图像数据内容
|
///图像数据内容
|
||||||
struct Content: Codable {
|
struct Content: Codable {
|
||||||
|
///常态数据通用
|
||||||
let musicCarouselShelfRenderer:MusicCarouselShelfRenderer?
|
let musicCarouselShelfRenderer:MusicCarouselShelfRenderer?
|
||||||
|
///模块详情特化
|
||||||
|
let gridRenderer:GridRenderer?
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case musicCarouselShelfRenderer = "musicCarouselShelfRenderer"
|
case musicCarouselShelfRenderer = "musicCarouselShelfRenderer"
|
||||||
|
case gridRenderer = "gridRenderer"
|
||||||
}
|
}
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
musicCarouselShelfRenderer = try values.decodeIfPresent(MusicCarouselShelfRenderer.self, forKey: .musicCarouselShelfRenderer)
|
musicCarouselShelfRenderer = try values.decodeIfPresent(MusicCarouselShelfRenderer.self, forKey: .musicCarouselShelfRenderer)
|
||||||
|
gridRenderer = try values.decodeIfPresent(GridRenderer.self, forKey: .gridRenderer)
|
||||||
}
|
}
|
||||||
struct MusicCarouselShelfRenderer: Codable {
|
struct MusicCarouselShelfRenderer: Codable {
|
||||||
///指向模块标题
|
///指向模块标题
|
||||||
@ -226,6 +230,82 @@ struct JsonBrowses: Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct GridRenderer: Codable {
|
||||||
|
let items:[Item]?
|
||||||
|
let header:Header?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case items = "items"
|
||||||
|
case header = "header"
|
||||||
|
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
items = try values.decodeIfPresent([Item].self, forKey: .items)
|
||||||
|
header = try values.decodeIfPresent(Header.self, forKey: .header)
|
||||||
|
}
|
||||||
|
struct Item: Codable {
|
||||||
|
///常规列表(通常是四组件构成,封面,一级标题,二级标题,三级标题,额外包含ID内容,通常是单曲)
|
||||||
|
let musicResponsiveListItemRenderer:RootMusicResponsiveListItemRenderer?
|
||||||
|
///两行式列表(通常是三组件构成,封面,一级标题,二级标题,额外包含ID内容,通常是歌单)
|
||||||
|
let musicTwoRowItemRenderer:RootMusicTwoRowItemRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case musicResponsiveListItemRenderer = "musicResponsiveListItemRenderer"
|
||||||
|
case musicTwoRowItemRenderer = "musicTwoRowItemRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
musicResponsiveListItemRenderer = try values.decodeIfPresent(RootMusicResponsiveListItemRenderer.self, forKey: .musicResponsiveListItemRenderer)
|
||||||
|
musicTwoRowItemRenderer = try values.decodeIfPresent(RootMusicTwoRowItemRenderer.self, forKey: .musicTwoRowItemRenderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct Header: Codable {
|
||||||
|
let gridHeaderRenderer:GridHeaderRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case gridHeaderRenderer = "gridHeaderRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
gridHeaderRenderer = try values.decodeIfPresent(GridHeaderRenderer.self, forKey: .gridHeaderRenderer)
|
||||||
|
}
|
||||||
|
struct GridHeaderRenderer: Codable {
|
||||||
|
let title:Title?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case title = "title"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
title = try values.decodeIfPresent(Title.self, forKey: .title)
|
||||||
|
}
|
||||||
|
struct Title: Codable {
|
||||||
|
///一般是第0位
|
||||||
|
let runs:[Run]?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case runs = "runs"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
runs = try values.decodeIfPresent([Run].self, forKey: .runs)
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - 文本内容,标题/作者/专辑
|
||||||
|
struct Run: Codable {
|
||||||
|
///关键文本内容(代表各级标题)
|
||||||
|
let text:String?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case text = "text"
|
||||||
|
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
text = try values.decodeIfPresent(String.self, forKey: .text)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
///续页编码
|
///续页编码
|
||||||
struct Continuation: Codable {
|
struct Continuation: Codable {
|
||||||
|
|||||||
@ -0,0 +1,231 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_JsonGenres.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
///心情与流派结构
|
||||||
|
struct JsonGenres: Codable {
|
||||||
|
let contents:Contents?
|
||||||
|
let header:Header?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case contents = "contents"
|
||||||
|
case header = "header"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
contents = try values.decodeIfPresent(Contents.self, forKey: .contents)
|
||||||
|
header = try values.decodeIfPresent(Header.self, forKey: .header)
|
||||||
|
}
|
||||||
|
struct Contents: Codable {
|
||||||
|
let singleColumnBrowseResultsRenderer:SingleColumnBrowseResultsRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case singleColumnBrowseResultsRenderer = "singleColumnBrowseResultsRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
singleColumnBrowseResultsRenderer = try values.decodeIfPresent(SingleColumnBrowseResultsRenderer.self, forKey: .singleColumnBrowseResultsRenderer)
|
||||||
|
}
|
||||||
|
struct SingleColumnBrowseResultsRenderer: Codable {
|
||||||
|
let tabs:[Tab]?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case tabs = "tabs"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
tabs = try values.decodeIfPresent([Tab].self, forKey: .tabs)
|
||||||
|
}
|
||||||
|
struct Tab:Codable {
|
||||||
|
let tabRenderer:TabRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case tabRenderer = "tabRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
tabRenderer = try values.decodeIfPresent(TabRenderer.self, forKey: .tabRenderer)
|
||||||
|
}
|
||||||
|
struct TabRenderer: Codable {
|
||||||
|
let content:Content?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case content = "content"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
content = try values.decodeIfPresent(Content.self, forKey: .content)
|
||||||
|
}
|
||||||
|
struct Content: Codable {
|
||||||
|
let sectionListRenderer:SectionListRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case sectionListRenderer = "sectionListRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
sectionListRenderer = try values.decodeIfPresent(SectionListRenderer.self, forKey: .sectionListRenderer)
|
||||||
|
}
|
||||||
|
struct SectionListRenderer: Codable {
|
||||||
|
let contents:[Content]?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case contents = "contents"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
contents = try values.decodeIfPresent([Content].self, forKey: .contents)
|
||||||
|
}
|
||||||
|
struct Content: Codable {
|
||||||
|
let gridRenderer:GridRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case gridRenderer = "gridRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
gridRenderer = try values.decodeIfPresent(GridRenderer.self, forKey: .gridRenderer)
|
||||||
|
}
|
||||||
|
struct GridRenderer: Codable {
|
||||||
|
let items:[Item]?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case items = "items"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
items = try values.decodeIfPresent([Item].self, forKey: .items)
|
||||||
|
}
|
||||||
|
struct Item: Codable {
|
||||||
|
let musicNavigationButtonRenderer:MusicNavigationButtonRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case musicNavigationButtonRenderer = "musicNavigationButtonRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
musicNavigationButtonRenderer = try values.decodeIfPresent(MusicNavigationButtonRenderer.self, forKey: .musicNavigationButtonRenderer)
|
||||||
|
}
|
||||||
|
struct MusicNavigationButtonRenderer: Codable {
|
||||||
|
///对应标题
|
||||||
|
let buttonText:ButtonText?
|
||||||
|
///对应颜色
|
||||||
|
let solid:Solid?
|
||||||
|
///点击事件
|
||||||
|
let clickCommand:ClickCommand?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case buttonText = "buttonText"
|
||||||
|
case solid = "solid"
|
||||||
|
case clickCommand = "clickCommand"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
buttonText = try values.decodeIfPresent(ButtonText.self, forKey: .buttonText)
|
||||||
|
solid = try values.decodeIfPresent(Solid.self, forKey: .solid)
|
||||||
|
clickCommand = try values.decodeIfPresent(ClickCommand.self, forKey: .clickCommand)
|
||||||
|
}
|
||||||
|
//对应标题
|
||||||
|
struct ButtonText: Codable{
|
||||||
|
//标题组
|
||||||
|
let runs:[Run]?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case runs = "runs"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
runs = try values.decodeIfPresent([Run].self, forKey: .runs)
|
||||||
|
}
|
||||||
|
struct Run: Codable {
|
||||||
|
//标题文本
|
||||||
|
let text:String?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case text = "text"
|
||||||
|
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
text = try values.decodeIfPresent(String.self, forKey: .text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//对应颜色
|
||||||
|
struct Solid: Codable {
|
||||||
|
///颜色值
|
||||||
|
let leftStripeColor:Int?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case leftStripeColor = "leftStripeColor"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
leftStripeColor = try values.decodeIfPresent(Int.self, forKey: .leftStripeColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//对应事件
|
||||||
|
struct ClickCommand: Codable {
|
||||||
|
let browseEndpoint:BrowseEndpoint?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case browseEndpoint = "browseEndpoint"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint)
|
||||||
|
}
|
||||||
|
struct BrowseEndpoint: Codable {
|
||||||
|
let browseId:String?
|
||||||
|
let params:String?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case browseId = "browseId"
|
||||||
|
case params = "params"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
browseId = try values.decodeIfPresent(String.self, forKey: .browseId)
|
||||||
|
params = try values.decodeIfPresent(String.self, forKey: .params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct Header: Codable {
|
||||||
|
let musicHeaderRenderer:MusicHeaderRenderer?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case musicHeaderRenderer = "musicHeaderRenderer"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
musicHeaderRenderer = try values.decodeIfPresent(MusicHeaderRenderer.self, forKey: .musicHeaderRenderer)
|
||||||
|
}
|
||||||
|
struct MusicHeaderRenderer: Codable {
|
||||||
|
let title:Title?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case title = "title"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
title = try values.decodeIfPresent(Title.self, forKey: .title)
|
||||||
|
}
|
||||||
|
struct Title: Codable {
|
||||||
|
let runs:[Run]?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case runs = "runs"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
runs = try values.decodeIfPresent([Run].self, forKey: .runs)
|
||||||
|
}
|
||||||
|
struct Run: Codable {
|
||||||
|
let text:String?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case text = "text"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
text = try values.decodeIfPresent(String.self, forKey: .text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_AdModelModel.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/10.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
///广告模型
|
||||||
|
class MPPositive_AdModelModel: NSObject, Codable {
|
||||||
|
///阶级(从高到低)
|
||||||
|
var level:Int
|
||||||
|
///id内容
|
||||||
|
var identifier:String
|
||||||
|
///广告商
|
||||||
|
var ad:String
|
||||||
|
///广告类型
|
||||||
|
var type:MPPositive_AdModelType
|
||||||
|
init(level: Int, identifier: String, ad: String, type:MPPositive_AdModelType) {
|
||||||
|
self.level = level
|
||||||
|
self.identifier = identifier
|
||||||
|
self.ad = ad
|
||||||
|
self.type = type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enum MPPositive_AdModelType: String, Codable {
|
||||||
|
///开屏
|
||||||
|
case Open = "Open"
|
||||||
|
///插页
|
||||||
|
case Insert = "Insert"
|
||||||
|
///原生
|
||||||
|
case Native = "Native"
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_GridModel.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class MPPositive_GridModel: NSObject, Codable {
|
||||||
|
///标题
|
||||||
|
var title:String
|
||||||
|
///颜色阈值
|
||||||
|
var stringColor:Int
|
||||||
|
///预览id
|
||||||
|
var browseId:String
|
||||||
|
///params
|
||||||
|
var params:String
|
||||||
|
|
||||||
|
init(title: String, stringColor: Int, browseId: String, params: String) {
|
||||||
|
self.title = title
|
||||||
|
self.stringColor = stringColor
|
||||||
|
self.browseId = browseId
|
||||||
|
self.params = params
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_GridViewModel.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
///模块ViewModel
|
||||||
|
class MPPositive_GridViewModel: NSObject, Codable {
|
||||||
|
///标题文本
|
||||||
|
var title:String?
|
||||||
|
///颜色
|
||||||
|
var stringColor:Int64?
|
||||||
|
///模块本身
|
||||||
|
var grid:MPPositive_GridModel
|
||||||
|
init(_ grid:MPPositive_GridModel) {
|
||||||
|
self.grid = grid
|
||||||
|
super.init()
|
||||||
|
configure()
|
||||||
|
}
|
||||||
|
//生成配置
|
||||||
|
private func configure() {
|
||||||
|
self.title = self.grid.title
|
||||||
|
self.stringColor = Int64(self.grid.stringColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -92,6 +92,8 @@ class MPPositive_BrowseLoadViewModel: NSObject {
|
|||||||
browseModuleLists.removeAll()
|
browseModuleLists.removeAll()
|
||||||
//调用网络请求工具的预览请求
|
//调用网络请求工具的预览请求
|
||||||
MP_NetWorkManager.shared.requestBrowseDatas()
|
MP_NetWorkManager.shared.requestBrowseDatas()
|
||||||
|
//同步更新gride
|
||||||
|
MPPositive_GridLoadViewModel.shared.reloadGrides()
|
||||||
}
|
}
|
||||||
///缓存预览数据
|
///缓存预览数据
|
||||||
private func cacheResponseData(_ array: [MPPositive_BrowseModuleListViewModel]) {
|
private func cacheResponseData(_ array: [MPPositive_BrowseModuleListViewModel]) {
|
||||||
|
|||||||
@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_GridLoadViewModel.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/12.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class MPPositive_GridLoadViewModel: NSObject {
|
||||||
|
static let shared = MPPositive_GridLoadViewModel()
|
||||||
|
var grideViewModels:[MPPositive_GridViewModel] = []
|
||||||
|
|
||||||
|
private override init() {
|
||||||
|
super.init()
|
||||||
|
if let data = chachedData() {
|
||||||
|
grideViewModels = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//更新grideModel
|
||||||
|
func reloadGrides() {
|
||||||
|
MP_NetWorkManager.shared.requestGenres { [weak self] array in
|
||||||
|
guard let self = self else {return}
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.grideViewModels = array
|
||||||
|
self.cacheResponseData(self.grideViewModels)
|
||||||
|
//发布通知
|
||||||
|
NotificationCenter.notificationKey.post(notificationName: .search_gride_reload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//存入默认数据
|
||||||
|
private func cacheResponseData(_ array: [MPPositive_GridViewModel]) {
|
||||||
|
guard grideViewModels.count != 0 else {
|
||||||
|
print("Search Gride数据未加载,无法缓存")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//将数据转为jsonData
|
||||||
|
do{
|
||||||
|
let jsonData = try JSONEncoder().encode(array)
|
||||||
|
//使用UserDefaults存入缓存数据
|
||||||
|
UserDefaults.standard.set(jsonData, forKey: "SearchGride")
|
||||||
|
print("已经将Search Gride数据缓存")
|
||||||
|
}catch{
|
||||||
|
//转为jsonData失败
|
||||||
|
print("Search Gride数据转为Data失败,失败原因\(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//获取默认数据
|
||||||
|
private func chachedData() -> [MPPositive_GridViewModel]? {
|
||||||
|
guard let cacheData = UserDefaults.standard.data(forKey: "SearchGride") else {
|
||||||
|
print("获取Search Gride缓存数据失败")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
let array:[MPPositive_GridViewModel] = try JSONDecoder().decode([MPPositive_GridViewModel].self, from: cacheData)
|
||||||
|
print("已经将Search Gride缓存数据取出")
|
||||||
|
return array
|
||||||
|
} catch {
|
||||||
|
//转为jsonData失败
|
||||||
|
print("获取Search Gride缓存数据失败,失败原因\(error)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -113,7 +113,7 @@ class MPPositive_LoadCoreModel: NSObject {
|
|||||||
///更新搜索历史
|
///更新搜索历史
|
||||||
func reloadSearchTags(_ complection:(() -> Void)?) {
|
func reloadSearchTags(_ complection:(() -> Void)?) {
|
||||||
MPPositive_SearchTagModel.fetchAll{ array in
|
MPPositive_SearchTagModel.fetchAll{ array in
|
||||||
let s = array.sorted(by: {$1.date > $0.date})
|
let s = array.sorted(by: {$0.date > $1.date})
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.searchTags = s
|
self.searchTags = s
|
||||||
if complection != nil {
|
if complection != nil {
|
||||||
|
|||||||
@ -40,7 +40,6 @@ class MPPositive_SearchResultsLoadViewModel: NSObject {
|
|||||||
tag.date = Date().timeZone()
|
tag.date = Date().timeZone()
|
||||||
tag.text = text
|
tag.text = text
|
||||||
MPPositive_SearchTagModel.save()
|
MPPositive_SearchTagModel.save()
|
||||||
MPPositive_LoadCoreModel.shared.reloadSearchTags(nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MP_NetWorkManager.shared.requestSearchPreviewResults(text) { [weak self] results in
|
MP_NetWorkManager.shared.requestSearchPreviewResults(text) { [weak self] results in
|
||||||
|
|||||||
@ -111,7 +111,7 @@ extension MPPositive_TabBarController {
|
|||||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(recommendVC, animated: false)
|
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(recommendVC, animated: false)
|
||||||
}
|
}
|
||||||
playerVC.searchBlock = { (text) in
|
playerVC.searchBlock = { (text) in
|
||||||
let resultVC = MPPositive_SearchResultShowViewController(text)
|
let resultVC = MPPositive_SearchResultShowViewController(text, isShowAd: false)
|
||||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(resultVC, animated: false)
|
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(resultVC, animated: false)
|
||||||
}
|
}
|
||||||
self?.present(playerVC, animated: true)
|
self?.present(playerVC, animated: true)
|
||||||
@ -163,6 +163,7 @@ extension MPPositive_TabBarController {
|
|||||||
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
||||||
//覆盖型广告将要将要展示
|
//覆盖型广告将要将要展示
|
||||||
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = true
|
||||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||||
print("当前展示的广告是播放插页广告,广告ID--\(MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? "")")
|
print("当前展示的广告是播放插页广告,广告ID--\(MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? "")")
|
||||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction()
|
MP_AnalyticsManager.shared.play_ads_showSuccessAction()
|
||||||
@ -170,6 +171,7 @@ extension MPPositive_TabBarController {
|
|||||||
}
|
}
|
||||||
//覆盖型广告已经消失
|
//覆盖型广告已经消失
|
||||||
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
MP_AdMobManager.shared.interstitialDate = Date()
|
MP_AdMobManager.shared.interstitialDate = Date()
|
||||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||||
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
||||||
@ -190,10 +192,15 @@ extension MPPositive_TabBarController {
|
|||||||
self?.present(playerVC, animated: true)
|
self?.present(playerVC, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//覆盖型广告加载出错
|
//覆盖型广告加载出错
|
||||||
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
MP_AdMobManager.shared.interstitialDate = Date()
|
MP_AdMobManager.shared.interstitialDate = Date()
|
||||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||||
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
||||||
@ -215,6 +222,10 @@ extension MPPositive_TabBarController {
|
|||||||
// self?.present(playerVC, animated: true)
|
// self?.present(playerVC, animated: true)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,189 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_GrideMoodViewController.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/12.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
///模块数据详情
|
||||||
|
class MPPositive_GrideMoodViewController: MPPositive_BaseViewController {
|
||||||
|
//tableView
|
||||||
|
private lazy var tableView:UITableView = {
|
||||||
|
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.estimatedRowHeight = 200
|
||||||
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
|
tableView.dataSource = self
|
||||||
|
tableView.delegate = self
|
||||||
|
tableView.register(MPPositive_HomeSinglesTableViewCell.self, forCellReuseIdentifier: MPPositive_HomeSinglesTableViewCellID)
|
||||||
|
tableView.register(MPPositive_HomeShowTableViewCell.self, forCellReuseIdentifier: MPPositive_HomeShowTableViewCellID)
|
||||||
|
tableView.contentInset = .init(top: 0, left: 0, bottom: 70*width, right: 0)
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
private let MPPositive_HomeSinglesTableViewCellID = "MPPositive_HomeSinglesTableViewCell"
|
||||||
|
private let MPPositive_HomeShowTableViewCellID = "MPPositive_HomeShowTableViewCell"
|
||||||
|
private var browseModuleLists:[MPPositive_BrowseModuleListViewModel]! = []{
|
||||||
|
didSet{
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
if browseModuleLists != nil{
|
||||||
|
configure()
|
||||||
|
reload()
|
||||||
|
removeErrorView()
|
||||||
|
MP_HUD.hideNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var browseId:String!
|
||||||
|
private var params:String!
|
||||||
|
private var titleText:String!
|
||||||
|
init(_ browseId:String, params:String, title:String) {
|
||||||
|
self.browseId = browseId
|
||||||
|
self.params = params
|
||||||
|
self.titleText = title
|
||||||
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
//执行网络请求获取对应模块详情数据
|
||||||
|
MP_HUD.loading()
|
||||||
|
MP_NetWorkManager.shared.requestMoodDetails(browseId, params: params) { [weak self] result in
|
||||||
|
guard let self = self else {return}
|
||||||
|
browseModuleLists = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
}
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
//设置页面标题
|
||||||
|
setTitle(titleText)
|
||||||
|
setPopBtn()
|
||||||
|
errorBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//移除所有(除了navView)的子控件,并告知页面处理错误,提示用户重试
|
||||||
|
view.subviews.forEach { item in
|
||||||
|
if item != self.navView {
|
||||||
|
//移除
|
||||||
|
if item.superview != nil {
|
||||||
|
item.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//添加报错View
|
||||||
|
setErrorView()
|
||||||
|
MP_HUD.hideNow()
|
||||||
|
}
|
||||||
|
retryBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
MP_HUD.loading()
|
||||||
|
MP_NetWorkManager.shared.requestMoodDetails(browseId, params: params) { [weak self] result in
|
||||||
|
guard let self = self else {return}
|
||||||
|
browseModuleLists = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
reload()
|
||||||
|
}
|
||||||
|
//页面刷新
|
||||||
|
private func reload() {
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
private func configure() {
|
||||||
|
view.addSubview(tableView)
|
||||||
|
tableView.snp.makeConstraints { make in
|
||||||
|
make.left.bottom.right.equalToSuperview()
|
||||||
|
make.top.equalTo(navView.snp.bottom).offset(20*width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - tableView
|
||||||
|
extension MPPositive_GrideMoodViewController: UITableViewDataSource, UITableViewDelegate {
|
||||||
|
func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
return browseModuleLists.count
|
||||||
|
}
|
||||||
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
if let first = browseModuleLists[indexPath.section].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_ATV" {
|
||||||
|
//是单曲
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeSinglesTableViewCellID, for: indexPath) as! MPPositive_HomeSinglesTableViewCell
|
||||||
|
cell.browseViewModel = browseModuleLists[indexPath.section]
|
||||||
|
|
||||||
|
return cell
|
||||||
|
}else {
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeShowTableViewCellID, for: indexPath) as! MPPositive_HomeShowTableViewCell
|
||||||
|
cell.browseViewModel = browseModuleLists[indexPath.section]
|
||||||
|
if let first = browseModuleLists[indexPath.section].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV" {
|
||||||
|
cell.showType = .Fifth
|
||||||
|
}else {
|
||||||
|
//判断是列表还是艺术家
|
||||||
|
if browseModuleLists[indexPath.section].items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||||
|
cell.showType = .Fourth
|
||||||
|
}else {
|
||||||
|
cell.showType = .Third
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell.requestNextBlock = {
|
||||||
|
[weak self] (item) in
|
||||||
|
guard let self = self else {return}
|
||||||
|
switch item.browseItem.itemType {
|
||||||
|
case .single:
|
||||||
|
//单曲/视频跳转
|
||||||
|
MPPositive_Debouncer.shared.call {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||||
|
MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
MP_AnalyticsManager.shared.song_clickAction("Mood")
|
||||||
|
//优先清除数据
|
||||||
|
MP_PlayerManager.shared.loadPlayer = nil
|
||||||
|
//弹出播放器
|
||||||
|
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||||
|
MP_AnalyticsManager.shared.player_b_impAction()
|
||||||
|
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||||
|
MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? ""){ [weak self] listSongs in
|
||||||
|
guard let self = self else {return}
|
||||||
|
//回掉的数据并不完善,生成一个playerloadViewModel
|
||||||
|
let lodaViewModel = MPPositive_PlayerLoadViewModel(listSongs, currentVideoId: item.browseItem.videoId ?? "")
|
||||||
|
lodaViewModel.improveData(item.browseItem.videoId ?? "")
|
||||||
|
//更改播放器播放类型
|
||||||
|
MP_PlayerManager.shared.setPlayType(.normal)
|
||||||
|
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||||
|
MP_AnalyticsManager.shared.player_b_listAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .list:
|
||||||
|
//列表专辑
|
||||||
|
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "")
|
||||||
|
navigationController?.pushViewController(listVC, animated: true)
|
||||||
|
case .artist:
|
||||||
|
//前往艺术家页面
|
||||||
|
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "")
|
||||||
|
navigationController?.pushViewController(artistVC, animated: true)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell.findMoreBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
let moreVC = MPPositive_MoreContentViewController(browseModuleLists[indexPath.section])
|
||||||
|
navigationController?.pushViewController(moreVC, animated: true)
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -57,18 +57,21 @@ class MPPositive_SearchResultShowViewController: MPPositive_BaseViewController,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private var isShowAd = true
|
||||||
//搜索文本
|
//搜索文本
|
||||||
private var searchText:String?
|
private var searchText:String?
|
||||||
//MARK: - 搜索建议View
|
//MARK: - 搜索建议View
|
||||||
private lazy var suggestionView:MPPositive_SearchSuggestionsView = .init(frame: .zero)
|
private lazy var suggestionView:MPPositive_SearchSuggestionsView = .init(frame: .zero)
|
||||||
//MARK: - 结果展示View
|
//MARK: - 结果展示View
|
||||||
private lazy var resultsShowView:MPPositive_SearchResultsShowView = .init(frame: .zero)
|
private lazy var resultsShowView:MPPositive_SearchResultsShowView = .init(frame: .zero, isShowAd: self.isShowAd)
|
||||||
|
|
||||||
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ text:String) {
|
init(_ text:String, isShowAd:Bool = true) {
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
self.isShowAd = isShowAd
|
||||||
searchTextField.text = text
|
searchTextField.text = text
|
||||||
searchText = text
|
searchText = text
|
||||||
resultsShowView.loadModel = .init(text)
|
resultsShowView.loadModel = .init(text)
|
||||||
|
|||||||
@ -14,7 +14,8 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
|||||||
imageView.contentMode = .scaleAspectFill
|
imageView.contentMode = .scaleAspectFill
|
||||||
return imageView
|
return imageView
|
||||||
}()
|
}()
|
||||||
private lazy var collectionView:UICollectionView = {
|
//搜索历史展示
|
||||||
|
private lazy var historyCollectionView:UICollectionView = {
|
||||||
let layout = MPPositive_TagFlowLayout()
|
let layout = MPPositive_TagFlowLayout()
|
||||||
layout.delegate = self
|
layout.delegate = self
|
||||||
let collectionView:UICollectionView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), collectionViewLayout: layout)
|
let collectionView:UICollectionView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), collectionViewLayout: layout)
|
||||||
@ -27,6 +28,21 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
|||||||
return collectionView
|
return collectionView
|
||||||
}()
|
}()
|
||||||
private let MPPositive_SearchTagCollectionViewCellID = "MPPositive_SearchTagCollectionViewCell"
|
private let MPPositive_SearchTagCollectionViewCellID = "MPPositive_SearchTagCollectionViewCell"
|
||||||
|
//模块展示
|
||||||
|
private lazy var grideCollectionView:UICollectionView = {
|
||||||
|
let layout = UICollectionViewFlowLayout()
|
||||||
|
layout.itemSize = .init(width: 162*width, height: 60*width)
|
||||||
|
layout.sectionInset = .init(top: 20*width, left: 18*width, bottom: 70*width, right: 18*width)
|
||||||
|
let collectionView = UICollectionView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), collectionViewLayout: layout)
|
||||||
|
collectionView.showsVerticalScrollIndicator = false
|
||||||
|
collectionView.showsHorizontalScrollIndicator = false
|
||||||
|
collectionView.backgroundColor = .clear
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.register(MPPositive_SearchGrideCollectionViewCell.self, forCellWithReuseIdentifier: MPPositive_SearchGrideCollectionViewCellID)
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
fileprivate let MPPositive_SearchGrideCollectionViewCellID = "MPPositive_SearchGrideCollectionViewCell"
|
||||||
//历史标签
|
//历史标签
|
||||||
private lazy var historyLabel:UILabel = createLabel("History", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .init(hex: "#666666"), textAlignment: .left)
|
private lazy var historyLabel:UILabel = createLabel("History", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .init(hex: "#666666"), textAlignment: .left)
|
||||||
//删除按钮
|
//删除按钮
|
||||||
@ -43,16 +59,25 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
|||||||
//加载搜索原生广告
|
//加载搜索原生广告
|
||||||
MP_AdMobManager.shared.configureSreachNativeAd(rootController: self)
|
MP_AdMobManager.shared.configureSreachNativeAd(rootController: self)
|
||||||
MP_AdMobManager.shared.loadSearchNativeAd()
|
MP_AdMobManager.shared.loadSearchNativeAd()
|
||||||
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(grideReloadAction(_ :)), notificationName: .search_gride_reload)
|
||||||
}
|
}
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
MP_AnalyticsManager.shared.search_pvAction()
|
MP_AnalyticsManager.shared.search_pvAction()
|
||||||
collectionView.reloadData()
|
MPPositive_LoadCoreModel.shared.reloadSearchTags {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
historyCollectionView.reloadData()
|
||||||
|
}
|
||||||
|
grideCollectionView.reloadData()
|
||||||
}
|
}
|
||||||
override func viewWillDisappear(_ animated: Bool) {
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
super.viewWillDisappear(animated)
|
super.viewWillDisappear(animated)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
deinit{
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
}
|
||||||
//配置
|
//配置
|
||||||
private func configure() {
|
private func configure() {
|
||||||
let searchView = createSearchView()
|
let searchView = createSearchView()
|
||||||
@ -78,12 +103,17 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
|||||||
make.centerY.equalTo(deleteBtn)
|
make.centerY.equalTo(deleteBtn)
|
||||||
make.left.equalToSuperview().offset(18*width)
|
make.left.equalToSuperview().offset(18*width)
|
||||||
}
|
}
|
||||||
view.addSubview(collectionView)
|
view.addSubview(historyCollectionView)
|
||||||
collectionView.snp.makeConstraints { make in
|
historyCollectionView.snp.makeConstraints { make in
|
||||||
make.left.right.equalToSuperview()
|
make.left.right.equalToSuperview()
|
||||||
make.top.equalTo(deleteBtn.snp.bottom).offset(6*width)
|
make.top.equalTo(deleteBtn.snp.bottom).offset(6*width)
|
||||||
make.height.equalTo(130*width)
|
make.height.equalTo(130*width)
|
||||||
}
|
}
|
||||||
|
view.addSubview(grideCollectionView)
|
||||||
|
grideCollectionView.snp.makeConstraints { make in
|
||||||
|
make.top.equalTo(historyCollectionView.snp.bottom)
|
||||||
|
make.left.right.bottom.equalToSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//生成一个顶部搜索框
|
//生成一个顶部搜索框
|
||||||
private func createSearchView() -> UIView{
|
private func createSearchView() -> UIView{
|
||||||
@ -110,6 +140,14 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
|||||||
searchView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(searchClick(_:))))
|
searchView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(searchClick(_:))))
|
||||||
return searchView
|
return searchView
|
||||||
}
|
}
|
||||||
|
//刷新
|
||||||
|
@objc private func grideReloadAction(_ sender:Notification) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
grideCollectionView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
//前往搜索结果页
|
//前往搜索结果页
|
||||||
@objc fileprivate func searchClick(_ sender:UITapGestureRecognizer) {
|
@objc fileprivate func searchClick(_ sender:UITapGestureRecognizer) {
|
||||||
let resultVC = MPPositive_SearchResultShowViewController()
|
let resultVC = MPPositive_SearchResultShowViewController()
|
||||||
@ -124,7 +162,7 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
|||||||
MPPositive_LoadCoreModel.shared.reloadSearchTags {
|
MPPositive_LoadCoreModel.shared.reloadSearchTags {
|
||||||
[weak self] in
|
[weak self] in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
collectionView.reloadData()
|
historyCollectionView.reloadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,17 +177,36 @@ extension MPPositive_SearchViewController: UICollectionViewDataSource, UICollect
|
|||||||
}
|
}
|
||||||
|
|
||||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
return MPPositive_LoadCoreModel.shared.searchTags.count > 10 ? 10:MPPositive_LoadCoreModel.shared.searchTags.count
|
if collectionView == historyCollectionView {
|
||||||
|
return MPPositive_LoadCoreModel.shared.searchTags.count > 10 ? 10:MPPositive_LoadCoreModel.shared.searchTags.count
|
||||||
|
}else {
|
||||||
|
return MPPositive_GridLoadViewModel.shared.grideViewModels.count
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_SearchTagCollectionViewCellID, for: indexPath) as! MPPositive_SearchTagCollectionViewCell
|
if collectionView == historyCollectionView {
|
||||||
cell.setText(MPPositive_LoadCoreModel.shared.searchTags[indexPath.row].text)
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_SearchTagCollectionViewCellID, for: indexPath) as! MPPositive_SearchTagCollectionViewCell
|
||||||
return cell
|
cell.setText(MPPositive_LoadCoreModel.shared.searchTags[indexPath.row].text)
|
||||||
|
return cell
|
||||||
|
}else {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_SearchGrideCollectionViewCellID, for: indexPath) as! MPPositive_SearchGrideCollectionViewCell
|
||||||
|
cell.gride = MPPositive_GridLoadViewModel.shared.grideViewModels[indexPath.row]
|
||||||
|
return cell
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
let text = MPPositive_LoadCoreModel.shared.searchTags[indexPath.row].text ?? ""
|
if collectionView == historyCollectionView {
|
||||||
let resultVC = MPPositive_SearchResultShowViewController(text)
|
let text = MPPositive_LoadCoreModel.shared.searchTags[indexPath.row].text ?? ""
|
||||||
navigationController?.pushViewController(resultVC, animated: false)
|
let resultVC = MPPositive_SearchResultShowViewController(text)
|
||||||
|
navigationController?.pushViewController(resultVC, animated: false)
|
||||||
|
}else {
|
||||||
|
if indexPath.row <= (MPPositive_GridLoadViewModel.shared.grideViewModels.count - 1) {
|
||||||
|
let item = MPPositive_GridLoadViewModel.shared.grideViewModels[indexPath.row]
|
||||||
|
MP_AnalyticsManager.shared.grid_mood_clickAction(item.title ?? "")
|
||||||
|
let moodVC = MPPositive_GrideMoodViewController(item.grid.browseId, params: item.grid.params, title: item.title ?? "")
|
||||||
|
navigationController?.pushViewController(moodVC, animated: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - 宽度代理
|
//MARK: - 宽度代理
|
||||||
|
|||||||
@ -81,7 +81,7 @@ class MPPositive_HomeSinglesTableViewCell: UITableViewCell, UIViewControllerTran
|
|||||||
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
|
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
|
||||||
let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
|
let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
|
||||||
collectionView.layoutIfNeeded()
|
collectionView.layoutIfNeeded()
|
||||||
let height = layout.itemSize.height*3 + layout.sectionInset.top
|
let height = layout.itemSize.height*3 + layout.sectionInset.top + 10
|
||||||
return CGSize(width: size.width, height: size.height + height)
|
return CGSize(width: size.width, height: size.height + height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_SearchGrideCollectionViewCell.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/12.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MarqueeLabel
|
||||||
|
class MPPositive_SearchGrideCollectionViewCell: UICollectionViewCell {
|
||||||
|
//颜色块
|
||||||
|
private lazy var colorView:UIView = .init()
|
||||||
|
//标题Label
|
||||||
|
private lazy var titleLabel:UILabel = createMarQueeLabel("Loading", font: .systemFont(ofSize: 16, weight: .bold), textColor: .white)
|
||||||
|
var gride:MPPositive_GridViewModel!{
|
||||||
|
didSet{
|
||||||
|
colorView.backgroundColor = .randomColor
|
||||||
|
titleLabel.text = gride.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
backgroundColor = .init(hex: "#1F1F1F")
|
||||||
|
layer.masksToBounds = true
|
||||||
|
layer.cornerRadius = 10*width
|
||||||
|
confirgue()
|
||||||
|
}
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
}
|
||||||
|
//配置
|
||||||
|
private func confirgue() {
|
||||||
|
addSubview(colorView)
|
||||||
|
colorView.snp.makeConstraints { make in
|
||||||
|
make.top.left.bottom.equalToSuperview()
|
||||||
|
make.width.equalToSuperview().multipliedBy(0.2)
|
||||||
|
}
|
||||||
|
addSubview(titleLabel)
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.left.equalTo(colorView.snp.right).offset(12*width)
|
||||||
|
make.right.equalToSuperview().offset(-12*width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,17 +17,19 @@ class MPPositive_SearchResultsShowView: UIView {
|
|||||||
if loadModel == nil {
|
if loadModel == nil {
|
||||||
emptyImageView.isHidden = false
|
emptyImageView.isHidden = false
|
||||||
}else {
|
}else {
|
||||||
MP_AdMobManager.shared.showSearchInterstitialAdIfAvailable { [weak self] ad in
|
if isShowAd == true {
|
||||||
guard let self = self else {return}
|
MP_AdMobManager.shared.showSearchInterstitialAdIfAvailable { [weak self] ad in
|
||||||
//判断数据是否有值
|
guard let self = self else {return}
|
||||||
if loadModel?.sectionLists?.count != nil {
|
//判断数据是否有值
|
||||||
//有值,不在展示
|
if loadModel?.sectionLists?.count != nil {
|
||||||
MP_AdMobManager.shared.setInterstitialSwitch(false)
|
//有值,不在展示
|
||||||
}else {
|
MP_AdMobManager.shared.setInterstitialSwitch(false)
|
||||||
MP_AdMobManager.shared.isShowingSearchInterstitialAd = true
|
}else {
|
||||||
//没有值,展示
|
MP_AdMobManager.shared.isShowingSearchInterstitialAd = true
|
||||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
//没有值,展示
|
||||||
ad.present(fromRootViewController: nil)
|
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
||||||
|
ad.present(fromRootViewController: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//搜索成功了
|
//搜索成功了
|
||||||
@ -43,6 +45,7 @@ class MPPositive_SearchResultsShowView: UIView {
|
|||||||
dataSource.titles = titles
|
dataSource.titles = titles
|
||||||
dataSource.reloadData(selectedIndex: 0)
|
dataSource.reloadData(selectedIndex: 0)
|
||||||
segmentView.reloadData()
|
segmentView.reloadData()
|
||||||
|
segmentView.selectItemAt(index: 0)
|
||||||
emptyImageView.isHidden = !(titles.count == 0)
|
emptyImageView.isHidden = !(titles.count == 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,8 +105,11 @@ class MPPositive_SearchResultsShowView: UIView {
|
|||||||
return imageView
|
return imageView
|
||||||
}()
|
}()
|
||||||
var scrollBlock:(() -> Void)?
|
var scrollBlock:(() -> Void)?
|
||||||
override init(frame: CGRect) {
|
//是否展示插页广告
|
||||||
|
private var isShowAd:Bool = true
|
||||||
|
init(frame: CGRect, isShowAd:Bool = true) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
self.isShowAd = isShowAd
|
||||||
backgroundColor = .init(hex: "1A1A1A")
|
backgroundColor = .init(hex: "1A1A1A")
|
||||||
configure()
|
configure()
|
||||||
MP_AdMobManager.shared.onSearchNativeAdBlock = {
|
MP_AdMobManager.shared.onSearchNativeAdBlock = {
|
||||||
|
|||||||
@ -63,11 +63,17 @@ class MPSideA_LoadDataMusic: NSObject {
|
|||||||
homeSecondMusics = locallistMusics.filter{($0.type == .Second)}
|
homeSecondMusics = locallistMusics.filter{($0.type == .Second)}
|
||||||
homeThirdMusics = convertToTwoArray(locallistMusics.filter{($0.type == .Third)}, raw: 3)
|
homeThirdMusics = convertToTwoArray(locallistMusics.filter{($0.type == .Third)}, raw: 3)
|
||||||
//取出固定内容
|
//取出固定内容
|
||||||
homeZeroMusics.append(homeThirdMusics.last!.last!)
|
if let last = homeThirdMusics.last?.last {
|
||||||
homeZeroMusics.append(homeSecondMusics.last!)
|
homeZeroMusics.append(last)
|
||||||
homeZeroMusics.append(homeFirstMusics.last!)
|
}
|
||||||
if userlistMusics.count != 0 {
|
if let last = homeSecondMusics.last {
|
||||||
homeZeroMusics.append(userlistMusics.last!)
|
homeZeroMusics.append(last)
|
||||||
|
}
|
||||||
|
if let last = homeFirstMusics.last {
|
||||||
|
homeZeroMusics.append(last)
|
||||||
|
}
|
||||||
|
if userlistMusics.count != 0, let last = userlistMusics.last {
|
||||||
|
homeZeroMusics.append(last)
|
||||||
}
|
}
|
||||||
completion?()
|
completion?()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -259,6 +259,7 @@ extension MPSideA_TabBarController {
|
|||||||
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
//MARK: - 覆盖型广告代理 GADFullScreenContentDelegate
|
||||||
//覆盖型广告将要将要展示
|
//覆盖型广告将要将要展示
|
||||||
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = true
|
||||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||||
print("当前展示的广告是播放插页广告,广告ID--\(MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? "")")
|
print("当前展示的广告是播放插页广告,广告ID--\(MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? "")")
|
||||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction()
|
MP_AnalyticsManager.shared.play_ads_showSuccessAction()
|
||||||
@ -266,6 +267,7 @@ extension MPSideA_TabBarController {
|
|||||||
}
|
}
|
||||||
//覆盖型广告已经消失
|
//覆盖型广告已经消失
|
||||||
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
MP_AdMobManager.shared.interstitialDate = Date()
|
MP_AdMobManager.shared.interstitialDate = Date()
|
||||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||||
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
||||||
@ -282,10 +284,15 @@ extension MPSideA_TabBarController {
|
|||||||
self?.present(playerVC, animated: true)
|
self?.present(playerVC, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//覆盖型广告加载出错
|
//覆盖型广告加载出错
|
||||||
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
|
||||||
|
// UIApplication.shared.isStatusBarHidden = false
|
||||||
MP_AdMobManager.shared.interstitialDate = Date()
|
MP_AdMobManager.shared.interstitialDate = Date()
|
||||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||||
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
let UUID = MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? ""
|
||||||
@ -304,6 +311,10 @@ extension MPSideA_TabBarController {
|
|||||||
// self?.present(playerVC, animated: true)
|
// self?.present(playerVC, animated: true)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
accessAppdelegate.setAudioSupport()
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3){
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
accessAppdelegate.setAudioSupport()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user