B面1.1.5内购提审版
@ -23,6 +23,10 @@
|
|||||||
CB1E3B662C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */; };
|
CB1E3B662C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */; };
|
||||||
CB1E3B682C23E09100071DEA /* MPPositive_CustomVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */; };
|
CB1E3B682C23E09100071DEA /* MPPositive_CustomVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */; };
|
||||||
CB20A0702C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB20A06F2C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift */; };
|
CB20A0702C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB20A06F2C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift */; };
|
||||||
|
CB2CAAD42C59DC1100EF691D /* MPPositive_TrashListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2CAAD32C59DC1100EF691D /* MPPositive_TrashListModel.swift */; };
|
||||||
|
CB2CAAD72C5A1AC500EF691D /* MP_IAPViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB2CAAD62C5A1AC500EF691D /* MP_IAPViewController.xib */; };
|
||||||
|
CB2CAAD82C5A1AC500EF691D /* MP_IAPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2CAAD52C5A1AC500EF691D /* MP_IAPViewController.swift */; };
|
||||||
|
CB4FA4D92C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CB4FA4D72C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld */; };
|
||||||
CB7FC5422C2AA01F00292A43 /* FacebookAEM in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5412C2AA01F00292A43 /* FacebookAEM */; };
|
CB7FC5422C2AA01F00292A43 /* FacebookAEM in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5412C2AA01F00292A43 /* FacebookAEM */; };
|
||||||
CB7FC5442C2AA01F00292A43 /* FacebookBasics in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5432C2AA01F00292A43 /* FacebookBasics */; };
|
CB7FC5442C2AA01F00292A43 /* FacebookBasics in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5432C2AA01F00292A43 /* FacebookBasics */; };
|
||||||
CB7FC5462C2AA01F00292A43 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5452C2AA01F00292A43 /* FacebookCore */; };
|
CB7FC5462C2AA01F00292A43 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5452C2AA01F00292A43 /* FacebookCore */; };
|
||||||
@ -238,7 +242,6 @@
|
|||||||
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 */; };
|
||||||
CBC2EBCA2C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CBC2EBC82C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld */; };
|
|
||||||
CBC3F2B22C3E76160075DC74 /* MPPositive_AdModelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */; };
|
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 */; };
|
||||||
@ -274,6 +277,10 @@
|
|||||||
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomPlayListModel.swift; sourceTree = "<group>"; };
|
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomPlayListModel.swift; sourceTree = "<group>"; };
|
||||||
CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomVideoModel.swift; sourceTree = "<group>"; };
|
CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomVideoModel.swift; sourceTree = "<group>"; };
|
||||||
CB20A06F2C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_WebVisitorDataManager.swift; sourceTree = "<group>"; };
|
CB20A06F2C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_WebVisitorDataManager.swift; sourceTree = "<group>"; };
|
||||||
|
CB2CAAD32C59DC1100EF691D /* MPPositive_TrashListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_TrashListModel.swift; sourceTree = "<group>"; };
|
||||||
|
CB2CAAD52C5A1AC500EF691D /* MP_IAPViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_IAPViewController.swift; sourceTree = "<group>"; };
|
||||||
|
CB2CAAD62C5A1AC500EF691D /* MP_IAPViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MP_IAPViewController.xib; sourceTree = "<group>"; };
|
||||||
|
CB4FA4D82C5CDC4A0027C949 /* MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MusicPlayer.xcdatamodel; sourceTree = "<group>"; };
|
||||||
CB7FC5472C2AC25C00292A43 /* MPPositive_CenterListSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CenterListSearchView.swift; sourceTree = "<group>"; };
|
CB7FC5472C2AC25C00292A43 /* MPPositive_CenterListSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CenterListSearchView.swift; sourceTree = "<group>"; };
|
||||||
CBAFC9F22C0A10500054500E /* MP_BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MP_BaseViewController.swift; sourceTree = "<group>"; };
|
CBAFC9F22C0A10500054500E /* MP_BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MP_BaseViewController.swift; sourceTree = "<group>"; };
|
||||||
CBAFC9F32C0A10500054500E /* MP_LunchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MP_LunchViewController.swift; sourceTree = "<group>"; };
|
CBAFC9F32C0A10500054500E /* MP_LunchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MP_LunchViewController.swift; sourceTree = "<group>"; };
|
||||||
@ -485,7 +492,6 @@
|
|||||||
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>"; };
|
||||||
CBC2EBC92C5277F1000ADA51 /* MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MusicPlayer.xcdatamodel; sourceTree = "<group>"; };
|
|
||||||
CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_AdModelModel.swift; 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>"; };
|
||||||
@ -562,6 +568,8 @@
|
|||||||
CBAFC9F42C0A10500054500E /* MP_LunchViewController.xib */,
|
CBAFC9F42C0A10500054500E /* MP_LunchViewController.xib */,
|
||||||
CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */,
|
CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */,
|
||||||
CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */,
|
CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */,
|
||||||
|
CB2CAAD52C5A1AC500EF691D /* MP_IAPViewController.swift */,
|
||||||
|
CB2CAAD62C5A1AC500EF691D /* MP_IAPViewController.xib */,
|
||||||
);
|
);
|
||||||
path = Controllers;
|
path = Controllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -586,7 +594,7 @@
|
|||||||
CBAFC9FB2C0A10500054500E /* DataBase */ = {
|
CBAFC9FB2C0A10500054500E /* DataBase */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CBC2EBC82C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld */,
|
CB4FA4D72C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld */,
|
||||||
);
|
);
|
||||||
path = DataBase;
|
path = DataBase;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -750,6 +758,7 @@
|
|||||||
CBAFCA462C0A10500054500E /* MPPositive_SongItemModel.swift */,
|
CBAFCA462C0A10500054500E /* MPPositive_SongItemModel.swift */,
|
||||||
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */,
|
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */,
|
||||||
CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */,
|
CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */,
|
||||||
|
CB2CAAD32C59DC1100EF691D /* MPPositive_TrashListModel.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1306,6 +1315,7 @@
|
|||||||
CBAFCB022C0A10500054500E /* Howling Wind.mp3 in Resources */,
|
CBAFCB022C0A10500054500E /* Howling Wind.mp3 in Resources */,
|
||||||
CBAFCB842C0A10500054500E /* MPSideA_DeleteViewController.xib in Resources */,
|
CBAFCB842C0A10500054500E /* MPSideA_DeleteViewController.xib in Resources */,
|
||||||
CBAFCB822C0A10500054500E /* MPSideA_CenterViewController.xib in Resources */,
|
CBAFCB822C0A10500054500E /* MPSideA_CenterViewController.xib in Resources */,
|
||||||
|
CB2CAAD72C5A1AC500EF691D /* MP_IAPViewController.xib in Resources */,
|
||||||
CBAFCB062C0A10500054500E /* waterfall.mp3 in Resources */,
|
CBAFCB062C0A10500054500E /* waterfall.mp3 in Resources */,
|
||||||
CBAFCAFE2C0A10500054500E /* Beach.mp3 in Resources */,
|
CBAFCAFE2C0A10500054500E /* Beach.mp3 in Resources */,
|
||||||
CBC2D7D42BFDF4B900E17703 /* PrivacyInfo.xcprivacy in Resources */,
|
CBC2D7D42BFDF4B900E17703 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
@ -1412,6 +1422,7 @@
|
|||||||
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 */,
|
||||||
|
CB2CAAD42C59DC1100EF691D /* MPPositive_TrashListModel.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 */,
|
||||||
CBB75FDD2C4F7AA60041665D /* UIImageView.swift in Sources */,
|
CBB75FDD2C4F7AA60041665D /* UIImageView.swift in Sources */,
|
||||||
@ -1424,10 +1435,12 @@
|
|||||||
CBAFCAF52C0A10500054500E /* CoreDataDelegete.swift in Sources */,
|
CBAFCAF52C0A10500054500E /* CoreDataDelegete.swift in Sources */,
|
||||||
CBAFCB5B2C0A10500054500E /* MPPositive_ArtistShowCollectionViewCell.swift in Sources */,
|
CBAFCB5B2C0A10500054500E /* MPPositive_ArtistShowCollectionViewCell.swift in Sources */,
|
||||||
CBAFCB182C0A10500054500E /* MPPositive_JsonArtistMore.swift in Sources */,
|
CBAFCB182C0A10500054500E /* MPPositive_JsonArtistMore.swift in Sources */,
|
||||||
|
CB4FA4D92C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld in Sources */,
|
||||||
CBAFCB982C0A10500054500E /* MPSideA_CustomTabBarItem.swift in Sources */,
|
CBAFCB982C0A10500054500E /* MPSideA_CustomTabBarItem.swift in Sources */,
|
||||||
CBAFCB5D2C0A10500054500E /* MPPositive_ArtistShowListableViewCell.swift in Sources */,
|
CBAFCB5D2C0A10500054500E /* MPPositive_ArtistShowListableViewCell.swift in Sources */,
|
||||||
CBAFCB7D2C0A10500054500E /* MPSideA_PresentationController.swift in Sources */,
|
CBAFCB7D2C0A10500054500E /* MPSideA_PresentationController.swift in Sources */,
|
||||||
CBAFCB2D2C0A10500054500E /* MPPositive_ArtistContentListViewModel.swift in Sources */,
|
CBAFCB2D2C0A10500054500E /* MPPositive_ArtistContentListViewModel.swift in Sources */,
|
||||||
|
CB2CAAD82C5A1AC500EF691D /* MP_IAPViewController.swift in Sources */,
|
||||||
CBC1FB7E2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift in Sources */,
|
CBC1FB7E2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift in Sources */,
|
||||||
CBAFCB992C0A10500054500E /* MPSideA_CustomTabBarView.swift in Sources */,
|
CBAFCB992C0A10500054500E /* MPSideA_CustomTabBarView.swift in Sources */,
|
||||||
CBAFCB342C0A10500054500E /* MPPositive_DownloadViewModel.swift in Sources */,
|
CBAFCB342C0A10500054500E /* MPPositive_DownloadViewModel.swift in Sources */,
|
||||||
@ -1446,7 +1459,6 @@
|
|||||||
CBAFCB7B2C0A10500054500E /* MPSideA_BaseViewController.swift in Sources */,
|
CBAFCB7B2C0A10500054500E /* MPSideA_BaseViewController.swift in Sources */,
|
||||||
CBAFCB102C0A10500054500E /* MP_NetWorkManager.swift in Sources */,
|
CBAFCB102C0A10500054500E /* MP_NetWorkManager.swift in Sources */,
|
||||||
CBAFCB9D2C0A10500054500E /* MPSideA_SettingTableViewCell.swift in Sources */,
|
CBAFCB9D2C0A10500054500E /* MPSideA_SettingTableViewCell.swift in Sources */,
|
||||||
CBC2EBCA2C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld in Sources */,
|
|
||||||
CBAFCAEC2C0A10500054500E /* AVPlayerItem.swift in Sources */,
|
CBAFCAEC2C0A10500054500E /* AVPlayerItem.swift in Sources */,
|
||||||
CBAFCB7E2C0A10500054500E /* MPSideA_TabBarController.swift in Sources */,
|
CBAFCB7E2C0A10500054500E /* MPSideA_TabBarController.swift in Sources */,
|
||||||
CBAFCB1D2C0A10500054500E /* MPPositive_JsonPlayer.swift in Sources */,
|
CBAFCB1D2C0A10500054500E /* MPPositive_JsonPlayer.swift in Sources */,
|
||||||
@ -1730,10 +1742,12 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CURRENT_PROJECT_VERSION = 1.1.4.1;
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
CURRENT_PROJECT_VERSION = 1.1.5.1;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = T93S37G27F;
|
DEVELOPMENT_TEAM = "";
|
||||||
|
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = relax.offline.mp3.music/Info.plist;
|
INFOPLIST_FILE = relax.offline.mp3.music/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Musiclax;
|
INFOPLIST_KEY_CFBundleDisplayName = Musiclax;
|
||||||
@ -1751,10 +1765,11 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.4;
|
MARKETING_VERSION = 1.1.5;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Musiclax_Development;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
@ -1773,10 +1788,12 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CURRENT_PROJECT_VERSION = 1.1.4.1;
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
CURRENT_PROJECT_VERSION = 1.1.5.1;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = T93S37G27F;
|
DEVELOPMENT_TEAM = "";
|
||||||
|
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = relax.offline.mp3.music/Info.plist;
|
INFOPLIST_FILE = relax.offline.mp3.music/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Musiclax;
|
INFOPLIST_KEY_CFBundleDisplayName = Musiclax;
|
||||||
@ -1794,10 +1811,11 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.4;
|
MARKETING_VERSION = 1.1.5;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Musiclax_Development;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
@ -1898,12 +1916,12 @@
|
|||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
|
|
||||||
/* Begin XCVersionGroup section */
|
/* Begin XCVersionGroup section */
|
||||||
CBC2EBC82C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld */ = {
|
CB4FA4D72C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld */ = {
|
||||||
isa = XCVersionGroup;
|
isa = XCVersionGroup;
|
||||||
children = (
|
children = (
|
||||||
CBC2EBC92C5277F1000ADA51 /* MusicPlayer.xcdatamodel */,
|
CB4FA4D82C5CDC4A0027C949 /* MusicPlayer.xcdatamodel */,
|
||||||
);
|
);
|
||||||
currentVersion = CBC2EBC92C5277F1000ADA51 /* MusicPlayer.xcdatamodel */;
|
currentVersion = CB4FA4D82C5CDC4A0027C949 /* MusicPlayer.xcdatamodel */;
|
||||||
name = relax.offline.mp3.xcdatamodeld;
|
name = relax.offline.mp3.xcdatamodeld;
|
||||||
path = "/Users/zhou/Desktop/纳克斯互娱/relax.offline.mp3.music/relax.offline.mp3.music/MP/Common/DataBase/relax.offline.mp3.xcdatamodeld";
|
path = "/Users/zhou/Desktop/纳克斯互娱/relax.offline.mp3.music/relax.offline.mp3.music/MP/Common/DataBase/relax.offline.mp3.xcdatamodeld";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import Tiercel
|
|||||||
import Firebase
|
import Firebase
|
||||||
import GoogleMobileAds
|
import GoogleMobileAds
|
||||||
import FacebookCore
|
import FacebookCore
|
||||||
|
import StoreKit
|
||||||
@_exported import IQKeyboardManagerSwift
|
@_exported import IQKeyboardManagerSwift
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
@ -61,7 +62,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
switch_lunch()
|
switch_lunch()
|
||||||
//执行用户启动事件日志
|
//执行用户启动事件日志
|
||||||
MP_AnalyticsManager.shared.user_launchAction()
|
MP_AnalyticsManager.shared.user_launchAction()
|
||||||
// NotificationCenter.default.addObserver(self, selector: #selector(appWillTerminateAction(_ :)), name:UIApplication.willTerminateNotification, object: nil)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:] ) -> Bool {
|
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:] ) -> Bool {
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "大背景@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "大背景@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 933 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "AD图标@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "AD图标@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "大背景@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "大背景@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 906 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "未选中框@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "未选中框@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "选中框@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "选中框@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "下载图标@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "下载图标@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "音乐图标@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "音乐图标@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "btn_square@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "btn_square@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 684 B |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "85_@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "85_@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
22
relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "盾@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "盾@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 834 B |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Rights@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Rights@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 60 KiB |
22
relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_1597880776@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_1597880776@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,177 @@
|
|||||||
|
//
|
||||||
|
// MP_IAPViewController.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
///内购选中图片
|
||||||
|
let IAPChooseedImage:UIImage? = .init(named: "IAP Chooseed'logo")
|
||||||
|
///内购未选中图片
|
||||||
|
let IAPChooseImage:UIImage? = .init(named: "IAP Choose'logo")
|
||||||
|
///内购页面(A/B面样式区别)
|
||||||
|
class MP_IAPViewController: UIViewController {
|
||||||
|
//样式版,根据A/B面决定
|
||||||
|
@IBOutlet weak var bgImageView: UIImageView!
|
||||||
|
@IBOutlet weak var scrollView: UIScrollView!
|
||||||
|
var isType:Bool = false
|
||||||
|
@IBOutlet weak var aConstraint: NSLayoutConstraint!
|
||||||
|
@IBOutlet weak var bConstraint: NSLayoutConstraint!
|
||||||
|
@IBOutlet weak var adView: UIView!
|
||||||
|
@IBOutlet weak var adLabel: UILabel!
|
||||||
|
@IBOutlet weak var musicView: UIView!
|
||||||
|
@IBOutlet weak var musicLabel: UILabel!
|
||||||
|
@IBOutlet weak var downloadView: UIView!
|
||||||
|
@IBOutlet weak var downloadLabel: UILabel!
|
||||||
|
@IBOutlet weak var weekView: UIView!{
|
||||||
|
didSet{
|
||||||
|
weekView.isUserInteractionEnabled = true
|
||||||
|
weekView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseLevelClick(_ :))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@IBOutlet weak var weekImageView: UIImageView!
|
||||||
|
@IBOutlet weak var weekPriceLabel: UILabel!
|
||||||
|
@IBOutlet weak var yearView: UIView!{
|
||||||
|
didSet{
|
||||||
|
yearView.isUserInteractionEnabled = true
|
||||||
|
yearView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseLevelClick(_ :))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@IBOutlet weak var yearImageView: UIImageView!
|
||||||
|
@IBOutlet weak var yearPriceLabel: UILabel!
|
||||||
|
@IBOutlet weak var lifeView: UIView!{
|
||||||
|
didSet{
|
||||||
|
lifeView.isUserInteractionEnabled = true
|
||||||
|
lifeView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseLevelClick(_ :))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@IBOutlet weak var lifeImageView: UIImageView!
|
||||||
|
@IBOutlet weak var lifePriceLabel: UILabel!
|
||||||
|
var privacyBlock:(() -> Void)?
|
||||||
|
var termsBlock:(() -> Void)?
|
||||||
|
//选择的等级
|
||||||
|
private var level:Int?
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
scrollView.contentInsetAdjustmentBehavior = .never
|
||||||
|
MP_IAPManager.shared.requestProducts()
|
||||||
|
//根据isType调整约束(A/B面样式存在差距)
|
||||||
|
if isType {
|
||||||
|
//B面
|
||||||
|
bgImageView.image = UIImage(named: "IAP B'bg")
|
||||||
|
aConstraint.priority = .init(500)
|
||||||
|
bConstraint.priority = .init(999)
|
||||||
|
//展示所有的权益
|
||||||
|
musicView.isHidden = false
|
||||||
|
downloadView.isHidden = false
|
||||||
|
|
||||||
|
}else {
|
||||||
|
//A面
|
||||||
|
bgImageView.image = UIImage(named: "IAP A'bg")
|
||||||
|
aConstraint.priority = .init(999)
|
||||||
|
bConstraint.priority = .init(500)
|
||||||
|
//隐藏权益
|
||||||
|
musicView.isHidden = true
|
||||||
|
downloadView.isHidden = true
|
||||||
|
}
|
||||||
|
//实现文本填充
|
||||||
|
adLabel.attributedText = setSubstring("Ad-free experience, NO ADs!!", coloredText: "NO ADs!!")
|
||||||
|
musicLabel.text = "All \"YouTube\" music & videos"
|
||||||
|
downloadLabel.text = "Unlimited Downloads"
|
||||||
|
|
||||||
|
//设置价格文本
|
||||||
|
weekPriceLabel.attributedText = setPriceText(1.99)
|
||||||
|
yearPriceLabel.attributedText = setPriceText(14.99)
|
||||||
|
lifePriceLabel.attributedText = setPriceText(24.99)
|
||||||
|
}
|
||||||
|
//根据文本内容调整显示颜色
|
||||||
|
private func setSubstring(_ fullText:String, coloredText:String) -> NSAttributedString {
|
||||||
|
//调整展示颜色
|
||||||
|
let attributedString = NSMutableAttributedString(string: fullText, attributes: [.foregroundColor:UIColor.white, .font:UIFont.systemFont(ofSize: 16*width)])
|
||||||
|
let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor(hex: "#80F988")]
|
||||||
|
if let range = fullText.range(of: coloredText) {
|
||||||
|
let nsRange = NSRange(range, in: fullText)
|
||||||
|
attributedString.addAttributes(attributes, range: nsRange)
|
||||||
|
}
|
||||||
|
return attributedString
|
||||||
|
}
|
||||||
|
//设置价格副文本
|
||||||
|
private func setPriceText(_ price:Double) -> NSAttributedString {
|
||||||
|
let font = UIFont(name: "DINAlternate-Bold", size: 24*width) ?? .systemFont(ofSize: 24*width, weight: .bold)
|
||||||
|
let attributedString = NSMutableAttributedString(string: "$\(price)", attributes: [.foregroundColor:UIColor.white, .font:font])
|
||||||
|
attributedString.addAttributes([.font:UIFont(name: "DINAlternate-Bold", size: 16*width) ?? .systemFont(ofSize: 16*width, weight: .bold)], range: .init(location: 0, length: 1))
|
||||||
|
return attributedString
|
||||||
|
}
|
||||||
|
|
||||||
|
//退出页面
|
||||||
|
@IBAction func dismissClick(_ sender: UIButton) {
|
||||||
|
dismiss(animated: true)
|
||||||
|
}
|
||||||
|
//选择档位
|
||||||
|
@objc private func chooseLevelClick(_ sender:UITapGestureRecognizer) {
|
||||||
|
let tag = sender.view?.tag ?? 0
|
||||||
|
switch tag {
|
||||||
|
case 0://选择了第一档
|
||||||
|
weekPriceLabel.setGradientTextColor(gradientTextColors)
|
||||||
|
weekImageView.image = IAPChooseedImage
|
||||||
|
|
||||||
|
yearPriceLabel.cleanGradientTextColor()
|
||||||
|
yearImageView.image = IAPChooseImage
|
||||||
|
lifePriceLabel.cleanGradientTextColor()
|
||||||
|
lifeImageView.image = IAPChooseImage
|
||||||
|
case 1://选择了第二档
|
||||||
|
yearPriceLabel.setGradientTextColor(gradientTextColors)
|
||||||
|
yearImageView.image = IAPChooseedImage
|
||||||
|
|
||||||
|
weekPriceLabel.cleanGradientTextColor()
|
||||||
|
weekImageView.image = IAPChooseImage
|
||||||
|
lifePriceLabel.cleanGradientTextColor()
|
||||||
|
lifeImageView.image = IAPChooseImage
|
||||||
|
default://选择了第三档
|
||||||
|
lifePriceLabel.setGradientTextColor(gradientTextColors)
|
||||||
|
lifeImageView.image = IAPChooseedImage
|
||||||
|
|
||||||
|
weekPriceLabel.cleanGradientTextColor()
|
||||||
|
weekImageView.image = IAPChooseImage
|
||||||
|
yearPriceLabel.cleanGradientTextColor()
|
||||||
|
yearImageView.image = IAPChooseImage
|
||||||
|
}
|
||||||
|
level = tag
|
||||||
|
}
|
||||||
|
//继续购买
|
||||||
|
@IBAction func continueClick(_ sender: UIButton) {
|
||||||
|
guard let level = level else {
|
||||||
|
MP_HUD.onlytext("Please select your membership type", delay: 1.0, completion: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||||
|
MP_HUD.onlytext("Bad connection~", delay: 1.0, completion: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
MP_IAPManager.shared.purchaseProduct(level)
|
||||||
|
}
|
||||||
|
//刷新商店
|
||||||
|
@IBAction func reStoreClick(_ sender: UIButton) {
|
||||||
|
MP_IAPManager.shared.restorePurchases()
|
||||||
|
}
|
||||||
|
//协议
|
||||||
|
@IBAction func privacyClick(_ sender: UIButton) {
|
||||||
|
dismiss(animated: true) {
|
||||||
|
[weak self] in
|
||||||
|
if let block = self?.privacyBlock {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//用户服务
|
||||||
|
@IBAction func termsClick(_ sender: UIButton) {
|
||||||
|
dismiss(animated: true) {
|
||||||
|
[weak self] in
|
||||||
|
if let block = self?.termsBlock {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,611 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||||
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<objects>
|
||||||
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MP_IAPViewController" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||||
|
<connections>
|
||||||
|
<outlet property="aConstraint" destination="tVb-7S-rd8" id="VvO-cU-hrO"/>
|
||||||
|
<outlet property="adLabel" destination="yNx-kt-wCp" id="QqE-FX-NJo"/>
|
||||||
|
<outlet property="adView" destination="5rd-jg-Oh0" id="gCW-Ff-moN"/>
|
||||||
|
<outlet property="bConstraint" destination="WeJ-cY-e6e" id="upI-wE-tCe"/>
|
||||||
|
<outlet property="bgImageView" destination="kdc-al-Dgu" id="6CO-xr-HXk"/>
|
||||||
|
<outlet property="downloadLabel" destination="yho-5R-DjF" id="e2d-Gj-P52"/>
|
||||||
|
<outlet property="downloadView" destination="s0J-Ld-XhO" id="4Qr-Gx-apD"/>
|
||||||
|
<outlet property="lifeImageView" destination="21u-ne-klE" id="WRc-K8-9x9"/>
|
||||||
|
<outlet property="lifePriceLabel" destination="mSD-Ht-ZAt" id="E4r-BI-tvl"/>
|
||||||
|
<outlet property="lifeView" destination="6m2-Pk-kEx" id="qGY-HI-O0p"/>
|
||||||
|
<outlet property="musicLabel" destination="bmg-bY-SQ2" id="asP-Of-UO6"/>
|
||||||
|
<outlet property="musicView" destination="4aH-sS-rjT" id="Oq2-nH-VSO"/>
|
||||||
|
<outlet property="scrollView" destination="BnJ-Xo-PqP" id="aAq-Mw-9Bt"/>
|
||||||
|
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||||
|
<outlet property="weekImageView" destination="f2Z-iY-0aL" id="1Me-2I-A4f"/>
|
||||||
|
<outlet property="weekPriceLabel" destination="zj9-cg-9xc" id="tPL-3l-Cuj"/>
|
||||||
|
<outlet property="weekView" destination="fVE-zT-baW" id="sLb-h7-9QP"/>
|
||||||
|
<outlet property="yearImageView" destination="Y9f-zt-bGB" id="cuk-g0-HuP"/>
|
||||||
|
<outlet property="yearPriceLabel" destination="C3t-AB-geN" id="VHn-eq-H4N"/>
|
||||||
|
<outlet property="yearView" destination="cw2-8u-Yru" id="2OH-Gs-zPb"/>
|
||||||
|
</connections>
|
||||||
|
</placeholder>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
|
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BnJ-Xo-PqP">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<subviews>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nGh-s6-UA5">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP B'bg" translatesAutoresizingMaskIntoConstraints="NO" id="kdc-al-Dgu">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="812" id="ZvV-J5-NWh">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Rights'logo" translatesAutoresizingMaskIntoConstraints="NO" id="JBI-cg-ZTm">
|
||||||
|
<rect key="frame" x="3.5" y="66" width="229" height="149"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="149" id="CKo-WY-ajE">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="width" constant="229" id="P6i-Im-9dq">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5rd-jg-Oh0">
|
||||||
|
<rect key="frame" x="19" y="204" width="337" height="25"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP AD'logo" translatesAutoresizingMaskIntoConstraints="NO" id="1uD-GG-xPH">
|
||||||
|
<rect key="frame" x="13" y="0.5" width="24" height="24"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="24" id="1uT-Ez-xQz">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="height" constant="24" id="OGY-K2-quX">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yNx-kt-wCp">
|
||||||
|
<rect key="frame" x="45" y="2.5" width="292" height="20"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="yNx-kt-wCp" secondAttribute="trailing" id="1s1-5F-p0S"/>
|
||||||
|
<constraint firstAttribute="height" constant="25" id="AV7-GY-Eog">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="yNx-kt-wCp" firstAttribute="centerY" secondItem="5rd-jg-Oh0" secondAttribute="centerY" id="DC6-iU-ltm"/>
|
||||||
|
<constraint firstItem="1uD-GG-xPH" firstAttribute="leading" secondItem="5rd-jg-Oh0" secondAttribute="leading" constant="13" id="MEB-ro-ftA">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="1uD-GG-xPH" firstAttribute="centerY" secondItem="5rd-jg-Oh0" secondAttribute="centerY" id="VPN-ZV-bJN"/>
|
||||||
|
<constraint firstItem="yNx-kt-wCp" firstAttribute="leading" secondItem="1uD-GG-xPH" secondAttribute="trailing" constant="8" id="WnA-fm-3Sr">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4aH-sS-rjT">
|
||||||
|
<rect key="frame" x="19" y="240" width="337" height="25"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP Mu'logo" translatesAutoresizingMaskIntoConstraints="NO" id="TIT-KH-pqz">
|
||||||
|
<rect key="frame" x="13" y="0.5" width="24" height="24"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="24" id="FDT-ue-3VW">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="height" constant="24" id="YtB-hc-LKm">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bmg-bY-SQ2">
|
||||||
|
<rect key="frame" x="45" y="2.5" width="292" height="20"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="TIT-KH-pqz" firstAttribute="centerY" secondItem="4aH-sS-rjT" secondAttribute="centerY" id="Jma-0o-3jg"/>
|
||||||
|
<constraint firstItem="bmg-bY-SQ2" firstAttribute="leading" secondItem="TIT-KH-pqz" secondAttribute="trailing" constant="8" id="NsQ-iG-rer">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="height" constant="25" id="WL4-4H-OhN">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="bmg-bY-SQ2" firstAttribute="centerY" secondItem="4aH-sS-rjT" secondAttribute="centerY" id="ZLr-OR-FES"/>
|
||||||
|
<constraint firstItem="TIT-KH-pqz" firstAttribute="leading" secondItem="4aH-sS-rjT" secondAttribute="leading" constant="13" id="ldO-8g-BiT">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="bmg-bY-SQ2" secondAttribute="trailing" id="zhU-hn-ZNb"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s0J-Ld-XhO">
|
||||||
|
<rect key="frame" x="19" y="276" width="337" height="25"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP Dn'logo" translatesAutoresizingMaskIntoConstraints="NO" id="EW0-Rs-5el">
|
||||||
|
<rect key="frame" x="13" y="0.5" width="24" height="24"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="24" id="5Z9-J6-VbC">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="width" constant="24" id="AA0-mY-m5l">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yho-5R-DjF">
|
||||||
|
<rect key="frame" x="45" y="2.5" width="292" height="20"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="EW0-Rs-5el" firstAttribute="leading" secondItem="s0J-Ld-XhO" secondAttribute="leading" constant="13" id="6d1-42-qVf">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="yho-5R-DjF" firstAttribute="leading" secondItem="EW0-Rs-5el" secondAttribute="trailing" constant="8" id="FYP-T2-zeV">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="yho-5R-DjF" firstAttribute="centerY" secondItem="s0J-Ld-XhO" secondAttribute="centerY" id="KDE-um-4t7"/>
|
||||||
|
<constraint firstItem="EW0-Rs-5el" firstAttribute="centerY" secondItem="s0J-Ld-XhO" secondAttribute="centerY" id="jXb-jB-AaL"/>
|
||||||
|
<constraint firstAttribute="height" constant="25" id="k3a-ku-dAt">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="yho-5R-DjF" secondAttribute="trailing" id="xQK-xD-NxY"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fVE-zT-baW">
|
||||||
|
<rect key="frame" x="19" y="364" width="337" height="69"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP Choose'logo" translatesAutoresizingMaskIntoConstraints="NO" id="f2Z-iY-0aL">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="337" height="69"/>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zj9-cg-9xc">
|
||||||
|
<rect key="frame" x="19" y="20.5" width="56" height="28"/>
|
||||||
|
<fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="24"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="/ Week" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sOg-Lz-yAo">
|
||||||
|
<rect key="frame" x="79" y="27.5" width="52" height="21"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="f2Z-iY-0aL" secondAttribute="trailing" id="4wT-u1-Enh"/>
|
||||||
|
<constraint firstItem="f2Z-iY-0aL" firstAttribute="top" secondItem="fVE-zT-baW" secondAttribute="top" id="Hc6-PF-3DH"/>
|
||||||
|
<constraint firstItem="f2Z-iY-0aL" firstAttribute="leading" secondItem="fVE-zT-baW" secondAttribute="leading" id="Kpb-Os-axJ"/>
|
||||||
|
<constraint firstItem="zj9-cg-9xc" firstAttribute="centerY" secondItem="fVE-zT-baW" secondAttribute="centerY" id="Pct-qk-N9a"/>
|
||||||
|
<constraint firstAttribute="height" constant="69" id="RvF-7J-de6">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="f2Z-iY-0aL" secondAttribute="bottom" id="Scv-pU-07I"/>
|
||||||
|
<constraint firstAttribute="width" constant="337" id="T1e-l0-fNS">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="zj9-cg-9xc" firstAttribute="leading" secondItem="fVE-zT-baW" secondAttribute="leading" constant="19" id="VSA-vD-pcL">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="sOg-Lz-yAo" firstAttribute="bottom" secondItem="zj9-cg-9xc" secondAttribute="bottom" id="h7K-PI-r0Z"/>
|
||||||
|
<constraint firstItem="sOg-Lz-yAo" firstAttribute="leading" secondItem="zj9-cg-9xc" secondAttribute="trailing" constant="4" id="nEh-6r-TBY"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<view tag="1" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cw2-8u-Yru">
|
||||||
|
<rect key="frame" x="19" y="457" width="337" height="69"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP Choose'logo" translatesAutoresizingMaskIntoConstraints="NO" id="Y9f-zt-bGB">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="337" height="69"/>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C3t-AB-geN">
|
||||||
|
<rect key="frame" x="19" y="20.5" width="56" height="28"/>
|
||||||
|
<fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="24"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="/ Year" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ONJ-Ib-N5a">
|
||||||
|
<rect key="frame" x="79" y="27.5" width="43" height="21"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="C3t-AB-geN" firstAttribute="leading" secondItem="cw2-8u-Yru" secondAttribute="leading" constant="19" id="4Eq-cN-JNK">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="ONJ-Ib-N5a" firstAttribute="bottom" secondItem="C3t-AB-geN" secondAttribute="bottom" id="AH1-HF-g6k"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="Y9f-zt-bGB" secondAttribute="trailing" id="ASd-yV-Kd7"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="Y9f-zt-bGB" secondAttribute="bottom" id="BPY-Tq-XZx"/>
|
||||||
|
<constraint firstAttribute="width" constant="337" id="JA4-8u-G6U">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="ONJ-Ib-N5a" firstAttribute="leading" secondItem="C3t-AB-geN" secondAttribute="trailing" constant="4" id="TwV-2i-A47"/>
|
||||||
|
<constraint firstAttribute="height" constant="69" id="UHf-8S-8nj">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="Y9f-zt-bGB" firstAttribute="top" secondItem="cw2-8u-Yru" secondAttribute="top" id="bK4-7v-Q0s"/>
|
||||||
|
<constraint firstItem="C3t-AB-geN" firstAttribute="centerY" secondItem="cw2-8u-Yru" secondAttribute="centerY" id="lVU-qb-XvJ"/>
|
||||||
|
<constraint firstItem="Y9f-zt-bGB" firstAttribute="leading" secondItem="cw2-8u-Yru" secondAttribute="leading" id="mNj-wW-BXl"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP Save'bg" translatesAutoresizingMaskIntoConstraints="NO" id="usZ-hA-14r">
|
||||||
|
<rect key="frame" x="249.5" y="443" width="87" height="27"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="27" id="9Xc-Vw-fSW">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="width" constant="87" id="wjD-g1-aYG">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Save 85%" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qu9-bX-6KG">
|
||||||
|
<rect key="frame" x="263.5" y="449" width="59" height="15"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
|
||||||
|
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<view tag="2" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6m2-Pk-kEx">
|
||||||
|
<rect key="frame" x="19" y="550" width="337" height="69"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IAP Choose'logo" translatesAutoresizingMaskIntoConstraints="NO" id="21u-ne-klE">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="337" height="69"/>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mSD-Ht-ZAt">
|
||||||
|
<rect key="frame" x="19" y="20.5" width="56" height="28"/>
|
||||||
|
<fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="24"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="/ Lifetime" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X28-0N-0hT">
|
||||||
|
<rect key="frame" x="79" y="27.5" width="70" height="21"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="69" id="Ers-Zw-6gy">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="X28-0N-0hT" firstAttribute="bottom" secondItem="mSD-Ht-ZAt" secondAttribute="bottom" id="MoV-Jc-Mn4"/>
|
||||||
|
<constraint firstItem="21u-ne-klE" firstAttribute="top" secondItem="6m2-Pk-kEx" secondAttribute="top" id="U0t-Xy-FqS"/>
|
||||||
|
<constraint firstItem="X28-0N-0hT" firstAttribute="leading" secondItem="mSD-Ht-ZAt" secondAttribute="trailing" constant="4" id="XTz-2I-8ny"/>
|
||||||
|
<constraint firstAttribute="width" constant="337" id="dM3-pv-Ig8">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="mSD-Ht-ZAt" firstAttribute="centerY" secondItem="6m2-Pk-kEx" secondAttribute="centerY" id="ej2-LQ-sAP"/>
|
||||||
|
<constraint firstItem="21u-ne-klE" firstAttribute="leading" secondItem="6m2-Pk-kEx" secondAttribute="leading" id="gbt-bf-0hn"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="21u-ne-klE" secondAttribute="trailing" id="opl-fF-WbS"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="21u-ne-klE" secondAttribute="bottom" id="tYv-J5-cDq"/>
|
||||||
|
<constraint firstItem="mSD-Ht-ZAt" firstAttribute="leading" secondItem="6m2-Pk-kEx" secondAttribute="leading" constant="19" id="vYE-qY-r8q">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No mandatory,cancel at anytime" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="m4k-if-t1p">
|
||||||
|
<rect key="frame" x="103" y="657" width="195" height="16"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0ZS-PD-jbN">
|
||||||
|
<rect key="frame" x="20" y="693" width="335" height="52"/>
|
||||||
|
<color key="backgroundColor" red="0.50196078431372548" green="0.97647058823529409" blue="0.53333333333333333" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="52" id="LoK-kz-miC">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="width" constant="335" id="O2F-0w-Twf">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" title="Continue">
|
||||||
|
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</state>
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||||
|
<real key="value" value="14"/>
|
||||||
|
</userDefinedRuntimeAttribute>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
<connections>
|
||||||
|
<action selector="continueClick:" destination="-1" eventType="touchUpInside" id="I6j-Wp-jld"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="No mandatory'logo" translatesAutoresizingMaskIntoConstraints="NO" id="GJR-RQ-rZY">
|
||||||
|
<rect key="frame" x="81" y="657" width="16" height="16"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="16" id="IrK-vo-oLG">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="width" constant="16" id="Ygb-nL-Bp6">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ot4-pt-BUj">
|
||||||
|
<rect key="frame" x="164" y="763" width="47" height="28"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" title="Restore">
|
||||||
|
<color key="titleColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</state>
|
||||||
|
<connections>
|
||||||
|
<action selector="reStoreClick:" destination="-1" eventType="touchUpInside" id="R4J-W4-aXF"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6ck-rH-HPa">
|
||||||
|
<rect key="frame" x="20" y="763" width="81" height="28"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" title="Terms of Use">
|
||||||
|
<color key="titleColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</state>
|
||||||
|
<connections>
|
||||||
|
<action selector="termsClick:" destination="-1" eventType="touchUpInside" id="gJc-0d-5Wb"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GrN-6O-QqU">
|
||||||
|
<rect key="frame" x="271" y="763" width="84" height="28"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" title="Privacy Policy">
|
||||||
|
<color key="titleColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</state>
|
||||||
|
<connections>
|
||||||
|
<action selector="privacyClick:" destination="-1" eventType="touchUpInside" id="6kq-5c-OnT"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="0ZS-PD-jbN" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="0iZ-ba-oFV"/>
|
||||||
|
<constraint firstItem="m4k-if-t1p" firstAttribute="leading" secondItem="GJR-RQ-rZY" secondAttribute="trailing" constant="6" id="2BZ-6H-rWz">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="Ot4-pt-BUj" firstAttribute="top" secondItem="0ZS-PD-jbN" secondAttribute="bottom" constant="18" id="2RC-z3-9bc">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="Ot4-pt-BUj" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="2Rd-mO-aZJ"/>
|
||||||
|
<constraint firstItem="0ZS-PD-jbN" firstAttribute="top" secondItem="m4k-if-t1p" secondAttribute="bottom" constant="20" id="2v7-g2-sam">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="cw2-8u-Yru" firstAttribute="top" secondItem="fVE-zT-baW" secondAttribute="bottom" constant="24" id="6ig-Mk-Ozp">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="5rd-jg-Oh0" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="977-jE-taE"/>
|
||||||
|
<constraint firstItem="4aH-sS-rjT" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="AX8-Pm-KiJ"/>
|
||||||
|
<constraint firstItem="JBI-cg-ZTm" firstAttribute="top" secondItem="nGh-s6-UA5" secondAttribute="top" constant="66" id="AdY-Pj-ibu">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="4aH-sS-rjT" firstAttribute="top" secondItem="5rd-jg-Oh0" secondAttribute="bottom" constant="11" id="Ci4-6G-tIg">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="usZ-hA-14r" firstAttribute="trailing" secondItem="cw2-8u-Yru" secondAttribute="trailing" constant="-19.5" id="F73-qC-gcw">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="cw2-8u-Yru" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="FpI-g3-B2C"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="kdc-al-Dgu" secondAttribute="trailing" id="G1M-BI-TxB"/>
|
||||||
|
<constraint firstItem="6ck-rH-HPa" firstAttribute="leading" secondItem="0ZS-PD-jbN" secondAttribute="leading" id="L1f-uf-qI2"/>
|
||||||
|
<constraint firstItem="m4k-if-t1p" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" multiplier="1.07" id="L8B-66-nB3"/>
|
||||||
|
<constraint firstItem="qu9-bX-6KG" firstAttribute="centerY" secondItem="usZ-hA-14r" secondAttribute="centerY" id="Lbn-XX-Xna"/>
|
||||||
|
<constraint firstItem="s0J-Ld-XhO" firstAttribute="top" secondItem="4aH-sS-rjT" secondAttribute="bottom" constant="11" id="OeH-wx-DYL">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="qu9-bX-6KG" firstAttribute="centerX" secondItem="usZ-hA-14r" secondAttribute="centerX" id="PlX-PY-CFh"/>
|
||||||
|
<constraint firstItem="kdc-al-Dgu" firstAttribute="leading" secondItem="nGh-s6-UA5" secondAttribute="leading" id="RfD-ny-np9"/>
|
||||||
|
<constraint firstItem="6m2-Pk-kEx" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="ShO-bi-I02"/>
|
||||||
|
<constraint firstItem="5rd-jg-Oh0" firstAttribute="top" secondItem="JBI-cg-ZTm" secondAttribute="bottom" constant="-11" id="TqH-pX-5SQ">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="s0J-Ld-XhO" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="WCD-Jc-WSm"/>
|
||||||
|
<constraint firstItem="fVE-zT-baW" firstAttribute="top" secondItem="s0J-Ld-XhO" secondAttribute="bottom" priority="999" constant="63" id="WeJ-cY-e6e">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="4aH-sS-rjT" firstAttribute="width" secondItem="5rd-jg-Oh0" secondAttribute="width" id="bZi-ts-0lb"/>
|
||||||
|
<constraint firstItem="s0J-Ld-XhO" firstAttribute="width" secondItem="4aH-sS-rjT" secondAttribute="width" id="dkz-iw-mR6"/>
|
||||||
|
<constraint firstItem="GrN-6O-QqU" firstAttribute="centerY" secondItem="Ot4-pt-BUj" secondAttribute="centerY" id="fWe-BZ-WpW"/>
|
||||||
|
<constraint firstItem="JBI-cg-ZTm" firstAttribute="leading" secondItem="nGh-s6-UA5" secondAttribute="leading" constant="3.3999999999999999" id="lHh-M8-ZWB">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="GrN-6O-QqU" firstAttribute="trailing" secondItem="0ZS-PD-jbN" secondAttribute="trailing" id="pAf-0M-8a8"/>
|
||||||
|
<constraint firstItem="6m2-Pk-kEx" firstAttribute="top" secondItem="cw2-8u-Yru" secondAttribute="bottom" constant="24" id="qru-Oo-f1x">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="GJR-RQ-rZY" firstAttribute="centerY" secondItem="m4k-if-t1p" secondAttribute="centerY" id="siD-on-ehc"/>
|
||||||
|
<constraint firstItem="fVE-zT-baW" firstAttribute="top" secondItem="5rd-jg-Oh0" secondAttribute="bottom" priority="500" constant="74" id="tVb-7S-rd8">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="0ZS-PD-jbN" firstAttribute="top" secondItem="6m2-Pk-kEx" secondAttribute="bottom" constant="74" id="vsN-ff-49R">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="usZ-hA-14r" firstAttribute="top" secondItem="cw2-8u-Yru" secondAttribute="top" constant="-14" id="wTg-lt-fKa">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="kdc-al-Dgu" secondAttribute="bottom" id="wUx-ey-X83"/>
|
||||||
|
<constraint firstItem="6ck-rH-HPa" firstAttribute="centerY" secondItem="Ot4-pt-BUj" secondAttribute="centerY" id="x9y-Hj-PR6"/>
|
||||||
|
<constraint firstItem="fVE-zT-baW" firstAttribute="centerX" secondItem="nGh-s6-UA5" secondAttribute="centerX" id="xfs-hW-X9O"/>
|
||||||
|
<constraint firstItem="kdc-al-Dgu" firstAttribute="top" secondItem="nGh-s6-UA5" secondAttribute="top" id="zjC-bZ-e5Y"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="nGh-s6-UA5" firstAttribute="trailing" secondItem="aSd-tu-AKa" secondAttribute="trailing" id="HXu-Ht-MlO"/>
|
||||||
|
<constraint firstItem="nGh-s6-UA5" firstAttribute="leading" secondItem="aSd-tu-AKa" secondAttribute="leading" id="JE7-jL-185"/>
|
||||||
|
<constraint firstItem="nGh-s6-UA5" firstAttribute="top" secondItem="aSd-tu-AKa" secondAttribute="top" id="Jog-e3-a36"/>
|
||||||
|
<constraint firstItem="nGh-s6-UA5" firstAttribute="width" secondItem="g92-EX-OdQ" secondAttribute="width" id="rem-Dp-P4v"/>
|
||||||
|
<constraint firstItem="nGh-s6-UA5" firstAttribute="bottom" secondItem="aSd-tu-AKa" secondAttribute="bottom" id="x3L-0x-fgi"/>
|
||||||
|
</constraints>
|
||||||
|
<viewLayoutGuide key="contentLayoutGuide" id="aSd-tu-AKa"/>
|
||||||
|
<viewLayoutGuide key="frameLayoutGuide" id="g92-EX-OdQ"/>
|
||||||
|
</scrollView>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zrl-aI-cae">
|
||||||
|
<rect key="frame" x="317" y="24" width="42" height="42"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="42" id="8Vw-5K-3gU"/>
|
||||||
|
<constraint firstAttribute="height" constant="42" id="caJ-4U-tpY"/>
|
||||||
|
</constraints>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" backgroundImage="IAP Out'logo"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="dismissClick:" destination="-1" eventType="touchUpInside" id="Sr0-ot-Cfs"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="Zrl-aI-cae" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="4" id="1Hm-Td-tsh">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="BnJ-Xo-PqP" secondAttribute="bottom" id="3Ef-ge-xiV"/>
|
||||||
|
<constraint firstItem="5rd-jg-Oh0" firstAttribute="width" secondItem="i5M-Pr-FkT" secondAttribute="width" multiplier="0.898667" id="AX5-Ce-xzb"/>
|
||||||
|
<constraint firstItem="BnJ-Xo-PqP" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="GtA-xD-gPQ"/>
|
||||||
|
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="Zrl-aI-cae" secondAttribute="trailing" constant="16" id="Iqb-vj-BRx">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="BnJ-Xo-PqP" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="Jhk-KI-R1D"/>
|
||||||
|
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="BnJ-Xo-PqP" secondAttribute="trailing" id="oUl-QC-ajw"/>
|
||||||
|
</constraints>
|
||||||
|
<point key="canvasLocation" x="130.40000000000001" y="-13.043478260869566"/>
|
||||||
|
</view>
|
||||||
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<image name="IAP AD'logo" width="24" height="24"/>
|
||||||
|
<image name="IAP B'bg" width="375" height="812"/>
|
||||||
|
<image name="IAP Choose'logo" width="337" height="69"/>
|
||||||
|
<image name="IAP Dn'logo" width="24" height="24"/>
|
||||||
|
<image name="IAP Mu'logo" width="24" height="24"/>
|
||||||
|
<image name="IAP Out'logo" width="42" height="42"/>
|
||||||
|
<image name="IAP Save'bg" width="87" height="27"/>
|
||||||
|
<image name="No mandatory'logo" width="16" height="16"/>
|
||||||
|
<image name="Rights'logo" width="229" height="149"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
@ -121,6 +121,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
private func switchAOrBAction() {
|
private func switchAOrBAction() {
|
||||||
//首先检测之前是否进入过B面
|
//首先检测之前是否进入过B面
|
||||||
guard UserDefaults.standard.bool(forKey: "MP_Into_B") != true else {
|
guard UserDefaults.standard.bool(forKey: "MP_Into_B") != true else {
|
||||||
|
MP_IAPManager.shared.startLunchStatus()
|
||||||
//更新开关以及响应的数据
|
//更新开关以及响应的数据
|
||||||
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
||||||
if open {
|
if open {
|
||||||
@ -166,6 +167,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
MP_NetWorkManager.shared.performTaskNetWrokAvailable {
|
MP_NetWorkManager.shared.performTaskNetWrokAvailable {
|
||||||
[weak self] in
|
[weak self] in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
|
MP_IAPManager.shared.startLunchStatus()
|
||||||
//进行开关检测
|
//进行开关检测
|
||||||
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
|
|||||||
@ -46,3 +46,37 @@ extension Range where Bound == String.Index {
|
|||||||
return NSRange(location: utf16IndexStart, length: utf16IndexEnd - utf16IndexStart)
|
return NSRange(location: utf16IndexStart, length: utf16IndexEnd - utf16IndexStart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///扩展UILabel
|
||||||
|
extension UILabel {
|
||||||
|
///设置文本渐变色
|
||||||
|
func setGradientTextColor(_ colors:[CGColor]) {
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
//设置一个渐变层
|
||||||
|
let gradientLayer = CAGradientLayer()
|
||||||
|
gradientLayer.colors = colors
|
||||||
|
gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
|
||||||
|
gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
|
||||||
|
gradientLayer.frame = self.bounds
|
||||||
|
//设置一个文本层
|
||||||
|
let textLayer = CATextLayer()
|
||||||
|
textLayer.frame = self.bounds
|
||||||
|
textLayer.string = self.attributedText
|
||||||
|
textLayer.isWrapped = true
|
||||||
|
textLayer.truncationMode = .end
|
||||||
|
textLayer.alignmentMode = .center
|
||||||
|
textLayer.contentsScale = UIScreen.main.scale
|
||||||
|
gradientLayer.mask = textLayer
|
||||||
|
//添加层级
|
||||||
|
self.layer.addSublayer(gradientLayer)
|
||||||
|
}
|
||||||
|
///清理文本渐变色
|
||||||
|
func cleanGradientTextColor() {
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
//判断是否具备渐变色层
|
||||||
|
for item in layer.sublayers ?? [] {
|
||||||
|
if item is CAGradientLayer {
|
||||||
|
item.removeFromSuperlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -75,6 +75,10 @@ let offline_songBGImage:UIImage = UIImage(named: "Offline Songs")!
|
|||||||
let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")!
|
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")!
|
||||||
|
///常用渐变色组合值
|
||||||
|
let gradientTextColors:[CGColor] = [UIColor(red: 0, green: 0.863, blue: 1, alpha: 1).cgColor,
|
||||||
|
UIColor(red: 0, green: 1, blue: 0.561, alpha: 1).cgColor,
|
||||||
|
UIColor(red: 0.776, green: 1, blue: 0.639, alpha: 1).cgColor]
|
||||||
|
|
||||||
//MARK: - 全局变量与方法
|
//MARK: - 全局变量与方法
|
||||||
//存储默认配置值
|
//存储默认配置值
|
||||||
|
|||||||
@ -15,6 +15,14 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
private let sharedInstance = GADMobileAds.sharedInstance()
|
private let sharedInstance = GADMobileAds.sharedInstance()
|
||||||
///广告总开关
|
///广告总开关
|
||||||
private var openAdStatus:Bool = true
|
private var openAdStatus:Bool = true
|
||||||
|
///设置广告总开关
|
||||||
|
func setOpenAdStatus(_ bool:Bool) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
openAdStatus = bool
|
||||||
|
}
|
||||||
|
}
|
||||||
///广告过期时间(50分钟)
|
///广告过期时间(50分钟)
|
||||||
private let expirationTime:TimeInterval = 3000
|
private let expirationTime:TimeInterval = 3000
|
||||||
|
|
||||||
@ -753,7 +761,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
var completePlayInterstitialAdBlock:(() -> Void)?
|
var completePlayInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载播放插页广告
|
//异步加载播放插页广告
|
||||||
func loadPlayInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
func loadPlayInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingPlayInterstitialAd || isPlayInterstitialAdAvailable() {
|
if isLoadingPlayInterstitialAd || isPlayInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -802,7 +813,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
}
|
}
|
||||||
///播放插页广告展示
|
///播放插页广告展示
|
||||||
func showPlayInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
func showPlayInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||||
guard !interstitialSwitch, !isShowingPlayInterstitialAd else { return }
|
guard !interstitialSwitch, !isShowingPlayInterstitialAd else { return }
|
||||||
//检索是否存在插页间隔时间
|
//检索是否存在插页间隔时间
|
||||||
@ -869,7 +882,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
var completeSwitchInterstitialAdBlock:(() -> Void)?
|
var completeSwitchInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载切歌插页广告
|
//异步加载切歌插页广告
|
||||||
func loadSwitchInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
func loadSwitchInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingSwitchInterstitialAd || isSwitchInterstitialAdAvailable() {
|
if isLoadingSwitchInterstitialAd || isSwitchInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -917,7 +933,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
}
|
}
|
||||||
///切歌插页广告展示
|
///切歌插页广告展示
|
||||||
func showSwitchInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
func showSwitchInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||||
guard !interstitialSwitch, !isShowingSwitchInterstitialAd else { return }
|
guard !interstitialSwitch, !isShowingSwitchInterstitialAd else { return }
|
||||||
//检索是否存在插页间隔时间
|
//检索是否存在插页间隔时间
|
||||||
@ -983,7 +1001,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
var completeLoadInterstitialAdBlock:(() -> Void)?
|
var completeLoadInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载下载插页广告
|
//异步加载下载插页广告
|
||||||
func loadLoadInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
func loadLoadInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingLoadInterstitialAd || isLoadInterstitialAdAvailable() {
|
if isLoadingLoadInterstitialAd || isLoadInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -1031,7 +1052,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
}
|
}
|
||||||
///下载插页广告展示
|
///下载插页广告展示
|
||||||
func showLoadInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
func showLoadInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||||
guard !interstitialSwitch, !isShowingLoadInterstitialAd else { return }
|
guard !interstitialSwitch, !isShowingLoadInterstitialAd else { return }
|
||||||
//检索是否存在插页间隔时间
|
//检索是否存在插页间隔时间
|
||||||
@ -1116,7 +1139,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
var onLibraryNativeAdBlock:(() -> Void)?
|
var onLibraryNativeAdBlock:(() -> Void)?
|
||||||
///配置搜索原生广告加载器
|
///配置搜索原生广告加载器
|
||||||
func configureLibraryNativeAd(rootController vc:UIViewController) {
|
func configureLibraryNativeAd(rootController vc:UIViewController) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
if libraryViewController == nil {
|
if libraryViewController == nil {
|
||||||
libraryViewController = vc
|
libraryViewController = vc
|
||||||
}
|
}
|
||||||
@ -1222,7 +1247,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
}
|
}
|
||||||
//异步加载曲库插页广告
|
//异步加载曲库插页广告
|
||||||
func loadLibraryInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
func loadLibraryInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingLibraryInterstitialAd || isLibraryInterstitialAdAvailable() {
|
if isLoadingLibraryInterstitialAd || isLibraryInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -1270,7 +1298,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
}
|
}
|
||||||
///曲库插页广告展示
|
///曲库插页广告展示
|
||||||
func showLibraryInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
func showLibraryInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||||
guard !interstitialSwitch, !isShowingLibraryInterstitialAd else { return }
|
guard !interstitialSwitch, !isShowingLibraryInterstitialAd else { return }
|
||||||
//检索是否存在插页间隔时间
|
//检索是否存在插页间隔时间
|
||||||
@ -1339,7 +1369,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
var completeGlobalInterstitialAdBlock:(() -> Void)?
|
var completeGlobalInterstitialAdBlock:(() -> Void)?
|
||||||
//异步加载全局插页广告
|
//异步加载全局插页广告
|
||||||
func loadGlobalInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
func loadGlobalInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 检测当前是否有广告或者有广告正在加载
|
// 检测当前是否有广告或者有广告正在加载
|
||||||
if isLoadingGlobalInterstitialAd || isGlobalInterstitialAdAvailable() {
|
if isLoadingGlobalInterstitialAd || isGlobalInterstitialAdAvailable() {
|
||||||
// 有广告或有广告在加载
|
// 有广告或有广告在加载
|
||||||
@ -1375,7 +1407,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
|||||||
}
|
}
|
||||||
///全局插页广告展示
|
///全局插页广告展示
|
||||||
func showGlobalInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
func showGlobalInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||||
guard openAdStatus else {return}
|
guard openAdStatus else {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||||
guard !interstitialSwitch, !isShowingGlobalInterstitialAd else { return }
|
guard !interstitialSwitch, !isShowingGlobalInterstitialAd else { return }
|
||||||
//检索是否存在插页间隔时间
|
//检索是否存在插页间隔时间
|
||||||
|
|||||||
@ -144,6 +144,28 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
}
|
}
|
||||||
MP_AdMobManager.shared.reloadAdMobIDs()
|
MP_AdMobManager.shared.reloadAdMobIDs()
|
||||||
}
|
}
|
||||||
|
//更新禁用名单
|
||||||
|
if let trashLists = self.remoteConfig.configValue(forKey: "trashLists").jsonValue as? [String:Any], let lists = trashLists["lists"] as? [[String:Any]] {
|
||||||
|
//将名单中所有处于启用状态的内容提取出来
|
||||||
|
var array:[MPPositive_TrashListModel] = lists.map({.init($0)})
|
||||||
|
array = array.filter({$0.statu == true})
|
||||||
|
//将启用的禁止名单进行分发
|
||||||
|
var trashKeyWords:[String] = []
|
||||||
|
var trashSingerIDs:[String] = []
|
||||||
|
var trashVideoIDs:[String] = []
|
||||||
|
array.forEach { item in
|
||||||
|
trashKeyWords.append(contentsOf: item.keyWords)
|
||||||
|
trashSingerIDs.append(item.singerID)
|
||||||
|
trashVideoIDs.append(contentsOf: item.videoIDs)
|
||||||
|
}
|
||||||
|
//去除所有为空的字符
|
||||||
|
trashKeyWords = trashKeyWords.filter({$0.isEmpty == false})
|
||||||
|
MP_NetWorkManager.shared.setTrashKeyWords(trashKeyWords)
|
||||||
|
trashSingerIDs = trashSingerIDs.filter({$0.isEmpty == false})
|
||||||
|
MP_NetWorkManager.shared.setTrashSingerIds(trashSingerIDs)
|
||||||
|
trashVideoIDs = trashVideoIDs.filter({$0.isEmpty == false})
|
||||||
|
MP_NetWorkManager.shared.setTrashVideoIds(trashVideoIDs)
|
||||||
|
}
|
||||||
//更新版本数据设置
|
//更新版本数据设置
|
||||||
if let versionData = self.remoteConfig.configValue(forKey: "dataVersion").jsonValue as? [String:String] {
|
if let versionData = self.remoteConfig.configValue(forKey: "dataVersion").jsonValue as? [String:String] {
|
||||||
//对数据进行更新
|
//对数据进行更新
|
||||||
@ -786,3 +808,4 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
return losAngelesTimeString
|
return losAngelesTimeString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,9 +10,9 @@ import StoreKit
|
|||||||
///内部购买项目管理器
|
///内部购买项目管理器
|
||||||
class MP_IAPManager: NSObject {
|
class MP_IAPManager: NSObject {
|
||||||
///单例
|
///单例
|
||||||
let shared = MP_IAPManager()
|
static let shared = MP_IAPManager()
|
||||||
///产品ID(根据开关获取)
|
///产品ID(根据开关获取)
|
||||||
private var productIdentifiers:[String] = ["6587553652","6587553795","6587554369"]
|
private var productIdentifiers:[String] = ["1weekvip","1yearvip","lifetimevip"]
|
||||||
///产品请求(根据ID获取产品信息)
|
///产品请求(根据ID获取产品信息)
|
||||||
private var productsRequest:SKProductsRequest?
|
private var productsRequest:SKProductsRequest?
|
||||||
///可用产品组
|
///可用产品组
|
||||||
@ -20,13 +20,22 @@ class MP_IAPManager: NSObject {
|
|||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
SKPaymentQueue.default().add(self)
|
||||||
}
|
}
|
||||||
//执行产品请求
|
deinit {
|
||||||
|
SKPaymentQueue.default().remove(self)
|
||||||
|
}
|
||||||
|
///执行产品请求
|
||||||
func requestProducts() {
|
func requestProducts() {
|
||||||
|
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||||
|
//无网络
|
||||||
|
print("无网络状况,无法获得产品")
|
||||||
|
return
|
||||||
|
}
|
||||||
//清空可用产品
|
//清空可用产品
|
||||||
availableProducts = []
|
availableProducts = []
|
||||||
//将产品ID转为Set集合
|
//将产品ID转为Set集合
|
||||||
var setStrings:Set<String> = Set(productIdentifiers)
|
let setStrings:Set<String> = Set(productIdentifiers)
|
||||||
//初始化产品请求
|
//初始化产品请求
|
||||||
productsRequest = SKProductsRequest(productIdentifiers: setStrings)
|
productsRequest = SKProductsRequest(productIdentifiers: setStrings)
|
||||||
//实现请求代理
|
//实现请求代理
|
||||||
@ -34,11 +43,73 @@ class MP_IAPManager: NSObject {
|
|||||||
//开始执行请求
|
//开始执行请求
|
||||||
productsRequest?.start()
|
productsRequest?.start()
|
||||||
}
|
}
|
||||||
|
///对指定产品进行购买
|
||||||
|
func purchaseProduct(_ index:Int) {
|
||||||
|
//检索用户选择的产品
|
||||||
|
guard availableProducts.indices.contains(index) else {
|
||||||
|
//越界了,说明广告总数出了问题,重新请求
|
||||||
|
MP_HUD.onlytext("Try again!", delay: 1.0, completion: nil)
|
||||||
|
requestProducts()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let id = productIdentifiers[index]
|
||||||
|
if let product = availableProducts.first(where: {$0.productIdentifier == id}) {
|
||||||
|
//将产品转为交易项
|
||||||
|
let payment = SKPayment(product: product)
|
||||||
|
//将交易项添加进购买线程中
|
||||||
|
SKPaymentQueue.default().add(payment)
|
||||||
|
MP_HUD.loading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///用户重新检索交易
|
||||||
|
func restorePurchases() {
|
||||||
|
MP_HUD.loading()
|
||||||
|
//更新信息
|
||||||
|
SKPaymentQueue.default().restoreCompletedTransactions()
|
||||||
|
}
|
||||||
|
///系统自动检索
|
||||||
|
func systemRestorePurchases() {
|
||||||
|
let receiptURL = Bundle.main.appStoreReceiptURL
|
||||||
|
guard let receipt = try? Data(contentsOf: receiptURL!) else {
|
||||||
|
// 收据不存在
|
||||||
|
print("没有收据,广告默认开")
|
||||||
|
//不能调用AppStore,默认使用广告
|
||||||
|
MP_AdMobManager.shared.setOpenAdStatus(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//收据,重置交易记录
|
||||||
|
SKPaymentQueue.default().restoreCompletedTransactions()
|
||||||
|
}
|
||||||
|
///启动时检索是否购买了广告
|
||||||
|
func startLunchStatus() {
|
||||||
|
//判断是否存在用户收据
|
||||||
|
let receiptURL = Bundle.main.appStoreReceiptURL
|
||||||
|
guard let receipt = try? Data(contentsOf: receiptURL!) else {
|
||||||
|
// 收据不存在
|
||||||
|
print("没有收据,广告默认开")
|
||||||
|
//不能调用AppStore,默认使用广告
|
||||||
|
MP_AdMobManager.shared.setOpenAdStatus(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//有收据
|
||||||
|
print("有收据,开始检索本地信息")
|
||||||
|
reloadOpenStatus()
|
||||||
|
}
|
||||||
|
///更新广告状态
|
||||||
|
func reloadOpenStatus() {
|
||||||
|
//更新广告开关状态
|
||||||
|
if isProductPurchased(productId: productIdentifiers[0]) || isProductPurchased(productId: productIdentifiers[1]) || isProductPurchased(productId: productIdentifiers[2]){
|
||||||
|
//设置广告开关为关
|
||||||
|
MP_AdMobManager.shared.setOpenAdStatus(false)
|
||||||
|
}else {
|
||||||
|
MP_AdMobManager.shared.setOpenAdStatus(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//MARK: - SKProductsRequestDelegate
|
//MARK: - SKProductsRequestDelegate
|
||||||
extension MP_IAPManager: SKProductsRequestDelegate {
|
extension MP_IAPManager: SKProductsRequestDelegate, SKPaymentTransactionObserver {
|
||||||
//产品请求回调执行
|
///产品请求回调执行
|
||||||
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||||
//获得可用产品
|
//获得可用产品
|
||||||
availableProducts = response.products
|
availableProducts = response.products
|
||||||
@ -48,5 +119,175 @@ extension MP_IAPManager: SKProductsRequestDelegate {
|
|||||||
print("无可用产品")
|
print("无可用产品")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
//产品可用,检索产品内容
|
||||||
|
for (index, item) in availableProducts.enumerated() {
|
||||||
|
print("第\(index)号产品--\(item)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///产品请求失败
|
||||||
|
func request(_ request: SKRequest, didFailWithError error: any Error) {
|
||||||
|
print("Failed to fetch products: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
///当交易的状况发生变化后
|
||||||
|
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||||
|
//遍历交易项
|
||||||
|
transactions.forEach { item in
|
||||||
|
//检索每笔交易的情况
|
||||||
|
switch item.transactionState {
|
||||||
|
case .purchasing://交易中
|
||||||
|
break
|
||||||
|
case .purchased://用户已经付款了
|
||||||
|
complete(transaction: item)
|
||||||
|
case .failed://交易失败了
|
||||||
|
fail(transaction: item)
|
||||||
|
case .restored://交易重置
|
||||||
|
restore(transaction: item)
|
||||||
|
case .deferred://等待外部操作
|
||||||
|
break
|
||||||
|
@unknown default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///重置交易状况
|
||||||
|
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
|
||||||
|
print("已重启交易")
|
||||||
|
MP_HUD.hideNow()
|
||||||
|
//确定用户是否购买过订单
|
||||||
|
if queue.transactions.isEmpty {
|
||||||
|
//用户ID没有购买过任何与当前产品有关的交易
|
||||||
|
print("没有购买产品/交易已过期")
|
||||||
|
productIdentifiers.forEach { item in
|
||||||
|
cleanPurchase(productId: item)
|
||||||
|
}
|
||||||
|
MP_AdMobManager.shared.setOpenAdStatus(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: any Error) {
|
||||||
|
print("重启交易失败")
|
||||||
|
MP_HUD.error("The current transaction failed, \(error.localizedDescription)", delay: 1.0, completion: nil)
|
||||||
|
//清理所有的VIP信息
|
||||||
|
productIdentifiers.forEach { item in
|
||||||
|
cleanPurchase(productId: item)
|
||||||
|
}
|
||||||
|
MP_AdMobManager.shared.setOpenAdStatus(true)
|
||||||
|
}
|
||||||
|
//存入交易信息值
|
||||||
|
private func storePurchase(productId: String) {
|
||||||
|
if isProductPurchased(productId: productId) == false {
|
||||||
|
var purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? []
|
||||||
|
purchasedProducts.append(productId)
|
||||||
|
UserDefaults.standard.set(purchasedProducts, forKey: "PurchasedProducts")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//检索用户是否购买该产品VIP产品
|
||||||
|
private func isProductPurchased(productId: String) -> Bool {
|
||||||
|
let purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? []
|
||||||
|
return purchasedProducts.contains(productId)
|
||||||
|
}
|
||||||
|
//清理对应的广告ID
|
||||||
|
private func cleanPurchase(productId: String) {
|
||||||
|
if isProductPurchased(productId: productId) {
|
||||||
|
var purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? []
|
||||||
|
purchasedProducts.removeAll(where: {$0 == productId})
|
||||||
|
UserDefaults.standard.set(purchasedProducts, forKey: "PurchasedProducts")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///交易完成
|
||||||
|
private func complete(transaction: SKPaymentTransaction) {
|
||||||
|
MP_HUD.success("Successfully purchased", delay: 1.0, completion: nil)
|
||||||
|
print("Transaction completed successfully.")
|
||||||
|
// 存储购买信息
|
||||||
|
self.storePurchase(productId: transaction.payment.productIdentifier)
|
||||||
|
SKPaymentQueue.default().finishTransaction(transaction)
|
||||||
|
//更新广告开关状态
|
||||||
|
reloadOpenStatus()
|
||||||
|
}
|
||||||
|
//重启交易
|
||||||
|
private func restore(transaction: SKPaymentTransaction) {
|
||||||
|
print("Transaction restored.")
|
||||||
|
// 存储购买信息
|
||||||
|
self.storePurchase(productId: transaction.payment.productIdentifier)
|
||||||
|
SKPaymentQueue.default().finishTransaction(transaction)
|
||||||
|
//更新广告开关状态
|
||||||
|
reloadOpenStatus()
|
||||||
|
}
|
||||||
|
///交易失败
|
||||||
|
private func fail(transaction: SKPaymentTransaction) {
|
||||||
|
//检索错误
|
||||||
|
if let error = transaction.error as NSError? {
|
||||||
|
if error.code != SKError.paymentCancelled.rawValue {
|
||||||
|
MP_HUD.error("The current transaction failed, \(error.localizedDescription)", delay: 1.0, completion: nil)
|
||||||
|
} else {
|
||||||
|
MP_HUD.onlytext("The current transaction has been canceled", delay: 1.0, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//获取收据信息
|
||||||
|
func fetchReceipt() -> String? {
|
||||||
|
guard let receiptURL = Bundle.main.appStoreReceiptURL else { return nil }
|
||||||
|
guard let receiptData = try? Data(contentsOf: receiptURL) else { return nil }
|
||||||
|
return receiptData.base64EncodedString(options: [])
|
||||||
|
}
|
||||||
|
//验证收据信息
|
||||||
|
func validateReceipt(completion: @escaping (Bool) -> Void) {
|
||||||
|
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//获取收据信息
|
||||||
|
guard let receiptString = fetchReceipt() else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//生成请求参数
|
||||||
|
let requestDictionary = ["receipt-data": receiptString,
|
||||||
|
"password": "d29627e4f78b4b50a0ce5166acd8aa9f" ]
|
||||||
|
guard JSONSerialization.isValidJSONObject(requestDictionary) else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
|
||||||
|
#if DEBUG
|
||||||
|
let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt"
|
||||||
|
#else
|
||||||
|
let validationURLString = "https://buy.itunes.apple.com/verifyReceipt"
|
||||||
|
#endif
|
||||||
|
guard let validationURL = URL(string: validationURLString) else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//创建请求
|
||||||
|
var request = URLRequest(url: validationURL)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.cachePolicy = .reloadIgnoringCacheData
|
||||||
|
request.httpBody = requestData
|
||||||
|
//设置会话
|
||||||
|
let session = URLSession.shared
|
||||||
|
//执行任务
|
||||||
|
let task = session.dataTask(with: request) { data, response, error in
|
||||||
|
guard error == nil, let data = data else {
|
||||||
|
completion(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
|
||||||
|
print("Receipt validation response: \(jsonResponse)")
|
||||||
|
// 根据苹果的验证响应处理购买信息
|
||||||
|
completion(true)
|
||||||
|
} else {
|
||||||
|
completion(false)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
completion(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task.resume()
|
||||||
|
} catch {
|
||||||
|
completion(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,26 @@ class MP_NetWorkManager: NSObject {
|
|||||||
private let codes:[String] = [
|
private let codes:[String] = [
|
||||||
"CL","GB","ID","IN","IT","IL","HU","NZ","ES","UY","UA","UG","GT","TR","TZ","SA","RS","SV","CH","SE","JP","PT","NO","NG","NI","ZA","MX","PE","US","RO","LU","KE","ZW","CZ","CA","HN","NL","KR","CR","CO","FI","FR","EC","RU","DO","DK","BO","PL","IS","BE","BR","PA","PY","AU","AT","EE","IE","EG","AE","AR","ZZ"
|
"CL","GB","ID","IN","IT","IL","HU","NZ","ES","UY","UA","UG","GT","TR","TZ","SA","RS","SV","CH","SE","JP","PT","NO","NG","NI","ZA","MX","PE","US","RO","LU","KE","ZW","CZ","CA","HN","NL","KR","CR","CO","FI","FR","EC","RU","DO","DK","BO","PL","IS","BE","BR","PA","PY","AU","AT","EE","IE","EG","AE","AR","ZZ"
|
||||||
]
|
]
|
||||||
|
///禁止关键词
|
||||||
|
private var trashKeyWords:[String] = []
|
||||||
|
///设置禁止关键词
|
||||||
|
func setTrashKeyWords(_ words:[String]){
|
||||||
|
trashKeyWords = words
|
||||||
|
}
|
||||||
|
///禁止歌手(id组)
|
||||||
|
private var trashSingerIds:[String] = []
|
||||||
|
///设置禁用歌手
|
||||||
|
func setTrashSingerIds(_ ids:[String]) {
|
||||||
|
trashSingerIds = ids
|
||||||
|
}
|
||||||
|
///禁止歌曲(id组)
|
||||||
|
private var trashVideoIds:[String] = []
|
||||||
|
///设置禁用歌曲
|
||||||
|
func setTrashVideoIds(_ ids:[String]) {
|
||||||
|
trashVideoIds = ids
|
||||||
|
}
|
||||||
|
///禁止下载
|
||||||
|
private var isAllowedDownload:Bool = true
|
||||||
//网络状态
|
//网络状态
|
||||||
enum NetWorkStatus: String {
|
enum NetWorkStatus: String {
|
||||||
case notReachable = "网络不可用"
|
case notReachable = "网络不可用"
|
||||||
@ -1237,6 +1257,15 @@ extension MP_NetWorkManager {
|
|||||||
print("Url is Incorrect")
|
print("Url is Incorrect")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
//检索关键词
|
||||||
|
guard trashKeyWords.contains(text) == false else {
|
||||||
|
//是禁用关键词
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
|
||||||
|
print("是禁用关键词")
|
||||||
|
completion([])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
//设置参数
|
//设置参数
|
||||||
let parameters:[String:Any] = [
|
let parameters:[String:Any] = [
|
||||||
"query":text,
|
"query":text,
|
||||||
@ -1537,8 +1566,8 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
browse.items.append(.init(item))
|
browse.items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
browse.items.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
browses.append(browse)
|
browses.append(browse)
|
||||||
@ -1618,8 +1647,8 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
browse.items.append(.init(item))
|
browse.items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
browse.items.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
browses.append(browse)
|
browses.append(browse)
|
||||||
@ -1649,8 +1678,8 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
items.append(.init(item))
|
items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
items.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}else if let musicShelfRenderer = content.musicShelfRenderer{
|
}else if let musicShelfRenderer = content.musicShelfRenderer{
|
||||||
@ -1660,8 +1689,8 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
items.append(.init(item))
|
items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
items.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1681,8 +1710,8 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
items.append(.init(item))
|
items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
items.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}else if let musicShelfRenderer = content.musicShelfRenderer{
|
}else if let musicShelfRenderer = content.musicShelfRenderer{
|
||||||
@ -1692,8 +1721,8 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
items.append(.init(item))
|
items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
items.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1785,8 +1814,8 @@ extension MP_NetWorkManager {
|
|||||||
params = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.params
|
params = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.params
|
||||||
//解析模块内容
|
//解析模块内容
|
||||||
musicCarouselShelfRenderer.contents?.forEach({ item in
|
musicCarouselShelfRenderer.contents?.forEach({ item in
|
||||||
if item.musicTwoRowItemRenderer != nil {
|
if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
itemViews.append(.init(parsingMusicTwoRowItemRenderer(item.musicTwoRowItemRenderer!)))
|
itemViews.append(.init(d))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1817,8 +1846,8 @@ extension MP_NetWorkManager {
|
|||||||
if let gridRenderer = content.gridRenderer {
|
if let gridRenderer = content.gridRenderer {
|
||||||
//是专辑列表
|
//是专辑列表
|
||||||
gridRenderer.items?.forEach({ item in
|
gridRenderer.items?.forEach({ item in
|
||||||
if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer {
|
if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
array.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
array.append(.init(d))
|
||||||
}
|
}
|
||||||
continuation = gridRenderer.continuations?.first?.nextContinuationData?.continuation
|
continuation = gridRenderer.continuations?.first?.nextContinuationData?.continuation
|
||||||
clickTrackingParams = gridRenderer.continuations?.first?.nextContinuationData?.clickTrackingParams
|
clickTrackingParams = gridRenderer.continuations?.first?.nextContinuationData?.clickTrackingParams
|
||||||
@ -1928,7 +1957,9 @@ extension MP_NetWorkManager {
|
|||||||
browse.items.append(.init(item))
|
browse.items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||||
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
|
browse.items.append(.init(item))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if browse.items.isEmpty != true {
|
if browse.items.isEmpty != true {
|
||||||
@ -1943,7 +1974,9 @@ extension MP_NetWorkManager {
|
|||||||
browse.items.append(.init(item))
|
browse.items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
|
||||||
browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
|
if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
|
browse.items.append(.init(item))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if browse.items.isEmpty != true {
|
if browse.items.isEmpty != true {
|
||||||
@ -2109,10 +2142,11 @@ extension MP_NetWorkManager {
|
|||||||
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
list.items.append(.init(item))
|
list.items.append(.init(item))
|
||||||
}
|
}
|
||||||
}else if content.musicTwoRowItemRenderer != nil {
|
}else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer{
|
||||||
let item = parsingMusicTwoRowItemRenderer(content.musicTwoRowItemRenderer!)
|
if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
|
||||||
list.items.append(.init(item))
|
list.items.append(.init(item))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
sectionLists.append(list)
|
sectionLists.append(list)
|
||||||
}
|
}
|
||||||
@ -2213,50 +2247,55 @@ extension MP_NetWorkManager {
|
|||||||
if let contents = musicCardShelfRenderer.contents {
|
if let contents = musicCardShelfRenderer.contents {
|
||||||
contents.forEach { content in
|
contents.forEach { content in
|
||||||
//生成更多内容块
|
//生成更多内容块
|
||||||
let item = MPPositive_BrowseItemModel()
|
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, (musicResponsiveListItemRenderer.playlistItemData != nil || musicResponsiveListItemRenderer.navigationEndpoint != nil) && (musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"){
|
|
||||||
if let trackingParams = musicResponsiveListItemRenderer.trackingParams {
|
|
||||||
item.clickTrackingParams = trackingParams
|
|
||||||
}
|
|
||||||
//设置预览图
|
|
||||||
item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
|
||||||
//设置一级标题与二级标题
|
|
||||||
for (index, flexColumn) in (musicResponsiveListItemRenderer.flexColumns ?? []).enumerated() {
|
|
||||||
if index == 0 {
|
|
||||||
//一级标题
|
|
||||||
item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
|
||||||
}else {
|
|
||||||
//二级标题
|
|
||||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.playListId = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
|
||||||
//设置id和类型
|
|
||||||
if musicResponsiveListItemRenderer.playlistItemData != nil {
|
|
||||||
//是单曲
|
|
||||||
item.itemType = .single
|
|
||||||
item.videoId = musicResponsiveListItemRenderer.playlistItemData?.videoId
|
|
||||||
}else {
|
|
||||||
//是专辑列表/艺术家
|
|
||||||
item.browseId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
|
|
||||||
let pageType = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
|
||||||
if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
|
||||||
//判断细分
|
|
||||||
if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
|
||||||
item.artistId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
|
|
||||||
//是艺术家
|
|
||||||
item.itemType = .artist
|
|
||||||
}else {
|
|
||||||
//是列表/专辑
|
|
||||||
item.itemType = .list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||||
resultList.previewItemViews.append(.init(item))
|
resultList.previewItemViews.append(.init(item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// let item = MPPositive_BrowseItemModel()
|
||||||
|
// if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, (musicResponsiveListItemRenderer.playlistItemData != nil || musicResponsiveListItemRenderer.navigationEndpoint != nil) && (musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"){
|
||||||
|
// if let trackingParams = musicResponsiveListItemRenderer.trackingParams {
|
||||||
|
// item.clickTrackingParams = trackingParams
|
||||||
|
// }
|
||||||
|
// //设置预览图
|
||||||
|
// item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
||||||
|
// //设置一级标题与二级标题
|
||||||
|
// for (index, flexColumn) in (musicResponsiveListItemRenderer.flexColumns ?? []).enumerated() {
|
||||||
|
// if index == 0 {
|
||||||
|
// //一级标题
|
||||||
|
// item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||||
|
// }else {
|
||||||
|
// //二级标题
|
||||||
|
// item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// item.playListId = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||||
|
// //设置id和类型
|
||||||
|
// if musicResponsiveListItemRenderer.playlistItemData != nil {
|
||||||
|
// //是单曲
|
||||||
|
// item.itemType = .single
|
||||||
|
// item.videoId = musicResponsiveListItemRenderer.playlistItemData?.videoId
|
||||||
|
// }else {
|
||||||
|
// //是专辑列表/艺术家
|
||||||
|
// item.browseId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
// let pageType = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||||
|
// if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||||
|
// //判断细分
|
||||||
|
// if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||||
|
// item.artistId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
// //是艺术家
|
||||||
|
// item.itemType = .artist
|
||||||
|
// }else {
|
||||||
|
// //是列表/专辑
|
||||||
|
// item.itemType = .list
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||||
|
// resultList.previewItemViews.append(.init(item))
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//由于是最佳结果模块,所以没有query和params值
|
//由于是最佳结果模块,所以没有query和params值
|
||||||
resultList.query = nil
|
resultList.query = nil
|
||||||
@ -2285,6 +2324,13 @@ extension MP_NetWorkManager {
|
|||||||
return item.item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"
|
return item.item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//移除每一个被禁止的内容
|
||||||
|
resultListSections.forEach { list in
|
||||||
|
list.previewItemViews = list.previewItemViews.filter({ item in
|
||||||
|
return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
resultListSections = resultListSections.filter({$0.previewItemViews.count != 0})
|
resultListSections = resultListSections.filter({$0.previewItemViews.count != 0})
|
||||||
return resultListSections
|
return resultListSections
|
||||||
}
|
}
|
||||||
@ -2296,47 +2342,52 @@ extension MP_NetWorkManager {
|
|||||||
contents.forEach({ content in
|
contents.forEach({ content in
|
||||||
//专辑/列表/单曲视频/艺术家
|
//专辑/列表/单曲视频/艺术家
|
||||||
let item = MPPositive_BrowseItemModel()
|
let item = MPPositive_BrowseItemModel()
|
||||||
if (content.musicResponsiveListItemRenderer?.playlistItemData != nil || content.musicResponsiveListItemRenderer?.navigationEndpoint != nil) && (content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE") {
|
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
//设置内容块的封面
|
|
||||||
item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
|
||||||
//设置一级标题与二级标题
|
|
||||||
for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
|
|
||||||
if index == 0 {
|
|
||||||
//一级标题
|
|
||||||
item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
|
||||||
}else {
|
|
||||||
//二级标题
|
|
||||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
|
||||||
//设置id和类型
|
|
||||||
if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
|
|
||||||
//是单曲
|
|
||||||
item.itemType = .single
|
|
||||||
item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
|
|
||||||
}else {
|
|
||||||
//是专辑列表/艺术家
|
|
||||||
item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
|
||||||
let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
|
||||||
if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
|
||||||
//判断细分
|
|
||||||
if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
|
||||||
item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
|
||||||
//是艺术家
|
|
||||||
item.itemType = .artist
|
|
||||||
}else {
|
|
||||||
//是列表/专辑
|
|
||||||
item.itemType = .list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//添加内容块
|
//添加内容块
|
||||||
if item.itemType != nil {
|
if item.itemType != nil {
|
||||||
array.append(.init(item))
|
array.append(.init(item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if (content.musicResponsiveListItemRenderer?.playlistItemData != nil || content.musicResponsiveListItemRenderer?.navigationEndpoint != nil) && (content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE") {
|
||||||
|
// //设置内容块的封面
|
||||||
|
// item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
||||||
|
// //设置一级标题与二级标题
|
||||||
|
// for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
|
||||||
|
// if index == 0 {
|
||||||
|
// //一级标题
|
||||||
|
// item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||||
|
// }else {
|
||||||
|
// //二级标题
|
||||||
|
// item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||||
|
// //设置id和类型
|
||||||
|
// if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
|
||||||
|
// //是单曲
|
||||||
|
// item.itemType = .single
|
||||||
|
// item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
|
||||||
|
// }else {
|
||||||
|
// //是专辑列表/艺术家
|
||||||
|
// item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
// let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||||
|
// if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||||
|
// //判断细分
|
||||||
|
// if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||||
|
// item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
// //是艺术家
|
||||||
|
// item.itemType = .artist
|
||||||
|
// }else {
|
||||||
|
// //是列表/专辑
|
||||||
|
// item.itemType = .list
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //添加内容块
|
||||||
|
// if item.itemType != nil {
|
||||||
|
// array.append(.init(item))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
var continuation:String?
|
var continuation:String?
|
||||||
@ -2346,6 +2397,9 @@ extension MP_NetWorkManager {
|
|||||||
continuation = continuations.nextContinuationData?.continuation
|
continuation = continuations.nextContinuationData?.continuation
|
||||||
clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams
|
clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams
|
||||||
}
|
}
|
||||||
|
array = array.filter({ item in
|
||||||
|
return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false)
|
||||||
|
})
|
||||||
array = array.filter({$0.item.itemType != nil})
|
array = array.filter({$0.item.itemType != nil})
|
||||||
return (array, continuation, clickTrackingParams)
|
return (array, continuation, clickTrackingParams)
|
||||||
}
|
}
|
||||||
@ -2355,46 +2409,52 @@ extension MP_NetWorkManager {
|
|||||||
if let contents = musicShelfContinuation.contents {
|
if let contents = musicShelfContinuation.contents {
|
||||||
///解析内容块
|
///解析内容块
|
||||||
contents.forEach({ content in
|
contents.forEach({ content in
|
||||||
//专辑/列表/单曲视频/艺术家
|
if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
|
||||||
let item = MPPositive_BrowseItemModel()
|
|
||||||
//设置内容块的封面
|
|
||||||
item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
|
||||||
//设置一级标题与二级标题
|
|
||||||
for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
|
|
||||||
if index == 0 {
|
|
||||||
//一级标题
|
|
||||||
item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
|
||||||
}else {
|
|
||||||
//二级标题
|
|
||||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
|
||||||
//设置id和类型
|
|
||||||
if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
|
|
||||||
//是单曲
|
|
||||||
item.itemType = .single
|
|
||||||
item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
|
|
||||||
}else {
|
|
||||||
//是专辑列表/艺术家
|
|
||||||
item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
|
||||||
let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
|
||||||
if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
|
||||||
//判断细分
|
|
||||||
if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
|
||||||
item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
|
||||||
//是艺术家
|
|
||||||
item.itemType = .artist
|
|
||||||
}else {
|
|
||||||
//是列表/专辑
|
|
||||||
item.itemType = .list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//添加内容块
|
//添加内容块
|
||||||
if item.itemType != nil {
|
if item.itemType != nil {
|
||||||
array.append(.init(item))
|
array.append(.init(item))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// //专辑/列表/单曲视频/艺术家
|
||||||
|
// let item = MPPositive_BrowseItemModel()
|
||||||
|
// //设置内容块的封面
|
||||||
|
// item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
|
||||||
|
// //设置一级标题与二级标题
|
||||||
|
// for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
|
||||||
|
// if index == 0 {
|
||||||
|
// //一级标题
|
||||||
|
// item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||||
|
// }else {
|
||||||
|
// //二级标题
|
||||||
|
// item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||||
|
// //设置id和类型
|
||||||
|
// if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
|
||||||
|
// //是单曲
|
||||||
|
// item.itemType = .single
|
||||||
|
// item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
|
||||||
|
// }else {
|
||||||
|
// //是专辑列表/艺术家
|
||||||
|
// item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
// let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
|
||||||
|
// if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
|
||||||
|
// //判断细分
|
||||||
|
// if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||||
|
// item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
// //是艺术家
|
||||||
|
// item.itemType = .artist
|
||||||
|
// }else {
|
||||||
|
// //是列表/专辑
|
||||||
|
// item.itemType = .list
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //添加内容块
|
||||||
|
// if item.itemType != nil {
|
||||||
|
// array.append(.init(item))
|
||||||
|
// }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
var continuation:String?
|
var continuation:String?
|
||||||
@ -2404,6 +2464,9 @@ extension MP_NetWorkManager {
|
|||||||
continuation = continuations.nextContinuationData?.continuation
|
continuation = continuations.nextContinuationData?.continuation
|
||||||
clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams
|
clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams
|
||||||
}
|
}
|
||||||
|
array = array.filter({ item in
|
||||||
|
return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false)
|
||||||
|
})
|
||||||
array = array.filter({$0.item.itemType != nil})
|
array = array.filter({$0.item.itemType != nil})
|
||||||
return (array, continuation, clickTrackingParams)
|
return (array, continuation, clickTrackingParams)
|
||||||
}
|
}
|
||||||
@ -2412,7 +2475,6 @@ extension MP_NetWorkManager {
|
|||||||
private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel? {
|
private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel? {
|
||||||
//生成一个音乐模型接收数据
|
//生成一个音乐模型接收数据
|
||||||
let item = MPPositive_BrowseItemModel()
|
let item = MPPositive_BrowseItemModel()
|
||||||
|
|
||||||
//预览图片路径
|
//预览图片路径
|
||||||
item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
|
item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
|
||||||
if let clickTrackingParams = musicResponsiveListItemRenderer.trackingParams {
|
if let clickTrackingParams = musicResponsiveListItemRenderer.trackingParams {
|
||||||
@ -2424,7 +2486,7 @@ extension MP_NetWorkManager {
|
|||||||
item.itemType = .single
|
item.itemType = .single
|
||||||
item.videoId = playlistItemData.videoId
|
item.videoId = playlistItemData.videoId
|
||||||
//设置主副标题
|
//设置主副标题
|
||||||
guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty != true else {
|
guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty == false else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//主标题为第一位,同时VideoId,PlayListId,pageType都以第一个flexColumn为主
|
//主标题为第一位,同时VideoId,PlayListId,pageType都以第一个flexColumn为主
|
||||||
@ -2441,16 +2503,33 @@ extension MP_NetWorkManager {
|
|||||||
//设置副标题,通常为作者/专辑
|
//设置副标题,通常为作者/专辑
|
||||||
flexColumns.forEach { flexColumn in
|
flexColumns.forEach { flexColumn in
|
||||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||||
|
if let ari = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint != nil}) {
|
||||||
|
if ari.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST", let id = ari.navigationEndpoint?.browseEndpoint?.browseId {
|
||||||
|
//这个文本指向作者,获取作者ID
|
||||||
|
item.artistId = id
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//继续补完videoId,检索是否具备playListId,当playListId为空时,说明并没有成功补完,需要使用菜单结构补全内容
|
//继续补完videoId,检索是否具备playListId,当playListId为空时,说明并没有成功补完,需要使用菜单结构补全内容
|
||||||
guard (item.playListId ?? "").isEmpty == true else {
|
guard (item.playListId ?? "").isEmpty == true else {
|
||||||
//不为空,说明需要的数据已经补完了
|
//判断是否禁止的作者或者禁止的音乐
|
||||||
|
if (trashSingerIds.contains(item.artistId ?? "")) == false && (trashVideoIds.contains(item.videoId ?? "")) == false {
|
||||||
return item
|
return item
|
||||||
|
}else {
|
||||||
|
//禁止内容
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//未补完,继续
|
//未补完,继续
|
||||||
if let watchItem = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first(where: {$0.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint != nil}) {
|
if let watchItem = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first(where: {$0.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint != nil}) {
|
||||||
item.playListId = watchItem.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
item.playListId = watchItem.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
|
||||||
|
//判断是否禁止的作者或者禁止的音乐
|
||||||
|
if (trashSingerIds.contains(item.artistId ?? "")) == false && (trashVideoIds.contains(item.videoId ?? "")) == false {
|
||||||
return item
|
return item
|
||||||
|
}else {
|
||||||
|
//禁止内容
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
//补完失败
|
//补完失败
|
||||||
return nil
|
return nil
|
||||||
@ -2470,6 +2549,12 @@ extension MP_NetWorkManager {
|
|||||||
//设置副标题,通常为作者/专辑
|
//设置副标题,通常为作者/专辑
|
||||||
flexColumns.forEach { flexColumn in
|
flexColumns.forEach { flexColumn in
|
||||||
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
|
||||||
|
if let ari = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) {
|
||||||
|
//这个文本指向作者,获取作者ID
|
||||||
|
if let id = ari.navigationEndpoint?.browseEndpoint?.browseId {
|
||||||
|
item.artistId = id
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//设置预览Id
|
//设置预览Id
|
||||||
guard let browseEndpoint = navigationEndpoint.browseEndpoint else {
|
guard let browseEndpoint = navigationEndpoint.browseEndpoint else {
|
||||||
@ -2490,6 +2575,8 @@ extension MP_NetWorkManager {
|
|||||||
}else if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
}else if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||||
//艺术家
|
//艺术家
|
||||||
item.itemType = .artist
|
item.itemType = .artist
|
||||||
|
item.artistId = item.browseId
|
||||||
|
if (trashSingerIds.contains(item.artistId ?? "")) == false {
|
||||||
return item
|
return item
|
||||||
}else {
|
}else {
|
||||||
return nil
|
return nil
|
||||||
@ -2497,9 +2584,12 @@ extension MP_NetWorkManager {
|
|||||||
}else {
|
}else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
}else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//解析musicResponsiveListItemRenderer(三组件结构)
|
//解析musicResponsiveListItemRenderer(三组件结构)
|
||||||
private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel {
|
private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel? {
|
||||||
//生成一个音乐模型接收数据
|
//生成一个音乐模型接收数据
|
||||||
let item = MPPositive_BrowseItemModel()
|
let item = MPPositive_BrowseItemModel()
|
||||||
//封面路径
|
//封面路径
|
||||||
@ -2508,6 +2598,10 @@ extension MP_NetWorkManager {
|
|||||||
item.title = musicTwoRowItemRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
item.title = musicTwoRowItemRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||||
//副标题
|
//副标题
|
||||||
item.subtitle = musicTwoRowItemRenderer.subtitle?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
item.subtitle = musicTwoRowItemRenderer.subtitle?.runs?.reduce("", { $0 + ($1.text ?? "")})
|
||||||
|
//获取这个预览项的作者(有的话)
|
||||||
|
if let art = musicTwoRowItemRenderer.subtitle?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) {
|
||||||
|
item.artistId = art.navigationEndpoint?.browseEndpoint?.browseId
|
||||||
|
}
|
||||||
if let clickTrackingParams = musicTwoRowItemRenderer.navigationEndpoint?.clickTrackingParams {
|
if let clickTrackingParams = musicTwoRowItemRenderer.navigationEndpoint?.clickTrackingParams {
|
||||||
item.clickTrackingParams = clickTrackingParams
|
item.clickTrackingParams = clickTrackingParams
|
||||||
}
|
}
|
||||||
@ -2533,7 +2627,11 @@ extension MP_NetWorkManager {
|
|||||||
item.browseId = browseEndpoint.browseId
|
item.browseId = browseEndpoint.browseId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (trashSingerIds.contains(item.artistId ?? "")) == false {
|
||||||
return item
|
return item
|
||||||
|
}else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - 解析资源加密
|
//MARK: - 解析资源加密
|
||||||
|
|||||||
@ -659,6 +659,8 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
|||||||
let text:String?
|
let text:String?
|
||||||
///文本导航
|
///文本导航
|
||||||
let navigationEndpoint:NavigationEndpoint?
|
let navigationEndpoint:NavigationEndpoint?
|
||||||
|
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case text = "text"
|
case text = "text"
|
||||||
case navigationEndpoint = "navigationEndpoint"
|
case navigationEndpoint = "navigationEndpoint"
|
||||||
@ -674,14 +676,18 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
|||||||
let clickTrackingParams:String?
|
let clickTrackingParams:String?
|
||||||
///资源特化
|
///资源特化
|
||||||
let watchEndpoint:WatchEndpoint?
|
let watchEndpoint:WatchEndpoint?
|
||||||
|
///导向其他
|
||||||
|
let browseEndpoint:BrowseEndpoint?
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case clickTrackingParams = "clickTrackingParams"
|
case clickTrackingParams = "clickTrackingParams"
|
||||||
case watchEndpoint = "watchEndpoint"
|
case watchEndpoint = "watchEndpoint"
|
||||||
|
case browseEndpoint = "browseEndpoint"
|
||||||
}
|
}
|
||||||
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)
|
||||||
clickTrackingParams = try values.decodeIfPresent(String.self, forKey: .clickTrackingParams)
|
clickTrackingParams = try values.decodeIfPresent(String.self, forKey: .clickTrackingParams)
|
||||||
watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint)
|
watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint)
|
||||||
|
browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint)
|
||||||
}
|
}
|
||||||
//导向播放
|
//导向播放
|
||||||
struct WatchEndpoint: Codable {
|
struct WatchEndpoint: Codable {
|
||||||
@ -724,6 +730,41 @@ struct RootMusicResponsiveListItemRenderer: Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//导向其他
|
||||||
|
struct BrowseEndpoint: Codable {
|
||||||
|
let browseId:String?
|
||||||
|
let browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case browseId = "browseId"
|
||||||
|
case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
browseId = try values.decodeIfPresent(String.self, forKey: .browseId)
|
||||||
|
browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs)
|
||||||
|
}
|
||||||
|
struct BrowseEndpointContextSupportedConfigs: Codable {
|
||||||
|
let browseEndpointContextMusicConfig:BrowseEndpointContextMusicConfig?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case browseEndpointContextMusicConfig = "browseEndpointContextMusicConfig"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig)
|
||||||
|
}
|
||||||
|
struct BrowseEndpointContextMusicConfig: Codable {
|
||||||
|
let pageType:String?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case pageType = "pageType"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
pageType = try values.decodeIfPresent(String.self, forKey: .pageType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -984,13 +1025,59 @@ struct RootMusicTwoRowItemRenderer: Codable {
|
|||||||
}
|
}
|
||||||
struct Run: Codable {
|
struct Run: Codable {
|
||||||
let text:String?
|
let text:String?
|
||||||
|
let navigationEndpoint:NavigationEndpoint?
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case text = "text"
|
case text = "text"
|
||||||
|
case navigationEndpoint = "navigationEndpoint"
|
||||||
}
|
}
|
||||||
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)
|
||||||
text = try values.decodeIfPresent(String.self, forKey: .text)
|
text = try values.decodeIfPresent(String.self, forKey: .text)
|
||||||
|
navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint)
|
||||||
|
}
|
||||||
|
struct NavigationEndpoint: 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 browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case browseId = "browseId"
|
||||||
|
case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
browseId = try values.decodeIfPresent(String.self, forKey: .browseId)
|
||||||
|
browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs)
|
||||||
|
}
|
||||||
|
struct BrowseEndpointContextSupportedConfigs: Codable {
|
||||||
|
let browseEndpointContextMusicConfig:BrowseEndpointContextMusicConfig?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case browseEndpointContextMusicConfig = "browseEndpointContextMusicConfig"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig)
|
||||||
|
}
|
||||||
|
struct BrowseEndpointContextMusicConfig: Codable {
|
||||||
|
let pageType:String?
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case pageType = "pageType"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
pageType = try values.decodeIfPresent(String.self, forKey: .pageType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// MPPositive_TrashListModel.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/7/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
///禁用名单模型
|
||||||
|
class MPPositive_TrashListModel: NSObject {
|
||||||
|
///禁用状态
|
||||||
|
var statu:Bool = false
|
||||||
|
///禁用歌手
|
||||||
|
var name:String = ""
|
||||||
|
///禁用关键词组
|
||||||
|
var keyWords:[String] = []
|
||||||
|
///禁用歌手ID
|
||||||
|
var singerID:String = ""
|
||||||
|
///禁用歌曲ID组
|
||||||
|
var videoIDs:[String] = []
|
||||||
|
|
||||||
|
init(_ dict:[String:Any]) {
|
||||||
|
super.init()
|
||||||
|
if let statu = dict["statu"] as? Bool {
|
||||||
|
self.statu = statu
|
||||||
|
}
|
||||||
|
if let name = dict["name"] as? String {
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
if let keyWords = dict["keyWords"] as? [String] {
|
||||||
|
self.keyWords = keyWords
|
||||||
|
}
|
||||||
|
if let singerID = dict["singerID"] as? String{
|
||||||
|
self.singerID = singerID
|
||||||
|
}
|
||||||
|
if let videoIDs = dict["videoIDs"] as? [String]{
|
||||||
|
self.videoIDs = videoIDs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,8 +15,8 @@ class MPPositive_RecommendLoadViewModel: NSObject {
|
|||||||
[weak self] in
|
[weak self] in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
//得到了搜索结果
|
//得到了搜索结果
|
||||||
if resultReloadBlock != nil {
|
if let block = resultReloadBlock {
|
||||||
resultReloadBlock!()
|
block()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,8 @@ class MPPositive_SearchResultsLoadViewModel: NSObject {
|
|||||||
[weak self] in
|
[weak self] in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
//得到了搜索结果
|
//得到了搜索结果
|
||||||
if resultReloadBlock != nil {
|
if let block = resultReloadBlock {
|
||||||
resultReloadBlock!()
|
block()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +43,9 @@ class MPPositive_SearchResultsLoadViewModel: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
MP_NetWorkManager.shared.requestSearchPreviewResults(text) { [weak self] results in
|
MP_NetWorkManager.shared.requestSearchPreviewResults(text) { [weak self] results in
|
||||||
self?.sectionLists = results
|
guard let self = self else {return}
|
||||||
|
MP_HUD.hideNow()
|
||||||
|
sectionLists = results
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,29 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
|||||||
btn.addTarget(self, action: #selector(menuRightClick(_ :)), for: .touchUpInside)
|
btn.addTarget(self, action: #selector(menuRightClick(_ :)), for: .touchUpInside)
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
//ViP按钮
|
||||||
|
private lazy var vipImageView:UIImageView = {
|
||||||
|
let imageView:UIImageView = UIImageView(image: .init(named: "VIP'logo"))
|
||||||
|
imageView.isUserInteractionEnabled = true
|
||||||
|
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(vipIAPClick(_ :))))
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
//斜向标题Label
|
||||||
|
private lazy var musicLaxLabel:UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "MusicLax"
|
||||||
|
// Create a bold italic font
|
||||||
|
if let boldItalicFontDescriptor = UIFont.systemFont(ofSize: 20*width, weight: .bold).fontDescriptor.withSymbolicTraits([.traitBold, .traitItalic]) {
|
||||||
|
let boldItalicFont = UIFont(descriptor: boldItalicFontDescriptor, size: 20*width)
|
||||||
|
label.font = boldItalicFont
|
||||||
|
} else {
|
||||||
|
label.font = UIFont.boldSystemFont(ofSize: 20*width)
|
||||||
|
}
|
||||||
|
label.textColor = .white
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
//搜索栏
|
||||||
|
private lazy var searchView = createSearchView()
|
||||||
//tableView
|
//tableView
|
||||||
private lazy var tableView:UITableView = {
|
private lazy var tableView:UITableView = {
|
||||||
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
|
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
|
||||||
@ -63,6 +86,7 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
|||||||
requestTrackingAuthorization { idfa in
|
requestTrackingAuthorization { idfa in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MP_IAPManager.shared.systemRestorePurchases()
|
||||||
setTitle("")
|
setTitle("")
|
||||||
confirgue()
|
confirgue()
|
||||||
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count == 0 {
|
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count == 0 {
|
||||||
@ -263,31 +287,55 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
|||||||
//MARK: - UI生成与配置
|
//MARK: - UI生成与配置
|
||||||
//配置
|
//配置
|
||||||
private func confirgue() {
|
private func confirgue() {
|
||||||
let searchView = createSearchView()
|
navView.frame = .init(x: 0, y: statusBarHeight, width: screen_Width, height: 90*width)
|
||||||
|
if memuBtn.superview == nil {
|
||||||
|
navView.addSubview(memuBtn)
|
||||||
|
memuBtn.snp.makeConstraints { make in
|
||||||
|
make.right.equalToSuperview().offset(-16*width)
|
||||||
|
make.top.equalToSuperview().offset(16*width)
|
||||||
|
make.width.height.equalTo(24*width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if vipImageView.superview == nil {
|
||||||
|
navView.addSubview(vipImageView)
|
||||||
|
vipImageView.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalTo(memuBtn.snp.centerY)
|
||||||
|
make.right.equalTo(memuBtn.snp.left).offset(-10*width)
|
||||||
|
make.width.equalTo(51*width)
|
||||||
|
make.height.equalTo(32*width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if musicLaxLabel.superview == nil {
|
||||||
|
navView.addSubview(musicLaxLabel)
|
||||||
|
musicLaxLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(16*width)
|
||||||
|
make.centerY.equalTo(memuBtn)
|
||||||
|
}
|
||||||
|
musicLaxLabel.setGradientTextColor(gradientTextColors)
|
||||||
|
}
|
||||||
|
if searchView.superview == nil {
|
||||||
navView.addSubview(searchView)
|
navView.addSubview(searchView)
|
||||||
searchView.snp.makeConstraints { make in
|
searchView.snp.makeConstraints { make in
|
||||||
make.width.equalTo(300*width)
|
make.width.equalTo(340*width)
|
||||||
make.height.equalTo(32*width)
|
make.height.equalTo(32*width)
|
||||||
make.left.equalToSuperview().offset(18*width)
|
make.centerX.equalToSuperview()
|
||||||
make.centerY.equalToSuperview()
|
make.bottom.equalToSuperview().offset(-9*width)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if bgImageView.superview == nil {
|
||||||
view.addSubview(bgImageView)
|
view.addSubview(bgImageView)
|
||||||
bgImageView.snp.makeConstraints { make in
|
bgImageView.snp.makeConstraints { make in
|
||||||
make.top.right.left.equalToSuperview()
|
make.top.right.left.equalToSuperview()
|
||||||
make.height.equalTo(981*width)
|
make.height.equalTo(981*width)
|
||||||
}
|
}
|
||||||
view.addSubview(tableView)
|
|
||||||
navView.addSubview(memuBtn)
|
|
||||||
memuBtn.snp.makeConstraints { make in
|
|
||||||
make.right.equalToSuperview().offset(-16*width)
|
|
||||||
make.centerY.equalToSuperview()
|
|
||||||
make.width.height.equalTo(24*width)
|
|
||||||
}
|
}
|
||||||
|
if tableView.superview == nil {
|
||||||
|
view.addSubview(tableView)
|
||||||
tableView.snp.makeConstraints { make in
|
tableView.snp.makeConstraints { make in
|
||||||
make.top.equalTo(navView.snp.bottom).offset(32*width)
|
make.top.equalTo(navView.snp.bottom).offset(15*width)
|
||||||
make.left.right.bottom.equalToSuperview()
|
make.left.right.bottom.equalToSuperview()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//MARK: - 页面刷新
|
//MARK: - 页面刷新
|
||||||
//页面刷新
|
//页面刷新
|
||||||
@ -315,6 +363,34 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
|||||||
setVC.cleanSide = true
|
setVC.cleanSide = true
|
||||||
navigationController?.pushViewController(setVC, animated: true)
|
navigationController?.pushViewController(setVC, animated: true)
|
||||||
}
|
}
|
||||||
|
//弹出VIP页面
|
||||||
|
@objc private func vipIAPClick(_ sender:UITapGestureRecognizer) {
|
||||||
|
view.endEditing(true)
|
||||||
|
let iapVC = MP_IAPViewController()
|
||||||
|
iapVC.isType = true
|
||||||
|
iapVC.privacyBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) {
|
||||||
|
[weak self] in
|
||||||
|
let privacyVC = MPSideA_PrivacyViewController()
|
||||||
|
self?.navigationController?.pushViewController(privacyVC, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iapVC.termsBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) {
|
||||||
|
[weak self] in
|
||||||
|
let serviceVC = MPSideA_ServiceViewController()
|
||||||
|
self?.navigationController?.pushViewController(serviceVC, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iapVC.modalPresentationStyle = .fullScreen
|
||||||
|
|
||||||
|
present(iapVC, animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//MARK: - tableView
|
//MARK: - tableView
|
||||||
extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDelegate {
|
extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDelegate {
|
||||||
|
|||||||
@ -207,12 +207,14 @@ class MPPositive_ListShowViewController: MPPositive_BaseViewController, UIViewCo
|
|||||||
make.left.equalToSuperview().offset(18*width)
|
make.left.equalToSuperview().offset(18*width)
|
||||||
make.height.equalTo(32*width)
|
make.height.equalTo(32*width)
|
||||||
make.bottom.equalTo(blurView.snp.bottom).offset(-29*width)
|
make.bottom.equalTo(blurView.snp.bottom).offset(-29*width)
|
||||||
|
// make.width.equalTo(90*width)
|
||||||
}
|
}
|
||||||
view.addSubview(shuffleBtn)
|
view.addSubview(shuffleBtn)
|
||||||
shuffleBtn.snp.makeConstraints { make in
|
shuffleBtn.snp.makeConstraints { make in
|
||||||
make.left.equalTo(playAllBtn.snp.right).offset(18*width)
|
make.left.equalTo(playAllBtn.snp.right).offset(18*width)
|
||||||
make.height.equalTo(32*width)
|
make.height.equalTo(32*width)
|
||||||
make.centerY.equalTo(playAllBtn)
|
make.centerY.equalTo(playAllBtn)
|
||||||
|
// make.width.equalTo(90*width)
|
||||||
}
|
}
|
||||||
view.addSubview(collectionListBtn)
|
view.addSubview(collectionListBtn)
|
||||||
collectionListBtn.snp.makeConstraints { make in
|
collectionListBtn.snp.makeConstraints { make in
|
||||||
|
|||||||
@ -34,11 +34,10 @@ class MPPositive_SearchResultsShowView: UIView {
|
|||||||
}
|
}
|
||||||
//搜索成功了
|
//搜索成功了
|
||||||
MP_AnalyticsManager.shared.search_result_pvAction()
|
MP_AnalyticsManager.shared.search_result_pvAction()
|
||||||
loadModel.resultReloadBlock = {
|
loadModel?.resultReloadBlock = {
|
||||||
[weak self] in
|
[weak self] in
|
||||||
//刷新分页控制器
|
//刷新分页控制器
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
MP_HUD.hideNow()
|
|
||||||
isHidden = false
|
isHidden = false
|
||||||
MP_AnalyticsManager.shared.search_resultsuccess_actionAction()
|
MP_AnalyticsManager.shared.search_resultsuccess_actionAction()
|
||||||
if let loadModel = loadModel, let titles = loadModel.sectionLists?.compactMap({$0.title ?? ""}) {
|
if let loadModel = loadModel, let titles = loadModel.sectionLists?.compactMap({$0.title ?? ""}) {
|
||||||
|
|||||||
@ -71,7 +71,37 @@ class MPSideA_HomeViewController: MPSideA_BaseViewController {
|
|||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// //当音乐播放器状态改变时
|
@IBAction func menueClick(_ sender: UIButton) {
|
||||||
|
let setVC = MPSideA_SettingViewController()
|
||||||
|
setVC.cleanSide = false
|
||||||
|
navigationController?.pushViewController(setVC, animated: true)
|
||||||
|
}
|
||||||
|
@IBAction func vipClick(_ sender: UIButton) {
|
||||||
|
view.endEditing(true)
|
||||||
|
let iapVC = MP_IAPViewController()
|
||||||
|
iapVC.isType = false
|
||||||
|
iapVC.privacyBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) {
|
||||||
|
[weak self] in
|
||||||
|
let privacyVC = MPSideA_PrivacyViewController()
|
||||||
|
self?.navigationController?.pushViewController(privacyVC, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iapVC.termsBlock = {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) {
|
||||||
|
[weak self] in
|
||||||
|
let serviceVC = MPSideA_ServiceViewController()
|
||||||
|
self?.navigationController?.pushViewController(serviceVC, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iapVC.modalPresentationStyle = .fullScreen
|
||||||
|
present(iapVC, animated: true)
|
||||||
|
}
|
||||||
|
// //当音乐播放器状态改变时
|
||||||
// @objc private func switchPlayerStateAction(_ sender:Notification) {
|
// @objc private func switchPlayerStateAction(_ sender:Notification) {
|
||||||
// //刷新页面内容
|
// //刷新页面内容
|
||||||
// tableView.reloadData()
|
// tableView.reloadData()
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MPSideA_HomeViewController" customModule="MusicPlayer" customModuleProvider="target">
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MPSideA_HomeViewController" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="tableView" destination="mLK-Jd-vck" id="5mS-bI-6RR"/>
|
<outlet property="tableView" destination="mLK-Jd-vck" id="5mS-bI-6RR"/>
|
||||||
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||||
@ -31,26 +31,100 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</imageView>
|
</imageView>
|
||||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="mLK-Jd-vck">
|
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="mLK-Jd-vck">
|
||||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
<rect key="frame" x="0.0" y="66" width="375" height="601"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</tableView>
|
</tableView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="MusicLax" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QKh-4L-ObN">
|
||||||
|
<rect key="frame" x="16" y="28" width="82.5" height="24"/>
|
||||||
|
<fontDescription key="fontDescription" type="italicSystem" pointSize="20"/>
|
||||||
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hKx-VM-y2a">
|
||||||
|
<rect key="frame" x="274" y="24" width="51" height="32"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="32" id="Mzp-RN-W5s">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="width" constant="51" id="PjR-H8-dch">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" backgroundImage="VIP'logo"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="vipClick:" destination="-1" eventType="touchUpInside" id="rpg-qp-peI"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="U4v-5X-SBo">
|
||||||
|
<rect key="frame" x="335" y="28" width="24" height="24"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="24" id="PPW-Dr-YGv">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstAttribute="height" constant="24" id="dnd-Vm-NoY">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||||
|
<state key="normal" backgroundImage="Home_Menu'logo"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="menueClick:" destination="-1" eventType="touchUpInside" id="R4F-Er-Dfk"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="Cpu-MK-rc5" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="7ZI-Y1-iuM"/>
|
<constraint firstItem="Cpu-MK-rc5" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="7ZI-Y1-iuM"/>
|
||||||
|
<constraint firstItem="QKh-4L-ObN" firstAttribute="centerY" secondItem="U4v-5X-SBo" secondAttribute="centerY" id="A36-wN-4KX"/>
|
||||||
<constraint firstItem="Cpu-MK-rc5" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="H3F-G4-wxZ"/>
|
<constraint firstItem="Cpu-MK-rc5" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="H3F-G4-wxZ"/>
|
||||||
|
<constraint firstItem="U4v-5X-SBo" firstAttribute="leading" secondItem="hKx-VM-y2a" secondAttribute="trailing" constant="10" id="IG2-gD-S8V">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="mLK-Jd-vck" secondAttribute="trailing" id="Jdt-xA-aO4"/>
|
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="mLK-Jd-vck" secondAttribute="trailing" id="Jdt-xA-aO4"/>
|
||||||
<constraint firstItem="mLK-Jd-vck" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" id="Pxg-kq-xiW"/>
|
<constraint firstItem="mLK-Jd-vck" firstAttribute="top" secondItem="hKx-VM-y2a" secondAttribute="bottom" constant="10" id="MDV-kE-cgK">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
|
<constraint firstItem="QKh-4L-ObN" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="16" id="TWX-Lm-1vU">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="Cpu-MK-rc5" secondAttribute="trailing" id="VKw-AA-xMC"/>
|
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="Cpu-MK-rc5" secondAttribute="trailing" id="VKw-AA-xMC"/>
|
||||||
|
<constraint firstItem="hKx-VM-y2a" firstAttribute="centerY" secondItem="U4v-5X-SBo" secondAttribute="centerY" id="cV2-aW-a5z"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="mLK-Jd-vck" secondAttribute="bottom" id="h8k-6P-60E"/>
|
<constraint firstAttribute="bottom" secondItem="mLK-Jd-vck" secondAttribute="bottom" id="h8k-6P-60E"/>
|
||||||
|
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="U4v-5X-SBo" secondAttribute="trailing" constant="16" id="hki-di-j4U">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
<constraint firstItem="mLK-Jd-vck" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="nPR-gi-zV7"/>
|
<constraint firstItem="mLK-Jd-vck" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="nPR-gi-zV7"/>
|
||||||
|
<constraint firstItem="U4v-5X-SBo" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="8" id="ufo-IS-9AB">
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</constraint>
|
||||||
</constraints>
|
</constraints>
|
||||||
<point key="canvasLocation" x="130.40000000000001" y="-12.143928035982009"/>
|
<point key="canvasLocation" x="130.40000000000001" y="-12.143928035982009"/>
|
||||||
</view>
|
</view>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="Home'bg" width="375" height="900.5"/>
|
<image name="Home'bg" width="375" height="900.5"/>
|
||||||
|
<image name="Home_Menu'logo" width="24" height="24"/>
|
||||||
|
<image name="VIP'logo" width="51" height="32"/>
|
||||||
<systemColor name="systemBackgroundColor">
|
<systemColor name="systemBackgroundColor">
|
||||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
|
|||||||