数据结构改动
This commit is contained in:
parent
57a5482045
commit
4621f95204
@ -56,6 +56,8 @@
|
||||
CBB9F9DF2BEDDCC5008338DE /* MP_PlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB9F9DE2BEDDCC5008338DE /* MP_PlayerManager.swift */; };
|
||||
CBBA6A222BFF12030047ADF8 /* MP_AVURLAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBA6A212BFF12030047ADF8 /* MP_AVURLAsset.swift */; };
|
||||
CBBA6A242BFF160C0047ADF8 /* MP_CacheManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBA6A232BFF160C0047ADF8 /* MP_CacheManager.swift */; };
|
||||
CBBFA0A62C0706DE00769999 /* MPPositive_MoreSongOperationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBFA0A52C0706DE00769999 /* MPPositive_MoreSongOperationsViewController.swift */; };
|
||||
CBBFA0A82C070BD900769999 /* MPPositive_MoreOperationDownLoadTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBFA0A72C070BD900769999 /* MPPositive_MoreOperationDownLoadTableViewCell.swift */; };
|
||||
CBBFA9182BBA83BA00057FD5 /* MP_CoreDataHandlerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBFA9172BBA83BA00057FD5 /* MP_CoreDataHandlerManager.swift */; };
|
||||
CBBFA91A2BBA846600057FD5 /* CoreDataDelegete.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBFA9192BBA846600057FD5 /* CoreDataDelegete.swift */; };
|
||||
CBBFA91E2BBA9B5C00057FD5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBFA91D2BBA9B5C00057FD5 /* Notification.swift */; };
|
||||
@ -260,6 +262,8 @@
|
||||
CBB9F9DE2BEDDCC5008338DE /* MP_PlayerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_PlayerManager.swift; sourceTree = "<group>"; };
|
||||
CBBA6A212BFF12030047ADF8 /* MP_AVURLAsset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_AVURLAsset.swift; sourceTree = "<group>"; };
|
||||
CBBA6A232BFF160C0047ADF8 /* MP_CacheManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_CacheManager.swift; sourceTree = "<group>"; };
|
||||
CBBFA0A52C0706DE00769999 /* MPPositive_MoreSongOperationsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_MoreSongOperationsViewController.swift; sourceTree = "<group>"; };
|
||||
CBBFA0A72C070BD900769999 /* MPPositive_MoreOperationDownLoadTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_MoreOperationDownLoadTableViewCell.swift; sourceTree = "<group>"; };
|
||||
CBBFA9172BBA83BA00057FD5 /* MP_CoreDataHandlerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_CoreDataHandlerManager.swift; sourceTree = "<group>"; };
|
||||
CBBFA9192BBA846600057FD5 /* CoreDataDelegete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataDelegete.swift; sourceTree = "<group>"; };
|
||||
CBBFA91D2BBA9B5C00057FD5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||
@ -872,6 +876,7 @@
|
||||
CB0918902BD255EA006D2B39 /* MPPositive_NavigationController.swift */,
|
||||
CB0918962BD25D8C006D2B39 /* MPPositive_TabBarController.swift */,
|
||||
CBCC234E2BEE57AC004D7A57 /* MPPositive_PresentationController.swift */,
|
||||
CBBFA0A52C0706DE00769999 /* MPPositive_MoreSongOperationsViewController.swift */,
|
||||
);
|
||||
path = "Base(基类,导航栏,标签栏)";
|
||||
sourceTree = "<group>";
|
||||
@ -926,6 +931,7 @@
|
||||
CB09189A2BD25F50006D2B39 /* MPPositive_CustomTabBarView.swift */,
|
||||
CB09189C2BD25F63006D2B39 /* MPPositive_CustomTabBarItem.swift */,
|
||||
CB0918A42BD26E16006D2B39 /* MPPositive_BottomShowView.swift */,
|
||||
CBBFA0A72C070BD900769999 /* MPPositive_MoreOperationDownLoadTableViewCell.swift */,
|
||||
);
|
||||
path = Base;
|
||||
sourceTree = "<group>";
|
||||
@ -1261,6 +1267,7 @@
|
||||
CBCB500A2BD11402009760B3 /* MPSideA_CustomTabBar.swift in Sources */,
|
||||
CB2416912C05D36F007877F7 /* MPPositive_DownloadViewModel.swift in Sources */,
|
||||
CBCAFB692BB3CAC400BC6520 /* MP_Lunch_ProgressView.swift in Sources */,
|
||||
CBBFA0A62C0706DE00769999 /* MPPositive_MoreSongOperationsViewController.swift in Sources */,
|
||||
CBD6F2182BF4A29B00343A4A /* MPPositive_ArtistViewModel.swift in Sources */,
|
||||
CBCB50102BD11402009760B3 /* MPSideA_SettingTableViewCell.swift in Sources */,
|
||||
CBCAFB5D2BB3C52100BC6520 /* HexColor.swift in Sources */,
|
||||
@ -1361,6 +1368,7 @@
|
||||
CBFECE3F2BF1176B00E07DC4 /* MPPositive_JsonSearchResults.swift in Sources */,
|
||||
CBC6874B2BC2B0710023ECA6 /* String.swift in Sources */,
|
||||
CBD3135F2BD642D90015D227 /* MPPositive_HomeListFourthCollectionViewCell.swift in Sources */,
|
||||
CBBFA0A82C070BD900769999 /* MPPositive_MoreOperationDownLoadTableViewCell.swift in Sources */,
|
||||
CBBA6A242BFF160C0047ADF8 /* MP_CacheManager.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
BIN
MusicPlayer/Assets.xcassets/Positive/More/Add Download.imageset/COCO_Line_Arrow_-_Bottom_1@2x.png
vendored
Normal file
BIN
MusicPlayer/Assets.xcassets/Positive/More/Add Download.imageset/COCO_Line_Arrow_-_Bottom_1@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
MusicPlayer/Assets.xcassets/Positive/More/Add Download.imageset/COCO_Line_Arrow_-_Bottom_1@3x.png
vendored
Normal file
BIN
MusicPlayer/Assets.xcassets/Positive/More/Add Download.imageset/COCO_Line_Arrow_-_Bottom_1@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
22
MusicPlayer/Assets.xcassets/Positive/More/Add Download.imageset/Contents.json
vendored
Normal file
22
MusicPlayer/Assets.xcassets/Positive/More/Add Download.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "COCO_Line_Arrow_-_Bottom_1@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "COCO_Line_Arrow_-_Bottom_1@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
6
MusicPlayer/Assets.xcassets/Positive/More/Contents.json
Normal file
6
MusicPlayer/Assets.xcassets/Positive/More/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
MusicPlayer/Assets.xcassets/Positive/More/Remove Download.imageset/COCO_Line_Arrow_-_Bottom_2@2x.png
vendored
Normal file
BIN
MusicPlayer/Assets.xcassets/Positive/More/Remove Download.imageset/COCO_Line_Arrow_-_Bottom_2@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
MusicPlayer/Assets.xcassets/Positive/More/Remove Download.imageset/COCO_Line_Arrow_-_Bottom_2@3x.png
vendored
Normal file
BIN
MusicPlayer/Assets.xcassets/Positive/More/Remove Download.imageset/COCO_Line_Arrow_-_Bottom_2@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
22
MusicPlayer/Assets.xcassets/Positive/More/Remove Download.imageset/Contents.json
vendored
Normal file
22
MusicPlayer/Assets.xcassets/Positive/More/Remove Download.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "COCO_Line_Arrow_-_Bottom_2@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "COCO_Line_Arrow_-_Bottom_2@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -310,30 +310,30 @@ class MP_ResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, URLSes
|
||||
// MARK: URLSession
|
||||
///网络请求响应体内容
|
||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||
guard response.mimeType?.contains("video") == true else {
|
||||
print("\(playItem?.title ?? "")网络地址不可用,响应类型是\(response.mimeType ?? "")")
|
||||
//重新请求数据
|
||||
MP_NetWorkManager.shared.requestPlayer(playItem?.videoId ?? "", playlistId: "") {[weak self] resourceUrls, coverUrls in
|
||||
//只需要重新配置第一条网络资源地址
|
||||
guard let self = self else {return}
|
||||
print("\(playItem?.title ?? "")重新加载一次")
|
||||
let url = URL(string: resourceUrls.0.first ?? "")!
|
||||
playItem?.url = url
|
||||
if mediaData == nil {
|
||||
startDataRequest(with: url)
|
||||
}else {
|
||||
continuationDataRequest(with: url, count: Int64(mediaData!.count))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
completionHandler(Foundation.URLSession.ResponseDisposition.allow)
|
||||
if mediaData == nil {
|
||||
mediaData = Data()
|
||||
mediaDataBlocks = []
|
||||
}
|
||||
self.response = response
|
||||
processPendingRequests()
|
||||
// guard response.mimeType?.contains("video") == true else {
|
||||
// print("\(playItem?.title ?? "")网络地址不可用,响应类型是\(response.mimeType ?? "")")
|
||||
// //重新请求数据
|
||||
// MP_NetWorkManager.shared.requestPlayer(playItem?.videoId ?? "", playlistId: "") {[weak self] resourceUrls, coverUrls in
|
||||
// //只需要重新配置第一条网络资源地址
|
||||
// guard let self = self else {return}
|
||||
// print("\(playItem?.title ?? "")重新加载一次")
|
||||
// let url = URL(string: resourceUrls.0.first ?? "")!
|
||||
// playItem?.url = url
|
||||
// if mediaData == nil {
|
||||
// startDataRequest(with: url)
|
||||
// }else {
|
||||
// continuationDataRequest(with: url, count: Int64(mediaData!.count))
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
// completionHandler(Foundation.URLSession.ResponseDisposition.allow)
|
||||
// if mediaData == nil {
|
||||
// mediaData = Data()
|
||||
// mediaDataBlocks = []
|
||||
// }
|
||||
// self.response = response
|
||||
// processPendingRequests()
|
||||
}
|
||||
///网络请求数据更新
|
||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
|
||||
@ -81,6 +81,22 @@ class DownloadManager: NSObject {
|
||||
session.cancel(key)
|
||||
}
|
||||
}
|
||||
//删除下载文件
|
||||
func deleteFileDocuments(_ videoId:String, completion:@escaping((String) -> Void)) {
|
||||
let downloadsURL = DocumentsURL.appendingPathComponent("Downloads")
|
||||
let fileURL = downloadsURL.appendingPathComponent("\(videoId).mp4")
|
||||
if FileManager.default.fileExists(atPath: fileURL.absoluteString) {
|
||||
do{
|
||||
try FileManager.default.removeItem(at: fileURL)
|
||||
//文件删除成功
|
||||
completion(videoId)
|
||||
}catch{
|
||||
print("删除文件时发生错误:\(error)")
|
||||
}
|
||||
}else {
|
||||
print("文件不存在")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ class MP_NetWorkManager: NSObject {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -205,7 +205,7 @@ extension MP_NetWorkManager {
|
||||
"clientName": "WEB_REMIX",
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -268,7 +268,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -325,7 +325,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -381,7 +381,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -434,7 +434,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -488,7 +488,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -539,7 +539,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -572,7 +572,7 @@ extension MP_NetWorkManager {
|
||||
//MARK: - 请求player播放资源
|
||||
/// 请求Player(单曲/视频)播放资源
|
||||
/// - Parameter item: 请求的预览实体
|
||||
func requestPlayer(_ videoId: String, playlistId: String, completion:@escaping ((([String],[Float],[String]), [String]?) -> Void)){
|
||||
func requestAndroidPlayer(_ videoId: String, playlistId: String, completion:@escaping ((([String],[Int],[String]), [String]?) -> Void)){
|
||||
//拼接出player路径
|
||||
let path = header+point+player
|
||||
//设置url
|
||||
@ -580,51 +580,34 @@ extension MP_NetWorkManager {
|
||||
print("Url is Incorrect")
|
||||
return
|
||||
}
|
||||
let day = Date().timeZone()
|
||||
//设置参数,videoId与params参数是必定携带内容
|
||||
let parameters:[String:Any] = [
|
||||
"videoId":videoId,
|
||||
"prettyPrint":"false",
|
||||
// "playlistId":"OLAK5uy_knZiqQOlTDeQ3jecXrW_VIAZKdMnkLGgw",
|
||||
"context":[
|
||||
"client":[
|
||||
// //当前访问版本(日期值)
|
||||
// "clientName": "WEB_REMIX",
|
||||
// "clientVersion": "1.\(currTimeDate).01.00"
|
||||
//web端
|
||||
"clientName": "WEB_REMIX",
|
||||
"visitorData":visitorData,
|
||||
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36,gzip(gfe)",
|
||||
// "remoteHost":"2401:b60:13:4335:bea3:7c0b:5c4e:db84",
|
||||
"originalUrl":"https://music.youtube.com/watch?v=\(videoId)",
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"clientName": "ANDROID_MUSIC",
|
||||
"clientVersion": "\(day.month).\(day.toString(.custom("dd"))).1",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
"gl":locaton
|
||||
]
|
||||
],
|
||||
"playbackContext": [
|
||||
"contentPlaybackContext": [
|
||||
"signatureTimestamp": MP_WebWork.shared.signatureTimestamp ?? 0
|
||||
"browserVersion":"125.0.0.0",
|
||||
// "userAgent":
|
||||
]
|
||||
]
|
||||
]
|
||||
//guard netWorkStatu != .notReachable else {return}
|
||||
requestPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
|
||||
requestAndroidPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
|
||||
completion(resourceUlrs, coverUrls)
|
||||
}
|
||||
}
|
||||
//请求单曲/视频
|
||||
private func requestPostPlayer(_ url:URL, parameters:Parameters, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)) {
|
||||
private func requestAndroidPostPlayer(_ url:URL, parameters:Parameters, completion:@escaping((([String],[Int],[String]), [String]?) -> Void)) {
|
||||
//发送post请求
|
||||
MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonPlayer.self) { [weak self] (response) in
|
||||
MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonAndroidPlayer.self) { [weak self] (response) in
|
||||
guard let self = self else {return}
|
||||
|
||||
switch response.result {
|
||||
case .success(let value):
|
||||
parsingPlayer(value) { resourceUlrs, coverUrls in
|
||||
parsingAndroidPlayer(value) { resourceUlrs, coverUrls in
|
||||
completion(resourceUlrs, coverUrls)
|
||||
}
|
||||
case .failure(let error):
|
||||
@ -633,6 +616,60 @@ extension MP_NetWorkManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
// func requestPlayer(_ videoId: String, playlistId: String, completion:@escaping ((([String],[Float],[String]), [String]?) -> Void)){
|
||||
// //拼接出player路径
|
||||
// let path = header+point+player
|
||||
// //设置url
|
||||
// guard let url = URL(string: path) else {
|
||||
// print("Url is Incorrect")
|
||||
// return
|
||||
// }
|
||||
// //设置参数,videoId与params参数是必定携带内容
|
||||
// let parameters:[String:Any] = [
|
||||
// "videoId":videoId,
|
||||
// "prettyPrint":"false",
|
||||
// "context":[
|
||||
// "client":[
|
||||
// "clientName": "WEB_REMIX",
|
||||
//// "visitorData":visitorData,
|
||||
//// "originalUrl":"https://music.youtube.com/watch?v=\(videoId)",
|
||||
// //当前访问版本(日期值)
|
||||
// "clientVersion": "1.\(currTimeDate).01.00",
|
||||
// "platform":"MOBILE",
|
||||
// //语言
|
||||
// "hl":Language_first_local,
|
||||
// //地址
|
||||
// "gl":locaton
|
||||
// ]
|
||||
// ],
|
||||
// "playbackContext": [
|
||||
// "contentPlaybackContext": [
|
||||
// "signatureTimestamp": MP_WebWork.shared.signatureTimestamp ?? 0
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// //guard netWorkStatu != .notReachable else {return}
|
||||
// requestPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
|
||||
// completion(resourceUlrs, coverUrls)
|
||||
// }
|
||||
// }
|
||||
//请求单曲/视频
|
||||
// private func requestPostPlayer(_ url:URL, parameters:Parameters, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)) {
|
||||
// //发送post请求
|
||||
// MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonPlayer.self) { [weak self] (response) in
|
||||
// guard let self = self else {return}
|
||||
//
|
||||
// switch response.result {
|
||||
// case .success(let value):
|
||||
// parsingPlayer(value) { resourceUlrs, coverUrls in
|
||||
// completion(resourceUlrs, coverUrls)
|
||||
// }
|
||||
// case .failure(let error):
|
||||
// // 请求失败,处理错误
|
||||
// print("Request failed: \(error)")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//MARK: - 请求歌词
|
||||
/// 请求歌词
|
||||
/// - Parameter lyricId: 歌词id
|
||||
@ -655,7 +692,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -702,7 +739,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -755,7 +792,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -806,7 +843,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -863,7 +900,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -920,7 +957,7 @@ extension MP_NetWorkManager {
|
||||
"visitorData":visitorData,
|
||||
//当前访问版本(日期值)
|
||||
"clientVersion": "1.\(currTimeDate).01.00",
|
||||
"platform":"DESKTOP",
|
||||
"platform":"MOBILE",
|
||||
//语言
|
||||
"hl":Language_first_local,
|
||||
//地址
|
||||
@ -1221,50 +1258,73 @@ extension MP_NetWorkManager {
|
||||
/// - Parameters:
|
||||
/// - player: player库
|
||||
/// - completion: 传递两个字符串数组,第一个资源路径组,第二个是封面路径组
|
||||
private func parsingPlayer(_ player:JsonPlayer, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)){
|
||||
// private func parsingPlayer(_ player:JsonPlayer, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)){
|
||||
// var infos:[String]?
|
||||
// //解析player,获取资源库和信息库
|
||||
// if let videoDetails = player.videoDetails {
|
||||
// infos = parsingPlayerVideoDetails(videoDetails)
|
||||
// }
|
||||
// if let streamingData = player.streamingData {
|
||||
// parsingPlayerStreamingData(streamingData){ videos,floats,approxDurationMs in
|
||||
// completion((videos,floats,approxDurationMs),infos)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
private func parsingAndroidPlayer(_ player:JsonAndroidPlayer,completion:@escaping((([String],[Int],[String]), [String]?) -> Void)){
|
||||
var infos:[String]?
|
||||
//解析player,获取资源库和信息库
|
||||
if let videoDetails = player.videoDetails {
|
||||
infos = parsingPlayerVideoDetails(videoDetails)
|
||||
infos = parsingAndroidPlayerVideoDetails(videoDetails)
|
||||
}
|
||||
if let streamingData = player.streamingData {
|
||||
parsingPlayerStreamingData(streamingData){ videos,floats,approxDurationMs in
|
||||
completion((videos,floats,approxDurationMs),infos)
|
||||
parsingAndroidPlayerStreamingData(streamingData){ videos,itags,mimeType in
|
||||
completion((videos,itags,mimeType),infos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 解析播放器_StreamingData
|
||||
/// - Parameters:
|
||||
/// - streamingData: 资源库
|
||||
/// - completion: 第一位是音频资源,第二位是视频资源
|
||||
private func parsingPlayerStreamingData(_ streamingData:JsonPlayer.StreamingData, completion:@escaping(([String],[Float],[String]) -> Void)) {
|
||||
var group:DispatchGroup? = DispatchGroup()
|
||||
private func parsingAndroidPlayerStreamingData(_ streamingData:JsonAndroidPlayer.StreamingData, completion:@escaping(([String],[Int],[String]) -> Void)) {
|
||||
var videos:[String] = []
|
||||
var floats:[Float] = []
|
||||
var approxDurationMs:[String] = []
|
||||
var itags:[Int] = []
|
||||
var mimeType:[String] = []
|
||||
let allFormats = (streamingData.formats ?? []) + (streamingData.adaptiveFormats ?? [])
|
||||
for format in allFormats {
|
||||
if let signatureCipher = format.signatureCipher {
|
||||
// 进入DispatchGroup,表示开始一个异步任务
|
||||
group?.enter()
|
||||
//获得资源签名,开始解密签名内容
|
||||
parsingPlayerSignatureCipher(signatureCipher) { result in
|
||||
//这是条视频资源
|
||||
videos.append(result)
|
||||
floats.append(format.bitrate ?? 0)
|
||||
approxDurationMs.append(format.approxDurationMs ?? "")
|
||||
// 离开DispatchGroup,表示异步任务完成
|
||||
group?.leave()
|
||||
}
|
||||
}
|
||||
}
|
||||
group?.notify(queue: .main) {
|
||||
completion(videos, floats, approxDurationMs)
|
||||
group = nil
|
||||
videos.append(format.url ?? "")
|
||||
itags.append(format.itag ?? 0)
|
||||
mimeType.append(format.mimeType ?? "")
|
||||
}
|
||||
completion(videos,itags,mimeType)
|
||||
}
|
||||
// private func parsingPlayerStreamingData(_ streamingData:JsonPlayer.StreamingData, completion:@escaping(([String],[Float],[String]) -> Void)) {
|
||||
// var group:DispatchGroup? = DispatchGroup()
|
||||
// var videos:[String] = []
|
||||
// var floats:[Float] = []
|
||||
// var approxDurationMs:[String] = []
|
||||
// let allFormats = (streamingData.formats ?? []) + (streamingData.adaptiveFormats ?? [])
|
||||
// for format in allFormats {
|
||||
// if let signatureCipher = format.signatureCipher {
|
||||
// // 进入DispatchGroup,表示开始一个异步任务
|
||||
// group?.enter()
|
||||
// //获得资源签名,开始解密签名内容
|
||||
// parsingPlayerSignatureCipher(signatureCipher) { result in
|
||||
// //这是条视频资源
|
||||
// videos.append(result)
|
||||
// floats.append(format.bitrate ?? 0)
|
||||
// approxDurationMs.append(format.approxDurationMs ?? "")
|
||||
// // 离开DispatchGroup,表示异步任务完成
|
||||
// group?.leave()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// group?.notify(queue: .main) {
|
||||
// completion(videos, floats, approxDurationMs)
|
||||
// group = nil
|
||||
// }
|
||||
// }
|
||||
///解析加密签名_SignatureCipher
|
||||
private func parsingPlayerSignatureCipher(_ signatureCipher:String, completion:@escaping((String) -> Void)) {
|
||||
// print("Resources-SignatureCipher:\(signatureCipher)")
|
||||
@ -1296,7 +1356,7 @@ extension MP_NetWorkManager {
|
||||
/// 解析播放器_VideoDetails
|
||||
/// - Parameter videoDetails: 信息库
|
||||
/// - Returns: 返回一个元组,值分别为 videoId,title,author,urls
|
||||
private func parsingPlayerVideoDetails(_ videoDetails:JsonPlayer.VideoDetails) -> [String]? {
|
||||
private func parsingAndroidPlayerVideoDetails(_ videoDetails:JsonAndroidPlayer.VideoDetails) -> [String]? {
|
||||
var urls:[String]?
|
||||
videoDetails.thumbnail?.thumbnails?.forEach({ item in
|
||||
if item.url != nil {
|
||||
@ -1310,6 +1370,20 @@ extension MP_NetWorkManager {
|
||||
})
|
||||
return urls
|
||||
}
|
||||
// private func parsingPlayerVideoDetails(_ videoDetails:JsonPlayer.VideoDetails) -> [String]? {
|
||||
// var urls:[String]?
|
||||
// videoDetails.thumbnail?.thumbnails?.forEach({ item in
|
||||
// if item.url != nil {
|
||||
// if urls != nil {
|
||||
// urls!.append(item.url!)
|
||||
// }else {
|
||||
// urls = []
|
||||
// urls!.append(item.url!)
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// return urls
|
||||
// }
|
||||
///解析歌词_Lyrics
|
||||
private func parsingLyrics(_ lyrics:JsonLyrics) -> String? {
|
||||
if let first = lyrics.contents?.sectionListRenderer?.contents?.first {
|
||||
|
||||
@ -162,7 +162,7 @@ class MP_PlayerManager:NSObject{
|
||||
}
|
||||
}else {
|
||||
//伪装每秒缓存进度
|
||||
let byte = currentTime + 100
|
||||
let byte = currentTime + 30
|
||||
let rate = Float(byte)/duration
|
||||
if self.cacheValueBlock != nil {
|
||||
self.cacheValueBlock!(rate)
|
||||
@ -193,7 +193,7 @@ class MP_PlayerManager:NSObject{
|
||||
}else {
|
||||
//配置当前播放音乐
|
||||
player = .init(url: loadPlayer.currentVideo.resourcePlayerURL!)
|
||||
player.maxRetryCount = 3
|
||||
player.maxRetryCount = 2
|
||||
}
|
||||
//预加载下一首(假如有的话)
|
||||
let index = loadPlayer.listViewVideos.firstIndex(of: loadPlayer.currentVideo) ?? 0
|
||||
@ -212,6 +212,7 @@ class MP_PlayerManager:NSObject{
|
||||
switch status {
|
||||
case .fsAudioStreamFailed://加载失败
|
||||
print("\(loadPlayer.currentVideo?.title ?? "")加载失败")
|
||||
playState = .Null
|
||||
case .fsAudioStreamRetryingFailed://重试都失败了
|
||||
print("\(loadPlayer.currentVideo?.title ?? "")重试失败")
|
||||
print("失败URL:\(String(describing: loadPlayer.currentVideo?.resourcePlayerURL))")
|
||||
|
||||
@ -125,3 +125,122 @@ struct JsonPlayer: Codable {
|
||||
}
|
||||
}
|
||||
}
|
||||
///安卓结构的播放器数据
|
||||
struct JsonAndroidPlayer: Codable {
|
||||
///资源路径块
|
||||
let streamingData:StreamingData?
|
||||
///单曲/视频信息块
|
||||
let videoDetails:VideoDetails?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case streamingData = "streamingData"
|
||||
case videoDetails = "videoDetails"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
streamingData = try values.decodeIfPresent(StreamingData.self, forKey: .streamingData)
|
||||
videoDetails = try values.decodeIfPresent(VideoDetails.self, forKey: .videoDetails)
|
||||
}
|
||||
//MARK: - 资源路径(各等级资源)
|
||||
struct StreamingData: Codable {
|
||||
///允许访问的时间值
|
||||
let expiresInSeconds:String?
|
||||
///资源标准格式
|
||||
let formats:[Format]?
|
||||
///更多资源格式
|
||||
let adaptiveFormats:[Format]?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case expiresInSeconds = "expiresInSeconds"
|
||||
case formats = "formats"
|
||||
case adaptiveFormats = "adaptiveFormats"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
expiresInSeconds = try values.decodeIfPresent(String.self, forKey: .expiresInSeconds)
|
||||
formats = try values.decodeIfPresent([Format].self, forKey: .formats)
|
||||
adaptiveFormats = try values.decodeIfPresent([Format].self, forKey: .adaptiveFormats)
|
||||
}
|
||||
|
||||
|
||||
///资源格式
|
||||
struct Format: Codable {
|
||||
///格式标签
|
||||
let itag: Int?
|
||||
///比特率
|
||||
let bitrate:Float?
|
||||
///格式编码
|
||||
let mimeType:String?
|
||||
///格式名
|
||||
let qualityLabel:String?
|
||||
///资源地址(双加密)
|
||||
let url:String?
|
||||
///总长度
|
||||
let approxDurationMs:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case itag = "itag"
|
||||
case bitrate = "bitrate"
|
||||
case mimeType = "mimeType"
|
||||
case qualityLabel = "qualityLabel"
|
||||
case url = "url"
|
||||
case approxDurationMs = "approxDurationMs"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
itag = try values.decodeIfPresent(Int.self, forKey: .itag)
|
||||
bitrate = try values.decodeIfPresent(Float.self, forKey: .bitrate)
|
||||
mimeType = try values.decodeIfPresent(String.self, forKey: .mimeType)
|
||||
qualityLabel = try values.decodeIfPresent(String.self, forKey: .qualityLabel)
|
||||
approxDurationMs = try values.decodeIfPresent(String.self, forKey: .approxDurationMs)
|
||||
url = try values.decodeIfPresent(String.self, forKey: .url)
|
||||
}
|
||||
}
|
||||
}
|
||||
//MARK: - 单曲/视频信息详情
|
||||
struct VideoDetails: Codable {
|
||||
///单曲/视频videoId
|
||||
let videoId:String?
|
||||
///标题
|
||||
let title:String?
|
||||
///封面资源
|
||||
let thumbnail:Thumbnail?
|
||||
///歌手
|
||||
let author:String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case videoId = "videoId"
|
||||
case title = "title"
|
||||
case thumbnail = "thumbnail"
|
||||
case author = "author"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
videoId = try values.decodeIfPresent(String.self, forKey: .videoId)
|
||||
title = try values.decodeIfPresent(String.self, forKey: .title)
|
||||
thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail)
|
||||
author = try values.decodeIfPresent(String.self, forKey: .author)
|
||||
}
|
||||
///封面资源
|
||||
struct Thumbnail: Codable {
|
||||
///封面库(一般取最后一位,图最大最清晰)
|
||||
let thumbnails:[Thumbnails]?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case thumbnails = "thumbnails"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
thumbnails = try values.decodeIfPresent([Thumbnails].self, forKey: .thumbnails)
|
||||
}
|
||||
struct Thumbnails: Codable {
|
||||
///封面路径
|
||||
let url:String?
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case url = "url"
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
url = try values.decodeIfPresent(String.self, forKey: .url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,10 +32,8 @@ class MPPositive_SongItemModel: NSObject {
|
||||
var videoId:String!
|
||||
///相关内容ID
|
||||
var relatedID:String!
|
||||
///比特率
|
||||
var bitrates:[Float]?
|
||||
///总长度
|
||||
var approxDurationMs:[String]?
|
||||
///列表ID
|
||||
var playlistId:String?
|
||||
///等级值
|
||||
var itags:[Int]?
|
||||
///类型
|
||||
var mimeTypes:[String]?
|
||||
}
|
||||
|
||||
@ -110,8 +110,8 @@ class MPPositive_PlayerLoadViewModel: NSObject {
|
||||
//补全资源路径组和封面路径组
|
||||
improveDataforResouceAndCover(item) {[weak self] resourceUrls, coverUrls in
|
||||
item.resourceUrls = resourceUrls.0
|
||||
item.bitrates = resourceUrls.1
|
||||
item.approxDurationMs = resourceUrls.2
|
||||
item.itags = resourceUrls.1
|
||||
item.mimeTypes = resourceUrls.2
|
||||
item.coverUrls = coverUrls
|
||||
//补全完成,转化为ViewModel,并添加进listViewVideos
|
||||
self?.listViewVideos.append(.init(item))
|
||||
@ -134,14 +134,14 @@ class MPPositive_PlayerLoadViewModel: NSObject {
|
||||
improveDataforResouceAndCover(currentVideo.song) {[weak self] resourceUrls, coverUrls in
|
||||
guard let self = self else {return}
|
||||
currentVideo.song.resourceUrls = resourceUrls.0
|
||||
currentVideo.song.bitrates = resourceUrls.1
|
||||
currentVideo.song.approxDurationMs = resourceUrls.2
|
||||
currentVideo.song.itags = resourceUrls.1
|
||||
currentVideo.song.mimeTypes = resourceUrls.2
|
||||
//成功更新资源,将重新补完的歌曲,放进listViewVideos中
|
||||
listViewVideos.forEach({ item in
|
||||
if item.song.videoId == self.currentVideo.song.videoId {
|
||||
item.song.resourceUrls = self.currentVideo.song.resourceUrls
|
||||
item.song.bitrates = self.currentVideo.song.bitrates
|
||||
item.song.approxDurationMs = self.currentVideo.song.approxDurationMs
|
||||
item.song.itags = self.currentVideo.song.itags
|
||||
item.song.mimeTypes = self.currentVideo.song.mimeTypes
|
||||
}
|
||||
})
|
||||
// currentVideo.resourceAsset = .init(url: .init(string: currentVideo.song.resourceUrls!.first!)!)
|
||||
@ -189,9 +189,9 @@ class MPPositive_PlayerLoadViewModel: NSObject {
|
||||
}
|
||||
}
|
||||
///调用player对资源路径和封面路径补全
|
||||
private func improveDataforResouceAndCover(_ song:MPPositive_SongItemModel, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)) {
|
||||
private func improveDataforResouceAndCover(_ song:MPPositive_SongItemModel, completion:@escaping((([String],[Int],[String]), [String]?) -> Void)) {
|
||||
//单曲补全需要调用player接口
|
||||
MP_NetWorkManager.shared.requestPlayer(song.videoId, playlistId: song.playlistId ?? "") { resourceUrls, coverUrls in
|
||||
MP_NetWorkManager.shared.requestAndroidPlayer(song.videoId, playlistId: "") { resourceUrls, coverUrls in
|
||||
completion(resourceUrls,coverUrls)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,196 @@
|
||||
//
|
||||
// MPPositive_MoreOperationsViewController.swift
|
||||
// MusicPlayer
|
||||
//
|
||||
// Created by Mr.Zhou on 2024/5/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Kingfisher
|
||||
///更多操作
|
||||
class MPPositive_MoreSongOperationsViewController: UIViewController {
|
||||
//下载进度条View
|
||||
private var loadView = CircularProgressView()
|
||||
//小角标图片
|
||||
private lazy var indictorImageView:UIImageView = .init(image: .init(named: "Player_Indictor'logo"))
|
||||
//展示ICON
|
||||
private lazy var iconImageView:UIImageView = {
|
||||
let imageView:UIImageView = .init()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
imageView.layer.masksToBounds = true
|
||||
imageView.layer.cornerRadius = 10*width
|
||||
return imageView
|
||||
}()
|
||||
//标题Label
|
||||
private lazy var titleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||
//副标题
|
||||
private lazy var subtitleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#666666"), textAlignment: .left)
|
||||
//是否收藏
|
||||
private lazy var collectionBtn:UIButton = {
|
||||
let btn = UIButton()
|
||||
btn.setImage(UIImage(named: "Artist_Collection'logo"), for: .normal)
|
||||
btn.setImage(UIImage(named: "Artist_Collectioned'logo"), for: .selected)
|
||||
btn.setBackgroundImage(UIImage(named: "Artist_Collection'bg"), for: .normal)
|
||||
btn.setBackgroundImage(UIImage(named: "Artist_Collectioned'bg"), for: .selected)
|
||||
btn.addTarget(self, action: #selector(collectionClick(_ :)), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
//分割线
|
||||
private lazy var lineView:UIView = {
|
||||
let lineView:UIView = UIView()
|
||||
lineView.backgroundColor = .init(hex: "#444444")
|
||||
return lineView
|
||||
}()
|
||||
//展示tableView
|
||||
private lazy var tableView:UITableView = {
|
||||
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
|
||||
tableView.backgroundColor = .clear
|
||||
tableView.separatorStyle = .none
|
||||
tableView.contentInset = .init(top: 0, left: 0, bottom: bottomPadding, right: 0)
|
||||
tableView.estimatedRowHeight = 200
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.dataSource = self
|
||||
tableView.delegate = self
|
||||
tableView.register(MPPositive_MoreOperationDownLoadTableViewCell.self, forCellReuseIdentifier: MPPositive_MoreOperationTableViewCellID)
|
||||
return tableView
|
||||
}()
|
||||
private let MPPositive_MoreOperationTableViewCellID = "MPPositive_MoreOperationTableViewCell"
|
||||
private var song:MPPositive_SongItemModel!{
|
||||
didSet{
|
||||
iconImageView.kf.setImage(with: URL(string: song.reviewUrls?.last ?? ""), placeholder: placeholderImage)
|
||||
titleLabel.text = song.title
|
||||
subtitleLabel.text = song.shortBylineText
|
||||
//判断该单曲是否收藏
|
||||
collectionBtn.isSelected = MPPositive_CollectionSongModel.fetch(.init(format: "videoId == %@", song.videoId)).count != 0
|
||||
//判断该单曲是否下载
|
||||
isLoaded = MPPositive_DownloadItemModel.fetch(.init(format: "videoId == %@", song.videoId)).count != 0
|
||||
}
|
||||
}
|
||||
private var isLoaded:Bool = false{
|
||||
didSet{
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
self?.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
init(_ song:MPPositive_SongItemModel) {
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.song = song
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = .init(hex: "#282A2C")
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.maskedCorners = [.layerMinXMinYCorner,.layerMinXMaxYCorner]
|
||||
view.layer.cornerRadius = 18*width
|
||||
configure()
|
||||
}
|
||||
|
||||
private func configure() {
|
||||
view.addSubview(indictorImageView)
|
||||
indictorImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.width.equalTo(29*width)
|
||||
make.height.equalTo(4*width)
|
||||
make.top.equalToSuperview().offset(8*width)
|
||||
}
|
||||
view.addSubview(iconImageView)
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(50*width)
|
||||
make.left.equalToSuperview().offset(18*width)
|
||||
make.top.equalToSuperview().offset(32*width)
|
||||
}
|
||||
view.addSubview(collectionBtn)
|
||||
collectionBtn.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(32*width)
|
||||
make.centerY.equalTo(iconImageView)
|
||||
make.right.equalToSuperview().offset(-18*width)
|
||||
}
|
||||
view.addSubview(titleLabel)
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(iconImageView).offset(8*width)
|
||||
make.left.equalTo(iconImageView.snp.right).offset(12*width)
|
||||
make.right.equalTo(collectionBtn.snp.left).offset(-12*width)
|
||||
}
|
||||
view.addSubview(subtitleLabel)
|
||||
subtitleLabel.snp.makeConstraints { make in
|
||||
make.left.right.equalTo(titleLabel)
|
||||
make.bottom.equalTo(iconImageView).offset(-8*width)
|
||||
}
|
||||
view.addSubview(lineView)
|
||||
lineView.snp.makeConstraints { make in
|
||||
make.width.equalTo(339*width)
|
||||
make.height.equalTo(1*width)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(iconImageView.snp.bottom).offset(15*width)
|
||||
}
|
||||
view.addSubview(tableView)
|
||||
tableView.snp.makeConstraints { make in
|
||||
make.top.equalTo(lineView.snp.bottom).offset(8*width)
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
}
|
||||
}
|
||||
//是否收藏
|
||||
@objc private func collectionClick(_ sender:UIButton) {
|
||||
if self.collectionBtn.isSelected == true{
|
||||
self.collectionBtn.isSelected = false
|
||||
MPPositive_CollectionSongModel.fetch(.init(format: "videoId == %@", song.videoId)).forEach { item in
|
||||
if item.videoId == song.videoId {
|
||||
MPPositive_CollectionSongModel.delete(item)
|
||||
}
|
||||
}
|
||||
MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel(nil)
|
||||
}else{
|
||||
self.collectionBtn.isSelected = true
|
||||
let item = MPPositive_CollectionSongModel.create()
|
||||
item.coverImage = URL(string: song.reviewUrls?.last ?? "")
|
||||
item.title = song.title
|
||||
item.subtitle = song.shortBylineText
|
||||
item.videoId = song.videoId
|
||||
item.lyricsID = song.lyricsID
|
||||
item.relatedID = song.relatedID
|
||||
MPPositive_CollectionSongModel.save()
|
||||
MPPositive_LoadCoreModel.shared.reloadCollectionSongViewModel(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
//MARK: - tableView
|
||||
extension MPPositive_MoreSongOperationsViewController:UITableViewDataSource, UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 1
|
||||
}
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_MoreOperationTableViewCellID, for: indexPath) as! MPPositive_MoreOperationDownLoadTableViewCell
|
||||
cell.title = isLoaded ? "Remove Download":"Add Download"
|
||||
return cell
|
||||
}
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if indexPath.row == 0 {
|
||||
if isLoaded {
|
||||
//移除下载
|
||||
MPPositive_DownloadItemModel.fetch(.init(format: "videoId == %@", song.videoId)).forEach { item in
|
||||
if item.videoId == song.videoId {
|
||||
MPPositive_DownloadItemModel.delete(item)
|
||||
}
|
||||
}
|
||||
MPPositive_LoadCoreModel.shared.reloadLoadSongViewModel(nil)
|
||||
DownloadManager.shared.deleteFileDocuments(song.videoId) { [weak self] videoId in
|
||||
guard let self = self else {return}
|
||||
MP_HUD.progress("Loading...", delay: 0.5) {
|
||||
self.isLoaded = false
|
||||
MP_HUD.text("Removed", delay: 1.0, completion: nil)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
//进行下载
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,8 @@ import UIKit
|
||||
enum MPPositive_PresentModal{
|
||||
///播放器弹出列表
|
||||
case PlayerList
|
||||
///更多选择弹出
|
||||
case MoreOperations
|
||||
}
|
||||
class MPPositive_PresentationController: UIPresentationController {
|
||||
//蒙板
|
||||
@ -27,6 +29,11 @@ class MPPositive_PresentationController: UIPresentationController {
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.height.equalTo(380*width)
|
||||
})
|
||||
case .MoreOperations:
|
||||
presentedView?.snp.makeConstraints({ (make) in
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.height.equalTo(160*width+bottomPadding)
|
||||
})
|
||||
}
|
||||
//添加蒙版
|
||||
setMask()
|
||||
|
||||
@ -70,6 +70,9 @@ extension MPPositive_LoveSongsViewController: UITableViewDataSource, UITableView
|
||||
return cell
|
||||
}
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//将当前收藏音乐放入列表中
|
||||
var array:[MPPositive_SongItemModel] = []
|
||||
for (index,song) in MPPositive_LoadCoreModel.shared.songViewModels.enumerated() {
|
||||
@ -89,4 +92,5 @@ extension MPPositive_LoveSongsViewController: UITableViewDataSource, UITableView
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +70,9 @@ extension MPPositive_OfflineSongsViewController: UITableViewDataSource, UITableV
|
||||
return cell
|
||||
}
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//将当前下载音乐放入列表中
|
||||
var array:[MPPositive_SongItemModel] = []
|
||||
for (index, song) in MPPositive_LoadCoreModel.shared.loadViewModels.enumerated() {
|
||||
@ -92,4 +95,5 @@ extension MPPositive_OfflineSongsViewController: UITableViewDataSource, UITableV
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,6 +181,9 @@ extension MPPositive_ArtistShowViewController: JXPagingViewDelegate{
|
||||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "")
|
||||
navigationController?.pushViewController(listVC, animated: true)
|
||||
case .single:
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//单曲/视频跳转
|
||||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||
MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? ""){ [weak self] listSongs in
|
||||
@ -191,6 +194,7 @@ extension MPPositive_ArtistShowViewController: JXPagingViewDelegate{
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
}
|
||||
}
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
|
||||
@ -108,6 +108,9 @@ extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDeleg
|
||||
switch item.browseItem.itemType {
|
||||
case .single:
|
||||
//单曲/视频跳转
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||
MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? ""){ [weak self] listSongs in
|
||||
guard let self = self else {return}
|
||||
@ -117,6 +120,7 @@ extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDeleg
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
}
|
||||
}
|
||||
case .list:
|
||||
//列表专辑
|
||||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: item.browseItem.params ?? "", title: item.title ?? "", subtitle: item.subtitle ?? "")
|
||||
|
||||
@ -278,6 +278,9 @@ extension MPPositive_ListShowViewController: UITableViewDataSource, UITableViewD
|
||||
return cell
|
||||
}
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||
MP_NetWorkManager.shared.requestNextList(listOrAlbum.items[indexPath.row].browseItem.playListId ?? "", videoId: listOrAlbum.items[indexPath.row].browseItem.videoId ?? ""){ [weak self] listSongs in
|
||||
guard let self = self else {return}
|
||||
@ -289,4 +292,5 @@ extension MPPositive_ListShowViewController: UITableViewDataSource, UITableViewD
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ class MPPositive_PlayerListShowViewController: UIViewController {
|
||||
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
|
||||
tableView.backgroundColor = .clear
|
||||
tableView.separatorStyle = .none
|
||||
tableView.contentInset = .init(top: 0, left: 0, bottom: 30*width, right: 0)
|
||||
tableView.contentInset = .init(top: 0, left: 0, bottom: bottomPadding, right: 0)
|
||||
tableView.estimatedRowHeight = 200
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.dataSource = self
|
||||
|
||||
@ -106,6 +106,9 @@ class MPPositive_SearchResultShowViewController: MPPositive_BaseViewController {
|
||||
let listVC = MPPositive_ListShowViewController(item.item.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "")
|
||||
navigationController?.pushViewController(listVC, animated: true)
|
||||
case .single:
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//单曲/视频跳转
|
||||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||
MP_NetWorkManager.shared.requestNextList(item.item.playListId ?? "", videoId: item.item.videoId ?? ""){ [weak self] listSongs in
|
||||
@ -116,6 +119,7 @@ class MPPositive_SearchResultShowViewController: MPPositive_BaseViewController {
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
}
|
||||
}
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
//
|
||||
// MPPositive_MoreOperationTableViewCell.swift
|
||||
// MusicPlayer
|
||||
//
|
||||
// Created by Mr.Zhou on 2024/5/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import DownloadButton
|
||||
class MPPositive_MoreOperationDownLoadTableViewCell: UITableViewCell {
|
||||
//特殊图片(展示预览图片)
|
||||
private lazy var iconImageView:UIImageView = {
|
||||
let imageView:UIImageView = .init()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
imageView.layer.masksToBounds = true
|
||||
return imageView
|
||||
}()
|
||||
//设置下载按钮
|
||||
private lazy var LoadBtn:PKDownloadButton = {
|
||||
let btn:PKDownloadButton = .init()
|
||||
//禁止交互
|
||||
btn.isUserInteractionEnabled = false
|
||||
btn.downloadedButton.cleanDefaultAppearance()
|
||||
// btn.downloadedButton.setBackgroundImage(UIImage(named: ""), for: <#T##UIControl.State#>)
|
||||
return btn
|
||||
}()
|
||||
|
||||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||
var title:String!{
|
||||
didSet{
|
||||
iconImageView.image = UIImage(named: title)
|
||||
titleLabel.text = title
|
||||
}
|
||||
}
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
selectionStyle = .none
|
||||
backgroundColor = .clear
|
||||
configure()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
private func configure() {
|
||||
contentView.addSubview(iconImageView)
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(24*width)
|
||||
make.top.equalToSuperview().offset(12*width).priority(999)
|
||||
make.bottom.equalToSuperview().offset(-12*width)
|
||||
make.left.equalToSuperview().offset(18*width)
|
||||
}
|
||||
contentView.addSubview(titleLabel)
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalTo(iconImageView.snp.right).offset(12*width)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,13 +17,6 @@ class MPPositive_LibraryTableViewCell: UITableViewCell {
|
||||
}()
|
||||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .medium), textColor: .white, textAlignment: .left)
|
||||
private lazy var subtitleLabel:UILabel = createLabel(font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#FFFFFF", alpha: 0.5), textAlignment: .left)
|
||||
///更多按钮
|
||||
private lazy var moreBtn:UIButton = {
|
||||
let btn:UIButton = .init()
|
||||
btn.setBackgroundImage(UIImage(named: "Song_More'logo"), for: .normal)
|
||||
btn.addTarget(self, action: #selector(moreActionClick(_ :)), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
var listViewModel:MPPositive_CollectionListViewModel!{
|
||||
didSet{
|
||||
listViewModel.setImage(iconImageView)
|
||||
@ -58,17 +51,11 @@ class MPPositive_LibraryTableViewCell: UITableViewCell {
|
||||
make.bottom.equalToSuperview().offset(-6*width)
|
||||
make.left.equalToSuperview().offset(18*width)
|
||||
}
|
||||
contentView.addSubview(moreBtn)
|
||||
moreBtn.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(24*width)
|
||||
make.centerY.equalTo(iconImageView.snp.centerY)
|
||||
make.right.equalToSuperview().offset(-18*width)
|
||||
}
|
||||
contentView.addSubview(titleLabel)
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(iconImageView.snp.top).offset(10*width)
|
||||
make.left.equalTo(iconImageView.snp.right).offset(12*width)
|
||||
make.right.equalTo(moreBtn.snp.left).offset(-10*width)
|
||||
make.right.equalToSuperview().offset(-10*width)
|
||||
}
|
||||
contentView.addSubview(subtitleLabel)
|
||||
subtitleLabel.snp.makeConstraints { make in
|
||||
@ -77,8 +64,8 @@ class MPPositive_LibraryTableViewCell: UITableViewCell {
|
||||
make.right.equalTo(titleLabel.snp.right)
|
||||
}
|
||||
}
|
||||
//点击更多
|
||||
@objc private func moreActionClick(_ sender:UIButton) {
|
||||
|
||||
}
|
||||
// //点击更多
|
||||
// @objc private func moreActionClick(_ sender:UIButton) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@ -45,9 +45,7 @@ class MPPositive_ArtistShowHeaderView: UIView {
|
||||
let items = MPPositive_CollectionArtistModel.fetch(.init(format: "artistId == %@", self.artistid))
|
||||
for item in items {
|
||||
if item.artistId == self.artistid {
|
||||
|
||||
self.collectionBtn.isSelected = true
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Created by Mr.Zhou on 2024/5/8.
|
||||
|
||||
import UIKit
|
||||
|
||||
import DownloadButton
|
||||
//B面播放器封面View(封面,标题,副标题,收藏,下载,进度条View)
|
||||
class MPPositive_PlayerCoverView: UIView {
|
||||
//下载进度条View
|
||||
@ -37,6 +37,26 @@ class MPPositive_PlayerCoverView: UIView {
|
||||
btn.addTarget(self, action: #selector(loadActionClick(_ :)), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
///下载按钮
|
||||
lazy var downloadButton:PKDownloadButton = {
|
||||
let btn:PKDownloadButton = .init()
|
||||
//开始下载状态
|
||||
btn.startDownloadButton.cleanDefaultAppearance()
|
||||
btn.startDownloadButton.setBackgroundImage(UIImage(named: "Song_Unload'logo"), for: .normal)
|
||||
//下载结束状态
|
||||
btn.downloadedButton.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal)
|
||||
btn.downloadedButton.isUserInteractionEnabled = false
|
||||
//停止下载状态
|
||||
btn.stopDownloadButton.stopButton.setImage(UIImage(named: "download"), for: .normal)
|
||||
btn.stopDownloadButton.isUserInteractionEnabled = false
|
||||
btn.stopDownloadButton.tintColor = UIColor(hex: "#80F988")
|
||||
btn.stopDownloadButton.filledLineWidth = 1.5
|
||||
btn.stopDownloadButton.filledLineStyleOuter = true
|
||||
//加载状态设置
|
||||
// btn.pendingView.tintColor = .
|
||||
return btn
|
||||
}()
|
||||
|
||||
///进度条View
|
||||
lazy var sliderView:MPPositive_PlayerSilder = {
|
||||
let sliderView:MPPositive_PlayerSilder = .init(frame: .init(x: 0, y: 0, width: 335*width, height: 6*width))
|
||||
|
||||
@ -93,9 +93,13 @@ class MPPositive_PlayerListShowTableViewCell: UITableViewCell {
|
||||
}
|
||||
//从歌单中移除
|
||||
@objc private func removeClick(_ sender:UIButton) {
|
||||
MPPositive_Debouncer.shared.call{
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
guard removeBlock != nil else {
|
||||
return
|
||||
}
|
||||
removeBlock!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
Podfile
2
Podfile
@ -25,6 +25,8 @@ pod 'JXPagingView/Paging'
|
||||
pod 'MJRefresh'
|
||||
#流音频播放
|
||||
pod 'FreeStreamer'
|
||||
#下载按钮
|
||||
pod "DownloadButton"
|
||||
#下载框架
|
||||
pod 'Tiercel'
|
||||
end
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
PODS:
|
||||
- Alamofire (5.9.1)
|
||||
- DownloadButton (0.1.0)
|
||||
- FreeStreamer (4.0.0):
|
||||
- Reachability (~> 3.0)
|
||||
- IQKeyboardManagerSwift (6.5.16)
|
||||
@ -17,6 +18,7 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- Alamofire
|
||||
- DownloadButton
|
||||
- FreeStreamer
|
||||
- IQKeyboardManagerSwift
|
||||
- JXPagingView/Paging
|
||||
@ -31,6 +33,7 @@ DEPENDENCIES:
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Alamofire
|
||||
- DownloadButton
|
||||
- FreeStreamer
|
||||
- IQKeyboardManagerSwift
|
||||
- JXPagingView
|
||||
@ -45,6 +48,7 @@ SPEC REPOS:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
|
||||
DownloadButton: 49a21a89e0d7d1b42d9134f79aaa40e727cd57c3
|
||||
FreeStreamer: 7e9c976045701ac2f7e9c14c17245203c37bf2ea
|
||||
IQKeyboardManagerSwift: 12d89768845bb77b55cc092ecc2b1f9370f06b76
|
||||
JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e
|
||||
@ -57,6 +61,6 @@ SPEC CHECKSUMS:
|
||||
SwiftDate: 72d28954e8e1c6c1c0f917ccc8005e4f83c7d4b2
|
||||
Tiercel: c0a73f876a72800333b15f4e7e48791f4ad21e90
|
||||
|
||||
PODFILE CHECKSUM: 3804949e23587f6d341ef21aa5e0b1c55a818968
|
||||
PODFILE CHECKSUM: 0b090feb210ab3fcc05329c1820f94cdb8cf93f6
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
|
||||
20
Pods/DownloadButton/LICENSE
generated
Normal file
20
Pods/DownloadButton/LICENSE
generated
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2015 Pavel Katunin <wk.katunin@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Contact details
|
||||
|
||||
Email: wk.katunin@gmail.com
|
||||
Site: https://ru.linkedin.com/in/pavelkatunin
|
||||
19
Pods/DownloadButton/Pod/Classes/CALayer+PKDownloadButtonAnimations.h
generated
Normal file
19
Pods/DownloadButton/Pod/Classes/CALayer+PKDownloadButtonAnimations.h
generated
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// CALayer+PKDownloadButtonAnimations.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 31/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@interface CALayer (PKDownloadButtonAnimations)
|
||||
|
||||
- (void)addRotationAnimationWithKey:(NSString *)animationKey
|
||||
fullRotationDuration:(NSTimeInterval)fullRotationDuration;
|
||||
- (void)removeRotationAnimationWithKey:(NSString *)animationKey;
|
||||
- (void)removeRotationAnimationWithKey:(NSString *)animationKey
|
||||
fullRotationDuration:(NSTimeInterval)fullRotationDuration;
|
||||
|
||||
@end
|
||||
60
Pods/DownloadButton/Pod/Classes/CALayer+PKDownloadButtonAnimations.m
generated
Normal file
60
Pods/DownloadButton/Pod/Classes/CALayer+PKDownloadButtonAnimations.m
generated
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// CALayer+PKDownloadButtonAnimations.m
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 31/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CALayer+PKDownloadButtonAnimations.h"
|
||||
|
||||
static NSString *kRorationEndKey = @"PKLayerRorationEndKey";
|
||||
|
||||
@implementation CALayer (PKDownloadButtonAnimations)
|
||||
|
||||
- (void)addRotationAnimationWithKey:(NSString *)animationKey fullRotationDuration:(NSTimeInterval)fullRotationDuration {
|
||||
NSNumber *fromValue = [self.presentationLayer valueForKeyPath:@"transform.rotation"];
|
||||
[self removeAnimationForKey:kRorationEndKey];
|
||||
|
||||
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||
rotationAnimation.fromValue = fromValue;
|
||||
rotationAnimation.toValue = @([rotationAnimation.fromValue floatValue] + (2. * M_PI));
|
||||
rotationAnimation.duration = fullRotationDuration;
|
||||
rotationAnimation.repeatCount = HUGE_VALF;
|
||||
rotationAnimation.removedOnCompletion = NO;
|
||||
|
||||
[self addAnimation:rotationAnimation forKey:animationKey];
|
||||
}
|
||||
|
||||
- (void)removeRotationAnimationWithKey:(NSString *)animationKey {
|
||||
[self removeRotationAnimationWithKey:animationKey fullRotationDuration:0.0];
|
||||
}
|
||||
|
||||
- (void)removeRotationAnimationWithKey:(NSString *)animationKey fullRotationDuration:(NSTimeInterval)fullRotationDuration {
|
||||
NSNumber *fromValue = [self.presentationLayer valueForKeyPath:@"transform.rotation"];
|
||||
NSNumber *toValue = @((fromValue.doubleValue < 0.0) ? 0.0 : 2.0 * M_PI);
|
||||
|
||||
[self removeAnimationForKey:animationKey];
|
||||
|
||||
const NSTimeInterval animationDuration = ABS(toValue.doubleValue - fromValue.doubleValue) * (fullRotationDuration / (2.0 * M_PI));
|
||||
|
||||
if (fromValue.doubleValue != 0.0 && ![fromValue isEqualToNumber:toValue] && animationDuration > 0.0) {
|
||||
[CATransaction begin];
|
||||
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||
rotationAnimation.fromValue = fromValue;
|
||||
rotationAnimation.toValue = toValue;
|
||||
rotationAnimation.duration = animationDuration;
|
||||
|
||||
[CATransaction setCompletionBlock:^{
|
||||
[self removeAnimationForKey:kRorationEndKey];
|
||||
}];
|
||||
|
||||
[self addAnimation:rotationAnimation forKey:kRorationEndKey];
|
||||
[CATransaction commit];
|
||||
}
|
||||
else {
|
||||
[self removeAnimationForKey:kRorationEndKey];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
18
Pods/DownloadButton/Pod/Classes/NSLayoutConstraint+PKDownloadButton.h
generated
Normal file
18
Pods/DownloadButton/Pod/Classes/NSLayoutConstraint+PKDownloadButton.h
generated
Normal file
@ -0,0 +1,18 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface NSLayoutConstraint (PKDownloadButton)
|
||||
|
||||
+ (NSArray *)constraintsForWrappedSubview:(UIView *)view withInsets:(UIEdgeInsets)insets;
|
||||
+ (NSArray *)horizontalConstraintsForWrappedSubview:(UIView *)view withInsets:(UIEdgeInsets)insets;
|
||||
+ (NSArray *)verticalConstraintsForWrappedSubview:(UIView *)view withInsets:(UIEdgeInsets)insets;
|
||||
+ (NSLayoutConstraint *)constraintForView:(UIView *)view withWidth:(CGFloat)width;
|
||||
+ (NSLayoutConstraint *)constraintForView:(UIView *)view withHeight:(CGFloat)height;
|
||||
+ (NSArray *)constraintsForView:(UIView *)view withSize:(CGSize)size;
|
||||
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format views:(NSDictionary *)views;
|
||||
+ (NSLayoutConstraint *)constraintForCenterByYView:(UIView *)overlay withView:(UIView *)view;
|
||||
+ (NSLayoutConstraint *)constraintForCenterByXView:(UIView *)overlay withView:(UIView *)view;
|
||||
// Constraints for center view above it's superview
|
||||
+ (NSArray *)constraintsForCenterView:(UIView *)overlay;
|
||||
+ (NSArray *)constraintsForCenterView:(UIView *)overlay withView:(UIView *)view;
|
||||
|
||||
@end
|
||||
99
Pods/DownloadButton/Pod/Classes/NSLayoutConstraint+PKDownloadButton.m
generated
Normal file
99
Pods/DownloadButton/Pod/Classes/NSLayoutConstraint+PKDownloadButton.m
generated
Normal file
@ -0,0 +1,99 @@
|
||||
#import "NSLayoutConstraint+PKDownloadButton.h"
|
||||
|
||||
@implementation NSLayoutConstraint (PKDownloadButton)
|
||||
|
||||
+ (NSArray *)constraintsForWrappedSubview:(UIView *)view withInsets:(UIEdgeInsets)insets {
|
||||
NSArray *horizontalConstraints = [self horizontalConstraintsForWrappedSubview:view withInsets:insets];
|
||||
NSArray *verticalConstraints = [self verticalConstraintsForWrappedSubview:view withInsets:insets];
|
||||
NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:[horizontalConstraints count] + [verticalConstraints count]];
|
||||
[resultArray addObjectsFromArray:horizontalConstraints];
|
||||
[resultArray addObjectsFromArray:verticalConstraints];
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
+ (NSArray *)horizontalConstraintsForWrappedSubview:(UIView *)view withInsets:(UIEdgeInsets)insets {
|
||||
NSString *horizontalConstraintsFormat = [NSString stringWithFormat:@"H:|-(%d)-[view]-(%d)-|",
|
||||
(int)insets.left,
|
||||
(int)roundf(insets.right)];
|
||||
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:horizontalConstraintsFormat
|
||||
options:0
|
||||
metrics:nil
|
||||
views:NSDictionaryOfVariableBindings(view)];
|
||||
return horizontalConstraints;
|
||||
}
|
||||
|
||||
+ (NSArray *)verticalConstraintsForWrappedSubview:(UIView *)view withInsets:(UIEdgeInsets)insets {
|
||||
NSString *verticalConstraintsFormat = [NSString stringWithFormat:@"V:|-(%d)-[view]-(%d)-|", (int)insets.top, (int)insets.bottom];
|
||||
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:verticalConstraintsFormat
|
||||
options:0
|
||||
metrics:nil
|
||||
views:NSDictionaryOfVariableBindings(view)];
|
||||
return verticalConstraints;
|
||||
}
|
||||
|
||||
+ (NSLayoutConstraint *)constraintForView:(UIView *)view withWidth:(CGFloat)width {
|
||||
return [NSLayoutConstraint constraintWithItem:view
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:width];
|
||||
}
|
||||
|
||||
+ (NSLayoutConstraint *)constraintForView:(UIView *)view withHeight:(CGFloat)height {
|
||||
return [NSLayoutConstraint constraintWithItem:view
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:height];
|
||||
}
|
||||
|
||||
+ (NSArray *)constraintsForView:(UIView *)view withSize:(CGSize)size {
|
||||
NSLayoutConstraint *width = [NSLayoutConstraint constraintForView:view
|
||||
withWidth:size.width];
|
||||
NSLayoutConstraint *height = [NSLayoutConstraint constraintForView:view
|
||||
withHeight:size.height];
|
||||
return @[width, height];
|
||||
}
|
||||
|
||||
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format views:(NSDictionary *)views {
|
||||
return [self constraintsWithVisualFormat:format options:0 metrics:nil views:views];
|
||||
}
|
||||
|
||||
+ (NSLayoutConstraint *)constraintForCenterByXView:(UIView *)overlay withView:(UIView *)view {
|
||||
return [NSLayoutConstraint constraintWithItem:overlay
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:view
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:0.0];
|
||||
}
|
||||
|
||||
+ (NSLayoutConstraint *)constraintForCenterByYView:(UIView *)overlay withView:(UIView *)view {
|
||||
return [NSLayoutConstraint constraintWithItem:overlay
|
||||
attribute:NSLayoutAttributeCenterY
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:view
|
||||
attribute:NSLayoutAttributeCenterY
|
||||
multiplier:1.0
|
||||
constant:0.0];
|
||||
}
|
||||
|
||||
+ (NSArray *)constraintsForCenterView:(UIView *)overlay {
|
||||
return [self constraintsForCenterView:overlay withView:overlay.superview];
|
||||
}
|
||||
|
||||
+ (NSArray *)constraintsForCenterView:(UIView *)overlay withView:(UIView *)view {
|
||||
NSMutableArray *constraints = [NSMutableArray array];
|
||||
|
||||
[constraints addObject:[self constraintForCenterByXView:overlay withView:view]];
|
||||
[constraints addObject:[self constraintForCenterByYView:overlay withView:view]];
|
||||
|
||||
return constraints;
|
||||
}
|
||||
|
||||
@end
|
||||
20
Pods/DownloadButton/Pod/Classes/PKCircleProgressView.h
generated
Normal file
20
Pods/DownloadButton/Pod/Classes/PKCircleProgressView.h
generated
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// PKCircleProgressView.h
|
||||
// PKDownloadButton
|
||||
//
|
||||
// Created by Pavel on 28/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface PKCircleProgressView : UIView
|
||||
|
||||
@property (nonatomic, assign) IBInspectable CGFloat progress; /// 0.f - 1.0f
|
||||
@property (nonatomic, assign) IBInspectable CGFloat filledLineWidth; /// 0.f +
|
||||
@property (nonatomic, assign) IBInspectable CGFloat emptyLineWidth; /// 0.f +
|
||||
@property (nonatomic, assign) IBInspectable CGFloat radius; /// 0.f +
|
||||
@property (nonatomic, assign) IBInspectable BOOL filledLineStyleOuter;
|
||||
|
||||
@end
|
||||
181
Pods/DownloadButton/Pod/Classes/PKCircleProgressView.m
generated
Normal file
181
Pods/DownloadButton/Pod/Classes/PKCircleProgressView.m
generated
Normal file
@ -0,0 +1,181 @@
|
||||
//
|
||||
// PKCircleProgressView.m
|
||||
// PKDownloadButton
|
||||
//
|
||||
// Created by Pavel on 28/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PKCircleProgressView.h"
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
#import "PKCircleView.h"
|
||||
#import "NSLayoutConstraint+PKDownloadButton.h"
|
||||
|
||||
static const CGFloat kDefaultRaduis = 13.f;
|
||||
static const CGFloat kDefaultFilledLineWidth = 3.f;
|
||||
static const CGFloat kDefaultEmptyLineWidth = 1.f;
|
||||
static const CGFloat kStartAngle = M_PI * 1.5;
|
||||
|
||||
@interface PKCircleProgressView ()
|
||||
|
||||
@property (nonatomic, assign) CGFloat startAngle;
|
||||
@property (nonatomic, assign) CGFloat endAngle;
|
||||
|
||||
@property (nonatomic, weak) PKCircleView *emptyLineCircleView;
|
||||
@property (nonatomic, weak) PKCircleView *filledLineCircleView;
|
||||
|
||||
@property (nonatomic, weak) NSLayoutConstraint *emptyLineCircleWidth;
|
||||
@property (nonatomic, weak) NSLayoutConstraint *emptyLineCircleHeight;
|
||||
|
||||
@property (nonatomic, weak) NSLayoutConstraint *filledLineCircleWidth;
|
||||
@property (nonatomic, weak) NSLayoutConstraint *filledLineCircleHeight;
|
||||
|
||||
@property (nonatomic, assign) CGFloat emptyLineCircleSize;
|
||||
@property (nonatomic, assign) CGFloat filledLineCircleSize;
|
||||
|
||||
- (PKCircleView *)createEmptyLineCircleView;
|
||||
- (PKCircleView *)createFilledLineCircleView;
|
||||
|
||||
- (NSArray *)createCircleConstraints;
|
||||
|
||||
@end
|
||||
|
||||
static PKCircleProgressView *CommonInit(PKCircleProgressView *self) {
|
||||
if (self != nil) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.startAngle = kStartAngle;
|
||||
self.endAngle = self.startAngle + (M_PI * 2);
|
||||
self.clipsToBounds = NO;
|
||||
|
||||
PKCircleView *emptyLineCircleView = [self createEmptyLineCircleView];
|
||||
self.emptyLineCircleView = emptyLineCircleView;
|
||||
emptyLineCircleView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:emptyLineCircleView];
|
||||
|
||||
PKCircleView *filledLineCircleView = [self createFilledLineCircleView];
|
||||
self.filledLineCircleView = filledLineCircleView;
|
||||
filledLineCircleView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:filledLineCircleView];
|
||||
|
||||
[self addConstraints:[self createCircleConstraints]];
|
||||
|
||||
self.emptyLineWidth = kDefaultEmptyLineWidth;
|
||||
self.filledLineWidth = kDefaultFilledLineWidth;
|
||||
self.radius = kDefaultRaduis;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@implementation PKCircleProgressView
|
||||
|
||||
#pragma mark - initilaization / deallocation
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
return CommonInit([super initWithCoder:decoder]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return CommonInit([super initWithFrame:frame]);
|
||||
}
|
||||
|
||||
#pragma mark - properties
|
||||
|
||||
- (void)setEmptyLineCircleSize:(CGFloat)emptyLineCircleSize {
|
||||
self.emptyLineCircleWidth.constant = emptyLineCircleSize;
|
||||
self.emptyLineCircleHeight.constant = emptyLineCircleSize;
|
||||
}
|
||||
|
||||
- (void)setFilledLineCircleSize:(CGFloat)filledLineCircleSize {
|
||||
self.filledLineCircleWidth.constant = filledLineCircleSize;
|
||||
self.filledLineCircleHeight.constant = filledLineCircleSize;
|
||||
}
|
||||
|
||||
- (void)setProgress:(CGFloat)progress {
|
||||
_progress = progress;
|
||||
self.filledLineCircleView.startAngleRadians = self.startAngle;
|
||||
self.filledLineCircleView.endAngleRadians = (self.endAngle - self.startAngle) * progress + self.startAngle;
|
||||
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)setFilledLineWidth:(CGFloat)filledLineWidth {
|
||||
_filledLineWidth = filledLineWidth;
|
||||
self.filledLineCircleView.lineWidth = filledLineWidth;
|
||||
[self setNeedsUpdateConstraints];
|
||||
}
|
||||
|
||||
- (void)setEmptyLineWidth:(CGFloat)emptyLineWidth {
|
||||
_emptyLineWidth = emptyLineWidth;
|
||||
self.emptyLineCircleView.lineWidth = emptyLineWidth;
|
||||
[self setNeedsUpdateConstraints];
|
||||
}
|
||||
|
||||
- (void)setRadius:(CGFloat)radius {
|
||||
_radius = radius;
|
||||
[self setNeedsUpdateConstraints];
|
||||
}
|
||||
|
||||
- (void)setFilledLineStyleOuter:(BOOL)filledLineStyleOuter {
|
||||
_filledLineStyleOuter = filledLineStyleOuter;
|
||||
[self setNeedsUpdateConstraints];
|
||||
}
|
||||
|
||||
#pragma mark - UIView
|
||||
|
||||
- (void)updateConstraints {
|
||||
[super updateConstraints];
|
||||
self.emptyLineCircleSize = self.radius * 2.f;
|
||||
CGFloat deltaRaduis = 0.f;
|
||||
if (self.filledLineStyleOuter) {
|
||||
deltaRaduis = - self.emptyLineCircleView.lineWidth / 2.f + self.filledLineCircleView.lineWidth;
|
||||
}
|
||||
else {
|
||||
deltaRaduis = - self.emptyLineCircleView.lineWidth / 2.f;
|
||||
}
|
||||
self.filledLineCircleSize = self.radius * 2.f + deltaRaduis * 2.f;
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
|
||||
- (PKCircleView *)createEmptyLineCircleView {
|
||||
PKCircleView *emptyCircelView = [[PKCircleView alloc] init];
|
||||
|
||||
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintForView:emptyCircelView
|
||||
withWidth:0.f];
|
||||
self.emptyLineCircleWidth = widthConstraint;
|
||||
[emptyCircelView addConstraint:widthConstraint];
|
||||
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintForView:emptyCircelView
|
||||
withHeight:0.f];
|
||||
self.emptyLineCircleHeight = heightConstraint;
|
||||
[emptyCircelView addConstraint:heightConstraint];
|
||||
|
||||
return emptyCircelView;
|
||||
}
|
||||
|
||||
- (PKCircleView *)createFilledLineCircleView {
|
||||
PKCircleView *filledCircelView = [[PKCircleView alloc] init];
|
||||
|
||||
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintForView:filledCircelView
|
||||
withWidth:0.f];
|
||||
self.filledLineCircleWidth = widthConstraint;
|
||||
[filledCircelView addConstraint:widthConstraint];
|
||||
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintForView:filledCircelView
|
||||
withHeight:0.f];
|
||||
self.filledLineCircleHeight = heightConstraint;
|
||||
[filledCircelView addConstraint:heightConstraint];
|
||||
|
||||
return filledCircelView;
|
||||
}
|
||||
|
||||
- (NSArray *)createCircleConstraints {
|
||||
NSMutableArray *constraints = [NSMutableArray array];
|
||||
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsForCenterView:self.emptyLineCircleView
|
||||
withView:self]];
|
||||
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsForCenterView:self.filledLineCircleView
|
||||
withView:self]];
|
||||
return constraints;
|
||||
}
|
||||
|
||||
@end
|
||||
18
Pods/DownloadButton/Pod/Classes/PKCircleView.h
generated
Normal file
18
Pods/DownloadButton/Pod/Classes/PKCircleView.h
generated
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// PKCircleView.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface PKCircleView : UIView
|
||||
|
||||
@property (nonatomic, assign) IBInspectable CGFloat startAngleRadians;
|
||||
@property (nonatomic, assign) IBInspectable CGFloat endAngleRadians;
|
||||
@property (nonatomic, assign) IBInspectable CGFloat lineWidth;
|
||||
|
||||
@end
|
||||
92
Pods/DownloadButton/Pod/Classes/PKCircleView.m
generated
Normal file
92
Pods/DownloadButton/Pod/Classes/PKCircleView.m
generated
Normal file
@ -0,0 +1,92 @@
|
||||
//
|
||||
// PKCircleView.m
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PKCircleView.h"
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
|
||||
static const CGFloat kDefaultLineWidth = 1.f;
|
||||
|
||||
@interface PKCircleView ()
|
||||
|
||||
- (void)drawCircleRadius:(CGFloat)radius
|
||||
rect:(CGRect)rect
|
||||
startAngle:(CGFloat)startAngle
|
||||
endAngle:(CGFloat)endAngel
|
||||
lineWidth:(CGFloat)lineWidth;
|
||||
|
||||
@end
|
||||
|
||||
static PKCircleView *CommonInit(PKCircleView *self) {
|
||||
if (self != nil) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.startAngleRadians = M_PI * 1.5;
|
||||
self.endAngleRadians = self.startAngleRadians + (M_PI * 2);
|
||||
self.lineWidth = kDefaultLineWidth;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@implementation PKCircleView
|
||||
|
||||
#pragma mark - initialization
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
return CommonInit([super initWithCoder:decoder]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return CommonInit([super initWithFrame:frame]);
|
||||
}
|
||||
|
||||
#pragma mark - properties
|
||||
|
||||
- (void)setLineWidth:(CGFloat)lineWidth {
|
||||
_lineWidth = lineWidth;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)setStartAngleRadians:(CGFloat)startAngleRadians {
|
||||
_startAngleRadians = startAngleRadians;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)setEndAngleRadians:(CGFloat)endAngleRadians {
|
||||
_endAngleRadians = endAngleRadians;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
#pragma mark - UIView
|
||||
|
||||
- (void)drawRect:(CGRect)rect {
|
||||
[self drawCircleRadius:MIN(rect.size.width / 2, rect.size.height / 2) - self.lineWidth / 2.f
|
||||
rect:rect
|
||||
startAngle:self.startAngleRadians
|
||||
endAngle:self.endAngleRadians
|
||||
lineWidth:self.lineWidth];
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
|
||||
- (void)drawCircleRadius:(CGFloat)radius
|
||||
rect:(CGRect)rect
|
||||
startAngle:(CGFloat)startAngle
|
||||
endAngle:(CGFloat)endAngel
|
||||
lineWidth:(CGFloat)lineWidth {
|
||||
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
|
||||
[self.tintColor setStroke];
|
||||
[bezierPath addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2)
|
||||
radius:radius
|
||||
startAngle:startAngle
|
||||
endAngle:endAngel
|
||||
clockwise:YES];
|
||||
|
||||
bezierPath.lineWidth = lineWidth;
|
||||
[bezierPath stroke];
|
||||
}
|
||||
|
||||
@end
|
||||
46
Pods/DownloadButton/Pod/Classes/PKDownloadButton.h
generated
Normal file
46
Pods/DownloadButton/Pod/Classes/PKDownloadButton.h
generated
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// PKDownloadButton.h
|
||||
// PKDownloadButton
|
||||
//
|
||||
// Created by Pavel on 28/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "PKStopDownloadButton.h"
|
||||
#import "PKCircleProgressView.h"
|
||||
#import "PKPendingView.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, PKDownloadButtonState) {
|
||||
kPKDownloadButtonState_StartDownload,
|
||||
kPKDownloadButtonState_Pending,
|
||||
kPKDownloadButtonState_Downloading,
|
||||
kPKDownloadButtonState_Downloaded
|
||||
};
|
||||
|
||||
@class PKDownloadButton;
|
||||
|
||||
typedef void(^DownloadButtonTappedCallback)(PKDownloadButton *downloadButton, PKDownloadButtonState state);
|
||||
|
||||
@protocol PKDownloadButtonDelegate <NSObject>
|
||||
|
||||
- (void)downloadButtonTapped:(PKDownloadButton *)downloadButton
|
||||
currentState:(PKDownloadButtonState)state;
|
||||
|
||||
@end
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface PKDownloadButton : UIView
|
||||
|
||||
@property (nonatomic, weak) IBOutlet id <PKDownloadButtonDelegate> delegate;
|
||||
@property (nonatomic, copy) DownloadButtonTappedCallback callback;
|
||||
|
||||
@property (nonatomic, weak, readonly) UIButton *startDownloadButton;
|
||||
@property (nonatomic, weak, readonly) PKStopDownloadButton *stopDownloadButton;
|
||||
@property (nonatomic, weak, readonly) UIButton *downloadedButton;
|
||||
@property (nonatomic, weak, readonly) PKPendingView *pendingView;
|
||||
|
||||
@property (nonatomic, assign) PKDownloadButtonState state;
|
||||
|
||||
@end
|
||||
190
Pods/DownloadButton/Pod/Classes/PKDownloadButton.m
generated
Normal file
190
Pods/DownloadButton/Pod/Classes/PKDownloadButton.m
generated
Normal file
@ -0,0 +1,190 @@
|
||||
//
|
||||
// PKDownloadButton.m
|
||||
// PKDownloadButton
|
||||
//
|
||||
// Created by Pavel on 28/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PKDownloadButton.h"
|
||||
#import "PKMacros.h"
|
||||
#import "NSLayoutConstraint+PKDownloadButton.h"
|
||||
#import "UIImage+PKDownloadButton.h"
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
#import "PKPendingView.h"
|
||||
#import "UIButton+PKDownloadButton.h"
|
||||
|
||||
static NSDictionary *DefaultTitleAttributes() {
|
||||
return @{ NSForegroundColorAttributeName : [UIColor defaultDwonloadButtonBlueColor],
|
||||
NSFontAttributeName : [UIFont systemFontOfSize:14.f]};
|
||||
}
|
||||
|
||||
static NSDictionary *HighlitedTitleAttributes() {
|
||||
return @{ NSForegroundColorAttributeName : [UIColor whiteColor],
|
||||
NSFontAttributeName : [UIFont systemFontOfSize:14.f]};
|
||||
}
|
||||
|
||||
@interface PKDownloadButton ()
|
||||
|
||||
@property (nonatomic, weak) UIButton *startDownloadButton;
|
||||
@property (nonatomic, weak) PKStopDownloadButton *stopDownloadButton;
|
||||
@property (nonatomic, weak) UIButton *downloadedButton;
|
||||
@property (nonatomic, weak) PKPendingView *pendingView;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *stateViews;
|
||||
|
||||
- (UIButton *)createStartDownloadButton;
|
||||
- (PKStopDownloadButton *)createStopDownloadButton;
|
||||
- (UIButton *)createDownloadedButton;
|
||||
- (PKPendingView *)createPendingView;
|
||||
|
||||
- (void)currentButtonTapped:(id)sender;
|
||||
|
||||
- (void)createSubviews;
|
||||
- (NSArray *)createConstraints;
|
||||
|
||||
@end
|
||||
|
||||
static PKDownloadButton *CommonInit(PKDownloadButton *self) {
|
||||
if (self != nil) {
|
||||
[self createSubviews];
|
||||
[self addConstraints:[self createConstraints]];
|
||||
|
||||
self.state = kPKDownloadButtonState_StartDownload;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@implementation PKDownloadButton
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setState:(PKDownloadButtonState)state {
|
||||
_state = state;
|
||||
|
||||
[self.stateViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
SafeObjClassCast(UIView, view, obj);
|
||||
view.hidden = YES;
|
||||
}];
|
||||
|
||||
switch (state) {
|
||||
case kPKDownloadButtonState_StartDownload:
|
||||
self.startDownloadButton.hidden = NO;
|
||||
break;
|
||||
case kPKDownloadButtonState_Pending:
|
||||
self.pendingView.hidden = NO;
|
||||
break;
|
||||
case kPKDownloadButtonState_Downloading:
|
||||
self.stopDownloadButton.hidden = NO;
|
||||
self.stopDownloadButton.progress = 0.f;
|
||||
break;
|
||||
case kPKDownloadButtonState_Downloaded:
|
||||
self.downloadedButton.hidden = NO;
|
||||
break;
|
||||
default:
|
||||
NSAssert(NO, @"unsupported state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
return CommonInit([super initWithCoder:decoder]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return CommonInit([super initWithFrame:frame]);
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
|
||||
- (UIButton *)createStartDownloadButton {
|
||||
UIButton *startDownloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[startDownloadButton configureDefaultAppearance];
|
||||
|
||||
NSAttributedString *title = [[NSAttributedString alloc] initWithString:@"DOWNLOAD" attributes:DefaultTitleAttributes()];
|
||||
[startDownloadButton setAttributedTitle:title forState:UIControlStateNormal];
|
||||
NSAttributedString *highlitedTitle = [[NSAttributedString alloc] initWithString:@"DOWNLOAD" attributes:HighlitedTitleAttributes()];
|
||||
[startDownloadButton setAttributedTitle:highlitedTitle forState:UIControlStateHighlighted];
|
||||
|
||||
[startDownloadButton addTarget:self
|
||||
action:@selector(currentButtonTapped:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
return startDownloadButton;
|
||||
}
|
||||
|
||||
- (PKStopDownloadButton *)createStopDownloadButton {
|
||||
PKStopDownloadButton *stopDownloadButton = [[PKStopDownloadButton alloc] init];
|
||||
[stopDownloadButton.stopButton addTarget:self action:@selector(currentButtonTapped:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
return stopDownloadButton;
|
||||
}
|
||||
|
||||
- (UIButton *)createDownloadedButton {
|
||||
UIButton *downloadedButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
NSAttributedString *title = [[NSAttributedString alloc] initWithString:@"REMOVE" attributes:DefaultTitleAttributes()];
|
||||
[downloadedButton setAttributedTitle:title forState:UIControlStateNormal];
|
||||
NSAttributedString *highlitedTitle = [[NSAttributedString alloc] initWithString:@"REMOVE" attributes:HighlitedTitleAttributes()];
|
||||
[downloadedButton setAttributedTitle:highlitedTitle forState:UIControlStateHighlighted];
|
||||
[downloadedButton configureDefaultAppearance];
|
||||
|
||||
[downloadedButton addTarget:self
|
||||
action:@selector(currentButtonTapped:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
return downloadedButton;
|
||||
}
|
||||
|
||||
- (PKPendingView *)createPendingView {
|
||||
PKPendingView *pendingView = [[PKPendingView alloc] init];
|
||||
[pendingView addTarget:self action:@selector(currentButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
|
||||
return pendingView;
|
||||
}
|
||||
|
||||
- (void)currentButtonTapped:(id)sender {
|
||||
[self.delegate downloadButtonTapped:self currentState:self.state];
|
||||
BlockSafeRun(self.callback, self, self.state);
|
||||
}
|
||||
|
||||
- (void)createSubviews {
|
||||
self.stateViews = (__bridge_transfer NSMutableArray *)CFArrayCreateMutable(nil, 0, nil);
|
||||
|
||||
UIButton *startDownloadButton = [self createStartDownloadButton];
|
||||
startDownloadButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:startDownloadButton];
|
||||
self.startDownloadButton = startDownloadButton;
|
||||
[self.stateViews addObject:startDownloadButton];
|
||||
|
||||
PKStopDownloadButton *stopDownloadButton = [self createStopDownloadButton];
|
||||
stopDownloadButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:stopDownloadButton];
|
||||
self.stopDownloadButton = stopDownloadButton;
|
||||
[self.stateViews addObject:stopDownloadButton];
|
||||
|
||||
UIButton *downloadedButton = [self createDownloadedButton];
|
||||
downloadedButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:downloadedButton];
|
||||
self.downloadedButton = downloadedButton;
|
||||
[self.stateViews addObject:downloadedButton];
|
||||
|
||||
PKPendingView *pendingView = [self createPendingView];
|
||||
pendingView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:pendingView];
|
||||
self.pendingView = pendingView;
|
||||
[self.stateViews addObject:pendingView];
|
||||
}
|
||||
|
||||
- (NSArray *)createConstraints {
|
||||
NSMutableArray *constraints = [NSMutableArray array];
|
||||
|
||||
[self.stateViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
SafeObjClassCast(UIView, view, obj);
|
||||
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsForWrappedSubview:view
|
||||
withInsets:UIEdgeInsetsZero]];
|
||||
}];
|
||||
|
||||
return constraints;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
42
Pods/DownloadButton/Pod/Classes/PKMacros.h
generated
Normal file
42
Pods/DownloadButton/Pod/Classes/PKMacros.h
generated
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// PKMacros.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Download_PKMacros_h
|
||||
#define Download_PKMacros_h
|
||||
|
||||
#pragma mark - Block helpers
|
||||
|
||||
#define BlockSafeRun(block_, ...) do { if ((block_) != NULL) (block_)(__VA_ARGS__); } while (NO)
|
||||
#define BlockSafeRunEx(defaultValue_, block_, ...) (((block_) != NULL) ? (block_)(__VA_ARGS__) : (defaultValue_))
|
||||
#define BlockSafeRunOnTargetQueue(queue, block, ...) do { if ((block) != NULL) dispatch_async(queue, ^{ (block)(__VA_ARGS__); }); } while (0)
|
||||
#define BlockSafeRunOnMainQueue(block, ...) BlockSafeRunOnTargetQueue(dispatch_get_main_queue(), (block), __VA_ARGS__)
|
||||
|
||||
#if __has_feature(objc_arc)
|
||||
#define BlockWeakObject(o) __typeof__(o) __weak
|
||||
#define BlockWeakSelf BlockWeakObject(self)
|
||||
#define BlockStrongObject(o) __typeof__(o) __strong
|
||||
#define BlockStrongSelf BlockStrongObject(self)
|
||||
#define WeakifySelf BlockWeakSelf ___weakSelf___ = self; do {} while (0)
|
||||
#define StrongifySelf BlockStrongSelf self = ___weakSelf___; do {} while (0)
|
||||
|
||||
#endif // __has_feature(objc_arc)
|
||||
|
||||
#define SafeObjClassCast(destClass_, resultObj_, originalObj_) \
|
||||
destClass_ *resultObj_ = (destClass_ *)originalObj_;\
|
||||
NSAssert2((resultObj_) == nil || [(resultObj_) isKindOfClass:[destClass_ class]],\
|
||||
@"Incorrect cast: original object (%@) could not be casted to the destination class (%@)", \
|
||||
(originalObj_), NSStringFromClass([destClass_ class]))
|
||||
|
||||
#define SafeObjProtocolCast(destProtocol_, resultObj_, originalObj_) \
|
||||
id <destProtocol_> resultObj_ = (id <destProtocol_>)originalObj_;\
|
||||
NSAssert2((resultObj_) == nil || [(resultObj_) conformsToProtocol:@protocol(destProtocol_)],\
|
||||
@"Incorrect cast: original object (%@) could not be casted to the destination protocol (%@)", \
|
||||
(originalObj_), NSStringFromProtocol(@protocol(destProtocol_)))
|
||||
|
||||
|
||||
#endif // Download_PKMacros_h
|
||||
25
Pods/DownloadButton/Pod/Classes/PKPendingView.h
generated
Normal file
25
Pods/DownloadButton/Pod/Classes/PKPendingView.h
generated
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// PKPendingView.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "PKCircleView.h"
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface PKPendingView : UIControl
|
||||
|
||||
@property (nonatomic, weak, readonly) PKCircleView *circleView;
|
||||
|
||||
@property (nonatomic, assign) IBInspectable CGFloat radius;
|
||||
@property (nonatomic, assign) IBInspectable CGFloat lineWidth;
|
||||
@property (nonatomic, assign) IBInspectable CGFloat emptyLineRadians;
|
||||
@property (nonatomic, assign) IBInspectable CGFloat spinTime;
|
||||
|
||||
- (void)startSpin;
|
||||
- (void)stopSpin;
|
||||
|
||||
@end
|
||||
134
Pods/DownloadButton/Pod/Classes/PKPendingView.m
generated
Normal file
134
Pods/DownloadButton/Pod/Classes/PKPendingView.m
generated
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// PKPendingView.m
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PKPendingView.h"
|
||||
#import "NSLayoutConstraint+PKDownloadButton.h"
|
||||
#import "CALayer+PKDownloadButtonAnimations.h"
|
||||
|
||||
static NSString *const kSpinAnimationKey = @"PKSpin";
|
||||
static const CGFloat kDefaultRaduis = 13.f;
|
||||
static const CGFloat kDefaultEmptyLineRadians = 0.4f;
|
||||
static const CGFloat kDefaultSpinTime = 1.f;
|
||||
|
||||
@interface PKPendingView ()
|
||||
|
||||
@property (nonatomic, weak) PKCircleView *circleView;
|
||||
@property (nonatomic, weak) NSLayoutConstraint *width;
|
||||
@property (nonatomic, weak) NSLayoutConstraint *height;
|
||||
@property (nonatomic, assign) BOOL isSpinning;
|
||||
|
||||
- (PKCircleView *)createCircleView;
|
||||
|
||||
- (NSArray *)createConstraints;
|
||||
|
||||
@end
|
||||
|
||||
static PKPendingView *CommonInit(PKPendingView *self) {
|
||||
if (self != nil) {
|
||||
PKCircleView *circleView = [self createCircleView];
|
||||
circleView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:circleView];
|
||||
self.circleView = circleView;
|
||||
self.circleView.userInteractionEnabled = NO;
|
||||
[self addConstraints:[self createConstraints]];
|
||||
|
||||
self.emptyLineRadians = kDefaultEmptyLineRadians;
|
||||
self.radius = kDefaultRaduis;
|
||||
self.clipsToBounds = NO;
|
||||
|
||||
self.spinTime = kDefaultSpinTime;
|
||||
[self startSpin];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@implementation PKPendingView
|
||||
|
||||
#pragma mark - initialization
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
return CommonInit([super initWithCoder:decoder]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return CommonInit([super initWithFrame:frame]);
|
||||
}
|
||||
|
||||
#pragma mark - properties
|
||||
|
||||
- (void)setSpinTime:(CGFloat)spinTime {
|
||||
_spinTime = spinTime;
|
||||
[self.circleView.layer removeRotationAnimationWithKey:kSpinAnimationKey];
|
||||
if (self.isSpinning) {
|
||||
[self startSpin];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setRadius:(CGFloat)radius {
|
||||
self.width.constant = radius * 2;
|
||||
self.height.constant = radius * 2;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setLineWidth:(CGFloat)lineWidth {
|
||||
self.circleView.lineWidth = lineWidth;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (CGFloat)lineWidth {
|
||||
return self.circleView.lineWidth;
|
||||
}
|
||||
|
||||
- (void)setEmptyLineRadians:(CGFloat)emptyLineRadians {
|
||||
_emptyLineRadians = emptyLineRadians;
|
||||
self.circleView.startAngleRadians = 1.5f * M_PI + emptyLineRadians / 2.f;
|
||||
self.circleView.endAngleRadians = self.circleView.startAngleRadians + 2 * M_PI - emptyLineRadians;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)setTintColor:(UIColor *)tintColor {
|
||||
self.circleView.tintColor = tintColor;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
|
||||
- (PKCircleView *)createCircleView {
|
||||
PKCircleView *circleView = [[PKCircleView alloc] init];
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintForView:circleView
|
||||
withHeight:0.f];
|
||||
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintForView:circleView
|
||||
withWidth:0.f];
|
||||
|
||||
[circleView addConstraints:@[heightConstraint, widthConstraint]];
|
||||
|
||||
self.width = widthConstraint;
|
||||
self.height = heightConstraint;
|
||||
|
||||
return circleView;
|
||||
}
|
||||
|
||||
- (NSArray *)createConstraints {
|
||||
NSMutableArray *constraints = [NSMutableArray array];
|
||||
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsForCenterView:self.circleView
|
||||
withView:self]];
|
||||
return constraints;
|
||||
}
|
||||
|
||||
- (void)startSpin {
|
||||
self.isSpinning = YES;
|
||||
[self.circleView.layer addRotationAnimationWithKey:kSpinAnimationKey
|
||||
fullRotationDuration:self.spinTime];
|
||||
}
|
||||
|
||||
- (void)stopSpin {
|
||||
[self.circleView.layer removeRotationAnimationWithKey:kSpinAnimationKey];
|
||||
self.isSpinning = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
18
Pods/DownloadButton/Pod/Classes/PKStopDownloadButton.h
generated
Normal file
18
Pods/DownloadButton/Pod/Classes/PKStopDownloadButton.h
generated
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// PKStopDownloadButton.h
|
||||
// PKDownloadButton
|
||||
//
|
||||
// Created by Pavel on 28/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "PKCircleProgressView.h"
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface PKStopDownloadButton : PKCircleProgressView
|
||||
|
||||
@property (nonatomic, assign) IBInspectable CGFloat stopButtonWidth;
|
||||
@property (nonatomic, weak, readonly) UIButton *stopButton;
|
||||
|
||||
@end
|
||||
96
Pods/DownloadButton/Pod/Classes/PKStopDownloadButton.m
generated
Normal file
96
Pods/DownloadButton/Pod/Classes/PKStopDownloadButton.m
generated
Normal file
@ -0,0 +1,96 @@
|
||||
//
|
||||
// PKStopDownloadButton.m
|
||||
// PKDownloadButton
|
||||
//
|
||||
// Created by Pavel on 28/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PKStopDownloadButton.h"
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
#import "NSLayoutConstraint+PKDownloadButton.h"
|
||||
#import "UIImage+PKDownloadButton.h"
|
||||
|
||||
static const CGFloat kDefaultStopButtonWidth = 8.f;
|
||||
|
||||
@interface PKStopDownloadButton ()
|
||||
|
||||
@property (nonatomic, weak) UIButton *stopButton;
|
||||
|
||||
- (UIButton *)createStopButton;
|
||||
- (NSArray *)createStopButtonConstraints;
|
||||
- (PKCircleProgressView *)createCircleProgressView;
|
||||
|
||||
@end
|
||||
|
||||
static PKStopDownloadButton *CommonInit(PKStopDownloadButton *self) {
|
||||
if (self != nil) {
|
||||
UIButton *stopButton = [self createStopButton];
|
||||
stopButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:stopButton];
|
||||
self.stopButton = stopButton;
|
||||
|
||||
[self addConstraints:[self createStopButtonConstraints]];
|
||||
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@implementation PKStopDownloadButton
|
||||
|
||||
#pragma mark - properties
|
||||
|
||||
- (void)setStopButtonWidth:(CGFloat)stopButtonWidth {
|
||||
_stopButtonWidth = stopButtonWidth;
|
||||
[self.stopButton setImage:[UIImage stopImageOfSize:stopButtonWidth
|
||||
color:self.tintColor]
|
||||
forState:UIControlStateNormal];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)setTintColor:(UIColor *)tintColor {
|
||||
[super setTintColor:tintColor];
|
||||
[self.stopButton setImage:[UIImage stopImageOfSize:self.stopButtonWidth
|
||||
color:tintColor]
|
||||
forState:UIControlStateNormal];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
#pragma mark - initialization
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||
return CommonInit([super initWithCoder:decoder]);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return CommonInit([super initWithFrame:frame]);
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
|
||||
- (UIButton *)createStopButton {
|
||||
UIButton *stopButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
_stopButtonWidth = kDefaultStopButtonWidth;
|
||||
[stopButton setImage:[UIImage stopImageOfSize:_stopButtonWidth
|
||||
color:[UIColor defaultDwonloadButtonBlueColor]]
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
return stopButton;
|
||||
}
|
||||
|
||||
- (NSArray *)createStopButtonConstraints {
|
||||
NSMutableArray *constraints = [NSMutableArray array];
|
||||
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsForWrappedSubview:self.stopButton
|
||||
withInsets:UIEdgeInsetsZero]];
|
||||
|
||||
return constraints;
|
||||
}
|
||||
|
||||
- (PKCircleProgressView *)createCircleProgressView {
|
||||
PKCircleProgressView *circleProgressView = [[PKCircleProgressView alloc] init];
|
||||
|
||||
return circleProgressView;
|
||||
}
|
||||
|
||||
@end
|
||||
16
Pods/DownloadButton/Pod/Classes/UIButton+PKDownloadButton.h
generated
Normal file
16
Pods/DownloadButton/Pod/Classes/UIButton+PKDownloadButton.h
generated
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// UIButton+PKDownloadButton.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 01/06/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIButton (PKDownloadButton)
|
||||
|
||||
- (void)configureDefaultAppearance;
|
||||
- (void)cleanDefaultAppearance;
|
||||
|
||||
@end
|
||||
31
Pods/DownloadButton/Pod/Classes/UIButton+PKDownloadButton.m
generated
Normal file
31
Pods/DownloadButton/Pod/Classes/UIButton+PKDownloadButton.m
generated
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// UIButton+PKDownloadButton.m
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 01/06/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIButton+PKDownloadButton.h"
|
||||
#import "UIImage+PKDownloadButton.h"
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
|
||||
@implementation UIButton (PKDownloadButton)
|
||||
|
||||
- (void)configureDefaultAppearance {
|
||||
UIImage *backImage = [UIImage buttonBackgroundWithColor:[UIColor defaultDwonloadButtonBlueColor]];
|
||||
[self setBackgroundImage:[backImage resizableImageWithCapInsets:UIEdgeInsetsMake(15.f, 15.f, 15.f, 15.f)]
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
[self setBackgroundImage:[UIImage highlitedButtonBackgroundWithColor:[UIColor defaultDwonloadButtonBlueColor]]
|
||||
forState:UIControlStateHighlighted];
|
||||
}
|
||||
|
||||
- (void)cleanDefaultAppearance {
|
||||
[self setBackgroundImage:nil forState:UIControlStateNormal];
|
||||
[self setBackgroundImage:nil forState:UIControlStateHighlighted];
|
||||
[self setAttributedTitle:nil forState:UIControlStateNormal];
|
||||
[self setAttributedTitle:nil forState:UIControlStateHighlighted];
|
||||
}
|
||||
|
||||
@end
|
||||
16
Pods/DownloadButton/Pod/Classes/UIColor+PKDownloadButton.h
generated
Normal file
16
Pods/DownloadButton/Pod/Classes/UIColor+PKDownloadButton.h
generated
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// UIColor+PKDownloadButton.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIColor (PKDownloadButton)
|
||||
|
||||
+ (UIColor *)defaultDwonloadButtonBlueColor;
|
||||
+ (UIColor *)defaultDwonloadButtonRedColor;
|
||||
|
||||
@end
|
||||
21
Pods/DownloadButton/Pod/Classes/UIColor+PKDownloadButton.m
generated
Normal file
21
Pods/DownloadButton/Pod/Classes/UIColor+PKDownloadButton.m
generated
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// UIColor+PKDownloadButton.m
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 30/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
|
||||
@implementation UIColor (PKDownloadButton)
|
||||
|
||||
+ (UIColor *)defaultDwonloadButtonBlueColor {
|
||||
return [UIColor colorWithRed:0.f green:113.f / 255.f blue:1.f alpha:1.f];
|
||||
}
|
||||
|
||||
+ (UIColor *)defaultDwonloadButtonRedColor {
|
||||
return [UIColor redColor];
|
||||
}
|
||||
|
||||
@end
|
||||
17
Pods/DownloadButton/Pod/Classes/UIImage+PKDownloadButton.h
generated
Normal file
17
Pods/DownloadButton/Pod/Classes/UIImage+PKDownloadButton.h
generated
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// UIImage+PKDownloadButton.h
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 31/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIImage (PKDownloadButton)
|
||||
|
||||
+ (UIImage *)stopImageOfSize:(CGFloat)size color:(UIColor *)color;
|
||||
+ (UIImage *)buttonBackgroundWithColor:(UIColor *)color;
|
||||
+ (UIImage *)highlitedButtonBackgroundWithColor:(UIColor *)color;
|
||||
|
||||
@end
|
||||
67
Pods/DownloadButton/Pod/Classes/UIImage+PKDownloadButton.m
generated
Normal file
67
Pods/DownloadButton/Pod/Classes/UIImage+PKDownloadButton.m
generated
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// UIImage+PKDownloadButton.m
|
||||
// Download
|
||||
//
|
||||
// Created by Pavel on 31/05/15.
|
||||
// Copyright (c) 2015 Katunin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIImage+PKDownloadButton.h"
|
||||
|
||||
@implementation UIImage (PKDownloadButton)
|
||||
|
||||
+ (UIImage *)stopImageOfSize:(CGFloat)size color:(UIColor *)color {
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size, size), NO, 1.0f);
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
[color setStroke];
|
||||
|
||||
CGRect stopImageRect = CGRectMake(0.f, 0.f, size, size);
|
||||
CGContextSetFillColorWithColor(context, color.CGColor);
|
||||
CGContextAddRect(context, stopImageRect);
|
||||
CGContextFillRect(context, stopImageRect);
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
UIGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (UIImage *)buttonBackgroundWithColor:(UIColor *)color {
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(30.f, 30.f), NO, 0.0f);
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
[color setStroke];
|
||||
|
||||
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(2.f, 2.f, 26.f, 26.f)
|
||||
cornerRadius:4.f];
|
||||
CGContextSetStrokeColorWithColor(context, color.CGColor);
|
||||
bezierPath.lineWidth = 1.f;
|
||||
[bezierPath stroke];
|
||||
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
UIGraphicsEndImageContext();
|
||||
return [image resizableImageWithCapInsets:UIEdgeInsetsMake(10.f, 10.f, 10.f, 10.f)];
|
||||
}
|
||||
|
||||
+ (UIImage *)highlitedButtonBackgroundWithColor:(UIColor *)color {
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(30.f, 30.f), NO, 0.0f);
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
[color setStroke];
|
||||
|
||||
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(2.f, 2.f, 26.f, 26.f)
|
||||
cornerRadius:4.f];
|
||||
CGContextSetStrokeColorWithColor(context, color.CGColor);
|
||||
bezierPath.lineWidth = 1.f;
|
||||
[bezierPath stroke];
|
||||
[color setFill];
|
||||
[bezierPath fill];
|
||||
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
UIGraphicsEndImageContext();
|
||||
return [image resizableImageWithCapInsets:UIEdgeInsetsMake(10.f, 10.f, 10.f, 10.f)];
|
||||
}
|
||||
|
||||
@end
|
||||
129
Pods/DownloadButton/README.md
generated
Normal file
129
Pods/DownloadButton/README.md
generated
Normal file
@ -0,0 +1,129 @@
|
||||
# DownloadButton
|
||||
|
||||
[](https://travis-ci.org/Pavel Katunin/DownloadButton)
|
||||
[](http://cocoapods.org/pods/DownloadButton)
|
||||
[](http://cocoapods.org/pods/DownloadButton)
|
||||
[](http://cocoapods.org/pods/DownloadButton)
|
||||
|
||||
Customizable appstore style download button.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Customizable designable components. Editing with IB.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
To run the example project, clone the repo, and run `pod install` from the Example directory first.
|
||||
Check example project to see usage.
|
||||
|
||||
```objective-c
|
||||
#import <DownloadButton/PKDownloadButton.h>
|
||||
```
|
||||
|
||||
Usage for representing network operations:
|
||||
|
||||
```objective-c
|
||||
#pragma mark - PKDownloadButtonDelegate
|
||||
|
||||
- (void)downloadButtonTapped:(PKDownloadButton *)downloadButton
|
||||
currentState:(PKDownloadButtonState)state {
|
||||
switch (state) {
|
||||
case kPKDownloadButtonState_StartDownload:
|
||||
self.downloadButton.state = kPKDownloadButtonState_Pending;
|
||||
[self.pendingSimulator startDownload];
|
||||
break;
|
||||
case kPKDownloadButtonState_Pending:
|
||||
[self.pendingSimulator cancelDownload];
|
||||
self.downloadButton.state = kPKDownloadButtonState_StartDownload;
|
||||
break;
|
||||
case kPKDownloadButtonState_Downloading:
|
||||
[self.downloaderSimulator cancelDownload];
|
||||
self.downloadButton.state = kPKDownloadButtonState_StartDownload;
|
||||
break;
|
||||
case kPKDownloadButtonState_Downloaded:
|
||||
self.downloadButton.state = kPKDownloadButtonState_StartDownload;
|
||||
self.imageView.hidden = YES;
|
||||
break;
|
||||
default:
|
||||
NSAssert(NO, @"unsupported state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - DownloaderSimulatorDelegate
|
||||
|
||||
- (void)simulator:(PKDownloaderSimulator *)simulator didUpdateProgress:(double)progress {
|
||||
if (simulator == self.pendingSimulator) {
|
||||
if (progress == 1.) {
|
||||
self.downloadButton.state = kPKDownloadButtonState_Downloading;
|
||||
[self.downloaderSimulator startDownload];
|
||||
}
|
||||
}
|
||||
else if (simulator == self.downloaderSimulator) {
|
||||
self.downloadButton.stopDownloadButton.progress = progress;
|
||||
if (progress == 1) {
|
||||
self.downloadButton.state = kPKDownloadButtonState_Downloaded;
|
||||
self.imageView.hidden = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Appearance customization:
|
||||
|
||||
```objective-c
|
||||
|
||||
#import "UIImage+PKDownloadButton.h"
|
||||
#import "UIButton+PKDownloadButton.h"
|
||||
|
||||
[self.downloadButton.downloadedButton cleanDefaultAppearance];
|
||||
[self.downloadButton.downloadedButton setBackgroundImage:[UIImage buttonBackgroundWithColor:[UIColor redColor]]
|
||||
forState:UIControlStateNormal];
|
||||
[self.downloadButton.downloadedButton setBackgroundImage:[UIImage highlitedButtonBackgroundWithColor:[UIColor redColor]]
|
||||
forState:UIControlStateHighlighted];
|
||||
[self.downloadButton.downloadedButton setTitle:@"delete" forState:UIControlStateNormal];
|
||||
[self.downloadButton.downloadedButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
|
||||
[self.downloadButton.downloadedButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
|
||||
|
||||
self.downloadButton.stopDownloadButton.tintColor = [UIColor blackColor];
|
||||
self.downloadButton.stopDownloadButton.filledLineStyleOuter = YES;
|
||||
|
||||
self.downloadButton.pendingView.tintColor = [UIColor orangeColor];
|
||||
self.downloadButton.pendingView.radius = 24.f;
|
||||
self.downloadButton.pendingView.emptyLineRadians = 2.f;
|
||||
self.downloadButton.pendingView.spinTime = 3.f;
|
||||
|
||||
[self.downloadButton.startDownloadButton cleanDefaultAppearance];
|
||||
[self.downloadButton.startDownloadButton setImage:[UIImage imageNamed:@"download_default"] forState:UIControlStateNormal];
|
||||
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
Requires iOS SDK version > 8.0
|
||||
|
||||
## Installation
|
||||
|
||||
DownloadButton is available through [CocoaPods](http://cocoapods.org). To install
|
||||
it, simply add the following line to your Podfile:
|
||||
|
||||
```ruby
|
||||
pod "DownloadButton"
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
Pavel Katunin, wk.katunin@gmail.com
|
||||
|
||||
## License
|
||||
|
||||
DownloadButton is available under the Apache License, Version 2.0. See the LICENSE file for more info.
|
||||
6
Pods/Manifest.lock
generated
6
Pods/Manifest.lock
generated
@ -1,5 +1,6 @@
|
||||
PODS:
|
||||
- Alamofire (5.9.1)
|
||||
- DownloadButton (0.1.0)
|
||||
- FreeStreamer (4.0.0):
|
||||
- Reachability (~> 3.0)
|
||||
- IQKeyboardManagerSwift (6.5.16)
|
||||
@ -17,6 +18,7 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- Alamofire
|
||||
- DownloadButton
|
||||
- FreeStreamer
|
||||
- IQKeyboardManagerSwift
|
||||
- JXPagingView/Paging
|
||||
@ -31,6 +33,7 @@ DEPENDENCIES:
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Alamofire
|
||||
- DownloadButton
|
||||
- FreeStreamer
|
||||
- IQKeyboardManagerSwift
|
||||
- JXPagingView
|
||||
@ -45,6 +48,7 @@ SPEC REPOS:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
|
||||
DownloadButton: 49a21a89e0d7d1b42d9134f79aaa40e727cd57c3
|
||||
FreeStreamer: 7e9c976045701ac2f7e9c14c17245203c37bf2ea
|
||||
IQKeyboardManagerSwift: 12d89768845bb77b55cc092ecc2b1f9370f06b76
|
||||
JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e
|
||||
@ -57,6 +61,6 @@ SPEC CHECKSUMS:
|
||||
SwiftDate: 72d28954e8e1c6c1c0f917ccc8005e4f83c7d4b2
|
||||
Tiercel: c0a73f876a72800333b15f4e7e48791f4ad21e90
|
||||
|
||||
PODFILE CHECKSUM: 3804949e23587f6d341ef21aa5e0b1c55a818968
|
||||
PODFILE CHECKSUM: 0b090feb210ab3fcc05329c1820f94cdb8cf93f6
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
|
||||
5819
Pods/Pods.xcodeproj/project.pbxproj
generated
5819
Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
26
Pods/Target Support Files/DownloadButton/DownloadButton-Info.plist
generated
Normal file
26
Pods/Target Support Files/DownloadButton/DownloadButton-Info.plist
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${CURRENT_PROJECT_VERSION}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
5
Pods/Target Support Files/DownloadButton/DownloadButton-dummy.m
generated
Normal file
5
Pods/Target Support Files/DownloadButton/DownloadButton-dummy.m
generated
Normal file
@ -0,0 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_DownloadButton : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_DownloadButton
|
||||
@end
|
||||
12
Pods/Target Support Files/DownloadButton/DownloadButton-prefix.pch
generated
Normal file
12
Pods/Target Support Files/DownloadButton/DownloadButton-prefix.pch
generated
Normal file
@ -0,0 +1,12 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
27
Pods/Target Support Files/DownloadButton/DownloadButton-umbrella.h
generated
Normal file
27
Pods/Target Support Files/DownloadButton/DownloadButton-umbrella.h
generated
Normal file
@ -0,0 +1,27 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#import "CALayer+PKDownloadButtonAnimations.h"
|
||||
#import "NSLayoutConstraint+PKDownloadButton.h"
|
||||
#import "PKCircleProgressView.h"
|
||||
#import "PKCircleView.h"
|
||||
#import "PKDownloadButton.h"
|
||||
#import "PKMacros.h"
|
||||
#import "PKPendingView.h"
|
||||
#import "PKStopDownloadButton.h"
|
||||
#import "UIButton+PKDownloadButton.h"
|
||||
#import "UIColor+PKDownloadButton.h"
|
||||
#import "UIImage+PKDownloadButton.h"
|
||||
|
||||
FOUNDATION_EXPORT double DownloadButtonVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char DownloadButtonVersionString[];
|
||||
|
||||
13
Pods/Target Support Files/DownloadButton/DownloadButton.debug.xcconfig
generated
Normal file
13
Pods/Target Support Files/DownloadButton/DownloadButton.debug.xcconfig
generated
Normal file
@ -0,0 +1,13 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DownloadButton
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/DownloadButton
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
6
Pods/Target Support Files/DownloadButton/DownloadButton.modulemap
generated
Normal file
6
Pods/Target Support Files/DownloadButton/DownloadButton.modulemap
generated
Normal file
@ -0,0 +1,6 @@
|
||||
framework module DownloadButton {
|
||||
umbrella header "DownloadButton-umbrella.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
13
Pods/Target Support Files/DownloadButton/DownloadButton.release.xcconfig
generated
Normal file
13
Pods/Target Support Files/DownloadButton/DownloadButton.release.xcconfig
generated
Normal file
@ -0,0 +1,13 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DownloadButton
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/DownloadButton
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
24
Pods/Target Support Files/DownloadButton/ResourceBundle-DownloadButton-DownloadButton-Info.plist
generated
Normal file
24
Pods/Target Support Files/DownloadButton/ResourceBundle-DownloadButton-DownloadButton-Info.plist
generated
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -24,6 +24,29 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
## DownloadButton
|
||||
|
||||
Copyright (c) 2015 Pavel Katunin <wk.katunin@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Contact details
|
||||
|
||||
Email: wk.katunin@gmail.com
|
||||
Site: https://ru.linkedin.com/in/pavelkatunin
|
||||
|
||||
## FreeStreamer
|
||||
|
||||
Copyright (c) 2011-2018 Matias Muhonen <mmu@iki.fi> 穆马帝
|
||||
|
||||
@ -41,6 +41,35 @@ THE SOFTWARE.
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2015 Pavel Katunin <wk.katunin@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Contact details
|
||||
|
||||
Email: wk.katunin@gmail.com
|
||||
Site: https://ru.linkedin.com/in/pavelkatunin</string>
|
||||
<key>License</key>
|
||||
<string>Apache License, Version 2.0</string>
|
||||
<key>Title</key>
|
||||
<string>DownloadButton</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2011-2018 Matias Muhonen <mmu@iki.fi> 穆马帝
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
${PODS_ROOT}/Target Support Files/Pods-MusicPlayer/Pods-MusicPlayer-frameworks.sh
|
||||
${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework
|
||||
${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework
|
||||
${BUILT_PRODUCTS_DIR}/FreeStreamer/FreeStreamer.framework
|
||||
${BUILT_PRODUCTS_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework
|
||||
${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FreeStreamer.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IQKeyboardManagerSwift.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXPagingView.framework
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
${PODS_ROOT}/Target Support Files/Pods-MusicPlayer/Pods-MusicPlayer-frameworks.sh
|
||||
${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework
|
||||
${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework
|
||||
${BUILT_PRODUCTS_DIR}/FreeStreamer/FreeStreamer.framework
|
||||
${BUILT_PRODUCTS_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework
|
||||
${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FreeStreamer.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IQKeyboardManagerSwift.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXPagingView.framework
|
||||
|
||||
@ -177,6 +177,7 @@ code_sign_if_enabled() {
|
||||
|
||||
if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/FreeStreamer/FreeStreamer.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework"
|
||||
@ -191,6 +192,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
fi
|
||||
if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/FreeStreamer/FreeStreamer.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/DownloadButton" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer/FreeStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView/JXPagingView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView/JXSegmentedView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel/Tiercel.framework/Headers" $(SDKROOT)/usr/include/libxml2
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DownloadButton/DownloadButton.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer/FreeStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView/JXPagingView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView/JXSegmentedView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel/Tiercel.framework/Headers" $(SDKROOT)/usr/include/libxml2
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"swiftCoreGraphics" -l"xml2" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreGraphics" -framework "Foundation" -framework "FreeStreamer" -framework "IQKeyboardManagerSwift" -framework "JXPagingView" -framework "JXSegmentedView" -framework "Kingfisher" -framework "MJRefresh" -framework "MediaPlayer" -framework "QuartzCore" -framework "Reachability" -framework "SVProgressHUD" -framework "SnapKit" -framework "SwiftDate" -framework "SystemConfiguration" -framework "Tiercel" -framework "UIKit" -weak_framework "Combine" -weak_framework "SwiftUI"
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"swiftCoreGraphics" -l"xml2" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreGraphics" -framework "DownloadButton" -framework "Foundation" -framework "FreeStreamer" -framework "IQKeyboardManagerSwift" -framework "JXPagingView" -framework "JXSegmentedView" -framework "Kingfisher" -framework "MJRefresh" -framework "MediaPlayer" -framework "QuartzCore" -framework "Reachability" -framework "SVProgressHUD" -framework "SnapKit" -framework "SwiftDate" -framework "SystemConfiguration" -framework "Tiercel" -framework "UIKit" -weak_framework "Combine" -weak_framework "SwiftUI"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/DownloadButton" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer/FreeStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView/JXPagingView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView/JXSegmentedView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel/Tiercel.framework/Headers" $(SDKROOT)/usr/include/libxml2
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DownloadButton/DownloadButton.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FreeStreamer/FreeStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView/JXPagingView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXSegmentedView/JXSegmentedView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Tiercel/Tiercel.framework/Headers" $(SDKROOT)/usr/include/libxml2
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"swiftCoreGraphics" -l"xml2" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreGraphics" -framework "Foundation" -framework "FreeStreamer" -framework "IQKeyboardManagerSwift" -framework "JXPagingView" -framework "JXSegmentedView" -framework "Kingfisher" -framework "MJRefresh" -framework "MediaPlayer" -framework "QuartzCore" -framework "Reachability" -framework "SVProgressHUD" -framework "SnapKit" -framework "SwiftDate" -framework "SystemConfiguration" -framework "Tiercel" -framework "UIKit" -weak_framework "Combine" -weak_framework "SwiftUI"
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"swiftCoreGraphics" -l"xml2" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreGraphics" -framework "DownloadButton" -framework "Foundation" -framework "FreeStreamer" -framework "IQKeyboardManagerSwift" -framework "JXPagingView" -framework "JXSegmentedView" -framework "Kingfisher" -framework "MJRefresh" -framework "MediaPlayer" -framework "QuartzCore" -framework "Reachability" -framework "SVProgressHUD" -framework "SnapKit" -framework "SwiftDate" -framework "SystemConfiguration" -framework "Tiercel" -framework "UIKit" -weak_framework "Combine" -weak_framework "SwiftUI"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user