فهرست منبع

Merge branch 'master' of https://git.yishihui.com/iOS/Introduce
合并代码

jsonwang 3 سال پیش
والد
کامیت
58c2e2cfee

+ 4 - 4
Introduce.xcodeproj/project.pbxproj

@@ -425,7 +425,7 @@
 				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 0.51;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = UH52C8A7SN;
 				ENABLE_BITCODE = NO;
 				EXCLUDED_ARCHS = "";
@@ -455,7 +455,7 @@
 				SWIFT_OBJC_BRIDGING_HEADER = "Introduce/Record/Introduce-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 1;
+				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Debug;
 		};
@@ -468,7 +468,7 @@
 				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 0.51;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = UH52C8A7SN;
 				ENABLE_BITCODE = NO;
 				EXCLUDED_ARCHS = "";
@@ -497,7 +497,7 @@
 				SWIFT_EMIT_LOC_STRINGS = YES;
 				SWIFT_OBJC_BRIDGING_HEADER = "Introduce/Record/Introduce-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 1;
+				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Release;
 		};

+ 1 - 1
Introduce/Aarchitecture/AppDelegate.swift

@@ -38,7 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         // 热启动重新生成SubSesstionId
         isEnterBack = true
         PQSingletoMemoryUtil.shared.createSubSesstionId()
-        BFConfig.shared.subSessionId = getUniqueId(desc: "subSessionid")
+        BFConfig.shared.subSessionId = PQSingletoMemoryUtil.shared.subSessionid
     }
 
     func application(_: UIApplication, supportedInterfaceOrientationsFor _: UIWindow?) -> UIInterfaceOrientationMask {

BIN
Introduce/Assets.xcassets/Export/export_saveonly_h.imageset/export_saveonly_h@3x.png


BIN
Introduce/Assets.xcassets/Export/export_saveonly_n.imageset/export_saveonly_n@3x.png


+ 33 - 0
Introduce/Record/INAppConfigUtil.swift

@@ -28,15 +28,24 @@ class INAppConfigUtil: NSObject {
         BFConfig.shared.hiddenMusicMask = false
         BFConfig.shared.otherTintColor = UIColor.hexColor(hexadecimal: "#333333")
         BFConfig.shared.statusBarStyle = .light
+        PQSingletoMemoryUtil.shared.createSesstionId()
+        BFConfig.shared.sessionId = PQSingletoMemoryUtil.shared.sessionId
+        BFConfig.shared.subSessionId = PQSingletoMemoryUtil.shared.sessionId
     }
 
     class func applicationConfig(launchOptions _: [UIApplication.LaunchOptionsKey: Any]?) {
         // 初始化友盟 61c3e145e0f9bb492ba6e4e4
         registerUM(umAppkey: "61c3e145e0f9bb492ba6e4e4")
+        // 初始化Bugly
+        registerBugly(appID: "80af5e913c", deviceId: getMachineCode())
         // 冷热启动上报
         appLaunchReportUpload()
     }
 
+    /// 初始化友盟
+    /// - Parameters:
+    ///   - umAppkey: <#umAppkey description#>
+    ///   - channel: <#channel description#>
     class func registerUM(umAppkey: String, channel: String = "AppStore") {
         #if DEBUG
             UMConfigure.setLogEnabled(true)
@@ -48,6 +57,30 @@ class INAppConfigUtil: NSObject {
         #endif
     }
 
+    /// 初始化Bugly
+    /// - Parameters:
+    ///   - appID: <#appID description#>
+    ///   - channel: <#channel description#>
+    ///   - deviceId: <#deviceId description#>
+    class func registerBugly(appID: String, channel: String = "AppStore", deviceId: String? = nil) {
+        let versionName = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "1.0.0")"
+        // 注册bugly
+        let buglyConfig = BuglyConfig()
+        buglyConfig.reportLogLevel = .warn
+        #if DEBUG
+            buglyConfig.version = versionName + ".6666"
+            buglyConfig.debugMode = true
+        #else
+            buglyConfig.version = versionName + "." + versionCode
+        #endif
+        buglyConfig.channel = channel
+        buglyConfig.deviceIdentifier = deviceId ?? ""
+        buglyConfig.unexpectedTerminatingDetectionEnable = true
+        buglyConfig.blockMonitorEnable = true
+        buglyConfig.blockMonitorTimeout = 2
+        Bugly.start(withAppId: appID, config: buglyConfig)
+    }
+
     // 冷热启动上报
     class func appLaunchReportUpload(isHotLaunch: Bool = false) {
         // 冷启动

+ 7 - 0
Introduce/Record/INIntroduceController.swift

@@ -118,6 +118,13 @@ class INIntroduceController: BFBaseViewController {
     }
 
     @objc func exportAction() {
+        if recordScreenVC.itemModels.count == 1
+            && recordScreenVC.itemModels[0].mediaType == .IMAGE
+            && recordScreenVC.itemModels[0].voiceStickers.count == 0{
+            cShowHUB(superView: nil, msg: "开局一张图也要编些话吧:)")
+            return
+        }
+        
         recordScreenVC.backBtnClick()
 
         let controller = INVideoExportController()

+ 191 - 60
Introduce/Record/INVideoExportController.swift

@@ -5,13 +5,14 @@
 //  Created by 胡志强 on 2021/11/29.
 //
 
+import BFAnalyzeKit
 import BFCommonKit
 import BFRecordScreenKit
 import BFUIKit
 import Foundation
 import Photos
+import SwiftUI
 import UIKit
-import BFAnalyzeKit
 
 class INVideoExportController: BFBaseViewController {
     var avplayerTimeObserver: NSKeyValueObservation?
@@ -22,6 +23,7 @@ class INVideoExportController: BFBaseViewController {
     var hasSaveOnly = false
     var saveAllUlr = URL(fileURLWithPath: "aaa")
     var saveOnlyUlr = URL(fileURLWithPath: "aaa")
+    var playViewFrame: CGRect = CGRect.zero
     var isExporting = false {
         didSet {
             if isExporting {
@@ -31,15 +33,7 @@ class INVideoExportController: BFBaseViewController {
     }
 
     // 预览播放进度
-    lazy var progreddL: UILabel = {
-        let l = UILabel(frame: CGRect(x: 0, y: cDevice_iPhoneStatusBarHei, width: cScreenWidth, height: 14))
-        l.textAlignment = .center
-        l.font = UIFont.systemFont(ofSize: 10)
-        l.textColor = .white
-        l.shadowColor = .black
-        l.shadowOffset = CGSize(width: 1, height: 1)
-        return l
-    }()
+    var sliderView: BFVideoPlayerSliderView?
 
     // 合成进度指示条
     lazy var progressView: UIView = {
@@ -73,7 +67,6 @@ class INVideoExportController: BFBaseViewController {
         btn.setImage(UIImage(named: "export_saveonly_n"), for: .normal)
         btn.setImage(UIImage(named: "export_saveonly_h"), for: .selected)
         btn.addTarget(self, action: #selector(saveOnlyAction(btn:)), for: .touchUpInside)
-        btn.isSelected = true
         return btn
     }()
 
@@ -102,20 +95,69 @@ class INVideoExportController: BFBaseViewController {
 //        vv.isHidden = true
         return vv
     }()
+    
+    lazy var errorView : UIView = {
+        let backV = UIView()
+        backV.backgroundColor = .black
+        backV.isHidden = true
+        
+        let titleL = UILabel()
+        titleL.text = "合成失败"
+        titleL.font = UIFont.systemFont(ofSize: 36)
+        titleL.textColor = .white
+        titleL.textAlignment = .center
+        backV.addSubview(titleL)
+        
+        let subTitleL = UILabel()
+        subTitleL.text = "请重新尝试"
+        subTitleL.tag = 33000
+        subTitleL.font = UIFont.systemFont(ofSize: 36)
+        subTitleL.textColor = UIColor.hexColor(hexadecimal: "#A6A6A6")
+        subTitleL.textAlignment = .center
+        backV.addSubview(subTitleL)
+        
+        let retryBtn = UIButton()
+        retryBtn.backgroundColor = ThemeStyleColor
+        retryBtn.addCorner(corner:5)
+        retryBtn.addTarget(self, action: #selector(retryAction), for: .touchUpInside)
+        backV.addSubview(retryBtn)
+        
+        retryBtn.snp.makeConstraints { make in
+            make.width.equalTo(245)
+            make.height.equalTo(50)
+            make.center.equalToSuperview()
+        }
+        subTitleL.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.height.equalTo(40)
+            make.bottom.equalTo(retryBtn.snp.top).offset(30)
+        }
+        titleL.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.height.equalTo(70)
+            make.bottom.equalTo(subTitleL.snp.top)
+        }
+        
+        
+        return backV
+    }()
 
+    var playerLayer: AVPlayerLayer!
     lazy var avplayer: AVPlayer = {
         let avplayer = AVPlayer()
-        avplayerTimeObserver = avplayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) { [weak self, weak avplayer] time in
+        avplayerTimeObserver = avplayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) { [weak self, weak avplayer] _ in
             //    进度监控
             if let item = avplayer?.currentItem {
                 DispatchQueue.main.async { [weak self] in
-                    self?.progreddL.text = String(format: "%@ / %@", CMTimeGetSeconds(time).formatDurationToHMS(), CMTimeGetSeconds(item.duration).formatDurationToHMS())
+                    self?.sliderView?.progress = CMTimeGetSeconds(item.currentTime()) / CMTimeGetSeconds(item.duration)
                 }
             }
         } as? NSKeyValueObservation
 
-        NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avplayer.currentItem, queue: .main) { [weak avplayer] _ in
+        NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avplayer.currentItem, queue: .main) { [weak avplayer, weak self] _ in
             avplayer?.seek(to: CMTime.zero)
+            self?.sliderView?.playEnd()
+            self?.changeToOriginalFrame()
         }
 
         return avplayer
@@ -136,7 +178,7 @@ class INVideoExportController: BFBaseViewController {
             }
         }
 
-        export.exportCompletion = { [weak self] _, url in
+        export.exportCompletion = { [weak self] error, url in
             DispatchQueue.main.async { [weak self] in
                 guard let sself = self else {
                     return
@@ -150,7 +192,7 @@ class INVideoExportController: BFBaseViewController {
                 sself.saveToPhotoBtn.isEnabled = true
                 sself.completeBtn.isEnabled = true
 
-                sself.progreddL.isHidden = false
+                sself.sliderView?.isHidden = false
                 sself.progressView.isHidden = true
                 sself.progressL.isHidden = true
 
@@ -168,10 +210,26 @@ class INVideoExportController: BFBaseViewController {
                         sself.saveOnlyUlr = fileUrl
                         sself.hasExportOnly = true
                     }
+                    // 添加播放进度视图
+                    self?.addVideoSliderView()
+                }else {
+                    if let l = sself.errorView.viewWithTag(33000) as? UILabel, let err = error as NSError? {
+                        switch err.code {
+                        case ExportError.FileNotExist.rawValue :
+                            l.text = "原视频/图片文件被删除"
+                        case ExportError.DiskNoSpace.rawValue :
+                            l.text = "手机存储空间不足"
+                        case ExportError.VoiceLost.rawValue :
+                            l.text = "手机存储空间不足"
+                        default:
+                            l.text = "请重新尝试"
+                        }
+                    }
+                    sself.errorView.isHidden = false
                 }
             }
             // 合成成功上报
-            BFEventTrackAdaptor.baseReportUpload(businessType: nil, objectType: .ot_composeSuccess, pageSource: .sp_composePage,commonParams: commonParams())
+            BFEventTrackAdaptor.baseReportUpload(businessType: nil, objectType: .ot_composeSuccess, pageSource: .sp_composePage, commonParams: commonParams())
         }
         return export
     }()
@@ -201,9 +259,7 @@ class INVideoExportController: BFBaseViewController {
             }
             return
         }
-        if !(hasExportAll || hasExportOnly) {
-            
-        }
+        if !(hasExportAll || hasExportOnly) {}
         export.cancelExport()
         super.backBtnClick()
     }
@@ -215,12 +271,14 @@ class INVideoExportController: BFBaseViewController {
         leftButton(image: nil, imageName: nil, tintColor: UIColor.white)
 
 //        backV.frame = CGRect(x: 0, y: navHeadImageView?.bottomY ?? 0, width: cScreenWidth, height: cScreenWidth)
-        backV.backgroundColor = .clear
-        backV.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(play)))
+        backV.backgroundColor = .black
+//        backV.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(play)))
 
         addSubviews()
 
 //        export.startExprot()
+        // 默认保留录音合成
+        saveOnlyBtn.isSelected = true
 
         DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
             self?.exportNow()
@@ -228,27 +286,21 @@ class INVideoExportController: BFBaseViewController {
     }
 
     func addSubviews() {
-        view.addSubview(backV)
         view.addSubview(bottomView)
+        view.addSubview(backV)
 
-        let playerLayer = AVPlayerLayer(player: avplayer)
+        playerLayer = AVPlayerLayer(player: avplayer)
         backV.layer.addSublayer(playerLayer)
 
         backV.addSubview(progressView)
         backV.addSubview(progressL)
-        backV.addSubview(progreddL)
-
+        backV.addSubview(errorView)
+        
         bottomView.addSubview(saveAllBtn)
         bottomView.addSubview(saveOnlyBtn)
         bottomView.addSubview(saveToPhotoBtn)
         bottomView.addSubview(completeBtn)
 
-        backV.snp.makeConstraints { make in
-            make.left.right.equalToSuperview()
-            make.top.equalTo(navHeadImageView!.snp.bottom)
-            make.bottom.equalTo(bottomView.snp.top)
-        }
-
         progressView.snp.makeConstraints { make in
             make.left.top.height.equalToSuperview()
             make.width.equalTo(0)
@@ -259,13 +311,6 @@ class INVideoExportController: BFBaseViewController {
             make.height.equalTo(28)
         }
 
-        progreddL.snp.makeConstraints { make in
-            make.bottom.equalToSuperview().offset(-10)
-            make.centerX.equalTo(backV)
-            make.width.equalTo(100)
-            make.height.equalTo(20)
-        }
-
         bottomView.snp.makeConstraints { make in
             make.left.right.equalToSuperview()
             if #available(iOS 11.0, *) {
@@ -302,12 +347,44 @@ class INVideoExportController: BFBaseViewController {
         }
 
         DispatchQueue.main.asyncAfter(deadline: .now() + 0) { [weak self] in
-            playerLayer.frame = self!.backV.bounds
+            self?.backV.frame = CGRect(x: 0, y: self?.navHeadImageView?.frame.maxY ?? 0, width: self?.view.width ?? 0, height: (self?.bottomView.frame.minY ?? 0) - (self?.navHeadImageView?.frame.maxY ?? 0))
+            self?.playerLayer.frame = self!.backV.bounds
         }
     }
 
-    // MARK: - 按钮事件
+    /// 添加播放进度视图
+    func addVideoSliderView() {
+        if sliderView == nil {
+            sliderView = BFVideoPlayerSliderView(frame: CGRect(x: 0, y: backV.frame.height - 60, width: backV.frame.width, height: 50))
+            sliderView?.valueChangeBloc = { [weak self] sender in
+                let cmtime = CMTime(value: CMTimeValue(Float64(sender.value) * Float64(self?.avplayer.currentItem?.asset.duration.seconds ?? 0) * 1000.0), timescale: CMTimeScale(1000.0))
+                BFLog(message: "cmtime == \(cmtime),\(cmtime.seconds)")
+                self?.avplayer.seek(to: cmtime)
+            }
+            sliderView?.btnClickBloc = { [weak self] sender in
+                // 按钮点击
+                if sender.tag == 1 {
+                    self?.play(sender: sender)
+                } else if sender.tag == 2 {
+                    if sender.isSelected {
+                        self?.changeToFullScreen()
+                    } else {
+                        self?.changeToOriginalFrame()
+                    }
+                }
+            }
+        }
+        sliderView?.duration = avplayer.currentItem?.asset.duration.seconds ?? 0
+        if sliderView?.superview == nil {
+            backV.addSubview(sliderView!)
+        }
+    }
 
+    // MARK: - 按钮事件
+    @objc func retryAction(){
+        exportNow()
+    }
+    
     func exportNow() {
         if isExporting {
             cShowHUB(superView: nil, msg: "正在合成中。。。")
@@ -322,11 +399,11 @@ class INVideoExportController: BFBaseViewController {
 
         progressView.isHidden = false
         progressL.isHidden = false
-        progreddL.isHidden = true
+        sliderView?.isHidden = true
         export.startExprot(synthesisAll: saveAllBtn.isSelected)
         UIApplication.shared.isIdleTimerDisabled = true
         // 开始合成上报
-        BFEventTrackAdaptor.baseReportUpload(businessType: nil, objectType: .ot_startCompose, pageSource: .sp_composePage,commonParams: commonParams())
+        BFEventTrackAdaptor.baseReportUpload(businessType: nil, objectType: .ot_startCompose, pageSource: .sp_composePage, commonParams: commonParams())
     }
 
     @objc func saveToPhotoNow() {
@@ -337,7 +414,7 @@ class INVideoExportController: BFBaseViewController {
         if let url = (avplayer.currentItem?.asset as? AVURLAsset)?.url {
             PHPhotoLibrary.shared().performChanges {
                 PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
-            } completionHandler: {[weak self] isFinished, _ in
+            } completionHandler: { [weak self] isFinished, _ in
                 guard let sself = self else {
                     return
                 }
@@ -354,7 +431,7 @@ class INVideoExportController: BFBaseViewController {
             }
         }
         // 点击保存至相册上报
-        BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_saveToAblum, pageSource: .sp_composePage,extParams: (saveAllBtn.isSelected ? ["saveAll":true] : ["saveRecord":true]),commonParams: commonParams())
+        BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_saveToAblum, pageSource: .sp_composePage, extParams: saveAllBtn.isSelected ? ["saveAll": true] : ["saveRecord": true], commonParams: commonParams())
     }
 
     @objc func saveAllAction(btn: UIButton) {
@@ -391,8 +468,10 @@ class INVideoExportController: BFBaseViewController {
 
     @objc func completeAction() {
         // MARK: 删除所有录制资源. 现在放在了选择相册展示时清理cache
-        if (!self.hasSaveOnly && self.saveOnlyUlr.absoluteString != "aaa")
-            || (!self.hasSaveAll && self.saveAllUlr.absoluteString != "aaa") {
+
+        if (!hasSaveOnly && saveOnlyUlr.absoluteString != "aaa")
+            || (!hasSaveAll && saveAllUlr.absoluteString != "aaa")
+        {
             let remindData = BFBaseModel()
             remindData.summary = "合成的视频尚未保存到相册"
             let alertV = BFRemindView(frame: view.bounds)
@@ -405,47 +484,45 @@ class INVideoExportController: BFBaseViewController {
                     return
                 }
                 if item.tag == 1 { // 确定返回到上一层
-                    if sself.hasExportOnly{
+                    if sself.hasExportOnly {
                         PHPhotoLibrary.shared().performChanges {
                             PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: sself.saveOnlyUlr)
-                        } completionHandler: { isFinished, _ in
-                            
+                        } completionHandler: { _, _ in
                         }
                     }
-                    if sself.hasExportAll{
+                    if sself.hasExportAll {
                         PHPhotoLibrary.shared().performChanges {
                             PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: sself.saveAllUlr)
-                        } completionHandler: { isFinished, _ in
-                            
+                        } completionHandler: { _, _ in
                         }
                     }
                 }
-                
+
                 sself.export.cancelExport()
                 sself.navigationController?.popToRootViewController(animated: true)
             }
             UIApplication.shared.keyWindow?.addSubview(alertV)
-        }else{
+        } else {
             export.cancelExport()
             navigationController?.popToRootViewController(animated: true)
         }
     }
 
-    @objc func play() {
+    @objc func play(sender: UIButton) {
         if isExporting {
             avplayer.pause()
             return
         }
         if avplayer.currentItem != nil {
-            if avplayer.timeControlStatus == .playing {
+            if avplayer.timeControlStatus == .playing || sender.isSelected {
                 avplayer.pause()
             } else if avplayer.timeControlStatus == .paused {
                 avplayer.play()
             }
         }
     }
-    
-    func whetherCancelExport(comfirm:(()->Void)?){
+
+    func whetherCancelExport(comfirm: (() -> Void)?) {
         let remindData = BFBaseModel()
         remindData.summary = "正在合成中,是否取消?"
         let alertV = BFRemindView(frame: view.bounds)
@@ -461,8 +538,62 @@ class INVideoExportController: BFBaseViewController {
                 sself.export.cancelExport()
                 comfirm?()
             }
-
         }
         UIApplication.shared.keyWindow?.addSubview(alertV)
     }
 }
+
+extension INVideoExportController {
+    @objc func changeToOriginalFrame() {
+        if !(sliderView?.isFullScreen ?? false) {
+            isHiddenStatus = false // (0.0, 64.0, 375.0, 401.0)
+            navHeadImageView?.isHidden = false
+            backV.frame = CGRect(x: 0, y: navHeadImageView?.frame.maxY ?? 0, width: view.width, height: bottomView.frame.minY - (navHeadImageView?.frame.maxY ?? 0))
+            playerLayer.frame = CGRect(x: 0, y: 0, width: view.width, height: bottomView.frame.minY - (navHeadImageView?.frame.maxY ?? 0))
+            sliderView?.frame = CGRect(x: 0, y: backV.frame.height - 60, width: view.frame.width, height: 50)
+            UIView.animate(withDuration: 0.2, animations: { [weak self] in
+                self?.changeOrientation(orientation: .portrait)
+                self?.backV.center = CGPoint(x: (self?.backV.width ?? 0) / 2, y: (self?.backV.height ?? 0) / 2 + (self?.navHeadImageView?.frame.maxY ?? 0))
+            }) { [weak self] _ in
+            }
+        }
+    }
+
+    func changeToFullScreen() {
+        if sliderView?.isFullScreen ?? false {
+            isHiddenStatus = true
+            navHeadImageView?.isHidden = true
+            backV.frame = CGRect(x: 0, y: 0, width: view.frame.height, height: view.frame.width)
+            playerLayer.frame = backV.bounds
+            sliderView?.frame = CGRect(x: 0, y: backV.frame.height - 60, width: backV.frame.width, height: 50)
+            UIView.animate(withDuration: 0.2, animations: { [weak self] in
+                let orientation = UIDevice.current.orientation
+                if orientation == .landscapeRight {
+                    self?.changeOrientation(orientation: .landscapeLeft)
+                } else {
+                    self?.changeOrientation(orientation: .landscapeRight)
+                }
+                self?.backV.center = CGPoint(x: (self?.view.frame.width ?? 0) / 2, y: (self?.view.frame.height ?? 0) / 2)
+            }) { [weak self] _ in
+            }
+        }
+    }
+
+    func changeOrientation(orientation: UIInterfaceOrientation) {
+        UIView.animate(withDuration: 0.2, animations: { [weak self] in
+            self?.backV.transform = self?.transformRotation(orientation: orientation) as! CGAffineTransform
+        }) { [weak self] _ in
+        }
+    }
+
+    @objc func transformRotation(orientation: UIInterfaceOrientation) -> CGAffineTransform {
+        if orientation == .portrait {
+            return .identity
+        } else if orientation == .landscapeLeft {
+            return CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
+        } else if orientation == .landscapeRight {
+            return CGAffineTransform(rotationAngle: CGFloat.pi / 2)
+        }
+        return .identity
+    }
+}

+ 1 - 0
Introduce/Record/Introduce-Bridging-Header.h

@@ -4,3 +4,4 @@
 
 #import <UMCommon/UMCommon.h>
 #import <UMCommon/MobClick.h>
+#import <Bugly/Bugly.h>

+ 1 - 1
Podfile

@@ -13,7 +13,7 @@ target 'Introduce' do
   pod 'UMDevice',                 '2.1.0'
   pod 'UMCSecurityPlugins',       '1.0.6'
   pod 'UMAPM',                    '1.5.5'
-
+  pod 'Bugly',                    '2.5.91'
 ## Pods-for-AppStore
 #  pod 'BFCommonKit',           '1.4.9'
 #  pod 'BFNetRequestKit',       '0.2.3'