南鑫林 5 lat temu
rodzic
commit
eb59afa6e3
15 zmienionych plików z 832 dodań i 82 usunięć
  1. 28 0
      RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj
  2. 11 8
      RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseTabbarViewController.swift
  3. 14 13
      RainbowPlanet/RainbowPlanet/Modules/CommunityModule/Community/ViewController/Main/CommunityViewController.swift
  4. 156 0
      RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLAssetsCollection.swift
  5. 322 0
      RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLPHAsset.swift
  6. 220 0
      RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLPhotoLibrary.swift
  7. 36 0
      RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLPhotoPickerConfigure.swift
  8. 1 1
      RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/PublishNewAlbumCollocationTableView/PublishNewAlbumCollocationView.swift
  9. 4 4
      RainbowPlanet/RainbowPlanet/Service/SwiftMoyaService/SwiftMoyaServiceManger/SwiftMoyaNetWorkManager/ApiMacro.swift
  10. 6 0
      RainbowPlanet/RainbowPlanet/Tools/Extension/Extension+Array.swift
  11. 19 0
      RainbowPlanet/RainbowPlanet/Tools/Extension/Extension+PHFetchOptions.swift
  12. 15 0
      RainbowPlanet/RainbowPlanet/Tools/Extension/Extension+UIImage.swift
  13. 0 25
      RainbowPlanet/RainbowPlanet/Tools/TLPhotoPicker/TLAssetCollection+Extension.swift
  14. 0 21
      RainbowPlanet/RainbowPlanet/Tools/TLPhotoPicker/TLAssetsCollection.swift
  15. 0 10
      RainbowPlanet/RainbowPlanet/Tools/TLPhotoPicker/TLPhotoLibrary.swift

+ 28 - 0
RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj

@@ -409,6 +409,11 @@
 		A7C3DD1A226422BF00FA262E /* SwiftMoyaServiceSMSApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C3DD19226422BF00FA262E /* SwiftMoyaServiceSMSApi.swift */; };
 		A7C3DD1C226422D200FA262E /* SwiftMoyaNetWorkServiceSMS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C3DD1B226422D200FA262E /* SwiftMoyaNetWorkServiceSMS.swift */; };
 		A7CA33FB2383888F009B0C40 /* PublishNewAlbumTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA33FA2383888F009B0C40 /* PublishNewAlbumTableView.swift */; };
+		A7CA33FE238398DB009B0C40 /* NXLPhotoLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA33FD238398DB009B0C40 /* NXLPhotoLibrary.swift */; };
+		A7CA340023839917009B0C40 /* NXLPHAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA33FF23839917009B0C40 /* NXLPHAsset.swift */; };
+		A7CA340223839B28009B0C40 /* NXLAssetsCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA340123839B28009B0C40 /* NXLAssetsCollection.swift */; };
+		A7CA34042383C119009B0C40 /* Extension+PHFetchOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA34032383C119009B0C40 /* Extension+PHFetchOptions.swift */; };
+		A7CA34062383C1C9009B0C40 /* NXLPhotoPickerConfigure.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA34052383C1C9009B0C40 /* NXLPhotoPickerConfigure.swift */; };
 		A7CC19B52382678E0053B4B5 /* PublishNewAlbumView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CC19B42382678E0053B4B5 /* PublishNewAlbumView.swift */; };
 		A7CC19B8238270940053B4B5 /* PublishNewAlbumNavigationBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CC19B7238270940053B4B5 /* PublishNewAlbumNavigationBarView.swift */; };
 		A7CC19BA238270D30053B4B5 /* PublishNewAlbumPreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CC19B9238270D30053B4B5 /* PublishNewAlbumPreView.swift */; };
@@ -1198,6 +1203,11 @@
 		A7C3DD19226422BF00FA262E /* SwiftMoyaServiceSMSApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaServiceSMSApi.swift; sourceTree = "<group>"; };
 		A7C3DD1B226422D200FA262E /* SwiftMoyaNetWorkServiceSMS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaNetWorkServiceSMS.swift; sourceTree = "<group>"; };
 		A7CA33FA2383888F009B0C40 /* PublishNewAlbumTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublishNewAlbumTableView.swift; sourceTree = "<group>"; };
+		A7CA33FD238398DB009B0C40 /* NXLPhotoLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NXLPhotoLibrary.swift; sourceTree = "<group>"; };
+		A7CA33FF23839917009B0C40 /* NXLPHAsset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NXLPHAsset.swift; sourceTree = "<group>"; };
+		A7CA340123839B28009B0C40 /* NXLAssetsCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NXLAssetsCollection.swift; sourceTree = "<group>"; };
+		A7CA34032383C119009B0C40 /* Extension+PHFetchOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+PHFetchOptions.swift"; sourceTree = "<group>"; };
+		A7CA34052383C1C9009B0C40 /* NXLPhotoPickerConfigure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NXLPhotoPickerConfigure.swift; sourceTree = "<group>"; };
 		A7CC19B42382678E0053B4B5 /* PublishNewAlbumView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublishNewAlbumView.swift; sourceTree = "<group>"; };
 		A7CC19B7238270940053B4B5 /* PublishNewAlbumNavigationBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublishNewAlbumNavigationBarView.swift; sourceTree = "<group>"; };
 		A7CC19B9238270D30053B4B5 /* PublishNewAlbumPreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublishNewAlbumPreView.swift; sourceTree = "<group>"; };
@@ -2327,6 +2337,7 @@
 				A72A729222321DE000B21995 /* Extension+String.swift */,
 				A72A728E22321DE000B21995 /* Extension+NSRange.swift */,
 				A72A729122321DE000B21995 /* Extension+Array.swift */,
+				A7CA34032383C119009B0C40 /* Extension+PHFetchOptions.swift */,
 				A72A729022321DE000B21995 /* Extension+UserDefaults.swift */,
 				A72A729D22321DE000B21995 /* Extension+Date.swift */,
 				A72A729E22321DE000B21995 /* Extension+CAGradientLayer.swift */,
@@ -4088,6 +4099,17 @@
 			path = PublishNewAlbumCollocationTableView;
 			sourceTree = "<group>";
 		};
+		A7CA33FC23839880009B0C40 /* NXLPhotoPicker */ = {
+			isa = PBXGroup;
+			children = (
+				A7CA33FD238398DB009B0C40 /* NXLPhotoLibrary.swift */,
+				A7CA33FF23839917009B0C40 /* NXLPHAsset.swift */,
+				A7CA340123839B28009B0C40 /* NXLAssetsCollection.swift */,
+				A7CA34052383C1C9009B0C40 /* NXLPhotoPickerConfigure.swift */,
+			);
+			path = NXLPhotoPicker;
+			sourceTree = "<group>";
+		};
 		A7CC19B623826FC60053B4B5 /* PublishNewAlbumView */ = {
 			isa = PBXGroup;
 			children = (
@@ -4095,6 +4117,7 @@
 				A7CC19B7238270940053B4B5 /* PublishNewAlbumNavigationBarView.swift */,
 				A7CC19B9238270D30053B4B5 /* PublishNewAlbumPreView.swift */,
 				A7CA33F923838354009B0C40 /* PublishNewAlbumCollocationTableView */,
+				A7CA33FC23839880009B0C40 /* NXLPhotoPicker */,
 			);
 			path = PublishNewAlbumView;
 			sourceTree = "<group>";
@@ -6627,6 +6650,7 @@
 				A7AA9F6722C640F10086498B /* CommunityRecommendFeedModel.swift in Sources */,
 				A7824B082271F53A00ABA381 /* EditSetDefaultTableViewCell.swift in Sources */,
 				A7811C98231F503800C2D8DE /* CommunityRecommnendSuperViewController.swift in Sources */,
+				A7CA34042383C119009B0C40 /* Extension+PHFetchOptions.swift in Sources */,
 				A7EE5AEA236C131D00309931 /* PublishNewVideoPhotoSetView.swift in Sources */,
 				A7811C89231ACC3900C2D8DE /* OtherPersonalCenterReportView.swift in Sources */,
 				A77F2CC3223203BA001BD3F6 /* AppDelegate+Window.swift in Sources */,
@@ -6643,6 +6667,7 @@
 				A77FAEF6235844BC002A1D08 /* CircleCommentListCommentTableViewCell.swift in Sources */,
 				A7FF1DAA23753A16002B3435 /* PublishEditNewEffectFilterView.swift in Sources */,
 				A7EE5AF2236C131D00309931 /* PublishNewEffectFilterCollectionViewCell.swift in Sources */,
+				A7CA34062383C1C9009B0C40 /* NXLPhotoPickerConfigure.swift in Sources */,
 				A7C0FDF322B65E5400BC1E86 /* FeaturedTopicsTableViewCell.swift in Sources */,
 				A770E61322D6625700CBD0A4 /* ShareCommunityViewCollectionViewCell.swift in Sources */,
 				A7F577D722FED3A100E2D757 /* PathManager.swift in Sources */,
@@ -6697,6 +6722,7 @@
 				A7F689002356F2A6000C313F /* CircleUserListTableViewCell.swift in Sources */,
 				A72623D722C26A2A00AEF875 /* MessageListModel.swift in Sources */,
 				A7FF1598228D092A00A85748 /* OrderListModel.swift in Sources */,
+				A7CA340223839B28009B0C40 /* NXLAssetsCollection.swift in Sources */,
 				A76068E222E44D6A008DF18F /* SheetSureView.swift in Sources */,
 				A7C0FDFB22B6672F00BC1E86 /* PopularVideoTableViewCell.swift in Sources */,
 				A797FDEB22C5AC6A0076DCB3 /* CacheManager.swift in Sources */,
@@ -6853,6 +6879,7 @@
 				A70E3F30236FF9530039D7FC /* PublishConfirmPhotoNewViewController.swift in Sources */,
 				A76068E722E48DC5008DF18F /* BrowsePictureRouterModuleType.swift in Sources */,
 				A70E3F40236FF9CD0039D7FC /* AliyunVodUpToYoPublishModel.swift in Sources */,
+				A7CA340023839917009B0C40 /* NXLPHAsset.swift in Sources */,
 				BD12B66922B47D4800AEB10B /* RecommendSubCommentTableViewCell.swift in Sources */,
 				A784F2B32350337D00E49140 /* ShareH5LinkView.swift in Sources */,
 				A7931E1822AFC1DF00297D0A /* CommunityFollowViewController.swift in Sources */,
@@ -6902,6 +6929,7 @@
 				BD61226122C3561C00D3F513 /* MagicCameraPressCircleView.m in Sources */,
 				A7EE5B0A236C13B900309931 /* AliPlayerManager.swift in Sources */,
 				A7AA9F5822C5F6150086498B /* SwiftMoyaServiceVirusApi.swift in Sources */,
+				A7CA33FE238398DB009B0C40 /* NXLPhotoLibrary.swift in Sources */,
 				A7284A542252FB5C000BAEC4 /* PaginationModel.swift in Sources */,
 				A77BB4672329EF7300DCAE32 /* NXLPermissionContacts.swift in Sources */,
 				A7C2567622CCB38D00420828 /* HeightModel.swift in Sources */,

+ 11 - 8
RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseTabbarViewController.swift

@@ -38,12 +38,15 @@ class BaseTabbarViewController: UITabBarController {
     
     override func viewDidLoad() {
         delegate = self
-        if #available(iOS 13.0, *) {
-            tabBar.standardAppearance.configureWithOpaqueBackground()
-            tabBar.standardAppearance.backgroundImage = UIImage.imageWithColor(color: UIColor.white)
-            tabBar.standardAppearance.shadowImage = UIImage(named: "navbar_shadow_pic_down")
+        tabBar.layer.shadowOpacity = 0.1
+        if #available(iOS 13, *) {
+            let appearance = tabBar.standardAppearance.copy()
+            appearance.backgroundImage = UIImage.imageWithColor(color: UIColor.white)
+            appearance.shadowImage = UIImage.imageWithColor(color: UIColor.clear)
+            tabBar.standardAppearance = appearance
         } else {
-            tabBar.shadowImage = UIImage(named: "navbar_shadow_pic_down")
+            tabBar.backgroundImage = UIImage.imageWithColor(color: UIColor.white)
+            tabBar.shadowImage = UIImage.imageWithColor(color: UIColor.clear)
         }
         
         /// 社区
@@ -90,10 +93,10 @@ class BaseTabbarViewController: UITabBarController {
         if !AliyunVodUpToyoPublishManager.shared.isUploading { // 是否正在上传中
             PublishNewPopView.show(imageStrs: ["publish_btn_picture","publish_btn_video","publish_btn_photo","publish_btn_article"], titles: ["相册","视频","拍照","文章"], columnCount: 4) { [weak self] (index) in
                 if index != 3 {
-//                    let pickVc = PublishViewController()
-//                    pickVc.index = index
-                    let  pickVc = PublishNewViewController()
+                    let pickVc = PublishViewController()
                     pickVc.index = index
+//                    let  pickVc = PublishNewViewController()
+//                    pickVc.index = index
                     let nav = BaseNavigationViewController.init(rootViewController: pickVc)
                     nav.modalPresentationStyle = .fullScreen
                     self?.present(nav, animated: true, completion: nil)

+ 14 - 13
RainbowPlanet/RainbowPlanet/Modules/CommunityModule/Community/ViewController/Main/CommunityViewController.swift

@@ -65,10 +65,10 @@ class CommunityViewController: BaseViewController {
         navigationBar.isHidden = true
         view.addSubview(segmentedView)
         view.addSubview(listContainerView)
-//        listContainerView.addSubview(publishUploadProgressView)
-//        listContainerView.bringSubviewToFront(publishUploadProgressView)
-        listContainerView.addSubview(publishManagerUploadView)
-        listContainerView.bringSubviewToFront(publishManagerUploadView)
+        listContainerView.addSubview(publishUploadProgressView)
+        listContainerView.bringSubviewToFront(publishUploadProgressView)
+//        listContainerView.addSubview(publishManagerUploadView)
+//        listContainerView.bringSubviewToFront(publishManagerUploadView)
 
         view.addSubview(communityNavigationBarView)
         
@@ -92,15 +92,16 @@ class CommunityViewController: BaseViewController {
             make.top.equalTo(segmentedView.snp.bottom)
             make.left.right.bottom.equalToSuperview()
         }
-//        publishUploadProgressView.snp.makeConstraints { (make) in
-//            make.top.left.right.equalToSuperview()
-//             make.height.equalTo(62)
-//        }
         
-        publishManagerUploadView.snp.makeConstraints { (make) in
+        publishUploadProgressView.snp.makeConstraints { (make) in
             make.top.left.right.equalToSuperview()
              make.height.equalTo(62)
         }
+        
+//        publishManagerUploadView.snp.makeConstraints { (make) in
+//            make.top.left.right.equalToSuperview()
+//             make.height.equalTo(62)
+//        }
 
 
     }
@@ -213,10 +214,10 @@ class CommunityViewController: BaseViewController {
         // 待发布
         observe = NotificationCenter.default.addObserver(forName: NSNotification.Name("DismissFromPublishEditVc"), object: nil, queue: OperationQueue.main) {[weak self] (notification) in
             self?.reloadSegmentedFollowView()
-//            let aliyunVodUpToYoPublishModel = notification.object as? AliyunVodUpToYoPublishModel
-//            self?.publishUploadProgressView.aliyunVodUpToYoPublishModel = aliyunVodUpToYoPublishModel
-            let publishManagerModel = notification.object as? PublishManagerModel
-            self?.publishManagerUploadView.publishManagerModel = publishManagerModel
+            let aliyunVodUpToYoPublishModel = notification.object as? AliyunVodUpToYoPublishModel
+            self?.publishUploadProgressView.aliyunVodUpToYoPublishModel = aliyunVodUpToYoPublishModel
+//            let publishManagerModel = notification.object as? PublishManagerModel
+//            self?.publishManagerUploadView.publishManagerModel = publishManagerModel
 
         }
         

+ 156 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLAssetsCollection.swift

@@ -0,0 +1,156 @@
+//
+//  NXLAssetsCollection.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/11/19.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import UIKit
+
+public enum PHFetchedResultGroupedBy {
+    case year
+    case month
+    case week
+    case day
+    case hour
+    case custom(dateFormat: String)
+    var dateFormat: String {
+        switch self {
+        case .year:
+            return "yyyy"
+        case .month:
+            return "yyyyMM"
+        case .week:
+            return "yyyyMMW"
+        case .day:
+            return "yyyyMMdd"
+        case .hour:
+            return "yyyyMMddHH"
+        case let .custom(dateFormat):
+            return dateFormat
+        }
+    }
+}
+
+struct NXLAssetsCollection {
+    
+    /// 资源列表
+    var phAssetCollection: PHAssetCollection? = nil
+    
+    /// 取得结果PHAsset
+    var fetchResult: PHFetchResult<PHAsset>? = nil
+    
+    /// 是否是使用相机
+    var isUseCameraButton: Bool = false
+    
+    /// 最近点
+    var recentPosition: CGPoint = CGPoint.zero
+    
+    /// 标题
+    var title: String
+    
+    /// 本地标识符
+    var localIdentifier: String
+    
+    /// 分区
+    var sections: [(title: String, assets: [NXLPHAsset])]? = nil
+    
+    /// 数量
+    var count: Int {
+        get {
+            guard let count = self.fetchResult?.count, count > 0 else { return self.isUseCameraButton ? 1 : 0 }
+            return count + (self.isUseCameraButton ? 1 : 0)
+        }
+    }
+    
+    /// 初始化
+    /// - Parameter collection: 资源
+    init(collection: PHAssetCollection) {
+        self.phAssetCollection = collection
+        self.title = collection.localizedTitle ?? ""
+        self.localIdentifier = collection.localIdentifier
+    }
+    
+    static func ==(lhs: NXLAssetsCollection, rhs: NXLAssetsCollection) -> Bool {
+        return lhs.localIdentifier == rhs.localIdentifier
+    }
+    
+    
+    /// 获取PHAsset
+    /// - Parameter index: 指定的资源
+    func getAsset(at index: Int) -> PHAsset? {
+        if self.isUseCameraButton && index == 0 { return nil }
+        let index = index - (self.isUseCameraButton ? 1 : 0)
+        guard let result = self.fetchResult, index < result.count else { return nil }
+        return result.object(at: max(index,0))
+    }
+    
+    /// 获取NXLPHAsset
+    /// - Parameter indexPath: 指定的资源
+    func getTLAsset(at indexPath: IndexPath) -> NXLPHAsset? {
+        let isCameraRow = self.isUseCameraButton && indexPath.section == 0 && indexPath.row == 0
+        if isCameraRow { return nil }
+        if let sections = self.sections {
+            let index = indexPath.row - ((self.isUseCameraButton && indexPath.section == 0) ? 1 : 0)
+            let result = sections[safe: indexPath.section]
+            return result?.assets[safe: index]
+        }else {
+            var index = indexPath.row
+            index = index - (self.isUseCameraButton ? 1 : 0)
+            guard let result = self.fetchResult, index < result.count else { return nil }
+            return NXLPHAsset(asset: result.object(at: max(index,0)))
+        }
+    }
+    
+    /// 重新加载分区
+    /// - Parameter groupedBy: 分区类型
+    mutating func reloadSection(groupedBy: PHFetchedResultGroupedBy) {
+        var groupedSections = self.section(groupedBy: groupedBy)
+        if self.isUseCameraButton {
+            groupedSections.insert(("camera",[NXLPHAsset(asset: nil)]), at: 0)
+        }
+        self.sections = groupedSections
+    }
+    
+}
+
+extension NXLAssetsCollection {
+    
+    
+    /// 遍历获取的结果
+    /// - Parameter groupedBy: 分组类型
+    func enumarateFetchResult(groupedBy: PHFetchedResultGroupedBy) -> Dictionary<String,[NXLPHAsset]> {
+        let dateFormatter = DateFormatter()
+        dateFormatter.dateFormat = groupedBy.dateFormat
+        var assets = [PHAsset]()
+        assets.reserveCapacity(self.fetchResult?.count ?? 0)
+        self.fetchResult?.enumerateObjects({ (phAsset, idx, stop) in
+            if phAsset.creationDate != nil {
+                assets.append(phAsset)
+            }
+        })
+        let sections = Dictionary(grouping: assets.map{ NXLPHAsset(asset: $0) }) { (element) -> String in
+            if let creationDate = element.phAsset?.creationDate {
+                let identifier = dateFormatter.string(from: creationDate)
+                return identifier
+            }
+            return ""
+        }
+        return sections
+    }
+    
+    /// 获取分区
+    /// - Parameter groupedBy: 分区类型
+    func section(groupedBy: PHFetchedResultGroupedBy) -> [(String,[NXLPHAsset])] {
+        let dict = enumarateFetchResult(groupedBy: groupedBy)
+        var sections = [(String,[NXLPHAsset])]()
+        let sortedKeys = dict.keys.sorted(by: >)
+        for key in sortedKeys {
+            if let array = dict[key] {
+                sections.append((key, array))
+            }
+        }
+        return sections
+    }
+}

+ 322 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLPHAsset.swift

@@ -0,0 +1,322 @@
+//
+//  NXLAssetsCollection.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/11/19.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import UIKit
+import Photos
+import PhotosUI
+import MobileCoreServices
+
+public struct NXLPHAsset {
+    
+    /// 云端下载状态
+    enum CloudDownloadState {
+        case ready, progress, complete, failed
+    }
+    
+    /// 资源类型
+    public enum AssetType {
+        case photo, video, livePhoto
+    }
+    
+    /// 图片后缀
+    public enum ImageExtType: String {
+        case png, jpg, gif, heic
+    }
+    
+    
+    /// 云端下载状态
+    var state = CloudDownloadState.ready
+    
+    /// 资源
+    var phAsset: PHAsset? = nil
+    
+    /// 是否选中相机
+    var isSelectedFromCamera = false
+    
+    /// 选中的订单
+    var selectedOrder: Int = 0
+    
+    /// 资源类型
+    var type: AssetType {
+        get {
+            guard let phAsset = self.phAsset else { return .photo }
+            if phAsset.mediaSubtypes.contains(.photoLive) {
+                return .livePhoto
+            }else if phAsset.mediaType == .video {
+                return .video
+            }else {
+                return .photo
+            }
+        }
+    }
+    
+    init(asset: PHAsset?) {
+        phAsset = asset
+    }
+    
+    static func asset(with localIdentifier: String) -> NXLPHAsset? {
+        let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil)
+        return NXLPHAsset(asset: fetchResult.firstObject)
+    }
+    
+    /// 全分辨率图像
+    var fullResolutionImage: UIImage? {
+        get {
+            guard let phAsset = self.phAsset else { return nil }
+            return NXLPhotoLibrary.fullResolutionImageData(asset: phAsset)
+        }
+    }
+    
+    /// 原始文件名
+    var originalFileName: String? {
+        get {
+            guard let phAsset = self.phAsset,let resource = PHAssetResource.assetResources(for: phAsset).first else { return nil }
+            return resource.originalFilename
+        }
+    }
+    
+    /// 图片后缀类型
+    func extType() -> ImageExtType {
+        var ext = ImageExtType.png
+        if let fileName = self.originalFileName, let extention = URL(string: fileName)?.pathExtension.lowercased() {
+            ext = ImageExtType(rawValue: extention) ?? .png
+        }
+        return ext
+    }
+    
+    /// 图片size
+    /// - Parameters:
+    ///   - options: 图像请求选项
+    ///   - completion: 完成回调
+    ///   - livePhotoVideoSize: 是否livePhotoView
+    func photoSize(options: PHImageRequestOptions? = nil ,completion: @escaping ((Int)->Void), livePhotoVideoSize: Bool = false) {
+        guard let phAsset = self.phAsset, self.type == .photo || self.type == .livePhoto else { completion(-1); return }
+        var resource: PHAssetResource? = nil
+        if phAsset.mediaSubtypes.contains(.photoLive) == true, livePhotoVideoSize {
+            resource = PHAssetResource.assetResources(for: phAsset).filter { $0.type == .pairedVideo }.first
+        }else {
+            resource = PHAssetResource.assetResources(for: phAsset).filter { $0.type == .photo }.first
+        }
+        if let fileSize = resource?.value(forKey: "fileSize") as? Int {
+            completion(fileSize)
+        }else {
+            PHImageManager.default().requestImageData(for: phAsset, options: nil) { (data, uti, orientation, info) in
+                var fileSize = -1
+                if let data = data {
+                    let bcf = ByteCountFormatter()
+                    bcf.countStyle = .file
+                    fileSize = data.count
+                }
+                DispatchQueue.main.async {
+                    completion(fileSize)
+                }
+            }
+        }
+    }
+    
+    
+    /// 视频size
+    /// - Parameters:
+    ///   - options: 视频请求选项
+    ///   - completion: 完成回调
+    public func videoSize(options: PHVideoRequestOptions? = nil, completion: @escaping ((Int)->Void)) {
+        guard let phAsset = self.phAsset, self.type == .video else {  completion(-1); return }
+        let resource = PHAssetResource.assetResources(for: phAsset).filter { $0.type == .video }.first
+        if let fileSize = resource?.value(forKey: "fileSize") as? Int {
+            completion(fileSize)
+        }else {
+            PHImageManager.default().requestAVAsset(forVideo: phAsset, options: options) { (avasset, audioMix, info) in
+                func fileSize(_ url: URL?) -> Int? {
+                    do {
+                        guard let fileSize = try url?.resourceValues(forKeys: [.fileSizeKey]).fileSize else { return nil }
+                        return fileSize
+                    }catch { return nil }
+                }
+                var url: URL? = nil
+                if let urlAsset = avasset as? AVURLAsset {
+                    url = urlAsset.url
+                }else if let sandboxKeys = info?["PHImageFileSandboxExtensionTokenKey"] as? String, let path = sandboxKeys.components(separatedBy: ";").last {
+                    url = URL(fileURLWithPath: path)
+                }
+                let size = fileSize(url) ?? -1
+                DispatchQueue.main.async {
+                    completion(size)
+                }
+            }
+        }
+    }
+    
+    /// MIMEType
+    /// - Parameter url: URL
+    func MIMEType(_ url: URL?) -> String? {
+        guard let ext = url?.pathExtension else { return nil }
+        if !ext.isEmpty {
+            let UTIRef = UTTypeCreatePreferredIdentifierForTag("public.filename-extension" as CFString, ext as CFString, nil)
+            let UTI = UTIRef?.takeUnretainedValue()
+            UTIRef?.release()
+            if let UTI = UTI {
+                guard let MIMETypeRef = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType) else { return nil }
+                let MIMEType = MIMETypeRef.takeUnretainedValue()
+                MIMETypeRef.release()
+                return MIMEType as String
+            }
+        }
+        return nil
+    }
+    
+    
+    /// 临时复制媒体文件
+    /// - Parameters:
+    ///   - videoRequestOptions: 视频请求选项
+    ///   - imageRequestOptions: 图片请求选项
+    ///   - exportPreset: 出口预设
+    ///   - convertLivePhotosToJPG:将实时照片转换为JPG /false : If you want mov file at live photos / true  : If you want png file at live photos ( HEIC )
+    ///   - progressBlock: 进度回调
+    ///   - completionBlock: 完成回调
+    @discardableResult
+    public func tempCopyMediaFile(videoRequestOptions: PHVideoRequestOptions? = nil, imageRequestOptions: PHImageRequestOptions? = nil, exportPreset: String = AVAssetExportPresetHighestQuality, convertLivePhotosToJPG: Bool = false, progressBlock:((Double) -> Void)? = nil, completionBlock:@escaping ((URL,String) -> Void)) -> PHImageRequestID? {
+        guard let phAsset = self.phAsset else { return nil }
+        var type: PHAssetResourceType? = nil
+        if phAsset.mediaSubtypes.contains(.photoLive) == true, convertLivePhotosToJPG == false {
+            type = .pairedVideo
+        }else {
+            type = phAsset.mediaType == .video ? .video : .photo
+        }
+        guard let resource = (PHAssetResource.assetResources(for: phAsset).filter{ $0.type == type }).first else { return nil }
+        let fileName = resource.originalFilename
+        var writeURL: URL? = nil
+        if #available(iOS 10.0, *) {
+            writeURL = FileManager.default.temporaryDirectory.appendingPathComponent("\(fileName)")
+        } else {
+            writeURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent("\(fileName)")
+        }
+        if (writeURL?.pathExtension.uppercased() == "HEIC" || writeURL?.pathExtension.uppercased() == "HEIF") && convertLivePhotosToJPG {
+            if let fileName2 = writeURL?.deletingPathExtension().lastPathComponent {
+                writeURL?.deleteLastPathComponent()
+                writeURL?.appendPathComponent("\(fileName2).jpg")
+            }
+        }
+        guard let localURL = writeURL,let mimetype = MIMEType(writeURL) else { return nil }
+        switch phAsset.mediaType {
+        case .video:
+            var requestOptions = PHVideoRequestOptions()
+            if let options = videoRequestOptions {
+                requestOptions = options
+            }else {
+                requestOptions.isNetworkAccessAllowed = true
+            }
+            //iCloud download progress
+            requestOptions.progressHandler = { (progress, error, stop, info) in
+                DispatchQueue.main.async {
+                    progressBlock?(progress)
+                }
+            }
+            return PHImageManager.default().requestExportSession(forVideo: phAsset, options: requestOptions, exportPreset: exportPreset) { (session, infoDict) in
+                session?.outputURL = localURL
+                session?.outputFileType = AVFileType.mov
+                session?.exportAsynchronously(completionHandler: {
+                    DispatchQueue.main.async {
+                        completionBlock(localURL, mimetype)
+                    }
+                })
+            }
+        case .image:
+            var requestOptions = PHImageRequestOptions()
+            if let options = imageRequestOptions {
+                requestOptions = options
+            }else {
+                requestOptions.isNetworkAccessAllowed = true
+            }
+            //iCloud download progress
+            requestOptions.progressHandler = { (progress, error, stop, info) in
+                DispatchQueue.main.async {
+                    progressBlock?(progress)
+                }
+            }
+            return PHImageManager.default().requestImageData(for: phAsset, options: requestOptions, resultHandler: { (data, uti, orientation, info) in
+                do {
+                    var data = data
+                    let needConvertLivePhotoToJPG = phAsset.mediaSubtypes.contains(.photoLive) == true && convertLivePhotosToJPG == true
+                    if needConvertLivePhotoToJPG, let imgData = data, let rawImage = UIImage(data: imgData)?.upOrientationImage() {
+                        data = rawImage.jpegData(compressionQuality: 1)
+                    }
+                    try data?.write(to: localURL)
+                    DispatchQueue.main.async {
+                        completionBlock(localURL, mimetype)
+                    }
+                }catch { }
+            })
+        default:
+            return nil
+        }
+    }
+    
+    /// 视频文件名
+    /// - Parameter phAsset: 资源
+    func videoFilename(phAsset: PHAsset) -> URL? {
+        guard let resource = (PHAssetResource.assetResources(for: phAsset).filter{ $0.type == .video }).first else {
+            return nil
+        }
+        var writeURL: URL?
+        let fileName = resource.originalFilename
+        if #available(iOS 10.0, *) {
+            writeURL = FileManager.default.temporaryDirectory.appendingPathComponent("\(fileName)")
+        } else {
+            writeURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent("\(fileName)")
+        }
+        return writeURL
+    }
+    
+    /// 导出视频文件
+    /// - Parameters:
+    ///   - options: 视频请求选项
+    ///   - outputURL: 输出网址
+    ///   - outputFileType: 输出文件类型
+    ///   - progressBlock: 进度回调
+    ///   - completionBlock: 完成回调
+    func exportVideoFile(options: PHVideoRequestOptions? = nil, outputURL: URL? = nil, outputFileType: AVFileType = .mov, progressBlock:((Double) -> Void)? = nil, completionBlock:@escaping ((URL,String) -> Void)) {
+        guard
+            let phAsset = self.phAsset,
+            phAsset.mediaType == .video,
+            let writeURL = outputURL ?? videoFilename(phAsset: phAsset),
+            let mimetype = MIMEType(writeURL)
+            else {
+                return
+        }
+        var requestOptions = PHVideoRequestOptions()
+        if let options = options {
+            requestOptions = options
+        }else {
+            requestOptions.isNetworkAccessAllowed = true
+        }
+        requestOptions.progressHandler = { (progress, error, stop, info) in
+            DispatchQueue.main.async {
+                progressBlock?(progress)
+            }
+        }
+        PHImageManager.default().requestAVAsset(forVideo: phAsset, options: requestOptions) { (avasset, avaudioMix, infoDict) in
+            guard let avasset = avasset else {
+                return
+            }
+            let exportSession = AVAssetExportSession.init(asset: avasset, presetName: AVAssetExportPresetHighestQuality)
+            exportSession?.outputURL = writeURL
+            exportSession?.outputFileType = outputFileType
+            exportSession?.exportAsynchronously(completionHandler: {
+                completionBlock(writeURL, mimetype)
+            })
+        }
+    }
+    
+}
+
+extension NXLPHAsset: Equatable {
+    public static func ==(lhs: NXLPHAsset, rhs: NXLPHAsset) -> Bool {
+        guard let lphAsset = lhs.phAsset, let rphAsset = rhs.phAsset else { return false }
+        return lphAsset.localIdentifier == rphAsset.localIdentifier
+    }
+}

+ 220 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLPhotoLibrary.swift

@@ -0,0 +1,220 @@
+//
+//  NXLPhotoLibrary.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/11/19.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import UIKit
+import Photos
+
+protocol NXLPhotoLibraryDelegate: class {
+    
+    /// 加载相机
+    func loadCameraRollCollection(collection: NXLAssetsCollection)
+    
+    /// 加载全部资源
+    func loadCompleteAllCollection(collections: [NXLAssetsCollection])
+}
+
+/// 类型
+class NXLPhotoLibrary {
+    
+    deinit {
+        NXLLog("deinit")
+    }
+    
+    weak var delegate: NXLPhotoLibraryDelegate? = nil
+
+    /// 图片管理器
+    lazy var imageManager: PHCachingImageManager = {
+        return PHCachingImageManager()
+    }()
+    
+    /// videoAsset
+    /// - Parameters:
+    ///   - asset: 资源
+    ///   - size: 资源打下
+    ///   - progressBlock: 加载进度
+    ///   - completionBlock: 完成回调
+    @discardableResult
+    func videoAsset(asset: PHAsset, size: CGSize = CGSize(width: 720, height: 1280), progressBlock: Photos.PHAssetImageProgressHandler? = nil, completionBlock:@escaping (AVPlayerItem?, [AnyHashable : Any]?) -> Void ) -> PHImageRequestID {
+        let options = PHVideoRequestOptions()
+        options.isNetworkAccessAllowed = true
+        options.deliveryMode = .automatic
+        options.progressHandler = progressBlock
+        let requestID = self.imageManager.requestPlayerItem(forVideo: asset, options: options, resultHandler: { playerItem, info in
+            completionBlock(playerItem,info)
+        })
+        return requestID
+    }
+    
+    /// livePhotoAsset
+    /// - Parameters:
+    ///   - asset: 资源
+    ///   - size: 资源打下
+    ///   - progressBlock: 加载进度
+    ///   - completionBlock: 完成回调
+    @discardableResult
+    func livePhotoAsset(asset: PHAsset, size: CGSize = CGSize(width: 720, height: 1280), progressBlock: Photos.PHAssetImageProgressHandler? = nil, completionBlock:@escaping (PHLivePhoto,Bool)-> Void ) -> PHImageRequestID {
+        let options = PHLivePhotoRequestOptions()
+        options.deliveryMode = .opportunistic
+        options.isNetworkAccessAllowed = true
+        options.progressHandler = progressBlock
+        let scale = min(UIScreen.main.scale,2)
+        let targetSize = CGSize(width: size.width*scale, height: size.height*scale)
+        let requestID = self.imageManager.requestLivePhoto(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { (livePhoto, info) in
+            let complete = (info?["PHImageResultIsDegradedKey"] as? Bool) == false
+            if let livePhoto = livePhoto {
+                completionBlock(livePhoto,complete)
+            }
+        }
+        return requestID
+    }
+    
+    /// imageAsset
+    /// - Parameters:
+    ///   - asset: 资源
+    ///   - size: 资源打下
+    ///   - progressBlock: 加载进度
+    ///   - completionBlock: 完成回调
+    @discardableResult
+    func imageAsset(asset: PHAsset, size: CGSize = CGSize(width: 160, height: 160), options: PHImageRequestOptions? = nil, completionBlock:@escaping (UIImage,Bool)-> Void ) -> PHImageRequestID {
+        var options = options
+        if options == nil {
+            options = PHImageRequestOptions()
+            options?.isSynchronous = false
+            options?.resizeMode = .exact
+            options?.deliveryMode = .opportunistic
+            options?.isNetworkAccessAllowed = true
+        }
+        let scale = min(UIScreen.main.scale,2)
+        let targetSize = CGSize(width: size.width*scale, height: size.height*scale)
+        let requestID = self.imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { image, info in
+            let complete = (info?["PHImageResultIsDegradedKey"] as? Bool) == false
+            if let image = image {
+                completionBlock(image,complete)
+            }
+        }
+        return requestID
+    }
+    
+    /// 取消加载
+    /// - Parameter requestID: 图片ID
+    func cancelPHImageRequest(requestID: PHImageRequestID) {
+        self.imageManager.cancelImageRequest(requestID)
+    }
+    
+    /// 下载云端图片
+    /// - Parameters:
+    ///   - asset: 资源
+    ///   - size: 图片打下
+    ///   - progressBlock: 下载进度
+    ///   - completionBlock: 完成回调
+    @discardableResult
+    class func cloudImageDownload(asset: PHAsset, size: CGSize = PHImageManagerMaximumSize, progressBlock: @escaping (Double) -> Void, completionBlock:@escaping (UIImage?)-> Void ) -> PHImageRequestID {
+        let options = PHImageRequestOptions()
+        options.isSynchronous = false
+        options.isNetworkAccessAllowed = true
+        options.deliveryMode = .opportunistic
+        options.version = .current
+        options.resizeMode = .exact
+        options.progressHandler = { (progress,error,stop,info) in
+            progressBlock(progress)
+        }
+        let requestID = PHCachingImageManager().requestImageData(for: asset, options: options) { (imageData, dataUTI, orientation, info) in
+            if let data = imageData,let _ = info {
+                completionBlock(UIImage(data: data))
+            }else{
+                completionBlock(nil)//error
+            }
+        }
+        return requestID
+    }
+    
+    /// 全分辨率图像
+    /// - Parameter asset: 资源
+    @discardableResult
+    class func fullResolutionImageData(asset: PHAsset) -> UIImage? {
+        let options = PHImageRequestOptions()
+        options.isSynchronous = true
+        options.resizeMode = .none
+        options.isNetworkAccessAllowed = true
+        options.version = .current
+        var image: UIImage? = nil
+        _ = PHCachingImageManager().requestImageData(for: asset, options: options) { (imageData, dataUTI, orientation, info) in
+            if let data = imageData {
+                image = UIImage(data: data)
+            }
+        }
+        return image
+    }
+    
+}
+
+extension NXLPhotoLibrary {
+    
+    /// 获取提取的设置
+    /// - Parameter configure: NXLPhotoPickerConfigure
+    func getOption(configure: NXLPhotoPickerConfigure) -> PHFetchOptions {
+        
+        /// 是否提取设置
+        let options: PHFetchOptions
+        if let fetchOption = configure.fetchOption {
+            options = fetchOption
+        }else {
+            options = PHFetchOptions()
+            options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
+        }
+        
+        /// 类型
+        if let mediaType = configure.mediaType {
+            let mediaPredicate = NSPredicate(format: "mediaType = %i", mediaType.rawValue)
+            options.merge(predicate: mediaPredicate)
+        }
+        
+        /// 是否允许视频
+        if configure.isAllowedVideo == false {
+            let notVideoPredicate = NSPredicate(format: "mediaType != %i", PHAssetMediaType.video.rawValue)
+            options.merge(predicate: notVideoPredicate)
+        }
+        
+        /// 是否允许图片
+        if configure.isAllowedPhotos == false {
+            let notVideoPredicate = NSPredicate(format: "mediaType != %i", PHAssetMediaType.image.rawValue)
+            options.merge(predicate: notVideoPredicate)
+        }
+        
+        /// 是否允许是图片
+        if configure.isAllowedLivePhotos == false {
+            let notLivePhotoPredicate = NSPredicate(format: "NOT ((mediaSubtype & %d) != 0)", PHAssetMediaSubtype.photoLive.rawValue)
+            options.merge(predicate: notLivePhotoPredicate)
+        }
+        
+        /// 最大时长
+        if let maxVideoDuration = configure.maxVideoDuration {
+            let durationPredicate = NSPredicate(format: "duration < %f", maxVideoDuration)
+            options.merge(predicate: durationPredicate)
+        }
+        
+        /// 最小时长
+        if let minVideoDuration = configure.minVideoDuration {
+            let durationPredicate = NSPredicate(format: "duration >= %f", minVideoDuration)
+            options.merge(predicate: durationPredicate)
+        }
+        return options
+    }
+    
+    
+    /// 提取结果
+    /// - Parameters:
+    ///   - collection: 资源
+    ///   - configure: NXLPhotoPickerConfigure
+    func fetchResult(collection: NXLAssetsCollection?, configure: NXLPhotoPickerConfigure) -> PHFetchResult<PHAsset>? {
+        guard let phAssetCollection = collection?.phAssetCollection else { return nil }
+        let options = getOption(configure: configure)
+        return PHAsset.fetchAssets(in: phAssetCollection, options: options)
+    }
+    
+}

+ 36 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/NXLPhotoPicker/NXLPhotoPickerConfigure.swift

@@ -0,0 +1,36 @@
+//
+//  NXLPhotoPickerConfigure.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/11/19.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import Foundation
+
+struct NXLPhotoPickerConfigure {
+    /// 是否总是视频
+    var isAllowedVideo : Bool? = nil
+    
+    /// 是否总是照片
+    var isAllowedPhotos : Bool? = nil
+    
+    /// 是否总是实时照片
+    var isAllowedLivePhotos : Bool? = nil
+    
+    /// 是否是使用相机
+    var isUsedCamera: Bool? = true
+    
+    /// 提取设置
+    var fetchOption: PHFetchOptions? = nil
+    
+    ///显示类型 unknown, image, video, audio
+    var mediaType: PHAssetMediaType? = nil
+    
+    /// 最大时长
+    var maxVideoDuration:TimeInterval? = nil
+    
+    /// 最小时长
+    var minVideoDuration:TimeInterval? = nil
+    
+}

+ 1 - 1
RainbowPlanet/RainbowPlanet/Modules/PublishNewModule/PublishNew/View/PublishNewAlbumView/PublishNewAlbumCollocationTableView/PublishNewAlbumCollocationView.swift

@@ -19,7 +19,7 @@ class PublishNewAlbumCollocationView: BaseView {
     /// 是否总是照片
     var isAllowedPhotos : Bool? = nil
     
-    /// 是否总是动态照片
+    /// 是否总是实时照片
     var isAllowedLivePhotos : Bool? = nil
     
     /// 是否使用预取

+ 4 - 4
RainbowPlanet/RainbowPlanet/Service/SwiftMoyaService/SwiftMoyaServiceManger/SwiftMoyaNetWorkManager/ApiMacro.swift

@@ -1,14 +1,14 @@
 /// Service
 let kPersonalService = false
 let kDevelopSever = false
-let kBetaSever = true
-let kProductSever = false
+let kBetaSever = false
+let kProductSever = true
 
 /// H5Service
 let kH5PersonalService = false
 let kH5DevelopSever = false
-let kH5BetaSever = true
-let kH5ProductSever = false
+let kH5BetaSever = false
+let kH5ProductSever = true
 
 // MARK: - 数据服务器
 public func kApiDataPrefix() -> String {

+ 6 - 0
RainbowPlanet/RainbowPlanet/Tools/Extension/Extension+Array.swift

@@ -54,3 +54,9 @@ extension Array {
     }
     
 }
+
+extension Array {
+    subscript (safe index: Int) -> Element? {
+        return indices ~= index ? self[index] : nil
+    }
+}

+ 19 - 0
RainbowPlanet/RainbowPlanet/Tools/Extension/Extension+PHFetchOptions.swift

@@ -0,0 +1,19 @@
+//
+//  Extension+PHFetchOptions.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/11/19.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import Foundation
+
+extension PHFetchOptions {
+    func merge(predicate: NSPredicate) {
+        if let storePredicate = self.predicate {
+            self.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [storePredicate, predicate])
+        }else {
+            self.predicate = predicate
+        }
+    }
+}

+ 15 - 0
RainbowPlanet/RainbowPlanet/Tools/Extension/Extension+UIImage.swift

@@ -294,3 +294,18 @@ extension UIImage {
     }
 }
 
+extension UIImage {
+    func upOrientationImage() -> UIImage? {
+        switch imageOrientation {
+        case .up:
+            return self
+        default:
+            UIGraphicsBeginImageContextWithOptions(size, false, scale)
+            draw(in: CGRect(origin: .zero, size: size))
+            let result = UIGraphicsGetImageFromCurrentImageContext()
+            UIGraphicsEndImageContext()
+            return result
+        }
+    }
+}
+

+ 0 - 25
RainbowPlanet/RainbowPlanet/Tools/TLPhotoPicker/TLAssetCollection+Extension.swift

@@ -8,31 +8,6 @@
 import Foundation
 import Photos
 
-public enum PHFetchedResultGroupedBy {
-    case year
-    case month
-    case week
-    case day
-    case hour
-    case custom(dateFormat: String)
-    var dateFormat: String {
-        switch self {
-        case .year:
-            return "yyyy"
-        case .month:
-            return "yyyyMM"
-        case .week:
-            return "yyyyMMW"
-        case .day:
-            return "yyyyMMdd"
-        case .hour:
-            return "yyyyMMddHH"
-        case let .custom(dateFormat):
-            return dateFormat
-        }
-    }
-}
-
 extension TLAssetsCollection {
     func enumarateFetchResult(groupedBy: PHFetchedResultGroupedBy) -> Dictionary<String,[TLPHAsset]> {
         let dateFormatter = DateFormatter()

+ 0 - 21
RainbowPlanet/RainbowPlanet/Tools/TLPhotoPicker/TLAssetsCollection.swift

@@ -290,12 +290,6 @@ extension TLPHAsset: Equatable {
     }
 }
 
-extension Array {
-    subscript (safe index: Int) -> Element? {
-        return indices ~= index ? self[index] : nil
-    }
-}
-
 public struct TLAssetsCollection {
     var phAssetCollection: PHAssetCollection? = nil
     var fetchResult: PHFetchResult<PHAsset>? = nil
@@ -366,18 +360,3 @@ public struct TLAssetsCollection {
         return lhs.localIdentifier == rhs.localIdentifier
     }
 }
-
-extension UIImage {
-    func upOrientationImage() -> UIImage? {
-        switch imageOrientation {
-        case .up:
-            return self
-        default:
-            UIGraphicsBeginImageContextWithOptions(size, false, scale)
-            draw(in: CGRect(origin: .zero, size: size))
-            let result = UIGraphicsGetImageFromCurrentImageContext()
-            UIGraphicsEndImageContext()
-            return result
-        }
-    }
-}

+ 0 - 10
RainbowPlanet/RainbowPlanet/Tools/TLPhotoPicker/TLPhotoLibrary.swift

@@ -118,16 +118,6 @@ class TLPhotoLibrary {
     }
 }
 
-extension PHFetchOptions {
-    func merge(predicate: NSPredicate) {
-        if let storePredicate = self.predicate {
-            self.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [storePredicate, predicate])
-        }else {
-            self.predicate = predicate
-        }
-    }
-}
-
 //MARK: - Load Collection
 extension TLPhotoLibrary {
     func getOption(configure: TLPhotosPickerConfigure) -> PHFetchOptions {