From 517365879a576449c3de299d495c4a0d26cfdaa0 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Fri, 17 Oct 2025 14:52:29 +0800 Subject: [PATCH] keep edit --- YuMi.xcodeproj/project.pbxproj | 72 +- YuMi/Appdelegate/AppDelegate.h | 8 +- YuMi/Appdelegate/AppDelegate.h.backup | 15 + YuMi/Appdelegate/AppDelegate.m | 75 +- YuMi/Appdelegate/AppDelegate.m.backup | 176 +++ YuMi/Config/APIConfig.swift | 49 +- YuMi/Config/APIConfig.swift.backup | 110 ++ YuMi/CustomUI/DJDKMIMOMColor.h | 78 +- YuMi/CustomUI/DJDKMIMOMColor.h.backup | 79 ++ YuMi/CustomUI/DJDKMIMOMColor.m | 69 +- YuMi/CustomUI/DJDKMIMOMColor.m.backup | 177 +++ .../TTPopup/Config/TTActionSheetConfig.h | 106 +- .../Config/TTActionSheetConfig.h.backup | 60 + .../TTPopup/Config/TTActionSheetConfig.m | 16 +- .../Config/TTActionSheetConfig.m.backup | 49 + .../TTPopup/Config/TTAlertButtonConfig.h | 58 +- .../Config/TTAlertButtonConfig.h.backup | 30 + .../TTPopup/Config/TTAlertButtonConfig.m | 8 +- .../Config/TTAlertButtonConfig.m.backup | 13 + YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h | 156 ++- .../TTPopup/Config/TTAlertConfig.h.backup | 86 ++ YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m | 57 +- .../TTPopup/Config/TTAlertConfig.m.backup | 90 ++ .../Config/TTAlertMessageAttributedConfig.h | 62 +- .../TTAlertMessageAttributedConfig.h.backup | 34 + .../Config/TTAlertMessageAttributedConfig.m | 8 +- .../TTAlertMessageAttributedConfig.m.backup | 13 + .../TTPopup/Header/TTPopupConstants.h | 61 +- .../TTPopup/Header/TTPopupConstants.h.backup | 38 + .../TTPopup/Manager/TTPopupManagerService.h | 45 +- .../Manager/TTPopupManagerService.h.backup | 24 + .../TTPopup/Manager/TTPopupManagerService.m | 54 +- .../Manager/TTPopupManagerService.m.backup | 200 ++++ .../Manager/TTPopupManagerServiceProtocol.h | 42 +- .../TTPopupManagerServiceProtocol.h.backup | 25 + .../CustomUI/TTPopup/Service/TTPopupService.h | 41 +- .../TTPopup/Service/TTPopupService.h.backup | 22 + .../CustomUI/TTPopup/Service/TTPopupService.m | 8 +- .../TTPopup/Service/TTPopupService.m.backup | 36 + .../TTPopup/Service/TTPopupServiceProtocol.h | 125 +- .../Service/TTPopupServiceProtocol.h.backup | 78 ++ YuMi/CustomUI/TTPopup/TTPopup.h | 204 ++-- YuMi/CustomUI/TTPopup/TTPopup.h.backup | 126 ++ YuMi/CustomUI/TTPopup/TTPopup.m | 31 +- YuMi/CustomUI/TTPopup/TTPopup.m.backup | 243 ++++ .../CustomUI/TTPopup/View/TTActionSheetView.h | 50 +- .../TTPopup/View/TTActionSheetView.h.backup | 26 + .../CustomUI/TTPopup/View/TTActionSheetView.m | 20 +- .../TTPopup/View/TTActionSheetView.m.backup | 159 +++ YuMi/CustomUI/TTPopup/View/TTAlertView.h | 48 +- .../TTPopup/View/TTAlertView.h.backup | 25 + YuMi/CustomUI/TTPopup/View/TTAlertView.m | 51 +- .../TTPopup/View/TTAlertView.m.backup | 255 ++++ YuMi/CustomUI/TTPopup/View/TTNewAlertView.h | 10 +- .../TTPopup/View/TTNewAlertView.h.backup | 20 + YuMi/CustomUI/TTPopup/View/TTNewAlertView.m | 11 +- .../TTPopup/View/TTNewAlertView.m.backup | 118 ++ YuMi/CustomUI/UIImage/UIImage+Utils.h | 86 +- YuMi/CustomUI/UIImage/UIImage+Utils.h.backup | 65 ++ YuMi/CustomUI/UIImage/UIImage+Utils.m | 572 +-------- YuMi/CustomUI/UIImage/UIImage+Utils.m.backup | 592 ++++++++++ YuMi/CustomUI/UIImageView/NetImageConfig.h | 8 +- .../UIImageView/NetImageConfig.h.backup | 22 + YuMi/CustomUI/UIImageView/NetImageConfig.m | 8 +- .../UIImageView/NetImageConfig.m.backup | 21 + YuMi/CustomUI/UIImageView/NetImageView.h | 10 +- .../UIImageView/NetImageView.h.backup | 45 + YuMi/CustomUI/UIImageView/NetImageView.m | 8 +- .../UIImageView/NetImageView.m.backup | 151 +++ YuMi/CustomUI/UIImageView/UIImageConstant.h | 48 +- .../UIImageView/UIImageConstant.h.backup | 53 + YuMi/CustomUI/UIImageView/UIImageConstant.m | 34 +- .../UIImageView/UIImageConstant.m.backup | 119 ++ YuMi/CustomUI/UIViewCorner/UIView+Corner.h | 41 +- .../UIViewCorner/UIView+Corner.h.backup | 67 ++ YuMi/CustomUI/UIViewCorner/UIView+Corner.m | 66 +- .../UIViewCorner/UIView+Corner.m.backup | 125 ++ .../UIView+GradientLayer.h | 21 +- .../UIView+GradientLayer.h.backup | 37 + .../UIView+GradientLayer.m | 40 +- .../UIView+GradientLayer.m.backup | 120 ++ .../VagueImageView/UIImage+ImageEffects.h | 2 +- .../UIImage+ImageEffects.h.backup | 108 ++ .../VagueImageView/UIImage+ImageEffects.m | 51 +- .../UIImage+ImageEffects.m.backup | 309 +++++ YuMi/CustomUI/XCCurrentVCStackManager.h | 52 +- .../CustomUI/XCCurrentVCStackManager.h.backup | 31 + YuMi/CustomUI/XCCurrentVCStackManager.m | 19 +- .../CustomUI/XCCurrentVCStackManager.m.backup | 123 ++ YuMi/CustomUI/XNDJTDDLoadingTool.h | 224 ++-- YuMi/CustomUI/XNDJTDDLoadingTool.h.backup | 148 +++ YuMi/CustomUI/XNDJTDDLoadingTool.m | 114 +- YuMi/CustomUI/XNDJTDDLoadingTool.m.backup | 391 +++++++ YuMi/E-P/Common/EPImageUploader.swift | 56 +- YuMi/E-P/Common/EPImageUploader.swift.backup | 163 +++ YuMi/E-P/Common/EPProgressHUD.swift | 29 +- YuMi/E-P/Common/EPProgressHUD.swift.backup | 92 ++ YuMi/E-P/Common/EPQCloudConfig.swift | 19 +- YuMi/E-P/Common/EPQCloudConfig.swift.backup | 56 + YuMi/E-P/Common/EPSDKManager.swift | 75 +- YuMi/E-P/Common/EPSDKManager.swift.backup | 253 ++++ .../EPLoginTypesViewController.swift | 693 +++++++++++ .../EPLoginTypesViewController.swift.backup} | 0 .../Controllers/EPLoginViewController.swift | 305 +++++ .../EPLoginViewController.swift.backup} | 0 YuMi/E-P/Login/Models/EPLoginBridge.swift | 30 + .../Models/EPLoginBridge.swift.backup} | 0 YuMi/E-P/Login/Models/EPLoginConfig.swift | 302 +++++ .../Models/EPLoginConfig.swift.backup} | 0 YuMi/E-P/Login/Models/EPLoginState.swift | 50 + .../Models/EPLoginState.swift.backup} | 0 YuMi/E-P/Login/Services/EPLoginManager.swift | 135 +++ .../Services/EPLoginManager.swift.backup} | 0 YuMi/E-P/Login/Services/EPLoginService.swift | 246 ++++ .../Services/EPLoginService.swift.backup} | 0 YuMi/E-P/Login/Views/EPLoginButton.swift | 125 ++ .../Views/EPLoginButton.swift.backup} | 0 YuMi/E-P/Login/Views/EPLoginInputView.swift | 319 +++++ .../Views/EPLoginInputView.swift.backup} | 0 YuMi/E-P/Login/Views/EPPolicyLabel.swift | 149 +++ .../Views/EPPolicyLabel.swift.backup} | 0 .../Controllers/EPAboutUsViewController.swift | 159 +++ .../EPAboutUsViewController.swift.backup} | 0 .../EPEditSettingViewController.swift | 846 ++++++++++++++ .../EPEditSettingViewController.swift.backup} | 0 .../Mine/Controllers/EPMineViewController.h | 16 + .../EPMineViewController.h.backup} | 0 .../Mine/Controllers/EPMineViewController.m | 218 ++++ .../EPMineViewController.m.backup} | 0 YuMi/E-P/Mine/Services/EPMineAPIHelper.h | 38 + .../Services/EPMineAPIHelper.h.backup} | 0 YuMi/E-P/Mine/Services/EPMineAPIHelper.m | 75 ++ .../Services/EPMineAPIHelper.m.backup} | 0 YuMi/E-P/Mine/Views/EPMineHeaderView.h | 22 + .../Views/EPMineHeaderView.h.backup} | 0 YuMi/E-P/Mine/Views/EPMineHeaderView.m | 240 ++++ .../Views/EPMineHeaderView.m.backup} | 0 .../EPMomentPublishViewController.h | 19 + .../EPMomentPublishViewController.h.backup} | 0 .../EPMomentPublishViewController.m | 435 +++++++ .../EPMomentPublishViewController.m.backup} | 0 .../Controllers/EPMomentViewController.h | 16 + .../EPMomentViewController.h.backup} | 0 .../Controllers/EPMomentViewController.m | 190 +++ .../EPMomentViewController.m.backup} | 0 .../Moments/Services/EPEmotionColorStorage.h | 47 + .../Services/EPEmotionColorStorage.h.backup} | 0 .../Moments/Services/EPEmotionColorStorage.m | 116 ++ .../Services/EPEmotionColorStorage.m.backup} | 0 .../Services/EPMomentAPISwiftHelper.swift | 90 ++ .../EPMomentAPISwiftHelper.swift.backup} | 0 YuMi/E-P/Moments/Views/EPEmotionColorPicker.h | 27 + .../Views/EPEmotionColorPicker.h.backup} | 0 YuMi/E-P/Moments/Views/EPEmotionColorPicker.m | 300 +++++ .../Views/EPEmotionColorPicker.m.backup} | 0 .../Moments/Views/EPEmotionColorWheelView.h | 36 + .../Views/EPEmotionColorWheelView.h.backup} | 0 .../Moments/Views/EPEmotionColorWheelView.m | 145 +++ .../Views/EPEmotionColorWheelView.m.backup} | 0 YuMi/E-P/Moments/Views/EPEmotionInfoView.h | 21 + .../Views/EPEmotionInfoView.h.backup} | 0 YuMi/E-P/Moments/Views/EPEmotionInfoView.m | 211 ++++ .../Views/EPEmotionInfoView.m.backup} | 0 YuMi/E-P/Moments/Views/EPMomentCell.h | 22 + .../Views/EPMomentCell.h.backup} | 0 YuMi/E-P/Moments/Views/EPMomentCell.m | 556 +++++++++ .../Views/EPMomentCell.m.backup} | 0 YuMi/E-P/Moments/Views/EPMomentListView.h | 41 + .../Views/EPMomentListView.h.backup} | 0 YuMi/E-P/Moments/Views/EPMomentListView.m | 250 ++++ .../Views/EPMomentListView.m.backup} | 0 .../Moments/Views/EPSignatureColorGuideView.h | 30 + .../Views/EPSignatureColorGuideView.h.backup} | 0 .../Moments/Views/EPSignatureColorGuideView.m | 370 ++++++ .../Views/EPSignatureColorGuideView.m.backup} | 0 YuMi/E-P/TabBar/EPTabBarController.swift | 519 +++++++++ .../EPTabBarController.swift.backup} | 0 YuMi/Global/BuglyManagerExample.h | 29 +- YuMi/Global/BuglyManagerExample.h.backup | 42 + YuMi/Global/BuglyManagerExample.m | 22 +- YuMi/Global/BuglyManagerExample.m.backup | 79 ++ YuMi/Global/YUMIConstant.h | 16 +- YuMi/Global/YUMIConstant.h.backup | 24 + YuMi/Global/YUMIConstant.m | 12 +- YuMi/Global/YUMIConstant.m.backup | 21 + YuMi/Global/YUMIHtmlUrl.h | 20 +- YuMi/Global/YUMIHtmlUrl.h.backup | 26 + YuMi/Global/YUMIHtmlUrl.m | 20 +- YuMi/Global/YUMIHtmlUrl.m.backup | 43 + YuMi/Global/YUMIMacroUitls.h | 51 +- YuMi/Global/YUMINNNN.h | 18 +- YuMi/Global/YUMINNNN.h.backup | 17 + YuMi/Info.plist | 12 +- YuMi/Modules/YMLogin/Api/Api+Login.h | 45 +- YuMi/Modules/YMLogin/Api/Api+Login.h.backup | 117 ++ YuMi/Modules/YMLogin/Api/Api+Login.m | 60 +- YuMi/Modules/YMLogin/Api/Api+Login.m.backup | 149 +++ .../YMLogin/View/NewLogin/PIUserSexView.h | 10 +- .../View/NewLogin/PIUserSexView.h.backup | 17 + .../YMLogin/View/NewLogin/PIUserSexView.m | 24 +- .../View/NewLogin/PIUserSexView.m.backup | 127 ++ .../View/NewLogin/XPForgetPwdViewController.h | 8 +- .../XPForgetPwdViewController.h.backup | 16 + .../View/NewLogin/XPForgetPwdViewController.m | 28 +- .../XPForgetPwdViewController.m.backup | 271 +++++ .../View/NewLogin/XPLoginAraeViewController.h | 10 +- .../XPLoginAraeViewController.h.backup | 21 + .../View/NewLogin/XPLoginAraeViewController.m | 20 +- .../XPLoginAraeViewController.m.backup | 191 +++ .../View/NewLogin/XPLoginAreaTableViewCell.h | 8 +- .../XPLoginAreaTableViewCell.h.backup | 24 + .../View/NewLogin/XPLoginAreaTableViewCell.m | 12 +- .../XPLoginAreaTableViewCell.m.backup | 88 ++ .../YMLogin/View/NewLogin/XPLoginAuthCodeVC.h | 8 +- .../View/NewLogin/XPLoginAuthCodeVC.h.backup | 23 + .../YMLogin/View/NewLogin/XPLoginAuthCodeVC.m | 16 +- .../View/NewLogin/XPLoginAuthCodeVC.m.backup | 165 +++ .../YMLogin/View/NewLogin/XPLoginInputView.h | 18 +- .../View/NewLogin/XPLoginInputView.h.backup | 37 + .../YMLogin/View/NewLogin/XPLoginInputView.m | 16 +- .../View/NewLogin/XPLoginInputView.m.backup | 168 +++ .../NewLogin/XPLoginPhoneViewController.h | 8 +- .../XPLoginPhoneViewController.h.backup | 16 + .../NewLogin/XPLoginPhoneViewController.m | 39 +- .../XPLoginPhoneViewController.m.backup | 430 +++++++ .../View/NewLogin/XPLoginPwdViewController.h | 8 +- .../XPLoginPwdViewController.h.backup | 16 + .../View/NewLogin/XPLoginPwdViewController.m | 21 +- .../XPLoginPwdViewController.m.backup | 193 +++ .../Session/Content/MessageContentUnSupport.m | 15 +- .../Content/MessageContentUnSupport.m.backup | 20 + YuMi/Modules/YMMine/Api/Api(GameOrder).h | 8 +- .../YMMine/Api/Api(GameOrder).h.backup | 16 + YuMi/Modules/YMMine/Api/Api(GameOrder).m | 8 +- .../YMMine/Api/Api(GameOrder).m.backup | 12 + YuMi/Modules/YMMine/Api/Api+Mine.h | 245 +--- YuMi/Modules/YMMine/Api/Api+Mine.h.backup | 366 ++++++ YuMi/Modules/YMMine/Api/Api+Mine.m | 297 ++--- YuMi/Modules/YMMine/Api/Api+Mine.m.backup | 484 ++++++++ .../Api/Api+EnterpriseRecharge.m | 18 +- .../Api/Api+EnterpriseRecharge.m.backup | 40 + .../MedalsCollectionViewCell_Refactored.m | 63 +- ...dalsCollectionViewCell_Refactored.m.backup | 214 ++++ YuMi/Modules/YMMonents/Api/Api+Moments.h | 142 +-- .../YMMonents/Api/Api+Moments.h.backup | 168 +++ YuMi/Modules/YMMonents/Api/Api+Moments.m | 172 +-- .../YMMonents/Api/Api+Moments.m.backup | 268 +++++ .../YMMonents/Model/MomentsInfoModel.h | 98 +- .../YMMonents/Model/MomentsInfoModel.h.backup | 111 ++ .../YMMonents/Model/MomentsInfoModel.m | 8 +- .../YMMonents/Model/MomentsInfoModel.m.backup | 28 + .../YMMonents/Model/MomentsListInfoModel.h | 12 +- .../Model/MomentsListInfoModel.h.backup | 19 + .../YMMonents/Model/MomentsListInfoModel.m | 8 +- .../Model/MomentsListInfoModel.m.backup | 16 + .../YMNewHome/View/Cell/XPBlankRoomModel.h | 8 +- .../View/Cell/XPBlankRoomModel.h.backup | 16 + .../YMNewHome/View/Cell/XPBlankRoomModel.m | 8 +- .../View/Cell/XPBlankRoomModel.m.backup | 12 + .../View/AnimationView/BannerSchedulerTest.m | 22 +- .../BannerSchedulerTest.m.backup | 174 +++ .../Test/XPTextLayoutTest.h | 29 +- .../Test/XPTextLayoutTest.h.backup | 41 + .../Test/XPTextLayoutTest.m | 26 +- .../Test/XPTextLayoutTest.m.backup | 117 ++ .../MessageContainerView/XPTextLayoutTest.h | 8 +- .../XPTextLayoutTest.h.backup | 26 + .../MessageContainerView/XPTextLayoutTest.m | 8 +- .../XPTextLayoutTest.m.backup | 166 +++ .../Action/XPRoomBackCleanMessagesAction.h | 8 +- .../XPRoomBackCleanMessagesAction.h.backup | 16 + .../View/RoomRank/ThemeColor+RoomRank.h | 18 +- .../RoomRank/ThemeColor+RoomRank.h.backup | 25 + .../View/RoomRank/ThemeColor+RoomRank.m | 18 +- .../RoomRank/ThemeColor+RoomRank.m.backup | 40 + .../View/Cell/XPRoomRankTableViewCell.m | 28 +- .../Cell/XPRoomRankTableViewCell.m.backup | 173 +++ .../View/SubViews/XPRoomRankUserInfoView.m | 30 +- .../SubViews/XPRoomRankUserInfoView.m.backup | 224 ++++ .../RoomRank/View/XPRoomRankViewController.m | 36 +- .../View/XPRoomRankViewController.m.backup | 234 ++++ .../YMRoom/View/WishGift/Api/Api+WishGift.h | 47 +- .../View/WishGift/Api/Api+WishGift.h.backup | 49 + .../YMRoom/View/WishGift/Api/Api+WishGift.m | 56 +- .../View/WishGift/Api/Api+WishGift.m.backup | 85 ++ .../WishGift/Model/WishGiftHistoryModel.h | 12 +- .../Model/WishGiftHistoryModel.h.backup | 21 + .../WishGift/Model/WishGiftHistoryModel.m | 8 +- .../Model/WishGiftHistoryModel.m.backup | 15 + .../View/WishGift/Model/WishGiftInfoModel.h | 30 +- .../WishGift/Model/WishGiftInfoModel.h.backup | 42 + .../View/WishGift/Model/WishGiftInfoModel.m | 8 +- .../WishGift/Model/WishGiftInfoModel.m.backup | 13 + .../WishGift/Model/WishGiftInfoUpdateModel.h | 12 +- .../Model/WishGiftInfoUpdateModel.h.backup | 19 + .../WishGift/Model/WishGiftInfoUpdateModel.m | 8 +- .../Model/WishGiftInfoUpdateModel.m.backup | 15 + .../View/WishGift/Model/WishGiftUserModel.h | 8 +- .../WishGift/Model/WishGiftUserModel.h.backup | 19 + .../View/WishGift/Model/WishGiftUserModel.m | 8 +- .../WishGift/Model/WishGiftUserModel.m.backup | 12 + .../WishGift/Presenter/XPWishGiftPresenter.h | 22 +- .../Presenter/XPWishGiftPresenter.h.backup | 31 + .../WishGift/Presenter/XPWishGiftPresenter.m | 22 +- .../Presenter/XPWishGiftPresenter.m.backup | 65 ++ .../WishGift/Protocol/XPWishGiftProtocol.h | 22 +- .../Protocol/XPWishGiftProtocol.h.backup | 35 + .../View/Cell/XPWishGiftEmptyTableViewCell.h | 8 +- .../XPWishGiftEmptyTableViewCell.h.backup | 16 + .../View/Cell/XPWishGiftEmptyTableViewCell.m | 12 +- .../XPWishGiftEmptyTableViewCell.m.backup | 73 ++ .../Cell/XPWishGiftHistoryTableViewCell.h | 12 +- .../XPWishGiftHistoryTableViewCell.h.backup | 20 + .../Cell/XPWishGiftHistoryTableViewCell.m | 24 +- .../XPWishGiftHistoryTableViewCell.m.backup | 173 +++ .../View/Cell/XPWishGiftTableViewCell.h | 16 +- .../Cell/XPWishGiftTableViewCell.h.backup | 30 + .../View/Cell/XPWishGiftTableViewCell.m | 30 +- .../Cell/XPWishGiftTableViewCell.m.backup | 235 ++++ .../WishGift/View/View/XPWishGiftEnterView.h | 10 +- .../View/View/XPWishGiftEnterView.h.backup | 17 + .../WishGift/View/View/XPWishGiftEnterView.m | 26 +- .../View/View/XPWishGiftEnterView.m.backup | 245 ++++ .../WishGift/View/View/XPWishGiftInfoView.h | 10 +- .../View/View/XPWishGiftInfoView.h.backup | 28 + .../WishGift/View/View/XPWishGiftInfoView.m | 30 +- .../View/View/XPWishGiftInfoView.m.backup | 245 ++++ .../WishGift/View/View/XPWishGiftListView.h | 14 +- .../View/View/XPWishGiftListView.h.backup | 30 + .../WishGift/View/View/XPWishGiftListView.m | 30 +- .../View/View/XPWishGiftListView.m.backup | 259 +++++ .../View/View/XPWishGiftSectionView.h | 8 +- .../View/View/XPWishGiftSectionView.h.backup | 16 + .../View/View/XPWishGiftSectionView.m | 14 +- .../View/View/XPWishGiftSectionView.m.backup | 55 + .../View/XPWishGiftCreateItemViewController.h | 20 +- ...PWishGiftCreateItemViewController.h.backup | 29 + .../View/XPWishGiftCreateItemViewController.m | 53 +- ...PWishGiftCreateItemViewController.m.backup | 522 +++++++++ .../View/XPWishGiftCreateViewController.h | 8 +- .../XPWishGiftCreateViewController.h.backup | 16 + .../View/XPWishGiftCreateViewController.m | 40 +- .../XPWishGiftCreateViewController.m.backup | 333 ++++++ .../View/XPWishGiftHistoryViewController.h | 8 +- .../XPWishGiftHistoryViewController.h.backup | 16 + .../View/XPWishGiftHistoryViewController.m | 24 +- .../XPWishGiftHistoryViewController.m.backup | 162 +++ .../WishGift/View/XPWishGiftViewController.h | 10 +- .../View/XPWishGiftViewController.h.backup | 29 + .../WishGift/View/XPWishGiftViewController.m | 50 +- .../View/XPWishGiftViewController.m.backup | 375 ++++++ YuMi/Modules/YMTabbar/Api/Api+Main.h | 10 +- YuMi/Modules/YMTabbar/Api/Api+Main.h.backup | 21 + YuMi/Modules/YMTabbar/Api/Api+Main.m | 15 +- YuMi/Modules/YMTabbar/Api/Api+Main.m.backup | 32 + YuMi/Modules/YMWeb/MSRoomGameWebVC.h | 8 +- YuMi/Modules/YMWeb/MSRoomGameWebVC.h.backup | 18 + YuMi/Modules/YMWeb/MSRoomGameWebVC.m | 89 +- YuMi/Modules/YMWeb/MSRoomGameWebVC.m.backup | 649 +++++++++++ YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h | 8 +- .../YMWeb/PIWebViewSavePhotoView.h.backup | 18 + YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m | 8 +- .../YMWeb/PIWebViewSavePhotoView.m.backup | 180 +++ YuMi/Modules/YMWeb/XPWebViewController.h | 25 +- .../YMWeb/XPWebViewController.h.backup | 60 + YuMi/Modules/YMWeb/XPWebViewController.m | 165 ++- .../YMWeb/XPWebViewController.m.backup | 1032 +++++++++++++++++ YuMi/Modules/YMWeb/XPWebViewNavView.h | 12 +- YuMi/Modules/YMWeb/XPWebViewNavView.h.backup | 21 + YuMi/Modules/YMWeb/XPWebViewNavView.m | 14 +- YuMi/Modules/YMWeb/XPWebViewNavView.m.backup | 79 ++ YuMi/Network/HttpRequestHelper.h | 12 +- YuMi/Network/HttpRequestHelper.h.backup | 64 + YuMi/Network/HttpRequestHelper.m | 56 +- YuMi/Network/HttpRequestHelper.m.backup | 521 +++++++++ YuMi/Network/MSParamsDecode.h | 14 +- YuMi/Network/MSParamsDecode.h.backup | 21 + YuMi/Network/MSParamsDecode.m | 18 +- YuMi/Network/MSParamsDecode.m.backup | 64 + .../Structure/Base/BaseNavigationController.h | 8 +- .../Base/BaseNavigationController.h.backup | 16 + .../Structure/Base/BaseNavigationController.m | 28 +- .../Base/BaseNavigationController.m.backup | 85 ++ YuMi/Structure/Base/BaseViewController.h | 63 +- .../Base/BaseViewController.h.backup | 100 ++ YuMi/Structure/Base/BaseViewController.m | 62 +- .../Base/BaseViewController.m.backup | 198 ++++ YuMi/Structure/MVP/Api/Api.h | 65 +- YuMi/Structure/MVP/Api/Api.h.backup | 103 ++ YuMi/Structure/MVP/Api/Api.m | 77 +- YuMi/Structure/MVP/Api/Api.m.backup | 158 +++ YuMi/Structure/MVP/Model/AccountInfoStorage.h | 78 +- .../MVP/Model/AccountInfoStorage.h.backup | 40 + YuMi/Structure/MVP/Model/AccountInfoStorage.m | 20 +- .../MVP/Model/AccountInfoStorage.m.backup | 171 +++ YuMi/Structure/MVP/Model/AccountModel.h | 8 +- .../Structure/MVP/Model/AccountModel.h.backup | 31 + YuMi/Structure/MVP/Model/AccountModel.m | 8 +- .../Structure/MVP/Model/AccountModel.m.backup | 15 + YuMi/Structure/MVP/Model/BaseModel.h | 16 +- YuMi/Structure/MVP/Model/BaseModel.h.backup | 26 + YuMi/Structure/MVP/Model/BaseModel.m | 8 +- YuMi/Structure/MVP/Model/BaseModel.m.backup | 12 + .../Structure/MVP/Model/NSObject+AutoCoding.h | 46 +- .../MVP/Model/NSObject+AutoCoding.h.backup | 25 + .../Structure/MVP/Model/NSObject+AutoCoding.m | 42 +- .../MVP/Model/NSObject+AutoCoding.m.backup | 245 ++++ YuMi/Structure/MVP/Model/PIBaseModel.h | 8 +- YuMi/Structure/MVP/Model/PIBaseModel.h.backup | 16 + YuMi/Structure/MVP/Model/PIBaseModel.m | 24 +- YuMi/Structure/MVP/Model/PIBaseModel.m.backup | 36 + YuMi/Structure/MVP/Model/UserInfoModel.h | 113 +- .../MVP/Model/UserInfoModel.h.backup | 203 ++++ YuMi/Structure/MVP/Model/UserInfoModel.m | 10 +- .../MVP/Model/UserInfoModel.m.backup | 76 ++ .../MVP/Presenter/BaseMvpPresenter.h | 9 +- .../MVP/Presenter/BaseMvpPresenter.h.backup | 37 + .../MVP/Presenter/BaseMvpPresenter.m | 28 +- .../MVP/Presenter/BaseMvpPresenter.m.backup | 137 +++ YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h | 10 +- .../MVP/Protocol/BaseMvpProtocol.h.backup | 25 + YuMi/Structure/MVP/View/MvpViewController.h | 9 +- .../MVP/View/MvpViewController.h.backup | 31 + YuMi/Structure/MVP/View/MvpViewController.m | 30 +- .../MVP/View/MvpViewController.m.backup | 204 ++++ YuMi/Structure/PrefixHeader.pch | 1 - YuMi/Tools/Bundle/NSBundle+Localizable.h | 8 +- .../Bundle/NSBundle+Localizable.h.backup | 20 + YuMi/Tools/Bundle/NSBundle+Localizable.m | 26 +- .../Bundle/NSBundle+Localizable.m.backup | 92 ++ YuMi/Tools/Bundle/YMLanguageConfig.h | 18 +- YuMi/Tools/Bundle/YMLanguageConfig.h.backup | 31 + YuMi/Tools/Bundle/YMLanguageConfig.m | 14 +- YuMi/Tools/Bundle/YMLanguageConfig.m.backup | 55 + YuMi/Tools/CountDown/CountDownHelper.h | 32 +- YuMi/Tools/CountDown/CountDownHelper.h.backup | 48 + YuMi/Tools/CountDown/CountDownHelper.m | 28 +- YuMi/Tools/CountDown/CountDownHelper.m.backup | 132 +++ YuMi/Tools/Date/NSDate+DateUtils.h | 8 +- YuMi/Tools/Date/NSDate+DateUtils.h.backup | 42 + YuMi/Tools/Date/NSDate+DateUtils.m | 34 +- YuMi/Tools/Date/NSDate+DateUtils.m.backup | 193 +++ YuMi/Tools/Date/NVDate.h | 189 ++- YuMi/Tools/Date/NVDate.h.backup | 95 ++ YuMi/Tools/Date/NVDate.m | 7 +- YuMi/Tools/Date/NVDate.m.backup | 394 +++++++ YuMi/Tools/Date/PLTimeUtil.h | 110 +- YuMi/Tools/Date/PLTimeUtil.h.backup | 59 + YuMi/Tools/Date/PLTimeUtil.m | 51 +- YuMi/Tools/Date/PLTimeUtil.m.backup | 307 +++++ .../{UploadFile.h => UploadFile.h.backup} | 0 .../{UploadFile.m => UploadFile.m.backup} | 0 ...adFileModel.h => UploadFileModel.h.backup} | 0 ...adFileModel.m => UploadFileModel.m.backup} | 0 YuMi/Tools/GCDHelper/GCDHelper.h | 18 +- YuMi/Tools/GCDHelper/GCDHelper.h.backup | 11 + YuMi/Tools/GCDHelper/GCDHelper.m | 8 +- YuMi/Tools/GCDHelper/GCDHelper.m.backup | 16 + YuMi/Tools/MJExtension/NSObject+MJExtension.h | 28 +- .../MJExtension/NSObject+MJExtension.h.backup | 43 + YuMi/Tools/MJExtension/NSObject+MJExtension.m | 28 +- .../MJExtension/NSObject+MJExtension.m.backup | 64 + YuMi/Tools/MedalMediaDisplayManager.h | 64 +- YuMi/Tools/MedalMediaDisplayManager.h.backup | 101 ++ YuMi/Tools/MedalMediaDisplayManager.m | 34 +- YuMi/Tools/MedalMediaDisplayManager.m.backup | 328 ++++++ YuMi/Tools/NSString/NSString+Utils.h | 33 +- YuMi/Tools/NSString/NSString+Utils.h.backup | 64 + YuMi/Tools/NSString/NSString+Utils.m | 192 ++- YuMi/Tools/NSString/NSString+Utils.m.backup | 524 +++++++++ YuMi/Tools/Reachability/YYReachability.h | 208 ++-- .../Reachability/YYReachability.h.backup | 109 ++ YuMi/Tools/Reachability/YYReachability.m | 61 +- .../Reachability/YYReachability.m.backup | 527 +++++++++ .../Tools/SDPhotoBrowser/SDBrowserImageView.h | 52 +- .../SDBrowserImageView.h.backup | 27 + .../Tools/SDPhotoBrowser/SDBrowserImageView.m | 22 +- .../SDBrowserImageView.m.backup | 237 ++++ YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h | 76 +- .../SDPhotoBrowser/SDPhotoBrowser.h.backup | 39 + YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m | 36 +- .../SDPhotoBrowser/SDPhotoBrowser.m.backup | 407 +++++++ .../SDPhotoBrowser/SDPhotoBrowserConfig.h | 80 +- .../SDPhotoBrowserConfig.h.backup | 42 + YuMi/Tools/SDPhotoBrowser/SDWaitingView.h | 32 +- .../SDPhotoBrowser/SDWaitingView.h.backup | 17 + YuMi/Tools/SDPhotoBrowser/SDWaitingView.m | 23 +- .../SDPhotoBrowser/SDWaitingView.m.backup | 93 ++ YuMi/Tools/Safe/NSArray+Safe.h | 8 +- YuMi/Tools/Safe/NSArray+Safe.h.backup | 16 + YuMi/Tools/Safe/NSArray+Safe.m | 8 +- YuMi/Tools/Safe/NSArray+Safe.m.backup | 23 + YuMi/Tools/Safe/NSMutableArray+Safe.h | 50 +- YuMi/Tools/Safe/NSMutableArray+Safe.h.backup | 64 + YuMi/Tools/Safe/NSMutableArray+Safe.m | 12 +- YuMi/Tools/Safe/NSMutableArray+Safe.m.backup | 69 ++ YuMi/Tools/Safe/NSMutableDictionary+Saft.h | 8 +- .../Safe/NSMutableDictionary+Saft.h.backup | 16 + YuMi/Tools/Safe/NSMutableDictionary+Saft.m | 8 +- .../Safe/NSMutableDictionary+Saft.m.backup | 17 + YuMi/Tools/Security/AESUtils.h | 8 +- YuMi/Tools/Security/AESUtils.h.backup | 19 + YuMi/Tools/Security/AESUtils.m | 50 +- YuMi/Tools/Security/AESUtils.m.backup | 151 +++ YuMi/Tools/Security/Base64.h | 30 +- YuMi/Tools/Security/Base64.h.backup | 16 + YuMi/Tools/Security/Base64.m | 8 +- YuMi/Tools/Security/Base64.m.backup | 133 +++ YuMi/Tools/Security/DESEncrypt.h | 30 +- YuMi/Tools/Security/DESEncrypt.h.backup | 16 + YuMi/Tools/Security/DESEncrypt.m | 10 +- YuMi/Tools/Security/DESEncrypt.m.backup | 63 + .../{XPWeakTimer.h => XPWeakTimer.h.backup} | 0 .../{XPWeakTimer.m => XPWeakTimer.m.backup} | 0 YuMi/Tools/Timestamp/Timestamp.h | 13 +- YuMi/Tools/Timestamp/Timestamp.h.backup | 20 + YuMi/Tools/Timestamp/Timestamp.m | 27 +- YuMi/Tools/Timestamp/Timestamp.m.backup | 68 ++ ...UILabel+Utils.h => UILabel+Utils.h.backup} | 0 ...UILabel+Utils.m => UILabel+Utils.m.backup} | 0 YuMi/Tools/YYUtility/CarrierIdentifier.h | 38 +- YuMi/Tools/YYUtility/YYUtility+App.m | 141 +-- YuMi/Tools/YYUtility/YYUtility+Carrier.m | 97 +- YuMi/Tools/YYUtility/YYUtility+Device.m | 260 +---- YuMi/Tools/YYUtility/YYUtility.h | 267 +---- YuMi/Tools/YYUtility/YYUtility.m | 8 +- .../catagory/3Party/fmdb/BSSDLayoutUtil.h | 20 +- .../3Party/fmdb/BSSDLayoutUtil.h.backup | 31 + .../catagory/3Party/fmdb/BSSDLayoutUtil.m | 11 +- .../3Party/fmdb/BSSDLayoutUtil.m.backup | 17 + .../sdkContent/catagory/Util/BSNSDictionary.h | 27 +- .../catagory/Util/BSNSDictionary.h.backup | 39 + .../sdkContent/catagory/Util/BSNSDictionary.m | 10 +- .../catagory/Util/BSNSDictionary.m.backup | 47 + .../sdkContent/catagory/Util/BSNSStringUtil.h | 45 +- .../catagory/Util/BSNSStringUtil.h.backup | 71 ++ .../sdkContent/catagory/Util/BSNSStringUtil.m | 32 +- .../catagory/Util/BSNSStringUtil.m.backup | 168 +++ .../sdkContent/catagory/Util/BSUIDemoUtil.h | 10 +- .../catagory/Util/BSUIDemoUtil.h.backup | 17 + .../sdkContent/catagory/Util/BSUIDemoUtil.m | 14 +- .../catagory/Util/BSUIDemoUtil.m.backup | 33 + .../sdkContent/catagory/Util/BSXWDateUtil.h | 74 +- .../catagory/Util/BSXWDateUtil.h.backup | 106 ++ .../sdkContent/catagory/Util/BSXWDateUtil.m | 41 +- .../catagory/Util/BSXWDateUtil.m.backup | 222 ++++ .../sdkContent/catagory/Util/BS_UIColor.h | 8 +- .../catagory/Util/BS_UIColor.h.backup | 16 + .../sdkContent/catagory/Util/BS_UIColor.m | 8 +- .../catagory/Util/BS_UIColor.m.backup | 31 + .../sdkContent/catagory/system/BS_Define.h | 12 +- .../catagory/system/BS_Define.h.backup | 32 + .../sdkContent/catagory/system/SystemUtil.h | 12 +- .../catagory/system/SystemUtil.h.backup | 18 + .../sdkContent/catagory/system/SystemUtil.m | 22 +- .../catagory/system/SystemUtil.m.backup | 35 + .../system/UILabel+YBAttributeTextTapAction.h | 37 +- .../UILabel+YBAttributeTextTapAction.h.backup | 62 + .../system/UILabel+YBAttributeTextTapAction.m | 7 +- .../UILabel+YBAttributeTextTapAction.m.backup | 396 +++++++ .../FileOption(文件操作)/BSFileOptionModel.h | 20 +- .../BSFileOptionModel.h.backup | 32 + .../FileOption(文件操作)/BSFileOptionModel.m | 59 +- .../BSFileOptionModel.m.backup | 206 ++++ YuMi/Tools/sdkContent/content/K/BSDrawLine.h | 61 +- .../sdkContent/content/K/BSDrawLine.h.backup | 90 ++ YuMi/Tools/sdkContent/content/K/BSDrawLine.m | 179 ++- .../sdkContent/content/K/BSDrawLine.m.backup | 530 +++++++++ YuMi/Tools/sdkContent/content/K/BSkObject.h | 37 +- .../sdkContent/content/K/BSkObject.h.backup | 45 + YuMi/Tools/sdkContent/content/K/BSkObject.m | 8 +- .../sdkContent/content/K/BSkObject.m.backup | 14 + .../NetListen(网络监听)/BSNetListenModel.h | 29 +- .../BSNetListenModel.h.backup | 60 + .../NetListen(网络监听)/BSNetListenModel.m | 48 +- .../BSNetListenModel.m.backup | 263 +++++ .../RealTime(实时)/BSLogNetDetailViewController.h | 9 +- .../BSLogNetDetailViewController.h.backup | 18 + .../RealTime(实时)/BSLogNetDetailViewController.m | 20 +- .../BSLogNetDetailViewController.m.backup | 90 ++ .../RealTime(实时)/BSLogTableViewController.h | 8 +- .../BSLogTableViewController.h.backup | 13 + .../RealTime(实时)/BSLogTableViewController.m | 36 +- .../BSLogTableViewController.m.backup | 260 +++++ .../RealTime(实时)/BSRealTextView.h | 10 +- .../RealTime(实时)/BSRealTextView.h.backup | 19 + .../RealTime(实时)/BSRealTextView.m | 26 +- .../RealTime(实时)/BSRealTextView.m.backup | 154 +++ .../RealTime(实时)/BSRealTimeView.h | 10 +- .../RealTime(实时)/BSRealTimeView.h.backup | 20 + .../RealTime(实时)/BSRealTimeView.m | 136 +-- .../RealTime(实时)/BSRealTimeView.m.backup | 613 ++++++++++ .../RealTime(实时)/model/RealViewCellModel.h | 15 +- .../model/RealViewCellModel.h.backup | 45 + .../RealTime(实时)/model/RealViewCellModel.m | 8 +- .../model/RealViewCellModel.m.backup | 13 + .../RealTime(实时)/view/RealViewNetWorkCell_0.h | 8 +- .../view/RealViewNetWorkCell_0.h.backup | 21 + .../RealTime(实时)/view/RealViewNetWorkCell_0.m | 37 +- .../view/RealViewNetWorkCell_0.m.backup | 154 +++ .../component(组件)/BSSelectView.h | 22 +- .../component(组件)/BSSelectView.h.backup | 29 + .../component(组件)/BSSelectView.m | 9 +- .../component(组件)/BSSelectView.m.backup | 71 ++ .../NetListen(网络监听)/model/BSRecordModel.h | 30 +- .../model/BSRecordModel.h.backup | 50 + .../NetListen(网络监听)/model/BSRecordModel.m | 10 +- .../model/BSRecordModel.m.backup | 89 ++ .../XWNotification(通知)/BSNotification.h | 82 +- .../BSNotification.h.backup | 132 +++ .../XWNotification(通知)/BSNotification.m | 34 +- .../BSNotification.m.backup | 193 +++ YuMi/YuMi-Bridging-Header.h | 29 +- YuMi/YuMi-Bridging-Header.h.backup | 90 ++ YuMi/en.lproj/InfoPlist.strings | 1 - YuMi/main.m | 2 +- YuMi/main.m.backup | 13 + analyze_macro_usage.py | 282 +++++ clean_comments.sh | 187 +++ remove_comments.py | 451 +++++++ test_comment_removal.m | 64 + test_doc_comment.m | 42 + 622 files changed, 40518 insertions(+), 7298 deletions(-) create mode 100644 YuMi/Appdelegate/AppDelegate.h.backup create mode 100644 YuMi/Appdelegate/AppDelegate.m.backup create mode 100644 YuMi/Config/APIConfig.swift.backup create mode 100644 YuMi/CustomUI/DJDKMIMOMColor.h.backup create mode 100644 YuMi/CustomUI/DJDKMIMOMColor.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Service/TTPopupService.h.backup create mode 100644 YuMi/CustomUI/TTPopup/Service/TTPopupService.m.backup create mode 100644 YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h.backup create mode 100644 YuMi/CustomUI/TTPopup/TTPopup.h.backup create mode 100644 YuMi/CustomUI/TTPopup/TTPopup.m.backup create mode 100644 YuMi/CustomUI/TTPopup/View/TTActionSheetView.h.backup create mode 100644 YuMi/CustomUI/TTPopup/View/TTActionSheetView.m.backup create mode 100644 YuMi/CustomUI/TTPopup/View/TTAlertView.h.backup create mode 100644 YuMi/CustomUI/TTPopup/View/TTAlertView.m.backup create mode 100644 YuMi/CustomUI/TTPopup/View/TTNewAlertView.h.backup create mode 100644 YuMi/CustomUI/TTPopup/View/TTNewAlertView.m.backup create mode 100644 YuMi/CustomUI/UIImage/UIImage+Utils.h.backup create mode 100644 YuMi/CustomUI/UIImage/UIImage+Utils.m.backup create mode 100644 YuMi/CustomUI/UIImageView/NetImageConfig.h.backup create mode 100644 YuMi/CustomUI/UIImageView/NetImageConfig.m.backup create mode 100644 YuMi/CustomUI/UIImageView/NetImageView.h.backup create mode 100644 YuMi/CustomUI/UIImageView/NetImageView.m.backup create mode 100644 YuMi/CustomUI/UIImageView/UIImageConstant.h.backup create mode 100644 YuMi/CustomUI/UIImageView/UIImageConstant.m.backup create mode 100644 YuMi/CustomUI/UIViewCorner/UIView+Corner.h.backup create mode 100644 YuMi/CustomUI/UIViewCorner/UIView+Corner.m.backup create mode 100644 YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h.backup create mode 100644 YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m.backup create mode 100755 YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h.backup create mode 100755 YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m.backup create mode 100644 YuMi/CustomUI/XCCurrentVCStackManager.h.backup create mode 100644 YuMi/CustomUI/XCCurrentVCStackManager.m.backup create mode 100644 YuMi/CustomUI/XNDJTDDLoadingTool.h.backup create mode 100644 YuMi/CustomUI/XNDJTDDLoadingTool.m.backup create mode 100644 YuMi/E-P/Common/EPImageUploader.swift.backup create mode 100644 YuMi/E-P/Common/EPProgressHUD.swift.backup create mode 100644 YuMi/E-P/Common/EPQCloudConfig.swift.backup create mode 100644 YuMi/E-P/Common/EPSDKManager.swift.backup create mode 100644 YuMi/E-P/Login/Controllers/EPLoginTypesViewController.swift rename YuMi/E-P/{NewLogin/Controllers/EPLoginTypesViewController.swift => Login/Controllers/EPLoginTypesViewController.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Controllers/EPLoginViewController.swift rename YuMi/E-P/{NewLogin/Controllers/EPLoginViewController.swift => Login/Controllers/EPLoginViewController.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Models/EPLoginBridge.swift rename YuMi/E-P/{NewLogin/Models/EPLoginBridge.swift => Login/Models/EPLoginBridge.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Models/EPLoginConfig.swift rename YuMi/E-P/{NewLogin/Models/EPLoginConfig.swift => Login/Models/EPLoginConfig.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Models/EPLoginState.swift rename YuMi/E-P/{NewLogin/Models/EPLoginState.swift => Login/Models/EPLoginState.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Services/EPLoginManager.swift rename YuMi/E-P/{NewLogin/Services/EPLoginManager.swift => Login/Services/EPLoginManager.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Services/EPLoginService.swift rename YuMi/E-P/{NewLogin/Services/EPLoginService.swift => Login/Services/EPLoginService.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Views/EPLoginButton.swift rename YuMi/E-P/{NewLogin/Views/EPLoginButton.swift => Login/Views/EPLoginButton.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Views/EPLoginInputView.swift rename YuMi/E-P/{NewLogin/Views/EPLoginInputView.swift => Login/Views/EPLoginInputView.swift.backup} (100%) create mode 100644 YuMi/E-P/Login/Views/EPPolicyLabel.swift rename YuMi/E-P/{NewLogin/Views/EPPolicyLabel.swift => Login/Views/EPPolicyLabel.swift.backup} (100%) create mode 100644 YuMi/E-P/Mine/Controllers/EPAboutUsViewController.swift rename YuMi/E-P/{NewMine/Controllers/EPAboutUsViewController.swift => Mine/Controllers/EPAboutUsViewController.swift.backup} (100%) create mode 100644 YuMi/E-P/Mine/Controllers/EPEditSettingViewController.swift rename YuMi/E-P/{NewMine/Controllers/EPEditSettingViewController.swift => Mine/Controllers/EPEditSettingViewController.swift.backup} (100%) create mode 100644 YuMi/E-P/Mine/Controllers/EPMineViewController.h rename YuMi/E-P/{NewMine/Controllers/EPMineViewController.h => Mine/Controllers/EPMineViewController.h.backup} (100%) create mode 100644 YuMi/E-P/Mine/Controllers/EPMineViewController.m rename YuMi/E-P/{NewMine/Controllers/EPMineViewController.m => Mine/Controllers/EPMineViewController.m.backup} (100%) create mode 100644 YuMi/E-P/Mine/Services/EPMineAPIHelper.h rename YuMi/E-P/{NewMine/Services/EPMineAPIHelper.h => Mine/Services/EPMineAPIHelper.h.backup} (100%) create mode 100644 YuMi/E-P/Mine/Services/EPMineAPIHelper.m rename YuMi/E-P/{NewMine/Services/EPMineAPIHelper.m => Mine/Services/EPMineAPIHelper.m.backup} (100%) create mode 100644 YuMi/E-P/Mine/Views/EPMineHeaderView.h rename YuMi/E-P/{NewMine/Views/EPMineHeaderView.h => Mine/Views/EPMineHeaderView.h.backup} (100%) create mode 100644 YuMi/E-P/Mine/Views/EPMineHeaderView.m rename YuMi/E-P/{NewMine/Views/EPMineHeaderView.m => Mine/Views/EPMineHeaderView.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.h rename YuMi/E-P/{NewMoments/Controllers/EPMomentPublishViewController.h => Moments/Controllers/EPMomentPublishViewController.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.m rename YuMi/E-P/{NewMoments/Controllers/EPMomentPublishViewController.m => Moments/Controllers/EPMomentPublishViewController.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Controllers/EPMomentViewController.h rename YuMi/E-P/{NewMoments/Controllers/EPMomentViewController.h => Moments/Controllers/EPMomentViewController.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Controllers/EPMomentViewController.m rename YuMi/E-P/{NewMoments/Controllers/EPMomentViewController.m => Moments/Controllers/EPMomentViewController.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Services/EPEmotionColorStorage.h rename YuMi/E-P/{NewMoments/Services/EPEmotionColorStorage.h => Moments/Services/EPEmotionColorStorage.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Services/EPEmotionColorStorage.m rename YuMi/E-P/{NewMoments/Services/EPEmotionColorStorage.m => Moments/Services/EPEmotionColorStorage.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Services/EPMomentAPISwiftHelper.swift rename YuMi/E-P/{NewMoments/Services/EPMomentAPISwiftHelper.swift => Moments/Services/EPMomentAPISwiftHelper.swift.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPEmotionColorPicker.h rename YuMi/E-P/{NewMoments/Views/EPEmotionColorPicker.h => Moments/Views/EPEmotionColorPicker.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPEmotionColorPicker.m rename YuMi/E-P/{NewMoments/Views/EPEmotionColorPicker.m => Moments/Views/EPEmotionColorPicker.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPEmotionColorWheelView.h rename YuMi/E-P/{NewMoments/Views/EPEmotionColorWheelView.h => Moments/Views/EPEmotionColorWheelView.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPEmotionColorWheelView.m rename YuMi/E-P/{NewMoments/Views/EPEmotionColorWheelView.m => Moments/Views/EPEmotionColorWheelView.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPEmotionInfoView.h rename YuMi/E-P/{NewMoments/Views/EPEmotionInfoView.h => Moments/Views/EPEmotionInfoView.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPEmotionInfoView.m rename YuMi/E-P/{NewMoments/Views/EPEmotionInfoView.m => Moments/Views/EPEmotionInfoView.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPMomentCell.h rename YuMi/E-P/{NewMoments/Views/EPMomentCell.h => Moments/Views/EPMomentCell.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPMomentCell.m rename YuMi/E-P/{NewMoments/Views/EPMomentCell.m => Moments/Views/EPMomentCell.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPMomentListView.h rename YuMi/E-P/{NewMoments/Views/EPMomentListView.h => Moments/Views/EPMomentListView.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPMomentListView.m rename YuMi/E-P/{NewMoments/Views/EPMomentListView.m => Moments/Views/EPMomentListView.m.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPSignatureColorGuideView.h rename YuMi/E-P/{NewMoments/Views/EPSignatureColorGuideView.h => Moments/Views/EPSignatureColorGuideView.h.backup} (100%) create mode 100644 YuMi/E-P/Moments/Views/EPSignatureColorGuideView.m rename YuMi/E-P/{NewMoments/Views/EPSignatureColorGuideView.m => Moments/Views/EPSignatureColorGuideView.m.backup} (100%) create mode 100644 YuMi/E-P/TabBar/EPTabBarController.swift rename YuMi/E-P/{NewTabBar/EPTabBarController.swift => TabBar/EPTabBarController.swift.backup} (100%) create mode 100644 YuMi/Global/BuglyManagerExample.h.backup create mode 100644 YuMi/Global/BuglyManagerExample.m.backup create mode 100644 YuMi/Global/YUMIConstant.h.backup create mode 100644 YuMi/Global/YUMIConstant.m.backup create mode 100644 YuMi/Global/YUMIHtmlUrl.h.backup create mode 100644 YuMi/Global/YUMIHtmlUrl.m.backup create mode 100644 YuMi/Global/YUMINNNN.h.backup create mode 100644 YuMi/Modules/YMLogin/Api/Api+Login.h.backup create mode 100644 YuMi/Modules/YMLogin/Api/Api+Login.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h.backup create mode 100644 YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m.backup create mode 100644 YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m.backup create mode 100644 YuMi/Modules/YMMine/Api/Api(GameOrder).h.backup create mode 100644 YuMi/Modules/YMMine/Api/Api(GameOrder).m.backup create mode 100644 YuMi/Modules/YMMine/Api/Api+Mine.h.backup create mode 100644 YuMi/Modules/YMMine/Api/Api+Mine.m.backup create mode 100644 YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m.backup create mode 100644 YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m.backup create mode 100644 YuMi/Modules/YMMonents/Api/Api+Moments.h.backup create mode 100644 YuMi/Modules/YMMonents/Api/Api+Moments.m.backup create mode 100644 YuMi/Modules/YMMonents/Model/MomentsInfoModel.h.backup create mode 100644 YuMi/Modules/YMMonents/Model/MomentsInfoModel.m.backup create mode 100644 YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h.backup create mode 100644 YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m.backup create mode 100644 YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h.backup create mode 100644 YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m.backup create mode 100644 YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m.backup create mode 100644 YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h.backup create mode 100644 YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m.backup create mode 100644 YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h.backup create mode 100644 YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m.backup create mode 100644 YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h.backup create mode 100644 YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h.backup create mode 100644 YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m.backup create mode 100644 YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m.backup create mode 100644 YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m.backup create mode 100644 YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h.backup create mode 100644 YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m.backup create mode 100644 YuMi/Modules/YMTabbar/Api/Api+Main.h.backup create mode 100644 YuMi/Modules/YMTabbar/Api/Api+Main.m.backup create mode 100644 YuMi/Modules/YMWeb/MSRoomGameWebVC.h.backup create mode 100644 YuMi/Modules/YMWeb/MSRoomGameWebVC.m.backup create mode 100644 YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h.backup create mode 100644 YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m.backup create mode 100644 YuMi/Modules/YMWeb/XPWebViewController.h.backup create mode 100644 YuMi/Modules/YMWeb/XPWebViewController.m.backup create mode 100644 YuMi/Modules/YMWeb/XPWebViewNavView.h.backup create mode 100644 YuMi/Modules/YMWeb/XPWebViewNavView.m.backup create mode 100644 YuMi/Network/HttpRequestHelper.h.backup create mode 100644 YuMi/Network/HttpRequestHelper.m.backup create mode 100644 YuMi/Network/MSParamsDecode.h.backup create mode 100644 YuMi/Network/MSParamsDecode.m.backup create mode 100644 YuMi/Structure/Base/BaseNavigationController.h.backup create mode 100644 YuMi/Structure/Base/BaseNavigationController.m.backup create mode 100644 YuMi/Structure/Base/BaseViewController.h.backup create mode 100644 YuMi/Structure/Base/BaseViewController.m.backup create mode 100644 YuMi/Structure/MVP/Api/Api.h.backup create mode 100644 YuMi/Structure/MVP/Api/Api.m.backup create mode 100644 YuMi/Structure/MVP/Model/AccountInfoStorage.h.backup create mode 100644 YuMi/Structure/MVP/Model/AccountInfoStorage.m.backup create mode 100644 YuMi/Structure/MVP/Model/AccountModel.h.backup create mode 100644 YuMi/Structure/MVP/Model/AccountModel.m.backup create mode 100644 YuMi/Structure/MVP/Model/BaseModel.h.backup create mode 100644 YuMi/Structure/MVP/Model/BaseModel.m.backup create mode 100644 YuMi/Structure/MVP/Model/NSObject+AutoCoding.h.backup create mode 100644 YuMi/Structure/MVP/Model/NSObject+AutoCoding.m.backup create mode 100644 YuMi/Structure/MVP/Model/PIBaseModel.h.backup create mode 100644 YuMi/Structure/MVP/Model/PIBaseModel.m.backup create mode 100644 YuMi/Structure/MVP/Model/UserInfoModel.h.backup create mode 100644 YuMi/Structure/MVP/Model/UserInfoModel.m.backup create mode 100644 YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h.backup create mode 100644 YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m.backup create mode 100644 YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h.backup create mode 100644 YuMi/Structure/MVP/View/MvpViewController.h.backup create mode 100644 YuMi/Structure/MVP/View/MvpViewController.m.backup create mode 100644 YuMi/Tools/Bundle/NSBundle+Localizable.h.backup create mode 100644 YuMi/Tools/Bundle/NSBundle+Localizable.m.backup create mode 100644 YuMi/Tools/Bundle/YMLanguageConfig.h.backup create mode 100644 YuMi/Tools/Bundle/YMLanguageConfig.m.backup create mode 100644 YuMi/Tools/CountDown/CountDownHelper.h.backup create mode 100644 YuMi/Tools/CountDown/CountDownHelper.m.backup create mode 100644 YuMi/Tools/Date/NSDate+DateUtils.h.backup create mode 100644 YuMi/Tools/Date/NSDate+DateUtils.m.backup create mode 100644 YuMi/Tools/Date/NVDate.h.backup create mode 100644 YuMi/Tools/Date/NVDate.m.backup create mode 100644 YuMi/Tools/Date/PLTimeUtil.h.backup create mode 100644 YuMi/Tools/Date/PLTimeUtil.m.backup rename YuMi/Tools/File/{UploadFile.h => UploadFile.h.backup} (100%) rename YuMi/Tools/File/{UploadFile.m => UploadFile.m.backup} (100%) rename YuMi/Tools/File/{UploadFileModel.h => UploadFileModel.h.backup} (100%) rename YuMi/Tools/File/{UploadFileModel.m => UploadFileModel.m.backup} (100%) create mode 100644 YuMi/Tools/GCDHelper/GCDHelper.h.backup create mode 100644 YuMi/Tools/GCDHelper/GCDHelper.m.backup create mode 100644 YuMi/Tools/MJExtension/NSObject+MJExtension.h.backup create mode 100644 YuMi/Tools/MJExtension/NSObject+MJExtension.m.backup create mode 100644 YuMi/Tools/MedalMediaDisplayManager.h.backup create mode 100644 YuMi/Tools/MedalMediaDisplayManager.m.backup create mode 100644 YuMi/Tools/NSString/NSString+Utils.h.backup create mode 100644 YuMi/Tools/NSString/NSString+Utils.m.backup create mode 100644 YuMi/Tools/Reachability/YYReachability.h.backup create mode 100644 YuMi/Tools/Reachability/YYReachability.m.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDWaitingView.h.backup create mode 100755 YuMi/Tools/SDPhotoBrowser/SDWaitingView.m.backup create mode 100644 YuMi/Tools/Safe/NSArray+Safe.h.backup create mode 100644 YuMi/Tools/Safe/NSArray+Safe.m.backup create mode 100644 YuMi/Tools/Safe/NSMutableArray+Safe.h.backup create mode 100644 YuMi/Tools/Safe/NSMutableArray+Safe.m.backup create mode 100644 YuMi/Tools/Safe/NSMutableDictionary+Saft.h.backup create mode 100644 YuMi/Tools/Safe/NSMutableDictionary+Saft.m.backup create mode 100644 YuMi/Tools/Security/AESUtils.h.backup create mode 100644 YuMi/Tools/Security/AESUtils.m.backup create mode 100644 YuMi/Tools/Security/Base64.h.backup create mode 100644 YuMi/Tools/Security/Base64.m.backup create mode 100644 YuMi/Tools/Security/DESEncrypt.h.backup create mode 100644 YuMi/Tools/Security/DESEncrypt.m.backup rename YuMi/Tools/Timer/{XPWeakTimer.h => XPWeakTimer.h.backup} (100%) rename YuMi/Tools/Timer/{XPWeakTimer.m => XPWeakTimer.m.backup} (100%) create mode 100644 YuMi/Tools/Timestamp/Timestamp.h.backup create mode 100644 YuMi/Tools/Timestamp/Timestamp.m.backup rename YuMi/Tools/UILabel/{UILabel+Utils.h => UILabel+Utils.h.backup} (100%) rename YuMi/Tools/UILabel/{UILabel+Utils.m => UILabel+Utils.m.backup} (100%) create mode 100644 YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m.backup create mode 100644 YuMi/Tools/sdkContent/catagory/system/BS_Define.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/system/SystemUtil.h.backup create mode 100644 YuMi/Tools/sdkContent/catagory/system/SystemUtil.m.backup create mode 100755 YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h.backup create mode 100755 YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m.backup create mode 100644 YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h.backup create mode 100644 YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m.backup create mode 100644 YuMi/Tools/sdkContent/content/K/BSDrawLine.h.backup create mode 100644 YuMi/Tools/sdkContent/content/K/BSDrawLine.m.backup create mode 100644 YuMi/Tools/sdkContent/content/K/BSkObject.h.backup create mode 100644 YuMi/Tools/sdkContent/content/K/BSkObject.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h.backup create mode 100644 YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m.backup create mode 100644 YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h.backup create mode 100644 YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m.backup create mode 100644 YuMi/YuMi-Bridging-Header.h.backup create mode 100644 YuMi/main.m.backup create mode 100755 analyze_macro_usage.py create mode 100755 clean_comments.sh create mode 100755 remove_comments.py create mode 100644 test_comment_removal.m create mode 100644 test_doc_comment.m diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index 9dfbf1e..6391cad 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -34,7 +34,6 @@ 18E7B31826F097E00064BC9B /* UserInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E7B31726F097E00064BC9B /* UserInfoModel.m */; }; 23116B0B2BDB8FDC00F7F97A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 2368ECD72BC38FED00EDF4C9 /* PrivacyInfo.xcprivacy */; }; 232EBBFF2BD7A25500E8CEAD /* MSParamsDecode.m in Sources */ = {isa = PBXBuildFile; fileRef = 232EBBFE2BD7A25500E8CEAD /* MSParamsDecode.m */; }; - 2331C1BD2A60F69E00E1D940 /* UILabel+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 2331C1BC2A60F69E00E1D940 /* UILabel+Utils.m */; }; 235A45232B04BEB6009753F5 /* PIBaseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 235A45222B04BEB6009753F5 /* PIBaseModel.m */; }; 2368ECCF2BC38F9800EDF4C9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2368ECCD2BC38F9800EDF4C9 /* InfoPlist.strings */; }; 2368ECD32BC38FDA00EDF4C9 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2368ECD52BC38FDA00EDF4C9 /* Launch Screen.storyboard */; }; @@ -45,7 +44,6 @@ 2377010E2BCF73F400D661F1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2377010D2BCF73F400D661F1 /* CoreGraphics.framework */; }; 237701102BCF740400D661F1 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 2377010F2BCF740400D661F1 /* libsqlite3.tbd */; }; 237701122BCF742C00D661F1 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 237701112BCF742C00D661F1 /* libz.tbd */; }; - 23959FE72BB15C930085A282 /* UploadFileModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 23959FE62BB15C930085A282 /* UploadFileModel.m */; }; 23CEFC4A2AFB8FC100576D89 /* BSNSStringUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 23CEFC0C2AFB8FC100576D89 /* BSNSStringUtil.m */; }; 23CEFC4B2AFB8FC100576D89 /* BSUIDemoUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 23CEFC0D2AFB8FC100576D89 /* BSUIDemoUtil.m */; }; 23CEFC4C2AFB8FC100576D89 /* BS_UIColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 23CEFC0F2AFB8FC100576D89 /* BS_UIColor.m */; }; @@ -138,11 +136,9 @@ 4CF464322EA1277C005E96C0 /* TTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CF464222EA1277C005E96C0 /* TTAlertView.m */; }; 73FFADDC93E195344047A2EC /* Pods_YuMi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CACF623970097D653132D69A /* Pods_YuMi.framework */; }; 9B0E1C5926E77022005D4442 /* BaseNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E1C5826E77022005D4442 /* BaseNavigationController.m */; }; - 9B33E3CB27D85379003B0E62 /* UploadFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B33E3C927D85379003B0E62 /* UploadFile.m */; }; 9BA8A47527C60D9F000365A3 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BA8A47427C60D9F000365A3 /* AudioToolbox.framework */; }; 9BA8A47727C60DF7000365A3 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BA8A47627C60DF7000365A3 /* AVFoundation.framework */; }; E8098CA7282E00920090B9F0 /* Api+Moments.m in Sources */ = {isa = PBXBuildFile; fileRef = E8098CA6282E00920090B9F0 /* Api+Moments.m */; }; - E80CBDEA27D0C53F001E1EC2 /* XPWeakTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = E80CBDE927D0C53F001E1EC2 /* XPWeakTimer.m */; }; E80E09A92A40B70100CD2BE7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E80E09AB2A40B70100CD2BE7 /* Localizable.strings */; }; E80E2377299A47F60013FD40 /* AESUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E80E2376299A47F60013FD40 /* AESUtils.m */; }; E81366E726F0A49E0076364C /* NSString+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = E81366E626F0A49E0076364C /* NSString+Utils.m */; }; @@ -237,8 +233,6 @@ 18E7B31726F097E00064BC9B /* UserInfoModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UserInfoModel.m; sourceTree = ""; }; 232EBBFD2BD7A25500E8CEAD /* MSParamsDecode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSParamsDecode.h; sourceTree = ""; }; 232EBBFE2BD7A25500E8CEAD /* MSParamsDecode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSParamsDecode.m; sourceTree = ""; }; - 2331C1BB2A60F69E00E1D940 /* UILabel+Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UILabel+Utils.h"; sourceTree = ""; }; - 2331C1BC2A60F69E00E1D940 /* UILabel+Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UILabel+Utils.m"; sourceTree = ""; }; 235A45212B04BEB6009753F5 /* PIBaseModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PIBaseModel.h; sourceTree = ""; }; 235A45222B04BEB6009753F5 /* PIBaseModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PIBaseModel.m; sourceTree = ""; }; 2368ECCA2BC38F6F00EDF4C9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; @@ -254,8 +248,6 @@ 2377010D2BCF73F400D661F1 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 2377010F2BCF740400D661F1 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; 237701112BCF742C00D661F1 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - 23959FE52BB15C930085A282 /* UploadFileModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadFileModel.h; sourceTree = ""; }; - 23959FE62BB15C930085A282 /* UploadFileModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UploadFileModel.m; sourceTree = ""; }; 23CEFC0B2AFB8FC100576D89 /* BSXWDateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSXWDateUtil.h; sourceTree = ""; }; 23CEFC0C2AFB8FC100576D89 /* BSNSStringUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSNSStringUtil.m; sourceTree = ""; }; 23CEFC0D2AFB8FC100576D89 /* BSUIDemoUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSUIDemoUtil.m; sourceTree = ""; }; @@ -417,16 +409,12 @@ 7DB00EC07F1D0ADFF900B38D /* Pods-YuMi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YuMi.debug.xcconfig"; path = "Target Support Files/Pods-YuMi/Pods-YuMi.debug.xcconfig"; sourceTree = ""; }; 9B0E1C5726E77022005D4442 /* BaseNavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseNavigationController.h; sourceTree = ""; }; 9B0E1C5826E77022005D4442 /* BaseNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseNavigationController.m; sourceTree = ""; }; - 9B33E3C927D85379003B0E62 /* UploadFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UploadFile.m; sourceTree = ""; }; - 9B33E3CA27D85379003B0E62 /* UploadFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UploadFile.h; sourceTree = ""; }; 9BA8A47427C60D9F000365A3 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 9BA8A47627C60DF7000365A3 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; B66633E061B1B34177CD011C /* Pods-YuMi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YuMi.release.xcconfig"; path = "Target Support Files/Pods-YuMi/Pods-YuMi.release.xcconfig"; sourceTree = ""; }; CACF623970097D653132D69A /* Pods_YuMi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_YuMi.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E8098CA5282E00920090B9F0 /* Api+Moments.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Api+Moments.h"; sourceTree = ""; }; E8098CA6282E00920090B9F0 /* Api+Moments.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "Api+Moments.m"; sourceTree = ""; }; - E80CBDE827D0C53F001E1EC2 /* XPWeakTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPWeakTimer.h; sourceTree = ""; }; - E80CBDE927D0C53F001E1EC2 /* XPWeakTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPWeakTimer.m; sourceTree = ""; }; E80E2375299A47F60013FD40 /* AESUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AESUtils.h; sourceTree = ""; }; E80E2376299A47F60013FD40 /* AESUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AESUtils.m; sourceTree = ""; }; E81366E526F0A49E0076364C /* NSString+Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+Utils.h"; sourceTree = ""; }; @@ -683,12 +671,9 @@ 23CEFC082AFB8FC100576D89 /* sdkContent */, E83645A42A40AEF600E0DBE4 /* Bundle */, E8F61356291E269700E12650 /* Safe */, - 9B33E3C827D85379003B0E62 /* File */, - E80CBDE727D0C528001E1EC2 /* Timer */, 180116F6279E8C3100F2CBC0 /* Date */, E88863D0278ED4A0004BCFAB /* Timestamp */, E8EEB8EA26FC2050007C6EBA /* SDPhotoBrowser */, - 2331C1BA2A60F67F00E1D940 /* UILabel */, E81366E426F0A4820076364C /* NSString */, E82109AA26F1C86E00FC3319 /* CountDown */, E81C278726EAFABF0031E639 /* Security */, @@ -748,15 +733,6 @@ path = YMTabbar; sourceTree = ""; }; - 2331C1BA2A60F67F00E1D940 /* UILabel */ = { - isa = PBXGroup; - children = ( - 2331C1BB2A60F69E00E1D940 /* UILabel+Utils.h */, - 2331C1BC2A60F69E00E1D940 /* UILabel+Utils.m */, - ); - path = UILabel; - sourceTree = ""; - }; 236B2E1B2AA0786E003967A8 /* Library */ = { isa = PBXGroup; children = ( @@ -971,14 +947,14 @@ path = Views; sourceTree = ""; }; - 4C0642752E97BD6D00BAF413 /* NewMine */ = { + 4C0642752E97BD6D00BAF413 /* Mine */ = { isa = PBXGroup; children = ( 4C1E98BE2E9A3A540031AE79 /* Services */, 4C0642712E97BD6D00BAF413 /* Controllers */, 4C0642742E97BD6D00BAF413 /* Views */, ); - path = NewMine; + path = Mine; sourceTree = ""; }; 4C0642782E97BD6D00BAF413 /* Controllers */ = { @@ -1011,32 +987,32 @@ path = Views; sourceTree = ""; }; - 4C06427C2E97BD6D00BAF413 /* NewMoments */ = { + 4C06427C2E97BD6D00BAF413 /* Moments */ = { isa = PBXGroup; children = ( 4C0642952E98F76F00BAF413 /* Services */, 4C0642782E97BD6D00BAF413 /* Controllers */, 4C06427B2E97BD6D00BAF413 /* Views */, ); - path = NewMoments; + path = Moments; sourceTree = ""; }; - 4C06427E2E97BD6D00BAF413 /* NewTabBar */ = { + 4C06427E2E97BD6D00BAF413 /* TabBar */ = { isa = PBXGroup; children = ( 4C06428A2E98DC5F00BAF413 /* EPTabBarController.swift */, ); - path = NewTabBar; + path = TabBar; sourceTree = ""; }; 4C0642922E98EF0A00BAF413 /* E-P */ = { isa = PBXGroup; children = ( - 4CD19C852E9CB31C0069DAA0 /* NewLogin */, + 4CD19C852E9CB31C0069DAA0 /* Login */, 4C1E98C22E9A45160031AE79 /* Common */, - 4C0642752E97BD6D00BAF413 /* NewMine */, - 4C06427C2E97BD6D00BAF413 /* NewMoments */, - 4C06427E2E97BD6D00BAF413 /* NewTabBar */, + 4C0642752E97BD6D00BAF413 /* Mine */, + 4C06427C2E97BD6D00BAF413 /* Moments */, + 4C06427E2E97BD6D00BAF413 /* TabBar */, ); path = "E-P"; sourceTree = ""; @@ -1109,7 +1085,7 @@ path = Views; sourceTree = ""; }; - 4CD19C852E9CB31C0069DAA0 /* NewLogin */ = { + 4CD19C852E9CB31C0069DAA0 /* Login */ = { isa = PBXGroup; children = ( 4CD19C8D2E9CBBC80069DAA0 /* Services */, @@ -1117,7 +1093,7 @@ 4CD19C812E9CB31C0069DAA0 /* Models */, 4CD19C842E9CB31C0069DAA0 /* Views */, ); - path = NewLogin; + path = Login; sourceTree = ""; }; 4CD19C8D2E9CBBC80069DAA0 /* Services */ = { @@ -1328,17 +1304,6 @@ path = TTPopup; sourceTree = ""; }; - 9B33E3C827D85379003B0E62 /* File */ = { - isa = PBXGroup; - children = ( - 9B33E3CA27D85379003B0E62 /* UploadFile.h */, - 9B33E3C927D85379003B0E62 /* UploadFile.m */, - 23959FE52BB15C930085A282 /* UploadFileModel.h */, - 23959FE62BB15C930085A282 /* UploadFileModel.m */, - ); - path = File; - sourceTree = ""; - }; 9B9DFDA227DB4F68000F95B3 /* Recovered References */ = { isa = PBXGroup; children = ( @@ -1373,15 +1338,6 @@ path = Pods; sourceTree = ""; }; - E80CBDE727D0C528001E1EC2 /* Timer */ = { - isa = PBXGroup; - children = ( - E80CBDE827D0C53F001E1EC2 /* XPWeakTimer.h */, - E80CBDE927D0C53F001E1EC2 /* XPWeakTimer.m */, - ); - path = Timer; - sourceTree = ""; - }; E81366E426F0A4820076364C /* NSString */ = { isa = PBXGroup; children = ( @@ -1743,7 +1699,6 @@ 18E7B31826F097E00064BC9B /* UserInfoModel.m in Sources */, 4C0642912E98DC8700BAF413 /* EPMomentViewController.m in Sources */, 232EBBFF2BD7A25500E8CEAD /* MSParamsDecode.m in Sources */, - 23959FE72BB15C930085A282 /* UploadFileModel.m in Sources */, 189DD73F26E21C3F00AB55B1 /* YYUtility+Carrier.m in Sources */, 23CEFC5D2AFB8FC100576D89 /* BSRecordModel.m in Sources */, 9B0E1C5926E77022005D4442 /* BaseNavigationController.m in Sources */, @@ -1758,7 +1713,6 @@ 23CEFC622AFB8FC100576D89 /* BSLogNetDetailViewController.m in Sources */, 4C7B909B2E9F822900A5E236 /* EPEmotionColorWheelView.m in Sources */, 4C7B8F632E9F6E1300A5E236 /* EPSignatureColorGuideView.m in Sources */, - 9B33E3CB27D85379003B0E62 /* UploadFile.m in Sources */, 4CD19EAE2E9CDFC30069DAA0 /* EPLoginButton.swift in Sources */, 4CD19EAF2E9CDFC30069DAA0 /* EPLoginInputView.swift in Sources */, 4C0642852E97BD9500BAF413 /* APIConfig.swift in Sources */, @@ -1788,7 +1742,6 @@ 187EEEDC26E89B32002833B2 /* BaseModel.m in Sources */, E80E2377299A47F60013FD40 /* AESUtils.m in Sources */, 23CEFC642AFB8FC100576D89 /* BSkObject.m in Sources */, - 2331C1BD2A60F69E00E1D940 /* UILabel+Utils.m in Sources */, E83645A82A40AF5400E0DBE4 /* NSBundle+Localizable.m in Sources */, 4C06429C2E99120600BAF413 /* EPMomentPublishViewController.m in Sources */, 23CEFC632AFB8FC100576D89 /* BSRealTextView.m in Sources */, @@ -1816,7 +1769,6 @@ 4CD19C8E2E9CBBC80069DAA0 /* EPLoginService.swift in Sources */, 4CD19C8F2E9CBBC80069DAA0 /* EPLoginManager.swift in Sources */, 4C1E98BF2E9A3A540031AE79 /* EPMineAPIHelper.m in Sources */, - E80CBDEA27D0C53F001E1EC2 /* XPWeakTimer.m in Sources */, 189DD55026DE37F900AB55B1 /* MvpViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/YuMi/Appdelegate/AppDelegate.h b/YuMi/Appdelegate/AppDelegate.h index d4ddd22..a01bf30 100644 --- a/YuMi/Appdelegate/AppDelegate.h +++ b/YuMi/Appdelegate/AppDelegate.h @@ -1,9 +1,7 @@ -// -// AppDelegate.h -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import diff --git a/YuMi/Appdelegate/AppDelegate.h.backup b/YuMi/Appdelegate/AppDelegate.h.backup new file mode 100644 index 0000000..d4ddd22 --- /dev/null +++ b/YuMi/Appdelegate/AppDelegate.h.backup @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end + diff --git a/YuMi/Appdelegate/AppDelegate.m b/YuMi/Appdelegate/AppDelegate.m index 231713c..9f6ffce 100644 --- a/YuMi/Appdelegate/AppDelegate.m +++ b/YuMi/Appdelegate/AppDelegate.m @@ -1,9 +1,6 @@ -// -// AppDelegate.m -// YUMI -// + + // Created by admin on 2023/3/9. -// #import "AppDelegate.h" @@ -40,9 +37,9 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; // MARK: - Helper Methods -/// 获取 keyWindow(iOS 13+ 兼容) + - (UIWindow *)getKeyWindow { - // iOS 13+ 使用 connectedScenes 获取 window + if (@available(iOS 13.0, *)) { for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) { if (scene.activationState == UISceneActivationStateForegroundActive) { @@ -51,13 +48,13 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; return window; } } - // 如果没有 keyWindow,返回第一个 window + return scene.windows.firstObject; } } } - // iOS 13 以下,使用旧方法(已废弃但仍然可用) + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" return [UIApplication sharedApplication].keyWindow; @@ -74,44 +71,44 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; }else{ [self toHomeTabbarPage]; - // 延迟检查专属颜色(等待 window 初始化完成) + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self checkAndShowSignatureColorGuide]; }); } } -/// 检查并显示专属颜色引导页 + - (void)checkAndShowSignatureColorGuide { UIWindow *keyWindow = [self getKeyWindow]; if (!keyWindow) return; BOOL hasSignatureColor = [EPEmotionColorStorage hasUserSignatureColor]; -#if DEBUG - // Debug 环境:总是显示引导页 - NSLog(@"[AppDelegate] Debug 模式:显示专属颜色引导页(已有颜色: %@)", hasSignatureColor ? @"YES" : @"NO"); +//#if DEBUG +// +// NSLog(@"[AppDelegate] Debug 模式:显示专属颜色引导页(已有颜色: %@)", hasSignatureColor ? @"YES" : @"NO"); +// +// EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init]; +// +// +// guideView.onColorConfirmed = ^(NSString *hexColor) { +// [EPEmotionColorStorage saveUserSignatureColor:hexColor]; +// NSLog(@"[AppDelegate] 用户选择专属颜色: %@", hexColor); +// }; +// +// +// if (hasSignatureColor) { +// guideView.onSkipTapped = ^{ +// NSLog(@"[AppDelegate] 用户跳过专属颜色选择"); +// }; +// } +// +// +// [guideView showInWindow:keyWindow showSkipButton:hasSignatureColor]; +// +//#else - EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init]; - - // 设置颜色确认回调 - guideView.onColorConfirmed = ^(NSString *hexColor) { - [EPEmotionColorStorage saveUserSignatureColor:hexColor]; - NSLog(@"[AppDelegate] 用户选择专属颜色: %@", hexColor); - }; - - // 如果已有颜色,设置 Skip 回调 - if (hasSignatureColor) { - guideView.onSkipTapped = ^{ - NSLog(@"[AppDelegate] 用户跳过专属颜色选择"); - }; - } - - // 显示引导页,已有颜色时显示 Skip 按钮 - [guideView showInWindow:keyWindow showSkipButton:hasSignatureColor]; - -#else - // Release 环境:仅在未设置专属颜色时显示 if (!hasSignatureColor) { EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init]; guideView.onColorConfirmed = ^(NSString *hexColor) { @@ -120,11 +117,11 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; }; [guideView showInWindow:keyWindow]; } -#endif +//#endif } - (void)toLoginPage { - // 使用新的 Swift 登录页面 + EPLoginViewController *lvc = [[EPLoginViewController alloc] init]; BaseNavigationController *navigationController = [[BaseNavigationController alloc] initWithRootViewController:lvc]; @@ -159,10 +156,10 @@ UIKIT_EXTERN NSString * const kOpenRoomNotification; case ATTrackingManagerAuthorizationStatusAuthorized: break; case ATTrackingManagerAuthorizationStatusNotDetermined: { -// NSLog(@"用户未做选择或未弹窗IDFA"); - //请求弹出用户授权框,只会在程序运行是弹框1次,除非卸载app重装,通地图、相机等权限弹框一样 + + [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { -// NSLog(@"app追踪IDFA权限:%lu",(unsigned long)status); + }]; } break; diff --git a/YuMi/Appdelegate/AppDelegate.m.backup b/YuMi/Appdelegate/AppDelegate.m.backup new file mode 100644 index 0000000..231713c --- /dev/null +++ b/YuMi/Appdelegate/AppDelegate.m.backup @@ -0,0 +1,176 @@ +// +// AppDelegate.m +// YUMI +// +// Created by admin on 2023/3/9. +// + + +#import "AppDelegate.h" + +#import "BaseNavigationController.h" +#import +#import "YuMi-swift.h" + +UIKIT_EXTERN NSString * const kOpenRoomNotification; + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + + UIStoryboard *launchStoryboard = [UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil]; + UIViewController *launchScreenVC = [launchStoryboard instantiateInitialViewController]; + self.window.rootViewController = launchScreenVC; + [self.window makeKeyAndVisible]; + + [self loadMainPage]; + + if (@available(iOS 15, *)) { + [[UITableView appearance] setSectionHeaderTopPadding:0]; + } + + return YES; +} + +// MARK: - Helper Methods + +/// 获取 keyWindow(iOS 13+ 兼容) +- (UIWindow *)getKeyWindow { + // iOS 13+ 使用 connectedScenes 获取 window + if (@available(iOS 13.0, *)) { + for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive) { + for (UIWindow *window in scene.windows) { + if (window.isKeyWindow) { + return window; + } + } + // 如果没有 keyWindow,返回第一个 window + return scene.windows.firstObject; + } + } + } + + // iOS 13 以下,使用旧方法(已废弃但仍然可用) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + return [UIApplication sharedApplication].keyWindow; +#pragma clang diagnostic pop +} + + +- (void)loadMainPage { + AccountModel *accountModel = [[AccountInfoStorage instance] getCurrentAccountInfo]; + if (accountModel == nil || + accountModel.uid == nil || + accountModel.access_token == nil) { + [self toLoginPage]; + }else{ + [self toHomeTabbarPage]; + + // 延迟检查专属颜色(等待 window 初始化完成) + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self checkAndShowSignatureColorGuide]; + }); + } +} + +/// 检查并显示专属颜色引导页 +- (void)checkAndShowSignatureColorGuide { + UIWindow *keyWindow = [self getKeyWindow]; + if (!keyWindow) return; + + BOOL hasSignatureColor = [EPEmotionColorStorage hasUserSignatureColor]; + +#if DEBUG + // Debug 环境:总是显示引导页 + NSLog(@"[AppDelegate] Debug 模式:显示专属颜色引导页(已有颜色: %@)", hasSignatureColor ? @"YES" : @"NO"); + + EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init]; + + // 设置颜色确认回调 + guideView.onColorConfirmed = ^(NSString *hexColor) { + [EPEmotionColorStorage saveUserSignatureColor:hexColor]; + NSLog(@"[AppDelegate] 用户选择专属颜色: %@", hexColor); + }; + + // 如果已有颜色,设置 Skip 回调 + if (hasSignatureColor) { + guideView.onSkipTapped = ^{ + NSLog(@"[AppDelegate] 用户跳过专属颜色选择"); + }; + } + + // 显示引导页,已有颜色时显示 Skip 按钮 + [guideView showInWindow:keyWindow showSkipButton:hasSignatureColor]; + +#else + // Release 环境:仅在未设置专属颜色时显示 + if (!hasSignatureColor) { + EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init]; + guideView.onColorConfirmed = ^(NSString *hexColor) { + [EPEmotionColorStorage saveUserSignatureColor:hexColor]; + NSLog(@"[AppDelegate] 用户选择专属颜色: %@", hexColor); + }; + [guideView showInWindow:keyWindow]; + } +#endif +} + +- (void)toLoginPage { + // 使用新的 Swift 登录页面 + EPLoginViewController *lvc = [[EPLoginViewController alloc] init]; + BaseNavigationController *navigationController = + [[BaseNavigationController alloc] initWithRootViewController:lvc]; + navigationController.modalPresentationStyle = UIModalPresentationFullScreen; + self.window.rootViewController = navigationController; +} + +- (void)toHomeTabbarPage { + EPTabBarController *epTabBar = [EPTabBarController create]; + [epTabBar refreshTabBarWithIsLogin:YES]; + + UIWindow *window = [self getKeyWindow]; + if (window) { + window.rootViewController = epTabBar; + [window makeKeyAndVisible]; + } +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + [self getAdvertisingTrackingAuthority]; + [[NSNotificationCenter defaultCenter]postNotificationName:@"kAppDidBecomeActive" object:nil]; +} + +- (void)getAdvertisingTrackingAuthority { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (@available(iOS 14, *)) { + ATTrackingManagerAuthorizationStatus status = ATTrackingManager.trackingAuthorizationStatus; + switch (status) { + case ATTrackingManagerAuthorizationStatusDenied: + break; + case ATTrackingManagerAuthorizationStatusAuthorized: + break; + case ATTrackingManagerAuthorizationStatusNotDetermined: { +// NSLog(@"用户未做选择或未弹窗IDFA"); + //请求弹出用户授权框,只会在程序运行是弹框1次,除非卸载app重装,通地图、相机等权限弹框一样 + [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { +// NSLog(@"app追踪IDFA权限:%lu",(unsigned long)status); + }]; + } + break; + default: + break; + } + } + }); +} + +@end diff --git a/YuMi/Config/APIConfig.swift b/YuMi/Config/APIConfig.swift index 8ba49c3..00d1c87 100644 --- a/YuMi/Config/APIConfig.swift +++ b/YuMi/Config/APIConfig.swift @@ -1,44 +1,39 @@ -// -// APIConfig.swift -// YuMi -// + + // Created by AI on 2025-10-09. // Copyright © 2025 YuMi. All rights reserved. -// + import Foundation -/// API 域名配置类 -/// 使用 XOR + Base64 双重混淆防止反编译 + @objc class APIConfig: NSObject { // MARK: - Private Properties - /// XOR 加密密钥 + private static let xorKey: UInt8 = 77 - /// RELEASE 环境域名(加密后) - /// 原始域名:https://api.epartylive.com + private static let releaseEncodedParts: [String] = [ - "JTk5PT53YmI=", // https:// (XOR 后 Base64) - "LD0kYw==", // api. (XOR 后 Base64) - "KD0sPzk0ISQ7KGMuIiA=", // epartylive.com (XOR 后 Base64) + "JTk5PT53YmI=", + "LD0kYw==", + "KD0sPzk0ISQ7KGMuIiA=", ] // MARK: - Public Methods - /// 获取 API 基础域名 - /// - Returns: 根据编译环境返回对应的域名 + @objc static func baseURL() -> String { #if DEBUG - // DEV 环境:临时使用硬编码(等 Bridging 修复后再改回 HttpRequestHelper) + // TODO: 修复后改为 return HttpRequestHelper.getHostUrl() return getDevBaseURL() #else - // RELEASE 环境:使用动态生成的新域名 + let url = decodeURL(from: releaseEncodedParts) - // 验证解密结果 + if url.isEmpty || !url.hasPrefix("http") { NSLog("[APIConfig] 警告:域名解密失败,使用备用域名") return backupURL() @@ -48,33 +43,29 @@ import Foundation #endif } - /// 获取 DEV 环境域名(临时方案) - /// - Returns: DEV 域名 + private static func getDevBaseURL() -> String { - // 从 UserDefaults 读取(原 HttpRequestHelper 的逻辑) + #if DEBUG let isProduction = UserDefaults.standard.string(forKey: "kIsProductionEnvironment") if isProduction == "YES" { - return "https://api.epartylive.com" // 正式环境 + return "https://api.epartylive.com" } else { - return "https://test-api.yourdomain.com" // 测试环境(请替换为实际测试域名) + return "https://test-api.yourdomain.com" } #else return "https://api.epartylive.com" #endif } - /// 备用域名(降级方案) - /// - Returns: 原域名(仅在解密失败时使用) + @objc static func backupURL() -> String { return getDevBaseURL() } // MARK: - Private Methods - /// 解密域名 - /// - Parameter parts: 加密后的域名片段数组 - /// - Returns: 解密后的完整域名 + private static func decodeURL(from parts: [String]) -> String { let decoded = parts.compactMap { part -> String? in guard let data = Data(base64Encoded: part) else { @@ -99,7 +90,7 @@ import Foundation #if DEBUG extension APIConfig { - /// 测试方法:验证域名加密/解密是否正常 + @objc static func testEncryption() { print("=== APIConfig 加密测试 ===") print("Release 域名: \(decodeURL(from: releaseEncodedParts))") diff --git a/YuMi/Config/APIConfig.swift.backup b/YuMi/Config/APIConfig.swift.backup new file mode 100644 index 0000000..8ba49c3 --- /dev/null +++ b/YuMi/Config/APIConfig.swift.backup @@ -0,0 +1,110 @@ +// +// APIConfig.swift +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +import Foundation + +/// API 域名配置类 +/// 使用 XOR + Base64 双重混淆防止反编译 +@objc class APIConfig: NSObject { + + // MARK: - Private Properties + + /// XOR 加密密钥 + private static let xorKey: UInt8 = 77 + + /// RELEASE 环境域名(加密后) + /// 原始域名:https://api.epartylive.com + private static let releaseEncodedParts: [String] = [ + "JTk5PT53YmI=", // https:// (XOR 后 Base64) + "LD0kYw==", // api. (XOR 后 Base64) + "KD0sPzk0ISQ7KGMuIiA=", // epartylive.com (XOR 后 Base64) + ] + + // MARK: - Public Methods + + /// 获取 API 基础域名 + /// - Returns: 根据编译环境返回对应的域名 + @objc static func baseURL() -> String { + #if DEBUG + // DEV 环境:临时使用硬编码(等 Bridging 修复后再改回 HttpRequestHelper) + // TODO: 修复后改为 return HttpRequestHelper.getHostUrl() + return getDevBaseURL() + #else + // RELEASE 环境:使用动态生成的新域名 + let url = decodeURL(from: releaseEncodedParts) + + // 验证解密结果 + if url.isEmpty || !url.hasPrefix("http") { + NSLog("[APIConfig] 警告:域名解密失败,使用备用域名") + return backupURL() + } + + return url + #endif + } + + /// 获取 DEV 环境域名(临时方案) + /// - Returns: DEV 域名 + private static func getDevBaseURL() -> String { + // 从 UserDefaults 读取(原 HttpRequestHelper 的逻辑) + #if DEBUG + let isProduction = UserDefaults.standard.string(forKey: "kIsProductionEnvironment") + if isProduction == "YES" { + return "https://api.epartylive.com" // 正式环境 + } else { + return "https://test-api.yourdomain.com" // 测试环境(请替换为实际测试域名) + } + #else + return "https://api.epartylive.com" + #endif + } + + /// 备用域名(降级方案) + /// - Returns: 原域名(仅在解密失败时使用) + @objc static func backupURL() -> String { + return getDevBaseURL() + } + + // MARK: - Private Methods + + /// 解密域名 + /// - Parameter parts: 加密后的域名片段数组 + /// - Returns: 解密后的完整域名 + private static func decodeURL(from parts: [String]) -> String { + let decoded = parts.compactMap { part -> String? in + guard let data = Data(base64Encoded: part) else { + NSLog("[APIConfig] Base64 解码失败: \(part)") + return nil + } + let xored = data.map { $0 ^ xorKey } + return String(bytes: xored, encoding: .utf8) + } + + let result = decoded.joined() + + #if DEBUG + NSLog("[APIConfig] 解密后的域名: \(result)") + #endif + + return result + } +} + +// MARK: - Debug Helper + +#if DEBUG +extension APIConfig { + /// 测试方法:验证域名加密/解密是否正常 + @objc static func testEncryption() { + print("=== APIConfig 加密测试 ===") + print("Release 域名: \(decodeURL(from: releaseEncodedParts))") + print("当前环境域名: \(baseURL())") + print("备用域名: \(backupURL())") + } +} +#endif diff --git a/YuMi/CustomUI/DJDKMIMOMColor.h b/YuMi/CustomUI/DJDKMIMOMColor.h index ec898b0..03ac851 100644 --- a/YuMi/CustomUI/DJDKMIMOMColor.h +++ b/YuMi/CustomUI/DJDKMIMOMColor.h @@ -1,9 +1,7 @@ -// -// DJDKMIMOMColor.h -// YUMI -// + + // Created by YUMI on 2021/9/9. -// + #import @@ -13,62 +11,58 @@ NS_ASSUME_NONNULL_BEGIN @interface DJDKMIMOMColor : NSObject -/// 主题色0x9682FF + + (UIColor *)appMainColor; -///强调色 #248CFE + + (UIColor *)appEmphasizeColor; -///强调色1 0xBF36FF + + (UIColor *)appEmphasizeColor1; -///强调色2 0xFB486A + + (UIColor *)appEmphasizeColor2; -/* ------页面相关颜色 START------ */ -/// view的背景色 0xF3F5FA + + + (UIColor *)appBackgroundColor; -/// cell的背景色 0xFFFFFF + + (UIColor *)appCellBackgroundColor; -///正文颜色 0x333333 + + (UIColor *)mainTextColor; -/// 二级文字颜色 0x666666 + + (UIColor *)secondTextColor; -///三级文字的颜色 0x999999 + + (UIColor *)textThirdColor; -///分割线的颜色 0xE8E8E8 + + (UIColor *)dividerColor; -/* ------页面相关颜色 END------ */ -/* ------Button 相关颜色 START------ */ -/// button 可用 渐变色的开始 0xFFA936 + + (UIColor *)confirmButtonGradientStartColor; -/// button 可用 渐变色的中间 #9CB3FF -+ (UIColor *)confirmButtonGradientMiddleColor; -/// button 可用 渐变色的开始 0xFFCB47 -+ (UIColor *)confirmButtonGradientEndColor; -/// 确定的按钮文字颜色 #FFFFFF -+ (UIColor *)confirmButtonTextColor; -/// 取消按钮 渐变色的开始 0xF7DDBF -+ (UIColor *)cancelButtonGradientStartColor; -/// 取消按钮 渐变色的结束 0xF7E8C4 -+ (UIColor *)cancelButtonGradientEndColor; -/// 取消的按钮文字颜色 0xFFA936 -+ (UIColor *)cancelButtonTextColor; -/// 取消按钮单一普通背景色 0xFFCE4E -+ (UIColor *)cancelButtonNormalBgColor; -/// 按钮不可点击背景色 0xD2D5D7 -+ (UIColor *)disableButtonColor; -/// 按钮不可点击文字颜色 0xF9F9F9 -+ (UIColor *)disableButtonTextColor; -/* ------Button 相关颜色 END------ */ -/* ------弹窗相关颜色 START------ */ ++ (UIColor *)confirmButtonGradientMiddleColor; + ++ (UIColor *)confirmButtonGradientEndColor; + ++ (UIColor *)confirmButtonTextColor; + ++ (UIColor *)cancelButtonGradientStartColor; + ++ (UIColor *)cancelButtonGradientEndColor; + ++ (UIColor *)cancelButtonTextColor; + ++ (UIColor *)cancelButtonNormalBgColor; + ++ (UIColor *)disableButtonColor; + ++ (UIColor *)disableButtonTextColor; + + + (UIColor *)alertBackgroundColor; + (UIColor *)alertTitleColor; + (UIColor *)alertMessageColor; + (UIColor *)actionSeparatorColor; -/* ------弹窗相关颜色 END------ */ -///tabbar 没有点击的时候颜色 0x333333, 0.4 + + (UIColor *)tabbarNormalColor; -/// tabbar的View的color 0xFFFFFF + + (UIColor *)tabbarViewColor; + (UIColor *)colorWithHexString:(NSString *)hexString; diff --git a/YuMi/CustomUI/DJDKMIMOMColor.h.backup b/YuMi/CustomUI/DJDKMIMOMColor.h.backup new file mode 100644 index 0000000..ec898b0 --- /dev/null +++ b/YuMi/CustomUI/DJDKMIMOMColor.h.backup @@ -0,0 +1,79 @@ +// +// DJDKMIMOMColor.h +// YUMI +// +// Created by YUMI on 2021/9/9. +// + +#import + +#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] + +#define UIColorRGBAlpha(rgbValue,a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:(a)] +NS_ASSUME_NONNULL_BEGIN + +@interface DJDKMIMOMColor : NSObject +/// 主题色0x9682FF ++ (UIColor *)appMainColor; +///强调色 #248CFE ++ (UIColor *)appEmphasizeColor; +///强调色1 0xBF36FF ++ (UIColor *)appEmphasizeColor1; +///强调色2 0xFB486A ++ (UIColor *)appEmphasizeColor2; +/* ------页面相关颜色 START------ */ +/// view的背景色 0xF3F5FA ++ (UIColor *)appBackgroundColor; +/// cell的背景色 0xFFFFFF ++ (UIColor *)appCellBackgroundColor; +///正文颜色 0x333333 ++ (UIColor *)mainTextColor; +/// 二级文字颜色 0x666666 ++ (UIColor *)secondTextColor; +///三级文字的颜色 0x999999 ++ (UIColor *)textThirdColor; +///分割线的颜色 0xE8E8E8 ++ (UIColor *)dividerColor; +/* ------页面相关颜色 END------ */ + +/* ------Button 相关颜色 START------ */ +/// button 可用 渐变色的开始 0xFFA936 ++ (UIColor *)confirmButtonGradientStartColor; +/// button 可用 渐变色的中间 #9CB3FF ++ (UIColor *)confirmButtonGradientMiddleColor; +/// button 可用 渐变色的开始 0xFFCB47 ++ (UIColor *)confirmButtonGradientEndColor; +/// 确定的按钮文字颜色 #FFFFFF ++ (UIColor *)confirmButtonTextColor; +/// 取消按钮 渐变色的开始 0xF7DDBF ++ (UIColor *)cancelButtonGradientStartColor; +/// 取消按钮 渐变色的结束 0xF7E8C4 ++ (UIColor *)cancelButtonGradientEndColor; +/// 取消的按钮文字颜色 0xFFA936 ++ (UIColor *)cancelButtonTextColor; +/// 取消按钮单一普通背景色 0xFFCE4E ++ (UIColor *)cancelButtonNormalBgColor; +/// 按钮不可点击背景色 0xD2D5D7 ++ (UIColor *)disableButtonColor; +/// 按钮不可点击文字颜色 0xF9F9F9 ++ (UIColor *)disableButtonTextColor; +/* ------Button 相关颜色 END------ */ + +/* ------弹窗相关颜色 START------ */ ++ (UIColor *)alertBackgroundColor; ++ (UIColor *)alertTitleColor; ++ (UIColor *)alertMessageColor; ++ (UIColor *)actionSeparatorColor; +/* ------弹窗相关颜色 END------ */ + +///tabbar 没有点击的时候颜色 0x333333, 0.4 ++ (UIColor *)tabbarNormalColor; +/// tabbar的View的color 0xFFFFFF ++ (UIColor *)tabbarViewColor; + ++ (UIColor *)colorWithHexString:(NSString *)hexString; + ++ (UIColor *)inputTextColor; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/DJDKMIMOMColor.m b/YuMi/CustomUI/DJDKMIMOMColor.m index e7e84d9..c11f858 100644 --- a/YuMi/CustomUI/DJDKMIMOMColor.m +++ b/YuMi/CustomUI/DJDKMIMOMColor.m @@ -1,105 +1,99 @@ -// -// DJDKMIMOMColor.m -// YUMI -// + + // Created by YUMI on 2021/9/9. -// + #import "DJDKMIMOMColor.h" @implementation DJDKMIMOMColor -/// 主题色0x9682FF + + (UIColor *)appMainColor { return UIColorFromRGB(0x9682FF); } -///强调色 #248CFE + + (UIColor *)appEmphasizeColor { return UIColorFromRGB(0x248CFE); } -///强调色1 0xBF36FF + + (UIColor *)appEmphasizeColor1 { return UIColorFromRGB(0xBF36FF); } -///强调色2 0xFB486A + + (UIColor *)appEmphasizeColor2 { return UIColorFromRGB(0xFB486A); } -/* ------页面相关颜色 START------ */ -/// view的背景色 0xF3F5FA + + (UIColor *)appBackgroundColor { return UIColorFromRGB(0xF3F5FA); } -/// cell的背景色 0xFFFFFF + + (UIColor *)appCellBackgroundColor { return UIColorFromRGB(0xFFFFFF); } -///正文颜色 0x333333 + + (UIColor *)mainTextColor { return UIColorFromRGB(0x161958); } -/// 二级文字颜色 0x666666 + + (UIColor *)secondTextColor { return UIColorFromRGB(0x8A8CAB); } -///三级文字的颜色 0x999999 + + (UIColor *)textThirdColor { return UIColorFromRGB(0xBABBCD); } -///分割线的颜色 0xE8E8E8 + + (UIColor *)dividerColor { return UIColorFromRGB(0xE8E8E8); } -/* ------页面相关颜色 END------ */ -/* ------Button 相关颜色 START------ */ -/// button 可用 渐变色的开始 0x3CAAFF + + (UIColor *)confirmButtonGradientStartColor { return UIColorFromRGB(0x13E2F5); } -/// button 可用 渐变色的开始 0xB176FF + + (UIColor *)confirmButtonGradientEndColor { return UIColorFromRGB(0xCC66FF); } -/// 确定的按钮文字颜色 #FFFFFF + + (UIColor *)confirmButtonTextColor { return UIColorFromRGB(0xFFFFFF); } -/// 取消按钮 渐变色的开始 0xF7DDBF + + (UIColor *)cancelButtonGradientStartColor { return UIColorFromRGB(0xCEEFFD); } -/// button 可用 渐变色的中间 #9CB3FF + + (UIColor *)confirmButtonGradientMiddleColor { return UIColorFromRGB(0xf9CB3FF); } -/// 取消按钮 渐变色的结束 0xF7E8C4 + + (UIColor *)cancelButtonGradientEndColor { return UIColorFromRGB(0xD2F4F4); } -/// 取消的按钮文字颜色 0xFFA936 + + (UIColor *)cancelButtonTextColor { return UIColorFromRGB(0x5FCCE4); } -/// 取消按钮单一普通背景色 0xFFCE4E + + (UIColor *)cancelButtonNormalBgColor { return UIColorFromRGB(0xCEEFFD); } -/// 按钮不可点击背景色 0xD2D5D7 + + (UIColor *)disableButtonColor { return UIColorFromRGB(0xCEEFFD); } -/// 按钮不可点击文字颜色 0xF9F9F9 + + (UIColor *)disableButtonTextColor { return UIColorFromRGB(0xB3B3C3); } -/* ------Button 相关颜色 END------ */ -/* ------弹窗相关颜色 START------ */ + + (UIColor *)alertBackgroundColor { return UIColorFromRGB(0xFFFFFF); } @@ -112,13 +106,12 @@ + (UIColor *)actionSeparatorColor { return UIColorFromRGB(0xF0F0F0); } -/* ------弹窗相关颜色 END------ */ -///tabbar 没有点击的时候颜色 0x333333, 0.4 + + (UIColor *)tabbarNormalColor { return UIColorRGBAlpha(0x333333, 0.4); } -/// tabbar的View的color 0xFFFFFF + + (UIColor *)tabbarViewColor { return UIColorFromRGB(0xFFFFFF); } @@ -130,25 +123,25 @@ NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString]; CGFloat alpha, red, blue, green; switch ([colorString length]) { - case 3: // #RGB + case 3: alpha = 1.0f; red = [self colorComponentFrom: colorString start: 0 length: 1]; green = [self colorComponentFrom: colorString start: 1 length: 1]; blue = [self colorComponentFrom: colorString start: 2 length: 1]; break; - case 4: // #ARGB + case 4: alpha = [self colorComponentFrom: colorString start: 0 length: 1]; red = [self colorComponentFrom: colorString start: 1 length: 1]; green = [self colorComponentFrom: colorString start: 2 length: 1]; blue = [self colorComponentFrom: colorString start: 3 length: 1]; break; - case 6: // #RRGGBB + case 6: alpha = 1.0f; red = [self colorComponentFrom: colorString start: 0 length: 2]; green = [self colorComponentFrom: colorString start: 2 length: 2]; blue = [self colorComponentFrom: colorString start: 4 length: 2]; break; - case 8: // #AARRGGBB + case 8: alpha = [self colorComponentFrom: colorString start: 0 length: 2]; red = [self colorComponentFrom: colorString start: 2 length: 2]; green = [self colorComponentFrom: colorString start: 4 length: 2]; @@ -169,7 +162,7 @@ return hexComponent / 255.0; } -///输入框的文本颜色 #1F1A4E + + (UIColor *)inputTextColor { return [self colorWithHexString:@"#1F1A4E"]; } diff --git a/YuMi/CustomUI/DJDKMIMOMColor.m.backup b/YuMi/CustomUI/DJDKMIMOMColor.m.backup new file mode 100644 index 0000000..e7e84d9 --- /dev/null +++ b/YuMi/CustomUI/DJDKMIMOMColor.m.backup @@ -0,0 +1,177 @@ +// +// DJDKMIMOMColor.m +// YUMI +// +// Created by YUMI on 2021/9/9. +// + +#import "DJDKMIMOMColor.h" + +@implementation DJDKMIMOMColor +/// 主题色0x9682FF ++ (UIColor *)appMainColor { + return UIColorFromRGB(0x9682FF); +} + +///强调色 #248CFE ++ (UIColor *)appEmphasizeColor { + return UIColorFromRGB(0x248CFE); +} + +///强调色1 0xBF36FF ++ (UIColor *)appEmphasizeColor1 { + return UIColorFromRGB(0xBF36FF); +} + +///强调色2 0xFB486A ++ (UIColor *)appEmphasizeColor2 { + return UIColorFromRGB(0xFB486A); +} + +/* ------页面相关颜色 START------ */ +/// view的背景色 0xF3F5FA ++ (UIColor *)appBackgroundColor { + return UIColorFromRGB(0xF3F5FA); +} +/// cell的背景色 0xFFFFFF ++ (UIColor *)appCellBackgroundColor { + return UIColorFromRGB(0xFFFFFF); +} +///正文颜色 0x333333 ++ (UIColor *)mainTextColor { + return UIColorFromRGB(0x161958); +} +/// 二级文字颜色 0x666666 ++ (UIColor *)secondTextColor { + return UIColorFromRGB(0x8A8CAB); +} +///三级文字的颜色 0x999999 ++ (UIColor *)textThirdColor { + return UIColorFromRGB(0xBABBCD); +} +///分割线的颜色 0xE8E8E8 ++ (UIColor *)dividerColor { + return UIColorFromRGB(0xE8E8E8); +} +/* ------页面相关颜色 END------ */ + +/* ------Button 相关颜色 START------ */ +/// button 可用 渐变色的开始 0x3CAAFF ++ (UIColor *)confirmButtonGradientStartColor { + return UIColorFromRGB(0x13E2F5); +} +/// button 可用 渐变色的开始 0xB176FF ++ (UIColor *)confirmButtonGradientEndColor { + return UIColorFromRGB(0xCC66FF); +} +/// 确定的按钮文字颜色 #FFFFFF ++ (UIColor *)confirmButtonTextColor { + return UIColorFromRGB(0xFFFFFF); +} +/// 取消按钮 渐变色的开始 0xF7DDBF ++ (UIColor *)cancelButtonGradientStartColor { + return UIColorFromRGB(0xCEEFFD); +} + +/// button 可用 渐变色的中间 #9CB3FF ++ (UIColor *)confirmButtonGradientMiddleColor { + return UIColorFromRGB(0xf9CB3FF); +} +/// 取消按钮 渐变色的结束 0xF7E8C4 ++ (UIColor *)cancelButtonGradientEndColor { + return UIColorFromRGB(0xD2F4F4); +} +/// 取消的按钮文字颜色 0xFFA936 ++ (UIColor *)cancelButtonTextColor { + return UIColorFromRGB(0x5FCCE4); +} +/// 取消按钮单一普通背景色 0xFFCE4E ++ (UIColor *)cancelButtonNormalBgColor { + return UIColorFromRGB(0xCEEFFD); +} +/// 按钮不可点击背景色 0xD2D5D7 ++ (UIColor *)disableButtonColor { + return UIColorFromRGB(0xCEEFFD); +} +/// 按钮不可点击文字颜色 0xF9F9F9 ++ (UIColor *)disableButtonTextColor { + return UIColorFromRGB(0xB3B3C3); +} +/* ------Button 相关颜色 END------ */ + +/* ------弹窗相关颜色 START------ */ ++ (UIColor *)alertBackgroundColor { + return UIColorFromRGB(0xFFFFFF); +} ++ (UIColor *)alertTitleColor { + return UIColorFromRGB(0x333333); +} ++ (UIColor *)alertMessageColor { + return UIColorFromRGB(0x333333); +} ++ (UIColor *)actionSeparatorColor { + return UIColorFromRGB(0xF0F0F0); +} +/* ------弹窗相关颜色 END------ */ + +///tabbar 没有点击的时候颜色 0x333333, 0.4 ++ (UIColor *)tabbarNormalColor { + return UIColorRGBAlpha(0x333333, 0.4); +} +/// tabbar的View的color 0xFFFFFF ++ (UIColor *)tabbarViewColor { + return UIColorFromRGB(0xFFFFFF); +} + ++ (UIColor *)colorWithHexString: (NSString *) hexString { + if (hexString.length == 0) { + return [UIColor blackColor]; + } + NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString]; + CGFloat alpha, red, blue, green; + switch ([colorString length]) { + case 3: // #RGB + alpha = 1.0f; + red = [self colorComponentFrom: colorString start: 0 length: 1]; + green = [self colorComponentFrom: colorString start: 1 length: 1]; + blue = [self colorComponentFrom: colorString start: 2 length: 1]; + break; + case 4: // #ARGB + alpha = [self colorComponentFrom: colorString start: 0 length: 1]; + red = [self colorComponentFrom: colorString start: 1 length: 1]; + green = [self colorComponentFrom: colorString start: 2 length: 1]; + blue = [self colorComponentFrom: colorString start: 3 length: 1]; + break; + case 6: // #RRGGBB + alpha = 1.0f; + red = [self colorComponentFrom: colorString start: 0 length: 2]; + green = [self colorComponentFrom: colorString start: 2 length: 2]; + blue = [self colorComponentFrom: colorString start: 4 length: 2]; + break; + case 8: // #AARRGGBB + alpha = [self colorComponentFrom: colorString start: 0 length: 2]; + red = [self colorComponentFrom: colorString start: 2 length: 2]; + green = [self colorComponentFrom: colorString start: 4 length: 2]; + blue = [self colorComponentFrom: colorString start: 6 length: 2]; + break; + default: + [NSException raise:@"Invalid color value" format: @"Color value %@ is invalid. It should be a hex value of the form #RBG, #ARGB, #RRGGBB, or #AARRGGBB", hexString]; + break; + } + return [UIColor colorWithRed: red green: green blue: blue alpha: alpha]; +} + ++ (CGFloat) colorComponentFrom: (NSString *) string start: (NSUInteger) start length: (NSUInteger) length { + NSString *substring = [string substringWithRange: NSMakeRange(start, length)]; + NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring]; + unsigned hexComponent; + [[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent]; + return hexComponent / 255.0; +} + +///输入框的文本颜色 #1F1A4E ++ (UIColor *)inputTextColor { + return [self colorWithHexString:@"#1F1A4E"]; +} + +@end diff --git a/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h index fe92d43..824a9ed 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h +++ b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h @@ -1,60 +1,46 @@ -// -// TTActionSheetConfig.h -// AFNetworking -// -// Created by lee on 2019/5/23. -// action sheet item 配置 - -#import - -typedef enum : NSUInteger { - TTItemSelectNormal, - TTItemSelectHighLight, -} TTItemSelectType; - - -NS_ASSUME_NONNULL_BEGIN -typedef void(^TTActionSheetClickAction)(void); - -@interface TTActionSheetConfig : NSObject - -/** 标题 */ -@property (nonatomic, copy) NSString *title; - -/** - 标题颜色 - */ -@property (nonatomic, strong) UIColor *titleColor; - -/** 是否选中 */ -@property (nonatomic, assign) TTItemSelectType type; - -/** 点击事件 */ -@property (nonatomic, copy) TTActionSheetClickAction clickAction; - -@property(nonatomic, assign) BOOL displayMoliCoin; - -/** - 构建 actionSheet item 实例 - - @param title 标题 - @param clickAction 点击事件 - @return item 实例 - */ -+ (TTActionSheetConfig *)normalTitle:(NSString *)title - clickAction:(TTActionSheetClickAction)clickAction; -+ (TTActionSheetConfig *)normalTitle:(NSString *)title - selectColorType:(TTItemSelectType)type clickAction:(TTActionSheetClickAction)clickAction; - - -/// 构建实例 -/// @param title 标题 -/// @param textColor 颜色 -/// @param handler 事件处理 -+ (TTActionSheetConfig *)actionWithTitle:(NSString *)title - color:(UIColor *)textColor - handler:(TTActionSheetClickAction)handler; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lee on 2019/5/23. + + +#import + +typedef enum : NSUInteger { + TTItemSelectNormal, + TTItemSelectHighLight, +} TTItemSelectType; + + +NS_ASSUME_NONNULL_BEGIN +typedef void(^TTActionSheetClickAction)(void); + +@interface TTActionSheetConfig : NSObject + + +@property (nonatomic, copy) NSString *title; + + +@property (nonatomic, strong) UIColor *titleColor; + + +@property (nonatomic, assign) TTItemSelectType type; + + +@property (nonatomic, copy) TTActionSheetClickAction clickAction; + +@property(nonatomic, assign) BOOL displayMoliCoin; + + ++ (TTActionSheetConfig *)normalTitle:(NSString *)title + clickAction:(TTActionSheetClickAction)clickAction; ++ (TTActionSheetConfig *)normalTitle:(NSString *)title + selectColorType:(TTItemSelectType)type clickAction:(TTActionSheetClickAction)clickAction; + + ++ (TTActionSheetConfig *)actionWithTitle:(NSString *)title + color:(UIColor *)textColor + handler:(TTActionSheetClickAction)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h.backup b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h.backup new file mode 100644 index 0000000..fe92d43 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.h.backup @@ -0,0 +1,60 @@ +// +// TTActionSheetConfig.h +// AFNetworking +// +// Created by lee on 2019/5/23. +// action sheet item 配置 + +#import + +typedef enum : NSUInteger { + TTItemSelectNormal, + TTItemSelectHighLight, +} TTItemSelectType; + + +NS_ASSUME_NONNULL_BEGIN +typedef void(^TTActionSheetClickAction)(void); + +@interface TTActionSheetConfig : NSObject + +/** 标题 */ +@property (nonatomic, copy) NSString *title; + +/** + 标题颜色 + */ +@property (nonatomic, strong) UIColor *titleColor; + +/** 是否选中 */ +@property (nonatomic, assign) TTItemSelectType type; + +/** 点击事件 */ +@property (nonatomic, copy) TTActionSheetClickAction clickAction; + +@property(nonatomic, assign) BOOL displayMoliCoin; + +/** + 构建 actionSheet item 实例 + + @param title 标题 + @param clickAction 点击事件 + @return item 实例 + */ ++ (TTActionSheetConfig *)normalTitle:(NSString *)title + clickAction:(TTActionSheetClickAction)clickAction; ++ (TTActionSheetConfig *)normalTitle:(NSString *)title + selectColorType:(TTItemSelectType)type clickAction:(TTActionSheetClickAction)clickAction; + + +/// 构建实例 +/// @param title 标题 +/// @param textColor 颜色 +/// @param handler 事件处理 ++ (TTActionSheetConfig *)actionWithTitle:(NSString *)title + color:(UIColor *)textColor + handler:(TTActionSheetClickAction)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m index e26cb40..9841c42 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m +++ b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m @@ -1,22 +1,14 @@ -// -// TTActionSheetConfig.m -// AFNetworking -// + + // Created by lee on 2019/5/23. -// + #import "TTActionSheetConfig.h" #import "DJDKMIMOMColor.h" @implementation TTActionSheetConfig -/** - 构建 actionSheet item 实例 - - @param title 标题 - @param clickAction 点击事件 - @return item 实例 - */ + + (TTActionSheetConfig *)normalTitle:(NSString *)title clickAction:(TTActionSheetClickAction)clickAction { return [self normalTitle:title selectColorType:TTItemSelectNormal clickAction:clickAction]; diff --git a/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m.backup b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m.backup new file mode 100644 index 0000000..e26cb40 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTActionSheetConfig.m.backup @@ -0,0 +1,49 @@ +// +// TTActionSheetConfig.m +// AFNetworking +// +// Created by lee on 2019/5/23. +// + +#import "TTActionSheetConfig.h" +#import "DJDKMIMOMColor.h" + +@implementation TTActionSheetConfig + +/** + 构建 actionSheet item 实例 + + @param title 标题 + @param clickAction 点击事件 + @return item 实例 + */ ++ (TTActionSheetConfig *)normalTitle:(NSString *)title clickAction:(TTActionSheetClickAction)clickAction { + + return [self normalTitle:title selectColorType:TTItemSelectNormal clickAction:clickAction]; +} + ++ (TTActionSheetConfig *)normalTitle:(NSString *)title selectColorType:(TTItemSelectType)type clickAction:(TTActionSheetClickAction)clickAction { + + UIColor *color = type == TTItemSelectHighLight ? [DJDKMIMOMColor alertTitleColor] : [DJDKMIMOMColor alertTitleColor]; + + TTActionSheetConfig *config = [self actionWithTitle:title color:color handler:clickAction]; + config.type = type; + + return config; +} + ++ (TTActionSheetConfig *)actionWithTitle:(NSString *)title + color:(UIColor *)textColor + handler:(TTActionSheetClickAction)handler { + + TTActionSheetConfig *config = [[TTActionSheetConfig alloc] init]; + config.type = TTItemSelectNormal; + config.title = title; + config.titleColor = textColor; + config.clickAction = handler; + + return config; +} + + +@end diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h index f886cc4..f3c15e7 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h @@ -1,30 +1,28 @@ -// -// TTAlertButtonConfig.h -// YM_TTChatViewKit -// -// Created by lee on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// alert 按钮配置 - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface TTAlertButtonConfig : NSObject -/** 按钮标题 */ -@property (nonatomic, copy) NSString *title; -/** 按钮字体 */ -@property (nonatomic, strong) UIFont *font; -/** 按钮字体颜色 */ -@property (nonatomic, strong) UIColor *titleColor; -/** 背景色 */ -@property (nonatomic, strong) UIColor *backgroundColor; -/** 背景图 */ -@property (nonatomic, strong) UIImage *backgroundImage; -/** 圆角 */ -@property (nonatomic, assign) CGFloat cornerRadius; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lee on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TTAlertButtonConfig : NSObject + +@property (nonatomic, copy) NSString *title; + +@property (nonatomic, strong) UIFont *font; + +@property (nonatomic, strong) UIColor *titleColor; + +@property (nonatomic, strong) UIColor *backgroundColor; + +@property (nonatomic, strong) UIImage *backgroundImage; + +@property (nonatomic, assign) CGFloat cornerRadius; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h.backup b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h.backup new file mode 100644 index 0000000..f886cc4 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.h.backup @@ -0,0 +1,30 @@ +// +// TTAlertButtonConfig.h +// YM_TTChatViewKit +// +// Created by lee on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// alert 按钮配置 + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TTAlertButtonConfig : NSObject +/** 按钮标题 */ +@property (nonatomic, copy) NSString *title; +/** 按钮字体 */ +@property (nonatomic, strong) UIFont *font; +/** 按钮字体颜色 */ +@property (nonatomic, strong) UIColor *titleColor; +/** 背景色 */ +@property (nonatomic, strong) UIColor *backgroundColor; +/** 背景图 */ +@property (nonatomic, strong) UIImage *backgroundImage; +/** 圆角 */ +@property (nonatomic, assign) CGFloat cornerRadius; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m index 4c85122..5058525 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m @@ -1,10 +1,8 @@ -// -// TTAlertButtonConfig.m -// YM_TTChatViewKit -// + + // Created by lee on 2019/5/21. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTAlertButtonConfig.h" diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m.backup b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m.backup new file mode 100644 index 0000000..4c85122 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertButtonConfig.m.backup @@ -0,0 +1,13 @@ +// +// TTAlertButtonConfig.m +// YM_TTChatViewKit +// +// Created by lee on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTAlertButtonConfig.h" + +@implementation TTAlertButtonConfig + +@end diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h index a88fde3..319716a 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h @@ -1,86 +1,70 @@ -// -// TTAlertConfig.h -// YM_TTChatViewKit -// -// Created by lee on 2019/5/20. -// Copyright © 2023 YUMI. All rights reserved. -// alert 配置 - -#import -#import -#import "TTAlertButtonConfig.h" -#import "TTAlertMessageAttributedConfig.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSUInteger, TTAlertActionStyle) { - TTAlertActionConfirmStyle = 0, // 只有确定按钮 - TTAlertActionCancelStyle = 1, // 只有取消按钮 - TTAlertActionBothStyle = 2, // 全部按钮 -}; - - -@interface TTAlertConfig : NSObject -// 按钮显示风格 -@property (nonatomic, assign) TTAlertActionStyle actionStyle; -// 容器背景设置 -@property (nonatomic, strong) UIColor *backgroundColor; - -// 标题设置 -@property (nonatomic, copy) NSString *title; -@property (nonatomic, strong) UIFont *titleFont; -@property (nonatomic, strong) UIColor *titleColor; - -// 内容设置 -@property (nonatomic, copy) NSString *message; -@property (nonatomic, strong) UIFont *messageFont; -@property (nonatomic, strong) UIColor *messageColor; -/** 内容的行间距,默认不设置,当值为 0 或负数时无效 */ -@property (nonatomic, assign) CGFloat messageLineSpacing; -@property(nonatomic, assign) NSTextAlignment messageTextAlignment; -/** 内容富文本配置 */ -@property (nonatomic, strong) NSArray *messageAttributedConfig; -///配置内容的富文本 -@property (nonatomic,strong) NSMutableAttributedString *messageAttributed; - -// 取消按钮配置 -@property (nonatomic, strong) TTAlertButtonConfig *cancelButtonConfig; - -// 确定按钮配置 -@property (nonatomic, strong) TTAlertButtonConfig *confirmButtonConfig; - -/** - 背景蒙层的透明度 - @Description 默认是 000000 黑色 0.3 alpha - */ -@property (nonatomic, assign) CGFloat maskBackgroundAlpha; - -// 圆角 -@property (nonatomic, assign) CGFloat cornerRadius; - -// 点击蒙层是否消失,默认:YES -@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch; - -/** - 点击‘确定’‘取消’按钮时禁止弹窗自动消失,默认:NO - - @discussion 若值为 YES,需要主动调用 [TTPopup dismiss] 消除弹窗 - */ -@property (nonatomic, assign) BOOL disableAutoDismissWhenClickButton; - -/** - 重复弹窗过滤,默认:NO - - @discussion 设置过滤时,队列中将不会出现相同过滤标识的弹窗 - 过滤标识通过 # 设置 - */ -@property (nonatomic, assign) BOOL shouldFilterPopup; - -/** - 过滤标识,默认:nil - */ -@property (nonatomic, copy) NSString *filterIdentifier; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lee on 2019/5/20. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import +#import "TTAlertButtonConfig.h" +#import "TTAlertMessageAttributedConfig.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, TTAlertActionStyle) { + TTAlertActionConfirmStyle = 0, + TTAlertActionCancelStyle = 1, + TTAlertActionBothStyle = 2, +}; + + +@interface TTAlertConfig : NSObject + +@property (nonatomic, assign) TTAlertActionStyle actionStyle; + +@property (nonatomic, strong) UIColor *backgroundColor; + + +@property (nonatomic, copy) NSString *title; +@property (nonatomic, strong) UIFont *titleFont; +@property (nonatomic, strong) UIColor *titleColor; + + +@property (nonatomic, copy) NSString *message; +@property (nonatomic, strong) UIFont *messageFont; +@property (nonatomic, strong) UIColor *messageColor; + +@property (nonatomic, assign) CGFloat messageLineSpacing; +@property(nonatomic, assign) NSTextAlignment messageTextAlignment; + +@property (nonatomic, strong) NSArray *messageAttributedConfig; + +@property (nonatomic,strong) NSMutableAttributedString *messageAttributed; + + +@property (nonatomic, strong) TTAlertButtonConfig *cancelButtonConfig; + + +@property (nonatomic, strong) TTAlertButtonConfig *confirmButtonConfig; + + +@property (nonatomic, assign) CGFloat maskBackgroundAlpha; + + +@property (nonatomic, assign) CGFloat cornerRadius; + + +@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch; + + +@property (nonatomic, assign) BOOL disableAutoDismissWhenClickButton; + + +@property (nonatomic, assign) BOOL shouldFilterPopup; + + +@property (nonatomic, copy) NSString *filterIdentifier; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h.backup b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h.backup new file mode 100644 index 0000000..a88fde3 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.h.backup @@ -0,0 +1,86 @@ +// +// TTAlertConfig.h +// YM_TTChatViewKit +// +// Created by lee on 2019/5/20. +// Copyright © 2023 YUMI. All rights reserved. +// alert 配置 + +#import +#import +#import "TTAlertButtonConfig.h" +#import "TTAlertMessageAttributedConfig.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, TTAlertActionStyle) { + TTAlertActionConfirmStyle = 0, // 只有确定按钮 + TTAlertActionCancelStyle = 1, // 只有取消按钮 + TTAlertActionBothStyle = 2, // 全部按钮 +}; + + +@interface TTAlertConfig : NSObject +// 按钮显示风格 +@property (nonatomic, assign) TTAlertActionStyle actionStyle; +// 容器背景设置 +@property (nonatomic, strong) UIColor *backgroundColor; + +// 标题设置 +@property (nonatomic, copy) NSString *title; +@property (nonatomic, strong) UIFont *titleFont; +@property (nonatomic, strong) UIColor *titleColor; + +// 内容设置 +@property (nonatomic, copy) NSString *message; +@property (nonatomic, strong) UIFont *messageFont; +@property (nonatomic, strong) UIColor *messageColor; +/** 内容的行间距,默认不设置,当值为 0 或负数时无效 */ +@property (nonatomic, assign) CGFloat messageLineSpacing; +@property(nonatomic, assign) NSTextAlignment messageTextAlignment; +/** 内容富文本配置 */ +@property (nonatomic, strong) NSArray *messageAttributedConfig; +///配置内容的富文本 +@property (nonatomic,strong) NSMutableAttributedString *messageAttributed; + +// 取消按钮配置 +@property (nonatomic, strong) TTAlertButtonConfig *cancelButtonConfig; + +// 确定按钮配置 +@property (nonatomic, strong) TTAlertButtonConfig *confirmButtonConfig; + +/** + 背景蒙层的透明度 + @Description 默认是 000000 黑色 0.3 alpha + */ +@property (nonatomic, assign) CGFloat maskBackgroundAlpha; + +// 圆角 +@property (nonatomic, assign) CGFloat cornerRadius; + +// 点击蒙层是否消失,默认:YES +@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch; + +/** + 点击‘确定’‘取消’按钮时禁止弹窗自动消失,默认:NO + + @discussion 若值为 YES,需要主动调用 [TTPopup dismiss] 消除弹窗 + */ +@property (nonatomic, assign) BOOL disableAutoDismissWhenClickButton; + +/** + 重复弹窗过滤,默认:NO + + @discussion 设置过滤时,队列中将不会出现相同过滤标识的弹窗 + 过滤标识通过 # 设置 + */ +@property (nonatomic, assign) BOOL shouldFilterPopup; + +/** + 过滤标识,默认:nil + */ +@property (nonatomic, copy) NSString *filterIdentifier; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m index ce12879..296b97e 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m @@ -1,10 +1,8 @@ -// -// TTAlertConfig.m -// YM_TTChatViewKit -// + + // Created by lee on 2019/5/20. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTAlertConfig.h" #import "UIImage+Utils.h" @@ -26,36 +24,35 @@ static CGFloat kAlertButtonCornerRadius = 8.f; _backgroundColor = [DJDKMIMOMColor alertBackgroundColor]; - //背景颜色 + kAlertTitleFont = 16.f; kAlertCornerRadius = 14.f; kAlertButtonCornerRadius = 19.f; _actionStyle = TTAlertActionBothStyle; - // title - _title = @"";// 标题 - _titleFont = [UIFont fontWithName:@"PingFangSC-Medium" size:kAlertTitleFont];// 字体 - _titleColor = [DJDKMIMOMColor alertTitleColor];// 颜色 - // message + _title = @""; + _titleFont = [UIFont fontWithName:@"PingFangSC-Medium" size:kAlertTitleFont]; + _titleColor = [DJDKMIMOMColor alertTitleColor]; + + _message = @""; - _messageFont = [UIFont systemFontOfSize:kAlertMessageFont];// 内容 - _messageColor = [DJDKMIMOMColor alertMessageColor];// 颜色 - _messageLineSpacing = kAlertMessageFontLineSpace;// 字体行间距 - _messageAttributedConfig = @[];// 自定义富文本样式 + _messageFont = [UIFont systemFontOfSize:kAlertMessageFont]; + _messageColor = [DJDKMIMOMColor alertMessageColor]; + _messageLineSpacing = kAlertMessageFontLineSpace; + _messageAttributedConfig = @[]; _messageTextAlignment = NSTextAlignmentCenter; - // cancel button + _cancelButtonConfig = [[TTAlertButtonConfig alloc] init]; - _cancelButtonConfig.title = YMLocalizedString(@"XPRoomSettingInputView4");// 取消按钮 - _cancelButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont];// 按钮字体 - _cancelButtonConfig.titleColor = [DJDKMIMOMColor cancelButtonTextColor];// 字体颜色 + _cancelButtonConfig.title = YMLocalizedString(@"XPRoomSettingInputView4"); + _cancelButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont]; + _cancelButtonConfig.titleColor = [DJDKMIMOMColor cancelButtonTextColor]; _cancelButtonConfig.backgroundImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor cancelButtonGradientStartColor], [DJDKMIMOMColor cancelButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)]; - _cancelButtonConfig.cornerRadius = kAlertButtonCornerRadius;// 按钮背景图 + _cancelButtonConfig.cornerRadius = kAlertButtonCornerRadius; - // confirm button _confirmButtonConfig = [[TTAlertButtonConfig alloc] init]; _confirmButtonConfig.title = YMLocalizedString(@"TTAlertConfig0"); _confirmButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont]; @@ -65,22 +62,12 @@ static CGFloat kAlertButtonCornerRadius = 8.f; imgSize:CGSizeMake(10, 10)]; _confirmButtonConfig.cornerRadius = kAlertButtonCornerRadius; -// // 创建渐变图层 -// CAGradientLayer *gradientLayer = [CAGradientLayer layer]; -// gradientLayer.colors = @[(__bridge id)UIColorFromRGB(0xE29030).CGColor, -// (__bridge id)UIColorFromRGB(0xFCC074).CGColor]; -// gradientLayer.startPoint = CGPointMake(0.0, 0.0); // 顶部中央 -// gradientLayer.endPoint = CGPointMake(0.0, 1.0); // 底部中央 -// gradientLayer.frame = CGRectMake(0, 0, 120, 38); // 设置渐变图层大小 -// -// // 将渐变图层添加到按钮图层 -// [_previewActionButton.layer insertSublayer:gradientLayer atIndex:0]; - _cornerRadius = kAlertCornerRadius;// 默认圆角 - _shouldDismissOnBackgroundTouch = YES;// 点击蒙层是否消失 + _cornerRadius = kAlertCornerRadius; + _shouldDismissOnBackgroundTouch = YES; - // mask default 0.3 black - _maskBackgroundAlpha = kAlertBackgroundColorAlpha; // alert 背景色 + + _maskBackgroundAlpha = kAlertBackgroundColorAlpha; _disableAutoDismissWhenClickButton = NO; } return self; diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m.backup b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m.backup new file mode 100644 index 0000000..ce12879 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertConfig.m.backup @@ -0,0 +1,90 @@ +// +// TTAlertConfig.m +// YM_TTChatViewKit +// +// Created by lee on 2019/5/20. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTAlertConfig.h" +#import "UIImage+Utils.h" +#import "DJDKMIMOMColor.h" + +static CGFloat kAlertTitleFont = 18.f; +static CGFloat kAlertButtonFont = 15.f; +static CGFloat kAlertMessageFont = 15.f; +static CGFloat kAlertCornerRadius = 12.f; +static CGFloat kAlertBackgroundColorAlpha = 0.3; +static CGFloat kAlertMessageFontLineSpace = -1; +static CGFloat kAlertButtonCornerRadius = 8.f; + +@implementation TTAlertConfig + +- (instancetype)init { + self = [super init]; + if (self) { + + _backgroundColor = [DJDKMIMOMColor alertBackgroundColor]; + + //背景颜色 + kAlertTitleFont = 16.f; + kAlertCornerRadius = 14.f; + kAlertButtonCornerRadius = 19.f; + + _actionStyle = TTAlertActionBothStyle; + + // title + _title = @"";// 标题 + _titleFont = [UIFont fontWithName:@"PingFangSC-Medium" size:kAlertTitleFont];// 字体 + _titleColor = [DJDKMIMOMColor alertTitleColor];// 颜色 + + // message + _message = @""; + _messageFont = [UIFont systemFontOfSize:kAlertMessageFont];// 内容 + _messageColor = [DJDKMIMOMColor alertMessageColor];// 颜色 + _messageLineSpacing = kAlertMessageFontLineSpace;// 字体行间距 + _messageAttributedConfig = @[];// 自定义富文本样式 + _messageTextAlignment = NSTextAlignmentCenter; + + // cancel button + _cancelButtonConfig = [[TTAlertButtonConfig alloc] init]; + _cancelButtonConfig.title = YMLocalizedString(@"XPRoomSettingInputView4");// 取消按钮 + _cancelButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont];// 按钮字体 + _cancelButtonConfig.titleColor = [DJDKMIMOMColor cancelButtonTextColor];// 字体颜色 + _cancelButtonConfig.backgroundImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor cancelButtonGradientStartColor], [DJDKMIMOMColor cancelButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)]; + _cancelButtonConfig.cornerRadius = kAlertButtonCornerRadius;// 按钮背景图 + + + // confirm button + _confirmButtonConfig = [[TTAlertButtonConfig alloc] init]; + _confirmButtonConfig.title = YMLocalizedString(@"TTAlertConfig0"); + _confirmButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont]; + _confirmButtonConfig.titleColor = [DJDKMIMOMColor confirmButtonTextColor]; + _confirmButtonConfig.backgroundImage = [UIImage gradientColorImageFromColors:@[UIColorFromRGB(0xE29030), UIColorFromRGB(0xFCC074)] + gradientType:GradientTypeLeftToRight + imgSize:CGSizeMake(10, 10)]; + _confirmButtonConfig.cornerRadius = kAlertButtonCornerRadius; + +// // 创建渐变图层 +// CAGradientLayer *gradientLayer = [CAGradientLayer layer]; +// gradientLayer.colors = @[(__bridge id)UIColorFromRGB(0xE29030).CGColor, +// (__bridge id)UIColorFromRGB(0xFCC074).CGColor]; +// gradientLayer.startPoint = CGPointMake(0.0, 0.0); // 顶部中央 +// gradientLayer.endPoint = CGPointMake(0.0, 1.0); // 底部中央 +// gradientLayer.frame = CGRectMake(0, 0, 120, 38); // 设置渐变图层大小 +// +// // 将渐变图层添加到按钮图层 +// [_previewActionButton.layer insertSublayer:gradientLayer atIndex:0]; + + _cornerRadius = kAlertCornerRadius;// 默认圆角 + _shouldDismissOnBackgroundTouch = YES;// 点击蒙层是否消失 + + // mask default 0.3 black + _maskBackgroundAlpha = kAlertBackgroundColorAlpha; // alert 背景色 + _disableAutoDismissWhenClickButton = NO; + } + return self; +} + +@end + diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h index 374c57d..7c0a0a8 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h @@ -1,34 +1,28 @@ -// -// TTAlertContentAttributedConfig.h -// YM_TTChatViewKit -// -// Created by lee on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// alert 提示内容富文本配置 - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface TTAlertMessageAttributedConfig : NSObject - -/** 富文本字段需要特殊显示的文本 */ -@property (nonatomic, copy) NSString *text; - -/** 颜色 */ -@property (nonatomic, strong) UIColor *color; - -/** 字体 */ -@property (nonatomic, strong) UIFont *font; - -/** - 目标文本指定位置,一旦设置则无视 text 的值 - - @discussion 内容文本中出现相同的目标文本时,可通过设置 range 精确指定位置 - */ -@property (nonatomic, assign) NSRange range; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lee on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TTAlertMessageAttributedConfig : NSObject + + +@property (nonatomic, copy) NSString *text; + + +@property (nonatomic, strong) UIColor *color; + + +@property (nonatomic, strong) UIFont *font; + + +@property (nonatomic, assign) NSRange range; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h.backup b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h.backup new file mode 100644 index 0000000..374c57d --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.h.backup @@ -0,0 +1,34 @@ +// +// TTAlertContentAttributedConfig.h +// YM_TTChatViewKit +// +// Created by lee on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// alert 提示内容富文本配置 + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TTAlertMessageAttributedConfig : NSObject + +/** 富文本字段需要特殊显示的文本 */ +@property (nonatomic, copy) NSString *text; + +/** 颜色 */ +@property (nonatomic, strong) UIColor *color; + +/** 字体 */ +@property (nonatomic, strong) UIFont *font; + +/** + 目标文本指定位置,一旦设置则无视 text 的值 + + @discussion 内容文本中出现相同的目标文本时,可通过设置 range 精确指定位置 + */ +@property (nonatomic, assign) NSRange range; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m index 91a2a92..e434aad 100644 --- a/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m @@ -1,10 +1,8 @@ -// -// TTAlertContentAttributedConfig.m -// YM_TTChatViewKit -// + + // Created by lee on 2019/5/21. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTAlertMessageAttributedConfig.h" diff --git a/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m.backup b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m.backup new file mode 100644 index 0000000..91a2a92 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Config/TTAlertMessageAttributedConfig.m.backup @@ -0,0 +1,13 @@ +// +// TTAlertContentAttributedConfig.m +// YM_TTChatViewKit +// +// Created by lee on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTAlertMessageAttributedConfig.h" + +@implementation TTAlertMessageAttributedConfig + +@end diff --git a/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h b/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h index 01fcb35..0e443cc 100644 --- a/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h +++ b/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h @@ -1,38 +1,23 @@ -// -// TTPopupConstants.h -// YM_TTChatViewKit -// -// Created by lvjunhang on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import - -/** - Popup 组件通用回调 - */ -typedef void(^TTPopupCompletionHandler)(void); - -/** - 弹窗类型 - - - TTPopupStyleAlert: Alert - - TTPopupStyleActionSheet: ActionSheet - */ -typedef NS_ENUM(NSUInteger, TTPopupStyle) { - TTPopupStyleAlert = 0, - TTPopupStyleActionSheet -}; - -/** - 弹窗优先级 - - - TTPopupPriorityNormal: 普通 - - TTPopupPriorityHigh: 高 - - TTPopupPriorityRequired: 必须 - */ -typedef NS_ENUM(NSUInteger, TTPopupPriority) { - TTPopupPriorityNormal = 0, - TTPopupPriorityHigh, - TTPopupPriorityRequired -}; + + +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import + + +typedef void(^TTPopupCompletionHandler)(void); + + +typedef NS_ENUM(NSUInteger, TTPopupStyle) { + TTPopupStyleAlert = 0, + TTPopupStyleActionSheet +}; + + +typedef NS_ENUM(NSUInteger, TTPopupPriority) { + TTPopupPriorityNormal = 0, + TTPopupPriorityHigh, + TTPopupPriorityRequired +}; diff --git a/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h.backup b/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h.backup new file mode 100644 index 0000000..01fcb35 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Header/TTPopupConstants.h.backup @@ -0,0 +1,38 @@ +// +// TTPopupConstants.h +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import + +/** + Popup 组件通用回调 + */ +typedef void(^TTPopupCompletionHandler)(void); + +/** + 弹窗类型 + + - TTPopupStyleAlert: Alert + - TTPopupStyleActionSheet: ActionSheet + */ +typedef NS_ENUM(NSUInteger, TTPopupStyle) { + TTPopupStyleAlert = 0, + TTPopupStyleActionSheet +}; + +/** + 弹窗优先级 + + - TTPopupPriorityNormal: 普通 + - TTPopupPriorityHigh: 高 + - TTPopupPriorityRequired: 必须 + */ +typedef NS_ENUM(NSUInteger, TTPopupPriority) { + TTPopupPriorityNormal = 0, + TTPopupPriorityHigh, + TTPopupPriorityRequired +}; diff --git a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h index 3d4718a..dd47acc 100644 --- a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h +++ b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h @@ -1,24 +1,21 @@ -// -// TTPopupManagerService.h -// YM_TTChatViewKit -// -// Created by lvjunhang on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import -#import "TTPopupManagerServiceProtocol.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface TTPopupManagerService : NSObject -/** - 当前显示的弹窗服务 - */ -@property (nonatomic, strong) id currentPopupService; - -+ (instancetype)sharedInstance; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import "TTPopupManagerServiceProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TTPopupManagerService : NSObject + + +@property (nonatomic, strong) id currentPopupService; + ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h.backup b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h.backup new file mode 100644 index 0000000..3d4718a --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.h.backup @@ -0,0 +1,24 @@ +// +// TTPopupManagerService.h +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import +#import "TTPopupManagerServiceProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TTPopupManagerService : NSObject +/** + 当前显示的弹窗服务 + */ +@property (nonatomic, strong) id currentPopupService; + ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m index c6d8267..d5baa3d 100644 --- a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m +++ b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m @@ -1,10 +1,8 @@ -// -// TTPopupManagerService.m -// YM_TTChatViewKit -// + + // Created by lvjunhang on 2019/5/21. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTPopupManagerService.h" @@ -13,9 +11,8 @@ @interface TTPopupManagerService () @property (nonatomic, strong) NSMutableArray< id > *queue; -/** - 当前是否正在显示状态 - */ + + @property (nonatomic, assign, getter=isShowingPopup) BOOL showingPopup; @end @@ -53,7 +50,7 @@ return; } [_queue insertObject:service atIndex:insertPosition]; - //当前没有弹窗显示且队列只有一个元素时,显示弹窗 + if (_currentPopupService == nil && _queue.count == 1) { [self showPopup]; } @@ -61,8 +58,7 @@ - (void)removePopupService { - //防止当弹窗还未显示完成,在显示过程中频繁调用 dismiss - //使得 _currentPopupService 被清空,导致弹窗无法消失,从而假死现象 + if (!self.isShowingPopup) { return; } @@ -79,11 +75,7 @@ _currentPopupService = nil; } -/** - 点击蒙层时移除队列中的数据源 - - @discussion 注意无需调用 dismissPopupForView - */ + - (void)removeSourceWhenTouchMaskView { if (_currentPopupService == nil) { return; @@ -95,9 +87,8 @@ } #pragma mark - Private Methods -/** - 显示弹窗 - */ + + - (void)showPopup { if (self.isShowingPopup) { return; @@ -131,27 +122,26 @@ [popup showWithLayout:FFPopupLayoutMake(horizontalLayout, verticalLayout) duration:0.0]; __weak typeof(self) weakSelf = self; - // 不管是调用’dismissPopupForView:animated:‘ 还是‘点击蒙层消除’,最终都会走到这里 - // 适合在此展示队列中下一个弹窗 - // 通过 _currentPopupService 是否为空可以判断是哪种消除方式 + + popup.didFinishDismissingBlock = ^{ __strong typeof(weakSelf) strongSelf = weakSelf; BOOL isDismissOnBackgroundTouch = strongSelf.currentPopupService != nil; if (isDismissOnBackgroundTouch) { - // ‘点击蒙层消除’时,在展现下一个弹窗前移除数据源 + [self removeSourceWhenTouchMaskView]; } if (popupService.didFinishDismissHandler) { popupService.didFinishDismissHandler(isDismissOnBackgroundTouch); } - // 弹窗消除结束,更新状态 + strongSelf.showingPopup = NO; - // 显示下一个弹窗 + [strongSelf showPopup]; }; popup.didFinishShowingBlock = ^{ - // 开始弹窗,更新状态 + self.showingPopup = YES; if (popupService.didFinishShowingHandler) { popupService.didFinishShowingHandler(); @@ -159,11 +149,7 @@ }; } -/** - 弹窗将要插入队列的位置 - @param service 弹窗服务实例 - @return 队列的位置 - */ + - (NSInteger)insertPositionForPopupService:(id)service { __block NSInteger result = NSNotFound; if (service == nil) { @@ -172,7 +158,7 @@ if (_queue.count == 0) { return 0; } - // 设置重复弹窗过滤 + if (service.shouldFilterPopup && service.filterIdentifier.length > 0) { BOOL filterFlag = NO; for (id serv in _queue) { @@ -186,13 +172,13 @@ } } [_queue enumerateObjectsUsingBlock:^(id _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) { - // 找到队中比当前弹窗优先级低的位置 + if (service.priority > model.priority) { result = idx; *stop = YES; } }]; - // 如果没有合适的位置,则将新的弹窗放在队尾 + result = MIN(result, _queue.count); return result; } diff --git a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m.backup b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m.backup new file mode 100644 index 0000000..c6d8267 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerService.m.backup @@ -0,0 +1,200 @@ +// +// TTPopupManagerService.m +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTPopupManagerService.h" + +#import + +@interface TTPopupManagerService () + +@property (nonatomic, strong) NSMutableArray< id > *queue; +/** + 当前是否正在显示状态 + */ +@property (nonatomic, assign, getter=isShowingPopup) BOOL showingPopup; + +@end + +@implementation TTPopupManagerService + +#pragma mark - Life Cycle ++ (instancetype)sharedInstance { + static TTPopupManagerService *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + + return instance; +} + +- (instancetype)init { + if (self = [super init]) { + _queue = [NSMutableArray array]; + } + return self; +} + +#pragma mark - TTPopupManagerServiceProtocol +- (void)addPopupService:(id)service { + if (![service conformsToProtocol:@protocol(TTPopupServiceProtocol)]) { + return; + } + if ([_queue containsObject:service]) { + return; + } + NSInteger insertPosition = [self insertPositionForPopupService:service]; + if (insertPosition == NSNotFound) { + return; + } + [_queue insertObject:service atIndex:insertPosition]; + //当前没有弹窗显示且队列只有一个元素时,显示弹窗 + if (_currentPopupService == nil && _queue.count == 1) { + [self showPopup]; + } +} + +- (void)removePopupService { + + //防止当弹窗还未显示完成,在显示过程中频繁调用 dismiss + //使得 _currentPopupService 被清空,导致弹窗无法消失,从而假死现象 + if (!self.isShowingPopup) { + return; + } + + if (_currentPopupService == nil) { + return; + } + + if (_queue.count > 0) { + [_queue removeObjectAtIndex:0]; + } + + [FFPopup dismissPopupForView:_currentPopupService.contentView animated:YES]; + _currentPopupService = nil; +} + +/** + 点击蒙层时移除队列中的数据源 + + @discussion 注意无需调用 dismissPopupForView + */ +- (void)removeSourceWhenTouchMaskView { + if (_currentPopupService == nil) { + return; + } + if (_queue.count > 0) { + [_queue removeObjectAtIndex:0]; + } + _currentPopupService = nil; +} + +#pragma mark - Private Methods +/** + 显示弹窗 + */ +- (void)showPopup { + if (self.isShowingPopup) { + return; + } + if (_currentPopupService) { + return; + } + if (_queue.count == 0) { + return; + } + id popupService = _queue.firstObject; + if (![popupService conformsToProtocol:@protocol(TTPopupServiceProtocol)]) { + return; + } + _currentPopupService = popupService; + FFPopupHorizontalLayout horizontalLayout = FFPopupHorizontalLayout_Center; + FFPopupVerticalLayout verticalLayout = FFPopupVerticalLayout_Center; + FFPopupShowType showType = (FFPopupShowType)popupService.showType; + FFPopupDismissType dismissType = FFPopupDismissType_GrowOut; + if (popupService.style == TTPopupStyleActionSheet) { + verticalLayout = FFPopupVerticalLayout_Bottom; + showType = FFPopupShowType_SlideInFromBottom; + dismissType = FFPopupDismissType_SlideOutToBottom; + } + FFPopup *popup = [FFPopup popupWithContentView:popupService.contentView]; + popup.showType = showType; + popup.dismissType = dismissType; + popup.maskType = FFPopupMaskType_Dimmed; + popup.dimmedMaskAlpha = popupService.maskBackgroundAlpha; + popup.shouldDismissOnBackgroundTouch = popupService.shouldDismissOnBackgroundTouch; + + [popup showWithLayout:FFPopupLayoutMake(horizontalLayout, verticalLayout) duration:0.0]; + __weak typeof(self) weakSelf = self; + // 不管是调用’dismissPopupForView:animated:‘ 还是‘点击蒙层消除’,最终都会走到这里 + // 适合在此展示队列中下一个弹窗 + // 通过 _currentPopupService 是否为空可以判断是哪种消除方式 + popup.didFinishDismissingBlock = ^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + BOOL isDismissOnBackgroundTouch = strongSelf.currentPopupService != nil; + if (isDismissOnBackgroundTouch) { + // ‘点击蒙层消除’时,在展现下一个弹窗前移除数据源 + [self removeSourceWhenTouchMaskView]; + } + if (popupService.didFinishDismissHandler) { + popupService.didFinishDismissHandler(isDismissOnBackgroundTouch); + } + // 弹窗消除结束,更新状态 + strongSelf.showingPopup = NO; + // 显示下一个弹窗 + [strongSelf showPopup]; + }; + + popup.didFinishShowingBlock = ^{ + // 开始弹窗,更新状态 + self.showingPopup = YES; + if (popupService.didFinishShowingHandler) { + popupService.didFinishShowingHandler(); + } + }; +} + +/** + 弹窗将要插入队列的位置 + @param service 弹窗服务实例 + @return 队列的位置 + */ +- (NSInteger)insertPositionForPopupService:(id)service { + __block NSInteger result = NSNotFound; + if (service == nil) { + return result; + } + if (_queue.count == 0) { + return 0; + } + // 设置重复弹窗过滤 + if (service.shouldFilterPopup && service.filterIdentifier.length > 0) { + BOOL filterFlag = NO; + for (id serv in _queue) { + if ([serv.filterIdentifier isEqualToString:service.filterIdentifier]) { + filterFlag = YES; + break; + } + } + if (filterFlag) { + return result; + } + } + [_queue enumerateObjectsUsingBlock:^(id _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) { + // 找到队中比当前弹窗优先级低的位置 + if (service.priority > model.priority) { + result = idx; + *stop = YES; + } + }]; + // 如果没有合适的位置,则将新的弹窗放在队尾 + result = MIN(result, _queue.count); + return result; +} + +@end diff --git a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h index c5f4c06..f83b314 100644 --- a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h +++ b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h @@ -1,25 +1,17 @@ -// -// TTPopupManagerServiceProtocol.h -// YM_TTChatViewKit -// -// Created by lvjunhang on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import "TTPopupServiceProtocol.h" - -@protocol TTPopupManagerServiceProtocol - -/** - 添加一个弹窗 - - @param service 服从弹窗服务的实例 - */ -- (void)addPopupService:(id)service; - -/** - 移除一个弹窗 - */ -- (void)removePopupService; - -@end + + +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import "TTPopupServiceProtocol.h" + +@protocol TTPopupManagerServiceProtocol + + +- (void)addPopupService:(id)service; + + +- (void)removePopupService; + +@end diff --git a/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h.backup b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h.backup new file mode 100644 index 0000000..c5f4c06 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Manager/TTPopupManagerServiceProtocol.h.backup @@ -0,0 +1,25 @@ +// +// TTPopupManagerServiceProtocol.h +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTPopupServiceProtocol.h" + +@protocol TTPopupManagerServiceProtocol + +/** + 添加一个弹窗 + + @param service 服从弹窗服务的实例 + */ +- (void)addPopupService:(id)service; + +/** + 移除一个弹窗 + */ +- (void)removePopupService; + +@end diff --git a/YuMi/CustomUI/TTPopup/Service/TTPopupService.h b/YuMi/CustomUI/TTPopup/Service/TTPopupService.h index 4532865..5efeb22 100644 --- a/YuMi/CustomUI/TTPopup/Service/TTPopupService.h +++ b/YuMi/CustomUI/TTPopup/Service/TTPopupService.h @@ -1,22 +1,19 @@ -// -// TTPopupService.h -// YM_TTChatViewKit -// -// Created by lvjunhang on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import -#import "TTPopupServiceProtocol.h" - -// TTPopupConfig 是 TTPopupService 的别称 -// 具体信息见 TTPopupService -#define TTPopupConfig TTPopupService - -NS_ASSUME_NONNULL_BEGIN - -@interface TTPopupService : NSObject - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import "TTPopupServiceProtocol.h" + + +#define TTPopupConfig TTPopupService + +NS_ASSUME_NONNULL_BEGIN + +@interface TTPopupService : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Service/TTPopupService.h.backup b/YuMi/CustomUI/TTPopup/Service/TTPopupService.h.backup new file mode 100644 index 0000000..4532865 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Service/TTPopupService.h.backup @@ -0,0 +1,22 @@ +// +// TTPopupService.h +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import +#import "TTPopupServiceProtocol.h" + +// TTPopupConfig 是 TTPopupService 的别称 +// 具体信息见 TTPopupService +#define TTPopupConfig TTPopupService + +NS_ASSUME_NONNULL_BEGIN + +@interface TTPopupService : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/Service/TTPopupService.m b/YuMi/CustomUI/TTPopup/Service/TTPopupService.m index 82db3c1..8f087db 100644 --- a/YuMi/CustomUI/TTPopup/Service/TTPopupService.m +++ b/YuMi/CustomUI/TTPopup/Service/TTPopupService.m @@ -1,10 +1,8 @@ -// -// TTPopupService.m -// YM_TTChatViewKit -// + + // Created by lvjunhang on 2019/5/21. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTPopupService.h" diff --git a/YuMi/CustomUI/TTPopup/Service/TTPopupService.m.backup b/YuMi/CustomUI/TTPopup/Service/TTPopupService.m.backup new file mode 100644 index 0000000..82db3c1 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Service/TTPopupService.m.backup @@ -0,0 +1,36 @@ +// +// TTPopupService.m +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTPopupService.h" + +@implementation TTPopupService + +@synthesize style = _style; +@synthesize priority = _priority; +@synthesize contentView = _contentView; +@synthesize maskBackgroundAlpha = _maskBackgroundAlpha; +@synthesize shouldDismissOnBackgroundTouch = _shouldDismissOnBackgroundTouch; +@synthesize didFinishDismissHandler = _didFinishDismissHandler; +@synthesize didFinishShowingHandler = _didFinishShowingHandler; +@synthesize shouldFilterPopup = _shouldFilterPopup; +@synthesize filterIdentifier = _filterIdentifier; +@synthesize showType = _showType; +- (instancetype)init { + self = [super init]; + if (self) { + _style = TTPopupStyleAlert; + _priority = TTPopupPriorityNormal; + _maskBackgroundAlpha = 0.5; + _shouldDismissOnBackgroundTouch = YES; + _shouldFilterPopup = NO; + _showType = TTPopupShowTypeDefault; + } + return self; +} + +@end diff --git a/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h b/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h index c19a37d..4a6e58d 100644 --- a/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h +++ b/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h @@ -1,78 +1,47 @@ -// -// TTPopupServiceProtocol.h -// YM_TTChatViewKit -// -// Created by lvjunhang on 2019/5/21. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import "TTPopupConstants.h" - -typedef NS_ENUM(NSUInteger, TTPopupShowType) { - TTPopupShowType_FadeIn = 1, - TTPopupShowTypeDefault = 8, -}; - -@class UIView; - -@protocol TTPopupServiceProtocol - -/** - 弹窗样式,默认:TTPopupStyleAlert - */ -@property (nonatomic, assign) TTPopupStyle style; - -/** - 弹窗优先级权重,默认:TTPopupPriorityNormal - - @discussion 权重越高在弹窗队列的优先级越高,即优先弹出;相同权重按先来后到原则 - */ -@property (nonatomic, assign) TTPopupPriority priority; - -/** - 自定义视图内容,默认:nil - - @discussion 如果未配置,或 contentView 未继承自 UIView 及其子类,将忽略该弹窗 - */ -@property (nonatomic, strong) UIView *contentView; - -/** - 背景蒙层透明度,默认:0x000000 0.3 alpha - - @discussion 由于第三方原因,暂不支持蒙层颜色修改 - */ -@property (nonatomic, assign) CGFloat maskBackgroundAlpha; - -/** - 点击蒙层是否消除弹窗,默认:YES - */ -@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch; - -/** - 弹窗消失回调,isDismissOnBackgroundTouch 区分是否点击蒙层触发 - */ -@property (nonatomic, copy) void (^didFinishDismissHandler)(BOOL isDismissOnBackgroundTouch); - -/** - 弹窗显示成功回调 - */ -@property (nonatomic, copy) void (^didFinishShowingHandler)(void); - -/** - 重复弹窗过滤,默认:NO - - @discussion 设置过滤时,队列中将不会出现相同过滤标识的弹窗 - 过滤标识通过 # 设置 - */ -@property (nonatomic, assign) BOOL shouldFilterPopup; - -/** - 过滤标识,默认:nil - */ -@property (nonatomic, copy) NSString *filterIdentifier; - -/** - 显示动画类型, 默认是 default - */ -@property (nonatomic, assign) TTPopupShowType showType; -@end + + +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. + + +#import "TTPopupConstants.h" + +typedef NS_ENUM(NSUInteger, TTPopupShowType) { + TTPopupShowType_FadeIn = 1, + TTPopupShowTypeDefault = 8, +}; + +@class UIView; + +@protocol TTPopupServiceProtocol + + +@property (nonatomic, assign) TTPopupStyle style; + + +@property (nonatomic, assign) TTPopupPriority priority; + + +@property (nonatomic, strong) UIView *contentView; + + +@property (nonatomic, assign) CGFloat maskBackgroundAlpha; + + +@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch; + + +@property (nonatomic, copy) void (^didFinishDismissHandler)(BOOL isDismissOnBackgroundTouch); + + +@property (nonatomic, copy) void (^didFinishShowingHandler)(void); + + +@property (nonatomic, assign) BOOL shouldFilterPopup; + + +@property (nonatomic, copy) NSString *filterIdentifier; + + +@property (nonatomic, assign) TTPopupShowType showType; +@end diff --git a/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h.backup b/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h.backup new file mode 100644 index 0000000..c19a37d --- /dev/null +++ b/YuMi/CustomUI/TTPopup/Service/TTPopupServiceProtocol.h.backup @@ -0,0 +1,78 @@ +// +// TTPopupServiceProtocol.h +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/21. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTPopupConstants.h" + +typedef NS_ENUM(NSUInteger, TTPopupShowType) { + TTPopupShowType_FadeIn = 1, + TTPopupShowTypeDefault = 8, +}; + +@class UIView; + +@protocol TTPopupServiceProtocol + +/** + 弹窗样式,默认:TTPopupStyleAlert + */ +@property (nonatomic, assign) TTPopupStyle style; + +/** + 弹窗优先级权重,默认:TTPopupPriorityNormal + + @discussion 权重越高在弹窗队列的优先级越高,即优先弹出;相同权重按先来后到原则 + */ +@property (nonatomic, assign) TTPopupPriority priority; + +/** + 自定义视图内容,默认:nil + + @discussion 如果未配置,或 contentView 未继承自 UIView 及其子类,将忽略该弹窗 + */ +@property (nonatomic, strong) UIView *contentView; + +/** + 背景蒙层透明度,默认:0x000000 0.3 alpha + + @discussion 由于第三方原因,暂不支持蒙层颜色修改 + */ +@property (nonatomic, assign) CGFloat maskBackgroundAlpha; + +/** + 点击蒙层是否消除弹窗,默认:YES + */ +@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch; + +/** + 弹窗消失回调,isDismissOnBackgroundTouch 区分是否点击蒙层触发 + */ +@property (nonatomic, copy) void (^didFinishDismissHandler)(BOOL isDismissOnBackgroundTouch); + +/** + 弹窗显示成功回调 + */ +@property (nonatomic, copy) void (^didFinishShowingHandler)(void); + +/** + 重复弹窗过滤,默认:NO + + @discussion 设置过滤时,队列中将不会出现相同过滤标识的弹窗 + 过滤标识通过 # 设置 + */ +@property (nonatomic, assign) BOOL shouldFilterPopup; + +/** + 过滤标识,默认:nil + */ +@property (nonatomic, copy) NSString *filterIdentifier; + +/** + 显示动画类型, 默认是 default + */ +@property (nonatomic, assign) TTPopupShowType showType; +@end diff --git a/YuMi/CustomUI/TTPopup/TTPopup.h b/YuMi/CustomUI/TTPopup/TTPopup.h index bdee4c7..d663ebe 100644 --- a/YuMi/CustomUI/TTPopup/TTPopup.h +++ b/YuMi/CustomUI/TTPopup/TTPopup.h @@ -1,126 +1,78 @@ -// -// TTPopup.h -// YM_TTChatViewKit -// -// Created by lvjunhang on 2019/5/22. -// Copyright © 2023 YUMI. All rights reserved. -// 弹窗工具类 - -#import -#import "TTPopupConstants.h" -#import "TTAlertConfig.h" -#import "TTActionSheetConfig.h" -#import "TTPopupService.h" - -NS_ASSUME_NONNULL_BEGIN - -@class UIView; - -@interface TTPopup : NSObject - -#pragma mark Alert -/** - 显示 alert 弹窗 - - @discussion 显示四个内容:默认标题‘提示’,提示内容,取消按钮,确认按钮 - - @param message 提示内容,不能为空(⊙o⊙)哦 - @param confirmHandler 确认操作 - @param cancelHandler 取消操作 - */ -+ (void)alertWithMessage:(NSString *)message - confirmHandler:(TTPopupCompletionHandler)confirmHandler - cancelHandler:(TTPopupCompletionHandler)cancelHandler; - - -/** -显示 alert 弹窗 - -@discussion 显示四个内容:默认标题‘提示’,提示内容,取消按钮,确认按钮 - -@param config 完善的视图配置,为您变态的需求保驾护航 -@param isShowBorder 是否显示边框 -@param confirmHandler 确认操作 -@param cancelHandler 取消操作 -*/ -+ (void)alertWithConfig:(TTAlertConfig *)config - showBorder:(BOOL)isShowBorder - confirmHandler:(TTPopupCompletionHandler)confirmHandler - cancelHandler:(TTPopupCompletionHandler)cancelHandler; - - - -+ (void)alertWithMessage:(NSString *)message - config:(TTAlertConfig *)config - showBorder:(BOOL)isShowBorder - cancelHandler:(TTPopupCompletionHandler)cancelHandler - confirmHandler:(TTPopupCompletionHandler)confirmHandler; - -/** - 显示 alert 弹窗 - @discussion 显示四个内容:标题,提示内容,取消按钮,确认按钮 - @param config 完善的视图配置,为您变态的需求保驾护航 - @param cancelHandler 取消操作 - @param confirmHandler 确认操作 - */ -+ (void)alertWithConfig:(TTAlertConfig *)config - confirmHandler:(TTPopupCompletionHandler)confirmHandler - cancelHandler:(TTPopupCompletionHandler)cancelHandler; - -#pragma mark Action Sheet -/** - 显示 action sheet 弹窗,自带贴心的取消按钮😊 - - @param items 配置列表 - */ -+ (void)actionSheetWithItems:(NSArray *)items; - -/** - 显示 action sheet 弹窗 - - @param items 配置列表 - @param showCancelItem 是否显示取消按钮 - */ -+ (void)actionSheetWithItems:(NSArray *)items - showCancelItem:(BOOL)showCancelItem; - -/** - 显示 action sheet 弹窗 - - @param items 配置列表 - @param cancelHandler 取消按钮回调 - */ -+ (void)actionSheetWithItems:(NSArray *)items - cancelHandler:(TTActionSheetClickAction)cancelHandler; - -#pragma mark Popup -/** - 显示自定义弹窗 - @param customView 自定义 view - @param style 弹窗样式 - */ -+ (void)popupView:(UIView *)customView - style:(TTPopupStyle)style; - -/** - 显示自定义弹窗 - - @param config 自定义弹窗配置 - */ -+ (void)popupWithConfig:(TTPopupService *)config; - -#pragma mark Dismiss -/** - 消除当前弹窗 - */ -+ (void)dismiss; - -#pragma mark Query -/** - 当前是否有显示弹窗 - */ -+ (BOOL)hasShowPopup; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lvjunhang on 2019/5/22. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import "TTPopupConstants.h" +#import "TTAlertConfig.h" +#import "TTActionSheetConfig.h" +#import "TTPopupService.h" + +NS_ASSUME_NONNULL_BEGIN + +@class UIView; + +@interface TTPopup : NSObject + +#pragma mark Alert + + ++ (void)alertWithMessage:(NSString *)message + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler; + + ++ (void)alertWithConfig:(TTAlertConfig *)config + showBorder:(BOOL)isShowBorder + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler; + + ++ (void)alertWithMessage:(NSString *)message + config:(TTAlertConfig *)config + showBorder:(BOOL)isShowBorder + cancelHandler:(TTPopupCompletionHandler)cancelHandler + confirmHandler:(TTPopupCompletionHandler)confirmHandler; + + ++ (void)alertWithConfig:(TTAlertConfig *)config + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler; + +#pragma mark Action Sheet + + ++ (void)actionSheetWithItems:(NSArray *)items; + + ++ (void)actionSheetWithItems:(NSArray *)items + showCancelItem:(BOOL)showCancelItem; + + ++ (void)actionSheetWithItems:(NSArray *)items + cancelHandler:(TTActionSheetClickAction)cancelHandler; + +#pragma mark Popup + + ++ (void)popupView:(UIView *)customView + style:(TTPopupStyle)style; + + ++ (void)popupWithConfig:(TTPopupService *)config; + +#pragma mark Dismiss + + ++ (void)dismiss; + +#pragma mark Query + + ++ (BOOL)hasShowPopup; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/TTPopup.h.backup b/YuMi/CustomUI/TTPopup/TTPopup.h.backup new file mode 100644 index 0000000..bdee4c7 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/TTPopup.h.backup @@ -0,0 +1,126 @@ +// +// TTPopup.h +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/22. +// Copyright © 2023 YUMI. All rights reserved. +// 弹窗工具类 + +#import +#import "TTPopupConstants.h" +#import "TTAlertConfig.h" +#import "TTActionSheetConfig.h" +#import "TTPopupService.h" + +NS_ASSUME_NONNULL_BEGIN + +@class UIView; + +@interface TTPopup : NSObject + +#pragma mark Alert +/** + 显示 alert 弹窗 + + @discussion 显示四个内容:默认标题‘提示’,提示内容,取消按钮,确认按钮 + + @param message 提示内容,不能为空(⊙o⊙)哦 + @param confirmHandler 确认操作 + @param cancelHandler 取消操作 + */ ++ (void)alertWithMessage:(NSString *)message + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler; + + +/** +显示 alert 弹窗 + +@discussion 显示四个内容:默认标题‘提示’,提示内容,取消按钮,确认按钮 + +@param config 完善的视图配置,为您变态的需求保驾护航 +@param isShowBorder 是否显示边框 +@param confirmHandler 确认操作 +@param cancelHandler 取消操作 +*/ ++ (void)alertWithConfig:(TTAlertConfig *)config + showBorder:(BOOL)isShowBorder + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler; + + + ++ (void)alertWithMessage:(NSString *)message + config:(TTAlertConfig *)config + showBorder:(BOOL)isShowBorder + cancelHandler:(TTPopupCompletionHandler)cancelHandler + confirmHandler:(TTPopupCompletionHandler)confirmHandler; + +/** + 显示 alert 弹窗 + @discussion 显示四个内容:标题,提示内容,取消按钮,确认按钮 + @param config 完善的视图配置,为您变态的需求保驾护航 + @param cancelHandler 取消操作 + @param confirmHandler 确认操作 + */ ++ (void)alertWithConfig:(TTAlertConfig *)config + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler; + +#pragma mark Action Sheet +/** + 显示 action sheet 弹窗,自带贴心的取消按钮😊 + + @param items 配置列表 + */ ++ (void)actionSheetWithItems:(NSArray *)items; + +/** + 显示 action sheet 弹窗 + + @param items 配置列表 + @param showCancelItem 是否显示取消按钮 + */ ++ (void)actionSheetWithItems:(NSArray *)items + showCancelItem:(BOOL)showCancelItem; + +/** + 显示 action sheet 弹窗 + + @param items 配置列表 + @param cancelHandler 取消按钮回调 + */ ++ (void)actionSheetWithItems:(NSArray *)items + cancelHandler:(TTActionSheetClickAction)cancelHandler; + +#pragma mark Popup +/** + 显示自定义弹窗 + @param customView 自定义 view + @param style 弹窗样式 + */ ++ (void)popupView:(UIView *)customView + style:(TTPopupStyle)style; + +/** + 显示自定义弹窗 + + @param config 自定义弹窗配置 + */ ++ (void)popupWithConfig:(TTPopupService *)config; + +#pragma mark Dismiss +/** + 消除当前弹窗 + */ ++ (void)dismiss; + +#pragma mark Query +/** + 当前是否有显示弹窗 + */ ++ (BOOL)hasShowPopup; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/TTPopup.m b/YuMi/CustomUI/TTPopup/TTPopup.m index 1edb23a..e26bcea 100644 --- a/YuMi/CustomUI/TTPopup/TTPopup.m +++ b/YuMi/CustomUI/TTPopup/TTPopup.m @@ -1,10 +1,8 @@ -// -// TTPopup.m -// YM_TTChatViewKit -// + + // Created by lvjunhang on 2019/5/22. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTPopup.h" #import "TTAlertView.h" @@ -59,13 +57,13 @@ static CGFloat const kMaxHeight = 450.f; NSAssert(NO, @" message can not be nil, 弹窗文案不可以为空"); return; #else - // 防止正式环境 crash + config.message = @" "; #endif } CGFloat width = [UIScreen mainScreen].bounds.size.width - 40 * 2; CGFloat height = ([self messageSize:config.message width:width].height + 160); - // 最小 200, 最大 450 + if (height < kMixHeight) { height = kMixHeight; } else if (height > KScreenHeight - kSafeAreaTopHeight - kSafeAreaBottomHeight) { @@ -77,7 +75,7 @@ static CGFloat const kMaxHeight = 450.f; contentView.cancelAction = cancelHandler; contentView.confirmAction = confirmHandler; if (!contentView.config.disableAutoDismissWhenClickButton) { - // 设置弹窗按钮自动消除 + contentView.dismissAction = ^{ [TTPopup dismiss]; }; @@ -115,7 +113,7 @@ static CGFloat const kMaxHeight = 450.f; CGFloat width = [UIScreen mainScreen].bounds.size.width - 40 * 2; CGFloat height = ([self messageSize:config.message width:width].height + 160); - // 最小 200, 最大 450 + if (height < kMixHeight) { height = kMixHeight; } else if (height > kMaxHeight) { @@ -129,7 +127,7 @@ static CGFloat const kMaxHeight = 450.f; contentView.isConfigBoard = isShowBorder; if (!contentView.config.disableAutoDismissWhenClickButton) { - // 设置弹窗按钮自动消除 + contentView.dismissAction = ^{ [TTPopup dismiss]; }; @@ -162,14 +160,14 @@ static CGFloat const kMaxHeight = 450.f; CGFloat width = [UIScreen mainScreen].bounds.size.width - kActionSheetViewPadding * 2; CGFloat height = kActionSheetViewCellHeight * items.count + kActionSheetViewBottomPadding; - // 如果需要显示取消按钮则增加响应的高度 + if (showCancelItem) { - // 按钮的高度和间距 + height += kActionSheetViewCancelViewHeight; } if (@available(iOS 11.0, *)) { - // 如果是 iPhone X 系列(刘海屏幕系列) 底部则需要添加 34 的高度 + height += [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom; } @@ -180,7 +178,7 @@ static CGFloat const kMaxHeight = 450.f; items:items]; sheetView.cancelAction = cancelHandler; - // 设置弹窗按钮自动消除 + sheetView.dismissAction = ^{ [TTPopup dismiss]; }; @@ -227,9 +225,8 @@ static CGFloat const kMaxHeight = 450.f; } #pragma mark Query -/** - 当前是否有显示弹窗 - */ + + + (BOOL)hasShowPopup { return [TTPopupManagerService sharedInstance].currentPopupService != nil; } diff --git a/YuMi/CustomUI/TTPopup/TTPopup.m.backup b/YuMi/CustomUI/TTPopup/TTPopup.m.backup new file mode 100644 index 0000000..1edb23a --- /dev/null +++ b/YuMi/CustomUI/TTPopup/TTPopup.m.backup @@ -0,0 +1,243 @@ +// +// TTPopup.m +// YM_TTChatViewKit +// +// Created by lvjunhang on 2019/5/22. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTPopup.h" +#import "TTAlertView.h" +#import "TTActionSheetView.h" +#import "TTPopupService.h" +#import "TTPopupManagerService.h" + +static CGFloat const kActionSheetViewPadding = 15.f; +static CGFloat const kActionSheetViewCellHeight = 52.f; +static CGFloat const kActionSheetViewCancelViewHeight = 67.f; +static CGFloat const kActionSheetViewBottomPadding = 15.f; +static CGFloat const kMixHeight = 200.f; +static CGFloat const kMaxHeight = 450.f; + +@implementation TTPopup + +#pragma mark - Public Methods +#pragma mark Alert ++ (void)alertWithMessage:(NSString *)message + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler { + + [self alertWithMessage:message + config:nil + cancelHandler:cancelHandler + confirmHandler:confirmHandler]; +} + ++ (void)alertWithConfig:(TTAlertConfig *)config + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler { + + [self alertWithMessage:nil + config:config + cancelHandler:cancelHandler + confirmHandler:confirmHandler]; +} + ++ (void)alertWithMessage:(NSString *)message + config:(TTAlertConfig *)config + cancelHandler:(TTPopupCompletionHandler)cancelHandler + confirmHandler:(TTPopupCompletionHandler)confirmHandler { + + if (!config) { + config = [[TTAlertConfig alloc] init]; + config.title = YMLocalizedString(@"UserDetail_CP_Toast_0"); + config.message = message; + } + + if (config.message.length <= 0 && config.messageAttributed.length <=0 && config.messageAttributedConfig.count <=0) { +#if DEBUG + NSAssert(NO, @" message can not be nil, 弹窗文案不可以为空"); + return; +#else + // 防止正式环境 crash + config.message = @" "; +#endif + } + CGFloat width = [UIScreen mainScreen].bounds.size.width - 40 * 2; + CGFloat height = ([self messageSize:config.message width:width].height + 160); + // 最小 200, 最大 450 + if (height < kMixHeight) { + height = kMixHeight; + } else if (height > KScreenHeight - kSafeAreaTopHeight - kSafeAreaBottomHeight) { + height = KScreenHeight - kSafeAreaTopHeight - kSafeAreaBottomHeight; + } + TTAlertView *contentView = [[TTAlertView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; + contentView.config = config; + contentView.isConfigBoard = NO; + contentView.cancelAction = cancelHandler; + contentView.confirmAction = confirmHandler; + if (!contentView.config.disableAutoDismissWhenClickButton) { + // 设置弹窗按钮自动消除 + contentView.dismissAction = ^{ + [TTPopup dismiss]; + }; + } + [self popupView:contentView style:TTPopupStyleAlert config:config]; +} + ++ (void)alertWithConfig:(TTAlertConfig *)config + showBorder:(BOOL)isShowBorder + confirmHandler:(TTPopupCompletionHandler)confirmHandler + cancelHandler:(TTPopupCompletionHandler)cancelHandler { + [self alertWithMessage:@"" + config:config + showBorder:isShowBorder + cancelHandler:cancelHandler + confirmHandler:confirmHandler]; +} + ++ (void)alertWithMessage:(NSString *)message + config:(TTAlertConfig *)config + showBorder:(BOOL)isShowBorder + cancelHandler:(TTPopupCompletionHandler)cancelHandler + confirmHandler:(TTPopupCompletionHandler)confirmHandler { + + if (!config) { + config = [[TTAlertConfig alloc] init]; + config.message = message; + } + + if (config.message.length <= 0) { + NSAssert(NO, @" message can not be nil, 弹窗文案不可以为空"); + return; + } + + CGFloat width = [UIScreen mainScreen].bounds.size.width - 40 * 2; + CGFloat height = ([self messageSize:config.message width:width].height + 160); + + // 最小 200, 最大 450 + if (height < kMixHeight) { + height = kMixHeight; + } else if (height > kMaxHeight) { + height = kMaxHeight; + } + + TTAlertView *contentView = [[TTAlertView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; + contentView.config = config; + contentView.cancelAction = cancelHandler; + contentView.confirmAction = confirmHandler; + contentView.isConfigBoard = isShowBorder; + + if (!contentView.config.disableAutoDismissWhenClickButton) { + // 设置弹窗按钮自动消除 + contentView.dismissAction = ^{ + [TTPopup dismiss]; + }; + } + + [self popupView:contentView style:TTPopupStyleAlert config:config]; +} + +#pragma mark Action Sheet ++ (void)actionSheetWithItems:(NSArray *)items { + + [TTPopup actionSheetWithItems:items showCancelItem:YES cancelHandler:nil]; +} + ++ (void)actionSheetWithItems:(NSArray *)items + showCancelItem:(BOOL)showCancelItem { + + [TTPopup actionSheetWithItems:items showCancelItem:showCancelItem cancelHandler:nil]; +} + ++ (void)actionSheetWithItems:(NSArray *)items cancelHandler:(TTActionSheetClickAction)cancelHandler { + + [TTPopup actionSheetWithItems:items showCancelItem:YES cancelHandler:cancelHandler]; +} + ++ (void)actionSheetWithItems:(NSArray *)items + showCancelItem:(BOOL)showCancelItem + cancelHandler:(TTActionSheetClickAction)cancelHandler { + + CGFloat width = [UIScreen mainScreen].bounds.size.width - kActionSheetViewPadding * 2; + CGFloat height = kActionSheetViewCellHeight * items.count + kActionSheetViewBottomPadding; + + // 如果需要显示取消按钮则增加响应的高度 + if (showCancelItem) { + // 按钮的高度和间距 + height += kActionSheetViewCancelViewHeight; + } + + if (@available(iOS 11.0, *)) { + // 如果是 iPhone X 系列(刘海屏幕系列) 底部则需要添加 34 的高度 + height += [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom; + } + + CGRect rect = CGRectMake(0, 0, width, height); + + TTActionSheetView *sheetView = [[TTActionSheetView alloc] initWithFrame:rect + needCancel:showCancelItem + items:items]; + sheetView.cancelAction = cancelHandler; + + // 设置弹窗按钮自动消除 + sheetView.dismissAction = ^{ + [TTPopup dismiss]; + }; + + [self popupView:sheetView style:TTPopupStyleActionSheet]; +} + + +#pragma mark Popup ++ (void)popupView:(UIView *)customView + style:(TTPopupStyle)style { + + TTPopupService *service = [[TTPopupService alloc] init]; + service.style = style; + service.contentView = customView; + + [self popupWithConfig:service]; +} + ++ (void)popupView:(UIView *)customView + style:(TTPopupStyle)style + config:(TTAlertConfig *)config { + + TTPopupService *service = [[TTPopupService alloc] init]; + service.style = style; + service.contentView = customView; + service.shouldDismissOnBackgroundTouch = config.shouldDismissOnBackgroundTouch; + service.maskBackgroundAlpha = config.maskBackgroundAlpha; + [self popupWithConfig:service]; +} + + ++ (void)popupWithConfig:(TTPopupService *)config { + if (![config.contentView isKindOfClass:UIView.class]) { + NSAssert(NO, @"TTPopup customView should inherit from UIView."); + return; + } + [[TTPopupManagerService sharedInstance] addPopupService:config]; +} + +#pragma mark Dismiss ++ (void)dismiss { + [[TTPopupManagerService sharedInstance] removePopupService]; +} + +#pragma mark Query +/** + 当前是否有显示弹窗 + */ ++ (BOOL)hasShowPopup { + return [TTPopupManagerService sharedInstance].currentPopupService != nil; +} + +#pragma mark - Privite ++ (CGSize)messageSize:(NSString *)text width:(CGFloat)width { + CGRect stringRect = [text boundingRectWithSize:CGSizeMake(width - 2 * 20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15.f]} context:nil]; + return stringRect.size; +} + +@end diff --git a/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h index 64aac06..3c982ba 100644 --- a/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h +++ b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h @@ -1,26 +1,24 @@ -// -// TTActionSheetView.h -// YM_TTChatViewKit -// -// Created by lee on 2019/5/22. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import -#import "TTPopupConstants.h" - -NS_ASSUME_NONNULL_BEGIN - -@class TTActionSheetConfig; - -@interface TTActionSheetView : UIView - -@property (nonatomic, copy) TTPopupCompletionHandler cancelAction; -@property (nonatomic, copy) TTPopupCompletionHandler dismissAction; - -- (instancetype)initWithFrame:(CGRect)frame - needCancel:(BOOL)needCancel - items:(NSArray *)items; -@end - -NS_ASSUME_NONNULL_END + + +// Created by lee on 2019/5/22. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import "TTPopupConstants.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TTActionSheetConfig; + +@interface TTActionSheetView : UIView + +@property (nonatomic, copy) TTPopupCompletionHandler cancelAction; +@property (nonatomic, copy) TTPopupCompletionHandler dismissAction; + +- (instancetype)initWithFrame:(CGRect)frame + needCancel:(BOOL)needCancel + items:(NSArray *)items; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h.backup b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h.backup new file mode 100644 index 0000000..64aac06 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.h.backup @@ -0,0 +1,26 @@ +// +// TTActionSheetView.h +// YM_TTChatViewKit +// +// Created by lee on 2019/5/22. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import +#import "TTPopupConstants.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TTActionSheetConfig; + +@interface TTActionSheetView : UIView + +@property (nonatomic, copy) TTPopupCompletionHandler cancelAction; +@property (nonatomic, copy) TTPopupCompletionHandler dismissAction; + +- (instancetype)initWithFrame:(CGRect)frame + needCancel:(BOOL)needCancel + items:(NSArray *)items; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m index bc27380..5328ca6 100644 --- a/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m +++ b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m @@ -1,10 +1,8 @@ -// -// TTActionSheetView.m -// YM_TTChatViewKit -// + + // Created by lee on 2019/5/22. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTActionSheetView.h" #import "TTActionSheetConfig.h" @@ -17,13 +15,13 @@ static NSString *const kSheetViewCellConst = @"kSheetViewCellConst"; @interface TTActionSheetView () -/** sheetView 载体 */ + @property (nonatomic, strong) UITableView *tableView; -/** 数据源 */ + @property (nonatomic, strong) NSArray *items; -/** 是否需要显示取消按钮 */ + @property (nonatomic, assign) BOOL needCancel; -/** 取消按钮 */ + @property (nonatomic, strong) UIButton *cancelButton; @end @@ -56,7 +54,7 @@ static NSString *const kSheetViewCellConst = @"kSheetViewCellConst"; }]; if (_needCancel) { - // 显示 cancel view + self.cancelButton.hidden = NO; [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.mas_equalTo(self); @@ -111,7 +109,7 @@ static NSString *const kSheetViewCellConst = @"kSheetViewCellConst"; - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - // 配置中的事件处理 + TTActionSheetConfig *config = _items[indexPath.row]; !config.clickAction ?: config.clickAction(); diff --git a/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m.backup b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m.backup new file mode 100644 index 0000000..bc27380 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/View/TTActionSheetView.m.backup @@ -0,0 +1,159 @@ +// +// TTActionSheetView.m +// YM_TTChatViewKit +// +// Created by lee on 2019/5/22. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTActionSheetView.h" +#import "TTActionSheetConfig.h" +#import "DJDKMIMOMColor.h" +#import + +static CGFloat const kSheetViewCellHeight = 51.f; +static CGFloat const kSheetViewCornerRadius = 14.f; +static NSString *const kSheetViewCellConst = @"kSheetViewCellConst"; + +@interface TTActionSheetView () + +/** sheetView 载体 */ +@property (nonatomic, strong) UITableView *tableView; +/** 数据源 */ +@property (nonatomic, strong) NSArray *items; +/** 是否需要显示取消按钮 */ +@property (nonatomic, assign) BOOL needCancel; +/** 取消按钮 */ +@property (nonatomic, strong) UIButton *cancelButton; + +@end + +@implementation TTActionSheetView + +#pragma mark - +#pragma mark lifeCycle +- (instancetype)initWithFrame:(CGRect)frame needCancel:(BOOL)needCancel items:(NSArray *)items { + self = [super initWithFrame:frame]; + if (self) { + _items = items; + _needCancel = needCancel; + [self initViews]; + [self initConstraints]; + } + return self; +} + +- (void)initViews { + [self addSubview:self.tableView]; + [self addSubview:self.cancelButton]; +} + +- (void)initConstraints { + + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.mas_equalTo(self); + make.height.mas_equalTo(self.items.count * kSheetViewCellHeight); + }]; + + if (_needCancel) { + // 显示 cancel view + self.cancelButton.hidden = NO; + [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self); + make.height.mas_equalTo(kSheetViewCellHeight); + make.top.mas_equalTo(self.tableView.mas_bottom).offset(15); + }]; + } + +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.items.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kSheetViewCellConst]; + cell.backgroundColor = UIColor.clearColor; + cell.textLabel.textAlignment = NSTextAlignmentCenter; + cell.textLabel.text = _items[indexPath.row].title; + cell.textLabel.textColor = _items[indexPath.row].titleColor; + + if ([_items[indexPath.row] displayMoliCoin]) { + NSTextAttachment *coinAttachment = [[NSTextAttachment alloc] init]; + coinAttachment.image = kImage(@"moli_money_icon"); + coinAttachment.bounds = CGRectMake(0, -3.5, 20, 20); + NSAttributedString *coinAttributedString = [NSAttributedString attributedStringWithAttachment:coinAttachment]; + NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithAttributedString:coinAttributedString]; + NSAttributedString *titleAttributedString = [[NSAttributedString alloc] initWithString:_items[indexPath.row].title + attributes:@{ + NSForegroundColorAttributeName: _items[indexPath.row].titleColor, + NSFontAttributeName: cell.textLabel.font + }]; + [string insertAttributedString:titleAttributedString atIndex:0]; + cell.textLabel.attributedText = string.copy; + + UIImageView *questionMark = [[UIImageView alloc] initWithImage:kImage(@"question_mark")]; + [cell.contentView addSubview:questionMark]; + [questionMark mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(cell.textLabel); + make.trailing.mas_equalTo(-20); + make.size.mas_equalTo(CGSizeMake(22, 22)); + }]; + } + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + // 配置中的事件处理 + TTActionSheetConfig *config = _items[indexPath.row]; + !config.clickAction ?: config.clickAction(); + + !_dismissAction ?: _dismissAction(); +} + +- (void)onClickCancelButtonAction:(UIButton *)cancelButton { + !_cancelAction ?: _cancelAction(); + !_dismissAction ?: _dismissAction(); +} + +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorColor = [DJDKMIMOMColor actionSeparatorColor]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; + _tableView.rowHeight = kSheetViewCellHeight; + _tableView.tableFooterView = [[UIView alloc] init]; + _tableView.backgroundColor = [UIColor whiteColor]; + _tableView.layer.cornerRadius = kSheetViewCornerRadius; + _tableView.layer.masksToBounds = YES; + _tableView.bounces = NO; + [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kSheetViewCellConst]; + } + return _tableView; +} + +- (UIButton *)cancelButton { + if (!_cancelButton) { + _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_cancelButton setTitle:YMLocalizedString(@"TTActionSheetView0") forState:UIControlStateNormal]; + [_cancelButton setBackgroundColor:UIColor.whiteColor]; + [_cancelButton setTitleColor:[DJDKMIMOMColor alertMessageColor] forState:UIControlStateNormal]; + [_cancelButton.titleLabel setFont:[UIFont systemFontOfSize:16]]; + _cancelButton.layer.cornerRadius = kSheetViewCornerRadius; + _cancelButton.layer.masksToBounds = YES; + [_cancelButton addTarget:self action:@selector(onClickCancelButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + _cancelButton.hidden = YES; + } + return _cancelButton; +} + +@end diff --git a/YuMi/CustomUI/TTPopup/View/TTAlertView.h b/YuMi/CustomUI/TTPopup/View/TTAlertView.h index bc6bcca..2f4c989 100644 --- a/YuMi/CustomUI/TTPopup/View/TTAlertView.h +++ b/YuMi/CustomUI/TTPopup/View/TTAlertView.h @@ -1,25 +1,23 @@ -// -// TTAlertView.h -// YM_TTChatViewKit -// -// Created by lee on 2019/5/20. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import -#import "TTPopupConstants.h" - -@class TTAlertConfig; - -NS_ASSUME_NONNULL_BEGIN - -@interface TTAlertView : UIView -@property (nonatomic, strong) TTAlertConfig *config;// 配置 -@property (nonatomic, assign) BOOL isConfigBoard;// 是否配置边框 -@property (nonatomic, copy) TTPopupCompletionHandler cancelAction; -@property (nonatomic, copy) TTPopupCompletionHandler confirmAction; -@property (nonatomic, copy) TTPopupCompletionHandler dismissAction; - -@end - -NS_ASSUME_NONNULL_END + + +// Created by lee on 2019/5/20. +// Copyright © 2023 YUMI. All rights reserved. + + +#import +#import "TTPopupConstants.h" + +@class TTAlertConfig; + +NS_ASSUME_NONNULL_BEGIN + +@interface TTAlertView : UIView +@property (nonatomic, strong) TTAlertConfig *config; +@property (nonatomic, assign) BOOL isConfigBoard; +@property (nonatomic, copy) TTPopupCompletionHandler cancelAction; +@property (nonatomic, copy) TTPopupCompletionHandler confirmAction; +@property (nonatomic, copy) TTPopupCompletionHandler dismissAction; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/View/TTAlertView.h.backup b/YuMi/CustomUI/TTPopup/View/TTAlertView.h.backup new file mode 100644 index 0000000..bc6bcca --- /dev/null +++ b/YuMi/CustomUI/TTPopup/View/TTAlertView.h.backup @@ -0,0 +1,25 @@ +// +// TTAlertView.h +// YM_TTChatViewKit +// +// Created by lee on 2019/5/20. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import +#import "TTPopupConstants.h" + +@class TTAlertConfig; + +NS_ASSUME_NONNULL_BEGIN + +@interface TTAlertView : UIView +@property (nonatomic, strong) TTAlertConfig *config;// 配置 +@property (nonatomic, assign) BOOL isConfigBoard;// 是否配置边框 +@property (nonatomic, copy) TTPopupCompletionHandler cancelAction; +@property (nonatomic, copy) TTPopupCompletionHandler confirmAction; +@property (nonatomic, copy) TTPopupCompletionHandler dismissAction; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/View/TTAlertView.m b/YuMi/CustomUI/TTPopup/View/TTAlertView.m index f1e3587..34a8dbf 100644 --- a/YuMi/CustomUI/TTPopup/View/TTAlertView.m +++ b/YuMi/CustomUI/TTPopup/View/TTAlertView.m @@ -1,10 +1,8 @@ -// -// TTAlertView.m -// YM_TTChatViewKit -// + + // Created by lee on 2019/5/20. // Copyright © 2023 YUMI. All rights reserved. -// + #import "TTAlertView.h" #import "TTAlertConfig.h" @@ -17,10 +15,10 @@ static CGFloat const kBtnHeight = 38.f; @interface TTAlertView () -@property (nonatomic, strong) UILabel *titleLabel; // 标题 -@property (nonatomic, strong) UILabel *messageLabel; // 内容 -@property (nonatomic, strong) UIButton *cancelButton; // 取消按钮 -@property (nonatomic, strong) UIButton *confirmButton; // 确认按钮 +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *messageLabel; +@property (nonatomic, strong) UIButton *cancelButton; +@property (nonatomic, strong) UIButton *confirmButton; @property (nonatomic, strong) UIStackView *stackView; @end @@ -86,27 +84,24 @@ static CGFloat const kBtnHeight = 38.f; } #pragma mark - private method -/** - 设置 messageLabel 需要显示的富文本效果 - @param config 弹窗配置 - @return 富文本内容 - */ + + - (NSMutableAttributedString *)messageAttributeString:(TTAlertConfig *)config { NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:config.message]; - if (config.messageLineSpacing > 0) { // 行间距 + if (config.messageLineSpacing > 0) { NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineSpacing = config.messageLineSpacing; paragraphStyle.alignment = config.messageTextAlignment; [attString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, config.message.length)]; } - // 富文本显示效果 + [config.messageAttributedConfig enumerateObjectsUsingBlock:^(TTAlertMessageAttributedConfig * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - // 遍历数组,添加展示富文本效果 + if ([obj isKindOfClass:[TTAlertMessageAttributedConfig class]]) { if (obj.text && obj.text.length > 0) { NSRange range = [config.message rangeOfString:obj.text]; - // 如果外部指定了 range 。就不用查找出的 range + if (obj.range.length != 0) { if (obj.range.location + obj.range.length > config.message.length) { NSAssert(NO, @"obj.range out of bounds"); @@ -114,10 +109,10 @@ static CGFloat const kBtnHeight = 38.f; } range = obj.range; } - if (obj.font) { // 字体 + if (obj.font) { [attString addAttribute:NSFontAttributeName value:obj.font range:range]; } - if (obj.color) { // 颜色 + if (obj.color) { [attString addAttribute:NSForegroundColorAttributeName value:obj.color range:range]; } } @@ -130,14 +125,14 @@ static CGFloat const kBtnHeight = 38.f; - (void)setConfig:(TTAlertConfig *)config { _config = config; - // cornerRadius + if (config.cornerRadius > 0) { self.layer.cornerRadius = config.cornerRadius; self.layer.masksToBounds = YES; } - //背景 + self.backgroundColor = config.backgroundColor; - // title + _titleLabel.text = config.title; _titleLabel.textColor = config.titleColor; _titleLabel.font = config.titleFont; @@ -145,7 +140,7 @@ static CGFloat const kBtnHeight = 38.f; _cancelButton.hidden = config.actionStyle == TTAlertActionConfirmStyle; _confirmButton.hidden = config.actionStyle == TTAlertActionCancelStyle; - // cancel button + [_cancelButton setTitle:config.cancelButtonConfig.title forState:UIControlStateNormal]; [_cancelButton setTitleColor:config.cancelButtonConfig.titleColor forState:UIControlStateNormal]; [_cancelButton.titleLabel setFont:config.cancelButtonConfig.font]; @@ -156,7 +151,7 @@ static CGFloat const kBtnHeight = 38.f; _cancelButton.layer.masksToBounds = YES; } - // confirm button + [_confirmButton setTitle:config.confirmButtonConfig.title forState:UIControlStateNormal]; [_confirmButton setTitleColor:config.confirmButtonConfig.titleColor forState:UIControlStateNormal]; [_confirmButton.titleLabel setFont:config.confirmButtonConfig.font]; @@ -167,7 +162,7 @@ static CGFloat const kBtnHeight = 38.f; _confirmButton.layer.masksToBounds = YES; } - // message + _messageLabel.font = config.messageFont; _messageLabel.textColor = config.messageColor; @@ -191,13 +186,13 @@ static CGFloat const kBtnHeight = 38.f; - (void)setIsConfigBoard:(BOOL)isConfigBoard { _isConfigBoard = isConfigBoard; if (isConfigBoard) { - //需要边框 + _cancelButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; _cancelButton.layer.borderWidth = 2.f; _confirmButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; _confirmButton.layer.borderWidth = 2.f; }else { - //不需要边框 + _cancelButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; _cancelButton.layer.borderWidth = 0; _confirmButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; diff --git a/YuMi/CustomUI/TTPopup/View/TTAlertView.m.backup b/YuMi/CustomUI/TTPopup/View/TTAlertView.m.backup new file mode 100644 index 0000000..f1e3587 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/View/TTAlertView.m.backup @@ -0,0 +1,255 @@ +// +// TTAlertView.m +// YM_TTChatViewKit +// +// Created by lee on 2019/5/20. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "TTAlertView.h" +#import "TTAlertConfig.h" +#import "DJDKMIMOMColor.h" +#import + +static CGFloat const kMargin = 25.f; +static CGFloat const kPadding = 20.f; +static CGFloat const kBtnHeight = 38.f; + +@interface TTAlertView () + +@property (nonatomic, strong) UILabel *titleLabel; // 标题 +@property (nonatomic, strong) UILabel *messageLabel; // 内容 +@property (nonatomic, strong) UIButton *cancelButton; // 取消按钮 +@property (nonatomic, strong) UIButton *confirmButton; // 确认按钮 +@property (nonatomic, strong) UIStackView *stackView; + +@end + +@implementation TTAlertView + +#pragma mark - lifeCyle +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initViews]; + [self initConstraints]; + } + return self; +} + +- (void)initViews { + [self addSubview:self.titleLabel]; + [self addSubview:self.messageLabel]; + [self addSubview:self.stackView]; + [self.stackView addSubview:self.cancelButton]; + [self.stackView addSubview:self.confirmButton]; +} + +- (void)initConstraints { + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self); + make.top.mas_equalTo(kPadding); + make.leading.trailing.mas_equalTo(self).inset(kPadding); + }]; + + [self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(kMargin); + make.leading.trailing.mas_equalTo(self).inset(kPadding); + make.bottom.mas_equalTo(self).offset(-kBtnHeight * 2); + }]; + + [self.stackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(-kPadding); + make.centerX.mas_equalTo(self); + }]; + + [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(kBtnHeight); + make.width.mas_equalTo(self.mas_width).multipliedBy(0.4); + }]; + + [self.confirmButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(kBtnHeight); + make.width.mas_equalTo(self.mas_width).multipliedBy(0.4); + }]; +} + +#pragma mark - Button Events +- (void)onClickConfirmButtonAction:(UIButton *)confirmButton { + !_confirmAction ?: _confirmAction(); + !_dismissAction ?: _dismissAction(); +} + +- (void)onClickCancelButtonAction:(UIButton *)cancelButton { + !_cancelAction ?: _cancelAction(); + !_dismissAction ?: _dismissAction(); +} + +#pragma mark - private method +/** + 设置 messageLabel 需要显示的富文本效果 + @param config 弹窗配置 + @return 富文本内容 + */ +- (NSMutableAttributedString *)messageAttributeString:(TTAlertConfig *)config { + NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:config.message]; + if (config.messageLineSpacing > 0) { // 行间距 + NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; + paragraphStyle.lineSpacing = config.messageLineSpacing; + paragraphStyle.alignment = config.messageTextAlignment; + [attString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, config.message.length)]; + } + + // 富文本显示效果 + [config.messageAttributedConfig enumerateObjectsUsingBlock:^(TTAlertMessageAttributedConfig * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + // 遍历数组,添加展示富文本效果 + if ([obj isKindOfClass:[TTAlertMessageAttributedConfig class]]) { + if (obj.text && obj.text.length > 0) { + NSRange range = [config.message rangeOfString:obj.text]; + // 如果外部指定了 range 。就不用查找出的 range + if (obj.range.length != 0) { + if (obj.range.location + obj.range.length > config.message.length) { + NSAssert(NO, @"obj.range out of bounds"); + return; + } + range = obj.range; + } + if (obj.font) { // 字体 + [attString addAttribute:NSFontAttributeName value:obj.font range:range]; + } + if (obj.color) { // 颜色 + [attString addAttribute:NSForegroundColorAttributeName value:obj.color range:range]; + } + } + } + }]; + return attString; +} + +#pragma mark - getter && setter + +- (void)setConfig:(TTAlertConfig *)config { + _config = config; + // cornerRadius + if (config.cornerRadius > 0) { + self.layer.cornerRadius = config.cornerRadius; + self.layer.masksToBounds = YES; + } + //背景 + self.backgroundColor = config.backgroundColor; + // title + _titleLabel.text = config.title; + _titleLabel.textColor = config.titleColor; + _titleLabel.font = config.titleFont; + + _cancelButton.hidden = config.actionStyle == TTAlertActionConfirmStyle; + _confirmButton.hidden = config.actionStyle == TTAlertActionCancelStyle; + + // cancel button + [_cancelButton setTitle:config.cancelButtonConfig.title forState:UIControlStateNormal]; + [_cancelButton setTitleColor:config.cancelButtonConfig.titleColor forState:UIControlStateNormal]; + [_cancelButton.titleLabel setFont:config.cancelButtonConfig.font]; + [_cancelButton setBackgroundColor:config.cancelButtonConfig.backgroundColor]; + [_cancelButton setBackgroundImage:config.cancelButtonConfig.backgroundImage forState:UIControlStateNormal]; + if (config.cancelButtonConfig.cornerRadius > 0) { + _cancelButton.layer.cornerRadius = config.cancelButtonConfig.cornerRadius; + _cancelButton.layer.masksToBounds = YES; + } + + // confirm button + [_confirmButton setTitle:config.confirmButtonConfig.title forState:UIControlStateNormal]; + [_confirmButton setTitleColor:config.confirmButtonConfig.titleColor forState:UIControlStateNormal]; + [_confirmButton.titleLabel setFont:config.confirmButtonConfig.font]; + [_confirmButton setBackgroundColor:config.confirmButtonConfig.backgroundColor]; + [_confirmButton setBackgroundImage:config.confirmButtonConfig.backgroundImage forState:UIControlStateNormal]; + if (config.confirmButtonConfig.cornerRadius > 0) { + _confirmButton.layer.cornerRadius = config.confirmButtonConfig.cornerRadius; + _confirmButton.layer.masksToBounds = YES; + } + + // message + _messageLabel.font = config.messageFont; + _messageLabel.textColor = config.messageColor; + + if (config.messageAttributedConfig.count > 0) { + _messageLabel.attributedText = [self messageAttributeString:config]; + _messageLabel.textAlignment = NSTextAlignmentCenter; + } else if(config.messageAttributed.length > 0) { + _messageLabel.attributedText = config.messageAttributed; + _messageLabel.textAlignment = NSTextAlignmentCenter; + } else { + _messageLabel.text = config.message; + _messageLabel.textAlignment = config.messageTextAlignment; + } + + _cancelButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; + _cancelButton.layer.borderWidth = 2.f; + _confirmButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; + _confirmButton.layer.borderWidth = 2.f; +} + +- (void)setIsConfigBoard:(BOOL)isConfigBoard { + _isConfigBoard = isConfigBoard; + if (isConfigBoard) { + //需要边框 + _cancelButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; + _cancelButton.layer.borderWidth = 2.f; + _confirmButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; + _confirmButton.layer.borderWidth = 2.f; + }else { + //不需要边框 + _cancelButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; + _cancelButton.layer.borderWidth = 0; + _confirmButton.layer.borderColor = [DJDKMIMOMColor dividerColor].CGColor; + _confirmButton.layer.borderWidth = 0; + } +} + + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.numberOfLines = 0; + } + return _titleLabel ; +} + +- (UILabel *)messageLabel { + if (!_messageLabel) { + _messageLabel = [[UILabel alloc] init]; + _messageLabel.numberOfLines = 0; + _messageLabel.textAlignment = NSTextAlignmentCenter; + _messageLabel.minimumScaleFactor = 0.7; + _messageLabel.adjustsFontSizeToFitWidth = YES; + } + return _messageLabel; +} + +- (UIButton *)cancelButton { + if (!_cancelButton) { + _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_cancelButton addTarget:self action:@selector(onClickCancelButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _cancelButton; +} + +- (UIButton *)confirmButton { + if (!_confirmButton) { + _confirmButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_confirmButton addTarget:self action:@selector(onClickConfirmButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _confirmButton; +} + +- (UIStackView *)stackView { + if (!_stackView) { + _stackView = [[UIStackView alloc] initWithArrangedSubviews:@[self.cancelButton, self.confirmButton]]; + _stackView.distribution = UIStackViewDistributionFillEqually; + _stackView.alignment = UIStackViewAlignmentCenter; + _stackView.spacing = 16; + } + return _stackView; +} + +@end diff --git a/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h index 0fadf88..dcadfba 100644 --- a/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h +++ b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h @@ -1,17 +1,13 @@ -// -// TTNewAlertView.h -// xplan-ios -// + + // Created by duoban on 2023/1/9. -// + #import NS_ASSUME_NONNULL_BEGIN - - @interface TTNewAlertView : UIView @property (nonatomic,copy) NSString *message; @property (nonatomic, copy) TTPopupCompletionHandler confirmHandle; diff --git a/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h.backup b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h.backup new file mode 100644 index 0000000..0fadf88 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.h.backup @@ -0,0 +1,20 @@ +// +// TTNewAlertView.h +// xplan-ios +// +// Created by duoban on 2023/1/9. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + + + + +@interface TTNewAlertView : UIView +@property (nonatomic,copy) NSString *message; +@property (nonatomic, copy) TTPopupCompletionHandler confirmHandle; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m index 5936960..8792fbf 100644 --- a/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m +++ b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m @@ -1,9 +1,7 @@ -// -// TTNewAlertView.m -// xplan-ios -// + + // Created by duoban on 2023/1/9. -// + #import "TTNewAlertView.h" @interface TTNewAlertView() @@ -58,7 +56,6 @@ }]; - } -(void)setMessage:(NSString *)message{ _message = message; @@ -86,7 +83,7 @@ } - (UILabel *)messageView{ if (!_messageView){ - _messageView = [UILabel labelInitWithText:@"" font:kFontRegular(15) textColor:[DJDKMIMOMColor inputTextColor]]; + _messageView = [[UILabel alloc] init]; _messageView.textAlignment = NSTextAlignmentCenter; _messageView.numberOfLines = 0; } diff --git a/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m.backup b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m.backup new file mode 100644 index 0000000..5936960 --- /dev/null +++ b/YuMi/CustomUI/TTPopup/View/TTNewAlertView.m.backup @@ -0,0 +1,118 @@ +// +// TTNewAlertView.m +// xplan-ios +// +// Created by duoban on 2023/1/9. +// + +#import "TTNewAlertView.h" +@interface TTNewAlertView() +@property (nonatomic,strong) UIView *bgView; +@property (nonatomic,strong) UILabel *messageView; +@property (nonatomic,strong) UIButton *confirmBtn; +@property (nonatomic,strong) UIButton *cancelBtn; +@end +@implementation TTNewAlertView + +-(instancetype)initWithFrame:(CGRect)frame{ + self = [super initWithFrame:frame]; + if(self){ + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + self.backgroundColor = [UIColor clearColor]; + [self addSubview:self.bgView]; + [self.bgView addSubview:self.messageView]; + [self.bgView addSubview:self.confirmBtn]; + [self.bgView addSubview:self.cancelBtn]; +} +- (void)initSubViewConstraints { + [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(kGetScaleWidth(310)); + make.height.mas_equalTo(kGetScaleWidth(149)); + make.center.equalTo(self); + }]; + + + [self.confirmBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kGetScaleWidth(110)); + make.height.mas_equalTo(kGetScaleWidth(37)); + make.leading.mas_equalTo(kGetScaleWidth(31)); + make.bottom.mas_equalTo(-kGetScaleWidth(31)); + }]; + + [self.cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.height.centerY.equalTo(self.confirmBtn); + make.trailing.mas_equalTo(-kGetScaleWidth(31)); + }]; + + [self.messageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(25)); + make.centerX.equalTo(self); + make.leading.trailing.equalTo(self).inset(kGetScaleWidth(10)); + }]; + + + +} +-(void)setMessage:(NSString *)message{ + _message = message; + _messageView.text = message; +} +-(void)confirmAction{ + [TTPopup dismiss]; + if(self.confirmHandle){ + self.confirmHandle(); + } +} +-(void)cancelAction{ + [TTPopup dismiss]; +} + +#pragma mark -懒加载 + +- (UIView *)bgView{ + if (!_bgView){ + _bgView = [UIView new]; + _bgView.backgroundColor = [UIColor whiteColor]; + [_bgView setCornerWithLeftTopCorner:kGetScaleWidth(12) rightTopCorner:kGetScaleWidth(12) bottomLeftCorner:kGetScaleWidth(12) bottomRightCorner:kGetScaleWidth(12) size:CGSizeMake(kGetScaleWidth(310), kGetScaleWidth(149))]; + } + return _bgView; +} +- (UILabel *)messageView{ + if (!_messageView){ + _messageView = [UILabel labelInitWithText:@"" font:kFontRegular(15) textColor:[DJDKMIMOMColor inputTextColor]]; + _messageView.textAlignment = NSTextAlignmentCenter; + _messageView.numberOfLines = 0; + } + return _messageView; +} +-(UIButton *)confirmBtn{ + if (!_confirmBtn){ + _confirmBtn = [UIButton new]; + [_confirmBtn setTitle:YMLocalizedString(@"TTAlertConfig0") forState:UIControlStateNormal]; + _confirmBtn.backgroundColor = UIColorFromRGB(0xE6E6F0); + _confirmBtn.layer.cornerRadius = kGetScaleWidth(37)/2; + _confirmBtn.layer.masksToBounds = YES; + [_confirmBtn addTarget:self action:@selector(confirmAction) forControlEvents:UIControlEventTouchUpInside]; + } + return _confirmBtn; +} +-(UIButton *)cancelBtn{ + if (!_cancelBtn){ + _cancelBtn = [UIButton new]; + [_cancelBtn setTitle:YMLocalizedString(@"XPShareView7") forState:UIControlStateNormal]; + UIImage *image = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor],[DJDKMIMOMColor confirmButtonGradientMiddleColor],[DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(110), kGetScaleWidth(37))]; + _cancelBtn.backgroundColor = [UIColor colorWithPatternImage:image]; + _cancelBtn.layer.cornerRadius = kGetScaleWidth(37)/2; + _cancelBtn.layer.masksToBounds = YES; + [_cancelBtn addTarget:self action:@selector(cancelAction) forControlEvents:UIControlEventTouchUpInside]; + } + return _cancelBtn; +} +@end diff --git a/YuMi/CustomUI/UIImage/UIImage+Utils.h b/YuMi/CustomUI/UIImage/UIImage+Utils.h index e0db37d..8540cfd 100644 --- a/YuMi/CustomUI/UIImage/UIImage+Utils.h +++ b/YuMi/CustomUI/UIImage/UIImage+Utils.h @@ -1,65 +1,21 @@ -// -// UIImage+Utils.h -// YYMobileFramework -// -// Created by wuwei on 14/6/20. -// Copyright (c) 2014年 YY Inc. All rights reserved. -// - -#import - -typedef NS_ENUM(NSUInteger, GradientType) { - GradientTypeTopToBottom = 0,//从上到小 - GradientTypeLeftToRight = 1,//从左到右 - GradientTypeUpleftToLowright = 2,//左上到右下 - GradientTypeUprightToLowleft = 3,//右上到左下 -}; - -@interface UIImage (Utils) - -- (UIImage *)grayscaleImage; - -- (UIImage *)imageBlendInGray; - -- (UIImage *)imageWithBlendMode:(CGBlendMode)blendMode; - -+ (UIImage *)imageWithColor:(UIColor *)color; - -+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size; - -+ (UIImage *)fixOrientation:(UIImage *)aImage; - -- (UIImage *)imageWithColor:(UIColor *)color; - -- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size; - -//异步生成纯色圆角图片 -- (void)imageWithSize:(CGSize)size radius:(CGFloat)radius backColor:(UIColor *)backColor completion:(void(^)(UIImage *image))completion; -/** - 返回指定大小,颜色,渐变模式的渐变色图片 - */ -+ (UIImage *)gradientColorImageFromColors:(NSArray*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize; - -+ (UIImage *)waterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect; - -+ (CGSize)sizeWithImageOriginSize:(CGSize)originSize - minSize:(CGSize)imageMinSize - maxSize:(CGSize)imageMaxSize; - -///裁剪图片 -- (UIImage *)cutImage:(CGSize)newSize; - -- (UIImage *)cropRightAndBottomPixels:(NSUInteger)pixels; - --(UIImage *)compressWithMaxLength:(NSUInteger)maxLength; -- (UIImage *)roundedImageWithCornerRadius:(CGFloat)cornerRadius size:(CGSize)size; -+(UIImage *)getImageFromView:(UIView *)view; -+ (NSString *)getImageTypeWithImageData: (NSData *)data; -+(UIImage *)getLanguageImage:(NSString *)image; -+(NSString *)getLanguageText:(NSString *)image; - -- (UIImage *)resizeTo:(CGSize)size; - -- (UIImage *)imageByApplyingAlpha:(CGFloat)alpha; - -@end + + +// Created by wuwei on 14/6/20. +// Copyright (c) 2014年 YY Inc. All rights reserved. + + +#import + +typedef NS_ENUM(NSUInteger, GradientType) { + GradientTypeTopToBottom = 0, + GradientTypeLeftToRight = 1, + GradientTypeUpleftToLowright = 2, + GradientTypeUprightToLowleft = 3, +}; + +@interface UIImage (Utils) + ++ (UIImage *)gradientColorImageFromColors:(NSArray*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize; ++ (NSString *)getImageTypeWithImageData: (NSData *)data; + +@end diff --git a/YuMi/CustomUI/UIImage/UIImage+Utils.h.backup b/YuMi/CustomUI/UIImage/UIImage+Utils.h.backup new file mode 100644 index 0000000..e0db37d --- /dev/null +++ b/YuMi/CustomUI/UIImage/UIImage+Utils.h.backup @@ -0,0 +1,65 @@ +// +// UIImage+Utils.h +// YYMobileFramework +// +// Created by wuwei on 14/6/20. +// Copyright (c) 2014年 YY Inc. All rights reserved. +// + +#import + +typedef NS_ENUM(NSUInteger, GradientType) { + GradientTypeTopToBottom = 0,//从上到小 + GradientTypeLeftToRight = 1,//从左到右 + GradientTypeUpleftToLowright = 2,//左上到右下 + GradientTypeUprightToLowleft = 3,//右上到左下 +}; + +@interface UIImage (Utils) + +- (UIImage *)grayscaleImage; + +- (UIImage *)imageBlendInGray; + +- (UIImage *)imageWithBlendMode:(CGBlendMode)blendMode; + ++ (UIImage *)imageWithColor:(UIColor *)color; + ++ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size; + ++ (UIImage *)fixOrientation:(UIImage *)aImage; + +- (UIImage *)imageWithColor:(UIColor *)color; + +- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size; + +//异步生成纯色圆角图片 +- (void)imageWithSize:(CGSize)size radius:(CGFloat)radius backColor:(UIColor *)backColor completion:(void(^)(UIImage *image))completion; +/** + 返回指定大小,颜色,渐变模式的渐变色图片 + */ ++ (UIImage *)gradientColorImageFromColors:(NSArray*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize; + ++ (UIImage *)waterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect; + ++ (CGSize)sizeWithImageOriginSize:(CGSize)originSize + minSize:(CGSize)imageMinSize + maxSize:(CGSize)imageMaxSize; + +///裁剪图片 +- (UIImage *)cutImage:(CGSize)newSize; + +- (UIImage *)cropRightAndBottomPixels:(NSUInteger)pixels; + +-(UIImage *)compressWithMaxLength:(NSUInteger)maxLength; +- (UIImage *)roundedImageWithCornerRadius:(CGFloat)cornerRadius size:(CGSize)size; ++(UIImage *)getImageFromView:(UIView *)view; ++ (NSString *)getImageTypeWithImageData: (NSData *)data; ++(UIImage *)getLanguageImage:(NSString *)image; ++(NSString *)getLanguageText:(NSString *)image; + +- (UIImage *)resizeTo:(CGSize)size; + +- (UIImage *)imageByApplyingAlpha:(CGFloat)alpha; + +@end diff --git a/YuMi/CustomUI/UIImage/UIImage+Utils.m b/YuMi/CustomUI/UIImage/UIImage+Utils.m index e1c59ea..10013f8 100644 --- a/YuMi/CustomUI/UIImage/UIImage+Utils.m +++ b/YuMi/CustomUI/UIImage/UIImage+Utils.m @@ -1,487 +1,13 @@ -// -// UIImage+Utils.m -// YYMobileFramework -// + + // Created by wuwei on 14/6/20. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import "UIImage+Utils.h" #import @implementation UIImage (Utils) -- (UIImage *)grayscaleImage -{ - CGFloat width = self.size.width; - CGFloat height = self.size.height; - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); - - CGContextRef context = CGBitmapContextCreate(nil, - width, - height, - 8, - 0, - colorSpace, - kCGImageAlphaNone); -// kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); - - - if (context == NULL) { - return nil; - } - - CGContextDrawImage(context, CGRectMake(0, 0, width, height), self.CGImage); - CGImageRef imageRef = CGBitmapContextCreateImage(context); - UIImage *grayscaleImage = [UIImage imageWithCGImage:imageRef]; - CGImageRelease(imageRef); - CGContextRelease(context); - CGColorSpaceRelease(colorSpace); - - return grayscaleImage; -} - - -- (UIImage *)imageBlendInGray { - - UIGraphicsBeginImageContext(self.size); - CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextFillRect(context, bounds); - [self drawInRect:bounds blendMode:kCGBlendModeLuminosity alpha:1.0f]; - [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f]; - UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return newImg; -} - - - -- (UIImage *)imageWithBlendMode:(CGBlendMode)blendMode { - - UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f); - CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height); - UIRectFill(bounds); - - [self drawInRect:bounds blendMode:blendMode alpha:1.0f]; - - if (blendMode != kCGBlendModeDestinationIn) { - [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f]; - } - UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return newImg; -} - -+ (UIImage *)imageWithColor:(UIColor *)color -{ - return [self imageWithColor:color size:CGSizeMake(1, 1)]; -} - -+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size { - if (!color || size.width <= 0 || size.height <= 0) return nil; - CGRect rect = CGRectMake(0.0f, 0.0f, size.width + 1, size.height); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, color.CGColor); - CGContextFillRect(context, rect); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -+ (UIImage *)fixOrientation:(UIImage *)aImage { - - // No-op if the orientation is already correct - if (aImage.imageOrientation == UIImageOrientationUp) - return aImage; - - // We need to calculate the proper transformation to make the image upright. - // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. - CGAffineTransform transform = CGAffineTransformIdentity; - - switch (aImage.imageOrientation) { - case UIImageOrientationDown: - case UIImageOrientationDownMirrored: - transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height); - transform = CGAffineTransformRotate(transform, M_PI); - break; - - case UIImageOrientationLeft: - case UIImageOrientationLeftMirrored: - transform = CGAffineTransformTranslate(transform, aImage.size.width, 0); - transform = CGAffineTransformRotate(transform, M_PI_2); - break; - - case UIImageOrientationRight: - case UIImageOrientationRightMirrored: - transform = CGAffineTransformTranslate(transform, 0, aImage.size.height); - transform = CGAffineTransformRotate(transform, -M_PI_2); - break; - default: - break; - } - - switch (aImage.imageOrientation) { - case UIImageOrientationUpMirrored: - case UIImageOrientationDownMirrored: - transform = CGAffineTransformTranslate(transform, aImage.size.width, 0); - transform = CGAffineTransformScale(transform, -1, 1); - break; - - case UIImageOrientationLeftMirrored: - case UIImageOrientationRightMirrored: - transform = CGAffineTransformTranslate(transform, aImage.size.height, 0); - transform = CGAffineTransformScale(transform, -1, 1); - break; - default: - break; - } - - // Now we draw the underlying CGImage into a new context, applying the transform - // calculated above. - CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height, - CGImageGetBitsPerComponent(aImage.CGImage), 0, - CGImageGetColorSpace(aImage.CGImage), - CGImageGetBitmapInfo(aImage.CGImage)); - CGContextConcatCTM(ctx, transform); - switch (aImage.imageOrientation) { - case UIImageOrientationLeft: - case UIImageOrientationLeftMirrored: - case UIImageOrientationRight: - case UIImageOrientationRightMirrored: - // Grr... - CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage); - break; - - default: - CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage); - break; - } - - // And now we just create a new UIImage from the drawing context - CGImageRef cgimg = CGBitmapContextCreateImage(ctx); - UIImage *img = [UIImage imageWithCGImage:cgimg]; - CGContextRelease(ctx); - CGImageRelease(cgimg); - return img; -} - -- (UIImage *)imageWithColor:(UIColor *)color { - CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); - UIGraphicsBeginImageContext(rect.size); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSetFillColorWithColor(context, [color CGColor]); - CGContextFillRect(context, rect); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; - -} - -//异步生成纯色圆角图片 -- (void)imageWithSize:(CGSize)size radius:(CGFloat)radius backColor:(UIColor *)backColor completion:(void(^)(UIImage *image))completion { - // 异步绘制裁切 - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - // 利用绘图建立上下文 - UIGraphicsBeginImageContextWithOptions(size, true, 0); - CGRect rect = CGRectMake(0, 0, size.width, size.height); - // 填充颜色 - [backColor setFill]; - UIRectFill(rect); - // // 贝塞尔裁切 - // UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; - // [path addClip]; - // [self drawInRect:rect]; - - // 获取结果 - UIImage *resultImage = [UIGraphicsGetImageFromCurrentImageContext() circularImage]; - // 关闭上下文 - UIGraphicsEndImageContext(); - // 主队列回调 - dispatch_async(dispatch_get_main_queue(), ^{ - completion(resultImage); - }); - }); - -} - -- (UIImage *)circularImage { - // 1. 开启图形上下文 - UIGraphicsBeginImageContextWithOptions(self.size, NO, 0); - - // 2. 描述路径 - - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.size.width, self.size.height) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(self.size.width, self.size.height)]; - // UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; - - // 3. 添加裁减区域 - [path addClip]; - - // 4. 绘制图片 - [self drawAtPoint:CGPointZero]; - - // 5. 从上下文获取图片 - UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); - - // 6. 关闭上下文 - UIGraphicsEndImageContext(); - - // 7. 设置图片 - return image; -} - -+ (UIImage *)gradientColorImageFromColors:(NSArray *)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize{ - - NSMutableArray *ar = [NSMutableArray array]; - for(UIColor *c in colors) { - [ar addObject:(id)c.CGColor]; - } - UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSaveGState(context); - CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]); - CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL); - CGPoint start; - CGPoint end; - switch (gradientType) { - case GradientTypeTopToBottom: - start = CGPointMake(0.0, 0.0); - end = CGPointMake(0.0, imgSize.height); - break; - case GradientTypeLeftToRight: - start = CGPointMake(0.0, 0.0); - end = CGPointMake(imgSize.width, 0.0); - break; - case GradientTypeUpleftToLowright: - start = CGPointMake(0.0, 0.0); - end = CGPointMake(imgSize.width, imgSize.height); - break; - case GradientTypeUprightToLowleft: - start = CGPointMake(imgSize.width, 0.0); - end = CGPointMake(0.0, imgSize.height); - break; - default: - break; - } - CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - CGGradientRelease(gradient); - CGContextRestoreGState(context); - CGColorSpaceRelease(colorSpace); - UIGraphicsEndImageContext(); - - return image; -} - -- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size { - //开启图形上下文 - UIGraphicsBeginImageContext(size); - //绘制圆角矩形 - CGRect rect = CGRectMake(0, 0, size.width, size.height); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; - //将Path添加到上下文中 - CGContextAddPath(UIGraphicsGetCurrentContext(), path.CGPath); - //裁剪上下文 - CGContextClip(UIGraphicsGetCurrentContext()); - //将图片绘制到上下文中 - [self drawInRect:rect]; - //设置绘制模式 - CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathStroke); - //获取图片 - UIImage *output = UIGraphicsGetImageFromCurrentImageContext(); - //关闭上下文 - UIGraphicsEndImageContext(); - //返回裁剪好的图片 - return output; -} - -// 给图片添加图片水印 -+ (UIImage *)waterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect -{ - //1.获取图片 - //2.开启上下文 - UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); - //3.绘制背景图片 - [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; - //绘制水印图片到当前上下文 - [waterImage drawInRect:rect]; - //4.从上下文中获取新图片 - UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext(); - //5.关闭图形上下文 - UIGraphicsEndImageContext(); - //返回图片 - return newImage; -} - -+ (CGSize)sizeWithImageOriginSize:(CGSize)originSize - minSize:(CGSize)imageMinSize - maxSize:(CGSize)imageMaxSiz { - CGSize size; - NSInteger imageWidth = originSize.width ,imageHeight = originSize.height; - NSInteger imageMinWidth = imageMinSize.width, imageMinHeight = imageMinSize.height; - NSInteger imageMaxWidth = imageMaxSiz.width, imageMaxHeight = imageMaxSiz.height; - if (imageWidth > imageHeight) //宽图 - { - size.height = imageMinHeight; //高度取最小高度 - size.width = imageWidth * imageMinHeight / imageHeight; - if (size.width > imageMaxWidth) - { - size.width = imageMaxWidth; - } - } - else if(imageWidth < imageHeight)//高图 - { - size.width = imageMinWidth; - size.height = imageHeight *imageMinWidth / imageWidth; - if (size.height > imageMaxHeight){ - size.height = imageMaxHeight; - } - } - else//方图 - { - if (imageWidth > imageMaxWidth){ - size.width = imageMaxWidth; - size.height = imageMaxHeight; - }else if(imageWidth > imageMinWidth){ - size.width = imageWidth; - size.height = imageHeight; - }else{ - size.width = imageMinWidth; - size.height = imageMinHeight; - } - } - return size; -} - -- (UIImage *)cutImage:(CGSize)newSize{ - - CGFloat scale = newSize.height / self.size.height; - UIImage *scaleImage = [self originImage:self scaleToSize:CGSizeMake(self.size.width*scale, self.size.height*scale)]; - //裁剪暂时有问题 - return scaleImage; -} - -- (UIImage *)resizeTo:(CGSize)size { - UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size]; - return [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context) { - [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; - }]; -} - -- (UIImage *)cropRightAndBottomPixels:(NSUInteger)pixels { - // 获取原图像的大小 - CGSize originalSize = self.size; - - // 计算新的裁剪后的图像大小 - CGSize newSize = CGSizeMake(originalSize.width - pixels, originalSize.height - pixels); - - // 开始图像上下文 - UIGraphicsBeginImageContextWithOptions(newSize, NO, self.scale); - - // 绘制裁剪后的图像到上下文 - [self drawAtPoint:CGPointZero]; - - // 获取裁剪后的图像 - UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext(); - - // 结束图像上下文 - UIGraphicsEndImageContext(); - - return croppedImage; -} - -- (UIImage*) originImage:(UIImage *)image scaleToSize:(CGSize)size { - - UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); - - [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; - - UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); - - return scaledImage; -} - - --(UIImage *)compressWithMaxLength:(NSUInteger)maxLength{ - // Compress by quality - CGFloat compression = 1; - NSData *data = UIImageJPEGRepresentation(self, compression); - if (data.length < maxLength) return self; - - CGFloat max = 1; - CGFloat min = 0; - for (int i = 0; i < 6; ++i) { - compression = (max + min) / 2; - data = UIImageJPEGRepresentation(self, compression); - //NSLog(@"Compression = %.1f", compression); - //NSLog(@"In compressing quality loop, image size = %ld KB", data.length / 1024); - if (data.length < maxLength * 0.9) { - min = compression; - } else if (data.length > maxLength) { - max = compression; - } else { - break; - } - } - //NSLog(@"After compressing quality, image size = %ld KB", data.length / 1024); - if (data.length < maxLength) return self; - UIImage *resultImage = [UIImage imageWithData:data]; - // Compress by size - NSUInteger lastDataLength = 0; - while (data.length > maxLength && data.length != lastDataLength) { - lastDataLength = data.length; - CGFloat ratio = (CGFloat)maxLength / data.length; - //NSLog(@"Ratio = %.1f", ratio); - CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)), - (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank - UIGraphicsBeginImageContext(size); - [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)]; - resultImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - data = UIImageJPEGRepresentation(resultImage, compression); - //NSLog(@"In compressing size loop, image size = %ld KB", data.length / 1024); - } - if (data) { - return [UIImage imageWithData:data];; - } else { - return self; - } -} -- (UIImage *)roundedImageWithCornerRadius:(CGFloat)cornerRadius size:(CGSize)size{ - UIGraphicsBeginImageContextWithOptions(size, NO, 1); - UIBezierPath *clippingPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:cornerRadius]; - [clippingPath addClip]; - [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; - UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return roundedImage; -} -+(UIImage *)getImageFromView:(UIView *)view { - // 1. 创建一个新的图像上下文,大小与view的bounds相匹配 - UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0); - - // 2. 获取当前图像上下文 - CGContextRef context = UIGraphicsGetCurrentContext(); - - // 3. 将view的层级渲染到上下文中 - [view.layer renderInContext:context]; - - // 4. 从上下文中获取生成的图片 - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - - // 5. 结束图像上下文 - UIGraphicsEndImageContext(); - - // 6. 返回生成的图片 - return image; -} + (NSString *)getImageTypeWithImageData:(NSData *)data { uint8_t c; @@ -530,63 +56,49 @@ return nil; } -+(UIImage *)getLanguageImage:(NSString *)image{ - NSString *curImage = image; - NSString *language = [NSBundle getLanguageText]; - if (isMSZH()) { - // 不處理 - } else if (isMSTR()) { - image = [NSString stringWithFormat:@"%@_tr", image]; - } else if (isMSRTL()) { - image = [NSString stringWithFormat:@"%@_ar", image]; - } else { - image = [NSString stringWithFormat:@"%@_en", image]; ++ (UIImage *)gradientColorImageFromColors:(NSArray *)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize{ + + NSMutableArray *ar = [NSMutableArray array]; + for(UIColor *c in colors) { + [ar addObject:(id)c.CGColor]; } - - // 尝试获取带语言后缀的图片 - UIImage *getImage = kImage(image); - - // 若图片不存在,尝试使用英语图片作为默认 - if (getImage == nil) { - NSString *defaultImageName = [NSString stringWithFormat:@"%@_en", curImage]; - getImage = kImage(defaultImageName) ?: kImage(curImage); + UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]); + CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL); + CGPoint start; + CGPoint end; + switch (gradientType) { + case GradientTypeTopToBottom: + start = CGPointMake(0.0, 0.0); + end = CGPointMake(0.0, imgSize.height); + break; + case GradientTypeLeftToRight: + start = CGPointMake(0.0, 0.0); + end = CGPointMake(imgSize.width, 0.0); + break; + case GradientTypeUpleftToLowright: + start = CGPointMake(0.0, 0.0); + end = CGPointMake(imgSize.width, imgSize.height); + break; + case GradientTypeUprightToLowleft: + start = CGPointMake(imgSize.width, 0.0); + end = CGPointMake(0.0, imgSize.height); + break; + default: + break; } - - return getImage; -} -+(NSString *)getLanguageText:(NSString *)image{ - NSString *curImage = image; - NSString *language = [NSBundle getLanguageText]; - if ([language isEqualToString:@"en"]){ - image = [NSString stringWithFormat:@"%@_en",image]; - } else if ([language isEqualToString:@"ar"]){ - image = [NSString stringWithFormat:@"%@_ar",image]; - } else if ([language isEqualToString:@"tr"]) { // 土耳其语默认使用英语内容 - image = [NSString stringWithFormat:@"%@_en",image]; - } - if (kImage(image) == nil){ - return curImage; - } - return image; -} - -- (UIImage *)imageByApplyingAlpha:(CGFloat)alpha { - UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f); - CGContextRef ctx = UIGraphicsGetCurrentContext(); - CGRect area = CGRectMake(0, 0, self.size.width, self.size.height); - - CGContextScaleCTM(ctx, 1, -1); - CGContextTranslateCTM(ctx, 0, -area.size.height); - - CGContextSetBlendMode(ctx, kCGBlendModeMultiply); - CGContextSetAlpha(ctx, alpha); - CGContextDrawImage(ctx, area, self.CGImage); - - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + CGGradientRelease(gradient); + CGContextRestoreGState(context); + CGColorSpaceRelease(colorSpace); UIGraphicsEndImageContext(); - - return newImage; + + return image; } + @end diff --git a/YuMi/CustomUI/UIImage/UIImage+Utils.m.backup b/YuMi/CustomUI/UIImage/UIImage+Utils.m.backup new file mode 100644 index 0000000..e1c59ea --- /dev/null +++ b/YuMi/CustomUI/UIImage/UIImage+Utils.m.backup @@ -0,0 +1,592 @@ +// +// UIImage+Utils.m +// YYMobileFramework +// +// Created by wuwei on 14/6/20. +// Copyright (c) 2014年 YY Inc. All rights reserved. +// + +#import "UIImage+Utils.h" +#import + +@implementation UIImage (Utils) +- (UIImage *)grayscaleImage +{ + CGFloat width = self.size.width; + CGFloat height = self.size.height; + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); + + CGContextRef context = CGBitmapContextCreate(nil, + width, + height, + 8, + 0, + colorSpace, + kCGImageAlphaNone); +// kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); + + + if (context == NULL) { + return nil; + } + + CGContextDrawImage(context, CGRectMake(0, 0, width, height), self.CGImage); + CGImageRef imageRef = CGBitmapContextCreateImage(context); + UIImage *grayscaleImage = [UIImage imageWithCGImage:imageRef]; + CGImageRelease(imageRef); + CGContextRelease(context); + CGColorSpaceRelease(colorSpace); + + return grayscaleImage; +} + + +- (UIImage *)imageBlendInGray { + + UIGraphicsBeginImageContext(self.size); + CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextFillRect(context, bounds); + [self drawInRect:bounds blendMode:kCGBlendModeLuminosity alpha:1.0f]; + [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f]; + UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return newImg; +} + + + +- (UIImage *)imageWithBlendMode:(CGBlendMode)blendMode { + + UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f); + CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height); + UIRectFill(bounds); + + [self drawInRect:bounds blendMode:blendMode alpha:1.0f]; + + if (blendMode != kCGBlendModeDestinationIn) { + [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f]; + } + UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImg; +} + ++ (UIImage *)imageWithColor:(UIColor *)color +{ + return [self imageWithColor:color size:CGSizeMake(1, 1)]; +} + ++ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size { + if (!color || size.width <= 0 || size.height <= 0) return nil; + CGRect rect = CGRectMake(0.0f, 0.0f, size.width + 1, size.height); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, color.CGColor); + CGContextFillRect(context, rect); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + ++ (UIImage *)fixOrientation:(UIImage *)aImage { + + // No-op if the orientation is already correct + if (aImage.imageOrientation == UIImageOrientationUp) + return aImage; + + // We need to calculate the proper transformation to make the image upright. + // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. + CGAffineTransform transform = CGAffineTransformIdentity; + + switch (aImage.imageOrientation) { + case UIImageOrientationDown: + case UIImageOrientationDownMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height); + transform = CGAffineTransformRotate(transform, M_PI); + break; + + case UIImageOrientationLeft: + case UIImageOrientationLeftMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.width, 0); + transform = CGAffineTransformRotate(transform, M_PI_2); + break; + + case UIImageOrientationRight: + case UIImageOrientationRightMirrored: + transform = CGAffineTransformTranslate(transform, 0, aImage.size.height); + transform = CGAffineTransformRotate(transform, -M_PI_2); + break; + default: + break; + } + + switch (aImage.imageOrientation) { + case UIImageOrientationUpMirrored: + case UIImageOrientationDownMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.width, 0); + transform = CGAffineTransformScale(transform, -1, 1); + break; + + case UIImageOrientationLeftMirrored: + case UIImageOrientationRightMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.height, 0); + transform = CGAffineTransformScale(transform, -1, 1); + break; + default: + break; + } + + // Now we draw the underlying CGImage into a new context, applying the transform + // calculated above. + CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height, + CGImageGetBitsPerComponent(aImage.CGImage), 0, + CGImageGetColorSpace(aImage.CGImage), + CGImageGetBitmapInfo(aImage.CGImage)); + CGContextConcatCTM(ctx, transform); + switch (aImage.imageOrientation) { + case UIImageOrientationLeft: + case UIImageOrientationLeftMirrored: + case UIImageOrientationRight: + case UIImageOrientationRightMirrored: + // Grr... + CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage); + break; + + default: + CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage); + break; + } + + // And now we just create a new UIImage from the drawing context + CGImageRef cgimg = CGBitmapContextCreateImage(ctx); + UIImage *img = [UIImage imageWithCGImage:cgimg]; + CGContextRelease(ctx); + CGImageRelease(cgimg); + return img; +} + +- (UIImage *)imageWithColor:(UIColor *)color { + CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); + UIGraphicsBeginImageContext(rect.size); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetFillColorWithColor(context, [color CGColor]); + CGContextFillRect(context, rect); + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; + +} + +//异步生成纯色圆角图片 +- (void)imageWithSize:(CGSize)size radius:(CGFloat)radius backColor:(UIColor *)backColor completion:(void(^)(UIImage *image))completion { + // 异步绘制裁切 + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + // 利用绘图建立上下文 + UIGraphicsBeginImageContextWithOptions(size, true, 0); + CGRect rect = CGRectMake(0, 0, size.width, size.height); + // 填充颜色 + [backColor setFill]; + UIRectFill(rect); + // // 贝塞尔裁切 + // UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; + // [path addClip]; + // [self drawInRect:rect]; + + // 获取结果 + UIImage *resultImage = [UIGraphicsGetImageFromCurrentImageContext() circularImage]; + // 关闭上下文 + UIGraphicsEndImageContext(); + // 主队列回调 + dispatch_async(dispatch_get_main_queue(), ^{ + completion(resultImage); + }); + }); + +} + +- (UIImage *)circularImage { + // 1. 开启图形上下文 + UIGraphicsBeginImageContextWithOptions(self.size, NO, 0); + + // 2. 描述路径 + + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.size.width, self.size.height) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(self.size.width, self.size.height)]; + // UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; + + // 3. 添加裁减区域 + [path addClip]; + + // 4. 绘制图片 + [self drawAtPoint:CGPointZero]; + + // 5. 从上下文获取图片 + UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); + + // 6. 关闭上下文 + UIGraphicsEndImageContext(); + + // 7. 设置图片 + return image; +} + ++ (UIImage *)gradientColorImageFromColors:(NSArray *)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize{ + + NSMutableArray *ar = [NSMutableArray array]; + for(UIColor *c in colors) { + [ar addObject:(id)c.CGColor]; + } + UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]); + CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL); + CGPoint start; + CGPoint end; + switch (gradientType) { + case GradientTypeTopToBottom: + start = CGPointMake(0.0, 0.0); + end = CGPointMake(0.0, imgSize.height); + break; + case GradientTypeLeftToRight: + start = CGPointMake(0.0, 0.0); + end = CGPointMake(imgSize.width, 0.0); + break; + case GradientTypeUpleftToLowright: + start = CGPointMake(0.0, 0.0); + end = CGPointMake(imgSize.width, imgSize.height); + break; + case GradientTypeUprightToLowleft: + start = CGPointMake(imgSize.width, 0.0); + end = CGPointMake(0.0, imgSize.height); + break; + default: + break; + } + CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + CGGradientRelease(gradient); + CGContextRestoreGState(context); + CGColorSpaceRelease(colorSpace); + UIGraphicsEndImageContext(); + + return image; +} + +- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size { + //开启图形上下文 + UIGraphicsBeginImageContext(size); + //绘制圆角矩形 + CGRect rect = CGRectMake(0, 0, size.width, size.height); + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; + //将Path添加到上下文中 + CGContextAddPath(UIGraphicsGetCurrentContext(), path.CGPath); + //裁剪上下文 + CGContextClip(UIGraphicsGetCurrentContext()); + //将图片绘制到上下文中 + [self drawInRect:rect]; + //设置绘制模式 + CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathStroke); + //获取图片 + UIImage *output = UIGraphicsGetImageFromCurrentImageContext(); + //关闭上下文 + UIGraphicsEndImageContext(); + //返回裁剪好的图片 + return output; +} + +// 给图片添加图片水印 ++ (UIImage *)waterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect +{ + //1.获取图片 + //2.开启上下文 + UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); + //3.绘制背景图片 + [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; + //绘制水印图片到当前上下文 + [waterImage drawInRect:rect]; + //4.从上下文中获取新图片 + UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext(); + //5.关闭图形上下文 + UIGraphicsEndImageContext(); + //返回图片 + return newImage; +} + ++ (CGSize)sizeWithImageOriginSize:(CGSize)originSize + minSize:(CGSize)imageMinSize + maxSize:(CGSize)imageMaxSiz { + CGSize size; + NSInteger imageWidth = originSize.width ,imageHeight = originSize.height; + NSInteger imageMinWidth = imageMinSize.width, imageMinHeight = imageMinSize.height; + NSInteger imageMaxWidth = imageMaxSiz.width, imageMaxHeight = imageMaxSiz.height; + if (imageWidth > imageHeight) //宽图 + { + size.height = imageMinHeight; //高度取最小高度 + size.width = imageWidth * imageMinHeight / imageHeight; + if (size.width > imageMaxWidth) + { + size.width = imageMaxWidth; + } + } + else if(imageWidth < imageHeight)//高图 + { + size.width = imageMinWidth; + size.height = imageHeight *imageMinWidth / imageWidth; + if (size.height > imageMaxHeight){ + size.height = imageMaxHeight; + } + } + else//方图 + { + if (imageWidth > imageMaxWidth){ + size.width = imageMaxWidth; + size.height = imageMaxHeight; + }else if(imageWidth > imageMinWidth){ + size.width = imageWidth; + size.height = imageHeight; + }else{ + size.width = imageMinWidth; + size.height = imageMinHeight; + } + } + return size; +} + +- (UIImage *)cutImage:(CGSize)newSize{ + + CGFloat scale = newSize.height / self.size.height; + UIImage *scaleImage = [self originImage:self scaleToSize:CGSizeMake(self.size.width*scale, self.size.height*scale)]; + //裁剪暂时有问题 + return scaleImage; +} + +- (UIImage *)resizeTo:(CGSize)size { + UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size]; + return [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context) { + [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; + }]; +} + +- (UIImage *)cropRightAndBottomPixels:(NSUInteger)pixels { + // 获取原图像的大小 + CGSize originalSize = self.size; + + // 计算新的裁剪后的图像大小 + CGSize newSize = CGSizeMake(originalSize.width - pixels, originalSize.height - pixels); + + // 开始图像上下文 + UIGraphicsBeginImageContextWithOptions(newSize, NO, self.scale); + + // 绘制裁剪后的图像到上下文 + [self drawAtPoint:CGPointZero]; + + // 获取裁剪后的图像 + UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext(); + + // 结束图像上下文 + UIGraphicsEndImageContext(); + + return croppedImage; +} + +- (UIImage*) originImage:(UIImage *)image scaleToSize:(CGSize)size { + + UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); + + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + + UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + return scaledImage; +} + + +-(UIImage *)compressWithMaxLength:(NSUInteger)maxLength{ + // Compress by quality + CGFloat compression = 1; + NSData *data = UIImageJPEGRepresentation(self, compression); + if (data.length < maxLength) return self; + + CGFloat max = 1; + CGFloat min = 0; + for (int i = 0; i < 6; ++i) { + compression = (max + min) / 2; + data = UIImageJPEGRepresentation(self, compression); + //NSLog(@"Compression = %.1f", compression); + //NSLog(@"In compressing quality loop, image size = %ld KB", data.length / 1024); + if (data.length < maxLength * 0.9) { + min = compression; + } else if (data.length > maxLength) { + max = compression; + } else { + break; + } + } + //NSLog(@"After compressing quality, image size = %ld KB", data.length / 1024); + if (data.length < maxLength) return self; + UIImage *resultImage = [UIImage imageWithData:data]; + // Compress by size + NSUInteger lastDataLength = 0; + while (data.length > maxLength && data.length != lastDataLength) { + lastDataLength = data.length; + CGFloat ratio = (CGFloat)maxLength / data.length; + //NSLog(@"Ratio = %.1f", ratio); + CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)), + (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank + UIGraphicsBeginImageContext(size); + [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)]; + resultImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + data = UIImageJPEGRepresentation(resultImage, compression); + //NSLog(@"In compressing size loop, image size = %ld KB", data.length / 1024); + } + if (data) { + return [UIImage imageWithData:data];; + } else { + return self; + } +} +- (UIImage *)roundedImageWithCornerRadius:(CGFloat)cornerRadius size:(CGSize)size{ + UIGraphicsBeginImageContextWithOptions(size, NO, 1); + UIBezierPath *clippingPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:cornerRadius]; + [clippingPath addClip]; + [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return roundedImage; +} ++(UIImage *)getImageFromView:(UIView *)view { + // 1. 创建一个新的图像上下文,大小与view的bounds相匹配 + UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0); + + // 2. 获取当前图像上下文 + CGContextRef context = UIGraphicsGetCurrentContext(); + + // 3. 将view的层级渲染到上下文中 + [view.layer renderInContext:context]; + + // 4. 从上下文中获取生成的图片 + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + + // 5. 结束图像上下文 + UIGraphicsEndImageContext(); + + // 6. 返回生成的图片 + return image; +} ++ (NSString *)getImageTypeWithImageData:(NSData *)data { + + uint8_t c; + + [data getBytes:&c length:1]; + + switch (c) { + + case 0xFF: + + return @"jpeg"; + + case 0x89: + + return @"png"; + + case 0x47: + + return @"gif"; + + case 0x49: + + case 0x4D: + + return @"tiff"; + + case 0x52: + + if ([data length] < 12) { + + return nil; + + } + + NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding]; + + if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) { + + return @"webp"; + + } + + return nil; + + } + + return nil; +} ++(UIImage *)getLanguageImage:(NSString *)image{ + NSString *curImage = image; + NSString *language = [NSBundle getLanguageText]; + + if (isMSZH()) { + // 不處理 + } else if (isMSTR()) { + image = [NSString stringWithFormat:@"%@_tr", image]; + } else if (isMSRTL()) { + image = [NSString stringWithFormat:@"%@_ar", image]; + } else { + image = [NSString stringWithFormat:@"%@_en", image]; + } + + // 尝试获取带语言后缀的图片 + UIImage *getImage = kImage(image); + + // 若图片不存在,尝试使用英语图片作为默认 + if (getImage == nil) { + NSString *defaultImageName = [NSString stringWithFormat:@"%@_en", curImage]; + getImage = kImage(defaultImageName) ?: kImage(curImage); + } + + return getImage; +} ++(NSString *)getLanguageText:(NSString *)image{ + NSString *curImage = image; + NSString *language = [NSBundle getLanguageText]; + if ([language isEqualToString:@"en"]){ + image = [NSString stringWithFormat:@"%@_en",image]; + } else if ([language isEqualToString:@"ar"]){ + image = [NSString stringWithFormat:@"%@_ar",image]; + } else if ([language isEqualToString:@"tr"]) { // 土耳其语默认使用英语内容 + image = [NSString stringWithFormat:@"%@_en",image]; + } + if (kImage(image) == nil){ + return curImage; + } + return image; +} + +- (UIImage *)imageByApplyingAlpha:(CGFloat)alpha { + UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGRect area = CGRectMake(0, 0, self.size.width, self.size.height); + + CGContextScaleCTM(ctx, 1, -1); + CGContextTranslateCTM(ctx, 0, -area.size.height); + + CGContextSetBlendMode(ctx, kCGBlendModeMultiply); + CGContextSetAlpha(ctx, alpha); + CGContextDrawImage(ctx, area, self.CGImage); + + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return newImage; +} + +@end diff --git a/YuMi/CustomUI/UIImageView/NetImageConfig.h b/YuMi/CustomUI/UIImageView/NetImageConfig.h index 9c00444..98e79b9 100644 --- a/YuMi/CustomUI/UIImageView/NetImageConfig.h +++ b/YuMi/CustomUI/UIImageView/NetImageConfig.h @@ -1,9 +1,7 @@ -// -// NetImageConfig.h -// YUMI -// + + // Created by zu on 2021/11/25. -// + #import #import "UIImageConstant.h" diff --git a/YuMi/CustomUI/UIImageView/NetImageConfig.h.backup b/YuMi/CustomUI/UIImageView/NetImageConfig.h.backup new file mode 100644 index 0000000..9c00444 --- /dev/null +++ b/YuMi/CustomUI/UIImageView/NetImageConfig.h.backup @@ -0,0 +1,22 @@ +// +// NetImageConfig.h +// YUMI +// +// Created by zu on 2021/11/25. +// + +#import +#import "UIImageConstant.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NetImageConfig : NSObject + +@property (nonatomic, assign) BOOL autoLoad; +@property (nonatomic, assign) ImageType imageType; +@property (nonatomic, assign) CGFloat radius; +@property (nonatomic, strong) UIImage * placeHolder; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/UIImageView/NetImageConfig.m b/YuMi/CustomUI/UIImageView/NetImageConfig.m index f1274d4..a7d6be2 100644 --- a/YuMi/CustomUI/UIImageView/NetImageConfig.m +++ b/YuMi/CustomUI/UIImageView/NetImageConfig.m @@ -1,9 +1,7 @@ -// -// NetImageConfig.m -// YUMI -// + + // Created by zu on 2021/11/25. -// + #import "NetImageConfig.h" diff --git a/YuMi/CustomUI/UIImageView/NetImageConfig.m.backup b/YuMi/CustomUI/UIImageView/NetImageConfig.m.backup new file mode 100644 index 0000000..f1274d4 --- /dev/null +++ b/YuMi/CustomUI/UIImageView/NetImageConfig.m.backup @@ -0,0 +1,21 @@ +// +// NetImageConfig.m +// YUMI +// +// Created by zu on 2021/11/25. +// + +#import "NetImageConfig.h" + +@implementation NetImageConfig + +- (instancetype)init +{ + self = [super init]; + if (self) { + _autoLoad = YES; + } + return self; +} + +@end diff --git a/YuMi/CustomUI/UIImageView/NetImageView.h b/YuMi/CustomUI/UIImageView/NetImageView.h index d299c75..d6e7258 100644 --- a/YuMi/CustomUI/UIImageView/NetImageView.h +++ b/YuMi/CustomUI/UIImageView/NetImageView.h @@ -1,9 +1,7 @@ -// -// NetImageView.h -// YUMI -// + + // Created by zu on 2021/11/2. -// + #import #import "UIImageConstant.h" @@ -24,7 +22,7 @@ typedef NS_ENUM(NSInteger, NetImageState){ @property (nonatomic, assign, readonly) NetImageState state; @property (nonatomic, copy) NSString* imageUrl; -@property (nonatomic, assign) NSInteger backgroundLightType; // 0: non; 1: gold; 2: gray; 3: purple +@property (nonatomic, assign) NSInteger backgroundLightType; - (instancetype)initWithUrl:(NSString * _Nonnull)imageUrl; - (instancetype)initWithConfig:(NetImageConfig * _Nullable)config; diff --git a/YuMi/CustomUI/UIImageView/NetImageView.h.backup b/YuMi/CustomUI/UIImageView/NetImageView.h.backup new file mode 100644 index 0000000..d299c75 --- /dev/null +++ b/YuMi/CustomUI/UIImageView/NetImageView.h.backup @@ -0,0 +1,45 @@ +// +// NetImageView.h +// YUMI +// +// Created by zu on 2021/11/2. +// + +#import +#import "UIImageConstant.h" +#import "NetImageConfig.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^LoadCompletion)(UIImage *_Nullable image, NSURL * url); +typedef void(^LoadFail)(NSError *error); + +typedef NS_ENUM(NSInteger, NetImageState){ + NetImageStateUnload = 1, + NetImageStateLoading, + NetImageStateLoaded, +}; + +@interface NetImageView : UIImageView + +@property (nonatomic, assign, readonly) NetImageState state; +@property (nonatomic, copy) NSString* imageUrl; +@property (nonatomic, assign) NSInteger backgroundLightType; // 0: non; 1: gold; 2: gray; 3: purple + +- (instancetype)initWithUrl:(NSString * _Nonnull)imageUrl; +- (instancetype)initWithConfig:(NetImageConfig * _Nullable)config; +- (instancetype)initWithUrl:(NSString * _Nonnull)imageUrl config:(NetImageConfig * _Nullable)config; + +- (UIImage *)lightImage:(NSInteger)type; + +- (void)loadImage:(LoadCompletion _Nullable)completion; +- (void)loadImageWithUrl:(NSString * _Nonnull)imageUrl completion:(LoadCompletion _Nullable)completion; +- (void)loadImageWithUrl:(NSString * _Nonnull)imageUrl completion:(LoadCompletion _Nullable)completion fail:(LoadFail _Nullable)fail; + +- (void)updateConfigPlaceHolder:(UIImage *)image; + +- (void)cancelLoadImage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/UIImageView/NetImageView.m b/YuMi/CustomUI/UIImageView/NetImageView.m index d773ec0..9a7ef2f 100644 --- a/YuMi/CustomUI/UIImageView/NetImageView.m +++ b/YuMi/CustomUI/UIImageView/NetImageView.m @@ -1,9 +1,7 @@ -// -// NetImageView.m -// YUMI -// + + // Created by zu on 2021/11/2. -// + #import "NetImageView.h" #import diff --git a/YuMi/CustomUI/UIImageView/NetImageView.m.backup b/YuMi/CustomUI/UIImageView/NetImageView.m.backup new file mode 100644 index 0000000..d773ec0 --- /dev/null +++ b/YuMi/CustomUI/UIImageView/NetImageView.m.backup @@ -0,0 +1,151 @@ +// +// NetImageView.m +// YUMI +// +// Created by zu on 2021/11/2. +// + +#import "NetImageView.h" +#import +#import + +@interface NetImageView() + +@property (nonatomic, assign, readwrite) NetImageState state; +@property (nonatomic, copy) NSString * innerConfigUrl; +@property (nonatomic, strong) NetImageConfig * config; +@property (nonatomic, strong) UIImageView *lightImageView; + +@end + +@implementation NetImageView + +- (instancetype)initWithUrl:(NSString *)url { + return [self initWithUrl:url config:nil]; +} + +- (instancetype)initWithConfig:(NetImageConfig *)config { + return [self initWithUrl:@"" config:config]; +} + +- (instancetype)initWithUrl:(NSString *)url config:(NetImageConfig *)config { + self = [super init]; + if (self) { + _state = NetImageStateUnload; + _config = config; + if (_config.autoLoad) { + [self setImageUrl:url]; + } else { + [self initImageUrl:url]; + } + + } + return self; +} + +- (void)cancelLoadImage { + [self sd_cancelCurrentImageLoad]; +} + +- (void)initImageUrl:(NSString *)imageUrl { + _imageUrl = imageUrl; + _innerConfigUrl = [UIImageConstant configUrl:_imageUrl type:self.config.imageType radius:self.config.radius]; +} + +- (void)setBackgroundLightType:(NSInteger)backgroundLightType { + _backgroundLightType = backgroundLightType; + if (!_lightImageView) { + _lightImageView = [[UIImageView alloc] init]; + [self insertSubview:_lightImageView atIndex:0]; + [_lightImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; + } + switch (_backgroundLightType) { + case 1: + _lightImageView.image = [UIImage imageNamed:@"room_pk_result_avatar_bg_yellow"]; + break; + case 2: + _lightImageView.image = [UIImage imageNamed:@"room_pk_result_avatar_bg_gray"]; + break; + case 3: + _lightImageView.image = [UIImage imageNamed:@"room_pk_result_avatar_bg_purple"]; + break; + default: + _lightImageView.image = nil; + break; + } +} + +- (UIImage *)lightImage:(NSInteger)type { + switch (type) { + case 1: + return [UIImage imageNamed:@"room_pk_result_avatar_bg_yellow"]; + case 2: + return [UIImage imageNamed:@"room_pk_result_avatar_bg_gray"]; + case 3: + return [UIImage imageNamed:@"room_pk_result_avatar_bg_purple"]; + default: + return nil; + } +} + +- (void)setImageUrl:(NSString *)imageUrl { + [self initImageUrl:imageUrl]; + [self loadImage:nil fail:nil]; +} + +- (void)loadImage:(LoadCompletion)completion { + [self loadImage:completion fail:nil]; +} + +- (void)loadImageWithUrl:(NSString *)imageUrl completion:(LoadCompletion)completion { + [self initImageUrl:imageUrl]; + [self loadImage:completion fail:nil]; +} + +- (void)loadImageWithUrl:(NSString * _Nonnull)imageUrl completion:(LoadCompletion _Nullable)completion fail:(LoadFail _Nullable)fail{ + [self initImageUrl:imageUrl]; + [self loadImage:completion fail:fail]; +} + +- (void)loadImage:(LoadCompletion _Nullable)completion fail:(LoadFail _Nullable)fail{ + self.state = NetImageStateLoading; + @kWeakify(self); + [self sd_setImageWithURL:[NSURL URLWithString:self.innerConfigUrl] + placeholderImage:self.config.placeHolder + options:SDWebImageRetryFailed | SDWebImageQueryMemoryData | SDWebImageQueryDiskDataSync + completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + @kStrongify(self); + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + self.state = NetImageStateUnload; + if (fail){ + fail(error); + } + } else { + self.image = image; + self.state = NetImageStateLoaded; + if (completion) { + completion(image, imageURL); + }; + } + }); + }]; +} + +- (NetImageConfig *)config { + if (!_config) { + _config = [[NetImageConfig alloc] init]; + } + return _config; +} + +- (void)updateConfigPlaceHolder:(UIImage *)image { + self.config.placeHolder = image; + if (self.state == NetImageStateUnload) { + self.image = image; + } +} + +@end diff --git a/YuMi/CustomUI/UIImageView/UIImageConstant.h b/YuMi/CustomUI/UIImageView/UIImageConstant.h index 55a4cc5..dc69c33 100644 --- a/YuMi/CustomUI/UIImageView/UIImageConstant.h +++ b/YuMi/CustomUI/UIImageView/UIImageConstant.h @@ -1,9 +1,7 @@ -// -// UIImageViewConstant.h -// YUMI -// + + // Created by YUMI on 2021/9/17. -// 存放一些 加载图片 需要做的裁剪的key + #import @@ -13,35 +11,33 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - 图片相关的 -UIKIT_EXTERN NSString * const kImageTypeRoomFace; //房间表情 -UIKIT_EXTERN NSString * const kImageTypeRoomGift; //房间礼物 -UIKIT_EXTERN NSString * const kImageTypeUserIcon; //用户头像60x60 -UIKIT_EXTERN NSString * const kImageTypeUserLibaryDetail;//用户相册大图nil -UIKIT_EXTERN NSString * const kImageTypeCornerAvatar;//圆角图形,会先把图形裁剪成正方形,并且转换为png -UIKIT_EXTERN NSString * const kImageTypeUserInfoAlbum;//用户信息里面相册 -UIKIT_EXTERN NSString * const kImageTypeUserCardLevel;///用户资料卡中 等级以高度20等比例缩放 -UIKIT_EXTERN NSString * const kImageTypeMonentsPhoto;///动态中的图片 +UIKIT_EXTERN NSString * const kImageTypeRoomFace; +UIKIT_EXTERN NSString * const kImageTypeRoomGift; +UIKIT_EXTERN NSString * const kImageTypeUserIcon; +UIKIT_EXTERN NSString * const kImageTypeUserLibaryDetail; +UIKIT_EXTERN NSString * const kImageTypeCornerAvatar; +UIKIT_EXTERN NSString * const kImageTypeUserInfoAlbum; +UIKIT_EXTERN NSString * const kImageTypeUserCardLevel; +UIKIT_EXTERN NSString * const kImageTypeMonentsPhoto; typedef NS_ENUM(NSUInteger, ImageType){ - ImageTypeRoomFace = 1, //房间表情 - ImageTypeRoomGift, //房间礼物 - ImageTypeUserIcon, //用户头像60x60 - ImageTypeUserLibaryDetail, //用户相册大图 - ImageTypeCornerAvatar, //圆角图形,会先把图形裁剪成正方形,并且转换为png - ImageTypeUserInfoAlbum, ///用户信息里面相册 - ImageTypeUserCardLevel, /// 用户资料卡中 等级以高度20等比例缩放 - ImageTypeMonentsPhoto, ///动态中的图片 + ImageTypeRoomFace = 1, + ImageTypeRoomGift, + ImageTypeUserIcon, + ImageTypeUserLibaryDetail, + ImageTypeCornerAvatar, + ImageTypeUserInfoAlbum, + ImageTypeUserCardLevel, + ImageTypeMonentsPhoto, }; -///展位图 -/// 头像的默认占位图 + (UIImage *)defaultAvatarPlaceholder; -///空白头像缺省图 + + (UIImage *)defaultEmptyAvatarPlaceholder; -/// 空白图的占位图 + + (UIImage *)defaultEmptyPlaceholder; + (UIImage *)defaultEmptyPlaceholder_UFO; -/// banner的占位图 + + (UIImage *)defaultBannerPlaceholder; + (NSString*)configUrl:(NSString*)url type:(ImageType)type; diff --git a/YuMi/CustomUI/UIImageView/UIImageConstant.h.backup b/YuMi/CustomUI/UIImageView/UIImageConstant.h.backup new file mode 100644 index 0000000..55a4cc5 --- /dev/null +++ b/YuMi/CustomUI/UIImageView/UIImageConstant.h.backup @@ -0,0 +1,53 @@ +// +// UIImageViewConstant.h +// YUMI +// +// Created by YUMI on 2021/9/17. +// 存放一些 加载图片 需要做的裁剪的key + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIImageConstant : NSObject + + +#pragma mark - 图片相关的 +UIKIT_EXTERN NSString * const kImageTypeRoomFace; //房间表情 +UIKIT_EXTERN NSString * const kImageTypeRoomGift; //房间礼物 +UIKIT_EXTERN NSString * const kImageTypeUserIcon; //用户头像60x60 +UIKIT_EXTERN NSString * const kImageTypeUserLibaryDetail;//用户相册大图nil +UIKIT_EXTERN NSString * const kImageTypeCornerAvatar;//圆角图形,会先把图形裁剪成正方形,并且转换为png +UIKIT_EXTERN NSString * const kImageTypeUserInfoAlbum;//用户信息里面相册 +UIKIT_EXTERN NSString * const kImageTypeUserCardLevel;///用户资料卡中 等级以高度20等比例缩放 +UIKIT_EXTERN NSString * const kImageTypeMonentsPhoto;///动态中的图片 +typedef NS_ENUM(NSUInteger, ImageType){ + ImageTypeRoomFace = 1, //房间表情 + ImageTypeRoomGift, //房间礼物 + ImageTypeUserIcon, //用户头像60x60 + ImageTypeUserLibaryDetail, //用户相册大图 + ImageTypeCornerAvatar, //圆角图形,会先把图形裁剪成正方形,并且转换为png + ImageTypeUserInfoAlbum, ///用户信息里面相册 + ImageTypeUserCardLevel, /// 用户资料卡中 等级以高度20等比例缩放 + ImageTypeMonentsPhoto, ///动态中的图片 +}; + +///展位图 + +/// 头像的默认占位图 ++ (UIImage *)defaultAvatarPlaceholder; +///空白头像缺省图 ++ (UIImage *)defaultEmptyAvatarPlaceholder; +/// 空白图的占位图 ++ (UIImage *)defaultEmptyPlaceholder; ++ (UIImage *)defaultEmptyPlaceholder_UFO; +/// banner的占位图 ++ (UIImage *)defaultBannerPlaceholder; + ++ (NSString*)configUrl:(NSString*)url type:(ImageType)type; ++ (NSString*)configUrl:(NSString*)url radius:(CGFloat)radius; ++ (NSString*)configUrl:(NSString*)url type:(ImageType)type radius:(CGFloat)radius; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/UIImageView/UIImageConstant.m b/YuMi/CustomUI/UIImageView/UIImageConstant.m index b5249f4..8f06a57 100644 --- a/YuMi/CustomUI/UIImageView/UIImageConstant.m +++ b/YuMi/CustomUI/UIImageView/UIImageConstant.m @@ -1,45 +1,43 @@ -// -// UIImageViewConstant.m -// YUMI -// + + // Created by YUMI on 2021/9/17. -// + #import "UIImageConstant.h" @implementation UIImageConstant -/// 房间表情 + NSString * const kImageTypeRoomFace = @""; -/// 房间礼物 + NSString * const kImageTypeRoomGift = @""; -/// 用户头像150x150 + NSString * const kImageTypeUserIcon = @"imageMogr2/auto-orient/thumbnail/150x150"; -/// 用户相册大图 + NSString * const kImageTypeUserLibaryDetail = @"imageMogr2/auto-orient/thumbnail/300x300"; NSString * const kImageTypeCornerAvatar = @"imageMogr2/auto-orient/thumbnail/300x300/format/png"; -/// 用户信息里面相册 + NSString * const kImageTypeUserInfoAlbum = @"imageMogr2/auto-orient/blur/375x375"; -/// 用户信息里面相册 + NSString * const kImageTypeUserCardLevel = @"imageMogr2/thumbnail/x40"; -/// 动态中的图片 400 * 400 + NSString * const kImageTypeMonentsPhoto = @"imageMogr2/auto-orient/thumbnail/400x400"; -/// 头像的默认占位图 + + (UIImage *)defaultAvatarPlaceholder { return [UIImage imageNamed:@"common_avatar"]; } -///空白头像缺省图 + + (UIImage *)defaultEmptyAvatarPlaceholder { return [UIImage imageNamed:@"common_avatar"]; } -/// 空白图的占位图 + + (UIImage *)defaultEmptyPlaceholder { return [UIImage imageNamed:@"common_empty"]; } -/// banner的占位图 + + (UIImage *)defaultBannerPlaceholder { return [UIImage imageNamed:@"common_banner"]; } @@ -107,10 +105,10 @@ NSString * const kImageTypeMonentsPhoto = @"imageMogr2/auto-orient/thumbnail/400 } NSString *percentEscapeString(NSString *string) { - // 创建一个包含所有不需要百分比编码的字符集 + NSMutableCharacterSet *allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; - // 手动删除你想要百分比编码的字符, 其余的非字符将会变成带 % 的转义符 + [allowedCharacterSet removeCharactersInString:@"|"]; return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; diff --git a/YuMi/CustomUI/UIImageView/UIImageConstant.m.backup b/YuMi/CustomUI/UIImageView/UIImageConstant.m.backup new file mode 100644 index 0000000..b5249f4 --- /dev/null +++ b/YuMi/CustomUI/UIImageView/UIImageConstant.m.backup @@ -0,0 +1,119 @@ +// +// UIImageViewConstant.m +// YUMI +// +// Created by YUMI on 2021/9/17. +// + +#import "UIImageConstant.h" + +@implementation UIImageConstant + +/// 房间表情 +NSString * const kImageTypeRoomFace = @""; +/// 房间礼物 +NSString * const kImageTypeRoomGift = @""; +/// 用户头像150x150 +NSString * const kImageTypeUserIcon = @"imageMogr2/auto-orient/thumbnail/150x150"; +/// 用户相册大图 +NSString * const kImageTypeUserLibaryDetail = @"imageMogr2/auto-orient/thumbnail/300x300"; +NSString * const kImageTypeCornerAvatar = @"imageMogr2/auto-orient/thumbnail/300x300/format/png"; +/// 用户信息里面相册 +NSString * const kImageTypeUserInfoAlbum = @"imageMogr2/auto-orient/blur/375x375"; +/// 用户信息里面相册 +NSString * const kImageTypeUserCardLevel = @"imageMogr2/thumbnail/x40"; +/// 动态中的图片 400 * 400 +NSString * const kImageTypeMonentsPhoto = @"imageMogr2/auto-orient/thumbnail/400x400"; + +/// 头像的默认占位图 ++ (UIImage *)defaultAvatarPlaceholder { + return [UIImage imageNamed:@"common_avatar"]; +} + +///空白头像缺省图 ++ (UIImage *)defaultEmptyAvatarPlaceholder { + return [UIImage imageNamed:@"common_avatar"]; +} + +/// 空白图的占位图 ++ (UIImage *)defaultEmptyPlaceholder { + return [UIImage imageNamed:@"common_empty"]; +} +/// banner的占位图 ++ (UIImage *)defaultBannerPlaceholder { + return [UIImage imageNamed:@"common_banner"]; +} + ++ (UIImage *)defaultEmptyPlaceholder_UFO { + return [UIImage imageNamed:@"common_empty_UFO"]; +} + + ++ (NSString *)configUrl:(NSString *)url type:(ImageType)type { + return [self configUrl:url type:type radius:0]; +} + ++ (NSString *)configUrl:(NSString *)url radius:(CGFloat)radius { + return [self configUrl:url type:-1 radius:radius]; +} + ++ (NSString *)configUrl:(NSString *)url type:(ImageType)type radius:(CGFloat)radius { + if (!url || url.length <= 0) return nil; + NSMutableString *urlString = [NSMutableString stringWithString:url]; + NSString *configUrl = nil; + switch (type) { + case ImageTypeUserIcon: + configUrl = kImageTypeUserIcon; + break; + case ImageTypeCornerAvatar: + configUrl = kImageTypeCornerAvatar; + break; + case ImageTypeRoomFace: + configUrl = kImageTypeRoomFace; + break; + case ImageTypeUserLibaryDetail: + configUrl = kImageTypeUserLibaryDetail; + break; + case ImageTypeRoomGift: + configUrl = kImageTypeRoomGift; + break; + case ImageTypeUserInfoAlbum: + configUrl = kImageTypeUserInfoAlbum; + break; + case ImageTypeUserCardLevel: + configUrl = kImageTypeUserCardLevel; + break; + case ImageTypeMonentsPhoto: + configUrl = kImageTypeMonentsPhoto; + break; + default: + break; + } + + if (configUrl) { + if ([url containsString:@"?"]) { + [urlString appendString:@"|"]; + }else{ + [urlString appendString:@"?"]; + } + [urlString appendString:configUrl]; + } + + if (radius > 0) { + [urlString appendString:[NSString stringWithFormat:@"|roundPic/radius/%f", radius]]; + } + + return percentEscapeString(urlString); +} + +NSString *percentEscapeString(NSString *string) { + // 创建一个包含所有不需要百分比编码的字符集 + NSMutableCharacterSet *allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + + // 手动删除你想要百分比编码的字符, 其余的非字符将会变成带 % 的转义符 + [allowedCharacterSet removeCharactersInString:@"|"]; + + return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; +} + +@end diff --git a/YuMi/CustomUI/UIViewCorner/UIView+Corner.h b/YuMi/CustomUI/UIViewCorner/UIView+Corner.h index 23781a5..d540686 100644 --- a/YuMi/CustomUI/UIViewCorner/UIView+Corner.h +++ b/YuMi/CustomUI/UIViewCorner/UIView+Corner.h @@ -1,9 +1,7 @@ -// -// UIView+Corner.h -// YUMI -// + + // Created by YUMI on 2022/6/15. -// + #import @@ -16,44 +14,15 @@ NS_ASSUME_NONNULL_BEGIN bottomRightCorner:(CGFloat)bottemRight size:(CGSize)size; -///** -// * 设置视图的圆角半径,边框宽度和颜色 -// * -// * @param radius 圆角半径 -// * @param corners 圆角位置 (可以组合使用 UIRectCornerTopLeft、UIRectCornerTopRight、UIRectCornerBottomLeft、UIRectCornerBottomRight) -// * @param borderWidth 边框宽度 -// * @param borderColor 边框颜色 -// */ -//- (void)setCornerRadius:(CGFloat)radius -// corners:(UIRectCorner)corners -// borderWidth:(CGFloat)borderWidth -// borderColor:(UIColor *)borderColor; -/** - * 直接设置视图的圆角半径,应用到所有角 - * - * @param radius 圆角半径 - */ - (void)setCornerRadius:(CGFloat)radius; -/** - * 直接设置视图的圆角半径和指定角 - * - * @param radius 圆角半径 - * @param corners 指定需要圆角的位置 (UIRectCornerTopLeft, UIRectCornerTopRight, etc.) - */ + - (void)setCornerRadius:(CGFloat)radius corners:(UIRectCorner)corners; - (void)setCornerRadius:(CGFloat)radius cornerMask:(CACornerMask)cornerMask; -/** - * 设置视图的指定圆角、圆角半径、边框宽度和边框颜色 - * - * @param radius 圆角半径 - * @param corners 需要圆角的角位置 (可以组合,例如 `kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner`) - * @param borderWidth 边框宽度 - * @param borderColor 边框颜色 - */ + - (void)setCornerRadius:(CGFloat)radius corners:(CACornerMask)corners borderWidth:(CGFloat)borderWidth diff --git a/YuMi/CustomUI/UIViewCorner/UIView+Corner.h.backup b/YuMi/CustomUI/UIViewCorner/UIView+Corner.h.backup new file mode 100644 index 0000000..23781a5 --- /dev/null +++ b/YuMi/CustomUI/UIViewCorner/UIView+Corner.h.backup @@ -0,0 +1,67 @@ +// +// UIView+Corner.h +// YUMI +// +// Created by YUMI on 2022/6/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (Corner) +- (void)setCornerWithLeftTopCorner:(CGFloat)leftTop + rightTopCorner:(CGFloat)rigtTop + bottomLeftCorner:(CGFloat)bottemLeft + bottomRightCorner:(CGFloat)bottemRight + size:(CGSize)size; + +///** +// * 设置视图的圆角半径,边框宽度和颜色 +// * +// * @param radius 圆角半径 +// * @param corners 圆角位置 (可以组合使用 UIRectCornerTopLeft、UIRectCornerTopRight、UIRectCornerBottomLeft、UIRectCornerBottomRight) +// * @param borderWidth 边框宽度 +// * @param borderColor 边框颜色 +// */ +//- (void)setCornerRadius:(CGFloat)radius +// corners:(UIRectCorner)corners +// borderWidth:(CGFloat)borderWidth +// borderColor:(UIColor *)borderColor; + +/** + * 直接设置视图的圆角半径,应用到所有角 + * + * @param radius 圆角半径 + */ +- (void)setCornerRadius:(CGFloat)radius; + +/** + * 直接设置视图的圆角半径和指定角 + * + * @param radius 圆角半径 + * @param corners 指定需要圆角的位置 (UIRectCornerTopLeft, UIRectCornerTopRight, etc.) + */ +- (void)setCornerRadius:(CGFloat)radius corners:(UIRectCorner)corners; + +- (void)setCornerRadius:(CGFloat)radius cornerMask:(CACornerMask)cornerMask; + +/** + * 设置视图的指定圆角、圆角半径、边框宽度和边框颜色 + * + * @param radius 圆角半径 + * @param corners 需要圆角的角位置 (可以组合,例如 `kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner`) + * @param borderWidth 边框宽度 + * @param borderColor 边框颜色 + */ +- (void)setCornerRadius:(CGFloat)radius + corners:(CACornerMask)corners + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor; + +- (void)setAllCornerRadius:(CGFloat)radius + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/UIViewCorner/UIView+Corner.m b/YuMi/CustomUI/UIViewCorner/UIView+Corner.m index b274a0f..be91a30 100644 --- a/YuMi/CustomUI/UIViewCorner/UIView+Corner.m +++ b/YuMi/CustomUI/UIViewCorner/UIView+Corner.m @@ -1,9 +1,7 @@ -// -// UIView+Corner.m -// YUMI -// + + // Created by YUMI on 2022/6/15. -// + #import "UIView+Corner.h" @@ -21,18 +19,18 @@ maskPath.lineWidth = 1.0; maskPath.lineCapStyle = kCGLineCapRound; maskPath.lineJoinStyle = kCGLineJoinRound; - [maskPath moveToPoint:CGPointMake(bottemRight, height)]; //左下角 + [maskPath moveToPoint:CGPointMake(bottemRight, height)]; [maskPath addLineToPoint:CGPointMake(width - bottemRight, height)]; - [maskPath addQuadCurveToPoint:CGPointMake(width, height- bottemRight) controlPoint:CGPointMake(width, height)]; //右下角的圆弧 - [maskPath addLineToPoint:CGPointMake(width, rigtTop)]; //右边直线 + [maskPath addQuadCurveToPoint:CGPointMake(width, height- bottemRight) controlPoint:CGPointMake(width, height)]; + [maskPath addLineToPoint:CGPointMake(width, rigtTop)]; - [maskPath addQuadCurveToPoint:CGPointMake(width - rigtTop, 0) controlPoint:CGPointMake(width, 0)]; //右上角圆弧 - [maskPath addLineToPoint:CGPointMake(leftTop, 0)]; //顶部直线 + [maskPath addQuadCurveToPoint:CGPointMake(width - rigtTop, 0) controlPoint:CGPointMake(width, 0)]; + [maskPath addLineToPoint:CGPointMake(leftTop, 0)]; - [maskPath addQuadCurveToPoint:CGPointMake(0, leftTop) controlPoint:CGPointMake(0, 0)]; //左上角圆弧 - [maskPath addLineToPoint:CGPointMake(0, height - bottemLeft)]; //左边直线 - [maskPath addQuadCurveToPoint:CGPointMake(bottemLeft, height) controlPoint:CGPointMake(0, height)]; //左下角圆弧 + [maskPath addQuadCurveToPoint:CGPointMake(0, leftTop) controlPoint:CGPointMake(0, 0)]; + [maskPath addLineToPoint:CGPointMake(0, height - bottemLeft)]; + [maskPath addQuadCurveToPoint:CGPointMake(bottemLeft, height) controlPoint:CGPointMake(0, height)]; CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = CGRectMake(0, 0, size.width, size.height); @@ -40,43 +38,17 @@ self.layer.mask = maskLayer; } -//- (void)setCornerRadius:(CGFloat)radius -// corners:(UIRectCorner)corners -// borderWidth:(CGFloat)borderWidth -// borderColor:(UIColor *)borderColor { -// -// // 创建 UIBezierPath 并应用圆角 -// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds -// byRoundingCorners:corners -// cornerRadii:CGSizeMake(radius, radius)]; -// -// // 创建 CAShapeLayer 并设置 path -// CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; -// maskLayer.path = path.CGPath; -// self.layer.mask = maskLayer; -// -// // 设置边框 -// if (borderWidth > 0 && borderColor) { -// CAShapeLayer *borderLayer = [[CAShapeLayer alloc] init]; -// borderLayer.path = path.CGPath; -// borderLayer.lineWidth = borderWidth; -// borderLayer.strokeColor = borderColor.CGColor; -// borderLayer.fillColor = UIColor.clearColor.CGColor; -// borderLayer.frame = self.bounds; -// [self.layer addSublayer:borderLayer]; -// } -//} - (void)setCornerRadius:(CGFloat)radius { self.layer.cornerRadius = radius; - self.layer.masksToBounds = YES; // 确保视图内容不会超出边界 + self.layer.masksToBounds = YES; } - (void)setCornerRadius:(CGFloat)radius corners:(UIRectCorner)corners { if (corners == UIRectCornerAllCorners) { [self setCornerRadius:radius]; } else { - // 如果是部分圆角,使用 `CAShapeLayer` 和 `UIBezierPath`,但仅在必要时使用 + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)]; @@ -98,12 +70,12 @@ borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor { - // 设置指定角的圆角 + self.layer.cornerRadius = radius; self.layer.maskedCorners = corners; - self.layer.masksToBounds = YES; // 确保内容不会超出边界 + self.layer.masksToBounds = YES; - // 设置边框 + self.layer.borderWidth = borderWidth; self.layer.borderColor = borderColor.CGColor; } @@ -111,12 +83,12 @@ - (void)setAllCornerRadius:(CGFloat)radius borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor { - // 设置指定角的圆角 + self.layer.cornerRadius = radius; self.layer.maskedCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight; - self.layer.masksToBounds = YES; // 确保内容不会超出边界 + self.layer.masksToBounds = YES; - // 设置边框 + self.layer.borderWidth = borderWidth; self.layer.borderColor = borderColor.CGColor; } diff --git a/YuMi/CustomUI/UIViewCorner/UIView+Corner.m.backup b/YuMi/CustomUI/UIViewCorner/UIView+Corner.m.backup new file mode 100644 index 0000000..b274a0f --- /dev/null +++ b/YuMi/CustomUI/UIViewCorner/UIView+Corner.m.backup @@ -0,0 +1,125 @@ +// +// UIView+Corner.m +// YUMI +// +// Created by YUMI on 2022/6/15. +// + +#import "UIView+Corner.h" + +@implementation UIView (Corner) + +- (void)setCornerWithLeftTopCorner:(CGFloat)leftTop + rightTopCorner:(CGFloat)rigtTop + bottomLeftCorner:(CGFloat)bottemLeft + bottomRightCorner:(CGFloat)bottemRight + size:(CGSize)size { + + CGFloat width = size.width; + CGFloat height = size.height; + UIBezierPath *maskPath = [UIBezierPath bezierPath]; + maskPath.lineWidth = 1.0; + maskPath.lineCapStyle = kCGLineCapRound; + maskPath.lineJoinStyle = kCGLineJoinRound; + [maskPath moveToPoint:CGPointMake(bottemRight, height)]; //左下角 + [maskPath addLineToPoint:CGPointMake(width - bottemRight, height)]; + + [maskPath addQuadCurveToPoint:CGPointMake(width, height- bottemRight) controlPoint:CGPointMake(width, height)]; //右下角的圆弧 + [maskPath addLineToPoint:CGPointMake(width, rigtTop)]; //右边直线 + + [maskPath addQuadCurveToPoint:CGPointMake(width - rigtTop, 0) controlPoint:CGPointMake(width, 0)]; //右上角圆弧 + [maskPath addLineToPoint:CGPointMake(leftTop, 0)]; //顶部直线 + + [maskPath addQuadCurveToPoint:CGPointMake(0, leftTop) controlPoint:CGPointMake(0, 0)]; //左上角圆弧 + [maskPath addLineToPoint:CGPointMake(0, height - bottemLeft)]; //左边直线 + [maskPath addQuadCurveToPoint:CGPointMake(bottemLeft, height) controlPoint:CGPointMake(0, height)]; //左下角圆弧 + + CAShapeLayer *maskLayer = [CAShapeLayer layer]; + maskLayer.frame = CGRectMake(0, 0, size.width, size.height); + maskLayer.path = maskPath.CGPath; + self.layer.mask = maskLayer; +} + +//- (void)setCornerRadius:(CGFloat)radius +// corners:(UIRectCorner)corners +// borderWidth:(CGFloat)borderWidth +// borderColor:(UIColor *)borderColor { +// +// // 创建 UIBezierPath 并应用圆角 +// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds +// byRoundingCorners:corners +// cornerRadii:CGSizeMake(radius, radius)]; +// +// // 创建 CAShapeLayer 并设置 path +// CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; +// maskLayer.path = path.CGPath; +// self.layer.mask = maskLayer; +// +// // 设置边框 +// if (borderWidth > 0 && borderColor) { +// CAShapeLayer *borderLayer = [[CAShapeLayer alloc] init]; +// borderLayer.path = path.CGPath; +// borderLayer.lineWidth = borderWidth; +// borderLayer.strokeColor = borderColor.CGColor; +// borderLayer.fillColor = UIColor.clearColor.CGColor; +// borderLayer.frame = self.bounds; +// [self.layer addSublayer:borderLayer]; +// } +//} + +- (void)setCornerRadius:(CGFloat)radius { + self.layer.cornerRadius = radius; + self.layer.masksToBounds = YES; // 确保视图内容不会超出边界 +} + +- (void)setCornerRadius:(CGFloat)radius corners:(UIRectCorner)corners { + if (corners == UIRectCornerAllCorners) { + [self setCornerRadius:radius]; + } else { + // 如果是部分圆角,使用 `CAShapeLayer` 和 `UIBezierPath`,但仅在必要时使用 + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds + byRoundingCorners:corners + cornerRadii:CGSizeMake(radius, radius)]; + CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; + maskLayer.path = path.CGPath; + self.layer.mask = maskLayer; + } +} + +- (void)setCornerRadius:(CGFloat)radius cornerMask:(CACornerMask)cornerMask { + self.layer.maskedCorners = cornerMask; + self.layer.cornerRadius = radius; + self.layer.masksToBounds = YES; +} + + +- (void)setCornerRadius:(CGFloat)radius + corners:(CACornerMask)corners + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor { + + // 设置指定角的圆角 + self.layer.cornerRadius = radius; + self.layer.maskedCorners = corners; + self.layer.masksToBounds = YES; // 确保内容不会超出边界 + + // 设置边框 + self.layer.borderWidth = borderWidth; + self.layer.borderColor = borderColor.CGColor; +} + +- (void)setAllCornerRadius:(CGFloat)radius + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor { + // 设置指定角的圆角 + self.layer.cornerRadius = radius; + self.layer.maskedCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight; + self.layer.masksToBounds = YES; // 确保内容不会超出边界 + + // 设置边框 + self.layer.borderWidth = borderWidth; + self.layer.borderColor = borderColor.CGColor; +} + +@end + diff --git a/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h index 26d1df4..0877cb9 100644 --- a/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h +++ b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h @@ -1,9 +1,7 @@ -// -// UIView+GradientLayer.h -// YuMi -// + + // Created by P on 2024/11/18. -// + #import @@ -11,23 +9,16 @@ NS_ASSUME_NONNULL_BEGIN @interface UIView (GradientLayer) -/// 为视图添加渐变背景 -/// @param colors 渐变颜色数组 (NSArray *) -/// @param startPoint 渐变起点 (CGPoint) -/// @param endPoint 渐变终点 (CGPoint) -/// @param cornerRadius 圆角半径 (CGFloat) + - (void)addGradientBackgroundWithColors:(NSArray *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint cornerRadius:(CGFloat)cornerRadius; -/// 移除渐变背景 + - (void)removeGradientBackground; -/// 更新渐变背景 -/// @param colors 渐变颜色数组 (NSArray *) -/// @param startPoint 渐变起点 (CGPoint) -/// @param endPoint 渐变终点 (CGPoint) + - (void)updateGradientBackgroundWithColors:(NSArray *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint; diff --git a/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h.backup b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h.backup new file mode 100644 index 0000000..26d1df4 --- /dev/null +++ b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.h.backup @@ -0,0 +1,37 @@ +// +// UIView+GradientLayer.h +// YuMi +// +// Created by P on 2024/11/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (GradientLayer) + +/// 为视图添加渐变背景 +/// @param colors 渐变颜色数组 (NSArray *) +/// @param startPoint 渐变起点 (CGPoint) +/// @param endPoint 渐变终点 (CGPoint) +/// @param cornerRadius 圆角半径 (CGFloat) +- (void)addGradientBackgroundWithColors:(NSArray *)colors + startPoint:(CGPoint)startPoint + endPoint:(CGPoint)endPoint + cornerRadius:(CGFloat)cornerRadius; + +/// 移除渐变背景 +- (void)removeGradientBackground; + +/// 更新渐变背景 +/// @param colors 渐变颜色数组 (NSArray *) +/// @param startPoint 渐变起点 (CGPoint) +/// @param endPoint 渐变终点 (CGPoint) +- (void)updateGradientBackgroundWithColors:(NSArray *)colors + startPoint:(CGPoint)startPoint + endPoint:(CGPoint)endPoint; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m index f71feb9..bd97979 100644 --- a/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m +++ b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m @@ -1,9 +1,7 @@ -// -// UIView+GradientLayer.m -// YuMi -// + + // Created by P on 2024/11/18. -// + #import "UIView+GradientLayer.h" #import @@ -13,15 +11,15 @@ static NSString * const kGradientLayerName = @"GradientLayer"; static void *kGradientObserverKey = &kGradientObserverKey; -// 添加渐变背景 + - (void)addGradientBackgroundWithColors:(NSArray *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint cornerRadius:(CGFloat)cornerRadius { - // 确保移除已有的渐变背景和 KVO 监听 + [self removeGradientBackground]; - // 创建渐变图层 + CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.name = kGradientLayerName; gradientLayer.colors = [self cgColorsFromUIColors:colors]; @@ -29,16 +27,16 @@ static void *kGradientObserverKey = &kGradientObserverKey; gradientLayer.endPoint = endPoint; gradientLayer.cornerRadius = cornerRadius; - // 初次设置 frame + gradientLayer.frame = self.bounds; [self.layer insertSublayer:gradientLayer atIndex:0]; - // 添加 KVO 监听 + [self setupLayoutObserverForGradientLayer:gradientLayer]; } -// 动态更新渐变背景 + - (void)updateGradientBackgroundWithColors:(NSArray *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint { @@ -50,22 +48,22 @@ static void *kGradientObserverKey = &kGradientObserverKey; } } -// 移除渐变背景和监听 + - (void)removeGradientBackground { - // 移除渐变图层 + CAGradientLayer *gradientLayer = [self gradientLayer]; if (gradientLayer) { [gradientLayer removeFromSuperlayer]; } - // 移除 KVO 监听 + if ([self hasAddedObserver]) { [self removeObserver:self forKeyPath:@"bounds"]; [self setHasAddedObserver:NO]; } } -// 获取渐变图层 + - (CAGradientLayer *)gradientLayer { for (CALayer *layer in self.layer.sublayers) { if ([layer.name isEqualToString:kGradientLayerName] && @@ -76,7 +74,7 @@ static void *kGradientObserverKey = &kGradientObserverKey; return nil; } -// 添加 KVO 监听 + - (void)setupLayoutObserverForGradientLayer:(CAGradientLayer *)gradientLayer { if (![self hasAddedObserver]) { [self addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:(__bridge void *)gradientLayer]; @@ -84,20 +82,20 @@ static void *kGradientObserverKey = &kGradientObserverKey; } } -// KVO 监听回调 + - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"bounds"]) { CAGradientLayer *gradientLayer = (__bridge CAGradientLayer *)context; - gradientLayer.frame = self.bounds; // 更新渐变图层的 frame + gradientLayer.frame = self.bounds; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } -// 工具方法:转换颜色数组 + - (NSArray *)cgColorsFromUIColors:(NSArray *)colors { NSMutableArray *cgColors = [NSMutableArray array]; for (UIColor *color in colors) { @@ -106,12 +104,12 @@ static void *kGradientObserverKey = &kGradientObserverKey; return [cgColors copy]; } -// 工具方法:判断是否已注册 KVO + - (BOOL)hasAddedObserver { return [objc_getAssociatedObject(self, kGradientObserverKey) boolValue]; } -// 工具方法:设置是否已注册 KVO + - (void)setHasAddedObserver:(BOOL)added { objc_setAssociatedObject(self, kGradientObserverKey, @(added), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } diff --git a/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m.backup b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m.backup new file mode 100644 index 0000000..f71feb9 --- /dev/null +++ b/YuMi/CustomUI/UIViewGradientLayer/UIView+GradientLayer.m.backup @@ -0,0 +1,120 @@ +// +// UIView+GradientLayer.m +// YuMi +// +// Created by P on 2024/11/18. +// + +#import "UIView+GradientLayer.h" +#import + +@implementation UIView (GradientLayer) + +static NSString * const kGradientLayerName = @"GradientLayer"; +static void *kGradientObserverKey = &kGradientObserverKey; + +// 添加渐变背景 +- (void)addGradientBackgroundWithColors:(NSArray *)colors + startPoint:(CGPoint)startPoint + endPoint:(CGPoint)endPoint + cornerRadius:(CGFloat)cornerRadius { + // 确保移除已有的渐变背景和 KVO 监听 + [self removeGradientBackground]; + + // 创建渐变图层 + CAGradientLayer *gradientLayer = [CAGradientLayer layer]; + gradientLayer.name = kGradientLayerName; + gradientLayer.colors = [self cgColorsFromUIColors:colors]; + gradientLayer.startPoint = startPoint; + gradientLayer.endPoint = endPoint; + gradientLayer.cornerRadius = cornerRadius; + + // 初次设置 frame + gradientLayer.frame = self.bounds; + + [self.layer insertSublayer:gradientLayer atIndex:0]; + + // 添加 KVO 监听 + [self setupLayoutObserverForGradientLayer:gradientLayer]; +} + +// 动态更新渐变背景 +- (void)updateGradientBackgroundWithColors:(NSArray *)colors + startPoint:(CGPoint)startPoint + endPoint:(CGPoint)endPoint { + CAGradientLayer *gradientLayer = [self gradientLayer]; + if (gradientLayer) { + gradientLayer.colors = [self cgColorsFromUIColors:colors]; + gradientLayer.startPoint = startPoint; + gradientLayer.endPoint = endPoint; + } +} + +// 移除渐变背景和监听 +- (void)removeGradientBackground { + // 移除渐变图层 + CAGradientLayer *gradientLayer = [self gradientLayer]; + if (gradientLayer) { + [gradientLayer removeFromSuperlayer]; + } + + // 移除 KVO 监听 + if ([self hasAddedObserver]) { + [self removeObserver:self forKeyPath:@"bounds"]; + [self setHasAddedObserver:NO]; + } +} + +// 获取渐变图层 +- (CAGradientLayer *)gradientLayer { + for (CALayer *layer in self.layer.sublayers) { + if ([layer.name isEqualToString:kGradientLayerName] && + [layer isKindOfClass:[CAGradientLayer class]]) { + return (CAGradientLayer *)layer; + } + } + return nil; +} + +// 添加 KVO 监听 +- (void)setupLayoutObserverForGradientLayer:(CAGradientLayer *)gradientLayer { + if (![self hasAddedObserver]) { + [self addObserver:self forKeyPath:@"bounds" options:NSKeyValueObservingOptionNew context:(__bridge void *)gradientLayer]; + [self setHasAddedObserver:YES]; + } +} + +// KVO 监听回调 +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqualToString:@"bounds"]) { + CAGradientLayer *gradientLayer = (__bridge CAGradientLayer *)context; + gradientLayer.frame = self.bounds; // 更新渐变图层的 frame + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +// 工具方法:转换颜色数组 +- (NSArray *)cgColorsFromUIColors:(NSArray *)colors { + NSMutableArray *cgColors = [NSMutableArray array]; + for (UIColor *color in colors) { + [cgColors addObject:(id)color.CGColor]; + } + return [cgColors copy]; +} + +// 工具方法:判断是否已注册 KVO +- (BOOL)hasAddedObserver { + return [objc_getAssociatedObject(self, kGradientObserverKey) boolValue]; +} + +// 工具方法:设置是否已注册 KVO +- (void)setHasAddedObserver:(BOOL)added { + objc_setAssociatedObject(self, kGradientObserverKey, @(added), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + + +@end diff --git a/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h index 3033e40..680abe9 100755 --- a/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h +++ b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h @@ -103,6 +103,6 @@ - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; -///为图片增加毛玻璃,value模糊程度 + +(UIImage *)setBlurImage:(UIImage *)image value:(CGFloat)value; @end diff --git a/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h.backup b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h.backup new file mode 100755 index 0000000..3033e40 --- /dev/null +++ b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.h.backup @@ -0,0 +1,108 @@ +/* + File: UIImage+ImageEffects.h + Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur. + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2013 Apple Inc. All Rights Reserved. + + + Copyright © 2013 Apple Inc. All rights reserved. + WWDC 2013 License + + NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013 + Session. Please refer to the applicable WWDC 2013 Session for further + information. + + IMPORTANT: This Apple software is supplied to you by Apple Inc. + ("Apple") in consideration of your agreement to the following terms, and + your use, installation, modification or redistribution of this Apple + software constitutes acceptance of these terms. If you do not agree with + these terms, please do not use, install, modify or redistribute this + Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a non-exclusive license, under + Apple's copyrights in this original Apple software (the "Apple + Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES + NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE + IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + EA1002 + 5/3/2013 + */ + +#import + +@interface UIImage (ImageEffects) + +- (UIImage *)applyLightEffect; +- (UIImage *)applyExtraLightEffect; +- (UIImage *)applyDarkEffect; +- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; + +- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; +///为图片增加毛玻璃,value模糊程度 ++(UIImage *)setBlurImage:(UIImage *)image value:(CGFloat)value; +@end diff --git a/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m index 606bffd..b066a12 100755 --- a/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m +++ b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m @@ -146,17 +146,17 @@ - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage { - // Check pre-conditions. + if (self.size.width < 1 || self.size.height < 1) { -// NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self); + return nil; } if (!self.CGImage) { -// NSLog (@"*** error: image must be backed by a CGImage: %@", self); + return nil; } if (maskImage && !maskImage.CGImage) { -// NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage); + return nil; } @@ -187,22 +187,12 @@ effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext); if (hasBlur) { - // A description of how to compute the box kernel width from the Gaussian - // radius (aka standard deviation) appears in the SVG spec: - // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement - // - // For larger values of 's' (s >= 2.0), an approximation can be used: Three - // successive box-blurs build a piece-wise quadratic convolution kernel, which - // approximates the Gaussian kernel to within roughly 3%. - // - // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) - // - // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. - // + + CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale]; NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5); if (radius % 2 != 1) { - radius += 1; // force radius to be odd so that the three box-blur methodology works. + radius += 1; } vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); @@ -240,16 +230,16 @@ UIGraphicsEndImageContext(); } - // Set up output context. + UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); CGContextRef outputContext = UIGraphicsGetCurrentContext(); CGContextScaleCTM(outputContext, 1.0, -1.0); CGContextTranslateCTM(outputContext, 0, -self.size.height); - // Draw base image. + CGContextDrawImage(outputContext, imageRect, self.CGImage); - // Draw effect image. + if (hasBlur) { CGContextSaveGState(outputContext); if (maskImage) { @@ -259,7 +249,7 @@ CGContextRestoreGState(outputContext); } - // Add in color tint. + if (tintColor) { CGContextSaveGState(outputContext); CGContextSetFillColorWithColor(outputContext, tintColor.CGColor); @@ -267,7 +257,7 @@ CGContextRestoreGState(outputContext); } - // Output image is ready. + UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); @@ -277,28 +267,25 @@ CIContext *context = [CIContext contextWithOptions:nil]; - CIImage * sourceImage = [CIImage imageWithCGImage:image.CGImage];//将图片转换成CIImage + CIImage * sourceImage = [CIImage imageWithCGImage:image.CGImage]; - ///图片仿射滤镜 + + CIFilter * clamp = [CIFilter filterWithName:@"CIAffineClamp"]; - CIFilter * clamp = [CIFilter filterWithName:@"CIAffineClamp"];//设置绘制类型 - - [clamp setValue:sourceImage forKey:kCIInputImageKey];//设置要绘制的图片 + [clamp setValue:sourceImage forKey:kCIInputImageKey]; CIImage *clampResult = [clamp valueForKey:kCIOutputImageKey]; - ///高斯模糊滤镜 - + CIFilter* gaussianBlur = [CIFilter filterWithName:@"CIGaussianBlur"]; [gaussianBlur setValue:clampResult forKey:kCIInputImageKey]; - [gaussianBlur setValue:[NSNumber numberWithFloat:value] forKey:@"inputRadius"];//设置模糊值 + [gaussianBlur setValue:[NSNumber numberWithFloat:value] forKey:@"inputRadius"]; CIImage * gaussianBlurResult = [gaussianBlur valueForKey:kCIOutputImageKey]; - ///转化获取图片 - + CGImageRef cgImage = [context createCGImage:gaussianBlurResult fromRect:[sourceImage extent]]; UIImage * resultImage = [UIImage imageWithCGImage:cgImage]; diff --git a/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m.backup b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m.backup new file mode 100755 index 0000000..606bffd --- /dev/null +++ b/YuMi/CustomUI/VagueImageView/UIImage+ImageEffects.m.backup @@ -0,0 +1,309 @@ +/* + File: UIImage+ImageEffects.m + Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur. + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2013 Apple Inc. All Rights Reserved. + + + Copyright © 2013 Apple Inc. All rights reserved. + WWDC 2013 License + + NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013 + Session. Please refer to the applicable WWDC 2013 Session for further + information. + + IMPORTANT: This Apple software is supplied to you by Apple Inc. + ("Apple") in consideration of your agreement to the following terms, and + your use, installation, modification or redistribution of this Apple + software constitutes acceptance of these terms. If you do not agree with + these terms, please do not use, install, modify or redistribute this + Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a non-exclusive license, under + Apple's copyrights in this original Apple software (the "Apple + Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES + NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE + IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + EA1002 + 5/3/2013 + */ + +#import "UIImage+ImageEffects.h" + +#import +#import + + +@implementation UIImage (ImageEffects) + + +- (UIImage *)applyLightEffect +{ + UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3]; + return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; +} + + +- (UIImage *)applyExtraLightEffect +{ + UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82]; + return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; +} + + +- (UIImage *)applyDarkEffect +{ + UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73]; + return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; +} + + +- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor +{ + const CGFloat EffectColorAlpha = 0.6; + UIColor *effectColor = tintColor; + int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor); + if (componentCount == 2) { + CGFloat b; + if ([tintColor getWhite:&b alpha:NULL]) { + effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha]; + } + } + else { + CGFloat r, g, b; + if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) { + effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha]; + } + } + return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil]; +} + + +- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage +{ + // Check pre-conditions. + if (self.size.width < 1 || self.size.height < 1) { +// NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self); + return nil; + } + if (!self.CGImage) { +// NSLog (@"*** error: image must be backed by a CGImage: %@", self); + return nil; + } + if (maskImage && !maskImage.CGImage) { +// NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage); + return nil; + } + + CGRect imageRect = { CGPointZero, self.size }; + UIImage *effectImage = self; + + BOOL hasBlur = blurRadius > __FLT_EPSILON__; + BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__; + if (hasBlur || hasSaturationChange) { + UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef effectInContext = UIGraphicsGetCurrentContext(); + CGContextScaleCTM(effectInContext, 1.0, -1.0); + CGContextTranslateCTM(effectInContext, 0, -self.size.height); + CGContextDrawImage(effectInContext, imageRect, self.CGImage); + + vImage_Buffer effectInBuffer; + effectInBuffer.data = CGBitmapContextGetData(effectInContext); + effectInBuffer.width = CGBitmapContextGetWidth(effectInContext); + effectInBuffer.height = CGBitmapContextGetHeight(effectInContext); + effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext); + + UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef effectOutContext = UIGraphicsGetCurrentContext(); + vImage_Buffer effectOutBuffer; + effectOutBuffer.data = CGBitmapContextGetData(effectOutContext); + effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext); + effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext); + effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext); + + if (hasBlur) { + // A description of how to compute the box kernel width from the Gaussian + // radius (aka standard deviation) appears in the SVG spec: + // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement + // + // For larger values of 's' (s >= 2.0), an approximation can be used: Three + // successive box-blurs build a piece-wise quadratic convolution kernel, which + // approximates the Gaussian kernel to within roughly 3%. + // + // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) + // + // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. + // + CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale]; + NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5); + if (radius % 2 != 1) { + radius += 1; // force radius to be odd so that the three box-blur methodology works. + } + vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); + vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); + vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); + } + BOOL effectImageBuffersAreSwapped = NO; + if (hasSaturationChange) { + CGFloat s = saturationDeltaFactor; + CGFloat floatingPointSaturationMatrix[] = { + 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0, + 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0, + 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0, + 0, 0, 0, 1, + }; + const int32_t divisor = 256; + NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]); + int16_t saturationMatrix[matrixSize]; + for (NSUInteger i = 0; i < matrixSize; ++i) { + saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor); + } + if (hasBlur) { + vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); + effectImageBuffersAreSwapped = YES; + } + else { + vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); + } + } + if (!effectImageBuffersAreSwapped) + effectImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + if (effectImageBuffersAreSwapped) + effectImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + } + + // Set up output context. + UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef outputContext = UIGraphicsGetCurrentContext(); + CGContextScaleCTM(outputContext, 1.0, -1.0); + CGContextTranslateCTM(outputContext, 0, -self.size.height); + + // Draw base image. + CGContextDrawImage(outputContext, imageRect, self.CGImage); + + // Draw effect image. + if (hasBlur) { + CGContextSaveGState(outputContext); + if (maskImage) { + CGContextClipToMask(outputContext, imageRect, maskImage.CGImage); + } + CGContextDrawImage(outputContext, imageRect, effectImage.CGImage); + CGContextRestoreGState(outputContext); + } + + // Add in color tint. + if (tintColor) { + CGContextSaveGState(outputContext); + CGContextSetFillColorWithColor(outputContext, tintColor.CGColor); + CGContextFillRect(outputContext, imageRect); + CGContextRestoreGState(outputContext); + } + + // Output image is ready. + UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return outputImage; +} ++(UIImage *)setBlurImage:(UIImage *)image value:(CGFloat)value{ + + + CIContext *context = [CIContext contextWithOptions:nil]; + CIImage * sourceImage = [CIImage imageWithCGImage:image.CGImage];//将图片转换成CIImage + + ///图片仿射滤镜 + + CIFilter * clamp = [CIFilter filterWithName:@"CIAffineClamp"];//设置绘制类型 + + [clamp setValue:sourceImage forKey:kCIInputImageKey];//设置要绘制的图片 + + CIImage *clampResult = [clamp valueForKey:kCIOutputImageKey]; + + ///高斯模糊滤镜 + + CIFilter* gaussianBlur = [CIFilter filterWithName:@"CIGaussianBlur"]; + + [gaussianBlur setValue:clampResult forKey:kCIInputImageKey]; + + [gaussianBlur setValue:[NSNumber numberWithFloat:value] forKey:@"inputRadius"];//设置模糊值 + + CIImage * gaussianBlurResult = [gaussianBlur valueForKey:kCIOutputImageKey]; + + ///转化获取图片 + + CGImageRef cgImage = [context createCGImage:gaussianBlurResult fromRect:[sourceImage extent]]; + + UIImage * resultImage = [UIImage imageWithCGImage:cgImage]; + return resultImage; + +} + +@end diff --git a/YuMi/CustomUI/XCCurrentVCStackManager.h b/YuMi/CustomUI/XCCurrentVCStackManager.h index aaa03a8..a24e9bb 100644 --- a/YuMi/CustomUI/XCCurrentVCStackManager.h +++ b/YuMi/CustomUI/XCCurrentVCStackManager.h @@ -1,31 +1,21 @@ -// -// YMCurrentVCStackManager.h -// YMBaseUIKit -// -// Created by 卫明何 on 2018/8/9. -// Copyright © 2018年 YUIMI. All rights reserved. -// - -#import -#import - -@interface XCCurrentVCStackManager : NSObject - -+ (instancetype)shareManager; - -/** - 当前的导航控制器 - - @return 导航控制器 - */ -- (UINavigationController *)currentNavigationController; - -/** - 当前最顶层控制器 - - @return 当前最顶层控制器 - */ -- (UIViewController *)getCurrentVC; - - -@end + + +// Created by 卫明何 on 2018/8/9. +// Copyright © 2018年 YUIMI. All rights reserved. + + +#import +#import + +@interface XCCurrentVCStackManager : NSObject + ++ (instancetype)shareManager; + + +- (UINavigationController *)currentNavigationController; + + +- (UIViewController *)getCurrentVC; + + +@end diff --git a/YuMi/CustomUI/XCCurrentVCStackManager.h.backup b/YuMi/CustomUI/XCCurrentVCStackManager.h.backup new file mode 100644 index 0000000..aaa03a8 --- /dev/null +++ b/YuMi/CustomUI/XCCurrentVCStackManager.h.backup @@ -0,0 +1,31 @@ +// +// YMCurrentVCStackManager.h +// YMBaseUIKit +// +// Created by 卫明何 on 2018/8/9. +// Copyright © 2018年 YUIMI. All rights reserved. +// + +#import +#import + +@interface XCCurrentVCStackManager : NSObject + ++ (instancetype)shareManager; + +/** + 当前的导航控制器 + + @return 导航控制器 + */ +- (UINavigationController *)currentNavigationController; + +/** + 当前最顶层控制器 + + @return 当前最顶层控制器 + */ +- (UIViewController *)getCurrentVC; + + +@end diff --git a/YuMi/CustomUI/XCCurrentVCStackManager.m b/YuMi/CustomUI/XCCurrentVCStackManager.m index 41a4372..e7b225c 100644 --- a/YuMi/CustomUI/XCCurrentVCStackManager.m +++ b/YuMi/CustomUI/XCCurrentVCStackManager.m @@ -1,10 +1,8 @@ -// -// YMCurrentVCStackManager.m -// YMBaseUIKit -// + + // Created by 卫明何 on 2018/8/9. // Copyright © 2018年 YUIMI. All rights reserved. -// + #import "XCCurrentVCStackManager.h" @@ -22,7 +20,7 @@ NSString * const kRoomChatPushViewKey = @"kRoomChatPushViewKey"; } - (UIViewController *)getCurrentVC { - ///兼容房间内私聊的 + [[NSNotificationCenter defaultCenter] postNotificationName:kRoomChatPushViewKey object:nil]; UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; @@ -33,19 +31,19 @@ NSString * const kRoomChatPushViewKey = @"kRoomChatPushViewKey"; - (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC { UIViewController *currentVC; if ([rootVC presentedViewController]) { - // 视图是被presented出来的 + rootVC = [rootVC presentedViewController]; } if ([rootVC isKindOfClass:[UITabBarController class]]) { - // 根视图为UITabBarController + currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]]; } else if ([rootVC isKindOfClass:[UINavigationController class]]) { - // 根视图为UINavigationController + currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]]; } else { - // 根视图为非导航类 + currentVC = rootVC; } return currentVC; @@ -80,7 +78,6 @@ NSString * const kRoomChatPushViewKey = @"kRoomChatPushViewKey"; } -//递归 - (UINavigationController *)getCurrentNCFrom:(UIViewController *)vc{ if ([vc isKindOfClass:NSClassFromString(@"MMDrawerController")]) { vc = (UIViewController *)[vc valueForKey:@"centerViewController"]; diff --git a/YuMi/CustomUI/XCCurrentVCStackManager.m.backup b/YuMi/CustomUI/XCCurrentVCStackManager.m.backup new file mode 100644 index 0000000..41a4372 --- /dev/null +++ b/YuMi/CustomUI/XCCurrentVCStackManager.m.backup @@ -0,0 +1,123 @@ +// +// YMCurrentVCStackManager.m +// YMBaseUIKit +// +// Created by 卫明何 on 2018/8/9. +// Copyright © 2018年 YUIMI. All rights reserved. +// + +#import "XCCurrentVCStackManager.h" + +NSString * const kRoomChatPushViewKey = @"kRoomChatPushViewKey"; +@implementation XCCurrentVCStackManager + ++ (instancetype)shareManager { + static dispatch_once_t onceToken = 0; + static id instance; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + + return instance; +} + +- (UIViewController *)getCurrentVC { + ///兼容房间内私聊的 + [[NSNotificationCenter defaultCenter] postNotificationName:kRoomChatPushViewKey object:nil]; + + UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; + UIViewController *currentVC = [self getCurrentVCFrom:rootViewController]; + return currentVC; +} + +- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC { + UIViewController *currentVC; + if ([rootVC presentedViewController]) { + // 视图是被presented出来的 + rootVC = [rootVC presentedViewController]; + } + if ([rootVC isKindOfClass:[UITabBarController class]]) { + // 根视图为UITabBarController + currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]]; + + } else if ([rootVC isKindOfClass:[UINavigationController class]]) { + // 根视图为UINavigationController + currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]]; + + } else { + // 根视图为非导航类 + currentVC = rootVC; + } + return currentVC; +} + +- (UIViewController *)currentViewController { + UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; + UIViewController *vc = keyWindow.rootViewController; + while (vc.presentedViewController) { + vc = vc.presentedViewController; + if ([vc isKindOfClass:[UINavigationController class]]) { + vc = [(UINavigationController *)vc visibleViewController]; + } + else if ([vc isKindOfClass:[UITabBarController class]]) { + vc = [(UITabBarController *)vc selectedViewController]; + } + } + return vc; +} + +- (UINavigationController *)currentNavigationController { + return [self currentNC]; +} + +- (UINavigationController *)currentNC{ + if (![[UIApplication sharedApplication].windows.lastObject isKindOfClass:[UIWindow class]]) { + NSAssert(0, @"未获取到导航控制器"); + return nil; + } + UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; + return [self getCurrentNCFrom:rootViewController]; +} + + +//递归 +- (UINavigationController *)getCurrentNCFrom:(UIViewController *)vc{ + if ([vc isKindOfClass:NSClassFromString(@"MMDrawerController")]) { + vc = (UIViewController *)[vc valueForKey:@"centerViewController"]; + } + if ([vc isKindOfClass:[UITabBarController class]]) { + UINavigationController *nc = ((UITabBarController *)vc).selectedViewController; + return [self getCurrentNCFrom:nc]; + } + else if ([vc isKindOfClass:[UINavigationController class]]) { + if (((UINavigationController *)vc).presentedViewController) { + return [self getCurrentNCFrom:((UINavigationController *)vc).presentedViewController]; + } + return [self getCurrentNCFrom:((UINavigationController *)vc).topViewController]; + } + else if ([vc isKindOfClass:[UIViewController class]]) { + if (vc.presentedViewController) { + return [self getCurrentNCFrom:vc.presentedViewController]; + } + else { + if (!vc.navigationController) { + if (vc.presentingViewController) { + [vc dismissViewControllerAnimated:NO completion:nil]; + + return [self getCurrentNCFrom:vc.presentingViewController]; + } else { + NSAssert(0, @"未获取到导航控制器"); + return nil; + } + } else { + return vc.navigationController; + } + } + } + else { + NSAssert(0, @"未获取到导航控制器"); + return nil; + } +} + +@end diff --git a/YuMi/CustomUI/XNDJTDDLoadingTool.h b/YuMi/CustomUI/XNDJTDDLoadingTool.h index 039a7c9..85db68b 100644 --- a/YuMi/CustomUI/XNDJTDDLoadingTool.h +++ b/YuMi/CustomUI/XNDJTDDLoadingTool.h @@ -1,148 +1,76 @@ -// -// YMHUDTool.h -// TTPlay -// -// Created by YM on 2022/5/15. -// Copyright © 2023 YUMI. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - showGIFLoading使用注意: - 1.谁负责showLoading, 谁负责hideHUD - 2.showLoading是指定了加载在那个View, hideHUD时请指定hide那个view的hud - */ - -@interface XNDJTDDLoadingTool : NSObject -/** - 隐藏HUD - */ -+ (void)hideHUD; - -/** - 隐藏HUD, 如果view为nil, 则默认隐藏主窗口的HUD - - @param view view - */ -+ (void)hideHUDInView:(nullable UIView *)view; - - -+(void)hideOnlyView:(UIView *)view; -+(void)showOnlyView:(UIView *)view; - - - -/** - 显示成功message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - */ -+ (void)showSuccessWithMessage:(NSString *)message; - -/** - 显示成功message, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - @param view 显示在哪个view上 - */ -+ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view; - -/** - 显示成功message - - @param message 文字 - @param view 显示在哪个view上 - @param afterDelay 延迟消失时间 - @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 - */ -+ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled; - -/** - 显示错误message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - */ -+ (void)showErrorWithMessage:(NSString *)message; - -/** - 显示错误message, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - @param view 显示在哪个view上 - */ -+ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view; - -/** - 显示错误message - - @param message 文字 - @param view 显示在哪个view上 - @param afterDelay 延迟消失时间 - @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 - */ -+ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled; - -/** - 在窗口上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 - */ -+ (void)showGIFLoading; - -/** - 在指定的view上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 - - @param view 显示在哪个view上 - */ -+ (void)showGIFLoadingInView:(nullable UIView *)view; - -/** - 在指定的view上显示自定义GIFLoading - - @param view 显示在哪个view上 - @param bgColor 背景颜色, 遮盖 - @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 - */ -+ (void)showGIFLoadingInView:(nullable UIView *)view bgColor:(nullable UIColor *)bgColor enabled:(BOOL)enabled; - -/** - 加载下一个个播房 - */ -+ (void)showAnchorLoading; - -+ (void)showAnchorLoading:(UIView *)view; - -/** - 在窗口上显示菊花 - */ -+ (void)showLoading; - -/** - 在view上显示菊花 - */ -+ (void)showLoadingInView:(nullable UIView *)view; - -/** - 在view上显示菊花 - */ -+ (void)showLoadingInView:(nullable UIView *)view enabled:(BOOL)enabled; - -/** - 在窗口上显示菊花+文字 - */ -+ (void)showLoadingWithMessage:(NSString *)message; - -/** - 在view上显示菊花+文字 - */ -+ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view; - -/** - 在view上显示菊花+文字 - */ -+ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view enabled:(BOOL)enabled; -+(void)showOnlyView:(UIView *)view enabled:(BOOL)enabled; -@end - -NS_ASSUME_NONNULL_END + + +// Created by YM on 2022/5/15. +// Copyright © 2023 YUMI. All rights reserved. + + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface XNDJTDDLoadingTool : NSObject + + ++ (void)hideHUD; + + ++ (void)hideHUDInView:(nullable UIView *)view; + + ++(void)hideOnlyView:(UIView *)view; ++(void)showOnlyView:(UIView *)view; + + ++ (void)showSuccessWithMessage:(NSString *)message; + + ++ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view; + + ++ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled; + + ++ (void)showErrorWithMessage:(NSString *)message; + + ++ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view; + + ++ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled; + + ++ (void)showGIFLoading; + + ++ (void)showGIFLoadingInView:(nullable UIView *)view; + + ++ (void)showGIFLoadingInView:(nullable UIView *)view bgColor:(nullable UIColor *)bgColor enabled:(BOOL)enabled; + + ++ (void)showAnchorLoading; + ++ (void)showAnchorLoading:(UIView *)view; + + ++ (void)showLoading; + + ++ (void)showLoadingInView:(nullable UIView *)view; + + ++ (void)showLoadingInView:(nullable UIView *)view enabled:(BOOL)enabled; + + ++ (void)showLoadingWithMessage:(NSString *)message; + + ++ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view; + + ++ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view enabled:(BOOL)enabled; ++(void)showOnlyView:(UIView *)view enabled:(BOOL)enabled; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/XNDJTDDLoadingTool.h.backup b/YuMi/CustomUI/XNDJTDDLoadingTool.h.backup new file mode 100644 index 0000000..039a7c9 --- /dev/null +++ b/YuMi/CustomUI/XNDJTDDLoadingTool.h.backup @@ -0,0 +1,148 @@ +// +// YMHUDTool.h +// TTPlay +// +// Created by YM on 2022/5/15. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + showGIFLoading使用注意: + 1.谁负责showLoading, 谁负责hideHUD + 2.showLoading是指定了加载在那个View, hideHUD时请指定hide那个view的hud + */ + +@interface XNDJTDDLoadingTool : NSObject +/** + 隐藏HUD + */ ++ (void)hideHUD; + +/** + 隐藏HUD, 如果view为nil, 则默认隐藏主窗口的HUD + + @param view view + */ ++ (void)hideHUDInView:(nullable UIView *)view; + + ++(void)hideOnlyView:(UIView *)view; ++(void)showOnlyView:(UIView *)view; + + + +/** + 显示成功message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + */ ++ (void)showSuccessWithMessage:(NSString *)message; + +/** + 显示成功message, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + @param view 显示在哪个view上 + */ ++ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view; + +/** + 显示成功message + + @param message 文字 + @param view 显示在哪个view上 + @param afterDelay 延迟消失时间 + @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 + */ ++ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled; + +/** + 显示错误message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + */ ++ (void)showErrorWithMessage:(NSString *)message; + +/** + 显示错误message, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + @param view 显示在哪个view上 + */ ++ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view; + +/** + 显示错误message + + @param message 文字 + @param view 显示在哪个view上 + @param afterDelay 延迟消失时间 + @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 + */ ++ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled; + +/** + 在窗口上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 + */ ++ (void)showGIFLoading; + +/** + 在指定的view上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 + + @param view 显示在哪个view上 + */ ++ (void)showGIFLoadingInView:(nullable UIView *)view; + +/** + 在指定的view上显示自定义GIFLoading + + @param view 显示在哪个view上 + @param bgColor 背景颜色, 遮盖 + @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 + */ ++ (void)showGIFLoadingInView:(nullable UIView *)view bgColor:(nullable UIColor *)bgColor enabled:(BOOL)enabled; + +/** + 加载下一个个播房 + */ ++ (void)showAnchorLoading; + ++ (void)showAnchorLoading:(UIView *)view; + +/** + 在窗口上显示菊花 + */ ++ (void)showLoading; + +/** + 在view上显示菊花 + */ ++ (void)showLoadingInView:(nullable UIView *)view; + +/** + 在view上显示菊花 + */ ++ (void)showLoadingInView:(nullable UIView *)view enabled:(BOOL)enabled; + +/** + 在窗口上显示菊花+文字 + */ ++ (void)showLoadingWithMessage:(NSString *)message; + +/** + 在view上显示菊花+文字 + */ ++ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view; + +/** + 在view上显示菊花+文字 + */ ++ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view enabled:(BOOL)enabled; ++(void)showOnlyView:(UIView *)view enabled:(BOOL)enabled; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/CustomUI/XNDJTDDLoadingTool.m b/YuMi/CustomUI/XNDJTDDLoadingTool.m index 8c361f6..d94e49e 100644 --- a/YuMi/CustomUI/XNDJTDDLoadingTool.m +++ b/YuMi/CustomUI/XNDJTDDLoadingTool.m @@ -1,10 +1,8 @@ -// -// YMHUDTool.m -// TTPlay -// + + // Created by YM on 2022/5/15. // Copyright © 2023 YUMI. All rights reserved. -// + #import "XNDJTDDLoadingTool.h" #import "GCDHelper.h" @@ -13,7 +11,7 @@ #define kDelayTime 2.5 @interface XNDJTDDLoadingTool () -/// + @property (class,nonatomic,copy) NSArray *animationImages; @end @@ -21,11 +19,7 @@ static NSArray * _animationImages = nil; -/** - 隐藏HUD, 如果view为nil, 则默认隐藏主窗口的HUD - - @param view view - */ + + (void)hideHUDInView:(nullable UIView *)view { dispatch_main_sync_safe(^{ if (view) { @@ -68,39 +62,22 @@ static NSArray * _animationImages = nil; return nil; } -/** - 隐藏HUD - */ + + (void)hideHUD { [self hideHUDInView:nil]; } -/** - 显示成功message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - */ + + (void)showSuccessWithMessage:(NSString *)message { [self showSuccessWithMessage:message inView:[UIApplication sharedApplication].keyWindow]; } -/** - 显示成功message, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - @param view 显示在哪个view上 - */ + + (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view { [self showSuccessWithMessage:message inView:view delay:kDelayTime enabled:NO]; } -/** - 显示成功message - @param message 文字 - @param view 显示在哪个view上 - @param afterDelay 延迟消失时间 - @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 - */ + + (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled { if (message.length == 0) { return; } @@ -110,13 +87,13 @@ static NSArray * _animationImages = nil; if (!inView) { inView = [UIApplication sharedApplication].keyWindow; } - [self hideHUDInView:view]; // 先隐藏 + [self hideHUDInView:view]; MBProgressHUD *hud = [self normalProgressHUD:view]; hud.userInteractionEnabled = enabled; hud.mode = MBProgressHUDModeText; hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; hud.margin = 8; - // 方框背景颜色 + hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.8]; hud.label.text = message; hud.label.numberOfLines = 0; @@ -126,40 +103,24 @@ static NSArray * _animationImages = nil; }); } -/** - 显示错误message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - */ + + (void)showErrorWithMessage:(NSString *)message { [self showErrorWithMessage:message inView:[UIApplication sharedApplication].keyWindow]; } -/** - 显示错误message, 2.5s后消失, 默认不拦截点击事件 - - @param message 文字 - @param view 显示在哪个view上 - */ + + (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view { [self showErrorWithMessage:message inView:view delay:kDelayTime enabled:NO]; } -/** - 显示错误message - - @param message 文字 - @param view 显示在哪个view上 - @param afterDelay 延迟消失时间 - @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 - */ + + (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled { if (message.length == 0) { return; } if (!view) { view = [UIApplication sharedApplication].keyWindow; } - [self hideHUDInView:view]; // 先隐藏 + [self hideHUDInView:view]; dispatch_main_sync_safe(^{ MBProgressHUD *hud = [self normalProgressHUD:view]; @@ -167,7 +128,7 @@ static NSArray * _animationImages = nil; hud.mode = MBProgressHUDModeText; hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; hud.margin = 8; - // 方框背景颜色 + hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.8]; hud.label.text = message; hud.label.numberOfLines = 0; @@ -177,52 +138,40 @@ static NSArray * _animationImages = nil; }); } -/** - * 在窗口上显示菊花 - */ + + (void)showLoading { [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; return; [self showLoadingInView:[UIApplication sharedApplication].keyWindow]; } -/** - * 在view上显示菊花 - */ + + (void)showLoadingInView:(nullable UIView *)view { [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; return; [self showLoadingInView:view enabled:YES]; } -/** - * 在view上显示菊花 - */ + + (void)showLoadingInView:(nullable UIView *)view enabled:(BOOL)enabled { [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; return; [self showLoadingWithMessage:@"" inView:view enabled:enabled]; } -/** - * 在窗口上显示菊花+文字 - */ + + (void)showLoadingWithMessage:(NSString *)message { [self showLoadingWithMessage:message inView:[UIApplication sharedApplication].keyWindow]; } -/** - * 在view上显示菊花+文字 - */ + + (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view { [self showLoadingWithMessage:message inView:view enabled:YES]; } -/** - * 在view上显示菊花+文字 - */ + + (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view enabled:(BOOL)enabled { @@ -246,28 +195,17 @@ static NSArray * _animationImages = nil; } -/** - 在窗口上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 - */ + + (void)showGIFLoading { [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; } -/** - 在指定的view上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 - - @param view 显示在哪个view上 - */ + + (void)showGIFLoadingInView:(nullable UIView *)view { [self showGIFLoadingInView:view bgColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.35] enabled:YES]; } -/** - 在指定的view上显示自定义GIFLoading - @param view 显示在哪个view上 - @param bgColor 背景颜色, 遮盖 - @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 - */ + + (void)showGIFLoadingInView:(nullable UIView *)view bgColor:(nullable UIColor *)bgColor enabled:(BOOL)enabled { if (!view) { view = [UIApplication sharedApplication].keyWindow; @@ -324,7 +262,6 @@ static NSArray * _animationImages = nil; } - + (UIView *)loadingView { UIView *bgView = [UIView new]; bgView.backgroundColor = [UIColor clearColor]; @@ -334,7 +271,6 @@ static NSArray * _animationImages = nil; } - +(void)hideOnlyView:(UIView *)view{ dispatch_main_sync_safe(^{ diff --git a/YuMi/CustomUI/XNDJTDDLoadingTool.m.backup b/YuMi/CustomUI/XNDJTDDLoadingTool.m.backup new file mode 100644 index 0000000..8c361f6 --- /dev/null +++ b/YuMi/CustomUI/XNDJTDDLoadingTool.m.backup @@ -0,0 +1,391 @@ +// +// YMHUDTool.m +// TTPlay +// +// Created by YM on 2022/5/15. +// Copyright © 2023 YUMI. All rights reserved. +// + +#import "XNDJTDDLoadingTool.h" +#import "GCDHelper.h" +#import +#import "MvpViewController.h" + +#define kDelayTime 2.5 +@interface XNDJTDDLoadingTool () +/// +@property (class,nonatomic,copy) NSArray *animationImages; +@end + +@implementation XNDJTDDLoadingTool + +static NSArray * _animationImages = nil; + +/** + 隐藏HUD, 如果view为nil, 则默认隐藏主窗口的HUD + + @param view view + */ ++ (void)hideHUDInView:(nullable UIView *)view { + dispatch_main_sync_safe(^{ + if (view) { + MBProgressHUD *hud = [XNDJTDDLoadingTool HUDForView:view]; + + if (hud != nil && hud.mode != MBProgressHUDModeText) { + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:NO]; + } + MBProgressHUD *windowHud = [XNDJTDDLoadingTool HUDForView:kWindow]; + if (windowHud != nil && windowHud.mode != MBProgressHUDModeText) { + windowHud.removeFromSuperViewOnHide = YES; + [windowHud hideAnimated:NO]; + } + } else { + MBProgressHUD *windowHud = [XNDJTDDLoadingTool HUDForView:kWindow]; + if (windowHud != nil && windowHud.mode != MBProgressHUDModeText) { + windowHud.removeFromSuperViewOnHide = YES; + [windowHud hideAnimated:NO]; + } + } + }); +} + + ++ (MBProgressHUD *)HUDForView:(UIView *)view { + NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; + for (UIView *subview in subviewsEnum) { + if ([subview isKindOfClass:[MBProgressHUD class]]) { + MBProgressHUD *hud = (MBProgressHUD *)subview; + id hasFinished = [hud valueForKey:@"hasFinished"]; + if (hasFinished != nil) { + if([hasFinished boolValue] == NO){ + return hud; + } + + } + } + } + return nil; +} + +/** + 隐藏HUD + */ ++ (void)hideHUD { + [self hideHUDInView:nil]; +} + +/** + 显示成功message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + */ ++ (void)showSuccessWithMessage:(NSString *)message { + [self showSuccessWithMessage:message inView:[UIApplication sharedApplication].keyWindow]; +} + +/** + 显示成功message, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + @param view 显示在哪个view上 + */ ++ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view { + [self showSuccessWithMessage:message inView:view delay:kDelayTime enabled:NO]; +} + +/** + 显示成功message + @param message 文字 + @param view 显示在哪个view上 + @param afterDelay 延迟消失时间 + @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 + */ ++ (void)showSuccessWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled { + + if (message.length == 0) { return; } + __block UIView *inView = view; + + dispatch_main_sync_safe(^{ + if (!inView) { + inView = [UIApplication sharedApplication].keyWindow; + } + [self hideHUDInView:view]; // 先隐藏 + MBProgressHUD *hud = [self normalProgressHUD:view]; + hud.userInteractionEnabled = enabled; + hud.mode = MBProgressHUDModeText; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.margin = 8; + // 方框背景颜色 + hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.8]; + hud.label.text = message; + hud.label.numberOfLines = 0; + hud.label.textColor = [UIColor whiteColor]; + hud.label.font = [UIFont systemFontOfSize:14]; + [hud hideAnimated:YES afterDelay:afterDelay]; + }); +} + +/** + 显示错误message, 默认显示在窗口上, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + */ ++ (void)showErrorWithMessage:(NSString *)message { + [self showErrorWithMessage:message inView:[UIApplication sharedApplication].keyWindow]; +} + +/** + 显示错误message, 2.5s后消失, 默认不拦截点击事件 + + @param message 文字 + @param view 显示在哪个view上 + */ ++ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view { + [self showErrorWithMessage:message inView:view delay:kDelayTime enabled:NO]; +} + +/** + 显示错误message + + @param message 文字 + @param view 显示在哪个view上 + @param afterDelay 延迟消失时间 + @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 + */ ++ (void)showErrorWithMessage:(NSString *)message inView:(nullable UIView *)view delay:(NSTimeInterval)afterDelay enabled:(BOOL)enabled { + if (message.length == 0) { return; } + if (!view) { + view = [UIApplication sharedApplication].keyWindow; + } + + [self hideHUDInView:view]; // 先隐藏 + + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [self normalProgressHUD:view]; + hud.userInteractionEnabled = enabled; + hud.mode = MBProgressHUDModeText; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.margin = 8; + // 方框背景颜色 + hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.8]; + hud.label.text = message; + hud.label.numberOfLines = 0; + hud.label.textColor = [UIColor whiteColor]; + hud.label.font = [UIFont systemFontOfSize:14]; + [hud hideAnimated:YES afterDelay:afterDelay]; + }); +} + +/** + * 在窗口上显示菊花 + */ ++ (void)showLoading { + [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; + return; + [self showLoadingInView:[UIApplication sharedApplication].keyWindow]; +} + +/** + * 在view上显示菊花 + */ ++ (void)showLoadingInView:(nullable UIView *)view { + [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; + return; + [self showLoadingInView:view enabled:YES]; +} + +/** + * 在view上显示菊花 + */ ++ (void)showLoadingInView:(nullable UIView *)view enabled:(BOOL)enabled { + [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; + return; + [self showLoadingWithMessage:@"" inView:view enabled:enabled]; +} + +/** + * 在窗口上显示菊花+文字 + */ ++ (void)showLoadingWithMessage:(NSString *)message { + + [self showLoadingWithMessage:message inView:[UIApplication sharedApplication].keyWindow]; +} + +/** + * 在view上显示菊花+文字 + */ ++ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view { + + [self showLoadingWithMessage:message inView:view enabled:YES]; +} + +/** + * 在view上显示菊花+文字 + */ ++ (void)showLoadingWithMessage:(NSString *)message inView:(nullable UIView *)view enabled:(BOOL)enabled { + + + if (!view) { + view = [UIApplication sharedApplication].keyWindow; + } + [self hideHUDInView:view]; + + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.userInteractionEnabled = enabled; + hud.bezelView.color = [[UIColor whiteColor] colorWithAlphaComponent:0.8]; + hud.removeFromSuperViewOnHide = YES; + if (message.length) { + hud.label.text = message; + hud.label.numberOfLines = 0; + hud.label.textColor = [UIColor blackColor]; + hud.label.font = [UIFont systemFontOfSize:14]; + } + }); + +} + +/** + 在窗口上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 + */ ++ (void)showGIFLoading { + [self showGIFLoadingInView:[UIApplication sharedApplication].keyWindow]; +} + +/** + 在指定的view上显示自定义GIFLoading, 背景默认黑色0.35透明度, 默认拦截点击事件 + + @param view 显示在哪个view上 + */ ++ (void)showGIFLoadingInView:(nullable UIView *)view { + [self showGIFLoadingInView:view bgColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.35] enabled:YES]; +} + +/** + 在指定的view上显示自定义GIFLoading + @param view 显示在哪个view上 + @param bgColor 背景颜色, 遮盖 + @param enabled 是否可以拦截事件 no:不拦截 yes:拦截 + */ ++ (void)showGIFLoadingInView:(nullable UIView *)view bgColor:(nullable UIColor *)bgColor enabled:(BOOL)enabled { + if (!view) { + view = [UIApplication sharedApplication].keyWindow; + } + [self hideHUDInView:view]; + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.minSize = CGSizeMake(100, 150); + hud.userInteractionEnabled = NO; + hud.mode = MBProgressHUDModeCustomView; + [hud.bezelView addSubview:[self loadingView]]; + hud.backgroundColor = bgColor; + hud.bezelView.color = [UIColor clearColor]; + hud.removeFromSuperViewOnHide = YES; + }); +} + + ++ (void)showAnchorLoading { + + UIView *view = [UIApplication sharedApplication].delegate.window; + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.userInteractionEnabled = NO; + hud.mode = MBProgressHUDModeCustomView; + hud.minSize = CGSizeMake(100, 150); + [hud.bezelView addSubview:[self loadingView ]]; + hud.bezelView.color = [UIColor clearColor]; + hud.removeFromSuperViewOnHide = YES; + }); +} + ++ (void)showAnchorLoading:(UIView *)view { + + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.userInteractionEnabled = NO; + hud.mode = MBProgressHUDModeCustomView; + hud.minSize = CGSizeMake(100, 150); + [hud.bezelView addSubview:[self loadingView ]]; + hud.bezelView.color = [UIColor clearColor]; + hud.removeFromSuperViewOnHide = YES; + }); +} + +#pragma mark - private ++ (MBProgressHUD *)normalProgressHUD:(UIView *)view { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.removeFromSuperViewOnHide = YES; + return hud; +} + + + ++ (UIView *)loadingView { + UIView *bgView = [UIView new]; + bgView.backgroundColor = [UIColor clearColor]; + bgView.frame = CGRectMake(0, 0, 100, 150); + + return bgView; +} + + + ++(void)hideOnlyView:(UIView *)view{ + + dispatch_main_sync_safe(^{ + if (view) { + UIView *getView; + if([view isKindOfClass:[MvpViewController class]]){ + getView = ((MvpViewController *)view).view; + }else{ + getView = view; + } + MBProgressHUD *hud = [XNDJTDDLoadingTool HUDForView:getView]; + if (hud != nil && hud.mode != MBProgressHUDModeText) { + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:NO]; + } + } + }); +} ++(void)showOnlyView:(UIView *)view{ + if (!view) { + view = [UIApplication sharedApplication].keyWindow; + } + [self hideOnlyView:view]; + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.minSize = CGSizeMake(100, 150); + hud.userInteractionEnabled = NO; + hud.mode = MBProgressHUDModeCustomView; + [hud.bezelView addSubview:[self loadingView]]; + hud.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.35]; + hud.bezelView.color = [UIColor clearColor]; + hud.removeFromSuperViewOnHide = YES; + }); +} ++(void)showOnlyView:(UIView *)view enabled:(BOOL)enabled{ + if (!view) { + view = [UIApplication sharedApplication].keyWindow; + } + [self hideOnlyView:view]; + dispatch_main_sync_safe(^{ + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; + hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; + hud.minSize = CGSizeMake(100, 150); + hud.userInteractionEnabled = enabled; + hud.mode = MBProgressHUDModeCustomView; + [hud.bezelView addSubview:[self loadingView]]; + hud.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.35]; + hud.bezelView.color = [UIColor clearColor]; + hud.removeFromSuperViewOnHide = YES; + }); +} + +@end diff --git a/YuMi/E-P/Common/EPImageUploader.swift b/YuMi/E-P/Common/EPImageUploader.swift index 98995bc..3b10573 100644 --- a/YuMi/E-P/Common/EPImageUploader.swift +++ b/YuMi/E-P/Common/EPImageUploader.swift @@ -1,27 +1,17 @@ -// -// EPImageUploader.swift -// YuMi -// + + // Created by AI on 2025-10-11. -// + import UIKit import Foundation -/// 图片批量上传工具(纯 Swift 内部类,直接使用 QCloudCOSXML SDK) -/// 不对外暴露,由 EPSDKManager 内部调用 + class EPImageUploader { init() {} - /// 批量上传图片(内部方法) - /// - Parameters: - /// - images: 要上传的图片数组 - /// - bucket: QCloud bucket 名称 - /// - customDomain: 自定义域名 - /// - progress: 进度回调 (已上传数, 总数) - /// - success: 成功回调 - /// - failure: 失败回调 + func performBatchUpload( _ images: [UIImage], bucket: String, @@ -32,7 +22,7 @@ class EPImageUploader { ) { let total = images.count let queue = DispatchQueue(label: "com.yumi.imageupload", attributes: .concurrent) - let semaphore = DispatchSemaphore(value: 3) // 最多同时上传 3 张 + let semaphore = DispatchSemaphore(value: 3) var uploadedCount = 0 var resultList: [[String: Any]] = [] var hasError = false @@ -42,7 +32,7 @@ class EPImageUploader { queue.async { semaphore.wait() - // 检查是否已经失败 + lock.lock() if hasError { lock.unlock() @@ -51,7 +41,7 @@ class EPImageUploader { } lock.unlock() - // 压缩图片 + guard let imageData = image.jpegData(compressionQuality: 0.5) else { lock.lock() hasError = true @@ -63,25 +53,25 @@ class EPImageUploader { return } - // 获取图片格式 + let format = UIImage.getImageType(withImageData: imageData) ?? "jpeg" - // 生成文件名 + let uuid = NSString.createUUID() let fileName = "image/\(uuid).\(format)" - // 直接使用 QCloud SDK 上传 + let request = QCloudCOSXMLUploadObjectRequest() request.bucket = bucket request.object = fileName request.body = imageData as NSData - // 监听上传进度(可选) + request.sendProcessBlock = { bytesSent, totalBytesSent, totalBytesExpectedToSend in - // 单个文件的上传进度(当前不使用) + } - // 监听上传结果 + request.finishBlock = { [weak self] result, error in guard let self = self else { semaphore.signal() @@ -89,7 +79,7 @@ class EPImageUploader { } if let error = error { - // 上传失败 + lock.lock() if !hasError { hasError = true @@ -103,12 +93,12 @@ class EPImageUploader { semaphore.signal() } } else if let result = result as? QCloudUploadObjectResult { - // 上传成功 + lock.lock() if !hasError { uploadedCount += 1 - // 解析上传 URL(参考 UploadFile.m line 217-223) + let uploadedURL = self.parseUploadURL(result.location, customDomain: customDomain) let imageInfo: [String: Any] = [ @@ -122,12 +112,12 @@ class EPImageUploader { let currentUploaded = uploadedCount lock.unlock() - // 进度回调 + DispatchQueue.main.async { progress(currentUploaded, total) } - // 全部完成 + if currentUploaded == total { DispatchQueue.main.async { success(resultList) @@ -142,17 +132,13 @@ class EPImageUploader { } } - // 执行上传 + QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(request) } } } - /// 解析上传返回的 URL(参考 UploadFile.m line 217-223) - /// - Parameters: - /// - location: QCloud 返回的原始 URL - /// - customDomain: 自定义域名 - /// - Returns: 解析后的 URL + private func parseUploadURL(_ location: String, customDomain: String) -> String { let components = location.components(separatedBy: ".com/") if components.count == 2 { diff --git a/YuMi/E-P/Common/EPImageUploader.swift.backup b/YuMi/E-P/Common/EPImageUploader.swift.backup new file mode 100644 index 0000000..98995bc --- /dev/null +++ b/YuMi/E-P/Common/EPImageUploader.swift.backup @@ -0,0 +1,163 @@ +// +// EPImageUploader.swift +// YuMi +// +// Created by AI on 2025-10-11. +// + +import UIKit +import Foundation + +/// 图片批量上传工具(纯 Swift 内部类,直接使用 QCloudCOSXML SDK) +/// 不对外暴露,由 EPSDKManager 内部调用 +class EPImageUploader { + + init() {} + + /// 批量上传图片(内部方法) + /// - Parameters: + /// - images: 要上传的图片数组 + /// - bucket: QCloud bucket 名称 + /// - customDomain: 自定义域名 + /// - progress: 进度回调 (已上传数, 总数) + /// - success: 成功回调 + /// - failure: 失败回调 + func performBatchUpload( + _ images: [UIImage], + bucket: String, + customDomain: String, + progress: @escaping (Int, Int) -> Void, + success: @escaping ([[String: Any]]) -> Void, + failure: @escaping (String) -> Void + ) { + let total = images.count + let queue = DispatchQueue(label: "com.yumi.imageupload", attributes: .concurrent) + let semaphore = DispatchSemaphore(value: 3) // 最多同时上传 3 张 + var uploadedCount = 0 + var resultList: [[String: Any]] = [] + var hasError = false + let lock = NSLock() + + for (_, image) in images.enumerated() { + queue.async { + semaphore.wait() + + // 检查是否已经失败 + lock.lock() + if hasError { + lock.unlock() + semaphore.signal() + return + } + lock.unlock() + + // 压缩图片 + guard let imageData = image.jpegData(compressionQuality: 0.5) else { + lock.lock() + hasError = true + lock.unlock() + semaphore.signal() + DispatchQueue.main.async { + failure(YMLocalizedString("error.image_compress_failed")) + } + return + } + + // 获取图片格式 + let format = UIImage.getImageType(withImageData: imageData) ?? "jpeg" + + // 生成文件名 + let uuid = NSString.createUUID() + let fileName = "image/\(uuid).\(format)" + + // 直接使用 QCloud SDK 上传 + let request = QCloudCOSXMLUploadObjectRequest() + request.bucket = bucket + request.object = fileName + request.body = imageData as NSData + + // 监听上传进度(可选) + request.sendProcessBlock = { bytesSent, totalBytesSent, totalBytesExpectedToSend in + // 单个文件的上传进度(当前不使用) + } + + // 监听上传结果 + request.finishBlock = { [weak self] result, error in + guard let self = self else { + semaphore.signal() + return + } + + if let error = error { + // 上传失败 + lock.lock() + if !hasError { + hasError = true + lock.unlock() + semaphore.signal() + DispatchQueue.main.async { + failure(error.localizedDescription) + } + } else { + lock.unlock() + semaphore.signal() + } + } else if let result = result as? QCloudUploadObjectResult { + // 上传成功 + lock.lock() + if !hasError { + uploadedCount += 1 + + // 解析上传 URL(参考 UploadFile.m line 217-223) + let uploadedURL = self.parseUploadURL(result.location, customDomain: customDomain) + + let imageInfo: [String: Any] = [ + "resUrl": uploadedURL, + "width": image.size.width, + "height": image.size.height, + "format": format + ] + resultList.append(imageInfo) + + let currentUploaded = uploadedCount + lock.unlock() + + // 进度回调 + DispatchQueue.main.async { + progress(currentUploaded, total) + } + + // 全部完成 + if currentUploaded == total { + DispatchQueue.main.async { + success(resultList) + } + } + } else { + lock.unlock() + } + semaphore.signal() + } else { + semaphore.signal() + } + } + + // 执行上传 + QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(request) + } + } + } + + /// 解析上传返回的 URL(参考 UploadFile.m line 217-223) + /// - Parameters: + /// - location: QCloud 返回的原始 URL + /// - customDomain: 自定义域名 + /// - Returns: 解析后的 URL + private func parseUploadURL(_ location: String, customDomain: String) -> String { + let components = location.components(separatedBy: ".com/") + if components.count == 2 { + return "\(customDomain)/\(components[1])" + } + return location + } +} diff --git a/YuMi/E-P/Common/EPProgressHUD.swift b/YuMi/E-P/Common/EPProgressHUD.swift index fcad5d3..0b251bf 100644 --- a/YuMi/E-P/Common/EPProgressHUD.swift +++ b/YuMi/E-P/Common/EPProgressHUD.swift @@ -1,19 +1,17 @@ -// -// EPProgressHUD.swift -// YuMi -// + + // Created by AI on 2025-10-11. -// + import UIKit import Foundation -/// 带进度的 Loading 组件(基于 MBProgressHUD) + @objc class EPProgressHUD: NSObject { private static var currentHUD: MBProgressHUD? - /// 获取当前活跃的 window(兼容 iOS 13+) + private static var keyWindow: UIWindow? { if #available(iOS 13.0, *) { return UIApplication.shared.connectedScenes @@ -25,20 +23,17 @@ import Foundation } } - /// 显示上传进度 - /// - Parameters: - /// - uploaded: 已上传数量 - /// - total: 总数量 + @objc static func showProgress(_ uploaded: Int, total: Int) { DispatchQueue.main.async { guard let window = keyWindow else { return } if let hud = currentHUD { - // 更新现有 HUD + hud.label.text = String(format: YMLocalizedString("upload.progress_format"), uploaded, total) hud.progress = Float(uploaded) / Float(total) } else { - // 创建新 HUD + let hud = MBProgressHUD.showAdded(to: window, animated: true) hud.mode = .determinateHorizontalBar hud.label.text = String(format: YMLocalizedString("upload.progress_format"), uploaded, total) @@ -49,8 +44,7 @@ import Foundation } } - /// 显示错误提示 - /// - Parameter message: 错误信息 + @objc static func showError(_ message: String) { DispatchQueue.main.async { guard let window = keyWindow else { return } @@ -64,8 +58,7 @@ import Foundation } } - /// 显示成功提示 - /// - Parameter message: 成功信息 + @objc static func showSuccess(_ message: String) { DispatchQueue.main.async { guard let window = keyWindow else { return } @@ -79,7 +72,7 @@ import Foundation } } - /// 关闭 HUD + @objc static func dismiss() { DispatchQueue.main.async { guard let hud = currentHUD else { return } diff --git a/YuMi/E-P/Common/EPProgressHUD.swift.backup b/YuMi/E-P/Common/EPProgressHUD.swift.backup new file mode 100644 index 0000000..fcad5d3 --- /dev/null +++ b/YuMi/E-P/Common/EPProgressHUD.swift.backup @@ -0,0 +1,92 @@ +// +// EPProgressHUD.swift +// YuMi +// +// Created by AI on 2025-10-11. +// + +import UIKit +import Foundation + +/// 带进度的 Loading 组件(基于 MBProgressHUD) +@objc class EPProgressHUD: NSObject { + + private static var currentHUD: MBProgressHUD? + + /// 获取当前活跃的 window(兼容 iOS 13+) + private static var keyWindow: UIWindow? { + if #available(iOS 13.0, *) { + return UIApplication.shared.connectedScenes + .compactMap { $0 as? UIWindowScene } + .flatMap { $0.windows } + .first { $0.isKeyWindow } + } else { + return UIApplication.shared.keyWindow + } + } + + /// 显示上传进度 + /// - Parameters: + /// - uploaded: 已上传数量 + /// - total: 总数量 + @objc static func showProgress(_ uploaded: Int, total: Int) { + DispatchQueue.main.async { + guard let window = keyWindow else { return } + + if let hud = currentHUD { + // 更新现有 HUD + hud.label.text = String(format: YMLocalizedString("upload.progress_format"), uploaded, total) + hud.progress = Float(uploaded) / Float(total) + } else { + // 创建新 HUD + let hud = MBProgressHUD.showAdded(to: window, animated: true) + hud.mode = .determinateHorizontalBar + hud.label.text = String(format: YMLocalizedString("upload.progress_format"), uploaded, total) + hud.progress = Float(uploaded) / Float(total) + hud.removeFromSuperViewOnHide = true + currentHUD = hud + } + } + } + + /// 显示错误提示 + /// - Parameter message: 错误信息 + @objc static func showError(_ message: String) { + DispatchQueue.main.async { + guard let window = keyWindow else { return } + + let hud = MBProgressHUD.showAdded(to: window, animated: true) + hud.mode = .text + hud.label.text = message + hud.label.numberOfLines = 0 + hud.removeFromSuperViewOnHide = true + hud.hide(animated: true, afterDelay: 2.0) + } + } + + /// 显示成功提示 + /// - Parameter message: 成功信息 + @objc static func showSuccess(_ message: String) { + DispatchQueue.main.async { + guard let window = keyWindow else { return } + + let hud = MBProgressHUD.showAdded(to: window, animated: true) + hud.mode = .text + hud.label.text = message + hud.label.numberOfLines = 0 + hud.removeFromSuperViewOnHide = true + hud.hide(animated: true, afterDelay: 2.0) + } + } + + /// 关闭 HUD + @objc static func dismiss() { + DispatchQueue.main.async { + guard let hud = currentHUD else { return } + + hud.hide(animated: true) + currentHUD = nil + } + } +} + diff --git a/YuMi/E-P/Common/EPQCloudConfig.swift b/YuMi/E-P/Common/EPQCloudConfig.swift index 77a5afc..88c3bff 100644 --- a/YuMi/E-P/Common/EPQCloudConfig.swift +++ b/YuMi/E-P/Common/EPQCloudConfig.swift @@ -1,13 +1,11 @@ -// -// EPQCloudConfig.swift -// YuMi -// + + // Created by AI on 2025-10-11. -// + import Foundation -/// QCloud 配置数据模型(对应 UploadFileModel) + struct EPQCloudConfig { let secretId: String let secretKey: String @@ -20,10 +18,9 @@ struct EPQCloudConfig { let appId: String let accelerate: Int - /// 从 API 返回的 dictionary 初始化 - /// API: GET tencent/cos/getToken + init?(dictionary: [String: Any]) { - // 必填字段检查 + guard let secretId = dictionary["secretId"] as? String, let secretKey = dictionary["secretKey"] as? String, let sessionToken = dictionary["sessionToken"] as? String, @@ -42,13 +39,13 @@ struct EPQCloudConfig { self.customDomain = customDomain self.appId = appId - // 可选字段使用默认值 + self.startTime = (dictionary["startTime"] as? Int64) ?? 0 self.expireTime = (dictionary["expireTime"] as? Int64) ?? 0 self.accelerate = (dictionary["accelerate"] as? Int) ?? 0 } - /// 检查配置是否过期 + var isExpired: Bool { return Date().timeIntervalSince1970 > Double(expireTime) } diff --git a/YuMi/E-P/Common/EPQCloudConfig.swift.backup b/YuMi/E-P/Common/EPQCloudConfig.swift.backup new file mode 100644 index 0000000..77a5afc --- /dev/null +++ b/YuMi/E-P/Common/EPQCloudConfig.swift.backup @@ -0,0 +1,56 @@ +// +// EPQCloudConfig.swift +// YuMi +// +// Created by AI on 2025-10-11. +// + +import Foundation + +/// QCloud 配置数据模型(对应 UploadFileModel) +struct EPQCloudConfig { + let secretId: String + let secretKey: String + let sessionToken: String + let bucket: String + let region: String + let customDomain: String + let startTime: Int64 + let expireTime: Int64 + let appId: String + let accelerate: Int + + /// 从 API 返回的 dictionary 初始化 + /// API: GET tencent/cos/getToken + init?(dictionary: [String: Any]) { + // 必填字段检查 + guard let secretId = dictionary["secretId"] as? String, + let secretKey = dictionary["secretKey"] as? String, + let sessionToken = dictionary["sessionToken"] as? String, + let bucket = dictionary["bucket"] as? String, + let region = dictionary["region"] as? String, + let customDomain = dictionary["customDomain"] as? String, + let appId = dictionary["appId"] as? String else { + return nil + } + + self.secretId = secretId + self.secretKey = secretKey + self.sessionToken = sessionToken + self.bucket = bucket + self.region = region + self.customDomain = customDomain + self.appId = appId + + // 可选字段使用默认值 + self.startTime = (dictionary["startTime"] as? Int64) ?? 0 + self.expireTime = (dictionary["expireTime"] as? Int64) ?? 0 + self.accelerate = (dictionary["accelerate"] as? Int) ?? 0 + } + + /// 检查配置是否过期 + var isExpired: Bool { + return Date().timeIntervalSince1970 > Double(expireTime) + } +} + diff --git a/YuMi/E-P/Common/EPSDKManager.swift b/YuMi/E-P/Common/EPSDKManager.swift index 4b4f27a..52ecfd4 100644 --- a/YuMi/E-P/Common/EPSDKManager.swift +++ b/YuMi/E-P/Common/EPSDKManager.swift @@ -1,15 +1,11 @@ -// -// EPSDKManager.swift -// YuMi -// + + // Created by AI on 2025-10-11. -// + import Foundation -/// 第三方 SDK 统一管理器(单例) -/// 统一入口:对外提供所有 SDK 能力 -/// 内部管理:QCloud 初始化、配置、上传等 + @objc class EPSDKManager: NSObject, QCloudSignatureProvider, QCloudCredentailFenceQueueDelegate { // MARK: - Singleton @@ -18,22 +14,22 @@ import Foundation // MARK: - Properties - // QCloud 配置缓存 + private var qcloudConfig: EPQCloudConfig? - // QCloud 初始化状态 + private var isQCloudInitializing = false - // QCloud 初始化回调队列 + private var qcloudInitCallbacks: [(Bool, String?) -> Void] = [] - // QCloud 凭证队列 + private var credentialFenceQueue: QCloudCredentailFenceQueue? - // 线程安全锁 + private let lock = NSLock() - // 内部图片上传器 + private let uploader = EPImageUploader() // MARK: - Initialization @@ -44,12 +40,7 @@ import Foundation // MARK: - Public API (对外统一入口) - /// 批量上传图片(统一入口) - /// - Parameters: - /// - images: 要上传的图片数组 - /// - progress: 进度回调 (已上传数, 总数) - /// - success: 成功回调,返回图片信息数组 - /// - failure: 失败回调 + @objc func uploadImages( _ images: [UIImage], progress: @escaping (Int, Int) -> Void, @@ -61,7 +52,7 @@ import Foundation return } - // 确保 QCloud 已就绪 + ensureQCloudReady { [weak self] isReady, errorMsg in guard let self = self, isReady else { DispatchQueue.main.async { @@ -70,7 +61,7 @@ import Foundation return } - // 委托给内部 uploader 执行 + self.uploader.performBatchUpload( images, bucket: self.qcloudConfig?.bucket ?? "", @@ -82,8 +73,7 @@ import Foundation } } - /// 检查 QCloud 是否已就绪 - /// - Returns: true 表示已初始化且未过期 + @objc func isQCloudReady() -> Bool { lock.lock() defer { lock.unlock() } @@ -96,42 +86,41 @@ import Foundation // MARK: - Internal Methods - /// 确保 QCloud 已就绪(自动初始化) + private func ensureQCloudReady(completion: @escaping (Bool, String?) -> Void) { if isQCloudReady() { completion(true, nil) return } - // 未初始化或已过期,重新初始化 + initializeQCloud(completion: completion) } - /// 初始化 QCloud(获取 Token 并配置 SDK) + private func initializeQCloud(completion: @escaping (Bool, String?) -> Void) { lock.lock() - // 如果正在初始化,加入回调队列 + if isQCloudInitializing { qcloudInitCallbacks.append(completion) lock.unlock() return } - // 如果已初始化且未过期,直接返回 + if let config = qcloudConfig, !config.isExpired { lock.unlock() completion(true, nil) return } - // 开始初始化 + isQCloudInitializing = true qcloudInitCallbacks.append(completion) lock.unlock() - // 调用 API 获取 QCloud Token - // API: GET tencent/cos/getToken + Api.getQCloudInfo { [weak self] (data, code, msg) in guard let self = self else { return } @@ -141,24 +130,24 @@ import Foundation let dict = data?.data as? [String: Any], let config = EPQCloudConfig(dictionary: dict) { - // 保存配置 + self.qcloudConfig = config - // 配置 QCloud SDK + self.configureQCloudSDK(with: config) - // 初始化完成 + self.isQCloudInitializing = false let callbacks = self.qcloudInitCallbacks self.qcloudInitCallbacks.removeAll() self.lock.unlock() - // 短暂延迟确保 SDK 配置完成 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { callbacks.forEach { $0(true, nil) } } } else { - // 初始化失败 + self.isQCloudInitializing = false let callbacks = self.qcloudInitCallbacks self.qcloudInitCallbacks.removeAll() @@ -172,7 +161,7 @@ import Foundation } } - /// 配置 QCloud SDK(参考 UploadFile.m line 42-64) + private func configureQCloudSDK(with config: EPQCloudConfig) { let configuration = QCloudServiceConfiguration() configuration.appID = config.appId @@ -181,7 +170,7 @@ import Foundation endpoint.regionName = config.region endpoint.useHTTPS = true - // 全球加速(参考 UploadFile.m line 56-59) + if config.accelerate == 1 { endpoint.suffix = "cos.accelerate.myqcloud.com" } @@ -189,18 +178,18 @@ import Foundation configuration.endpoint = endpoint configuration.signatureProvider = self - // 注册 COS 服务 + QCloudCOSXMLService.registerDefaultCOSXML(with: configuration) QCloudCOSTransferMangerService.registerDefaultCOSTransferManger(with: configuration) - // 初始化凭证队列 + credentialFenceQueue = QCloudCredentailFenceQueue() credentialFenceQueue?.delegate = self } // MARK: - QCloudSignatureProvider Protocol - /// 提供签名(参考 UploadFile.m line 67-104) + func signature( with fields: QCloudSignatureFields, request: QCloudBizHTTPRequest, @@ -228,7 +217,7 @@ import Foundation // MARK: - QCloudCredentailFenceQueueDelegate Protocol - /// 管理凭证(参考 UploadFile.m line 107-133) + func fenceQueue( _ queue: QCloudCredentailFenceQueue, requestCreatorWithContinue continueBlock: @escaping QCloudCredentailFenceQueueContinue diff --git a/YuMi/E-P/Common/EPSDKManager.swift.backup b/YuMi/E-P/Common/EPSDKManager.swift.backup new file mode 100644 index 0000000..4b4f27a --- /dev/null +++ b/YuMi/E-P/Common/EPSDKManager.swift.backup @@ -0,0 +1,253 @@ +// +// EPSDKManager.swift +// YuMi +// +// Created by AI on 2025-10-11. +// + +import Foundation + +/// 第三方 SDK 统一管理器(单例) +/// 统一入口:对外提供所有 SDK 能力 +/// 内部管理:QCloud 初始化、配置、上传等 +@objc class EPSDKManager: NSObject, QCloudSignatureProvider, QCloudCredentailFenceQueueDelegate { + + // MARK: - Singleton + + @objc static let shared = EPSDKManager() + + // MARK: - Properties + + // QCloud 配置缓存 + private var qcloudConfig: EPQCloudConfig? + + // QCloud 初始化状态 + private var isQCloudInitializing = false + + // QCloud 初始化回调队列 + private var qcloudInitCallbacks: [(Bool, String?) -> Void] = [] + + // QCloud 凭证队列 + private var credentialFenceQueue: QCloudCredentailFenceQueue? + + // 线程安全锁 + private let lock = NSLock() + + // 内部图片上传器 + private let uploader = EPImageUploader() + + // MARK: - Initialization + + private override init() { + super.init() + } + + // MARK: - Public API (对外统一入口) + + /// 批量上传图片(统一入口) + /// - Parameters: + /// - images: 要上传的图片数组 + /// - progress: 进度回调 (已上传数, 总数) + /// - success: 成功回调,返回图片信息数组 + /// - failure: 失败回调 + @objc func uploadImages( + _ images: [UIImage], + progress: @escaping (Int, Int) -> Void, + success: @escaping ([[String: Any]]) -> Void, + failure: @escaping (String) -> Void + ) { + guard !images.isEmpty else { + success([]) + return + } + + // 确保 QCloud 已就绪 + ensureQCloudReady { [weak self] isReady, errorMsg in + guard let self = self, isReady else { + DispatchQueue.main.async { + failure(errorMsg ?? YMLocalizedString("error.qcloud_init_failed")) + } + return + } + + // 委托给内部 uploader 执行 + self.uploader.performBatchUpload( + images, + bucket: self.qcloudConfig?.bucket ?? "", + customDomain: self.qcloudConfig?.customDomain ?? "", + progress: progress, + success: success, + failure: failure + ) + } + } + + /// 检查 QCloud 是否已就绪 + /// - Returns: true 表示已初始化且未过期 + @objc func isQCloudReady() -> Bool { + lock.lock() + defer { lock.unlock() } + + guard let config = qcloudConfig else { + return false + } + return !config.isExpired + } + + // MARK: - Internal Methods + + /// 确保 QCloud 已就绪(自动初始化) + private func ensureQCloudReady(completion: @escaping (Bool, String?) -> Void) { + if isQCloudReady() { + completion(true, nil) + return + } + + // 未初始化或已过期,重新初始化 + initializeQCloud(completion: completion) + } + + /// 初始化 QCloud(获取 Token 并配置 SDK) + private func initializeQCloud(completion: @escaping (Bool, String?) -> Void) { + lock.lock() + + // 如果正在初始化,加入回调队列 + if isQCloudInitializing { + qcloudInitCallbacks.append(completion) + lock.unlock() + return + } + + // 如果已初始化且未过期,直接返回 + if let config = qcloudConfig, !config.isExpired { + lock.unlock() + completion(true, nil) + return + } + + // 开始初始化 + isQCloudInitializing = true + qcloudInitCallbacks.append(completion) + lock.unlock() + + // 调用 API 获取 QCloud Token + // API: GET tencent/cos/getToken + Api.getQCloudInfo { [weak self] (data, code, msg) in + guard let self = self else { return } + + self.lock.lock() + + if code == 200, + let dict = data?.data as? [String: Any], + let config = EPQCloudConfig(dictionary: dict) { + + // 保存配置 + self.qcloudConfig = config + + // 配置 QCloud SDK + self.configureQCloudSDK(with: config) + + // 初始化完成 + self.isQCloudInitializing = false + let callbacks = self.qcloudInitCallbacks + self.qcloudInitCallbacks.removeAll() + self.lock.unlock() + + // 短暂延迟确保 SDK 配置完成 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + callbacks.forEach { $0(true, nil) } + } + } else { + // 初始化失败 + self.isQCloudInitializing = false + let callbacks = self.qcloudInitCallbacks + self.qcloudInitCallbacks.removeAll() + self.lock.unlock() + + let errorMsg = msg ?? YMLocalizedString("error.qcloud_config_failed") + DispatchQueue.main.async { + callbacks.forEach { $0(false, errorMsg) } + } + } + } + } + + /// 配置 QCloud SDK(参考 UploadFile.m line 42-64) + private func configureQCloudSDK(with config: EPQCloudConfig) { + let configuration = QCloudServiceConfiguration() + configuration.appID = config.appId + + let endpoint = QCloudCOSXMLEndPoint() + endpoint.regionName = config.region + endpoint.useHTTPS = true + + // 全球加速(参考 UploadFile.m line 56-59) + if config.accelerate == 1 { + endpoint.suffix = "cos.accelerate.myqcloud.com" + } + + configuration.endpoint = endpoint + configuration.signatureProvider = self + + // 注册 COS 服务 + QCloudCOSXMLService.registerDefaultCOSXML(with: configuration) + QCloudCOSTransferMangerService.registerDefaultCOSTransferManger(with: configuration) + + // 初始化凭证队列 + credentialFenceQueue = QCloudCredentailFenceQueue() + credentialFenceQueue?.delegate = self + } + + // MARK: - QCloudSignatureProvider Protocol + + /// 提供签名(参考 UploadFile.m line 67-104) + func signature( + with fields: QCloudSignatureFields, + request: QCloudBizHTTPRequest, + urlRequest: NSMutableURLRequest, + compelete: @escaping QCloudHTTPAuthentationContinueBlock + ) { + guard let config = qcloudConfig else { + let error = NSError(domain: "com.yumi.qcloud", code: -1, + userInfo: [NSLocalizedDescriptionKey: YMLocalizedString("error.qcloud_config_not_initialized")]) + compelete(nil, error) + return + } + + let credential = QCloudCredential() + credential.secretID = config.secretId + credential.secretKey = config.secretKey + credential.token = config.sessionToken + credential.startDate = Date(timeIntervalSince1970: TimeInterval(config.startTime)) + credential.expirationDate = Date(timeIntervalSince1970: TimeInterval(config.expireTime)) + + let creator = QCloudAuthentationV5Creator(credential: credential) + let signature = creator?.signature(forData: urlRequest) + compelete(signature, nil) + } + + // MARK: - QCloudCredentailFenceQueueDelegate Protocol + + /// 管理凭证(参考 UploadFile.m line 107-133) + func fenceQueue( + _ queue: QCloudCredentailFenceQueue, + requestCreatorWithContinue continueBlock: @escaping QCloudCredentailFenceQueueContinue + ) { + guard let config = qcloudConfig else { + let error = NSError(domain: "com.yumi.qcloud", code: -1, + userInfo: [NSLocalizedDescriptionKey: YMLocalizedString("error.qcloud_config_not_initialized")]) + continueBlock(nil, error) + return + } + + let credential = QCloudCredential() + credential.secretID = config.secretId + credential.secretKey = config.secretKey + credential.token = config.sessionToken + credential.startDate = Date(timeIntervalSince1970: TimeInterval(config.startTime)) + credential.expirationDate = Date(timeIntervalSince1970: TimeInterval(config.expireTime)) + + let creator = QCloudAuthentationV5Creator(credential: credential) + continueBlock(creator, nil) + } +} diff --git a/YuMi/E-P/Login/Controllers/EPLoginTypesViewController.swift b/YuMi/E-P/Login/Controllers/EPLoginTypesViewController.swift new file mode 100644 index 0000000..dc79bb2 --- /dev/null +++ b/YuMi/E-P/Login/Controllers/EPLoginTypesViewController.swift @@ -0,0 +1,693 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit + +class EPLoginTypesViewController: BaseViewController { + + // MARK: - Properties + + var displayType: EPLoginDisplayType = .id + + private let loginService = EPLoginService() + + private let backgroundImageView = UIImageView() + private let titleLabel = UILabel() + private let backButton = UIButton(type: .system) + + private let firstInputView = EPLoginInputView() + private let secondInputView = EPLoginInputView() + private var thirdInputView: EPLoginInputView? + + private let actionButton = UIButton(type: .system) + private var forgotPasswordButton: UIButton? + + private var hasAddedGradient = false + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + setupUI() + configureForDisplayType() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(true, animated: false) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + + if !hasAddedGradient && actionButton.bounds.width > 0 { + actionButton.addGradientBackground( + with: [ + EPLoginConfig.Colors.gradientStart, + EPLoginConfig.Colors.gradientEnd + ], + start: CGPoint(x: 0, y: 0.5), + end: CGPoint(x: 1, y: 0.5), + cornerRadius: EPLoginConfig.Layout.uniformCornerRadius + ) + hasAddedGradient = true + } + } + + // MARK: - Setup + + private func setupUI() { + setupBackground() + setupNavigationBar() + setupTitle() + setupInputViews() + setupActionButton() + } + + private func setupBackground() { + view.addSubview(backgroundImageView) + backgroundImageView.translatesAutoresizingMaskIntoConstraints = false + backgroundImageView.image = kImage(EPLoginConfig.Images.background) + backgroundImageView.contentMode = .scaleAspectFill + + backgroundImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + + private func setupNavigationBar() { + view.addSubview(backButton) + backButton.translatesAutoresizingMaskIntoConstraints = false + backButton.setImage(UIImage(systemName: EPLoginConfig.Images.iconBack), for: .normal) + backButton.tintColor = EPLoginConfig.Colors.textLight + backButton.addTarget(self, action: #selector(handleBack), for: .touchUpInside) + + backButton.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.compactHorizontalPadding) + make.top.equalTo(view.safeAreaLayoutGuide).offset(8) + make.size.equalTo(EPLoginConfig.Layout.backButtonSize) + } + } + + private func setupTitle() { + view.addSubview(titleLabel) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.font = .systemFont(ofSize: EPLoginConfig.Layout.titleFontSize, weight: .bold) + titleLabel.textColor = EPLoginConfig.Colors.textLight + + titleLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.centerY.equalTo(backButton) + } + } + + private func setupInputViews() { + firstInputView.translatesAutoresizingMaskIntoConstraints = false + secondInputView.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(firstInputView) + view.addSubview(secondInputView) + + firstInputView.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.uniformHorizontalPadding) + make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.uniformHorizontalPadding) + make.top.equalTo(titleLabel.snp.bottom).offset(EPLoginConfig.Layout.inputTitleSpacing) + make.height.equalTo(EPLoginConfig.Layout.uniformHeight) + } + + secondInputView.snp.makeConstraints { make in + make.leading.trailing.equalTo(firstInputView) + make.top.equalTo(firstInputView.snp.bottom).offset(EPLoginConfig.Layout.inputVerticalSpacing) + make.height.equalTo(EPLoginConfig.Layout.uniformHeight) + } + } + + private func setupActionButton() { + view.addSubview(actionButton) + actionButton.translatesAutoresizingMaskIntoConstraints = false + actionButton.setTitle("Login", for: .normal) + actionButton.setTitleColor(EPLoginConfig.Colors.textLight, for: .normal) + actionButton.layer.cornerRadius = EPLoginConfig.Layout.uniformCornerRadius + actionButton.titleLabel?.font = .systemFont(ofSize: EPLoginConfig.Layout.buttonFontSize, weight: .semibold) + actionButton.addTarget(self, action: #selector(handleAction), for: .touchUpInside) + + + actionButton.isEnabled = false + actionButton.alpha = 0.5 + + actionButton.snp.makeConstraints { make in + make.leading.trailing.equalTo(firstInputView) + make.top.equalTo(secondInputView.snp.bottom).offset(EPLoginConfig.Layout.buttonTopSpacing) + make.height.equalTo(EPLoginConfig.Layout.uniformHeight) + } + } + + // MARK: - Configuration + + private func configureForDisplayType() { + switch displayType { + case .id: + titleLabel.text = YMLocalizedString("1.0.37_text_26") + firstInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: false, + icon: "icon_login_id", + placeholder: "Please enter ID", + keyboardType: .numberPad + )) + firstInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + + secondInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: true, + icon: "icon_login_id", + placeholder: "Please enter password", + keyboardType: .default + )) + secondInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + + actionButton.setTitle("Login", for: .normal) + + + setupForgotPasswordButton() + + case .email: + titleLabel.text = YMLocalizedString("20.20.51_text_1") + firstInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: false, + icon: "envelope", + placeholder: "Please enter email", + keyboardType: .emailAddress + )) + firstInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + + secondInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: true, + isSecure: false, + icon: "number", + placeholder: "Please enter verification code", + keyboardType: .numberPad + )) + secondInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + secondInputView.delegate = self + actionButton.setTitle("Login", for: .normal) + + case .phone: + titleLabel.text = "Phone Login" + firstInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: false, + icon: "phone", + placeholder: "Please enter phone", + keyboardType: .numberPad + )) + firstInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + + secondInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: true, + isSecure: false, + icon: "number", + placeholder: "Please enter verification code", + keyboardType: .numberPad + )) + secondInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + secondInputView.delegate = self + actionButton.setTitle("Login", for: .normal) + + case .emailReset: + titleLabel.text = YMLocalizedString("20.20.51_text_20") + firstInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: false, + icon: "envelope", + placeholder: "Please enter email", + keyboardType: .emailAddress + )) + firstInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + + secondInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: true, + isSecure: false, + icon: "number", + placeholder: "Please enter verification code", + keyboardType: .numberPad + )) + secondInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + secondInputView.delegate = self + + + setupThirdInputView() + actionButton.setTitle("Confirm", for: .normal) + + case .phoneReset: + titleLabel.text = YMLocalizedString("20.20.51_text_20") + firstInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: false, + icon: "phone", + placeholder: "Please enter phone", + keyboardType: .numberPad + )) + firstInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + + secondInputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: true, + isSecure: false, + icon: "number", + placeholder: "Please enter verification code", + keyboardType: .numberPad + )) + secondInputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + secondInputView.delegate = self + + + setupThirdInputView() + actionButton.setTitle("Confirm", for: .normal) + } + } + + private func setupForgotPasswordButton() { + let button = UIButton(type: .system) + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle("Forgot Password?", for: .normal) + button.setTitleColor(EPLoginConfig.Colors.textLight, for: .normal) + button.titleLabel?.font = .systemFont(ofSize: EPLoginConfig.Layout.smallFontSize) + button.addTarget(self, action: #selector(handleForgotPassword), for: .touchUpInside) + + view.addSubview(button) + + button.snp.makeConstraints { make in + make.trailing.equalTo(secondInputView) + make.top.equalTo(secondInputView.snp.bottom).offset(8) + } + + forgotPasswordButton = button + } + + private func setupThirdInputView() { + let inputView = EPLoginInputView() + inputView.translatesAutoresizingMaskIntoConstraints = false + inputView.configure(with: EPLoginInputConfig( + showAreaCode: false, + showCodeButton: false, + isSecure: true, + icon: EPLoginConfig.Images.iconLock, + placeholder: "6-16 Digits + English Letters", + keyboardType: .default + )) + inputView.onTextChanged = { [weak self] _ in + self?.checkActionButtonStatus() + } + view.addSubview(inputView) + + inputView.snp.makeConstraints { make in + make.leading.trailing.equalTo(firstInputView) + make.top.equalTo(secondInputView.snp.bottom).offset(EPLoginConfig.Layout.inputVerticalSpacing) + make.height.equalTo(EPLoginConfig.Layout.uniformHeight) + } + + + actionButton.snp.remakeConstraints { make in + make.leading.trailing.equalTo(firstInputView) + make.top.equalTo(inputView.snp.bottom).offset(EPLoginConfig.Layout.buttonTopSpacing) + make.height.equalTo(EPLoginConfig.Layout.uniformHeight) + } + + thirdInputView = inputView + } + + // MARK: - Actions + + @objc private func handleBack() { + navigationController?.popViewController(animated: true) + } + + @objc private func handleAction() { + view.endEditing(true) + + + switch displayType { + case .id: + handleIDLogin() + case .email: + handleEmailLogin() + case .phone: + handlePhoneLogin() + case .emailReset: + handleEmailResetPassword() + case .phoneReset: + handlePhoneResetPassword() + } + } + + @objc private func handleForgotPassword() { + let vc = EPLoginTypesViewController() + vc.displayType = .emailReset + navigationController?.pushViewController(vc, animated: true) + } + + // MARK: - 登录逻辑 + + private func handleIDLogin() { + let id = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + let password = secondInputView.text + + + guard !id.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter0")) + return + } + + guard !password.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + + showLoading(true) + + loginService.loginWithID(id: id, password: password) { [weak self] (accountModel: AccountModel) in + DispatchQueue.main.async { + self?.showLoading(false) + print("[EPLogin] ID登录成功: \(accountModel.uid)") + self?.showSuccessToast(YMLocalizedString("XPLoginPhoneViewController1")) + EPLoginManager.jumpToHome(from: self!) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showErrorToast(msg) + } + } + } + + private func handleEmailLogin() { + let email = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + let code = secondInputView.text + + + guard !email.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter0")) + return + } + + guard !code.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + showLoading(true) + + loginService.loginWithEmail(email: email, code: code) { [weak self] (accountModel: AccountModel) in + DispatchQueue.main.async { + self?.showLoading(false) + print("[EPLogin] 邮箱登录成功: \(accountModel.uid)") + self?.showSuccessToast(YMLocalizedString("XPLoginPhoneViewController1")) + EPLoginManager.jumpToHome(from: self!) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showErrorToast(msg) + } + } + } + + private func handlePhoneLogin() { + let phone = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + let code = secondInputView.text + + + guard !phone.isEmpty else { + showErrorToast(YMLocalizedString("XPLoginPhoneViewController0")) + return + } + + guard !code.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + showLoading(true) + + loginService.loginWithPhone(phone: phone, code: code, areaCode: "+86") { [weak self] (accountModel: AccountModel) in + DispatchQueue.main.async { + self?.showLoading(false) + print("[EPLogin] 手机登录成功: \(accountModel.uid)") + self?.showSuccessToast(YMLocalizedString("XPLoginPhoneViewController1")) + EPLoginManager.jumpToHome(from: self!) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showErrorToast(msg) + } + } + } + + private func handleEmailResetPassword() { + guard let thirdInput = thirdInputView else { return } + + let email = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + let code = secondInputView.text + let newPassword = thirdInput.text + + + guard !email.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter0")) + return + } + + guard !code.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + guard !newPassword.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + showLoading(true) + + loginService.resetEmailPassword(email: email, code: code, newPassword: newPassword) { [weak self] in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showSuccessToast(YMLocalizedString("XPForgetPwdViewController1")) + self?.navigationController?.popViewController(animated: true) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showErrorToast(msg) + } + } + } + + private func handlePhoneResetPassword() { + guard let thirdInput = thirdInputView else { return } + + let phone = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + let code = secondInputView.text + let newPassword = thirdInput.text + + + guard !phone.isEmpty else { + showErrorToast(YMLocalizedString("XPLoginPhoneViewController0")) + return + } + + guard !code.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + guard !newPassword.isEmpty else { + showErrorToast(YMLocalizedString("LoginPresenter1")) + return + } + + showLoading(true) + + loginService.resetPhonePassword(phone: phone, code: code, areaCode: "+86", newPassword: newPassword) { [weak self] in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showSuccessToast(YMLocalizedString("XPForgetPwdViewController1")) + self?.navigationController?.popViewController(animated: true) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.showLoading(false) + self?.showErrorToast(msg) + } + } + } + + // MARK: - 验证码发送 + + private func sendEmailCode() { + let email = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + + + guard !email.isEmpty else { + secondInputView.stopCountdown() + return + } + + let type = (displayType == .emailReset) ? 2 : 1 + + loginService.sendEmailCode(email: email, type: type) { [weak self] in + DispatchQueue.main.async { + self?.secondInputView.startCountdown() + self?.secondInputView.displayKeyboard() + self?.showSuccessToast(YMLocalizedString("XPLoginPhoneViewController2")) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.secondInputView.stopCountdown() + self?.showErrorToast(msg) + } + } + } + + private func sendPhoneCode() { + let phone = firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) + + + guard !phone.isEmpty else { + showErrorToast(YMLocalizedString("XPLoginPhoneViewController0")) + secondInputView.stopCountdown() + return + } + + + loadCaptchaWebView { [weak self] in + guard let self = self else { return } + + let type = (self.displayType == .phoneReset) ? 2 : 1 + + self.loginService.sendPhoneCode(phone: phone, areaCode: "+86", type: type) { [weak self] in + DispatchQueue.main.async { + self?.secondInputView.startCountdown() + self?.secondInputView.displayKeyboard() + self?.showSuccessToast(YMLocalizedString("XPLoginPhoneViewController2")) + } + } failure: { [weak self] (code: Int, msg: String) in + DispatchQueue.main.async { + self?.secondInputView.stopCountdown() + self?.showErrorToast(msg) + } + } + } + } + + private func sendEmailResetCode() { + sendEmailCode() + } + + private func sendPhoneResetCode() { + sendPhoneCode() + } + + // MARK: - UI Helpers + + private func showLoading(_ show: Bool) { + if show { + actionButton.isEnabled = false + actionButton.alpha = 0.5 + actionButton.setTitle("Loading...", for: .normal) + } else { + switch displayType { + case .id, .email, .phone: + actionButton.setTitle("Login", for: .normal) + case .emailReset, .phoneReset: + actionButton.setTitle("Confirm", for: .normal) + } + checkActionButtonStatus() + } + } + + + private func checkActionButtonStatus() { + let isEnabled: Bool + + switch displayType { + case .id: + let hasId = !firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + let hasPassword = !secondInputView.text.isEmpty + isEnabled = hasId && hasPassword + + case .email, .phone: + let hasAccount = !firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + let hasCode = !secondInputView.text.isEmpty + isEnabled = hasAccount && hasCode + + case .emailReset, .phoneReset: + let hasAccount = !firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + let hasCode = !secondInputView.text.isEmpty + let hasPassword = !(thirdInputView?.text.isEmpty ?? true) + isEnabled = hasAccount && hasCode && hasPassword + } + + actionButton.isEnabled = isEnabled + actionButton.alpha = isEnabled ? 1.0 : 0.5 + } + + + private func loadCaptchaWebView(completion: @escaping () -> Void) { + completion() + } +} + +// MARK: - EPLoginInputViewDelegate + +extension EPLoginTypesViewController: EPLoginInputViewDelegate { + func inputViewDidRequestCode(_ inputView: EPLoginInputView) { + if inputView == secondInputView { + if displayType == .email || displayType == .emailReset { + sendEmailCode() + } else if displayType == .phone || displayType == .phoneReset { + sendPhoneCode() + } + } + } + + func inputViewDidSelectArea(_ inputView: EPLoginInputView) { + + print("[EPLogin] Area selection - 占位,Phase 2 实现") + } +} diff --git a/YuMi/E-P/NewLogin/Controllers/EPLoginTypesViewController.swift b/YuMi/E-P/Login/Controllers/EPLoginTypesViewController.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Controllers/EPLoginTypesViewController.swift rename to YuMi/E-P/Login/Controllers/EPLoginTypesViewController.swift.backup diff --git a/YuMi/E-P/Login/Controllers/EPLoginViewController.swift b/YuMi/E-P/Login/Controllers/EPLoginViewController.swift new file mode 100644 index 0000000..4c41415 --- /dev/null +++ b/YuMi/E-P/Login/Controllers/EPLoginViewController.swift @@ -0,0 +1,305 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit + +@objc class EPLoginViewController: UIViewController { + + // MARK: - Properties + + private let backgroundImageView = UIImageView() + private let logoImageView = UIImageView() + private let epartiTitleLabel = UILabel() + + private let idLoginButton = EPLoginButton() + private let emailLoginButton = EPLoginButton() + + private let agreeCheckbox = UIButton(type: .custom) + private let policyLabel = EPPolicyLabel() + + private let feedbackButton = UIButton(type: .custom) + + #if DEBUG + private let debugButton = UIButton(type: .custom) + #endif + + private let policySelectedKey = EPLoginConfig.Keys.policyAgreed + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + + // 验证 DEBUG 编译条件 + #if DEBUG + print("✅ [EPLogin] DEBUG 模式已激活") + #else + print("⚠️ [EPLogin] 当前为 Release 模式") + #endif + + navigationController?.setNavigationBarHidden(true, animated: false) + setupUI() + loadPolicyStatus() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(true, animated: false) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + } + + // MARK: - Setup + + private func setupUI() { + setupBackground() + setupLogo() + setupLoginButtons() + setupPolicyArea() + setupNavigationBar() + } + + private func setupBackground() { + view.addSubview(backgroundImageView) + backgroundImageView.image = kImage(EPLoginConfig.Images.background) + backgroundImageView.contentMode = .scaleAspectFill + + backgroundImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + + private func setupLogo() { + view.addSubview(logoImageView) + logoImageView.image = kImage(EPLoginConfig.Images.loginBg) + + logoImageView.snp.makeConstraints { make in + make.top.leading.trailing.equalTo(view) + make.height.equalTo(EPLoginConfig.Layout.logoHeight) + } + + + view.addSubview(epartiTitleLabel) + epartiTitleLabel.text = "E-PARTY" + epartiTitleLabel.font = .systemFont(ofSize: EPLoginConfig.Layout.epartiTitleFontSize, weight: .bold) + epartiTitleLabel.textColor = EPLoginConfig.Colors.textLight + epartiTitleLabel.transform = CGAffineTransform(a: 1, b: 0, c: -0.2, d: 1, tx: 0, ty: 0) + + epartiTitleLabel.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.epartiTitleLeading) + make.bottom.equalTo(logoImageView.snp.bottom).offset(EPLoginConfig.Layout.epartiTitleBottomOffset) + } + } + + private func setupLoginButtons() { + + idLoginButton.configure( + icon: EPLoginConfig.Images.iconLoginId, + title: YMLocalizedString(EPLoginConfig.LocalizedKeys.idLogin) + ) + idLoginButton.delegate = self + + emailLoginButton.configure( + icon: EPLoginConfig.Images.iconLoginEmail, + title: YMLocalizedString(EPLoginConfig.LocalizedKeys.emailLogin) + ) + emailLoginButton.delegate = self + + + let stackView = UIStackView(arrangedSubviews: [idLoginButton, emailLoginButton]) + stackView.axis = .vertical + stackView.spacing = EPLoginConfig.Layout.loginButtonSpacing + stackView.distribution = .fillEqually + view.addSubview(stackView) + + stackView.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.loginButtonHorizontalPadding) + make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.loginButtonHorizontalPadding) + make.top.equalTo(logoImageView.snp.bottom) + } + + idLoginButton.snp.makeConstraints { make in + make.height.equalTo(EPLoginConfig.Layout.loginButtonHeight) + } + + emailLoginButton.snp.makeConstraints { make in + make.height.equalTo(EPLoginConfig.Layout.loginButtonHeight) + } + } + + private func setupPolicyArea() { + view.addSubview(agreeCheckbox) + view.addSubview(policyLabel) + + agreeCheckbox.setImage(kImage("login_privace_select"), for: .selected) + agreeCheckbox.setImage(kImage("login_privace_unselect"), for: .normal) + agreeCheckbox.addTarget(self, action: #selector(togglePolicyCheckbox), for: .touchUpInside) + + policyLabel.onUserAgreementTapped = { [weak self] in + print("[EPLogin] User agreement tapped callback triggered") + let url = self?.getUserAgreementURL() ?? "" + print("[EPLogin] User agreement URL: \(url)") + self?.openPolicyInExternalBrowser(url) + } + policyLabel.onPrivacyPolicyTapped = { [weak self] in + print("[EPLogin] Privacy policy tapped callback triggered") + let url = self?.getPrivacyPolicyURL() ?? "" + print("[EPLogin] Privacy policy URL: \(url)") + self?.openPolicyInExternalBrowser(url) + } + + agreeCheckbox.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.horizontalPadding) + make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-30) + make.size.equalTo(EPLoginConfig.Layout.checkboxSize) + } + + policyLabel.snp.makeConstraints { make in + make.leading.equalTo(agreeCheckbox.snp.trailing).offset(8) + make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.horizontalPadding) + make.centerY.equalTo(agreeCheckbox) + } + } + + private func setupNavigationBar() { +#if DEBUG + view.addSubview(feedbackButton) + feedbackButton.setTitle(YMLocalizedString(EPLoginConfig.LocalizedKeys.feedback), for: .normal) + feedbackButton.titleLabel?.font = .systemFont(ofSize: EPLoginConfig.Layout.smallFontSize) + feedbackButton.backgroundColor = EPLoginConfig.Colors.backgroundTransparent + feedbackButton.layer.cornerRadius = EPLoginConfig.Layout.feedbackButtonCornerRadius + feedbackButton.addTarget(self, action: #selector(handleFeedback), for: .touchUpInside) + + feedbackButton.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.compactHorizontalPadding) + make.top.equalTo(view.safeAreaLayoutGuide).offset(8) + make.height.equalTo(EPLoginConfig.Layout.feedbackButtonHeight) + } + + view.addSubview(debugButton) + debugButton.setTitle("切换环境", for: .normal) + debugButton.setTitleColor(.blue, for: .normal) + debugButton.addTarget(self, action: #selector(handleDebug), for: .touchUpInside) + + debugButton.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.compactHorizontalPadding) + make.top.equalTo(view.safeAreaLayoutGuide).offset(8) + } +#endif // DEBUG + } + + // MARK: - Actions + + private func handleIDLogin() { + let vc = EPLoginTypesViewController() + vc.displayType = .id + navigationController?.pushViewController(vc, animated: true) + } + + private func handleEmailLogin() { + let vc = EPLoginTypesViewController() + vc.displayType = .email + navigationController?.pushViewController(vc, animated: true) + } + + @objc private func togglePolicyCheckbox() { + agreeCheckbox.isSelected.toggle() + UserDefaults.standard.set(agreeCheckbox.isSelected, forKey: policySelectedKey) + } + + @objc private func handleFeedback() { + print("[EPLogin] Feedback - 占位,Phase 2 实现") + } + + #if DEBUG + @objc private func handleDebug() { + print("[EPLogin] Debug - 占位,Phase 2 实现") + } + #endif + + private func openPolicyInExternalBrowser(_ urlString: String) { + print("[EPLogin] Original URL: \(urlString)") + + + var fullUrl = urlString + if !urlString.hasPrefix("http") && !urlString.hasPrefix("https") { + let hostUrl = HttpRequestHelper.getHostUrl() + fullUrl = "\(hostUrl)/\(urlString)" + print("[EPLogin] Added host URL, full URL: \(fullUrl)") + } + + print("[EPLogin] Opening URL in external browser: \(fullUrl)") + + guard let url = URL(string: fullUrl) else { + print("[EPLogin] ❌ Invalid URL: \(fullUrl)") + return + } + + print("[EPLogin] URL object created: \(url)") + + + if UIApplication.shared.canOpenURL(url) { + print("[EPLogin] ✅ Can open URL, attempting to open...") + UIApplication.shared.open(url, options: [:]) { success in + print("[EPLogin] Open external browser: \(success ? "✅ Success" : "❌ Failed")") + } + } else { + print("[EPLogin] ❌ Cannot open URL: \(fullUrl)") + } + } + + // MARK: - Helpers + + private func loadPolicyStatus() { + agreeCheckbox.isSelected = UserDefaults.standard.bool(forKey: policySelectedKey) + + if !UserDefaults.standard.bool(forKey: EPLoginConfig.Keys.hasLaunchedBefore) { + agreeCheckbox.isSelected = true + UserDefaults.standard.set(true, forKey: policySelectedKey) + UserDefaults.standard.set(true, forKey: EPLoginConfig.Keys.hasLaunchedBefore) + } + } + + + private func getUserAgreementURL() -> String { + + let url = URLWithType(URLType(rawValue: 4)!) as String + print("[EPLogin] User agreement URL from URLWithType: \(url)") + return url + } + + + private func getPrivacyPolicyURL() -> String { + + let url = URLWithType(URLType(rawValue: 0)!) as String + print("[EPLogin] Privacy policy URL from URLWithType: \(url)") + return url + } + + private func checkPolicyAgreed() -> Bool { + if !agreeCheckbox.isSelected { + + print("[EPLogin] Please agree to policy first") + return false + } + return true + } +} + +// MARK: - EPLoginButtonDelegate + +extension EPLoginViewController: EPLoginButtonDelegate { + func loginButtonDidTap(_ button: EPLoginButton) { + guard checkPolicyAgreed() else { return } + + if button == idLoginButton { + handleIDLogin() + } else if button == emailLoginButton { + handleEmailLogin() + } + } +} diff --git a/YuMi/E-P/NewLogin/Controllers/EPLoginViewController.swift b/YuMi/E-P/Login/Controllers/EPLoginViewController.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Controllers/EPLoginViewController.swift rename to YuMi/E-P/Login/Controllers/EPLoginViewController.swift.backup diff --git a/YuMi/E-P/Login/Models/EPLoginBridge.swift b/YuMi/E-P/Login/Models/EPLoginBridge.swift new file mode 100644 index 0000000..f016a7c --- /dev/null +++ b/YuMi/E-P/Login/Models/EPLoginBridge.swift @@ -0,0 +1,30 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit + + +func kImage(_ name: String) -> UIImage? { + return UIImage(named: name) +} + + +func YMLocalizedString(_ key: String) -> String { + return Bundle.ymLocalizedString(forKey: key) +} + + +extension URLType { + static var captchaSwitch: URLType { + return URLType(rawValue: 113)! + } +} + + +func encryptDES(_ plainText: String) -> String { + + let key = "1ea53d260ecf11e7b56e00163e046a26" + return DESEncrypt.encryptUseDES(plainText, key: key) ?? plainText +} diff --git a/YuMi/E-P/NewLogin/Models/EPLoginBridge.swift b/YuMi/E-P/Login/Models/EPLoginBridge.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Models/EPLoginBridge.swift rename to YuMi/E-P/Login/Models/EPLoginBridge.swift.backup diff --git a/YuMi/E-P/Login/Models/EPLoginConfig.swift b/YuMi/E-P/Login/Models/EPLoginConfig.swift new file mode 100644 index 0000000..918c871 --- /dev/null +++ b/YuMi/E-P/Login/Models/EPLoginConfig.swift @@ -0,0 +1,302 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit + + +struct EPLoginConfig { + + // MARK: - Layout 布局尺寸 + + struct Layout { + + static let buttonWidth: CGFloat = 294 + + static let buttonHeight: CGFloat = 46 + + static let loginButtonHeight: CGFloat = 56 + + static let loginButtonSpacing: CGFloat = 24 + + static let loginButtonHorizontalPadding: CGFloat = 30 + + + static let uniformHeight: CGFloat = 56 + + static let uniformHorizontalPadding: CGFloat = 29 + + static let uniformCornerRadius: CGFloat = 28 + + static let cornerRadius: CGFloat = 23 + + + static let logoHeight: CGFloat = 400 + + static let logoTopOffset: CGFloat = 80 + + + static let epartiTitleFontSize: CGFloat = 56 + + static let epartiTitleLeading: CGFloat = 40 + + static let epartiTitleBottomOffset: CGFloat = -30 + + + static let inputVerticalSpacing: CGFloat = 16 + + static let inputTitleSpacing: CGFloat = 60 + + + static let buttonTopSpacing: CGFloat = 40 + + + static let horizontalPadding: CGFloat = 40 + + static let compactHorizontalPadding: CGFloat = 16 + + + static let titleFontSize: CGFloat = 28 + + static let buttonFontSize: CGFloat = 16 + + static let inputFontSize: CGFloat = 14 + + static let smallFontSize: CGFloat = 12 + + + static let iconSize: CGFloat = 24 + + static let loginButtonIconSize: CGFloat = 30 + + static let loginButtonIconLeading: CGFloat = 33 + + static let iconLeading: CGFloat = 15 + + static let iconTextSpacing: CGFloat = 12 + + + static let checkboxSize: CGFloat = 18 + + + static let backButtonSize: CGFloat = 44 + + + static let feedbackButtonHeight: CGFloat = 22 + static let feedbackButtonCornerRadius: CGFloat = 10.5 + + + static let inputHeight: CGFloat = 56 + + static let inputCornerRadius: CGFloat = 28 + + static let inputHorizontalPadding: CGFloat = 24 + + static let inputIconSize: CGFloat = 20 + + static let inputBorderWidth: CGFloat = 1 + + + static let codeButtonWidth: CGFloat = 102 + + static let codeButtonHeight: CGFloat = 38 + } + + // MARK: - Colors 颜色主题 + + struct Colors { + + static let primary = UIColor.systemPurple + + + static let background = UIColor.white + static let backgroundTransparent = UIColor.white.withAlphaComponent(0.5) + + + static let text = UIColor.darkText + static let textSecondary = UIColor.darkGray + static let textLight = UIColor.white + + + static let icon = UIColor.darkGray + static let iconDisabled = UIColor.gray + + + static let inputBackground = UIColor.white.withAlphaComponent(0.1) + static let inputText = UIColor(red: 0x1F/255.0, green: 0x1B/255.0, blue: 0x4F/255.0, alpha: 1.0) + static let inputBorder = UIColor.white + static let inputBorderFocused = UIColor.systemPurple + + + static let gradientStart = UIColor(red: 0xF8/255.0, green: 0x54/255.0, blue: 0xFC/255.0, alpha: 1.0) + static let gradientEnd = UIColor(red: 0x50/255.0, green: 0x0F/255.0, blue: 0xFF/255.0, alpha: 1.0) + + + static let codeButtonBackground = UIColor(red: 0x91/255.0, green: 0x68/255.0, blue: 0xFA/255.0, alpha: 1.0) + + + static let buttonEnabled = UIColor.systemPurple + static let buttonDisabled = UIColor.lightGray + + + static let error = UIColor.systemRed + static let success = UIColor.systemGreen + + + static let link = UIColor.black + static let linkUnderline = UIColor.black + } + + // MARK: - Animation 动画配置 + + struct Animation { + + static let duration: TimeInterval = 0.3 + + static let shortDuration: TimeInterval = 0.15 + + static let longDuration: TimeInterval = 0.5 + + + static let springDamping: CGFloat = 0.75 + + static let springVelocity: CGFloat = 0.5 + + + static let buttonPressScale: CGFloat = 0.95 + + + static let shakeOffset: CGFloat = 10 + + static let shakeCount: Int = 3 + } + + // MARK: - Validation 验证规则 + + struct Validation { + + static let passwordMinLength = 6 + + static let passwordMaxLength = 16 + + + static let codeLength = 6 + + + static let phoneMinLength = 10 + + static let phoneMaxLength = 15 + + + static let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}" + + static let phoneRegex = "^[0-9]{10,15}$" + } + + // MARK: - Timing 时间配置 + + struct Timing { + + static let codeCountdownSeconds = 60 + + + static let toastDuration: TimeInterval = 2.0 + + + static let requestTimeout: TimeInterval = 30.0 + } + + // MARK: - API 接口配置 + + struct API { + + static let clientSecret = "uyzjdhds" + + static let clientId = "erban-client" + + static let grantType = "password" + + static let version = "1" + + + static let codeTypeLogin = 1 + + static let codeTypeReset = 2 + } + + // MARK: - UserDefaults Keys + + struct Keys { + + static let policyAgreed = "HadAgreePrivacy" + + static let hasLaunchedBefore = "HasLaunchedBefore" + } + + // MARK: - Images 图片资源名称 + + struct Images { + + static let background = "vc_bg" + + static let loginBg = "login_bg" + + + static let iconLoginId = "icon_login_id" + + static let iconLoginEmail = "icon_login_email" + + + static let iconPerson = "person.circle" + static let iconPersonFill = "person" + + static let iconEmail = "envelope.circle" + static let iconEmailFill = "envelope" + + static let iconPhone = "phone.circle" + static let iconPhoneFill = "phone" + + static let iconApple = "apple.logo" + + static let iconLock = "lock" + + static let iconNumber = "number" + + + static let iconPasswordSee = "icon_password_see" + static let iconPasswordUnsee = "icon_password_unsee" + + + static let iconBack = "chevron.left" + + static let iconEyeSlash = "eye.slash" + + static let iconEye = "eye" + + + static let checkboxEmpty = "circle" + + static let checkboxFilled = "checkmark.circle" + } + + // MARK: - Localized Strings Keys + + struct LocalizedKeys { + + static let idLogin = "1.0.37_text_26" + + static let emailLogin = "20.20.51_text_1" + + + static let policyFullText = "XPLoginViewController6" + + static let userAgreement = "XPLoginViewController7" + + static let privacyPolicy = "XPLoginViewController9" + + + static let feedback = "XPMineFeedbackViewController0" + } +} + diff --git a/YuMi/E-P/NewLogin/Models/EPLoginConfig.swift b/YuMi/E-P/Login/Models/EPLoginConfig.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Models/EPLoginConfig.swift rename to YuMi/E-P/Login/Models/EPLoginConfig.swift.backup diff --git a/YuMi/E-P/Login/Models/EPLoginState.swift b/YuMi/E-P/Login/Models/EPLoginState.swift new file mode 100644 index 0000000..8281d10 --- /dev/null +++ b/YuMi/E-P/Login/Models/EPLoginState.swift @@ -0,0 +1,50 @@ + + +// Created by AI on 2025-01-27. + + +import Foundation + + +enum EPLoginDisplayType { + case id + case email + case phone + case emailReset + case phoneReset +} + + +class EPLoginValidator { + + + func validatePassword(_ password: String) -> Bool { + guard password.count >= 6 && password.count <= 16 else { return false } + + let hasLetter = password.rangeOfCharacter(from: .letters) != nil + let hasDigit = password.rangeOfCharacter(from: .decimalDigits) != nil + + return hasLetter && hasDigit + } + + + func validateEmail(_ email: String) -> Bool { + let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}" + let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex) + return emailPredicate.evaluate(with: email) + } + + + func validateCode(_ code: String) -> Bool { + guard code.count == 6 else { return false } + return code.allSatisfy { $0.isNumber } + } + + + func validatePhone(_ phone: String) -> Bool { + let phoneRegex = "^[0-9]{10,15}$" + let phonePredicate = NSPredicate(format: "SELF MATCHES %@", phoneRegex) + return phonePredicate.evaluate(with: phone) + } +} + diff --git a/YuMi/E-P/NewLogin/Models/EPLoginState.swift b/YuMi/E-P/Login/Models/EPLoginState.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Models/EPLoginState.swift rename to YuMi/E-P/Login/Models/EPLoginState.swift.backup diff --git a/YuMi/E-P/Login/Services/EPLoginManager.swift b/YuMi/E-P/Login/Services/EPLoginManager.swift new file mode 100644 index 0000000..8886a05 --- /dev/null +++ b/YuMi/E-P/Login/Services/EPLoginManager.swift @@ -0,0 +1,135 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit + + +@objc class EPLoginManager: NSObject { + + // MARK: - Login Success Navigation + + + static func jumpToHome(from viewController: UIViewController) { + + + guard let accountModel = AccountInfoStorage.instance().getCurrentAccountInfo() else { + print("[EPLoginManager] 账号信息不完整,无法继续") + return + } + + let accessToken = accountModel.access_token + guard !accessToken.isEmpty else { + print("[EPLoginManager] access_token 为空,无法继续") + return + } + + + let loginService = EPLoginService() + loginService.requestTicket(accessToken: accessToken) { ticket in + + + AccountInfoStorage.instance().saveTicket(ticket) + + + DispatchQueue.main.async { + let epTabBar = EPTabBarController.create() + epTabBar.refreshTabBarWithIsLogin(true) + + + if let window = getKeyWindow() { + window.rootViewController = epTabBar + window.makeKeyAndVisible() + + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { + Self.checkAndShowSignatureColorGuide(in: window) + } + } + + print("[EPLoginManager] 登录成功,已切换到 EPTabBarController") + } + + } failure: { code, msg in + print("[EPLoginManager] 请求 Ticket 失败: \(code) - \(msg)") + + + DispatchQueue.main.async { + let epTabBar = EPTabBarController.create() + epTabBar.refreshTabBarWithIsLogin(true) + + if let window = getKeyWindow() { + window.rootViewController = epTabBar + window.makeKeyAndVisible() + + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { + Self.checkAndShowSignatureColorGuide(in: window) + } + } + + print("[EPLoginManager] Ticket 请求失败,仍跳转到首页") + } + } + } + + + static func loginWithApple(from viewController: UIViewController) { + print("[EPLoginManager] Apple Login - 占位,Phase 2 实现") + + } + + // MARK: - Helper Methods + + + private static func getKeyWindow() -> UIWindow? { + if #available(iOS 13.0, *) { + for windowScene in UIApplication.shared.connectedScenes { + if let windowScene = windowScene as? UIWindowScene, + windowScene.activationState == .foregroundActive { + for window in windowScene.windows { + if window.isKeyWindow { + return window + } + } + + return windowScene.windows.first + } + } + } else { + + return UIApplication.shared.keyWindow + } + return nil + } + + + private static func checkAndShowSignatureColorGuide(in window: UIWindow) { + let hasSignatureColor = EPEmotionColorStorage.hasUserSignatureColor() + +// #if DEBUG + print("[EPLoginManager] Debug 模式:显示专属颜色引导页(已有颜色: \(hasSignatureColor))") + + let guideView = EPSignatureColorGuideView() + + + guideView.onColorConfirmed = { (hexColor: String) in + EPEmotionColorStorage.saveUserSignatureColor(hexColor) + print("[EPLoginManager] 用户选择专属颜色: \(hexColor)") + } + + + if hasSignatureColor { + guideView.onSkipTapped = { + print("[EPLoginManager] 用户跳过专属颜色选择") + } + } + + + guideView.show(in: window, showSkipButton: hasSignatureColor) + + + } +} + diff --git a/YuMi/E-P/NewLogin/Services/EPLoginManager.swift b/YuMi/E-P/Login/Services/EPLoginManager.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Services/EPLoginManager.swift rename to YuMi/E-P/Login/Services/EPLoginManager.swift.backup diff --git a/YuMi/E-P/Login/Services/EPLoginService.swift b/YuMi/E-P/Login/Services/EPLoginService.swift new file mode 100644 index 0000000..bd80528 --- /dev/null +++ b/YuMi/E-P/Login/Services/EPLoginService.swift @@ -0,0 +1,246 @@ + + +// Created by AI on 2025-01-27. + + +import Foundation + + +@objc class EPLoginService: NSObject { + + // MARK: - Constants + + private let clientSecret = EPLoginConfig.API.clientSecret + private let clientId = EPLoginConfig.API.clientId + private let version = EPLoginConfig.API.version + + // MARK: - Private Helper Methods + + + private func parseAndSaveAccount(data: BaseModel?, + code: Int64, + completion: @escaping (AccountModel) -> Void, + failure: @escaping (Int, String) -> Void) { + if code == 200 { + if let accountDict = data?.data as? NSDictionary, + let accountModel = AccountModel.mj_object(withKeyValues: accountDict) { + + AccountInfoStorage.instance().saveAccountInfo(accountModel) + completion(accountModel) + } else { + failure(Int(code), YMLocalizedString("error.account_parse_failed")) + } + } else { + failure(Int(code), YMLocalizedString("error.operation_failed")) + } + } + + // MARK: - Request Ticket + + + @objc func requestTicket(accessToken: String, + completion: @escaping (String) -> Void, + failure: @escaping (Int, String) -> Void) { + + Api.requestTicket({ (data, code, msg) in + if code == 200, let dict = data?.data as? NSDictionary { + if let tickets = dict["tickets"] as? NSArray, + let firstTicket = tickets.firstObject as? NSDictionary, + let ticket = firstTicket["ticket"] as? String { + completion(ticket) + } else { + failure(Int(code), YMLocalizedString("error.ticket_parse_failed")) + } + } else { + failure(Int(code), msg ?? YMLocalizedString("error.request_ticket_failed")) + } + }, access_token: accessToken, issue_type: "multi") + } + + // MARK: - Send Verification Code + + + @objc func sendEmailCode(email: String, + type: Int, + completion: @escaping () -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedEmail = encryptDES(email) + + Api.emailGetCode({ (data, code, msg) in + if code == 200 { + completion() + } else { + failure(Int(code), msg ?? YMLocalizedString("error.send_email_code_failed")) + } + }, emailAddress: encryptedEmail, type: NSNumber(value: type)) + } + + + @objc func sendPhoneCode(phone: String, + areaCode: String, + type: Int, + completion: @escaping () -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedPhone = encryptDES(phone) + + Api.phoneSmsCode({ (data, code, msg) in + if code == 200 { + completion() + } else { + failure(Int(code), msg ?? YMLocalizedString("error.send_phone_code_failed")) + } + }, mobile: encryptedPhone, type: String(type), phoneAreaCode: areaCode) + } + + // MARK: - Login Methods + + + @objc func loginWithID(id: String, + password: String, + completion: @escaping (AccountModel) -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedId = encryptDES(id) + let encryptedPassword = encryptDES(password) + + Api.login(password: { [weak self] (data, code, msg) in + self?.parseAndSaveAccount( + data: data, + code: Int64(code), + completion: completion, + failure: { errorCode, _ in + failure(errorCode, msg ?? YMLocalizedString("error.login_failed")) + }) + }, + phone: encryptedId, + password: encryptedPassword, + client_secret: clientSecret, + version: version, + client_id: clientId, + grant_type: "password") + } + + + @objc func loginWithEmail(email: String, + code: String, + completion: @escaping (AccountModel) -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedEmail = encryptDES(email) + + Api.login(code: { [weak self] (data, code, msg) in + self?.parseAndSaveAccount( + data: data, + code: Int64(code), + completion: completion, + failure: { errorCode, _ in + failure(errorCode, msg ?? YMLocalizedString("error.login_failed")) + }) + }, + email: encryptedEmail, + code: code, + client_secret: clientSecret, + version: version, + client_id: clientId, + grant_type: "email") + } + + + @objc func loginWithPhone(phone: String, + code: String, + areaCode: String, + completion: @escaping (AccountModel) -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedPhone = encryptDES(phone) + + Api.login(code: { [weak self] (data, code, msg) in + self?.parseAndSaveAccount( + data: data, + code: Int64(code), + completion: completion, + failure: { errorCode, _ in + failure(errorCode, msg ?? YMLocalizedString("error.login_failed")) + }) + }, + phone: encryptedPhone, + code: code, + client_secret: clientSecret, + version: version, + client_id: clientId, + grant_type: "password", + phoneAreaCode: areaCode) + } + + // MARK: - Reset Password + + + @objc func resetEmailPassword(email: String, + code: String, + newPassword: String, + completion: @escaping () -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedEmail = encryptDES(email) + let encryptedPassword = encryptDES(newPassword) + + Api.resetPassword(email: { (data, code, msg) in + if code == 200 { + completion() + } else { + failure(Int(code), msg ?? YMLocalizedString("error.reset_password_failed")) + } + }, email: encryptedEmail, newPwd: encryptedPassword, code: code) + } + + + @objc func resetPhonePassword(phone: String, + code: String, + areaCode: String, + newPassword: String, + completion: @escaping () -> Void, + failure: @escaping (Int, String) -> Void) { + + + let encryptedPhone = encryptDES(phone) + let encryptedPassword = encryptDES(newPassword) + + Api.resetPassword(phone: { (data, code, msg) in + if code == 200 { + completion() + } else { + failure(Int(code), msg ?? YMLocalizedString("error.reset_password_failed")) + } + }, phone: encryptedPhone, newPwd: encryptedPassword, smsCode: code, phoneAreaCode: areaCode) + } + + // MARK: - Phone Quick Login (保留接口) + + + @objc func phoneQuickLogin(accessToken: String, + token: String, + completion: @escaping (AccountModel) -> Void, + failure: @escaping (Int, String) -> Void) { + + Api.phoneQuickLogin({ [weak self] (data, code, msg) in + self?.parseAndSaveAccount( + data: data, + code: Int64(code), + completion: completion, + failure: { errorCode, _ in + failure(errorCode, msg ?? YMLocalizedString("error.quick_login_failed")) + }) + }, + accessToken: accessToken, + token: token) + } +} + diff --git a/YuMi/E-P/NewLogin/Services/EPLoginService.swift b/YuMi/E-P/Login/Services/EPLoginService.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Services/EPLoginService.swift rename to YuMi/E-P/Login/Services/EPLoginService.swift.backup diff --git a/YuMi/E-P/Login/Views/EPLoginButton.swift b/YuMi/E-P/Login/Views/EPLoginButton.swift new file mode 100644 index 0000000..72ecd49 --- /dev/null +++ b/YuMi/E-P/Login/Views/EPLoginButton.swift @@ -0,0 +1,125 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit +import SnapKit + + +protocol EPLoginButtonDelegate: AnyObject { + func loginButtonDidTap(_ button: EPLoginButton) +} + + +class EPLoginButton: UIControl { + + // MARK: - Properties + + weak var delegate: EPLoginButtonDelegate? + + private let stackView = UIStackView() + private let iconImageView = UIImageView() + private let titleLabel = UILabel() + private let leftSpacer = UIView() + private let rightSpacer = UIView() + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Setup + + private func setupUI() { + backgroundColor = EPLoginConfig.Colors.background + layer.cornerRadius = EPLoginConfig.Layout.cornerRadius + + + stackView.axis = .horizontal + stackView.alignment = .center + stackView.distribution = .fill + stackView.spacing = 0 + stackView.isUserInteractionEnabled = false + addSubview(stackView) + + + iconImageView.contentMode = .scaleAspectFit + + + titleLabel.font = .systemFont(ofSize: EPLoginConfig.Layout.inputFontSize, weight: .semibold) + titleLabel.textColor = EPLoginConfig.Colors.text + titleLabel.textAlignment = .center + + + leftSpacer.setContentHuggingPriority(.defaultLow, for: .horizontal) + rightSpacer.setContentHuggingPriority(.defaultLow, for: .horizontal) + + + let leadingPadding = UIView() + let trailingPadding = UIView() + + stackView.addArrangedSubview(leadingPadding) + stackView.addArrangedSubview(iconImageView) + stackView.addArrangedSubview(leftSpacer) + stackView.addArrangedSubview(titleLabel) + stackView.addArrangedSubview(rightSpacer) + stackView.addArrangedSubview(trailingPadding) + + + stackView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + leadingPadding.snp.makeConstraints { make in + make.width.equalTo(EPLoginConfig.Layout.loginButtonIconLeading) + } + + iconImageView.snp.makeConstraints { make in + make.size.equalTo(EPLoginConfig.Layout.loginButtonIconSize) + } + + trailingPadding.snp.makeConstraints { make in + make.width.equalTo(EPLoginConfig.Layout.loginButtonIconLeading) + } + + + leftSpacer.snp.makeConstraints { make in + make.width.equalTo(rightSpacer) + } + + + addTarget(self, action: #selector(handleTap), for: .touchUpInside) + } + + // MARK: - Configuration + + + func configure(icon: String, title: String) { + iconImageView.image = kImage(icon) + titleLabel.text = title + } + + // MARK: - Actions + + @objc private func handleTap() { + delegate?.loginButtonDidTap(self) + } + + // MARK: - Touch Feedback + + override var isHighlighted: Bool { + didSet { + UIView.animate(withDuration: 0.1) { + self.alpha = self.isHighlighted ? 0.7 : 1.0 + } + } + } +} + diff --git a/YuMi/E-P/NewLogin/Views/EPLoginButton.swift b/YuMi/E-P/Login/Views/EPLoginButton.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Views/EPLoginButton.swift rename to YuMi/E-P/Login/Views/EPLoginButton.swift.backup diff --git a/YuMi/E-P/Login/Views/EPLoginInputView.swift b/YuMi/E-P/Login/Views/EPLoginInputView.swift new file mode 100644 index 0000000..80d27ef --- /dev/null +++ b/YuMi/E-P/Login/Views/EPLoginInputView.swift @@ -0,0 +1,319 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit +import SnapKit + + +struct EPLoginInputConfig { + var showAreaCode: Bool = false + var showCodeButton: Bool = false + var isSecure: Bool = false + var icon: String? + var placeholder: String + var keyboardType: UIKeyboardType = .default +} + + +protocol EPLoginInputViewDelegate: AnyObject { + func inputViewDidRequestCode(_ inputView: EPLoginInputView) + func inputViewDidSelectArea(_ inputView: EPLoginInputView) +} + + +class EPLoginInputView: UIView { + + // MARK: - Properties + + weak var delegate: EPLoginInputViewDelegate? + + + var onTextChanged: ((String) -> Void)? + + private let stackView = UIStackView() + + + private let areaStackView = UIStackView() + private let areaCodeButton = UIButton(type: .custom) + private let areaArrowImageView = UIImageView() + private let areaTapButton = UIButton(type: .custom) + + + private let inputTextField = UITextField() + private let iconImageView = UIImageView() + + + private let eyeButton = UIButton(type: .custom) + + + private let codeButton = UIButton(type: .custom) + + + private var timer: DispatchSourceTimer? + private var countdownSeconds = 60 + private var isCountingDown = false + + + private var config: EPLoginInputConfig? + + + var text: String { + return inputTextField.text ?? "" + } + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + stopCountdown() + } + + // MARK: - Setup + + private func setupUI() { + backgroundColor = EPLoginConfig.Colors.inputBackground + layer.cornerRadius = EPLoginConfig.Layout.inputCornerRadius + layer.borderWidth = EPLoginConfig.Layout.inputBorderWidth + layer.borderColor = EPLoginConfig.Colors.inputBorder.cgColor + + + stackView.axis = .horizontal + stackView.alignment = .center + stackView.distribution = .fill + stackView.spacing = 8 + stackView.translatesAutoresizingMaskIntoConstraints = false + addSubview(stackView) + + setupAreaCodeView() + setupInputTextField() + setupEyeButton() + setupCodeButton() + + stackView.snp.makeConstraints { make in + make.leading.equalToSuperview().offset(EPLoginConfig.Layout.inputHorizontalPadding) + make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.inputHorizontalPadding) + make.top.bottom.equalToSuperview() + } + + + areaStackView.isHidden = true + eyeButton.isHidden = true + codeButton.isHidden = true + iconImageView.isHidden = true + } + + private func setupAreaCodeView() { + + areaStackView.axis = .horizontal + areaStackView.alignment = .center + areaStackView.distribution = .fill + areaStackView.spacing = 8 + areaStackView.translatesAutoresizingMaskIntoConstraints = false + + + areaCodeButton.setTitle("+86", for: .normal) + areaCodeButton.setTitleColor(EPLoginConfig.Colors.inputText, for: .normal) + areaCodeButton.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) + areaCodeButton.isUserInteractionEnabled = false + areaCodeButton.translatesAutoresizingMaskIntoConstraints = false + + + areaArrowImageView.image = kImage("login_area_arrow") + areaArrowImageView.contentMode = .scaleAspectFit + areaArrowImageView.isUserInteractionEnabled = false + areaArrowImageView.translatesAutoresizingMaskIntoConstraints = false + + + areaTapButton.translatesAutoresizingMaskIntoConstraints = false + areaTapButton.addTarget(self, action: #selector(handleAreaTap), for: .touchUpInside) + + areaStackView.addSubview(areaTapButton) + areaStackView.addArrangedSubview(areaCodeButton) + areaStackView.addArrangedSubview(areaArrowImageView) + + stackView.addArrangedSubview(areaStackView) + + areaTapButton.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + areaCodeButton.snp.makeConstraints { make in + make.width.lessThanOrEqualTo(60) + } + + areaArrowImageView.snp.makeConstraints { make in + make.width.equalTo(12) + make.height.equalTo(8) + } + } + + private func setupInputTextField() { + + iconImageView.contentMode = .scaleAspectFit + iconImageView.tintColor = EPLoginConfig.Colors.icon + iconImageView.translatesAutoresizingMaskIntoConstraints = false + stackView.addArrangedSubview(iconImageView) + + iconImageView.snp.makeConstraints { make in + make.size.equalTo(EPLoginConfig.Layout.inputIconSize) + } + + + inputTextField.textColor = EPLoginConfig.Colors.textLight + inputTextField.font = .systemFont(ofSize: 14) + inputTextField.tintColor = EPLoginConfig.Colors.textLight + inputTextField.translatesAutoresizingMaskIntoConstraints = false + inputTextField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged) + stackView.addArrangedSubview(inputTextField) + } + + @objc private func textFieldDidChange() { + onTextChanged?(inputTextField.text ?? "") + } + + private func setupEyeButton() { + eyeButton.translatesAutoresizingMaskIntoConstraints = false + eyeButton.setImage(kImage(EPLoginConfig.Images.iconPasswordUnsee), for: .normal) + eyeButton.setImage(kImage(EPLoginConfig.Images.iconPasswordSee), for: .selected) + eyeButton.addTarget(self, action: #selector(handleEyeTap), for: .touchUpInside) + stackView.addArrangedSubview(eyeButton) + + eyeButton.snp.makeConstraints { make in + make.size.equalTo(24) + } + } + + private func setupCodeButton() { + codeButton.translatesAutoresizingMaskIntoConstraints = false + codeButton.setTitle(YMLocalizedString("XPLoginInputView0"), for: .normal) + codeButton.setTitleColor(.white, for: .normal) + codeButton.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) + codeButton.titleLabel?.textAlignment = .center + codeButton.titleLabel?.numberOfLines = 2 + codeButton.layer.cornerRadius = EPLoginConfig.Layout.codeButtonHeight / 2 + codeButton.backgroundColor = EPLoginConfig.Colors.codeButtonBackground + codeButton.addTarget(self, action: #selector(handleCodeTap), for: .touchUpInside) + stackView.addArrangedSubview(codeButton) + + codeButton.snp.makeConstraints { make in + make.width.equalTo(EPLoginConfig.Layout.codeButtonWidth) + make.height.equalTo(EPLoginConfig.Layout.codeButtonHeight) + } + } + + // MARK: - Configuration + + + func configure(with config: EPLoginInputConfig) { + self.config = config + + + areaStackView.isHidden = !config.showAreaCode + + + iconImageView.isHidden = true + + + inputTextField.attributedPlaceholder = NSAttributedString( + string: config.placeholder, + attributes: [NSAttributedString.Key.foregroundColor: UIColor.white.withAlphaComponent(0.6)] + ) + + + inputTextField.keyboardType = config.keyboardType + + + inputTextField.isSecureTextEntry = config.isSecure + eyeButton.isHidden = !config.isSecure + + + codeButton.isHidden = !config.showCodeButton + } + + + func setAreaCode(_ code: String) { + areaCodeButton.setTitle(code, for: .normal) + } + + + func clearInput() { + inputTextField.text = "" + } + + + func displayKeyboard() { + inputTextField.becomeFirstResponder() + } + + // MARK: - Actions + + @objc private func handleAreaTap() { + delegate?.inputViewDidSelectArea(self) + } + + @objc private func handleEyeTap() { + eyeButton.isSelected.toggle() + inputTextField.isSecureTextEntry = !eyeButton.isSelected + } + + @objc private func handleCodeTap() { + guard !isCountingDown else { return } + delegate?.inputViewDidRequestCode(self) + } + + // MARK: - Countdown + + + func startCountdown() { + guard !isCountingDown else { return } + + isCountingDown = true + countdownSeconds = 60 + codeButton.isEnabled = false + codeButton.backgroundColor = EPLoginConfig.Colors.iconDisabled + + let queue = DispatchQueue.main + let timer = DispatchSource.makeTimerSource(queue: queue) + timer.schedule(deadline: .now(), repeating: 1.0) + + timer.setEventHandler { [weak self] in + guard let self = self else { return } + + self.countdownSeconds -= 1 + + if self.countdownSeconds <= 0 { + self.stopCountdown() + self.codeButton.setTitle(YMLocalizedString("XPLoginInputView1"), for: .normal) + } else { + self.codeButton.setTitle("\(self.countdownSeconds)s", for: .normal) + } + } + + timer.resume() + self.timer = timer + } + + + func stopCountdown() { + guard let timer = timer else { return } + + timer.cancel() + self.timer = nil + isCountingDown = false + + codeButton.isEnabled = true + codeButton.backgroundColor = EPLoginConfig.Colors.codeButtonBackground + codeButton.setTitle(YMLocalizedString("XPLoginInputView0"), for: .normal) + } +} + diff --git a/YuMi/E-P/NewLogin/Views/EPLoginInputView.swift b/YuMi/E-P/Login/Views/EPLoginInputView.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Views/EPLoginInputView.swift rename to YuMi/E-P/Login/Views/EPLoginInputView.swift.backup diff --git a/YuMi/E-P/Login/Views/EPPolicyLabel.swift b/YuMi/E-P/Login/Views/EPPolicyLabel.swift new file mode 100644 index 0000000..b327b5c --- /dev/null +++ b/YuMi/E-P/Login/Views/EPPolicyLabel.swift @@ -0,0 +1,149 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit + +class EPPolicyLabel: UILabel { + + // MARK: - Properties + + var onUserAgreementTapped: (() -> Void)? + var onPrivacyPolicyTapped: (() -> Void)? + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + // MARK: - Setup + + private func setup() { + numberOfLines = 0 + isUserInteractionEnabled = true + + + let fullText = YMLocalizedString("XPLoginViewController6") + let userAgreementText = YMLocalizedString("XPLoginViewController7") + let privacyPolicyText = YMLocalizedString("XPLoginViewController9") + + let attributedString = NSMutableAttributedString(string: fullText) + attributedString.addAttribute(NSAttributedString.Key.foregroundColor, + value: UIColor.darkGray, + range: NSRange(location: 0, length: fullText.count)) + attributedString.addAttribute(NSAttributedString.Key.font, + value: UIFont.systemFont(ofSize: 12), + range: NSRange(location: 0, length: fullText.count)) + + + if let userRange = fullText.range(of: userAgreementText) { + let nsRange = NSRange(userRange, in: fullText) + attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.systemBlue, range: nsRange) + attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: nsRange) + } + + + if let privacyRange = fullText.range(of: privacyPolicyText) { + let nsRange = NSRange(privacyRange, in: fullText) + attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.systemBlue, range: nsRange) + attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: nsRange) + } + + attributedText = attributedString + + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) + addGestureRecognizer(tapGesture) + } + + // MARK: - Actions + + @objc private func handleTap(_ gesture: UITapGestureRecognizer) { + guard let attributedText = self.attributedText else { + print("[EPPolicyLabel] No attributed text") + return + } + + let text = attributedText.string + let userAgreementText = YMLocalizedString("XPLoginViewController7") + let privacyPolicyText = YMLocalizedString("XPLoginViewController9") + + print("[EPPolicyLabel] Tap detected, text: \(text)") + + let layoutManager = NSLayoutManager() + let textContainer = NSTextContainer(size: bounds.size) + let textStorage = NSTextStorage(attributedString: attributedText) + + layoutManager.addTextContainer(textContainer) + textStorage.addLayoutManager(layoutManager) + + textContainer.lineFragmentPadding = 0 + textContainer.maximumNumberOfLines = numberOfLines + textContainer.lineBreakMode = lineBreakMode + + let locationOfTouchInLabel = gesture.location(in: self) + let textBoundingBox = layoutManager.usedRect(for: textContainer) + + + var textContainerOffset = CGPoint.zero + switch textAlignment { + case .left, .natural, .justified: + textContainerOffset = CGPoint(x: 0, y: (bounds.height - textBoundingBox.height) / 2) + case .center: + textContainerOffset = CGPoint(x: (bounds.width - textBoundingBox.width) / 2, + y: (bounds.height - textBoundingBox.height) / 2) + case .right: + textContainerOffset = CGPoint(x: bounds.width - textBoundingBox.width, + y: (bounds.height - textBoundingBox.height) / 2) + @unknown default: + textContainerOffset = CGPoint(x: 0, y: (bounds.height - textBoundingBox.height) / 2) + } + + let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, + y: locationOfTouchInLabel.y - textContainerOffset.y) + + + guard textBoundingBox.contains(locationOfTouchInTextContainer) else { + print("[EPPolicyLabel] Tap outside text bounds") + return + } + + let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, + in: textContainer, + fractionOfDistanceBetweenInsertionPoints: nil) + + print("[EPPolicyLabel] Character index: \(indexOfCharacter)") + + + if let userRange = text.range(of: userAgreementText) { + let nsRange = NSRange(userRange, in: text) + print("[EPPolicyLabel] User agreement range: \(nsRange)") + if NSLocationInRange(indexOfCharacter, nsRange) { + print("[EPPolicyLabel] User agreement tapped!") + onUserAgreementTapped?() + return + } + } + + if let privacyRange = text.range(of: privacyPolicyText) { + let nsRange = NSRange(privacyRange, in: text) + print("[EPPolicyLabel] Privacy policy range: \(nsRange)") + if NSLocationInRange(indexOfCharacter, nsRange) { + print("[EPPolicyLabel] Privacy policy tapped!") + onPrivacyPolicyTapped?() + return + } + } + + print("[EPPolicyLabel] No link tapped") + } +} + diff --git a/YuMi/E-P/NewLogin/Views/EPPolicyLabel.swift b/YuMi/E-P/Login/Views/EPPolicyLabel.swift.backup similarity index 100% rename from YuMi/E-P/NewLogin/Views/EPPolicyLabel.swift rename to YuMi/E-P/Login/Views/EPPolicyLabel.swift.backup diff --git a/YuMi/E-P/Mine/Controllers/EPAboutUsViewController.swift b/YuMi/E-P/Mine/Controllers/EPAboutUsViewController.swift new file mode 100644 index 0000000..13d947f --- /dev/null +++ b/YuMi/E-P/Mine/Controllers/EPAboutUsViewController.swift @@ -0,0 +1,159 @@ + + +// Created by AI on 2025-01-28. + + +import UIKit +import SnapKit + + +class EPAboutUsViewController: BaseViewController { + + // MARK: - UI Components + + private lazy var appIconImageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFit + imageView.layer.cornerRadius = 20 + imageView.layer.masksToBounds = true + + if let iconName = Bundle.main.object(forInfoDictionaryKey: "CFBundleIconName") as? String { + imageView.image = UIImage(named: iconName) + } else if let icons = Bundle.main.object(forInfoDictionaryKey: "CFBundleIcons") as? [String: Any], + let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String: Any], + let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String], + let lastIcon = iconFiles.last { + imageView.image = UIImage(named: lastIcon) + } else { + + imageView.image = UIImage(named: "pi_app_logo_new_bg") + } + return imageView + }() + + private lazy var appNameLabel: UILabel = { + let label = UILabel() + label.text = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String + ?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String + ?? "YuMi" + label.textColor = .white + label.font = .systemFont(ofSize: 24, weight: .bold) + label.textAlignment = .center + return label + }() + + private lazy var versionLabel: UILabel = { + let label = UILabel() + let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "1.0.0" + let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "1" + label.text = "Version \(version) (\(build))" + label.textColor = UIColor.white.withAlphaComponent(0.7) + label.font = .systemFont(ofSize: 16) + label.textAlignment = .center + return label + }() + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + setupNavigationBar() + setupUI() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: animated) + } + + // MARK: - Setup + + private func setupNavigationBar() { + title = YMLocalizedString("EPEditSetting.AboutUs") + + + let appearance = UINavigationBarAppearance() + appearance.configureWithOpaqueBackground() + appearance.backgroundColor = UIColor(hex: "#0C0527") + appearance.titleTextAttributes = [ + .foregroundColor: UIColor.white, + .font: UIFont.systemFont(ofSize: 18, weight: .medium) + ] + appearance.shadowColor = .clear + + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance + navigationController?.navigationBar.compactAppearance = appearance + navigationController?.navigationBar.tintColor = .white + + + navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + } + + private func setupUI() { + view.backgroundColor = UIColor(hex: "#0C0527") + + + let containerView = UIView() + view.addSubview(containerView) + + + containerView.addSubview(appIconImageView) + containerView.addSubview(appNameLabel) + containerView.addSubview(versionLabel) + + + containerView.snp.makeConstraints { make in + make.centerY.equalTo(view).offset(-50) + make.leading.trailing.equalTo(view).inset(40) + } + + + appIconImageView.snp.makeConstraints { make in + make.top.equalTo(containerView) + make.centerX.equalTo(containerView) + make.size.equalTo(100) + } + + + appNameLabel.snp.makeConstraints { make in + make.top.equalTo(appIconImageView.snp.bottom).offset(24) + make.leading.trailing.equalTo(containerView) + } + + + versionLabel.snp.makeConstraints { make in + make.top.equalTo(appNameLabel.snp.bottom).offset(12) + make.leading.trailing.equalTo(containerView) + } + } +} + +// MARK: - UIColor Extension + +private extension UIColor { + convenience init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (1, 1, 1, 0) + } + + self.init( + red: CGFloat(r) / 255, + green: CGFloat(g) / 255, + blue: CGFloat(b) / 255, + alpha: CGFloat(a) / 255 + ) + } +} + diff --git a/YuMi/E-P/NewMine/Controllers/EPAboutUsViewController.swift b/YuMi/E-P/Mine/Controllers/EPAboutUsViewController.swift.backup similarity index 100% rename from YuMi/E-P/NewMine/Controllers/EPAboutUsViewController.swift rename to YuMi/E-P/Mine/Controllers/EPAboutUsViewController.swift.backup diff --git a/YuMi/E-P/Mine/Controllers/EPEditSettingViewController.swift b/YuMi/E-P/Mine/Controllers/EPEditSettingViewController.swift new file mode 100644 index 0000000..6aead0b --- /dev/null +++ b/YuMi/E-P/Mine/Controllers/EPEditSettingViewController.swift @@ -0,0 +1,846 @@ + + +// Created by AI on 2025-01-27. + + +import UIKit +import Photos +import SnapKit +import WebKit + + +class EPEditSettingViewController: BaseViewController { + + // MARK: - UI Components + private lazy var profileImageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFill + imageView.layer.cornerRadius = 60 + imageView.layer.masksToBounds = true + imageView.backgroundColor = .systemGray5 + imageView.isUserInteractionEnabled = true + return imageView + }() + + private lazy var cameraIconView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFit + imageView.image = UIImage(named: "icon_setting_camear") + imageView.backgroundColor = UIColor(hex: "#0C0527") + imageView.layer.cornerRadius = 15 + imageView.layer.masksToBounds = true + return imageView + }() + + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.backgroundColor = UIColor(hex: "#0C0527") + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "SettingCell") + tableView.isScrollEnabled = true + return tableView + }() + + private lazy var logoutButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle(YMLocalizedString("EPEditSetting.Logout"), for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = .systemFont(ofSize: 17, weight: .semibold) + button.layer.cornerRadius = 25 + button.addTarget(self, action: #selector(logoutButtonTapped), for: .touchUpInside) + return button + }() + + // MARK: - Data + + private var settingItems: [SettingItem] = [] + private var userInfo: UserInfoModel? + private var apiHelper: EPMineAPIHelper = EPMineAPIHelper() + private var hasAddedGradient = false + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + setupNavigationBar() + setupUI() + setupData() + loadUserInfo() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: animated) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + restoreParentNavigationBarStyle() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + + if !hasAddedGradient && logoutButton.bounds.width > 0 { + logoutButton.addGradientBackground( + with: [ + UIColor(red: 0xF8/255.0, green: 0x54/255.0, blue: 0xFC/255.0, alpha: 1.0), + UIColor(red: 0x50/255.0, green: 0x0F/255.0, blue: 0xFF/255.0, alpha: 1.0) + ], + start: CGPoint(x: 0, y: 0.5), + end: CGPoint(x: 1, y: 0.5), + cornerRadius: 25 + ) + hasAddedGradient = true + } + } + + // MARK: - Setup + + private func setupNavigationBar() { + title = YMLocalizedString("EPEditSetting.Title") + + + let appearance = UINavigationBarAppearance() + appearance.configureWithOpaqueBackground() + appearance.backgroundColor = UIColor(hex: "#0C0527") + appearance.titleTextAttributes = [ + .foregroundColor: UIColor.white, + .font: UIFont.systemFont(ofSize: 18, weight: .medium) + ] + appearance.shadowColor = .clear + + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance + navigationController?.navigationBar.compactAppearance = appearance + navigationController?.navigationBar.tintColor = .white + + + navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + + + navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem( + title: "", + style: .plain, + target: nil, + action: nil + ) + } + + private func restoreParentNavigationBarStyle() { + + let transparentAppearance = UINavigationBarAppearance() + transparentAppearance.configureWithTransparentBackground() + transparentAppearance.backgroundColor = .clear + transparentAppearance.shadowColor = .clear + + navigationController?.navigationBar.standardAppearance = transparentAppearance + navigationController?.navigationBar.scrollEdgeAppearance = transparentAppearance + navigationController?.navigationBar.compactAppearance = transparentAppearance + } + + private func setupUI() { + view.backgroundColor = UIColor(hex: "#0C0527") + + + view.addSubview(profileImageView) + profileImageView.snp.makeConstraints { make in + make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(40) + make.centerX.equalTo(view) + make.size.equalTo(120) + } + + + view.addSubview(cameraIconView) + cameraIconView.snp.makeConstraints { make in + make.bottom.equalTo(profileImageView.snp.bottom) + make.trailing.equalTo(profileImageView.snp.trailing) + make.size.equalTo(30) + } + + + view.addSubview(logoutButton) + logoutButton.snp.makeConstraints { make in + make.leading.trailing.equalTo(view).inset(20) + make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-40) + make.height.equalTo(50) + } + + + view.addSubview(tableView) + tableView.snp.makeConstraints { make in + make.top.equalTo(profileImageView.snp.bottom).offset(40) + make.leading.trailing.equalTo(view) + make.bottom.equalTo(logoutButton.snp.top).offset(-20) + } + + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(profileImageTapped)) + profileImageView.addGestureRecognizer(tapGesture) + + + let cameraTapGesture = UITapGestureRecognizer(target: self, action: #selector(profileImageTapped)) + cameraIconView.addGestureRecognizer(cameraTapGesture) + } + + + private func setupData() { + settingItems = [ + SettingItem( + title: YMLocalizedString("EPEditSetting.PersonalInfo"), + action: { [weak self] in self?.handleReservedAction("PersonalInfo") } + ), + SettingItem( + title: YMLocalizedString("EPEditSetting.Help"), + action: { [weak self] in self?.handleReservedAction("Help") } + ), + SettingItem( + title: YMLocalizedString("EPEditSetting.ClearCache"), + action: { [weak self] in self?.handleReservedAction("ClearCache") } + ), + SettingItem( + title: YMLocalizedString("EPEditSetting.AboutUs"), + action: { [weak self] in self?.handleReservedAction("AboutUs") } + ) + ] + NSLog("[EPEditSetting] setupData 完成,设置项数量: \(settingItems.count)") + } + + private func loadUserInfo() { + + if userInfo != nil { + updateProfileImage() + tableView.reloadData() + return + } + + + guard let uid = AccountInfoStorage.instance().getUid(), !uid.isEmpty else { + print("[EPEditSetting] 未登录,无法获取用户信息") + return + } + + // TODO: 调用API获取用户详细信息 + + let tempUserInfo = UserInfoModel() + tempUserInfo.nick = "User" + tempUserInfo.avatar = "" + userInfo = tempUserInfo + + updateProfileImage() + tableView.reloadData() + } + + private func updateProfileImage() { + guard let avatarUrl = userInfo?.avatar, !avatarUrl.isEmpty else { + profileImageView.image = UIImage(systemName: "person.circle.fill") + return + } + + + if let url = URL(string: avatarUrl) { + profileImageView.sd_setImage(with: url, placeholderImage: UIImage(systemName: "person.circle.fill")) + } + } + + // MARK: - Actions + + @objc private func profileImageTapped() { + showAvatarSelectionSheet() + } + + @objc private func openSettings() { + + handleReservedAction("Settings") + } + + @objc private func logoutButtonTapped() { + showLogoutConfirm() + } + + private func showAvatarSelectionSheet() { + let alert = UIAlertController(title: YMLocalizedString("EPEditSetting.EditNickname"), message: nil, preferredStyle: .actionSheet) + + + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Camera"), style: .default) { [weak self] _ in + self?.checkCameraPermissionAndPresent() + }) + + + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.PhotoLibrary"), style: .default) { [weak self] _ in + self?.checkPhotoLibraryPermissionAndPresent() + }) + + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Cancel"), style: .cancel)) + + + if let popover = alert.popoverPresentationController { + popover.sourceView = profileImageView + popover.sourceRect = profileImageView.bounds + } + + present(alert, animated: true) + } + + private func checkCameraPermissionAndPresent() { + YYUtility.checkCameraAvailable { [weak self] in + self?.presentImagePicker(sourceType: .camera) + } denied: { [weak self] in + self?.showPermissionAlert(title: "Camera Access", message: "Please allow camera access in Settings") + } restriction: { [weak self] in + self?.showPermissionAlert(title: "Camera Restricted", message: "Camera access is restricted on this device") + } + } + + private func checkPhotoLibraryPermissionAndPresent() { + YYUtility.checkAssetsLibrayAvailable { [weak self] in + self?.presentImagePicker(sourceType: .photoLibrary) + } denied: { [weak self] in + self?.showPermissionAlert(title: "Photo Library Access", message: "Please allow photo library access in Settings") + } restriction: { [weak self] in + self?.showPermissionAlert(title: "Photo Library Restricted", message: "Photo library access is restricted on this device") + } + } + + private func presentImagePicker(sourceType: UIImagePickerController.SourceType) { + let imagePicker = UIImagePickerController() + imagePicker.delegate = self + imagePicker.sourceType = sourceType + imagePicker.allowsEditing = true + present(imagePicker, animated: true) + } + + private func showPermissionAlert(title: String, message: String) { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "Settings", style: .default) { _ in + if let settingsURL = URL(string: UIApplication.openSettingsURLString) { + UIApplication.shared.open(settingsURL) + } + }) + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Cancel"), style: .cancel)) + present(alert, animated: true) + } + + private func showNicknameEditAlert() { + let alert = UIAlertController( + title: YMLocalizedString("EPEditSetting.EditNickname"), + message: nil, + preferredStyle: .alert + ) + + alert.addTextField { [weak self] textField in + textField.text = self?.userInfo?.nick ?? "" + textField.placeholder = YMLocalizedString("EPEditSetting.EnterNickname") + } + + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Cancel"), style: .cancel)) + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Confirm"), style: .default) { [weak self] _ in + guard let newNickname = alert.textFields?.first?.text, !newNickname.isEmpty else { return } + self?.updateNickname(newNickname) + }) + + present(alert, animated: true) + } + + private func updateNickname(_ newNickname: String) { + + showLoading() + + + apiHelper.updateNickname(withNick: newNickname, + completion: { [weak self] in + self?.hideHUD() + + + self?.userInfo?.nick = newNickname + self?.tableView.reloadData() + + + self?.showSuccessToast(YMLocalizedString("XPMineUserInfoEditViewController13")) + + print("[EPEditSetting] 昵称更新成功: \(newNickname)") + }, + failure: { [weak self] (code: Int, msg: String?) in + self?.hideHUD() + + + let errorMsg = msg ?? YMLocalizedString("setting.nickname_update_failed") + self?.showErrorToast(errorMsg) + + print("[EPEditSetting] 昵称更新失败: \(code) - \(errorMsg)") + } + ) + } + + private func showLogoutConfirm() { + let alert = UIAlertController( + title: YMLocalizedString("EPEditSetting.LogoutConfirm"), + message: nil, + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Cancel"), style: .cancel)) + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Logout"), style: .destructive) { [weak self] _ in + self?.performLogout() + }) + + present(alert, animated: true) + } + + private func performLogout() { + guard let account = AccountInfoStorage.instance().accountModel else { + print("[EPEditSetting] 账号信息不存在") + return + } + + + Api.logoutCurrentAccount({ [weak self] (data, code, msg) in + DispatchQueue.main.async { + + AccountInfoStorage.instance().saveAccountInfo(nil) + AccountInfoStorage.instance().saveTicket(nil) + + + self?.navigateToLogin() + } + }, access_token: account.access_token) + } + + private func navigateToLogin() { + let loginVC = EPLoginViewController() + let nav = UINavigationController(rootViewController: loginVC) + + if let window = UIApplication.shared.windows.first { + window.rootViewController = nav + window.makeKeyAndVisible() + } + + print("[EPEditSetting] 已跳转到登录页面") + } + + private func handleReservedAction(_ title: String) { + print("[\(title)] - 功能触发") + + + if title == "AboutUs" { + let aboutVC = EPAboutUsViewController() + navigationController?.pushViewController(aboutVC, animated: true) + return + } + + + if title == "PersonalInfo" { + showPolicyOptionsSheet() + return + } + + + if title == "Help" { + let faqUrl = getFAQURL() + openPolicyInExternalBrowser(faqUrl) + return + } + + + if title == "ClearCache" { + showClearCacheConfirmation() + return + } + + + // TODO: Phase 2 implementation + let alert = UIAlertController(title: "Coming Soon", message: "This feature will be available in the next update.", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default)) + present(alert, animated: true) + } + + private func showClearCacheConfirmation() { + let alert = UIAlertController( + title: YMLocalizedString("EPEditSetting.ClearCacheTitle"), + message: YMLocalizedString("EPEditSetting.ClearCacheMessage"), + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Cancel"), style: .cancel)) + alert.addAction(UIAlertAction(title: YMLocalizedString("EPEditSetting.Confirm"), style: .destructive) { [weak self] _ in + self?.performClearCache() + }) + + present(alert, animated: true) + } + + private func performClearCache() { + print("[EPEditSetting] 开始清理缓存") + + + showLoading() + + + SDWebImageManager.shared.imageCache.clear?(with: .all) { + print("[EPEditSetting] SDWebImage 缓存已清理") + + + let websiteDataTypes = WKWebsiteDataStore.allWebsiteDataTypes() + let dateFrom = Date(timeIntervalSince1970: 0) + WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes, modifiedSince: dateFrom) { [weak self] in + print("[EPEditSetting] WKWebsiteDataStore 缓存已清理") + + DispatchQueue.main.async { + self?.hideHUD() + self?.showSuccessToast(YMLocalizedString("EPEditSetting.ClearCacheSuccess")) + print("[EPEditSetting] 缓存清理完成") + } + } + } + } + + private func showPolicyOptionsSheet() { + let alert = UIAlertController( + title: nil, + message: nil, + preferredStyle: .actionSheet + ) + + + alert.addAction(UIAlertAction( + title: YMLocalizedString("EPEditSetting.UserAgreement"), + style: .default + ) { [weak self] _ in + let url = self?.getUserAgreementURL() ?? "" + self?.openPolicyInExternalBrowser(url) + }) + + + alert.addAction(UIAlertAction( + title: YMLocalizedString("EPEditSetting.PrivacyPolicy"), + style: .default + ) { [weak self] _ in + let url = self?.getPrivacyPolicyURL() ?? "" + self?.openPolicyInExternalBrowser(url) + }) + + + alert.addAction(UIAlertAction( + title: YMLocalizedString("EPEditSetting.Cancel"), + style: .cancel + )) + + + if let popover = alert.popoverPresentationController { + popover.sourceView = view + popover.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0) + popover.permittedArrowDirections = [] + } + + present(alert, animated: true) + } + + + private func getUserAgreementURL() -> String { + + let url = URLWithType(URLType(rawValue: 4)!) as String + print("[EPEditSetting] User agreement URL from URLWithType: \(url)") + return url + } + + + private func getPrivacyPolicyURL() -> String { + + let url = URLWithType(URLType(rawValue: 0)!) as String + print("[EPEditSetting] Privacy policy URL from URLWithType: \(url)") + return url + } + + + private func getFAQURL() -> String { + + let url = URLWithType(URLType(rawValue: 6)!) as String + print("[EPEditSetting] FAQ URL from URLWithType: \(url)") + return url + } + + private func openPolicyInExternalBrowser(_ urlString: String) { + print("[EPEditSetting] Original URL: \(urlString)") + + + var fullUrl = urlString + if !urlString.hasPrefix("http") && !urlString.hasPrefix("https") { + let hostUrl = HttpRequestHelper.getHostUrl() + fullUrl = "\(hostUrl)/\(urlString)" + print("[EPEditSetting] Added host URL, full URL: \(fullUrl)") + } + + print("[EPEditSetting] Opening URL in external browser: \(fullUrl)") + + guard let url = URL(string: fullUrl) else { + print("[EPEditSetting] ❌ Invalid URL: \(fullUrl)") + return + } + + print("[EPEditSetting] URL object created: \(url)") + + + if UIApplication.shared.canOpenURL(url) { + print("[EPEditSetting] ✅ Can open URL, attempting to open...") + UIApplication.shared.open(url, options: [:]) { success in + print("[EPEditSetting] Open external browser: \(success ? "✅ Success" : "❌ Failed")") + } + } else { + print("[EPEditSetting] ❌ Cannot open URL: \(fullUrl)") + } + } + + // MARK: - Public Methods + + + @objc func updateWithUserInfo(_ userInfo: UserInfoModel) { + self.userInfo = userInfo + updateProfileImage() + tableView.reloadData() + NSLog("[EPEditSetting] 已更新用户信息: \(userInfo.nick)") + } +} + +// MARK: - UITableViewDataSource & UITableViewDelegate + +extension EPEditSettingViewController: UITableViewDataSource, UITableViewDelegate { + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + let count = settingItems.count + 1 + NSLog("[EPEditSetting] TableView rows count: \(count), settingItems: \(settingItems.count)") + return count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "SettingCell", for: indexPath) + cell.backgroundColor = UIColor(hex: "#0C0527") + cell.textLabel?.textColor = .white + cell.selectionStyle = .none + + + cell.contentView.subviews.forEach { $0.removeFromSuperview() } + + if indexPath.row == 0 { + + cell.textLabel?.text = YMLocalizedString("EPEditSetting.Nickname") + + + let arrowImageView = UIImageView() + arrowImageView.image = UIImage(named: "icon_setting_right_arrow") + arrowImageView.contentMode = .scaleAspectFit + cell.contentView.addSubview(arrowImageView) + arrowImageView.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-20) + make.centerY.equalToSuperview() + make.size.equalTo(22) + } + + + let nicknameLabel = UILabel() + nicknameLabel.text = userInfo?.nick ?? YMLocalizedString("user.not_set") + nicknameLabel.textColor = .lightGray + nicknameLabel.font = UIFont.systemFont(ofSize: 16) + cell.contentView.addSubview(nicknameLabel) + nicknameLabel.snp.makeConstraints { make in + make.trailing.equalTo(arrowImageView.snp.leading).offset(-12) + make.centerY.equalToSuperview() + } + + } else { + + let item = settingItems[indexPath.row - 1] + cell.textLabel?.text = item.title + cell.textLabel?.textColor = .white + + + let arrowImageView = UIImageView() + arrowImageView.image = UIImage(named: "icon_setting_right_arrow") + arrowImageView.contentMode = .scaleAspectFit + cell.contentView.addSubview(arrowImageView) + arrowImageView.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-20) + make.centerY.equalToSuperview() + make.size.equalTo(22) + } + } + + return cell + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 60 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + if indexPath.row == 0 { + + showNicknameEditAlert() + } else { + + let item = settingItems[indexPath.row - 1] + item.action() + } + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return 0 + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + return nil + } + + func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 0 + } + + func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + return nil + } +} + +// MARK: - UIImagePickerControllerDelegate & UINavigationControllerDelegate + +extension EPEditSettingViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { + + func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { + picker.dismiss(animated: true) + + guard let image = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage else { + print("[EPEditSetting] 未能获取选择的图片") + return + } + + + profileImageView.image = image + + + uploadAvatar(image) + } + + func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { + picker.dismiss(animated: true) + } + + private func uploadAvatar(_ image: UIImage) { + + EPProgressHUD.showProgress(0, total: 1) + + + EPSDKManager.shared.uploadImages([image], + progress: { uploaded, total in + EPProgressHUD.showProgress(uploaded, total: total) + }, + success: { [weak self] resList in + EPProgressHUD.dismiss() + + guard !resList.isEmpty, + let firstRes = resList.first, + let avatarUrl = firstRes["resUrl"] as? String else { + print("[EPEditSetting] 头像上传成功但无法获取URL") + + return + } + + print("[EPEditSetting] 头像上传成功: \(avatarUrl)") + + + self?.updateAvatarAPI(avatarUrl: avatarUrl) + }, + failure: { [weak self] errorMsg in + EPProgressHUD.dismiss() + print("[EPEditSetting] 头像上传失败: \(errorMsg)") + + + DispatchQueue.main.async { + let alert = UIAlertController(title: YMLocalizedString("common.upload_failed"), message: errorMsg, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: YMLocalizedString("common.confirm"), style: .default)) + self?.present(alert, animated: true) + } + } + ) + } + + private func updateAvatarAPI(avatarUrl: String) { + + apiHelper.updateAvatar(withUrl: avatarUrl, completion: { [weak self] in + print("[EPEditSetting] 头像更新成功") + + + self?.userInfo?.avatar = avatarUrl + + + self?.notifyParentAvatarUpdated(avatarUrl) + + }, failure: { [weak self] (code: Int, msg: String?) in + print("[EPEditSetting] 头像更新失败: \(code) - \(msg ?? "未知错误")") + + + DispatchQueue.main.async { + let alert = UIAlertController( + title: YMLocalizedString("common.update_failed"), + message: msg ?? YMLocalizedString("setting.avatar_update_failed"), + preferredStyle: .alert + ) + alert.addAction(UIAlertAction(title: YMLocalizedString("common.confirm"), style: .default)) + self?.present(alert, animated: true) + } + }) + } + + private func notifyParentAvatarUpdated(_ avatarUrl: String) { + + let userInfo = ["avatarUrl": avatarUrl] + NotificationCenter.default.post(name: NSNotification.Name("EPEditSettingAvatarUpdated"), object: nil, userInfo: userInfo) + } +} + +// MARK: - Helper Models + +private struct SettingItem { + let title: String + let action: () -> Void + + init(title: String, action: @escaping () -> Void) { + self.title = title + self.action = action + } +} + +// MARK: - UIColor Extension + +private extension UIColor { + convenience init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (1, 1, 1, 0) + } + + self.init( + red: CGFloat(r) / 255, + green: CGFloat(g) / 255, + blue: CGFloat(b) / 255, + alpha: CGFloat(a) / 255 + ) + } +} diff --git a/YuMi/E-P/NewMine/Controllers/EPEditSettingViewController.swift b/YuMi/E-P/Mine/Controllers/EPEditSettingViewController.swift.backup similarity index 100% rename from YuMi/E-P/NewMine/Controllers/EPEditSettingViewController.swift rename to YuMi/E-P/Mine/Controllers/EPEditSettingViewController.swift.backup diff --git a/YuMi/E-P/Mine/Controllers/EPMineViewController.h b/YuMi/E-P/Mine/Controllers/EPMineViewController.h new file mode 100644 index 0000000..3742793 --- /dev/null +++ b/YuMi/E-P/Mine/Controllers/EPMineViewController.h @@ -0,0 +1,16 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface EPMineViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/E-P/NewMine/Controllers/EPMineViewController.h b/YuMi/E-P/Mine/Controllers/EPMineViewController.h.backup similarity index 100% rename from YuMi/E-P/NewMine/Controllers/EPMineViewController.h rename to YuMi/E-P/Mine/Controllers/EPMineViewController.h.backup diff --git a/YuMi/E-P/Mine/Controllers/EPMineViewController.m b/YuMi/E-P/Mine/Controllers/EPMineViewController.m new file mode 100644 index 0000000..77265d0 --- /dev/null +++ b/YuMi/E-P/Mine/Controllers/EPMineViewController.m @@ -0,0 +1,218 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import "EPMineViewController.h" +#import "EPMineHeaderView.h" +#import "EPMomentListView.h" +#import "EPMineAPIHelper.h" +#import "AccountInfoStorage.h" +#import "UserInfoModel.h" +#import +#import "YuMi-Swift.h" + +@interface EPMineViewController () + +// MARK: - UI Components + + +@property (nonatomic, strong) EPMomentListView *momentListView; + + +@property (nonatomic, strong) EPMineHeaderView *headerView; + +// MARK: - Data + + +@property (nonatomic, strong) UserInfoModel *userInfo; + + +@property (nonatomic, strong) EPMineAPIHelper *apiHelper; + +@end + +@implementation EPMineViewController + +// MARK: - Lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + [self setupUI]; + + NSLog(@"[EPMineViewController] viewDidLoad 完成"); +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:YES animated:animated]; + + [self loadUserDetailInfo]; +} + +// MARK: - Setup + +- (void)setupUI { + UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; + bgImageView.contentMode = UIViewContentModeScaleAspectFill; + bgImageView.clipsToBounds = YES; + [self.view addSubview:bgImageView]; + [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.view); + }]; + + [self setupHeaderView]; + [self setupMomentListView]; + + NSLog(@"[EPMineViewController] UI 设置完成"); +} + +- (void)setupHeaderView { + self.headerView = [[EPMineHeaderView alloc] initWithFrame:CGRectZero]; + [self.view addSubview:self.headerView]; + + + [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.view); + make.leading.mas_equalTo(self.view); + make.trailing.mas_equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(260)); + }]; + + + __weak typeof(self) weakSelf = self; + self.headerView.onSettingsButtonTapped = ^{ + __strong typeof(weakSelf) self = weakSelf; + [self openSettings]; + }; + + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onAvatarUpdated:) + name:@"EPEditSettingAvatarUpdated" + object:nil]; +} + +- (void)setupMomentListView { + self.momentListView = [[EPMomentListView alloc] initWithFrame:CGRectZero]; + [self.view addSubview:self.momentListView]; + + [self.momentListView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.headerView.mas_bottom); + make.bottom.mas_equalTo(self.view); + make.leading.mas_equalTo(self.view); + make.trailing.mas_equalTo(self.view); + }]; + + + __weak typeof(self) weakSelf = self; + [self.momentListView loadWithDynamicInfo:@[] refreshCallback:^{ + __strong typeof(weakSelf) self = weakSelf; + [self loadUserDetailInfo]; + }]; +} + +// MARK: - Data Loading + +- (void)loadUserDetailInfo { + NSString *uid = [[AccountInfoStorage instance] getUid]; + if (!uid || uid.length == 0) { + NSLog(@"[EPMineViewController] 用户未登录"); + return; + } + + @kWeakify(self); + [self.apiHelper getUserDetailInfoWithUid:uid + completion:^(UserInfoModel * _Nullable userInfo) { + @kStrongify(self); + if (!userInfo) { + NSLog(@"[EPMineViewController] 加载用户信息失败"); + return; + } + + self.userInfo = userInfo; + [self updateHeaderWithUserInfo:userInfo]; + + + if (userInfo.dynamicInfo && userInfo.dynamicInfo.count > 0) { + [self.momentListView loadWithDynamicInfo:userInfo.dynamicInfo refreshCallback:^{ + [self loadUserDetailInfo]; + }]; + } + } failure:^(NSInteger code, NSString * _Nullable msg) { + NSLog(@"[EPMineViewController] 加载用户信息失败: %@", msg); + }]; +} + +- (void)updateHeaderWithUserInfo:(UserInfoModel *)userInfo { + NSDictionary *userInfoDict = @{ + @"nickname": userInfo.nick ?: @"未设置昵称", + @"uid": [NSString stringWithFormat:@"%ld", (long)userInfo.erbanNo], + @"avatar": userInfo.avatar ?: @"", + @"following": @(userInfo.followNum), + @"followers": @(userInfo.fansNum) + }; + + [self.headerView updateWithUserInfo:userInfoDict]; +} + +// MARK: - Lazy Loading + +- (EPMomentListView *)momentListView { + if (!_momentListView) { + _momentListView = [[EPMomentListView alloc] init]; + __weak typeof(self) weakSelf = self; + _momentListView.onSelectMoment = ^(NSInteger index) { + __strong typeof(weakSelf) self = weakSelf; + NSLog(@"[EPMineViewController] 点击了第 %ld 条动态", (long)index); + // TODO: 跳转到动态详情页 + }; + } + return _momentListView; +} + +- (EPMineAPIHelper *)apiHelper { + if (!_apiHelper) { + _apiHelper = [[EPMineAPIHelper alloc] init]; + } + return _apiHelper; +} + +// MARK: - Actions + +- (void)openSettings { + + self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" + style:UIBarButtonItemStylePlain + target:nil + action:nil]; + + EPEditSettingViewController *settingsVC = [[EPEditSettingViewController alloc] init]; + + if (self.userInfo) { + [settingsVC updateWithUserInfo:self.userInfo]; + } + [self.navigationController pushViewController:settingsVC animated:YES]; + NSLog(@"[EPMineViewController] 打开设置页面,已传递用户信息"); +} + +- (void)onAvatarUpdated:(NSNotification *)notification { + NSString *avatarUrl = notification.userInfo[@"avatarUrl"]; + if (avatarUrl && self.userInfo) { + + self.userInfo.avatar = avatarUrl; + + + [self updateHeaderWithUserInfo:self.userInfo]; + + NSLog(@"[EPMineViewController] 头像已更新: %@", avatarUrl); + } +} + +- (void)dealloc { + + [[NSNotificationCenter defaultCenter] removeObserver:self name:@"EPEditSettingAvatarUpdated" object:nil]; +} + +@end diff --git a/YuMi/E-P/NewMine/Controllers/EPMineViewController.m b/YuMi/E-P/Mine/Controllers/EPMineViewController.m.backup similarity index 100% rename from YuMi/E-P/NewMine/Controllers/EPMineViewController.m rename to YuMi/E-P/Mine/Controllers/EPMineViewController.m.backup diff --git a/YuMi/E-P/Mine/Services/EPMineAPIHelper.h b/YuMi/E-P/Mine/Services/EPMineAPIHelper.h new file mode 100644 index 0000000..ad1bac3 --- /dev/null +++ b/YuMi/E-P/Mine/Services/EPMineAPIHelper.h @@ -0,0 +1,38 @@ + + +// Created by AI on 2025-10-10. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class UserInfoModel; + + +@interface EPMineAPIHelper : NSObject + + +- (void)getUserInfoWithUid:(NSString *)uid + completion:(void (^)(UserInfoModel * _Nullable userInfo))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure; + + +- (void)getUserDetailInfoWithUid:(NSString *)uid + completion:(void (^)(UserInfoModel * _Nullable userInfo))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure; + + +- (void)updateAvatarWithUrl:(NSString *)avatarUrl + completion:(void (^)(void))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure; + + +- (void)updateNicknameWithNick:(NSString *)nickname + completion:(void (^)(void))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMine/Services/EPMineAPIHelper.h b/YuMi/E-P/Mine/Services/EPMineAPIHelper.h.backup similarity index 100% rename from YuMi/E-P/NewMine/Services/EPMineAPIHelper.h rename to YuMi/E-P/Mine/Services/EPMineAPIHelper.h.backup diff --git a/YuMi/E-P/Mine/Services/EPMineAPIHelper.m b/YuMi/E-P/Mine/Services/EPMineAPIHelper.m new file mode 100644 index 0000000..733d760 --- /dev/null +++ b/YuMi/E-P/Mine/Services/EPMineAPIHelper.m @@ -0,0 +1,75 @@ + + +// Created by AI on 2025-10-10. + + +#import "EPMineAPIHelper.h" +#import "Api+Mine.h" +#import "UserInfoModel.h" +#import "BaseModel.h" +#import "AccountInfoStorage.h" + +@implementation EPMineAPIHelper + +- (void)getUserInfoWithUid:(NSString *)uid + completion:(void (^)(UserInfoModel * _Nullable userInfo))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure { + [Api getUserInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200 && data.data) { + UserInfoModel *userInfo = [UserInfoModel modelWithDictionary:data.data]; + if (completion) completion(userInfo); + } else { + if (failure) failure(code, msg); + } + } uid:uid]; +} + +- (void)getUserDetailInfoWithUid:(NSString *)uid + completion:(void (^)(UserInfoModel * _Nullable userInfo))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure { + [Api userDetailInfoCompletion:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200 && data.data) { + UserInfoModel *userInfo = [UserInfoModel modelWithDictionary:data.data]; + if (completion) completion(userInfo); + } else { + if (failure) failure(code, msg); + } + } uid:uid page:@"1" pageSize:@"20"]; +} + +- (void)updateAvatarWithUrl:(NSString *)avatarUrl + completion:(void (^)(void))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure { + [Api userV2UploadAvatar:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200) { + if (completion) completion(); + } else { + if (failure) failure(code, msg); + } + } avatarUrl:avatarUrl needPay:@NO]; +} + +- (void)updateNicknameWithNick:(NSString *)nickname + completion:(void (^)(void))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure { + NSString *uid = [[AccountInfoStorage instance] getUid]; + NSString *ticket = [[AccountInfoStorage instance] getTicket]; + + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (nickname.length > 0) { + [params setValue:nickname forKey:@"nick"]; + } + [params setObject:uid forKey:@"uid"]; + [params setObject:ticket forKey:@"ticket"]; + + [Api completeUserInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200) { + if (completion) completion(); + } else { + if (failure) failure(code, msg); + } + } userInfo:params]; +} + +@end + diff --git a/YuMi/E-P/NewMine/Services/EPMineAPIHelper.m b/YuMi/E-P/Mine/Services/EPMineAPIHelper.m.backup similarity index 100% rename from YuMi/E-P/NewMine/Services/EPMineAPIHelper.m rename to YuMi/E-P/Mine/Services/EPMineAPIHelper.m.backup diff --git a/YuMi/E-P/Mine/Views/EPMineHeaderView.h b/YuMi/E-P/Mine/Views/EPMineHeaderView.h new file mode 100644 index 0000000..671e262 --- /dev/null +++ b/YuMi/E-P/Mine/Views/EPMineHeaderView.h @@ -0,0 +1,22 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface EPMineHeaderView : UIView + + +@property (nonatomic, copy, nullable) void(^onSettingsButtonTapped)(void); + + +- (void)updateWithUserInfo:(NSDictionary *)userInfoDict; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/YuMi/E-P/NewMine/Views/EPMineHeaderView.h b/YuMi/E-P/Mine/Views/EPMineHeaderView.h.backup similarity index 100% rename from YuMi/E-P/NewMine/Views/EPMineHeaderView.h rename to YuMi/E-P/Mine/Views/EPMineHeaderView.h.backup diff --git a/YuMi/E-P/Mine/Views/EPMineHeaderView.m b/YuMi/E-P/Mine/Views/EPMineHeaderView.m new file mode 100644 index 0000000..c5bbb24 --- /dev/null +++ b/YuMi/E-P/Mine/Views/EPMineHeaderView.m @@ -0,0 +1,240 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import "EPMineHeaderView.h" +#import +#import +#import "EPEmotionColorStorage.h" + +@interface EPMineHeaderView () + + +@property (nonatomic, strong) UIImageView *avatarImageView; + + +@property (nonatomic, strong) CALayer *glowLayer; + + +@property (nonatomic, strong) UILabel *nicknameLabel; + + +@property (nonatomic, strong) UILabel *idLabel; + + +@property (nonatomic, strong) UIButton *settingsButton; + +@end + +@implementation EPMineHeaderView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + + if (self.glowLayer) { + self.glowLayer.frame = CGRectInset(self.avatarImageView.frame, -8, -8); + } +} + +- (void)setupUI { + + self.avatarImageView = [[UIImageView alloc] init]; + self.avatarImageView.layer.cornerRadius = 60; + self.avatarImageView.layer.masksToBounds = NO; + self.avatarImageView.layer.borderWidth = 0; + self.avatarImageView.backgroundColor = [UIColor whiteColor]; + self.avatarImageView.contentMode = UIViewContentModeScaleAspectFill; + + + self.avatarImageView.clipsToBounds = YES; + + [self addSubview:self.avatarImageView]; + + [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self).offset(60); + make.size.mas_equalTo(CGSizeMake(120, 120)); + }]; + + + self.nicknameLabel = [[UILabel alloc] init]; + self.nicknameLabel.font = [UIFont boldSystemFontOfSize:24]; + self.nicknameLabel.textColor = [UIColor whiteColor]; + self.nicknameLabel.textAlignment = NSTextAlignmentCenter; + [self addSubview:self.nicknameLabel]; + + [self.nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self.avatarImageView.mas_bottom).offset(16); + }]; + + + self.idLabel = [[UILabel alloc] init]; + self.idLabel.font = [UIFont systemFontOfSize:14]; + self.idLabel.textColor = [UIColor whiteColor]; + self.idLabel.alpha = 0.8; + self.idLabel.textAlignment = NSTextAlignmentCenter; + [self addSubview:self.idLabel]; + + [self.idLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self.nicknameLabel.mas_bottom).offset(8); + }]; + + + self.settingsButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.settingsButton setImage:[UIImage systemImageNamed:@"gearshape"] forState:UIControlStateNormal]; + self.settingsButton.tintColor = [UIColor whiteColor]; + self.settingsButton.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2]; + self.settingsButton.layer.cornerRadius = 20; + [self.settingsButton addTarget:self action:@selector(settingsButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:self.settingsButton]; + + [self.settingsButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self).offset(50); + make.trailing.equalTo(self).offset(-20); + make.size.mas_equalTo(CGSizeMake(40, 40)); + }]; +} + +- (void)updateWithUserInfo:(NSDictionary *)userInfoDict { + + NSString *nickname = userInfoDict[@"nickname"] ?: YMLocalizedString(@"user.nickname_not_set"); + self.nicknameLabel.text = nickname; + + + NSString *uid = userInfoDict[@"uid"] ?: @""; + self.idLabel.text = [NSString stringWithFormat:@"ID:%@", uid]; + + + NSString *avatarURL = userInfoDict[@"avatar"]; + if (avatarURL && avatarURL.length > 0) { + [self.avatarImageView sd_setImageWithURL:[NSURL URLWithString:avatarURL] + placeholderImage:[UIImage imageNamed:@"default_avatar"]]; + } else { + + self.avatarImageView.image = [UIImage imageNamed:@"default_avatar"]; + } + + + [self applyUserSignatureColor]; +} + + +- (void)applyUserSignatureColor { + NSString *signatureColor = [EPEmotionColorStorage userSignatureColor]; + + if (signatureColor) { + + UIColor *color = [self colorFromHex:signatureColor]; + + + self.avatarImageView.layer.borderWidth = 0; + + + self.avatarImageView.layer.shadowColor = color.CGColor; + self.avatarImageView.layer.shadowOffset = CGSizeMake(0, 4); + self.avatarImageView.layer.shadowOpacity = 0.6; + self.avatarImageView.layer.shadowRadius = 12; + + NSLog(@"[EPMineHeaderView] 应用专属颜色: %@", signatureColor); + + + [self applyBreathingGlow]; + } else { + + self.avatarImageView.layer.borderWidth = 0; + + + self.avatarImageView.layer.shadowColor = [UIColor blackColor].CGColor; + self.avatarImageView.layer.shadowOffset = CGSizeMake(0, 2); + self.avatarImageView.layer.shadowOpacity = 0.2; + self.avatarImageView.layer.shadowRadius = 8; + + + if (self.glowLayer) { + [self.glowLayer removeFromSuperlayer]; + self.glowLayer = nil; + } + } +} + + +- (void)applyBreathingGlow { + NSString *signatureColor = [EPEmotionColorStorage userSignatureColor]; + if (!signatureColor) return; + + UIColor *color = [self colorFromHex:signatureColor]; + + + if (!self.glowLayer) { + self.glowLayer = [CALayer layer]; + self.glowLayer.frame = CGRectInset(self.avatarImageView.frame, -8, -8); + self.glowLayer.cornerRadius = 68; + self.glowLayer.backgroundColor = [color colorWithAlphaComponent:0.75].CGColor; + + + [self.layer insertSublayer:self.glowLayer below:self.avatarImageView.layer]; + } else { + + self.glowLayer.backgroundColor = [color colorWithAlphaComponent:0.75].CGColor; + } + + + [self.glowLayer removeAllAnimations]; + + + CAAnimationGroup *breathingGroup = [CAAnimationGroup animation]; + breathingGroup.duration = 1.8; + breathingGroup.repeatCount = HUGE_VALF; + breathingGroup.autoreverses = YES; + breathingGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + + + CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:@"opacity"]; + opacityAnim.fromValue = @(0.65); + opacityAnim.toValue = @(1.0); + + + CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; + scaleAnim.fromValue = @(1.0); + scaleAnim.toValue = @(1.1); + + breathingGroup.animations = @[opacityAnim, scaleAnim]; + + [self.glowLayer addAnimation:breathingGroup forKey:@"breathing"]; + + NSLog(@"[EPMineHeaderView] 启动呼吸光晕动效"); +} + + +- (UIColor *)colorFromHex:(NSString *)hexString { + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 + green:((rgbValue & 0xFF00) >> 8)/255.0 + blue:(rgbValue & 0xFF)/255.0 + alpha:1.0]; +} + +- (void)settingsButtonTapped { + NSLog(@"[EPMineHeaderView] 设置按钮点击"); + + if (self.onSettingsButtonTapped) { + self.onSettingsButtonTapped(); + } +} + +@end diff --git a/YuMi/E-P/NewMine/Views/EPMineHeaderView.m b/YuMi/E-P/Mine/Views/EPMineHeaderView.m.backup similarity index 100% rename from YuMi/E-P/NewMine/Views/EPMineHeaderView.m rename to YuMi/E-P/Mine/Views/EPMineHeaderView.m.backup diff --git a/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.h b/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.h new file mode 100644 index 0000000..36d3f87 --- /dev/null +++ b/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.h @@ -0,0 +1,19 @@ + + +// Created by AI on 2025-10-10. + + +#import + +NS_ASSUME_NONNULL_BEGIN + + +extern NSString *const EPMomentPublishSuccessNotification; + + +@interface EPMomentPublishViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentPublishViewController.h b/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Controllers/EPMomentPublishViewController.h rename to YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.h.backup diff --git a/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.m b/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.m new file mode 100644 index 0000000..d0b7218 --- /dev/null +++ b/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.m @@ -0,0 +1,435 @@ + + +// Created by AI on 2025-10-10. + + +// NOTE: 话题选择功能未实现 + + +#import "EPMomentPublishViewController.h" +#import +#import +#import "DJDKMIMOMColor.h" +#import "SZTextView.h" +#import "YuMi-Swift.h" +#import "EPEmotionColorPicker.h" +#import "EPEmotionColorStorage.h" +#import "UIView+GradientLayer.h" + + +NSString *const EPMomentPublishSuccessNotification = @"EPMomentPublishSuccessNotification"; + +@interface EPMomentPublishViewController () + +@property (nonatomic, strong) UIView *navView; +@property (nonatomic, strong) UIButton *backButton; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIButton *publishButton; + +@property (nonatomic, strong) UIView *contentView; +@property (nonatomic, strong) SZTextView *textView; +@property (nonatomic, strong) UILabel *limitLabel; +@property (nonatomic, strong) UIView *lineView; +@property (nonatomic, strong) UIButton *emotionButton; +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) NSMutableArray *images; +@property (nonatomic, strong) NSMutableArray *selectedAssets; +@property (nonatomic, copy) NSString *selectedEmotionColor; + +@property (nonatomic, assign) BOOL hasAddedGradient; + +@end + +@implementation EPMomentPublishViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor colorWithRed:0x0C/255.0 green:0x05/255.0 blue:0x27/255.0 alpha:1.0]; + [self setupUI]; + + + [self loadUserSignatureColor]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + + if (!self.hasAddedGradient && self.publishButton.bounds.size.width > 0) { + + + [self.publishButton addGradientBackgroundWithColors:@[ + [UIColor colorWithRed:0xF8/255.0 green:0x54/255.0 blue:0xFC/255.0 alpha:1.0], + [UIColor colorWithRed:0x50/255.0 green:0x0F/255.0 blue:0xFF/255.0 alpha:1.0] + ] startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5) cornerRadius:25]; + + self.hasAddedGradient = YES; + } +} + + +- (void)loadUserSignatureColor { + NSString *signatureColor = [EPEmotionColorStorage userSignatureColor]; + if (signatureColor) { + self.selectedEmotionColor = signatureColor; + [self updateEmotionButtonAppearance]; + NSLog(@"[Publish] 自动选中专属颜色: %@", signatureColor); + } +} + +- (void)setupUI { + [self.view addSubview:self.navView]; + [self.view addSubview:self.contentView]; + [self.navView addSubview:self.backButton]; + [self.navView addSubview:self.titleLabel]; + + [self.contentView addSubview:self.textView]; + [self.contentView addSubview:self.limitLabel]; + [self.contentView addSubview:self.lineView]; + [self.contentView addSubview:self.emotionButton]; + [self.contentView addSubview:self.collectionView]; + [self.contentView addSubview:self.publishButton]; + + [self.navView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.equalTo(self.view); + make.height.mas_equalTo(kNavigationHeight); + }]; + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.view).offset(10); + make.top.mas_equalTo(statusbarHeight); + make.size.mas_equalTo(CGSizeMake(44, 44)); + }]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.navView); + make.centerY.equalTo(self.backButton); + }]; + + [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.view); + make.top.equalTo(self.navView.mas_bottom); + make.bottom.equalTo(self.view); + }]; + [self.textView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.contentView).inset(15); + make.top.equalTo(self.contentView).offset(10); + make.height.mas_equalTo(150); + }]; + [self.limitLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.textView.mas_bottom).offset(5); + make.trailing.equalTo(self.textView); + }]; + [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.limitLabel.mas_bottom).offset(10); + make.leading.trailing.equalTo(self.textView); + make.height.mas_equalTo(1); + }]; + + + [self.emotionButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.contentView).inset(15); + make.top.equalTo(self.lineView.mas_bottom).offset(10); + make.height.mas_equalTo(44); + }]; + + + CGFloat itemW = (KScreenWidth - 15*2 - 10*2)/3.0; + CGFloat collectionHeight = itemW * 3 + 10 * 2; + + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.contentView).inset(15); + make.top.equalTo(self.emotionButton.mas_bottom).offset(10); + make.height.mas_equalTo(collectionHeight); + }]; + + + [self.publishButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.view).inset(20); + make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-20); + make.height.mas_equalTo(50); + }]; +} + +#pragma mark - Actions + +- (void)onBack { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)onEmotionButtonTapped { + EPEmotionColorPicker *picker = [[EPEmotionColorPicker alloc] init]; + + + picker.preselectedColor = self.selectedEmotionColor; + + __weak typeof(self) weakSelf = self; + picker.onColorSelected = ^(NSString *hexColor) { + __strong typeof(weakSelf) self = weakSelf; + self.selectedEmotionColor = hexColor; + [self updateEmotionButtonAppearance]; + }; + [picker showInView:self.view]; +} + +- (void)updateEmotionButtonAppearance { + if (self.selectedEmotionColor) { + + UIColor *color = [self colorFromHex:self.selectedEmotionColor]; + + + UIView *colorDot = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; + colorDot.backgroundColor = color; + colorDot.layer.cornerRadius = 10; + colorDot.layer.masksToBounds = YES; + colorDot.layer.borderWidth = 2; + colorDot.layer.borderColor = [UIColor whiteColor].CGColor; + + + UIGraphicsBeginImageContextWithOptions(colorDot.bounds.size, NO, 0); + [colorDot.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *colorDotImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [self.emotionButton setImage:colorDotImage forState:UIControlStateNormal]; + + + NSString *emotionName = [EPEmotionColorStorage emotionNameForColor:self.selectedEmotionColor]; + NSString *title = emotionName + ? [NSString stringWithFormat:@" Selected Emotion: %@", emotionName] + : @" Emotion Selected"; + [self.emotionButton setTitle:title forState:UIControlStateNormal]; + } else { + [self.emotionButton setImage:nil forState:UIControlStateNormal]; + [self.emotionButton setTitle:@"🎨 Add Emotion" forState:UIControlStateNormal]; + } +} + +- (UIColor *)colorFromHex:(NSString *)hexString { + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 + green:((rgbValue & 0xFF00) >> 8)/255.0 + blue:(rgbValue & 0xFF)/255.0 + alpha:1.0]; +} + +- (void)onPublish { + [self.view endEditing:YES]; + + + if (self.textView.text.length == 0 && self.images.count == 0) { + [EPProgressHUD showError:YMLocalizedString(@"publish.content_or_image_required")]; + return; + } + + + EPMomentAPISwiftHelper *apiHelper = [[EPMomentAPISwiftHelper alloc] init]; + + + NSString *emotionColorToSave = self.selectedEmotionColor; + + if (self.images.count > 0) { + + [[EPSDKManager shared] uploadImages:self.images + progress:^(NSInteger uploaded, NSInteger total) { + [EPProgressHUD showProgress:uploaded total:total]; + } + success:^(NSArray *resList) { + [EPProgressHUD dismiss]; + [apiHelper publishMomentWithType:@"2" + content:self.textView.text ?: @"" + resList:resList + completion:^{ + + if (emotionColorToSave) { + [self savePendingEmotionColor:emotionColorToSave]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:EPMomentPublishSuccessNotification object:nil]; + [self dismissViewControllerAnimated:YES completion:nil]; + } failure:^(NSInteger code, NSString *msg) { + // TODO: 显示错误 Toast + NSLog(@"发布失败: %ld - %@", (long)code, msg); + }]; + } + failure:^(NSString *errorMsg) { + [EPProgressHUD dismiss]; + // TODO: 显示错误 Toast + NSLog(@"上传失败: %@", errorMsg); + }]; + } else { + + [apiHelper publishMomentWithType:@"0" + content:self.textView.text + resList:@[] + completion:^{ + + if (emotionColorToSave) { + [self savePendingEmotionColor:emotionColorToSave]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:EPMomentPublishSuccessNotification object:nil]; + [self dismissViewControllerAnimated:YES completion:nil]; + } failure:^(NSInteger code, NSString *msg) { + // TODO: 显示错误 Toast + NSLog(@"发布失败: %ld - %@", (long)code, msg); + }]; + } +} + + +- (void)savePendingEmotionColor:(NSString *)color { + [[NSUserDefaults standardUserDefaults] setObject:color forKey:@"EP_Pending_Emotion_Color"]; + [[NSUserDefaults standardUserDefaults] setObject:@([[NSDate date] timeIntervalSince1970]) forKey:@"EP_Pending_Emotion_Timestamp"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +#pragma mark - UICollectionView + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.images.count + 1; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ep.publish.cell" forIndexPath:indexPath]; + cell.contentView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.06]; + cell.contentView.layer.cornerRadius = 12; + + for (UIView *sub in cell.contentView.subviews) { [sub removeFromSuperview]; } + BOOL showAdd = (self.images.count < 9) && (indexPath.item == self.images.count); + if (showAdd) { + UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon_moment_addphoto"]]; + iv.contentMode = UIViewContentModeScaleAspectFill; + iv.clipsToBounds = YES; + [cell.contentView addSubview:iv]; + [iv mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(cell.contentView); }]; + } else { + UIImageView *iv = [[UIImageView alloc] init]; + iv.contentMode = UIViewContentModeScaleAspectFill; + iv.layer.masksToBounds = YES; + [cell.contentView addSubview:iv]; + [iv mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(cell.contentView); }]; + NSInteger idx = MIN(indexPath.item, (NSInteger)self.images.count - 1); + if (idx >= 0 && idx < self.images.count) iv.image = self.images[idx]; + } + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.item == self.images.count) { + TZImagePickerController *picker = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:self]; + picker.allowPickingVideo = NO; + picker.allowTakeVideo = NO; + picker.selectedAssets = self.selectedAssets; + picker.maxImagesCount = 9; + [self presentViewController:picker animated:YES completion:nil]; + } +} + +#pragma mark - TZImagePickerControllerDelegate +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray *)infos { + + for (NSInteger i = 0; i < assets.count; i++) { + id asset = assets[i]; + UIImage *img = [photos xpSafeObjectAtIndex:i] ?: photos[i]; + if (![self.selectedAssets containsObject:asset] && self.images.count < 9) { + [self.selectedAssets addObject:asset]; + [self.images addObject:img]; + } + } + [self.collectionView reloadData]; +} + +#pragma mark - UITextViewDelegate +- (void)textViewDidChange:(UITextView *)textView { + if (textView.text.length > 500) { + textView.text = [textView.text substringToIndex:500]; + } + self.limitLabel.text = [NSString stringWithFormat:@"%lu/500", (unsigned long)textView.text.length]; +} + +#pragma mark - Lazy + +- (UIView *)navView { if (!_navView) { _navView = [UIView new]; _navView.backgroundColor = [UIColor clearColor]; } return _navView; } +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + + UIImage *backImage = [UIImage systemImageNamed:@"chevron.left"]; + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:20 weight:UIImageSymbolWeightMedium]; + backImage = [backImage imageByApplyingSymbolConfiguration:config]; + [_backButton setImage:backImage forState:UIControlStateNormal]; + [_backButton setTintColor:[UIColor whiteColor]]; + [_backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside]; + } + return _backButton; +} +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.text = YMLocalizedString(@"publish.title"); + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.font = [UIFont systemFontOfSize:17]; + } + return _titleLabel; +} +- (UIButton *)publishButton { + if (!_publishButton) { + _publishButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_publishButton setTitle:YMLocalizedString(@"common.publish") forState:UIControlStateNormal]; + [_publishButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _publishButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium]; + _publishButton.layer.cornerRadius = 25; + _publishButton.layer.masksToBounds = NO; + + [_publishButton addTarget:self action:@selector(onPublish) forControlEvents:UIControlEventTouchUpInside]; + } + return _publishButton; +} +- (UIView *)contentView { if (!_contentView) { _contentView = [UIView new]; _contentView.backgroundColor = [UIColor clearColor]; } return _contentView; } +- (SZTextView *)textView { + if (!_textView) { + _textView = [SZTextView new]; + _textView.placeholder = @"Enter Content"; + _textView.textColor = [UIColor whiteColor]; + _textView.placeholderTextColor = [[UIColor whiteColor] colorWithAlphaComponent:0.4]; + _textView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.08]; + _textView.layer.cornerRadius = 12; + _textView.layer.masksToBounds = YES; + _textView.font = [UIFont systemFontOfSize:15]; + _textView.delegate = self; + } + return _textView; +} +- (UILabel *)limitLabel { + if (!_limitLabel) { + _limitLabel = [UILabel new]; + _limitLabel.text = @"0/500"; + _limitLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6]; + _limitLabel.font = [UIFont systemFontOfSize:12]; + } + return _limitLabel; +} +- (UIView *)lineView { if (!_lineView) { _lineView = [UIView new]; _lineView.backgroundColor = [DJDKMIMOMColor dividerColor]; } return _lineView; } +- (UIButton *)emotionButton { + if (!_emotionButton) { + _emotionButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_emotionButton setTitle:@"🎨 Add Emotion" forState:UIControlStateNormal]; + [_emotionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _emotionButton.titleLabel.font = [UIFont systemFontOfSize:15]; + _emotionButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + _emotionButton.contentEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0); + _emotionButton.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.08]; + _emotionButton.layer.cornerRadius = 8; + _emotionButton.layer.masksToBounds = YES; + [_emotionButton addTarget:self action:@selector(onEmotionButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _emotionButton; +} +- (UICollectionView *)collectionView { if (!_collectionView) { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.minimumLineSpacing = 10; layout.minimumInteritemSpacing = 10; CGFloat itemW = (KScreenWidth - 15*2 - 10*2)/3.0; layout.itemSize = CGSizeMake(itemW, itemW); _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; _collectionView.delegate = self; _collectionView.dataSource = self; _collectionView.backgroundColor = [UIColor clearColor]; [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"ep.publish.cell"]; } return _collectionView; } +- (NSMutableArray *)images { if (!_images) { _images = [NSMutableArray array]; } return _images; } +- (NSMutableArray *)selectedAssets { if (!_selectedAssets) { _selectedAssets = [NSMutableArray array]; } return _selectedAssets; } + +@end + diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentPublishViewController.m b/YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Controllers/EPMomentPublishViewController.m rename to YuMi/E-P/Moments/Controllers/EPMomentPublishViewController.m.backup diff --git a/YuMi/E-P/Moments/Controllers/EPMomentViewController.h b/YuMi/E-P/Moments/Controllers/EPMomentViewController.h new file mode 100644 index 0000000..4b0c1c4 --- /dev/null +++ b/YuMi/E-P/Moments/Controllers/EPMomentViewController.h @@ -0,0 +1,16 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface EPMomentViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.h b/YuMi/E-P/Moments/Controllers/EPMomentViewController.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Controllers/EPMomentViewController.h rename to YuMi/E-P/Moments/Controllers/EPMomentViewController.h.backup diff --git a/YuMi/E-P/Moments/Controllers/EPMomentViewController.m b/YuMi/E-P/Moments/Controllers/EPMomentViewController.m new file mode 100644 index 0000000..e51b53c --- /dev/null +++ b/YuMi/E-P/Moments/Controllers/EPMomentViewController.m @@ -0,0 +1,190 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import "EPMomentViewController.h" +#import +#import +#import "EPMomentCell.h" +#import "EPMomentListView.h" +#import "EPMomentPublishViewController.h" +#import "YUMIMacroUitls.h" + +@interface EPMomentViewController () + +// MARK: - UI Components + + +@property (nonatomic, strong) EPMomentListView *listView; + + +@property (nonatomic, strong) UIImageView *topIconImageView; + + +@property (nonatomic, strong) UILabel *topTipLabel; + +@end + +@implementation EPMomentViewController + +// MARK: - Lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.title = @"Enjoy your Life Time"; + + + [self.navigationController.navigationBar setTitleTextAttributes:@{ + NSForegroundColorAttributeName: [UIColor whiteColor] + }]; + + [self setupUI]; + [self.listView reloadFirstPage]; + + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onMomentPublishSuccess:) + name:EPMomentPublishSuccessNotification + object:nil]; + + + [self scheduleAutoRefreshIfNeeded]; + + NSLog(@"[EPMomentViewController] 页面加载完成"); +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; +} + +// MARK: - Setup UI + +- (void)setupUI { + UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; + bgImageView.contentMode = UIViewContentModeScaleAspectFill; + bgImageView.clipsToBounds = YES; + [self.view addSubview:bgImageView]; + [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.view); + }]; + + + [self.view addSubview:self.topIconImageView]; + [self.topIconImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(14); + make.size.mas_equalTo(CGSizeMake(56, 41)); + }]; + + + [self.view addSubview:self.topTipLabel]; + [self.topTipLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.topIconImageView.mas_bottom).offset(14); + make.leading.trailing.equalTo(self.view).inset(20); + }]; + + + [self.view addSubview:self.listView]; + [self.listView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.equalTo(self.view); + make.top.equalTo(self.topTipLabel.mas_bottom).offset(8); + }]; + + + UIImage *addIcon = [UIImage imageNamed:@"icon_moment_add"]; + UIButton *publishButton = [UIButton buttonWithType:UIButtonTypeCustom]; + publishButton.contentMode = UIViewContentModeScaleAspectFit; + [publishButton setImage:addIcon forState:UIControlStateNormal]; + publishButton.frame = CGRectMake(0, 0, 40, 40); + [publishButton addTarget:self action:@selector(onPublishButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + UIBarButtonItem *publishItem = [[UIBarButtonItem alloc] initWithCustomView:publishButton]; + self.navigationItem.rightBarButtonItem = publishItem; + + NSLog(@"[EPMomentViewController] UI 设置完成"); +} + + +// MARK: - Auto Refresh + + +- (void)scheduleAutoRefreshIfNeeded { + __weak typeof(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf) self = weakSelf; + if (!self) return; + + + if (self.listView.rawList.count == 0) { + NSLog(@"[EPMomentViewController] ⚠️ 冷启动 1 秒后检测到无数据,自动刷新一次"); + [self.listView reloadFirstPage]; + } else { + NSLog(@"[EPMomentViewController] ✅ 冷启动 1 秒后检测到已有 %lu 条数据,无需刷新", (unsigned long)self.listView.rawList.count); + } + }); +} + +// MARK: - Actions + +- (void)onPublishButtonTapped { + NSLog(@"[EPMomentViewController] 发布按钮点击"); + EPMomentPublishViewController *vc = [[EPMomentPublishViewController alloc] init]; + vc.modalPresentationStyle = UIModalPresentationFullScreen; + [self.navigationController presentViewController:vc animated:YES completion:nil]; +} + +- (void)showAlertWithMessage:(NSString *)message { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:YMLocalizedString(@"common.tips") + message:message + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:YMLocalizedString(@"common.confirm") style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void)onMomentPublishSuccess:(NSNotification *)notification { + NSLog(@"[EPMomentViewController] 收到发布成功通知,刷新列表"); + [self.listView reloadFirstPage]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + + +// MARK: - Lazy Loading + +- (EPMomentListView *)listView { + if (!_listView) { + _listView = [[EPMomentListView alloc] initWithFrame:CGRectZero]; + + _listView.onSelectMoment = ^(NSInteger index) { + + + }; + } + return _listView; +} + +- (UIImageView *)topIconImageView { + if (!_topIconImageView) { + _topIconImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon_moment_Volume"]]; + _topIconImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _topIconImageView; +} + +- (UILabel *)topTipLabel { + if (!_topTipLabel) { + _topTipLabel = [UILabel new]; + _topTipLabel.numberOfLines = 0; + _topTipLabel.textColor = [UIColor whiteColor]; + _topTipLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightRegular]; + _topTipLabel.text = @"In the quiet gallery of the heart, we learn to see the colors of emotion. And in the shared silence between souls, we begin to find the sound of resonance. This is more than an app—it's a space where your inner world is both a masterpiece and a melody."; + } + return _topTipLabel; +} + + +@end diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m b/YuMi/E-P/Moments/Controllers/EPMomentViewController.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m rename to YuMi/E-P/Moments/Controllers/EPMomentViewController.m.backup diff --git a/YuMi/E-P/Moments/Services/EPEmotionColorStorage.h b/YuMi/E-P/Moments/Services/EPEmotionColorStorage.h new file mode 100644 index 0000000..75ca157 --- /dev/null +++ b/YuMi/E-P/Moments/Services/EPEmotionColorStorage.h @@ -0,0 +1,47 @@ + + +// Created by AI on 2025-10-14. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EPEmotionColorStorage : NSObject + + ++ (void)saveColor:(NSString *)hexColor forDynamicId:(NSString *)dynamicId; + + ++ (nullable NSString *)colorForDynamicId:(NSString *)dynamicId; + + ++ (void)removeColorForDynamicId:(NSString *)dynamicId; + + ++ (NSArray *)allEmotionColors; + + ++ (NSString *)randomEmotionColor; + + ++ (nullable NSString *)emotionNameForColor:(NSString *)hexColor; + +#pragma mark - User Signature Color + + ++ (void)saveUserSignatureColor:(NSString *)hexColor; + + ++ (nullable NSString *)userSignatureColor; + + ++ (BOOL)hasUserSignatureColor; + + ++ (void)clearUserSignatureColor; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Services/EPEmotionColorStorage.h b/YuMi/E-P/Moments/Services/EPEmotionColorStorage.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Services/EPEmotionColorStorage.h rename to YuMi/E-P/Moments/Services/EPEmotionColorStorage.h.backup diff --git a/YuMi/E-P/Moments/Services/EPEmotionColorStorage.m b/YuMi/E-P/Moments/Services/EPEmotionColorStorage.m new file mode 100644 index 0000000..9167452 --- /dev/null +++ b/YuMi/E-P/Moments/Services/EPEmotionColorStorage.m @@ -0,0 +1,116 @@ + + +// Created by AI on 2025-10-14. + + +#import "EPEmotionColorStorage.h" + +static NSString *const kEmotionColorStorageKey = @"EP_Emotion_Colors"; +static NSString *const kUserSignatureColorKey = @"EP_User_Signature_Color"; +static NSString *const kUserSignatureTimestampKey = @"EP_User_Signature_Timestamp"; + +@implementation EPEmotionColorStorage + +#pragma mark - Public Methods + ++ (void)saveColor:(NSString *)hexColor forDynamicId:(NSString *)dynamicId { + if (!hexColor || !dynamicId) return; + + NSMutableDictionary *colorDict = [[self loadColorDictionary] mutableCopy]; + colorDict[dynamicId] = hexColor; + + [[NSUserDefaults standardUserDefaults] setObject:colorDict forKey:kEmotionColorStorageKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + ++ (NSString *)colorForDynamicId:(NSString *)dynamicId { + if (!dynamicId) return nil; + + NSDictionary *colorDict = [self loadColorDictionary]; + return colorDict[dynamicId]; +} + ++ (void)removeColorForDynamicId:(NSString *)dynamicId { + if (!dynamicId) return; + + NSMutableDictionary *colorDict = [[self loadColorDictionary] mutableCopy]; + [colorDict removeObjectForKey:dynamicId]; + + [[NSUserDefaults standardUserDefaults] setObject:colorDict forKey:kEmotionColorStorageKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + ++ (NSArray *)allEmotionColors { + return @[ + @"#FFD700", + @"#4A90E2", + @"#E74C3C", + @"#9B59B6", + @"#FF9A3D", + @"#2ECC71", + @"#3498DB", + @"#F39C12" + ]; +} + ++ (NSString *)randomEmotionColor { + NSArray *colors = [self allEmotionColors]; + uint32_t randomIndex = arc4random_uniform((uint32_t)colors.count); + return colors[randomIndex]; +} + ++ (NSString *)emotionNameForColor:(NSString *)hexColor { + if (!hexColor || hexColor.length == 0) return nil; + + NSArray *colors = [self allEmotionColors]; + NSArray *emotions = @[@"Joy", @"Sadness", @"Anger", @"Fear", @"Surprise", @"Disgust", @"Trust", @"Anticipation"]; + + + NSString *upperHex = [hexColor uppercaseString]; + for (NSInteger i = 0; i < colors.count; i++) { + if ([[colors[i] uppercaseString] isEqualToString:upperHex]) { + return emotions[i]; + } + } + + return nil; +} + +#pragma mark - Private Methods + ++ (NSDictionary *)loadColorDictionary { + NSDictionary *dict = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kEmotionColorStorageKey]; + return dict ?: @{}; +} + +#pragma mark - User Signature Color + ++ (void)saveUserSignatureColor:(NSString *)hexColor { + if (!hexColor) return; + + [[NSUserDefaults standardUserDefaults] setObject:hexColor forKey:kUserSignatureColorKey]; + [[NSUserDefaults standardUserDefaults] setObject:@([[NSDate date] timeIntervalSince1970]) + forKey:kUserSignatureTimestampKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + NSLog(@"[EPEmotionColorStorage] 保存用户专属颜色: %@", hexColor); +} + ++ (NSString *)userSignatureColor { + return [[NSUserDefaults standardUserDefaults] stringForKey:kUserSignatureColorKey]; +} + ++ (BOOL)hasUserSignatureColor { + return [self userSignatureColor] != nil; +} + ++ (void)clearUserSignatureColor { + [[NSUserDefaults standardUserDefaults] removeObjectForKey:kUserSignatureColorKey]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:kUserSignatureTimestampKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + NSLog(@"[EPEmotionColorStorage] 清除用户专属颜色"); +} + +@end + diff --git a/YuMi/E-P/NewMoments/Services/EPEmotionColorStorage.m b/YuMi/E-P/Moments/Services/EPEmotionColorStorage.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Services/EPEmotionColorStorage.m rename to YuMi/E-P/Moments/Services/EPEmotionColorStorage.m.backup diff --git a/YuMi/E-P/Moments/Services/EPMomentAPISwiftHelper.swift b/YuMi/E-P/Moments/Services/EPMomentAPISwiftHelper.swift new file mode 100644 index 0000000..a65c6ea --- /dev/null +++ b/YuMi/E-P/Moments/Services/EPMomentAPISwiftHelper.swift @@ -0,0 +1,90 @@ + + +// Created by AI on 2025-10-11. + + +import Foundation + + +@objc class EPMomentAPISwiftHelper: NSObject { + + + @objc func fetchLatestMomentsWithNextID( + _ nextID: String, + completion: @escaping ([MomentsInfoModel], String) -> Void, + failure: @escaping (Int, String) -> Void + ) { + let pageSize = "20" + let types = "0,2" + + Api.momentsLatestList({ (data, code, msg) in + if code == 200, let dict = data?.data as? NSDictionary { + + + if let listInfo = MomentsListInfoModel.mj_object(withKeyValues: dict) { + let dynamicList = listInfo.dynamicList + let nextDynamicId = listInfo.nextDynamicId + completion(dynamicList, nextDynamicId) + } else { + + completion([], "") + } + } else { + failure(Int(code), msg ?? YMLocalizedString("error.request_failed")) + } + }, dynamicId: nextID, pageSize: pageSize, types: types) + } + + + @objc func publishMoment( + type: String, + content: String, + resList: [[String: Any]], + completion: @escaping () -> Void, + failure: @escaping (Int, String) -> Void + ) { + guard let uid = AccountInfoStorage.instance().getUid() else { + failure(-1, YMLocalizedString("error.not_logged_in")) + return + } + + + // NOTE: 旧版本 XPMonentsPublishViewController 包含话题选择功能 + + + Api.momentsPublish({ (data, code, msg) in + if code == 200 { + completion() + } else { + failure(Int(code), msg ?? YMLocalizedString("error.publish_failed")) + } + }, uid: uid, type: type, worldId: "", content: content, resList: resList) + } + + + @objc func likeMoment( + dynamicId: String, + isLike: Bool, + likedUid: String, + worldId: Int, + completion: @escaping () -> Void, + failure: @escaping (Int, String) -> Void + ) { + guard let uid = AccountInfoStorage.instance().getUid() else { + failure(-1, YMLocalizedString("error.not_logged_in")) + return + } + + let status = isLike ? "1" : "0" + let worldIdStr = String(format: "%ld", worldId) + + Api.momentsLike({ (data, code, msg) in + if code == 200 { + completion() + } else { + failure(Int(code), msg ?? YMLocalizedString("error.like_failed")) + } + }, dynamicId: dynamicId, uid: uid, status: status, likedUid: likedUid, worldId: worldIdStr) + } +} + diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPISwiftHelper.swift b/YuMi/E-P/Moments/Services/EPMomentAPISwiftHelper.swift.backup similarity index 100% rename from YuMi/E-P/NewMoments/Services/EPMomentAPISwiftHelper.swift rename to YuMi/E-P/Moments/Services/EPMomentAPISwiftHelper.swift.backup diff --git a/YuMi/E-P/Moments/Views/EPEmotionColorPicker.h b/YuMi/E-P/Moments/Views/EPEmotionColorPicker.h new file mode 100644 index 0000000..11c428a --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPEmotionColorPicker.h @@ -0,0 +1,27 @@ + + +// Created by AI on 2025-10-14. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EPEmotionColorPicker : UIView + + +@property (nonatomic, copy) void(^onColorSelected)(NSString *hexColor); + + +@property (nonatomic, copy) NSString *preselectedColor; + + +- (void)showInView:(UIView *)parentView; + + +- (void)dismiss; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Views/EPEmotionColorPicker.h b/YuMi/E-P/Moments/Views/EPEmotionColorPicker.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPEmotionColorPicker.h rename to YuMi/E-P/Moments/Views/EPEmotionColorPicker.h.backup diff --git a/YuMi/E-P/Moments/Views/EPEmotionColorPicker.m b/YuMi/E-P/Moments/Views/EPEmotionColorPicker.m new file mode 100644 index 0000000..5ef98bb --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPEmotionColorPicker.m @@ -0,0 +1,300 @@ + + +// Created by AI on 2025-10-14. + + +#import "EPEmotionColorPicker.h" +#import "EPEmotionColorWheelView.h" +#import "EPEmotionInfoView.h" +#import + +@interface EPEmotionColorPicker () + +@property (nonatomic, strong) UIView *backgroundMask; +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIButton *infoButton; +@property (nonatomic, strong) UIView *selectedColorView; +@property (nonatomic, strong) UILabel *selectedColorLabel; +@property (nonatomic, strong) UIButton *okButton; +@property (nonatomic, strong) EPEmotionColorWheelView *colorWheelView; +@property (nonatomic, copy) NSString *currentSelectedColor; +@property (nonatomic, assign) NSInteger currentSelectedIndex; + +@end + +@implementation EPEmotionColorPicker + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + self.backgroundColor = [UIColor clearColor]; + + + [self addSubview:self.backgroundMask]; + [self.backgroundMask mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + + + [self addSubview:self.containerView]; + [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.equalTo(self); + make.height.mas_equalTo(450); + }]; + + + [self.containerView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.containerView).offset(20); + make.centerX.equalTo(self.containerView); + }]; + + + [self.containerView addSubview:self.infoButton]; + [self.infoButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.containerView).offset(16); + make.centerY.equalTo(self.titleLabel); + make.size.mas_equalTo(CGSizeMake(28, 28)); + }]; + + + [self.containerView addSubview:self.okButton]; + [self.okButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.equalTo(self.containerView).offset(-16); + make.centerY.equalTo(self.titleLabel); + make.size.mas_equalTo(CGSizeMake(60, 32)); + }]; + + + [self.containerView addSubview:self.selectedColorView]; + [self.selectedColorView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(20); + make.centerX.equalTo(self.containerView); + make.height.mas_equalTo(50); + make.leading.trailing.equalTo(self.containerView).inset(20); + }]; + + + [self.containerView addSubview:self.colorWheelView]; + [self.colorWheelView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.containerView); + make.top.equalTo(self.selectedColorView.mas_bottom).offset(20); + make.size.mas_equalTo(CGSizeMake(280, 280)); + }]; +} + +#pragma mark - Actions + +- (void)onBackgroundTapped { + [self dismiss]; +} + +- (void)onInfoButtonTapped { + EPEmotionInfoView *infoView = [[EPEmotionInfoView alloc] init]; + [infoView showInView:self]; +} + +- (void)onOkButtonTapped { + if (self.currentSelectedColor && self.onColorSelected) { + self.onColorSelected(self.currentSelectedColor); + } + [self dismiss]; +} + +#pragma mark - Public Methods + +- (void)showInView:(UIView *)parentView { + [parentView addSubview:self]; + [self mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(parentView); + }]; + + + self.backgroundMask.alpha = 0; + self.containerView.transform = CGAffineTransformMakeTranslation(0, 450); + + + [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.backgroundMask.alpha = 1; + self.containerView.transform = CGAffineTransformIdentity; + } completion:nil]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ + self.backgroundMask.alpha = 0; + self.containerView.transform = CGAffineTransformMakeTranslation(0, 450); + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +#pragma mark - Lazy Loading + +- (UIView *)backgroundMask { + if (!_backgroundMask) { + _backgroundMask = [[UIView alloc] init]; + _backgroundMask.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onBackgroundTapped)]; + [_backgroundMask addGestureRecognizer:tap]; + } + return _backgroundMask; +} + +- (UIView *)containerView { + if (!_containerView) { + _containerView = [[UIView alloc] init]; + _containerView.backgroundColor = [UIColor colorWithRed:0x0C/255.0 green:0x05/255.0 blue:0x27/255.0 alpha:1.0]; + _containerView.layer.cornerRadius = 20; + _containerView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner; + _containerView.layer.masksToBounds = YES; + } + return _containerView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = @"Choose your emotion"; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UIButton *)infoButton { + if (!_infoButton) { + _infoButton = [UIButton buttonWithType:UIButtonTypeCustom]; + + + UIImage *infoIcon = [UIImage systemImageNamed:@"info.circle"]; + [_infoButton setImage:infoIcon forState:UIControlStateNormal]; + _infoButton.tintColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7]; + + + [_infoButton addTarget:self action:@selector(onInfoButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _infoButton; +} + +- (UIView *)selectedColorView { + if (!_selectedColorView) { + _selectedColorView = [[UIView alloc] init]; + _selectedColorView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.1]; + _selectedColorView.layer.cornerRadius = 25; + _selectedColorView.layer.masksToBounds = YES; + _selectedColorView.hidden = YES; + + + UIView *colorDot = [[UIView alloc] init]; + colorDot.tag = 100; + colorDot.layer.cornerRadius = 12; + colorDot.layer.masksToBounds = YES; + [_selectedColorView addSubview:colorDot]; + [colorDot mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(_selectedColorView).offset(15); + make.centerY.equalTo(_selectedColorView); + make.size.mas_equalTo(CGSizeMake(24, 24)); + }]; + + + [_selectedColorView addSubview:self.selectedColorLabel]; + [self.selectedColorLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(colorDot.mas_trailing).offset(12); + make.centerY.equalTo(_selectedColorView); + make.trailing.equalTo(_selectedColorView).offset(-15); + }]; + } + return _selectedColorView; +} + +- (UILabel *)selectedColorLabel { + if (!_selectedColorLabel) { + _selectedColorLabel = [[UILabel alloc] init]; + _selectedColorLabel.textColor = [UIColor whiteColor]; + _selectedColorLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _selectedColorLabel.text = @"Select an emotion"; + } + return _selectedColorLabel; +} + +- (UIButton *)okButton { + if (!_okButton) { + _okButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_okButton setTitle:@"OK" forState:UIControlStateNormal]; + [_okButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _okButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _okButton.backgroundColor = [UIColor colorWithRed:0x9B/255.0 green:0x59/255.0 blue:0xB6/255.0 alpha:1.0]; + _okButton.layer.cornerRadius = 16; + _okButton.layer.masksToBounds = YES; + _okButton.enabled = NO; + _okButton.alpha = 0.5; + [_okButton addTarget:self action:@selector(onOkButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _okButton; +} + +- (EPEmotionColorWheelView *)colorWheelView { + if (!_colorWheelView) { + _colorWheelView = [[EPEmotionColorWheelView alloc] init]; + _colorWheelView.radius = 100.0; + _colorWheelView.buttonSize = 50.0; + _colorWheelView.preselectedColor = self.preselectedColor; + + __weak typeof(self) weakSelf = self; + _colorWheelView.onColorTapped = ^(NSString *hexColor, NSInteger index) { + __strong typeof(weakSelf) self = weakSelf; + + + self.currentSelectedColor = hexColor; + self.currentSelectedIndex = index; + + + [self updateSelectedColorDisplay:hexColor index:index]; + }; + } + return _colorWheelView; +} + + +- (void)updateSelectedColorDisplay:(NSString *)hexColor index:(NSInteger)index { + NSArray *emotions = @[@"Joy", @"Sadness", @"Anger", @"Fear", @"Surprise", @"Disgust", @"Trust", @"Anticipation"]; + + + self.selectedColorView.hidden = NO; + + + UIView *colorDot = [self.selectedColorView viewWithTag:100]; + colorDot.backgroundColor = [self colorFromHex:hexColor]; + + + self.selectedColorLabel.text = emotions[index]; + + + self.okButton.enabled = YES; + self.okButton.alpha = 1.0; +} + + +- (UIColor *)colorFromHex:(NSString *)hexString { + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 + green:((rgbValue & 0xFF00) >> 8)/255.0 + blue:(rgbValue & 0xFF)/255.0 + alpha:1.0]; +} + +@end + diff --git a/YuMi/E-P/NewMoments/Views/EPEmotionColorPicker.m b/YuMi/E-P/Moments/Views/EPEmotionColorPicker.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPEmotionColorPicker.m rename to YuMi/E-P/Moments/Views/EPEmotionColorPicker.m.backup diff --git a/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.h b/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.h new file mode 100644 index 0000000..b507863 --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.h @@ -0,0 +1,36 @@ + + +// Created by AI on 2025-10-15. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EPEmotionColorWheelView : UIView + +#pragma mark - Configuration + + +@property (nonatomic, assign) CGFloat radius; + + +@property (nonatomic, assign) CGFloat buttonSize; + + +@property (nonatomic, copy, nullable) NSString *preselectedColor; + +#pragma mark - Callbacks + + +@property (nonatomic, copy) void(^onColorTapped)(NSString *hexColor, NSInteger index); + +#pragma mark - Methods + + +- (void)reloadWithPreselectedColor:(nullable NSString *)color; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Views/EPEmotionColorWheelView.h b/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPEmotionColorWheelView.h rename to YuMi/E-P/Moments/Views/EPEmotionColorWheelView.h.backup diff --git a/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.m b/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.m new file mode 100644 index 0000000..c61e89b --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.m @@ -0,0 +1,145 @@ + + +// Created by AI on 2025-10-15. + + +#import "EPEmotionColorWheelView.h" +#import "EPEmotionColorStorage.h" + +@interface EPEmotionColorWheelView () + +@property (nonatomic, strong) NSMutableArray *colorButtons; +@property (nonatomic, assign) NSInteger selectedIndex; + +@end + +@implementation EPEmotionColorWheelView + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + + _radius = 80.0; + _buttonSize = 50.0; + _colorButtons = [NSMutableArray array]; + + self.backgroundColor = [UIColor clearColor]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + + if (self.colorButtons.count == 0) { + [self createColorButtons]; + } +} + +#pragma mark - Public Methods + +- (void)reloadWithPreselectedColor:(NSString *)color { + self.preselectedColor = color; + + + for (UIButton *btn in self.colorButtons) { + [btn removeFromSuperview]; + } + [self.colorButtons removeAllObjects]; + + + [self createColorButtons]; +} + +#pragma mark - Private Methods + +- (void)createColorButtons { + NSArray *colors = [EPEmotionColorStorage allEmotionColors]; + NSArray *emotions = @[@"Joy", @"Sadness", @"Anger", @"Fear", @"Surprise", @"Disgust", @"Trust", @"Anticipation"]; + + CGFloat angleStep = M_PI * 2.0 / colors.count; + CGFloat centerX = CGRectGetWidth(self.bounds) / 2.0; + CGFloat centerY = CGRectGetHeight(self.bounds) / 2.0; + + for (NSInteger i = 0; i < colors.count; i++) { + + CGFloat angle = angleStep * i - M_PI_2; + CGFloat x = centerX + self.radius * cos(angle) - self.buttonSize / 2.0; + CGFloat y = centerY + self.radius * sin(angle) - self.buttonSize / 2.0; + + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + button.frame = CGRectMake(x, y, self.buttonSize, self.buttonSize); + button.backgroundColor = [self colorFromHex:colors[i]]; + button.layer.cornerRadius = self.buttonSize / 2.0; + button.layer.masksToBounds = YES; + button.layer.borderWidth = 3.0; + button.layer.borderColor = [UIColor whiteColor].CGColor; + button.tag = i; + [button addTarget:self action:@selector(onButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + + + if (self.preselectedColor && [colors[i] isEqualToString:self.preselectedColor]) { + button.layer.borderWidth = 5.0; + button.transform = CGAffineTransformMakeScale(1.1, 1.1); + } + + + button.layer.shadowColor = [self colorFromHex:colors[i]].CGColor; + button.layer.shadowOffset = CGSizeMake(0, 2); + button.layer.shadowOpacity = 0.6; + button.layer.shadowRadius = 8; + button.layer.masksToBounds = NO; + + [self addSubview:button]; + [self.colorButtons addObject:button]; + } +} + +- (void)onButtonTapped:(UIButton *)sender { + NSInteger index = sender.tag; + self.selectedIndex = index; + + + [self updateSelectionState]; + + + NSArray *colors = [EPEmotionColorStorage allEmotionColors]; + NSString *selectedColor = colors[index]; + if (self.onColorTapped) { + self.onColorTapped(selectedColor, index); + } +} + + +- (void)updateSelectionState { + for (NSInteger i = 0; i < self.colorButtons.count; i++) { + UIButton *button = self.colorButtons[i]; + if (i == self.selectedIndex) { + + button.layer.borderWidth = 5.0; + button.transform = CGAffineTransformMakeScale(1.1, 1.1); + } else { + + button.layer.borderWidth = 3.0; + button.transform = CGAffineTransformIdentity; + } + } +} + +#pragma mark - Utilities + +- (UIColor *)colorFromHex:(NSString *)hexString { + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 + green:((rgbValue & 0xFF00) >> 8)/255.0 + blue:(rgbValue & 0xFF)/255.0 + alpha:1.0]; +} + +@end + diff --git a/YuMi/E-P/NewMoments/Views/EPEmotionColorWheelView.m b/YuMi/E-P/Moments/Views/EPEmotionColorWheelView.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPEmotionColorWheelView.m rename to YuMi/E-P/Moments/Views/EPEmotionColorWheelView.m.backup diff --git a/YuMi/E-P/Moments/Views/EPEmotionInfoView.h b/YuMi/E-P/Moments/Views/EPEmotionInfoView.h new file mode 100644 index 0000000..3b0a522 --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPEmotionInfoView.h @@ -0,0 +1,21 @@ + + +// Created by AI on 2025-10-16. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EPEmotionInfoView : UIView + + +- (void)showInView:(UIView *)parentView; + + +- (void)dismiss; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Views/EPEmotionInfoView.h b/YuMi/E-P/Moments/Views/EPEmotionInfoView.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPEmotionInfoView.h rename to YuMi/E-P/Moments/Views/EPEmotionInfoView.h.backup diff --git a/YuMi/E-P/Moments/Views/EPEmotionInfoView.m b/YuMi/E-P/Moments/Views/EPEmotionInfoView.m new file mode 100644 index 0000000..6c88200 --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPEmotionInfoView.m @@ -0,0 +1,211 @@ + + +// Created by AI on 2025-10-16. + + +#import "EPEmotionInfoView.h" +#import + +@interface EPEmotionInfoView () + +@property (nonatomic, strong) UIView *backgroundMask; +@property (nonatomic, strong) UIView *contentContainer; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, strong) UILabel *contentLabel; +@property (nonatomic, strong) UIButton *closeButton; + +@end + +@implementation EPEmotionInfoView + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + self.backgroundColor = [UIColor clearColor]; + + + [self addSubview:self.backgroundMask]; + [self.backgroundMask mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + + + [self addSubview:self.contentContainer]; + [self.contentContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self); + make.leading.trailing.equalTo(self).inset(30); + make.height.mas_lessThanOrEqualTo(500); + }]; + + + [self.contentContainer addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contentContainer).offset(24); + make.leading.trailing.equalTo(self.contentContainer).inset(20); + }]; + + + [self.contentContainer addSubview:self.scrollView]; + [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(16); + make.leading.trailing.equalTo(self.contentContainer).inset(20); + make.height.mas_lessThanOrEqualTo(320); + }]; + + + [self.scrollView addSubview:self.contentLabel]; + [self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.scrollView); + make.width.equalTo(self.scrollView); + }]; + + + [self.contentContainer addSubview:self.closeButton]; + [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.scrollView.mas_bottom).offset(20); + make.centerX.equalTo(self.contentContainer); + make.leading.trailing.equalTo(self.contentContainer).inset(20); + make.height.mas_equalTo(50); + make.bottom.equalTo(self.contentContainer).offset(-24); + }]; +} + +#pragma mark - Actions + +- (void)onBackgroundTapped { + [self dismiss]; +} + +- (void)onCloseButtonTapped { + [self dismiss]; +} + +#pragma mark - Public Methods + +- (void)showInView:(UIView *)parentView { + [parentView addSubview:self]; + [self mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(parentView); + }]; + + + self.backgroundMask.alpha = 0; + self.contentContainer.alpha = 0; + self.contentContainer.transform = CGAffineTransformMakeScale(0.9, 0.9); + + + [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.backgroundMask.alpha = 1; + self.contentContainer.alpha = 1; + self.contentContainer.transform = CGAffineTransformIdentity; + } completion:nil]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ + self.backgroundMask.alpha = 0; + self.contentContainer.alpha = 0; + self.contentContainer.transform = CGAffineTransformMakeScale(0.95, 0.95); + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +#pragma mark - Lazy Loading + +- (UIView *)backgroundMask { + if (!_backgroundMask) { + _backgroundMask = [[UIView alloc] init]; + _backgroundMask.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6]; + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onBackgroundTapped)]; + [_backgroundMask addGestureRecognizer:tap]; + } + return _backgroundMask; +} + +- (UIView *)contentContainer { + if (!_contentContainer) { + _contentContainer = [[UIView alloc] init]; + _contentContainer.backgroundColor = [UIColor colorWithRed:0x1a/255.0 green:0x1a/255.0 blue:0x2e/255.0 alpha:1.0]; + _contentContainer.layer.cornerRadius = 16; + _contentContainer.layer.masksToBounds = YES; + } + return _contentContainer; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = @"About Emotion Colors"; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightBold]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UIScrollView *)scrollView { + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] init]; + _scrollView.showsVerticalScrollIndicator = YES; + _scrollView.alwaysBounceVertical = YES; + } + return _scrollView; +} + +- (UILabel *)contentLabel { + if (!_contentLabel) { + _contentLabel = [[UILabel alloc] init]; + _contentLabel.numberOfLines = 0; + _contentLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9]; + _contentLabel.font = [UIFont systemFontOfSize:15]; + + + NSString *content = @"Based on Plutchik's Wheel of Emotions, we use 8 core colors to represent fundamental human emotions:\n\n" + "🟡 Joy (Gold)\n" + "Represents happiness, delight, and cheerfulness. Like sunshine warming your heart.\n\n" + "🔵 Sadness (Sky Blue)\n" + "Reflects sorrow, melancholy, and contemplation. The quiet depth of blue skies.\n\n" + "🔴 Anger (Coral Red)\n" + "Expresses frustration, rage, and intensity. The fire of passionate emotions.\n\n" + "🟣 Fear (Violet)\n" + "Embodies anxiety, worry, and apprehension. The uncertainty of purple twilight.\n\n" + "🟠 Surprise (Amber)\n" + "Captures amazement, shock, and wonder. The spark of unexpected moments.\n\n" + "🟢 Disgust (Emerald)\n" + "Conveys aversion, distaste, and rejection. The instinctive green of caution.\n\n" + "🔵 Trust (Bright Blue)\n" + "Symbolizes confidence, faith, and security. The clarity of open skies.\n\n" + "🟡 Anticipation (Amber)\n" + "Represents expectation, hope, and eagerness. The warmth of looking forward.\n\n" + "Each color helps you express your current emotional state in moments you share."; + + _contentLabel.text = content; + } + return _contentLabel; +} + +- (UIButton *)closeButton { + if (!_closeButton) { + _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_closeButton setTitle:@"Got it" forState:UIControlStateNormal]; + [_closeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _closeButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _closeButton.backgroundColor = [UIColor colorWithRed:0x9B/255.0 green:0x59/255.0 blue:0xB6/255.0 alpha:1.0]; + _closeButton.layer.cornerRadius = 25; + _closeButton.layer.masksToBounds = YES; + [_closeButton addTarget:self action:@selector(onCloseButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _closeButton; +} + +@end + diff --git a/YuMi/E-P/NewMoments/Views/EPEmotionInfoView.m b/YuMi/E-P/Moments/Views/EPEmotionInfoView.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPEmotionInfoView.m rename to YuMi/E-P/Moments/Views/EPEmotionInfoView.m.backup diff --git a/YuMi/E-P/Moments/Views/EPMomentCell.h b/YuMi/E-P/Moments/Views/EPMomentCell.h new file mode 100644 index 0000000..05f5c3e --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPMomentCell.h @@ -0,0 +1,22 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import + +@class MomentsInfoModel; +@class SDPhotoBrowser; + +NS_ASSUME_NONNULL_BEGIN + + +@interface EPMomentCell : UITableViewCell + + +- (void)configureWithModel:(MomentsInfoModel *)model; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/E-P/NewMoments/Views/EPMomentCell.h b/YuMi/E-P/Moments/Views/EPMomentCell.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPMomentCell.h rename to YuMi/E-P/Moments/Views/EPMomentCell.h.backup diff --git a/YuMi/E-P/Moments/Views/EPMomentCell.m b/YuMi/E-P/Moments/Views/EPMomentCell.m new file mode 100644 index 0000000..4d9f471 --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPMomentCell.m @@ -0,0 +1,556 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +#import "EPMomentCell.h" +#import "MomentsInfoModel.h" +#import "AccountInfoStorage.h" +#import "NetImageView.h" +#import "EPEmotionColorStorage.h" +#import "SDPhotoBrowser.h" +#import "YuMi-Swift.h" + +@interface EPMomentCell () + +// MARK: - UI Components + + +@property (nonatomic, strong) UIView *cardView; + + +@property (nonatomic, strong) UIView *colorBackgroundView; + + +@property (nonatomic, strong) UIVisualEffectView *blurEffectView; + + +@property (nonatomic, strong) NetImageView *avatarImageView; + + +@property (nonatomic, strong) UILabel *nameLabel; + + +@property (nonatomic, strong) UILabel *timeLabel; + + +@property (nonatomic, strong) UILabel *contentLabel; + + +@property (nonatomic, strong) UIView *imagesContainer; +@property (nonatomic, strong) NSMutableArray *imageViews; + + +@property (nonatomic, strong) UIView *actionBar; + + +@property (nonatomic, strong) UIButton *likeButton; + + +@property (nonatomic, strong) UIButton *commentButton; + + +@property (nonatomic, strong) MomentsInfoModel *currentModel; + + +@property (nonatomic, strong) EPMomentAPISwiftHelper *apiHelper; + +@end + +@implementation EPMomentCell + +// MARK: - Lifecycle + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.selectionStyle = UITableViewCellSelectionStyleNone; + self.backgroundColor = [UIColor clearColor]; + [self setupUI]; + } + return self; +} + +// MARK: - Setup UI + +- (void)setupUI { + + [self.contentView addSubview:self.cardView]; + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.contentView).inset(15); + make.top.equalTo(self.contentView).offset(8); + make.bottom.equalTo(self.contentView).offset(-8).priority(UILayoutPriorityRequired - 1); + }]; + + + [self.cardView addSubview:self.colorBackgroundView]; + [self.colorBackgroundView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.cardView); + }]; + + + [self.cardView addSubview:self.blurEffectView]; + [self.blurEffectView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.cardView); + }]; + + + [self.blurEffectView.contentView addSubview:self.avatarImageView]; + [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.cardView).offset(15); + make.top.equalTo(self.cardView).offset(15); + make.size.mas_equalTo(CGSizeMake(40, 40)); + }]; + + + [self.blurEffectView.contentView addSubview:self.nameLabel]; + [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.avatarImageView.mas_trailing).offset(10); + make.top.equalTo(self.avatarImageView); + make.trailing.equalTo(self.cardView).offset(-15); + }]; + + + [self.blurEffectView.contentView addSubview:self.timeLabel]; + [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.nameLabel); + make.bottom.equalTo(self.avatarImageView); + make.trailing.equalTo(self.cardView).offset(-15); + }]; + + + [self.blurEffectView.contentView addSubview:self.contentLabel]; + [self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.cardView).inset(15); + make.top.equalTo(self.avatarImageView.mas_bottom).offset(12); + }]; + + + [self.blurEffectView.contentView addSubview:self.imagesContainer]; + [self.imagesContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.cardView).inset(15); + make.top.equalTo(self.contentLabel.mas_bottom).offset(12); + make.height.mas_equalTo(0); + }]; + + + [self.blurEffectView.contentView addSubview:self.actionBar]; + [self.actionBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.cardView); + make.top.equalTo(self.imagesContainer.mas_bottom).offset(12); + make.height.mas_equalTo(50); + + make.bottom.equalTo(self.cardView).offset(-8).priority(UILayoutPriorityRequired - 2); + }]; + + + [self.actionBar addSubview:self.likeButton]; + [self.likeButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.actionBar); + make.centerY.equalTo(self.actionBar); + make.width.mas_greaterThanOrEqualTo(80); + }]; +} + +// MARK: - Public Methods + +- (void)configureWithModel:(MomentsInfoModel *)model { + self.currentModel = model; + + + self.nameLabel.text = model.nick ?: YMLocalizedString(@"user.anonymous"); + + + self.timeLabel.text = [self formatTimestampToDate:model.publishTime]; + + + self.contentLabel.text = model.content ?: @""; + + + [self renderImages:model.dynamicResList]; + + + NSInteger likeCnt = MAX(0, model.likeCount.integerValue); + self.likeButton.selected = model.isLike; + [self.likeButton setTitle:[NSString stringWithFormat:@" %ld", (long)likeCnt] forState:UIControlStateNormal]; + [self.likeButton setTitle:[NSString stringWithFormat:@" %ld", (long)likeCnt] forState:UIControlStateSelected]; + + self.avatarImageView.imageUrl = model.avatar; + + + [self applyEmotionColorEffect:model.emotionColor]; + + + [self setNeedsLayout]; +} + + +- (void)applyEmotionColorEffect:(NSString *)emotionColorHex { + + if (!emotionColorHex) { + NSLog(@"[EPMomentCell] 警告:emotionColorHex 为 nil"); + return; + } + + UIColor *color = [self colorFromHex:emotionColorHex]; + + + self.cardView.layer.borderWidth = 0; + + + self.colorBackgroundView.backgroundColor = [color colorWithAlphaComponent:0.5]; + + + self.cardView.layer.shadowColor = color.CGColor; + self.cardView.layer.shadowOffset = CGSizeMake(0, 2); + self.cardView.layer.shadowOpacity = 0.5; + self.cardView.layer.shadowRadius = 16.0; +} + + +- (UIColor *)colorFromHex:(NSString *)hexString { + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 + green:((rgbValue & 0xFF00) >> 8)/255.0 + blue:(rgbValue & 0xFF)/255.0 + alpha:1.0]; +} + +// MARK: - Images Grid + +- (void)renderImages:(NSArray *)resList { + + for (UIView *iv in self.imageViews) { [iv removeFromSuperview]; } + [self.imageViews removeAllObjects]; + if (resList.count == 0) { + [self.imagesContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.cardView).inset(15); + make.top.equalTo(self.contentLabel.mas_bottom).offset(0); + make.height.mas_equalTo(0); + }]; + + + [self.contentView setNeedsLayout]; + [self.contentView layoutIfNeeded]; + return; + } + NSInteger columns = 3; + CGFloat spacing = 6.0; + CGFloat totalWidth = [UIScreen mainScreen].bounds.size.width - 30 - 30; + CGFloat itemW = floor((totalWidth - spacing * (columns - 1)) / columns); + + for (NSInteger i = 0; i < resList.count && i < 9; i++) { + NetImageConfig *config = [[NetImageConfig alloc] init]; + config.placeHolder = [UIImageConstant defaultBannerPlaceholder]; + NetImageView *iv = [[NetImageView alloc] initWithConfig:config]; + iv.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + iv.layer.cornerRadius = 6; + iv.layer.masksToBounds = YES; + iv.contentMode = UIViewContentModeScaleAspectFill; + iv.userInteractionEnabled = YES; + iv.tag = i; + + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onImageTapped:)]; + [iv addGestureRecognizer:tap]; + + [self.imagesContainer addSubview:iv]; + [self.imageViews addObject:iv]; + NSInteger row = i / columns; + NSInteger col = i % columns; + [iv mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self.imagesContainer).offset((itemW + spacing) * col); + make.top.equalTo(self.imagesContainer).offset((itemW + spacing) * row); + make.size.mas_equalTo(CGSizeMake(itemW, itemW)); + }]; + + NSString *url = nil; + id item = resList[i]; + if ([item isKindOfClass:[NSDictionary class]]) { + url = [item valueForKey:@"resUrl"] ?: [item valueForKey:@"url"]; + } else if ([item respondsToSelector:@selector(resUrl)]) { + url = [item valueForKey:@"resUrl"]; + } + iv.imageUrl = url; + } + + NSInteger rows = ((MIN(resList.count, 9) - 1) / columns) + 1; + CGFloat height = rows * itemW + (rows - 1) * spacing; + [self.imagesContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.cardView).inset(15); + make.top.equalTo(self.contentLabel.mas_bottom).offset(12); + make.height.mas_equalTo(height); + }]; + + + [self.contentView setNeedsLayout]; + [self.contentView layoutIfNeeded]; +} + + +- (NSString *)formatTimestampToDate:(NSString *)timestampString { + if (!timestampString || timestampString.length == 0) { + return @""; + } + + + NSTimeInterval timestamp = [timestampString doubleValue] / 1000.0; + + if (timestamp <= 0) { + return @""; + } + + NSDate *date = [NSDate dateWithTimeIntervalSince1970:timestamp]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"MM/dd"; + + return [formatter stringFromDate:date]; +} + + +- (NSString *)formatTimeInterval:(NSInteger)timestamp { + if (timestamp <= 0) return YMLocalizedString(@"time.just_now"); + + NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] - timestamp / 1000.0; + + if (interval < 60) { + return YMLocalizedString(@"time.just_now"); + } else if (interval < 3600) { + return [NSString stringWithFormat:YMLocalizedString(@"time.minutes_ago"), interval / 60]; + } else if (interval < 86400) { + return [NSString stringWithFormat:YMLocalizedString(@"time.hours_ago"), interval / 3600]; + } else if (interval < 604800) { + return [NSString stringWithFormat:YMLocalizedString(@"time.days_ago"), interval / 86400]; + } else { + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyy-MM-dd"; + return [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:timestamp / 1000.0]]; + } +} + +// MARK: - Actions + +- (void)onLikeButtonTapped { + if (!self.currentModel) return; + + + if (self.currentModel.isLike) { + [self performLikeAction:NO]; + return; + } + + + if (self.currentModel.status == 0) { + NSLog(@"[EPMomentCell] 动态审核中,无法点赞"); + // TODO: 可选择显示提示 Toast + return; + } + + + [self performLikeAction:YES]; +} + +- (void)performLikeAction:(BOOL)isLike { + NSLog(@"[EPMomentCell] %@ 动态: %@", isLike ? @"点赞" : @"取消点赞", self.currentModel.dynamicId); + + NSString *dynamicId = self.currentModel.dynamicId; + NSString *likedUid = self.currentModel.uid; + long worldId = self.currentModel.worldId; + + + @kWeakify(self); + [self.apiHelper likeMomentWithDynamicId:dynamicId + isLike:isLike + likedUid:likedUid + worldId:worldId + completion:^{ + @kStrongify(self); + + self.currentModel.isLike = isLike; + NSInteger likeCount = [self.currentModel.likeCount integerValue]; + likeCount += isLike ? 1 : -1; + likeCount = MAX(0, likeCount); + self.currentModel.likeCount = @(likeCount).stringValue; + + + self.likeButton.selected = self.currentModel.isLike; + [self.likeButton setTitle:[NSString stringWithFormat:@" %ld", (long)likeCount] forState:UIControlStateNormal]; + [self.likeButton setTitle:[NSString stringWithFormat:@" %ld", (long)likeCount] forState:UIControlStateSelected]; + + NSLog(@"[EPMomentCell] %@ 成功", isLike ? @"点赞" : @"取消点赞"); + } failure:^(NSInteger code, NSString * _Nonnull msg) { + NSLog(@"[EPMomentCell] %@ 失败 (code: %ld): %@", isLike ? @"点赞" : @"取消点赞", (long)code, msg); + }]; +} + + +- (void)onImageTapped:(UITapGestureRecognizer *)gesture { + if (!self.currentModel || !self.currentModel.dynamicResList.count) return; + + NSInteger index = gesture.view.tag; + NSLog(@"[EPMomentCell] 点击图片索引: %ld", (long)index); + + SDPhotoBrowser *browser = [[SDPhotoBrowser alloc] init]; + browser.sourceImagesContainerView = self.imagesContainer; + browser.delegate = self; + browser.imageCount = self.currentModel.dynamicResList.count; + browser.currentImageIndex = index; + [browser show]; +} + +#pragma mark - SDPhotoBrowserDelegate + +- (NSURL *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index { + if (index >= 0 && index < self.currentModel.dynamicResList.count) { + id item = self.currentModel.dynamicResList[index]; + NSString *url = nil; + if ([item isKindOfClass:[NSDictionary class]]) { + url = [item valueForKey:@"resUrl"] ?: [item valueForKey:@"url"]; + } else if ([item respondsToSelector:@selector(resUrl)]) { + url = [item valueForKey:@"resUrl"]; + } + if (url) { + return [NSURL URLWithString:url]; + } + } + return nil; +} + +- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index { + return [UIImageConstant defaultBannerPlaceholder]; +} + +// MARK: - Lazy Loading + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [[UIView alloc] init]; + _cardView.backgroundColor = [UIColor clearColor]; + _cardView.layer.cornerRadius = 12; + + _cardView.layer.masksToBounds = NO; + } + return _cardView; +} + +- (UIView *)colorBackgroundView { + if (!_colorBackgroundView) { + _colorBackgroundView = [[UIView alloc] init]; + _colorBackgroundView.layer.cornerRadius = 12; + _colorBackgroundView.layer.masksToBounds = YES; + } + return _colorBackgroundView; +} + +- (UIVisualEffectView *)blurEffectView { + if (!_blurEffectView) { + UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + _blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; + _blurEffectView.layer.cornerRadius = 12; + _blurEffectView.layer.masksToBounds = YES; + } + return _blurEffectView; +} + +- (UIImageView *)avatarImageView { + if (!_avatarImageView) { + NetImageConfig *config = [[NetImageConfig alloc] init]; + _avatarImageView = [[NetImageView alloc] initWithConfig:config]; + _avatarImageView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; + _avatarImageView.layer.cornerRadius = 20; + _avatarImageView.layer.masksToBounds = YES; + _avatarImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _avatarImageView; +} + +- (UILabel *)nameLabel { + if (!_nameLabel) { + _nameLabel = [[UILabel alloc] init]; + _nameLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; + _nameLabel.textColor = [UIColor whiteColor]; + } + return _nameLabel; +} + +- (UILabel *)timeLabel { + if (!_timeLabel) { + _timeLabel = [[UILabel alloc] init]; + _timeLabel.font = [UIFont systemFontOfSize:12]; + _timeLabel.textColor = [UIColor colorWithWhite:1 alpha:0.6]; + } + return _timeLabel; +} + +- (UILabel *)contentLabel { + if (!_contentLabel) { + _contentLabel = [[UILabel alloc] init]; + _contentLabel.font = [UIFont systemFontOfSize:15]; + _contentLabel.textColor = [UIColor whiteColor]; + _contentLabel.numberOfLines = 0; + _contentLabel.lineBreakMode = NSLineBreakByWordWrapping; + } + return _contentLabel; +} + +- (UIView *)actionBar { + if (!_actionBar) { + _actionBar = [[UIView alloc] init]; + _actionBar.backgroundColor = [UIColor clearColor]; + } + return _actionBar; +} + +- (UIButton *)likeButton { + if (!_likeButton) { + _likeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_likeButton setImage:[UIImage imageNamed:@"monents_info_like_count_normal"] forState:UIControlStateNormal]; + [_likeButton setImage:[UIImage imageNamed:@"monents_info_like_count_select"] forState:UIControlStateSelected]; + [_likeButton setTitle:@" 0" forState:UIControlStateNormal]; + _likeButton.titleLabel.font = [UIFont systemFontOfSize:13]; + [_likeButton setTitleColor:[UIColor colorWithWhite:1 alpha:0.6] forState:UIControlStateNormal]; + [_likeButton setTitleColor:[UIColor colorWithWhite:1 alpha:1.0] forState:UIControlStateSelected]; + [_likeButton addTarget:self action:@selector(onLikeButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _likeButton; +} + + +- (UIButton *)commentButton { + return nil; +} + +- (UIButton *)createActionButtonWithTitle:(NSString *)title { + UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; + [button setTitle:title forState:UIControlStateNormal]; + button.titleLabel.font = [UIFont systemFontOfSize:13]; + [button setTitleColor:[UIColor colorWithWhite:0.5 alpha:1.0] forState:UIControlStateNormal]; + return button; +} + +- (UIView *)imagesContainer { + if (!_imagesContainer) { + _imagesContainer = [[UIView alloc] init]; + _imagesContainer.backgroundColor = [UIColor clearColor]; + } + return _imagesContainer; +} + +- (NSMutableArray *)imageViews { + if (!_imageViews) { + _imageViews = [NSMutableArray array]; + } + return _imageViews; +} + +- (EPMomentAPISwiftHelper *)apiHelper { + if (!_apiHelper) { + _apiHelper = [[EPMomentAPISwiftHelper alloc] init]; + } + return _apiHelper; +} + +@end diff --git a/YuMi/E-P/NewMoments/Views/EPMomentCell.m b/YuMi/E-P/Moments/Views/EPMomentCell.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPMomentCell.m rename to YuMi/E-P/Moments/Views/EPMomentCell.m.backup diff --git a/YuMi/E-P/Moments/Views/EPMomentListView.h b/YuMi/E-P/Moments/Views/EPMomentListView.h new file mode 100644 index 0000000..4d2956e --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPMomentListView.h @@ -0,0 +1,41 @@ + + +// Created by AI on 2025-10-10. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class EPMomentAPISwiftHelper; +@class MomentsInfoModel; + + +typedef NS_ENUM(NSInteger, EPMomentListSourceType) { + EPMomentListSourceTypeRecommend = 0, + EPMomentListSourceTypeMine = 1 +}; + + +@interface EPMomentListView : UIView + + +@property (nonatomic, strong, readonly) NSArray *rawList; + + +@property (nonatomic, assign) EPMomentListSourceType sourceType; + + +@property (nonatomic, copy) void (^onSelectMoment)(NSInteger index); + + +- (void)reloadFirstPage; + + +- (void)loadWithDynamicInfo:(NSArray *)dynamicInfo + refreshCallback:(void(^)(void))refreshCallback; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Views/EPMomentListView.h b/YuMi/E-P/Moments/Views/EPMomentListView.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPMomentListView.h rename to YuMi/E-P/Moments/Views/EPMomentListView.h.backup diff --git a/YuMi/E-P/Moments/Views/EPMomentListView.m b/YuMi/E-P/Moments/Views/EPMomentListView.m new file mode 100644 index 0000000..5e228fd --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPMomentListView.m @@ -0,0 +1,250 @@ + + +// Created by AI on 2025-10-10. + + +#import +#import "EPMomentListView.h" +#import "EPMomentCell.h" +#import +#import "YuMi-Swift.h" +#import "EPEmotionColorStorage.h" + + +@interface EPMomentListView () + +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) UIRefreshControl *refreshControl; +@property (nonatomic, strong) NSMutableArray *mutableRawList; +@property (nonatomic, strong) EPMomentAPISwiftHelper *api; +@property (nonatomic, assign) BOOL isLoading; +@property (nonatomic, copy) NSString *nextID; +@property (nonatomic, assign) BOOL isLocalMode; +@property (nonatomic, copy) void (^refreshCallback)(void); +@end + +@implementation EPMomentListView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + _api = [[EPMomentAPISwiftHelper alloc] init]; + _mutableRawList = [NSMutableArray array]; + _sourceType = EPMomentListSourceTypeRecommend; + _isLocalMode = NO; + + [self addSubview:self.tableView]; + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + } + return self; +} + +- (NSArray *)rawList { + return [self.mutableRawList copy]; +} + +- (void)reloadFirstPage { + if (self.isLocalMode) { + + if (self.refreshCallback) { + self.refreshCallback(); + } + [self.refreshControl endRefreshing]; + return; + } + + + self.nextID = @""; + [self.mutableRawList removeAllObjects]; + [self.tableView reloadData]; + [self.tableView.mj_footer resetNoMoreData]; + [self requestNextPage]; +} + +- (void)loadWithDynamicInfo:(NSArray *)dynamicInfo + refreshCallback:(void (^)(void))refreshCallback { + self.isLocalMode = YES; + self.refreshCallback = refreshCallback; + + [self.mutableRawList removeAllObjects]; + if (dynamicInfo.count > 0) { + [self.mutableRawList addObjectsFromArray:dynamicInfo]; + } + + + self.tableView.mj_footer.hidden = YES; + + [self.tableView reloadData]; + [self.refreshControl endRefreshing]; +} + +- (void)requestNextPage { + if (self.isLoading) return; + self.isLoading = YES; + + @kWeakify(self); + [self.api fetchLatestMomentsWithNextID:self.nextID + completion:^(NSArray * _Nonnull list, NSString * _Nonnull nextMomentID) { + @kStrongify(self); + [self endLoading]; + if (list.count > 0) { + + [self processEmotionColors:list isFirstPage:(self.nextID.length == 0)]; + + self.nextID = nextMomentID; + [self.mutableRawList addObjectsFromArray:list]; + [self.tableView reloadData]; + if (nextMomentID.length > 0) { + [self.tableView.mj_footer endRefreshing]; + } else { + [self.tableView.mj_footer endRefreshingWithNoMoreData]; + } + } else { + + [self.tableView.mj_footer endRefreshingWithNoMoreData]; + } + } failure:^(NSInteger code, NSString * _Nonnull msg) { + @kStrongify(self); + [self endLoading]; + // TODO: 完全没有数据情况下,后续补充数据异常页面 + [self.tableView.mj_footer endRefreshing]; + }]; +} + +- (void)endLoading { + self.isLoading = NO; + [self.refreshControl endRefreshing]; +} + + +- (void)processEmotionColors:(NSArray *)list isFirstPage:(BOOL)isFirstPage { + + NSString *pendingColor = [[NSUserDefaults standardUserDefaults] stringForKey:@"EP_Pending_Emotion_Color"]; + NSNumber *pendingTimestamp = [[NSUserDefaults standardUserDefaults] objectForKey:@"EP_Pending_Emotion_Timestamp"]; + + for (NSInteger i = 0; i < list.count; i++) { + MomentsInfoModel *model = list[i]; + + + if (isFirstPage && i == 0 && pendingColor && pendingTimestamp) { + + NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; + NSTimeInterval pending = pendingTimestamp.doubleValue; + if ((now - pending) < 5.0) { + model.emotionColor = pendingColor; + + [EPEmotionColorStorage saveColor:pendingColor forDynamicId:model.dynamicId]; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"EP_Pending_Emotion_Color"]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"EP_Pending_Emotion_Timestamp"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + continue; + } + } + + + NSString *savedColor = [EPEmotionColorStorage colorForDynamicId:model.dynamicId]; + if (savedColor) { + model.emotionColor = savedColor; + } else { + + NSString *randomColor = [EPEmotionColorStorage randomEmotionColor]; + model.emotionColor = randomColor; + [EPEmotionColorStorage saveColor:randomColor forDynamicId:model.dynamicId]; + NSLog(@"[EPMomentListView] 为动态 %@ 分配随机颜色: %@", model.dynamicId, randomColor); + } + } +} + +#pragma mark - UITableView + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.mutableRawList.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + EPMomentCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewMomentCell" forIndexPath:indexPath]; + if (indexPath.row < self.mutableRawList.count) { + MomentsInfoModel *model = [self.mutableRawList xpSafeObjectAtIndex:indexPath.row]; + [cell configureWithModel:model]; + } + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewAutomaticDimension; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 200; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (self.onSelectMoment) self.onSelectMoment(indexPath.row); +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + if (self.isLocalMode) return; + + CGFloat offsetY = scrollView.contentOffset.y; + CGFloat contentHeight = scrollView.contentSize.height; + CGFloat screenHeight = scrollView.frame.size.height; + if (offsetY > contentHeight - screenHeight - 100 && !self.isLoading) { + [self requestNextPage]; + } +} + +#pragma mark - Lazy + +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _tableView.backgroundColor = [UIColor clearColor]; + _tableView.estimatedRowHeight = 200; + _tableView.rowHeight = UITableViewAutomaticDimension; + _tableView.showsVerticalScrollIndicator = NO; + + _tableView.contentInset = UIEdgeInsetsMake(10, 0, 120, 0); + _tableView.scrollIndicatorInsets = UIEdgeInsetsMake(10, 0, 120, 0); + [_tableView registerClass:[EPMomentCell class] forCellReuseIdentifier:@"NewMomentCell"]; + _tableView.refreshControl = self.refreshControl; + + + __weak typeof(self) weakSelf = self; + MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ + __strong typeof(weakSelf) self = weakSelf; + if (!self.isLoading && self.nextID.length > 0) { + [self requestNextPage]; + } else if (self.nextID.length == 0) { + [self.tableView.mj_footer endRefreshingWithNoMoreData]; + } else { + [self.tableView.mj_footer endRefreshing]; + } + }]; + + footer.stateLabel.textColor = [UIColor whiteColor]; + footer.loadingView.color = [UIColor whiteColor]; + _tableView.mj_footer = footer; + } + return _tableView; +} + +- (UIRefreshControl *)refreshControl { + if (!_refreshControl) { + _refreshControl = [[UIRefreshControl alloc] init]; + _refreshControl.tintColor = [UIColor whiteColor]; + [_refreshControl addTarget:self action:@selector(reloadFirstPage) forControlEvents:UIControlEventValueChanged]; + } + return _refreshControl; +} + +@end + diff --git a/YuMi/E-P/NewMoments/Views/EPMomentListView.m b/YuMi/E-P/Moments/Views/EPMomentListView.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPMomentListView.m rename to YuMi/E-P/Moments/Views/EPMomentListView.m.backup diff --git a/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.h b/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.h new file mode 100644 index 0000000..eeaac66 --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.h @@ -0,0 +1,30 @@ + + +// Created by AI on 2025-10-15. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EPSignatureColorGuideView : UIView + + +@property (nonatomic, copy) void(^onColorConfirmed)(NSString *hexColor); + + +@property (nonatomic, copy) void(^onSkipTapped)(void); + + +- (void)showInWindow:(UIWindow *)window; + + +- (void)showInWindow:(UIWindow *)window showSkipButton:(BOOL)showSkip; + + +- (void)dismiss; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/YuMi/E-P/NewMoments/Views/EPSignatureColorGuideView.h b/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.h.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPSignatureColorGuideView.h rename to YuMi/E-P/Moments/Views/EPSignatureColorGuideView.h.backup diff --git a/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.m b/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.m new file mode 100644 index 0000000..c204af3 --- /dev/null +++ b/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.m @@ -0,0 +1,370 @@ + + +// Created by AI on 2025-10-15. + + +#import "EPSignatureColorGuideView.h" +#import "EPEmotionColorWheelView.h" +#import "EPEmotionInfoView.h" +#import + +@interface EPSignatureColorGuideView () + +@property (nonatomic, strong) CAGradientLayer *gradientLayer; +@property (nonatomic, strong) UIView *contentContainer; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *subtitleLabel; +@property (nonatomic, strong) UIButton *infoButton; +@property (nonatomic, strong) UIView *selectedColorView; +@property (nonatomic, strong) UILabel *selectedColorLabel; +@property (nonatomic, strong) EPEmotionColorWheelView *colorWheelView; +@property (nonatomic, strong) UIButton *confirmButton; +@property (nonatomic, strong) UIButton *skipButton; +@property (nonatomic, copy) NSString *selectedColor; + +@end + +@implementation EPSignatureColorGuideView + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + + CAGradientLayer *gradientLayer = [CAGradientLayer layer]; + gradientLayer.colors = @[ + (id)[UIColor colorWithRed:0x1a/255.0 green:0x09/255.0 blue:0x33/255.0 alpha:1.0].CGColor, + (id)[UIColor colorWithRed:0x0d/255.0 green:0x1b/255.0 blue:0x2a/255.0 alpha:1.0].CGColor + ]; + gradientLayer.startPoint = CGPointMake(0.5, 0); + gradientLayer.endPoint = CGPointMake(0.5, 1); + [self.layer insertSublayer:gradientLayer atIndex:0]; + self.gradientLayer = gradientLayer; + + + [self addSubview:self.contentContainer]; + [self.contentContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self); + make.leading.trailing.equalTo(self).inset(30); + }]; + + + [self.contentContainer addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contentContainer); + make.centerX.equalTo(self.contentContainer); + }]; + + + [self.contentContainer addSubview:self.subtitleLabel]; + [self.subtitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(12); + make.centerX.equalTo(self.contentContainer); + make.leading.trailing.equalTo(self.contentContainer).inset(20); + }]; + + + [self addSubview:self.infoButton]; + [self.infoButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self).offset(20); + make.top.equalTo(self).offset(60); + make.size.mas_equalTo(CGSizeMake(36, 36)); + }]; + + + [self.contentContainer addSubview:self.selectedColorView]; + [self.selectedColorView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.subtitleLabel.mas_bottom).offset(30); + make.centerX.equalTo(self.contentContainer); + make.height.mas_equalTo(60); + make.leading.trailing.equalTo(self.contentContainer).inset(40); + }]; + + + [self.contentContainer addSubview:self.colorWheelView]; + [self.colorWheelView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.selectedColorView.mas_bottom).offset(30); + make.centerX.equalTo(self.contentContainer); + make.size.mas_equalTo(CGSizeMake(360, 360)); + }]; + + + [self.contentContainer addSubview:self.confirmButton]; + [self.confirmButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.colorWheelView.mas_bottom).offset(50); + make.leading.trailing.equalTo(self.contentContainer).inset(20); + make.height.mas_equalTo(56); + make.bottom.equalTo(self.contentContainer); + }]; + + + [self addSubview:self.skipButton]; + [self.skipButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self).offset(60); + make.trailing.equalTo(self).offset(-20); + make.size.mas_equalTo(CGSizeMake(60, 36)); + }]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + self.gradientLayer.frame = self.bounds; +} + +#pragma mark - Actions + +- (void)onConfirmButtonTapped { + if (!self.selectedColor) return; + + + if (self.onColorConfirmed) { + self.onColorConfirmed(self.selectedColor); + } + + + [self dismiss]; +} + +- (void)onSkipButtonTapped { + + if (self.onSkipTapped) { + self.onSkipTapped(); + } + + + [self dismiss]; +} + +- (void)onInfoButtonTapped { + EPEmotionInfoView *infoView = [[EPEmotionInfoView alloc] init]; + [infoView showInView:self]; +} + +#pragma mark - Public Methods + +- (void)showInWindow:(UIWindow *)window { + [self showInWindow:window showSkipButton:NO]; +} + +- (void)showInWindow:(UIWindow *)window showSkipButton:(BOOL)showSkip { + [window addSubview:self]; + [self mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(window); + }]; + + + self.skipButton.hidden = !showSkip; + + + self.alpha = 0; + self.contentContainer.transform = CGAffineTransformMakeScale(0.8, 0.8); + + + [UIView animateWithDuration:0.4 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.alpha = 1.0; + self.contentContainer.transform = CGAffineTransformIdentity; + } completion:nil]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ + self.alpha = 0; + self.contentContainer.transform = CGAffineTransformMakeScale(0.95, 0.95); + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +#pragma mark - Lazy Loading + +- (UIView *)contentContainer { + if (!_contentContainer) { + _contentContainer = [[UIView alloc] init]; + _contentContainer.backgroundColor = [UIColor clearColor]; + } + return _contentContainer; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = @"Choose your signature emotion"; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.font = [UIFont systemFontOfSize:24 weight:UIFontWeightBold]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UILabel *)subtitleLabel { + if (!_subtitleLabel) { + _subtitleLabel = [[UILabel alloc] init]; + _subtitleLabel.text = @"This color represents your emotional identity"; + _subtitleLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7]; + _subtitleLabel.font = [UIFont systemFontOfSize:14]; + _subtitleLabel.textAlignment = NSTextAlignmentCenter; + _subtitleLabel.numberOfLines = 0; + } + return _subtitleLabel; +} + +- (UIView *)selectedColorView { + if (!_selectedColorView) { + _selectedColorView = [[UIView alloc] init]; + _selectedColorView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.15]; + _selectedColorView.layer.cornerRadius = 30; + _selectedColorView.layer.masksToBounds = YES; + _selectedColorView.hidden = YES; + + + UIView *colorDot = [[UIView alloc] init]; + colorDot.tag = 100; + colorDot.layer.cornerRadius = 16; + colorDot.layer.masksToBounds = YES; + [_selectedColorView addSubview:colorDot]; + [colorDot mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(_selectedColorView).offset(20); + make.centerY.equalTo(_selectedColorView); + make.size.mas_equalTo(CGSizeMake(32, 32)); + }]; + + + [_selectedColorView addSubview:self.selectedColorLabel]; + [self.selectedColorLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(colorDot.mas_trailing).offset(16); + make.centerY.equalTo(_selectedColorView); + make.trailing.equalTo(_selectedColorView).offset(-20); + }]; + } + return _selectedColorView; +} + +- (UILabel *)selectedColorLabel { + if (!_selectedColorLabel) { + _selectedColorLabel = [[UILabel alloc] init]; + _selectedColorLabel.textColor = [UIColor whiteColor]; + _selectedColorLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightMedium]; + _selectedColorLabel.text = @"Select your signature emotion"; + } + return _selectedColorLabel; +} + +- (EPEmotionColorWheelView *)colorWheelView { + if (!_colorWheelView) { + _colorWheelView = [[EPEmotionColorWheelView alloc] init]; + _colorWheelView.radius = 100.0; + _colorWheelView.buttonSize = 54.0; + + __weak typeof(self) weakSelf = self; + _colorWheelView.onColorTapped = ^(NSString *hexColor, NSInteger index) { + __strong typeof(weakSelf) self = weakSelf; + + + self.selectedColor = hexColor; + + + [self updateSelectedColorDisplay:hexColor index:index]; + + + self.confirmButton.enabled = YES; + self.confirmButton.alpha = 1.0; + }; + } + return _colorWheelView; +} + + +- (void)updateSelectedColorDisplay:(NSString *)hexColor index:(NSInteger)index { + NSArray *emotions = @[@"Joy", @"Sadness", @"Anger", @"Fear", @"Surprise", @"Disgust", @"Trust", @"Anticipation"]; + + + self.selectedColorView.hidden = NO; + + + UIView *colorDot = [self.selectedColorView viewWithTag:100]; + colorDot.backgroundColor = [self colorFromHex:hexColor]; + + + self.selectedColorLabel.text = emotions[index]; +} + + +- (UIColor *)colorFromHex:(NSString *)hexString { + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 + green:((rgbValue & 0xFF00) >> 8)/255.0 + blue:(rgbValue & 0xFF)/255.0 + alpha:1.0]; +} + +- (UIButton *)confirmButton { + if (!_confirmButton) { + _confirmButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_confirmButton setTitle:@"Confirm & Continue" forState:UIControlStateNormal]; + [_confirmButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _confirmButton.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _confirmButton.layer.cornerRadius = 28; + _confirmButton.layer.masksToBounds = YES; + + + CAGradientLayer *gradient = [CAGradientLayer layer]; + gradient.colors = @[ + (id)[UIColor colorWithRed:0x9B/255.0 green:0x59/255.0 blue:0xB6/255.0 alpha:1.0].CGColor, + (id)[UIColor colorWithRed:0x6C/255.0 green:0x34/255.0 blue:0x83/255.0 alpha:1.0].CGColor + ]; + gradient.startPoint = CGPointMake(0, 0); + gradient.endPoint = CGPointMake(1, 0); + gradient.frame = CGRectMake(0, 0, 1000, 56); + [_confirmButton.layer insertSublayer:gradient atIndex:0]; + + [_confirmButton addTarget:self action:@selector(onConfirmButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + + + _confirmButton.enabled = NO; + _confirmButton.alpha = 0.5; + } + return _confirmButton; +} + +- (UIButton *)infoButton { + if (!_infoButton) { + _infoButton = [UIButton buttonWithType:UIButtonTypeCustom]; + + + UIImage *infoIcon = [UIImage systemImageNamed:@"info.circle"]; + [_infoButton setImage:infoIcon forState:UIControlStateNormal]; + _infoButton.tintColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8]; + + + [_infoButton addTarget:self action:@selector(onInfoButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _infoButton; +} + +- (UIButton *)skipButton { + if (!_skipButton) { + _skipButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_skipButton setTitle:@"Skip" forState:UIControlStateNormal]; + [_skipButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _skipButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _skipButton.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.2]; + _skipButton.layer.cornerRadius = 18; + _skipButton.layer.masksToBounds = YES; + [_skipButton addTarget:self action:@selector(onSkipButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + _skipButton.hidden = YES; + } + return _skipButton; +} + +@end + diff --git a/YuMi/E-P/NewMoments/Views/EPSignatureColorGuideView.m b/YuMi/E-P/Moments/Views/EPSignatureColorGuideView.m.backup similarity index 100% rename from YuMi/E-P/NewMoments/Views/EPSignatureColorGuideView.m rename to YuMi/E-P/Moments/Views/EPSignatureColorGuideView.m.backup diff --git a/YuMi/E-P/TabBar/EPTabBarController.swift b/YuMi/E-P/TabBar/EPTabBarController.swift new file mode 100644 index 0000000..f33c100 --- /dev/null +++ b/YuMi/E-P/TabBar/EPTabBarController.swift @@ -0,0 +1,519 @@ + + +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. + + +import UIKit +import SnapKit + + +@objc class EPTabBarController: UITabBarController { + + // MARK: - Properties + + + private var isLoggedIn: Bool = false + + + private var customTabBarView: UIView! + + + private var tabBarBackgroundView: UIVisualEffectView! + + + private var tabButtons: [UIButton] = [] + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + + + #if DEBUG + APIConfig.testEncryption() + #endif + + + self.tabBar.isHidden = true + + + self.delegate = self + + + performAutoLogin() + + setupCustomFloatingTabBar() + setupInitialViewControllers() + + NSLog("[EPTabBarController] 悬浮 TabBar 初始化完成") + } + + deinit { + NSLog("[EPTabBarController] 已释放") + } + + // MARK: - Setup + + + private func setupCustomFloatingTabBar() { + + customTabBarView = UIView() + customTabBarView.translatesAutoresizingMaskIntoConstraints = false + customTabBarView.backgroundColor = .clear + view.addSubview(customTabBarView) + + + let effect: UIVisualEffect + if #available(iOS 26.0, *) { + + effect = UIGlassEffect() + } else { + + effect = UIBlurEffect(style: .systemMaterial) + } + + tabBarBackgroundView = UIVisualEffectView(effect: effect) + tabBarBackgroundView.translatesAutoresizingMaskIntoConstraints = false + tabBarBackgroundView.layer.cornerRadius = 28 + tabBarBackgroundView.layer.masksToBounds = true + + + tabBarBackgroundView.layer.borderWidth = 0.5 + tabBarBackgroundView.layer.borderColor = UIColor.white.withAlphaComponent(0.2).cgColor + + customTabBarView.addSubview(tabBarBackgroundView) + + + customTabBarView.snp.makeConstraints { make in + make.leading.equalTo(view).offset(16) + make.trailing.equalTo(view).offset(-16) + make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-12) + make.height.equalTo(64) + } + + tabBarBackgroundView.snp.makeConstraints { make in + make.edges.equalTo(customTabBarView) + } + + + setupTabButtons() + + NSLog("[EPTabBarController] 悬浮 TabBar 设置完成") + } + + + private func setupTabButtons() { + let momentButton = createTabButton( + normalImage: "tab_moment_off", + selectedImage: "tab_moment_on", + tag: 0 + ) + + let mineButton = createTabButton( + normalImage: "tab_mine_off", + selectedImage: "tab_mine_on", + tag: 1 + ) + + tabButtons = [momentButton, mineButton] + + let stackView = UIStackView(arrangedSubviews: tabButtons) + stackView.axis = .horizontal + stackView.distribution = .fillEqually + stackView.spacing = 20 + stackView.translatesAutoresizingMaskIntoConstraints = false + tabBarBackgroundView.contentView.addSubview(stackView) + + stackView.snp.makeConstraints { make in + make.top.equalTo(tabBarBackgroundView).offset(8) + make.leading.equalTo(tabBarBackgroundView).offset(20) + make.trailing.equalTo(tabBarBackgroundView).offset(-20) + make.bottom.equalTo(tabBarBackgroundView).offset(-8) + } + + + updateTabButtonStates(selectedIndex: 0) + } + + + private func createTabButton(normalImage: String, selectedImage: String, tag: Int) -> UIButton { + let button = UIButton(type: .custom) + button.tag = tag + button.adjustsImageWhenHighlighted = false + + + if let normalImg = UIImage(named: normalImage), let selectedImg = UIImage(named: selectedImage) { + + button.setImage(normalImg, for: .normal) + button.setImage(selectedImg, for: .selected) + } else { + + let fallbackIcons = ["sparkles", "person.circle"] + let iconName = fallbackIcons[tag] + let imageConfig = UIImage.SymbolConfiguration(pointSize: 24, weight: .medium) + let normalIcon = UIImage(systemName: iconName, withConfiguration: imageConfig) + + button.setImage(normalIcon, for: .normal) + button.setImage(normalIcon, for: .selected) + button.tintColor = .white.withAlphaComponent(0.6) + } + + + button.imageView?.contentMode = .scaleAspectFit + + + button.setTitle(nil, for: .normal) + button.setTitle(nil, for: .selected) + + + button.imageView?.snp.makeConstraints { make in + make.size.equalTo(28) + } + + button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) + return button + } + + + @objc private func tabButtonTapped(_ sender: UIButton) { + let newIndex = sender.tag + + + if newIndex == selectedIndex { + return + } + + + updateTabButtonStates(selectedIndex: newIndex) + + + UIView.performWithoutAnimation { + selectedIndex = newIndex + } + + let tabNames = [YMLocalizedString("tab.moment"), YMLocalizedString("tab.mine")] + NSLog("[EPTabBarController] 选中 Tab: \(tabNames[newIndex])") + } + + + private func updateTabButtonStates(selectedIndex: Int) { + + tabButtons.forEach { $0.isUserInteractionEnabled = false } + + for (index, button) in tabButtons.enumerated() { + let isSelected = (index == selectedIndex) + + + button.isSelected = isSelected + + + if button.currentImage?.isSymbolImage == true { + button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) + } + + + UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseOut], animations: { + button.transform = isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : .identity + }) + } + + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { + self.tabButtons.forEach { $0.isUserInteractionEnabled = true } + } + } + + + private func setupInitialViewControllers() { + // TODO: 暂时使用空白页面占位 + let blankVC1 = UIViewController() + blankVC1.view.backgroundColor = .white + blankVC1.tabBarItem = createTabBarItem( + title: YMLocalizedString("tab.moment"), + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + let blankVC2 = UIViewController() + blankVC2.view.backgroundColor = .white + blankVC2.tabBarItem = createTabBarItem( + title: YMLocalizedString("tab.mine"), + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [blankVC1, blankVC2] + selectedIndex = 0 + + NSLog("[EPTabBarController] 初始 ViewControllers 设置完成") + } + + + private func createTabBarItem(title: String, normalImage: String, selectedImage: String) -> UITabBarItem { + let item = UITabBarItem( + title: title, + image: UIImage(named: normalImage)?.withRenderingMode(.alwaysOriginal), + selectedImage: UIImage(named: selectedImage)?.withRenderingMode(.alwaysOriginal) + ) + return item + } + + // MARK: - Public Methods + + + func refreshTabBar(isLogin: Bool) { + isLoggedIn = isLogin + + if isLogin { + setupLoggedInViewControllers() + } else { + setupInitialViewControllers() + } + + NSLog("[EPTabBarController] TabBar 已刷新,登录状态: \(isLogin)") + } + + + private func setupLoggedInViewControllers() { + + if viewControllers?.count != 2 || + !(viewControllers?[0] is UINavigationController) || + !(viewControllers?[1] is UINavigationController) { + + + let momentVC = EPMomentViewController() + momentVC.title = YMLocalizedString("tab.moment") + let momentNav = createTransparentNavigationController( + rootViewController: momentVC, + tabTitle: YMLocalizedString("tab.moment"), + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + + let mineVC = EPMineViewController() + mineVC.title = YMLocalizedString("tab.mine") + let mineNav = createTransparentNavigationController( + rootViewController: mineVC, + tabTitle: YMLocalizedString("tab.mine"), + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [momentNav, mineNav] + NSLog("[EPTabBarController] 登录后 ViewControllers 创建完成 - Moment & Mine") + } + + selectedIndex = 0 + } + + + private func createTransparentNavigationController( + rootViewController: UIViewController, + tabTitle: String, + normalImage: String, + selectedImage: String + ) -> UINavigationController { + let nav = UINavigationController(rootViewController: rootViewController) + nav.navigationBar.isTranslucent = true + nav.navigationBar.setBackgroundImage(UIImage(), for: .default) + nav.navigationBar.shadowImage = UIImage() + nav.view.backgroundColor = .clear + nav.tabBarItem = createTabBarItem( + title: tabTitle, + normalImage: normalImage, + selectedImage: selectedImage + ) + + + nav.delegate = self + + return nav + } + + // MARK: - TabBar Visibility Control + + + private func showCustomTabBar(animated: Bool = true) { + guard customTabBarView.isHidden else { return } + + if animated { + customTabBarView.isHidden = false + customTabBarView.alpha = 0 + customTabBarView.transform = CGAffineTransform(translationX: 0, y: 20) + + UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseOut) { + self.customTabBarView.alpha = 1 + self.customTabBarView.transform = .identity + } + } else { + customTabBarView.isHidden = false + customTabBarView.alpha = 1 + } + } + + + private func hideCustomTabBar(animated: Bool = true) { + guard !customTabBarView.isHidden else { return } + + if animated { + UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseIn, animations: { + self.customTabBarView.alpha = 0 + self.customTabBarView.transform = CGAffineTransform(translationX: 0, y: 20) + }) { _ in + self.customTabBarView.isHidden = true + self.customTabBarView.transform = .identity + } + } else { + customTabBarView.isHidden = true + customTabBarView.alpha = 0 + } + } +} + +// MARK: - UITabBarControllerDelegate + +extension EPTabBarController: UITabBarControllerDelegate { + + override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { + NSLog("[EPTabBarController] 选中 Tab: \(item.title ?? "Unknown")") + } + + + func tabBarController(_ tabBarController: UITabBarController, + animationControllerForTransitionFrom fromVC: UIViewController, + to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { + + return nil + } + + + func tabBarController(_ tabBarController: UITabBarController, + shouldSelect viewController: UIViewController) -> Bool { + + return true + } +} + +// MARK: - UINavigationControllerDelegate + +extension EPTabBarController: UINavigationControllerDelegate { + + func navigationController(_ navigationController: UINavigationController, + willShow viewController: UIViewController, + animated: Bool) { + + + let isRootViewController = navigationController.viewControllers.count == 1 + + if isRootViewController { + + showCustomTabBar(animated: animated) + NSLog("[EPTabBarController] 显示 TabBar - 根页面") + } else { + + hideCustomTabBar(animated: animated) + NSLog("[EPTabBarController] 隐藏 TabBar - 子页面 (层级: \(navigationController.viewControllers.count))") + } + } +} + +// MARK: - Auto Login & Ticket Validation + +extension EPTabBarController { + + + private func performAutoLogin() { + + guard let accountModel = AccountInfoStorage.instance().getCurrentAccountInfo() else { + NSLog("[EPTabBarController] ⚠️ 账号信息不存在,跳转到登录页") + handleTokenInvalid() + return + } + + + let uid = accountModel.uid + let accessToken = accountModel.access_token + + guard !uid.isEmpty, !accessToken.isEmpty else { + NSLog("[EPTabBarController] ⚠️ uid 或 access_token 为空,跳转到登录页") + handleTokenInvalid() + return + } + + + let existingTicket = AccountInfoStorage.instance().getTicket() ?? "" + if !existingTicket.isEmpty { + NSLog("[EPTabBarController] ✅ Ticket 已存在,自动登录成功") + return + } + + + NSLog("[EPTabBarController] 🔄 Ticket 不存在,正在请求...") + let loginService = EPLoginService() + + loginService.requestTicket(accessToken: accessToken) { ticket in + NSLog("[EPTabBarController] ✅ Ticket 请求成功: \(ticket)") + AccountInfoStorage.instance().saveTicket(ticket) + } failure: { [weak self] code, msg in + NSLog("[EPTabBarController] ❌ Ticket 请求失败 (\(code)): \(msg)") + + + DispatchQueue.main.async { + self?.handleTokenInvalid() + } + } + } + + + private func handleTokenInvalid() { + NSLog("[EPTabBarController] ⚠️ Token 失效,清空账号数据...") + + + AccountInfoStorage.instance().saveAccountInfo(nil) + AccountInfoStorage.instance().saveTicket("") + + + DispatchQueue.main.async { + let loginVC = EPLoginViewController() + let nav = BaseNavigationController(rootViewController: loginVC) + nav.modalPresentationStyle = .fullScreen + + + if #available(iOS 13.0, *) { + for scene in UIApplication.shared.connectedScenes { + if let windowScene = scene as? UIWindowScene, + windowScene.activationState == .foregroundActive, + let window = windowScene.windows.first(where: { $0.isKeyWindow }) { + window.rootViewController = nav + window.makeKeyAndVisible() + break + } + } + } else { + if let window = UIApplication.shared.keyWindow { + window.rootViewController = nav + window.makeKeyAndVisible() + } + } + + NSLog("[EPTabBarController] ✅ 已跳转到登录页") + } + } +} + +// MARK: - OC Compatibility + +extension EPTabBarController { + + + @objc static func create() -> EPTabBarController { + return EPTabBarController() + } + + + @objc func refreshTabBarWithIsLogin(_ isLogin: Bool) { + refreshTabBar(isLogin: isLogin) + } +} diff --git a/YuMi/E-P/NewTabBar/EPTabBarController.swift b/YuMi/E-P/TabBar/EPTabBarController.swift.backup similarity index 100% rename from YuMi/E-P/NewTabBar/EPTabBarController.swift rename to YuMi/E-P/TabBar/EPTabBarController.swift.backup diff --git a/YuMi/Global/BuglyManagerExample.h b/YuMi/Global/BuglyManagerExample.h index dd3d945..b35a048 100644 --- a/YuMi/Global/BuglyManagerExample.h +++ b/YuMi/Global/BuglyManagerExample.h @@ -1,40 +1,27 @@ -// -// BuglyManagerExample.h -// YuMi -// + + // Created by BuglyManager Example // Copyright © 2024 YuMi. All rights reserved. -// + #import #import "BuglyManager.h" NS_ASSUME_NONNULL_BEGIN -/** - * BuglyManager 使用示例类 - * 展示如何使用 BuglyManager 的各种功能 - */ + @interface BuglyManagerExample : NSObject -/** - * 设置 Bugly 代理 - */ + - (void)setupBuglyDelegate; -/** - * 上报业务错误示例 - */ + - (void)reportBusinessErrorExample; -/** - * 上报网络错误示例 - */ + - (void)reportNetworkErrorExample; -/** - * 上报内购错误示例 - */ + - (void)reportIAPErrorExample; @end diff --git a/YuMi/Global/BuglyManagerExample.h.backup b/YuMi/Global/BuglyManagerExample.h.backup new file mode 100644 index 0000000..dd3d945 --- /dev/null +++ b/YuMi/Global/BuglyManagerExample.h.backup @@ -0,0 +1,42 @@ +// +// BuglyManagerExample.h +// YuMi +// +// Created by BuglyManager Example +// Copyright © 2024 YuMi. All rights reserved. +// + +#import +#import "BuglyManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * BuglyManager 使用示例类 + * 展示如何使用 BuglyManager 的各种功能 + */ +@interface BuglyManagerExample : NSObject + +/** + * 设置 Bugly 代理 + */ +- (void)setupBuglyDelegate; + +/** + * 上报业务错误示例 + */ +- (void)reportBusinessErrorExample; + +/** + * 上报网络错误示例 + */ +- (void)reportNetworkErrorExample; + +/** + * 上报内购错误示例 + */ +- (void)reportIAPErrorExample; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Global/BuglyManagerExample.m b/YuMi/Global/BuglyManagerExample.m index 5810ec3..4163667 100644 --- a/YuMi/Global/BuglyManagerExample.m +++ b/YuMi/Global/BuglyManagerExample.m @@ -1,10 +1,8 @@ -// -// BuglyManagerExample.m -// YuMi -// + + // Created by BuglyManager Example // Copyright © 2024 YuMi. All rights reserved. -// + #import "BuglyManagerExample.h" #import "BuglyManager.h" @@ -13,12 +11,12 @@ #pragma mark - 使用示例 -// 示例1:设置代理监听卡顿 + - (void)setupBuglyDelegate { [BuglyManager sharedManager].delegate = self; } -// 示例2:上报业务错误 + - (void)reportBusinessErrorExample { NSDictionary *context = @{ @"page": @"HomePage", @@ -31,7 +29,7 @@ context:context]; } -// 示例3:上报网络错误 + - (void)reportNetworkErrorExample { NSDictionary *userInfo = @{ @"requestParams": @{@"userId": @"12345"}, @@ -44,7 +42,7 @@ userInfo:userInfo]; } -// 示例4:上报内购错误 + - (void)reportIAPErrorExample { NSDictionary *context = @{ @"retryCount": @3, @@ -64,10 +62,8 @@ NSLog(@"[Example] 检测到卡顿,持续时间: %.2f 秒", duration); // TODO: 在这里实现卡顿通知逻辑 - // 1. 记录到本地日志 - // 2. 发送本地通知 - // 3. 上报到性能监控系统 - // 4. 触发用户反馈机制 + + } - (void)buglyManager:(BuglyManager *)manager didDetectBlock:(NSTimeInterval)duration { diff --git a/YuMi/Global/BuglyManagerExample.m.backup b/YuMi/Global/BuglyManagerExample.m.backup new file mode 100644 index 0000000..5810ec3 --- /dev/null +++ b/YuMi/Global/BuglyManagerExample.m.backup @@ -0,0 +1,79 @@ +// +// BuglyManagerExample.m +// YuMi +// +// Created by BuglyManager Example +// Copyright © 2024 YuMi. All rights reserved. +// + +#import "BuglyManagerExample.h" +#import "BuglyManager.h" + +@implementation BuglyManagerExample + +#pragma mark - 使用示例 + +// 示例1:设置代理监听卡顿 +- (void)setupBuglyDelegate { + [BuglyManager sharedManager].delegate = self; +} + +// 示例2:上报业务错误 +- (void)reportBusinessErrorExample { + NSDictionary *context = @{ + @"page": @"HomePage", + @"action": @"loadData", + @"timestamp": @([[NSDate date] timeIntervalSince1970]) + }; + + [[BuglyManager sharedManager] reportBusinessError:@"数据加载失败" + code:1001 + context:context]; +} + +// 示例3:上报网络错误 +- (void)reportNetworkErrorExample { + NSDictionary *userInfo = @{ + @"requestParams": @{@"userId": @"12345"}, + @"responseData": @"服务器错误" + }; + + [[BuglyManager sharedManager] reportNetworkError:@"user123" + api:@"user/profile" + code:500 + userInfo:userInfo]; +} + +// 示例4:上报内购错误 +- (void)reportIAPErrorExample { + NSDictionary *context = @{ + @"retryCount": @3, + @"productId": @"com.yumi.coin100" + }; + + [[BuglyManager sharedManager] reportIAPError:@"user123" + transactionId:@"txn_123456" + orderId:@"order_789" + status:2 + context:context]; +} + +#pragma mark - BuglyManagerDelegate + +- (void)buglyManager:(BuglyManager *)manager didDetectLag:(NSTimeInterval)duration { + NSLog(@"[Example] 检测到卡顿,持续时间: %.2f 秒", duration); + + // TODO: 在这里实现卡顿通知逻辑 + // 1. 记录到本地日志 + // 2. 发送本地通知 + // 3. 上报到性能监控系统 + // 4. 触发用户反馈机制 +} + +- (void)buglyManager:(BuglyManager *)manager didDetectBlock:(NSTimeInterval)duration { + NSLog(@"[Example] 检测到主线程阻塞,持续时间: %.2f 秒", duration); + + // TODO: 在这里实现阻塞通知逻辑 +} + +@end diff --git a/YuMi/Global/YUMIConstant.h b/YuMi/Global/YUMIConstant.h index acd68a9..d52b610 100644 --- a/YuMi/Global/YUMIConstant.h +++ b/YuMi/Global/YUMIConstant.h @@ -1,22 +1,20 @@ -// -// YMConstant.h -// YUMI -// + + // Created by YUMI on 2021/9/13. -// -///项目配置常量 + + #import NS_ASSUME_NONNULL_BEGIN @interface YUMIConstant : NSObject -/// 配置Key类型枚举(仅保留实际使用的类型) + typedef NS_ENUM(NSUInteger, Pi_KeyType) { - KeyType_Sign = 0, ///参数加密签名Key + KeyType_Sign = 0, }; -/// 获取指定类型的配置值 + NSString * const KeyWithType(Pi_KeyType type); @end diff --git a/YuMi/Global/YUMIConstant.h.backup b/YuMi/Global/YUMIConstant.h.backup new file mode 100644 index 0000000..acd68a9 --- /dev/null +++ b/YuMi/Global/YUMIConstant.h.backup @@ -0,0 +1,24 @@ +// +// YMConstant.h +// YUMI +// +// Created by YUMI on 2021/9/13. +// +///项目配置常量 +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface YUMIConstant : NSObject + +/// 配置Key类型枚举(仅保留实际使用的类型) +typedef NS_ENUM(NSUInteger, Pi_KeyType) { + KeyType_Sign = 0, ///参数加密签名Key +}; + +/// 获取指定类型的配置值 +NSString * const KeyWithType(Pi_KeyType type); + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Global/YUMIConstant.m b/YuMi/Global/YUMIConstant.m index 3fc369b..1efeaca 100644 --- a/YuMi/Global/YUMIConstant.m +++ b/YuMi/Global/YUMIConstant.m @@ -1,17 +1,15 @@ -// -// YMConstant.m -// YUMI -// + + // Created by YUMI on 2021/9/13. -// + #import "YUMIConstant.h" @implementation YUMIConstant -/// 获取指定类型的配置值 + NSString * const KeyWithType(Pi_KeyType type) { - // 参数加密签名Key(用于API请求签名) + if (type == KeyType_Sign) { return @"rpbs6us1m8r2j9g6u06ff2bo18orwaya"; } diff --git a/YuMi/Global/YUMIConstant.m.backup b/YuMi/Global/YUMIConstant.m.backup new file mode 100644 index 0000000..3fc369b --- /dev/null +++ b/YuMi/Global/YUMIConstant.m.backup @@ -0,0 +1,21 @@ +// +// YMConstant.m +// YUMI +// +// Created by YUMI on 2021/9/13. +// + +#import "YUMIConstant.h" + +@implementation YUMIConstant + +/// 获取指定类型的配置值 +NSString * const KeyWithType(Pi_KeyType type) { + // 参数加密签名Key(用于API请求签名) + if (type == KeyType_Sign) { + return @"rpbs6us1m8r2j9g6u06ff2bo18orwaya"; + } + return @""; +} + +@end diff --git a/YuMi/Global/YUMIHtmlUrl.h b/YuMi/Global/YUMIHtmlUrl.h index 092d8db..995376a 100644 --- a/YuMi/Global/YUMIHtmlUrl.h +++ b/YuMi/Global/YUMIHtmlUrl.h @@ -1,22 +1,20 @@ -// -// YMHtmlUrl.h -// YUMI -// + + // Created by YUMI on 2021/9/13. -// -///放置h5的链接地址 + + #import NS_ASSUME_NONNULL_BEGIN @interface YUMIHtmlUrl : NSObject -/// URL类型枚举(仅保留实际使用的类型) + typedef NS_ENUM(NSUInteger, URLType) { - kPrivacyURL = 0, ///隐私政策 - kUserProtocalURL = 4, ///用户协议 - kFAQURL = 6, ///帮助/常见问题 - kCaptchaSwitchPath = 113, ///人机验证 + kPrivacyURL = 0, + kUserProtocalURL = 4, + kFAQURL = 6, + kCaptchaSwitchPath = 113, }; NSString * const URLWithType(URLType type); diff --git a/YuMi/Global/YUMIHtmlUrl.h.backup b/YuMi/Global/YUMIHtmlUrl.h.backup new file mode 100644 index 0000000..092d8db --- /dev/null +++ b/YuMi/Global/YUMIHtmlUrl.h.backup @@ -0,0 +1,26 @@ +// +// YMHtmlUrl.h +// YUMI +// +// Created by YUMI on 2021/9/13. +// +///放置h5的链接地址 +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface YUMIHtmlUrl : NSObject + +/// URL类型枚举(仅保留实际使用的类型) +typedef NS_ENUM(NSUInteger, URLType) { + kPrivacyURL = 0, ///隐私政策 + kUserProtocalURL = 4, ///用户协议 + kFAQURL = 6, ///帮助/常见问题 + kCaptchaSwitchPath = 113, ///人机验证 +}; + +NSString * const URLWithType(URLType type); + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Global/YUMIHtmlUrl.m b/YuMi/Global/YUMIHtmlUrl.m index f9bb2e9..ea9e65e 100644 --- a/YuMi/Global/YUMIHtmlUrl.m +++ b/YuMi/Global/YUMIHtmlUrl.m @@ -1,9 +1,7 @@ -// -// YMHtmlUrl.m -// YUMI -// + + // Created by YUMI on 2021/9/13. -// + #import "YUMIHtmlUrl.h" #import "AESUtils.h" @@ -13,7 +11,7 @@ NSString * const URLWithType(URLType type) { NSString *prefix = @"eparty"; - // 明文 URL 配置(无需加密的路径) + NSDictionary *plainUrls = @{ @(kCaptchaSwitchPath): @"modules/humanMachineVerification/index.html", }; @@ -23,11 +21,11 @@ NSString * const URLWithType(URLType type) { return [NSString stringWithFormat:@"%@/%@", prefix, plainUrl]; } - // 加密 URL 配置(需要 AES 解密的路径) + NSDictionary *encryptedUrls = @{ - @(kPrivacyURL): @"sPa8x4YF1hFEeCeH5v+RMOulemxgjjZLbxkN8ZrBSM8=", // modules/rule/privacy-wap.html - @(kUserProtocalURL): @"0sBhBaRqf7oBlYvNK4azCrVPTFjv9FYF0A2v9+qkSxg=", // modules/rule/protocol.html - @(kFAQURL): @"k/Bqnh8nGkuhV8KhU6xN5a8EkxEQrbDMAWNBtaAdJCo=", // modules/rule/guide.html + @(kPrivacyURL): @"sPa8x4YF1hFEeCeH5v+RMOulemxgjjZLbxkN8ZrBSM8=", + @(kUserProtocalURL): @"0sBhBaRqf7oBlYvNK4azCrVPTFjv9FYF0A2v9+qkSxg=", + @(kFAQURL): @"k/Bqnh8nGkuhV8KhU6xN5a8EkxEQrbDMAWNBtaAdJCo=", }; NSString *encryptedUrl = encryptedUrls[@(type)]; @@ -36,7 +34,7 @@ NSString * const URLWithType(URLType type) { return [NSString stringWithFormat:@"%@/%@", prefix, decryptedPath]; } - // 未找到对应的 URL 配置 + return @""; } diff --git a/YuMi/Global/YUMIHtmlUrl.m.backup b/YuMi/Global/YUMIHtmlUrl.m.backup new file mode 100644 index 0000000..f9bb2e9 --- /dev/null +++ b/YuMi/Global/YUMIHtmlUrl.m.backup @@ -0,0 +1,43 @@ +// +// YMHtmlUrl.m +// YUMI +// +// Created by YUMI on 2021/9/13. +// + +#import "YUMIHtmlUrl.h" +#import "AESUtils.h" + +@implementation YUMIHtmlUrl + +NSString * const URLWithType(URLType type) { + NSString *prefix = @"eparty"; + + // 明文 URL 配置(无需加密的路径) + NSDictionary *plainUrls = @{ + @(kCaptchaSwitchPath): @"modules/humanMachineVerification/index.html", + }; + + NSString *plainUrl = plainUrls[@(type)]; + if (plainUrl) { + return [NSString stringWithFormat:@"%@/%@", prefix, plainUrl]; + } + + // 加密 URL 配置(需要 AES 解密的路径) + NSDictionary *encryptedUrls = @{ + @(kPrivacyURL): @"sPa8x4YF1hFEeCeH5v+RMOulemxgjjZLbxkN8ZrBSM8=", // modules/rule/privacy-wap.html + @(kUserProtocalURL): @"0sBhBaRqf7oBlYvNK4azCrVPTFjv9FYF0A2v9+qkSxg=", // modules/rule/protocol.html + @(kFAQURL): @"k/Bqnh8nGkuhV8KhU6xN5a8EkxEQrbDMAWNBtaAdJCo=", // modules/rule/guide.html + }; + + NSString *encryptedUrl = encryptedUrls[@(type)]; + if (encryptedUrl) { + NSString *decryptedPath = [AESUtils aesDecrypt:encryptedUrl]; + return [NSString stringWithFormat:@"%@/%@", prefix, decryptedPath]; + } + + // 未找到对应的 URL 配置 + return @""; +} + +@end diff --git a/YuMi/Global/YUMIMacroUitls.h b/YuMi/Global/YUMIMacroUitls.h index b43848b..6c4b818 100644 --- a/YuMi/Global/YUMIMacroUitls.h +++ b/YuMi/Global/YUMIMacroUitls.h @@ -1,10 +1,8 @@ -// -// YMMacro.h -// YUMI -// + + // Created by YUMI on 2021/9/10. -// -///一些宏 + + #import #import "../Tools/Bundle/NSBundle+Localizable.h" @@ -13,7 +11,7 @@ #import "../Tools/Bundle/YMLanguageConfig.h" -//iPhoneX系列设备(刘海屏设备) + #define iPhoneXSeries \ ({BOOL isPhoneXSeries = NO;\ if (@available(iOS 11.0, *)) {\ @@ -24,7 +22,7 @@ isPhoneXSeries = [[UIApplication sharedApplication] delegate].window.safeAreaIns #define KScreenWidth [[UIScreen mainScreen] bounds].size.width #define KScreenHeight [[UIScreen mainScreen] bounds].size.height -// 兼容 iOS 13+ 的状态栏高度获取 + #define statusbarHeight ({\ CGFloat height = 0;\ if (@available(iOS 13.0, *)) {\ @@ -40,16 +38,13 @@ isPhoneXSeries = [[UIApplication sharedApplication] delegate].window.safeAreaIns #define kSafeAreaBottomHeight (iPhoneXSeries ? 34 : 0) #define kSafeAreaTopHeight (iPhoneXSeries ? 24 : 0) #define kNavigationHeight (kStatusBarHeight + 44) -#define kTabBarHeight (iPhoneXSeries ? 49.0+34.0 : 49.0) #define kScreenScale ((CGFloat)KScreenWidth / (CGFloat)375) -#define kScreenHeightScale ((CGFloat)KScreenHeight / (CGFloat)812) -#define kHalfScreenHeight KScreenHeight * 0.65 #define kGetScaleWidth(width) kRoundValue(width) #define kRoundValue(value) round(kScreenScale * value) #define kWeakify(o) try{}@finally{} __weak typeof(o) o##Weak = o; #define kStrongify(o) autoreleasepool{} __strong typeof(o) o = o##Weak; -// 兼容 iOS 13+ 的 keyWindow 获取 + #define kWindow ({\ UIWindow *window = nil;\ if (@available(iOS 13.0, *)) {\ @@ -72,45 +67,17 @@ isPhoneXSeries = [[UIApplication sharedApplication] delegate].window.safeAreaIns #define kImage(image) [UIImage imageNamed:image] -///UIFont -#define kFontLight(font) [UIFont systemFontOfSize:kGetScaleWidth(font) weight:UIFontWeightLight] #define kFontRegular(font) [UIFont systemFontOfSize:kGetScaleWidth(font) weight:UIFontWeightRegular] #define kFontMedium(font) [UIFont systemFontOfSize:kGetScaleWidth(font) weight:UIFontWeightMedium] #define kFontSemibold(font) [UIFont systemFontOfSize:kGetScaleWidth(font) weight:UIFontWeightSemibold] #define kFontBold(font) [UIFont systemFontOfSize:kGetScaleWidth(font) weight:UIFontWeightBold] -#define kFontHeavy(font) [UIFont systemFontOfSize:kGetScaleWidth(font) weight:UIFontWeightHeavy] -///内置版本号 #define PI_App_Version @"1.0.0" -///渠道 -#define PI_App_Source @"appstore" -#define PI_Test_Flight @"TestFlight" -#define ISTestFlight 0 -///正式环境 -#define API_HOST_URL @"https://api.epartylive.com" -///测试环境 -#define API_HOST_TEST_URL @"http://beta.api.epartylive.com" // http://beta.api.epartylive.com | http://beta.api.pekolive.com | http://beta.api.molistar.xyz -#define API_Image_URL @"https://image.hfighting.com" +#define API_HOST_URL @"https://api.epartylive.com" #define YMLocalizedString(key) \ [NSBundle ymLocalizedStringForKey:(key)] -#define isMSRTL() [YMLanguageConfig isRTLanguage:[NSBundle getLanguageText]] -///是否是中文 -#define isMSZH() [[NSBundle getLanguageText] hasPrefix:@"zh"] -///是否是英文 -#define isMSEN() [[NSBundle getLanguageText] hasPrefix:@"en"] -///是否土耳其语 -#define isMSTR() [[NSBundle getLanguageText] hasPrefix:@"tr"] -///是否葡萄牙语 -#define isMSPT() [[NSBundle getLanguageText] hasPrefix:@"pt"] -///是否西班牙语 -#define isMSES() [[NSBundle getLanguageText] hasPrefix:@"es"] -///是否俄语 -#define isMSRU() [[NSBundle getLanguageText] hasPrefix:@"ru"] -///是否乌兹别克语 -#define isMSUZ() [[NSBundle getLanguageText] hasPrefix:@"uz"] - -#endif /* YUMIMacroUitls_h */ +#endif diff --git a/YuMi/Global/YUMINNNN.h b/YuMi/Global/YUMINNNN.h index a108cad..5ef55f4 100644 --- a/YuMi/Global/YUMINNNN.h +++ b/YuMi/Global/YUMINNNN.h @@ -1,17 +1,15 @@ -// -// YMEnum.h -// YUMI -// + + // Created by YUMI on 2021/9/13. -// -///全局枚举定义(仅保留实际使用的类型) + + #ifndef YUMINNNN_h #define YUMINNNN_h -/// 短信验证码业务类型(仅保留实际使用的类型) + typedef NS_ENUM(NSUInteger, GetSmsType) { - GetSmsType_Regist = 1, ///注册 - GetSmsType_Reset_Password = 3, ///重设密码 + GetSmsType_Regist = 1, + GetSmsType_Reset_Password = 3, }; -#endif /* YUMINNNN_h */ +#endif diff --git a/YuMi/Global/YUMINNNN.h.backup b/YuMi/Global/YUMINNNN.h.backup new file mode 100644 index 0000000..a108cad --- /dev/null +++ b/YuMi/Global/YUMINNNN.h.backup @@ -0,0 +1,17 @@ +// +// YMEnum.h +// YUMI +// +// Created by YUMI on 2021/9/13. +// +///全局枚举定义(仅保留实际使用的类型) +#ifndef YUMINNNN_h +#define YUMINNNN_h + +/// 短信验证码业务类型(仅保留实际使用的类型) +typedef NS_ENUM(NSUInteger, GetSmsType) { + GetSmsType_Regist = 1, ///注册 + GetSmsType_Reset_Password = 3, ///重设密码 +}; + +#endif /* YUMINNNN_h */ diff --git a/YuMi/Info.plist b/YuMi/Info.plist index e864069..8182ca5 100644 --- a/YuMi/Info.plist +++ b/YuMi/Info.plist @@ -36,15 +36,17 @@ NSCameraUsageDescription - "E-Party"需要您的同意,才可以访问进行拍照并上传您的图片,然后展示在您的个人主页上,便于他人查看 + "E-Party" needs your consent before you can visit, take photos and upload your pictures, and then display them on your personal homepage for others to view NSLocalNetworkUsageDescription - 此App将可发现和连接到您所用网络上的设备。 + The app will discover and connect to devices on your network + NSLocationWhenInUseUsageDescription + Your consent is required before you can use location services and recommend nearby friends NSPhotoLibraryAddUsageDescription - "E-Party"需要您的同意,才可以存储相片到相册 + "E-Party" needs your consent before it can store photos in the album NSPhotoLibraryUsageDescription - "E-Party"需要您的同意,才可以访问相册并选择您需要上传的图片,然后展示在您的个人主页上,便于他人查看 + "E-Party" needs your consent before you can access the album and select the pictures you need to upload, and then display them on your personal homepage for others to view NSUserTrackingUsageDescription - 請允許我們獲取您的IDFA權限,可以為您提供個性化活動和服務。未經您的允許,您的信息將不作其他用途。 + Please allow us to obtain your idfa permission to provide you with personalized activities and services. your information will not be used for other purposes without your permission UIApplicationSupportsIndirectInputEvents UILaunchStoryboardName diff --git a/YuMi/Modules/YMLogin/Api/Api+Login.h b/YuMi/Modules/YMLogin/Api/Api+Login.h index 49fe781..bbf5118 100644 --- a/YuMi/Modules/YMLogin/Api/Api+Login.h +++ b/YuMi/Modules/YMLogin/Api/Api+Login.h @@ -1,9 +1,7 @@ -// -// Api+Login.h -// YUMI -// + + // Created by zu on 2021/9/6. -// + #import "Api.h" NS_ASSUME_NONNULL_BEGIN @@ -13,10 +11,8 @@ NS_ASSUME_NONNULL_BEGIN + (void)phoneQuickLogin:(HttpRequestHelperCompletion)completion accessToken:(NSString *)accessToken token:(NSString *)token; -/// 手机验证码登录 -/// @param completion 完成 -/// @param phone 手机号 -/// @param code 验证码 + + + (void)loginWithCode:(HttpRequestHelperCompletion)completion phone:(NSString *)phone code:(NSString *)code @@ -26,10 +22,7 @@ NS_ASSUME_NONNULL_BEGIN grant_type:(NSString *)grant_type phoneAreaCode:(NSString *)phoneAreaCode; -/// 手机密码登录 -/// @param completion 完成 -/// @param phone 手机号 -/// @param password 验证码 + + (void)loginWithPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone password:(NSString *)password @@ -38,50 +31,34 @@ NS_ASSUME_NONNULL_BEGIN client_id:(NSString *)client_id grant_type:(NSString *)grant_type; -/// 充值密码 没有登录的时候 -/// @param complction 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 -/// @param smsCode 验证码 + + (void)resetPasswordWithPhone:(HttpRequestHelperCompletion)complction phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode phoneAreaCode:(NSString *)phoneAreaCode; -/// 第三方登录 -/// @param complction 完成 -/// @param openid 唯一标识符 -/// @param unionid unionid -/// @param access_token access_token -/// @param type 第三方登录的类型 + + (void)loginWithThirdPart:(HttpRequestHelperCompletion)complction openid:(NSString *)openid unionid:(NSString *)unionid access_token:(NSString *)access_token type:(NSString *)type; -/// 随机获取一个昵称 -/// @param completion 完成 + + (void)randomNick:(HttpRequestHelperCompletion)completion; -/// 绑定手机号码 -/// @param complection 完成 -/// @param phone 手机号 -/// @param code 验证码 -/// @param ticket ticket + + (void)bindMoblieCode:(HttpRequestHelperCompletion)complection phone:(NSString *)phone code:(NSString *)code ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode; +(void)getPhoneAreaCodeList:(HttpRequestHelperCompletion)complection; -/// 绑定授权码 -/// @param complection 完成 + +(void)bindAuthorizationCode:(HttpRequestHelperCompletion)complection authCode:(NSString *)authCode; -///反馈 + (void)loadFeedbackConfig:(HttpRequestHelperCompletion)completion; + (void)commitFeedback:(HttpRequestHelperCompletion)completion type:(NSString *)type diff --git a/YuMi/Modules/YMLogin/Api/Api+Login.h.backup b/YuMi/Modules/YMLogin/Api/Api+Login.h.backup new file mode 100644 index 0000000..49fe781 --- /dev/null +++ b/YuMi/Modules/YMLogin/Api/Api+Login.h.backup @@ -0,0 +1,117 @@ +// +// Api+Login.h +// YUMI +// +// Created by zu on 2021/9/6. +// + +#import "Api.h" +NS_ASSUME_NONNULL_BEGIN + +@interface Api (Login) + ++ (void)phoneQuickLogin:(HttpRequestHelperCompletion)completion + accessToken:(NSString *)accessToken + token:(NSString *)token; +/// 手机验证码登录 +/// @param completion 完成 +/// @param phone 手机号 +/// @param code 验证码 ++ (void)loginWithCode:(HttpRequestHelperCompletion)completion + phone:(NSString *)phone + code:(NSString *)code + client_secret:(NSString *)client_secret + version:(NSString *)version + client_id:(NSString *)client_id + grant_type:(NSString *)grant_type + phoneAreaCode:(NSString *)phoneAreaCode; + +/// 手机密码登录 +/// @param completion 完成 +/// @param phone 手机号 +/// @param password 验证码 ++ (void)loginWithPassword:(HttpRequestHelperCompletion)completion + phone:(NSString *)phone + password:(NSString *)password + client_secret:(NSString *)client_secret + version:(NSString *)version + client_id:(NSString *)client_id + grant_type:(NSString *)grant_type; + +/// 充值密码 没有登录的时候 +/// @param complction 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 +/// @param smsCode 验证码 ++ (void)resetPasswordWithPhone:(HttpRequestHelperCompletion)complction + phone:(NSString *)phone + newPwd:(NSString *)newPwd + smsCode:(NSString *)smsCode phoneAreaCode:(NSString *)phoneAreaCode; + +/// 第三方登录 +/// @param complction 完成 +/// @param openid 唯一标识符 +/// @param unionid unionid +/// @param access_token access_token +/// @param type 第三方登录的类型 ++ (void)loginWithThirdPart:(HttpRequestHelperCompletion)complction + openid:(NSString *)openid + unionid:(NSString *)unionid + access_token:(NSString *)access_token + type:(NSString *)type; + +/// 随机获取一个昵称 +/// @param completion 完成 ++ (void)randomNick:(HttpRequestHelperCompletion)completion; + +/// 绑定手机号码 +/// @param complection 完成 +/// @param phone 手机号 +/// @param code 验证码 +/// @param ticket ticket ++ (void)bindMoblieCode:(HttpRequestHelperCompletion)complection + phone:(NSString *)phone + code:(NSString *)code + ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode; + ++(void)getPhoneAreaCodeList:(HttpRequestHelperCompletion)complection; +/// 绑定授权码 +/// @param complection 完成 + ++(void)bindAuthorizationCode:(HttpRequestHelperCompletion)complection authCode:(NSString *)authCode; + + +///反馈 ++ (void)loadFeedbackConfig:(HttpRequestHelperCompletion)completion; ++ (void)commitFeedback:(HttpRequestHelperCompletion)completion + type:(NSString *)type + desc:(NSString *)desc + screenUrl:(NSString *)screenUrl + contact:(NSString *)contact; + ++ (void)emailGetCode:(HttpRequestHelperCompletion)completion emailAddress:(NSString *)emailAddress type:(NSNumber *)type; + ++ (void)emailVerify:(HttpRequestHelperCompletion)completion emailAddress:(NSString *)emailAddress code:(NSString *)code; + + ++ (void)loginWithCode:(HttpRequestHelperCompletion)completion + email:(NSString *)email + code:(NSString *)code + client_secret:(NSString *)client_secret + version:(NSString *)version + client_id:(NSString *)client_id + grant_type:(NSString *)grant_type; + ++ (void)userBoundEmail:(HttpRequestHelperCompletion)completion + email:(NSString *)email + code:(NSString *)code; ++ (void)userBoundPhone:(HttpRequestHelperCompletion)completion + phone:(NSString *)email + code:(NSString *)code + phoneAreaCode:(NSString *)phoneAreaCode; + ++ (void)resetPasswordWithEmail:(HttpRequestHelperCompletion)completion email:(NSString *)email newPwd:(NSString *)newPwd code:(NSString *)code; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/Api/Api+Login.m b/YuMi/Modules/YMLogin/Api/Api+Login.m index 5eb5bfb..390d542 100644 --- a/YuMi/Modules/YMLogin/Api/Api+Login.m +++ b/YuMi/Modules/YMLogin/Api/Api+Login.m @@ -1,44 +1,32 @@ -// -// Api+Login.m -// YUMI -// + + // Created by zu on 2021/9/6. -// + #import "Api+Login.h" #import @implementation Api (Login) + (void)phoneQuickLogin:(HttpRequestHelperCompletion)completion accessToken:(NSString *)accessToken token:(NSString *)token { - NSString * fang = [NSString stringFromBase64String:@"YWNjL29uZWNsaWNrL2xvZ2lu"];///acc/oneclick/login + NSString * fang = [NSString stringFromBase64String:@"YWNjL29uZWNsaWNrL2xvZ2lu"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, accessToken, token, nil]; } -/// 手机验证码登录 -/// @param completion 完成 -/// @param phone 手机号 -/// @param code 验证码 + + (void)loginWithCode:(HttpRequestHelperCompletion)completion phone:(NSString *)phone code:(NSString *)code client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type phoneAreaCode:(NSString *)phoneAreaCode{ - NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="];///oauth/token + NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,phone,code,client_secret,version, client_id, grant_type,phoneAreaCode, nil]; } -/// 手机密码登录 -/// @param completion 完成 -/// @param phone 手机号 -/// @param password 验证码 + + (void)loginWithPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone password:(NSString *)password client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type { [self makeRequest:@"oauth/token" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,phone,password,client_secret,version, client_id, grant_type, nil]; } -/// 重置手机号登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 -/// @param smsCode 验证码 + + (void)resetPasswordWithPhone:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode phoneAreaCode:(NSString *)phoneAreaCode{ - NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9yZXNldA=="];/// acc/pwd/reset + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9yZXNldA=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, phone, newPwd, smsCode,phoneAreaCode, nil]; } @@ -47,49 +35,37 @@ } -/// 第三方登录 -/// @param completion 完成 -/// @param openid 唯一标识符 -/// @param unionid unionid -/// @param access_token access_token -/// @param type 第三方登录的类型 + (void)loginWithThirdPart:(HttpRequestHelperCompletion)completion openid:(NSString *)openid unionid:(NSString *)unionid access_token:(NSString *)access_token type:(NSString *)type { - NSString * fang = [NSString stringFromBase64String:@"YWNjL3RoaXJkL2xvZ2lu"];///acc/third/login + NSString * fang = [NSString stringFromBase64String:@"YWNjL3RoaXJkL2xvZ2lu"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, openid, unionid, access_token, type, nil]; } -/// 随机获取一个昵称 -/// @param completion 完成 + + (void)randomNick:(HttpRequestHelperCompletion)completion { - NSString * fang = [NSString stringFromBase64String:@"cmFuZG9tL25pY2svZ2V0"];///random/nick/get + NSString * fang = [NSString stringFromBase64String:@"cmFuZG9tL25pY2svZ2V0"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, nil]; } -/// 绑定手机号码 -/// @param complection 完成 -/// @param phone 手机号 -/// @param code 验证码 -/// @param ticket ticket + + (void)bindMoblieCode:(HttpRequestHelperCompletion)complection phone:(NSString *)phone code:(NSString *)code ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode{ - NSString * fang = [NSString stringFromBase64String:@"d2l0aERyYXcvcGhvbmU="];///withDraw/phone + NSString * fang = [NSString stringFromBase64String:@"d2l0aERyYXcvcGhvbmU="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__, phone, code, ticket,phoneAreaCode, nil]; } +(void)getPhoneAreaCodeList:(HttpRequestHelperCompletion)complection{ - NSString * fang = [NSString stringFromBase64String:@"YXJlYUluZm8vbGlzdA=="];///areaInfo/list + NSString * fang = [NSString stringFromBase64String:@"YXJlYUluZm8vbGlzdA=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__,nil]; } -/// 绑定授权码 -/// @param complection 完成 + +(void)bindAuthorizationCode:(HttpRequestHelperCompletion)complection authCode:(NSString *)authCode{ [self makeRequest:@"phone/auth/bound" method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__,authCode, nil]; } -///反馈 + + (void)loadFeedbackConfig:(HttpRequestHelperCompletion)completion { [self makeRequest:@"feedback/getConfig" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } @@ -125,7 +101,7 @@ version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type { - NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="];///oauth/token + NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,email,code,client_secret,version, client_id, grant_type, nil]; } diff --git a/YuMi/Modules/YMLogin/Api/Api+Login.m.backup b/YuMi/Modules/YMLogin/Api/Api+Login.m.backup new file mode 100644 index 0000000..5eb5bfb --- /dev/null +++ b/YuMi/Modules/YMLogin/Api/Api+Login.m.backup @@ -0,0 +1,149 @@ +// +// Api+Login.m +// YUMI +// +// Created by zu on 2021/9/6. +// + +#import "Api+Login.h" +#import +@implementation Api (Login) + ++ (void)phoneQuickLogin:(HttpRequestHelperCompletion)completion accessToken:(NSString *)accessToken token:(NSString *)token { + NSString * fang = [NSString stringFromBase64String:@"YWNjL29uZWNsaWNrL2xvZ2lu"];///acc/oneclick/login + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, accessToken, token, nil]; +} + +/// 手机验证码登录 +/// @param completion 完成 +/// @param phone 手机号 +/// @param code 验证码 ++ (void)loginWithCode:(HttpRequestHelperCompletion)completion phone:(NSString *)phone code:(NSString *)code client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type phoneAreaCode:(NSString *)phoneAreaCode{ + NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="];///oauth/token + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,phone,code,client_secret,version, client_id, grant_type,phoneAreaCode, nil]; +} + +/// 手机密码登录 +/// @param completion 完成 +/// @param phone 手机号 +/// @param password 验证码 ++ (void)loginWithPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone password:(NSString *)password client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type { + + [self makeRequest:@"oauth/token" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,phone,password,client_secret,version, client_id, grant_type, nil]; +} + +/// 重置手机号登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 +/// @param smsCode 验证码 ++ (void)resetPasswordWithPhone:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode phoneAreaCode:(NSString *)phoneAreaCode{ + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9yZXNldA=="];/// acc/pwd/reset + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, phone, newPwd, smsCode,phoneAreaCode, nil]; +} + ++ (void)resetPasswordWithEmail:(HttpRequestHelperCompletion)completion email:(NSString *)email newPwd:(NSString *)newPwd code:(NSString *)code{ + [self makeRequest:@"acc/pwd/resetByEmail" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, email, newPwd, code, nil]; +} + + +/// 第三方登录 +/// @param completion 完成 +/// @param openid 唯一标识符 +/// @param unionid unionid +/// @param access_token access_token +/// @param type 第三方登录的类型 ++ (void)loginWithThirdPart:(HttpRequestHelperCompletion)completion openid:(NSString *)openid unionid:(NSString *)unionid access_token:(NSString *)access_token type:(NSString *)type { + NSString * fang = [NSString stringFromBase64String:@"YWNjL3RoaXJkL2xvZ2lu"];///acc/third/login + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, openid, unionid, access_token, type, nil]; +} + +/// 随机获取一个昵称 +/// @param completion 完成 ++ (void)randomNick:(HttpRequestHelperCompletion)completion { + NSString * fang = [NSString stringFromBase64String:@"cmFuZG9tL25pY2svZ2V0"];///random/nick/get + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, nil]; +} + +/// 绑定手机号码 +/// @param complection 完成 +/// @param phone 手机号 +/// @param code 验证码 +/// @param ticket ticket ++ (void)bindMoblieCode:(HttpRequestHelperCompletion)complection + phone:(NSString *)phone + code:(NSString *)code + ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode{ + NSString * fang = [NSString stringFromBase64String:@"d2l0aERyYXcvcGhvbmU="];///withDraw/phone + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__, phone, code, ticket,phoneAreaCode, nil]; +} + ++(void)getPhoneAreaCodeList:(HttpRequestHelperCompletion)complection{ + NSString * fang = [NSString stringFromBase64String:@"YXJlYUluZm8vbGlzdA=="];///areaInfo/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__,nil]; +} +/// 绑定授权码 +/// @param complection 完成 + ++(void)bindAuthorizationCode:(HttpRequestHelperCompletion)complection authCode:(NSString *)authCode{ + [self makeRequest:@"phone/auth/bound" method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__,authCode, nil]; +} + +///反馈 ++ (void)loadFeedbackConfig:(HttpRequestHelperCompletion)completion { + [self makeRequest:@"feedback/getConfig" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++ (void)commitFeedback:(HttpRequestHelperCompletion)completion + type:(NSString *)type + desc:(NSString *)desc + screenUrl:(NSString *)screenUrl + contact:(NSString *)contact { + [self makeRequest:@"feedback/commit" + method:HttpRequestHelperMethodPOST + completion:completion, __FUNCTION__, type, desc, screenUrl, contact, nil]; + +} + ++ (void)emailGetCode:(HttpRequestHelperCompletion)completion emailAddress:(NSString *)emailAddress type:(NSNumber *)type { + [self makeRequest:@"email/getCode" + method:HttpRequestHelperMethodPOST + completion:completion, __FUNCTION__, emailAddress, type, nil]; +} + + ++ (void)emailVerify:(HttpRequestHelperCompletion)completion emailAddress:(NSString *)emailAddress code:(NSString *)code { + [self makeRequest:@"email/verify" + method:HttpRequestHelperMethodPOST + completion:completion, __FUNCTION__, emailAddress, code, nil]; +} + ++ (void)loginWithCode:(HttpRequestHelperCompletion)completion + email:(NSString *)email + code:(NSString *)code + client_secret:(NSString *)client_secret + version:(NSString *)version + client_id:(NSString *)client_id + grant_type:(NSString *)grant_type { + NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="];///oauth/token + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,email,code,client_secret,version, client_id, grant_type, nil]; +} + ++ (void)userBoundEmail:(HttpRequestHelperCompletion)completion + email:(NSString *)email + code:(NSString *)code { + [self makeRequest:@"user/boundEmail" + method:HttpRequestHelperMethodPOST + completion:completion, __FUNCTION__, email, code, nil]; +} + ++ (void)userBoundPhone:(HttpRequestHelperCompletion)completion + phone:(NSString *)email + code:(NSString *)code + phoneAreaCode:(NSString *)phoneAreaCode { + [self makeRequest:@"user/boundPhone" + method:HttpRequestHelperMethodPOST + completion:completion, __FUNCTION__, email, code, nil]; +} + +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h index 09b044c..a90155b 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h @@ -1,16 +1,14 @@ -// -// PIUserSexView.h -// YuMi -// + + // Created by duoban on 2023/8/14. -// + #import NS_ASSUME_NONNULL_BEGIN @interface PIUserSexView : UIView -@property (nonatomic,assign) NSInteger gender; /// 性别 1:男 2:女 +@property (nonatomic,assign) NSInteger gender; @property (nonatomic,assign) BOOL selected; @end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h.backup new file mode 100644 index 0000000..09b044c --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.h.backup @@ -0,0 +1,17 @@ +// +// PIUserSexView.h +// YuMi +// +// Created by duoban on 2023/8/14. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PIUserSexView : UIView +@property (nonatomic,assign) NSInteger gender; /// 性别 1:男 2:女 +@property (nonatomic,assign) BOOL selected; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m index 0e21b21..4c310ee 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m @@ -1,19 +1,17 @@ -// -// PIUserSexView.m -// YuMi -// + + // Created by duoban on 2023/8/14. -// + #import "PIUserSexView.h" @interface PIUserSexView () -///背景 + @property (nonatomic,strong) UIImageView *backImageView; -///头像 + @property (nonatomic,strong) UIImageView *logoImageView; -///性别图标 + @property (nonatomic,strong) UIImageView *sexImageView; -///性别 + @property (nonatomic,strong) UILabel *sexLb; @end @implementation PIUserSexView @@ -59,11 +57,11 @@ - (void)setGender:(NSInteger)gender { _gender = gender; - if (_gender == 1) { // 男性 + if (_gender == 1) { self.logoImageView.image = [UIImage imageNamed:@"login_full_male_logo"]; self.sexLb.text = YMLocalizedString(@"PIUserSexView0"); self.sexImageView.image = [UIImage imageNamed:@"login_full_male"]; - } else if (_gender == 2) { // 女性 + } else if (_gender == 2) { self.logoImageView.image = [UIImage imageNamed:@"login_full_female_logo"]; self.sexLb.text = YMLocalizedString(@"PIUserSexView1"); self.sexImageView.image = [UIImage imageNamed:@"login_full_female"]; @@ -73,10 +71,10 @@ - (void)setSelected:(BOOL)selected { _selected = selected; if (_selected) { - if (self.gender == 1) { // 男性 + if (self.gender == 1) { self.backImageView.image = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#EBF5FF"],[DJDKMIMOMColor colorWithHexString:@"#FFFFFF"]] gradientType:GradientTypeTopToBottom imgSize:CGSizeMake(10, 10)]; self.backImageView.layer.borderColor = [DJDKMIMOMColor colorWithHexString:@"#B8E5FF"].CGColor; - } else { // 女性 + } else { self.backImageView.image = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#FFEBFA"],[DJDKMIMOMColor colorWithHexString:@"#FFFFFF"]] gradientType:GradientTypeTopToBottom imgSize:CGSizeMake(10, 10)]; self.backImageView.layer.borderColor = [DJDKMIMOMColor colorWithHexString:@"#FFB8E2"].CGColor; } diff --git a/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m.backup new file mode 100644 index 0000000..0e21b21 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/PIUserSexView.m.backup @@ -0,0 +1,127 @@ +// +// PIUserSexView.m +// YuMi +// +// Created by duoban on 2023/8/14. +// + +#import "PIUserSexView.h" +@interface PIUserSexView () +///背景 +@property (nonatomic,strong) UIImageView *backImageView; +///头像 +@property (nonatomic,strong) UIImageView *logoImageView; +///性别图标 +@property (nonatomic,strong) UIImageView *sexImageView; +///性别 +@property (nonatomic,strong) UILabel *sexLb; +@end +@implementation PIUserSexView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +- (void)initSubViews { + [self addSubview:self.backImageView]; + [self.backImageView addSubview:self.logoImageView]; + [self.backImageView addSubview:self.sexLb]; + [self.backImageView addSubview:self.sexImageView]; +} + +- (void)initSubViewConstraints { + [self.backImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; + + [self.logoImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(kGetScaleWidth(66), kGetScaleWidth(66))); + make.centerX.mas_equalTo(self.backImageView); + make.top.mas_equalTo(self.backImageView).offset(kGetScaleWidth(8)); + }]; + + [self.sexImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(kGetScaleWidth(16), kGetScaleWidth(16))); + make.trailing.mas_equalTo(self.backImageView.mas_centerX).offset(-1.5); + make.top.mas_equalTo(self.logoImageView.mas_bottom).offset(kGetScaleWidth(8)); + }]; + + [self.sexLb mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.backImageView.mas_centerX).offset(1.5); + make.centerY.mas_equalTo(self.sexImageView); + }]; +} + +- (void)setGender:(NSInteger)gender { + _gender = gender; + if (_gender == 1) { // 男性 + self.logoImageView.image = [UIImage imageNamed:@"login_full_male_logo"]; + self.sexLb.text = YMLocalizedString(@"PIUserSexView0"); + self.sexImageView.image = [UIImage imageNamed:@"login_full_male"]; + } else if (_gender == 2) { // 女性 + self.logoImageView.image = [UIImage imageNamed:@"login_full_female_logo"]; + self.sexLb.text = YMLocalizedString(@"PIUserSexView1"); + self.sexImageView.image = [UIImage imageNamed:@"login_full_female"]; + } +} + +- (void)setSelected:(BOOL)selected { + _selected = selected; + if (_selected) { + if (self.gender == 1) { // 男性 + self.backImageView.image = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#EBF5FF"],[DJDKMIMOMColor colorWithHexString:@"#FFFFFF"]] gradientType:GradientTypeTopToBottom imgSize:CGSizeMake(10, 10)]; + self.backImageView.layer.borderColor = [DJDKMIMOMColor colorWithHexString:@"#B8E5FF"].CGColor; + } else { // 女性 + self.backImageView.image = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#FFEBFA"],[DJDKMIMOMColor colorWithHexString:@"#FFFFFF"]] gradientType:GradientTypeTopToBottom imgSize:CGSizeMake(10, 10)]; + self.backImageView.layer.borderColor = [DJDKMIMOMColor colorWithHexString:@"#FFB8E2"].CGColor; + } + + } else { + self.backImageView.image = [UIImage imageWithColor:[UIColor clearColor]]; + self.backImageView.layer.borderColor = [DJDKMIMOMColor colorWithHexString:@"#FAFBFC"].CGColor; + } +} + +- (UIImageView *)backImageView { + if (!_backImageView) { + _backImageView = [[UIImageView alloc] init]; + _backImageView.userInteractionEnabled = YES; + _backImageView.layer.masksToBounds = YES; + _backImageView.layer.borderWidth = 1; + _backImageView.layer.cornerRadius = kGetScaleWidth(18); + } + return _backImageView; +} + +- (UIImageView *)logoImageView { + if (!_logoImageView) { + _logoImageView = [[UIImageView alloc] init]; + _logoImageView.userInteractionEnabled = YES; + } + return _logoImageView; +} + +- (UIImageView *)sexImageView { + if (!_sexImageView) { + _sexImageView = [[UIImageView alloc] init]; + _sexImageView.userInteractionEnabled = YES; + } + return _sexImageView; +} + +- (UILabel *)sexLb { + if (!_sexLb) { + _sexLb = [[UILabel alloc] init]; + _sexLb.font = kFontMedium(14); + _sexLb.textColor = [DJDKMIMOMColor colorWithHexString:@"#1F1A4E"]; + } + return _sexLb; +} + + +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h index d3f3aae..a987548 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h @@ -1,9 +1,7 @@ -// -// YMForgetPwdViewController.h -// YUMI -// + + // Created by XY on 2023/2/14. -// + #import "MvpViewController.h" diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h.backup new file mode 100644 index 0000000..d3f3aae --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.h.backup @@ -0,0 +1,16 @@ +// +// YMForgetPwdViewController.h +// YUMI +// +// Created by XY on 2023/2/14. +// + +#import "MvpViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPForgetPwdViewController : MvpViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m index 676bdc3..fba4df8 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m @@ -1,9 +1,7 @@ -// -// YMForgetPwdViewController.m -// YUMI -// + + // Created by XY on 2023/2/14. -// + #import "XPForgetPwdViewController.h" #import @@ -17,19 +15,19 @@ #import "XPLoginAraeViewController.h" @interface XPForgetPwdViewController () -///背景 + @property(nonatomic,strong) UIImageView *bgImageView; -///返回 + @property(nonatomic,strong) UIButton *backBnt; -/// 标题 + @property (nonatomic, strong) UILabel *titleLabel; -/// 手机号输入框 + @property (nonatomic, strong) XPLoginInputView *phoneInputView; -/// 验证码输入框 + @property (nonatomic, strong) XPLoginInputView *codeInputView; -/// 密码输入框 + @property (nonatomic, strong) XPLoginInputView *pwdInputView; -/// 确定按钮 + @property (nonatomic, strong) UIButton *sureBtn; @property (nonatomic,copy) NSString *pi_phoneAreaCode; @@ -127,7 +125,7 @@ }] takeUntil:self.rac_willDeallocSignal]; } -/// 确认 + - (void)sureBtnClicked { NSString *phone = self.phoneInputView.inputTextField.text; NSString *smsCode = self.codeInputView.inputTextField.text; @@ -162,13 +160,13 @@ #pragma mark - LoginForgetPasswordProtocol -///请求手机号的验证码成功 + - (void)phoneSmsCodeSuccess { [self showSuccessToast:YMLocalizedString(@"XPForgetPwdViewController1")]; [self.codeInputView fireTimer]; } -///重置密码成功 + - (void)resetPasswrodSuccess { [self showSuccessToast:YMLocalizedString(@"XPForgetPwdViewController2")]; [self.navigationController popViewControllerAnimated:YES]; diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m.backup new file mode 100644 index 0000000..676bdc3 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPForgetPwdViewController.m.backup @@ -0,0 +1,271 @@ +// +// YMForgetPwdViewController.m +// YUMI +// +// Created by XY on 2023/2/14. +// + +#import "XPForgetPwdViewController.h" +#import +#import "YUMIMacroUitls.h" +#import + +#import "XPLoginInputView.h" + +#import "LoginForgetPasswordPresent.h" +#import "LoginForgetPasswordProtocol.h" +#import "XPLoginAraeViewController.h" + +@interface XPForgetPwdViewController () +///背景 +@property(nonatomic,strong) UIImageView *bgImageView; +///返回 +@property(nonatomic,strong) UIButton *backBnt; +/// 标题 +@property (nonatomic, strong) UILabel *titleLabel; +/// 手机号输入框 +@property (nonatomic, strong) XPLoginInputView *phoneInputView; +/// 验证码输入框 +@property (nonatomic, strong) XPLoginInputView *codeInputView; +/// 密码输入框 +@property (nonatomic, strong) XPLoginInputView *pwdInputView; +/// 确定按钮 +@property (nonatomic, strong) UIButton *sureBtn; +@property (nonatomic,copy) NSString *pi_phoneAreaCode; + +@end + +@implementation XPForgetPwdViewController +- (BOOL)isHiddenNavBar { + return YES; +} +- (LoginForgetPasswordPresent *)createPresenter { + return [[LoginForgetPasswordPresent alloc] init]; +} +- (void)viewWillDisappear:(BOOL)animated{ + [super viewWillDisappear:animated]; + [self.codeInputView cancelTimer]; +} +- (void)viewDidLoad { + NSString *code = [NSString getCountryCode]; + self.pi_phoneAreaCode = [code stringByReplacingOccurrencesOfString:@"+" withString:@""]; + + [super viewDidLoad]; + [self createUI]; + [self racBind]; +} + +- (void)createUI { + self.view.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:self.bgImageView]; + [self.view addSubview:self.backBnt]; + [self.view addSubview:self.titleLabel]; + UIView *bgView = [UIView new]; + bgView.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:bgView]; + bgView.layer.cornerRadius = kGetScaleWidth(20); + bgView.layer.masksToBounds = YES; + [self.view addSubview:self.phoneInputView]; + [self.view addSubview:self.codeInputView]; + [self.view addSubview:self.pwdInputView]; + [self.view addSubview:self.sureBtn]; + + + [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(418)); + }]; + [self.backBnt mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kGetScaleWidth(20)); + make.width.mas_equalTo(kGetScaleWidth(28)); + make.height.mas_equalTo(kGetScaleWidth(28)); + make.top.mas_equalTo(kGetScaleWidth(52)); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.equalTo(self.backBnt.mas_bottom).mas_offset(kGetScaleWidth(48)); + make.leading.mas_equalTo(kGetScaleWidth(24)); + make.height.mas_equalTo(kGetScaleWidth(40)); + }]; + [bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.equalTo(self.view); + make.top.mas_equalTo(kGetScaleWidth(257)); + }]; + [self.phoneInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(kGetScaleWidth(303)); + make.top.mas_equalTo(kGetScaleWidth(296)); + make.height.mas_equalTo(kGetScaleWidth(52)); + }]; + [self.codeInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(kGetScaleWidth(303)); + make.top.mas_equalTo(self.phoneInputView.mas_bottom).offset(kGetScaleWidth(20)); + make.height.mas_equalTo(kGetScaleWidth(52)); + }]; + [self.pwdInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(kGetScaleWidth(303)); + make.top.mas_equalTo(self.codeInputView.mas_bottom).offset(kGetScaleWidth(20)); + make.height.mas_equalTo(kGetScaleWidth(52)); + }]; + [self.sureBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.pwdInputView.mas_bottom).offset(kGetScaleWidth(48)); + make.centerX.mas_equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(48)); + make.width.mas_equalTo(kGetScaleWidth(303)); + }]; + +} +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + [self.view endEditing:YES]; +} +- (void)racBind { + RAC(self.sureBtn, enabled) = [[RACSignal combineLatest:@[self.phoneInputView.inputTextField.rac_textSignal, self.pwdInputView.inputTextField.rac_textSignal, self.pwdInputView.inputTextField.rac_textSignal] reduce:^id _Nonnull(NSString *phone, NSString* smsCode, NSString *password){ + return @((phone.length > 0) && smsCode.length >= 5 && (password.length >= 6 && password.length <= 16)); + }] takeUntil:self.rac_willDeallocSignal]; +} + +/// 确认 +- (void)sureBtnClicked { + NSString *phone = self.phoneInputView.inputTextField.text; + NSString *smsCode = self.codeInputView.inputTextField.text; + NSString *password = self.pwdInputView.inputTextField.text; + [self.presenter resetPassword:[NSString stringWithFormat:@"%@%@",self.pi_phoneAreaCode,phone] newPwd:password smsCode:smsCode phoneAreaCode:self.pi_phoneAreaCode]; +} + +#pragma mark - XPLoginInputViewDelegate + +- (void)smsCodeAction { + NSString *phone = self.phoneInputView.inputTextField.text; + if (phone.length <= 0) { + [self showErrorToast:YMLocalizedString(@"XPForgetPwdViewController0")]; + return; + } + [self.presenter phoneSmsCode:[NSString stringWithFormat:@"%@%@",self.pi_phoneAreaCode,phone] type:GetSmsType_Reset_Password phoneAreaCode:self.pi_phoneAreaCode]; + +} + +- (void)areaListAction { + XPLoginAraeViewController *codeVC = [XPLoginAraeViewController new]; + codeVC.delegate = self; + [self.navigationController pushViewController:codeVC animated:YES]; +} + +- (void)chooseAreaCodeSuccess:(NSString *)code { + if (code.length > 0) { + self.pi_phoneAreaCode = code; + [self.phoneInputView.areaCodeBtn setTitle:[NSString stringWithFormat:@"+%@", code] forState:UIControlStateNormal]; + } +} + +#pragma mark - LoginForgetPasswordProtocol + +///请求手机号的验证码成功 +- (void)phoneSmsCodeSuccess { + [self showSuccessToast:YMLocalizedString(@"XPForgetPwdViewController1")]; + [self.codeInputView fireTimer]; +} + +///重置密码成功 +- (void)resetPasswrodSuccess { + [self showSuccessToast:YMLocalizedString(@"XPForgetPwdViewController2")]; + [self.navigationController popViewControllerAnimated:YES]; + +} +-(void)backViewAction1{ + [self.navigationController popViewControllerAnimated:YES]; +} +#pragma mark - 懒加载 + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = kFontBold(28); + _titleLabel.textColor = UIColorFromRGB(0x1F1B4F); + _titleLabel.text = YMLocalizedString(@"XPForgetPwdViewController3"); + + } + return _titleLabel; +} + +- (XPLoginInputView *)phoneInputView { + if (!_phoneInputView) { + _phoneInputView = [[XPLoginInputView alloc] init]; + _phoneInputView.areaStackView.hidden = NO; + _phoneInputView.delegate = self; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPForgetPwdViewController4")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _phoneInputView.inputTextField.attributedPlaceholder = placeholder; + _phoneInputView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + } + return _phoneInputView; +} + +- (XPLoginInputView *)codeInputView { + if (!_codeInputView) { + _codeInputView = [[XPLoginInputView alloc] init]; + _codeInputView.smsCodeBtn.hidden = NO; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPForgetPwdViewController5")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _codeInputView.inputTextField.attributedPlaceholder = placeholder; + _codeInputView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + _codeInputView.delegate = self; + } + return _codeInputView; +} + +- (XPLoginInputView *)pwdInputView { + if (!_pwdInputView) { + _pwdInputView = [[XPLoginInputView alloc] init]; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPForgetPwdViewController6")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _pwdInputView.inputTextField.attributedPlaceholder = placeholder; + _pwdInputView.inputTextField.keyboardType = UIKeyboardTypeAlphabet; + _pwdInputView.inputTextField.secureTextEntry = YES; + } + return _pwdInputView; +} + +- (UIButton *)sureBtn { + if (!_sureBtn) { + _sureBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + + UIImage *nextImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor],[DJDKMIMOMColor confirmButtonGradientMiddleColor],[DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(303), kGetScaleWidth(48))]; + UIImage *disableImage = [UIImage gradientColorImageFromColors:@[UIColorFromRGB(0xD1F9FF),UIColorFromRGB(0xDEE4FF),UIColorFromRGB(0xEEDCFF)] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(303), kGetScaleWidth(48))]; + + [_sureBtn setImage:nextImage forState:UIControlStateNormal]; + [_sureBtn setImage:disableImage forState:UIControlStateDisabled]; + _sureBtn.layer.cornerRadius = kGetScaleWidth(48)/2; + _sureBtn.layer.masksToBounds = YES; + + + UILabel *titleView = [UILabel labelInitWithText:YMLocalizedString(@"XPLoginPhoneViewController8") font:kFontMedium(16) textColor:[UIColor whiteColor]]; + titleView.textAlignment = NSTextAlignmentCenter; + [_sureBtn addSubview:titleView]; + [titleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.sureBtn); + }]; + [_sureBtn addTarget:self action:@selector(sureBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _sureBtn; +} +- (UIImageView *)bgImageView{ + if(!_bgImageView){ + _bgImageView = [[UIImageView alloc]init]; + _bgImageView.image = kImage(@"login_phone_pwd_bg"); + _bgImageView.contentMode = 2; + } + return _bgImageView; +} +- (UIButton *)backBnt{ + if(!_backBnt){ + _backBnt = [UIButton new]; + [_backBnt setImage:[kImage(@"common_nav_back")ms_SetImageForRTL] forState:UIControlStateNormal]; + [_backBnt addTarget:self action:@selector(backViewAction1) forControlEvents:UIControlEventTouchUpInside]; + [_backBnt setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + } + return _backBnt; +} +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h index 1a1f289..fbfde6f 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h @@ -1,9 +1,7 @@ -// -// XPLoginAraeViewController.h -// YuMi -// + + // Created by YuMi on 2023/6/25. -// + #import "BaseViewController.h" @@ -14,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @end @interface XPLoginAraeViewController : BaseViewController -///代理 + @property (nonatomic,weak) id delegate; @end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h.backup new file mode 100644 index 0000000..1a1f289 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.h.backup @@ -0,0 +1,21 @@ +// +// XPLoginAraeViewController.h +// YuMi +// +// Created by YuMi on 2023/6/25. +// + +#import "BaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN +@protocol XPLoginAraeViewControllerDelegate + +-(void)chooseAreaCodeSuccess:(NSString *)code; + +@end +@interface XPLoginAraeViewController : BaseViewController +///代理 +@property (nonatomic,weak) id delegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m index f314a1e..5053687 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m @@ -1,18 +1,16 @@ -// -// XPLoginAraeViewController.m -// YuMi -// + + // Created by YuMi on 2023/6/25. -// + #import "XPLoginAraeViewController.h" -///view + #import "XPLoginAreaTableViewCell.h" #import "LoginAreaModel.h" #import "NSObject+MJExtension.h" #import "YUMIMacroUitls.h" #import "Api+Login.h" -///Third + #import @interface XPLoginAraeViewController () @property (nonatomic,strong) UITableView *tableView; @@ -31,17 +29,17 @@ #pragma mark - LoginVerifCodeProtocol -(void)getPhoneAreaCodeList{ - // 获取文件路径 + NSString *path = [[NSBundle mainBundle] pathForResource:@"pi_area_info" ofType:@"json"]; - // 将文件数据化 + NSData *data = [[NSData alloc] initWithContentsOfFile:path]; - // 对数据进行JSON格式化并返回字典形式 + NSError *error = nil; NSDictionary *codeData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error]; if (error) { -// NSLog(@"JSON Parsing Error: %@", error.localizedDescription); + } NSArray *codeList = [LoginAreaModel modelsWithArray:codeData[@"RECORDS"]]; [self getLocalPlistWithList:codeList]; diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m.backup new file mode 100644 index 0000000..f314a1e --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAraeViewController.m.backup @@ -0,0 +1,191 @@ +// +// XPLoginAraeViewController.m +// YuMi +// +// Created by YuMi on 2023/6/25. +// + +#import "XPLoginAraeViewController.h" +///view +#import "XPLoginAreaTableViewCell.h" +#import "LoginAreaModel.h" +#import "NSObject+MJExtension.h" +#import "YUMIMacroUitls.h" +#import "Api+Login.h" +///Third +#import +@interface XPLoginAraeViewController () +@property (nonatomic,strong) UITableView *tableView; +@property (nonatomic,strong) NSMutableArray *listData; +@property (nonatomic,strong) NSMutableArray *titleList; +@end + +@implementation XPLoginAraeViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + [self initSubViews]; + [self initSubViewConstraints]; + [self getPhoneAreaCodeList]; +} +#pragma mark - LoginVerifCodeProtocol + +-(void)getPhoneAreaCodeList{ + // 获取文件路径 + NSString *path = [[NSBundle mainBundle] pathForResource:@"pi_area_info" ofType:@"json"]; + // 将文件数据化 + NSData *data = [[NSData alloc] initWithContentsOfFile:path]; + // 对数据进行JSON格式化并返回字典形式 + NSError *error = nil; + NSDictionary *codeData = [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableLeaves + error:&error]; + if (error) { +// NSLog(@"JSON Parsing Error: %@", error.localizedDescription); + } + NSArray *codeList = [LoginAreaModel modelsWithArray:codeData[@"RECORDS"]]; + [self getLocalPlistWithList:codeList]; +} +-(void)getLocalPlistWithList:(NSArray *)list{ + + NSArray * letterList = @[@"",@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z"]; + NSMutableArray *otherList = [NSMutableArray array]; + NSMutableArray *defaultList = [NSMutableArray array]; + LoginAreaModel *TwModel; + LoginAreaModel *HKModel ; + LoginAreaModel *SPModel ; + LoginAreaModel *MYModel ; + LoginAreaModel *ChinsModel ; + [self.titleList addObject:@""]; + for (NSString *letter in letterList) { + NSMutableArray *modelList = [NSMutableArray array]; + for (LoginAreaModel *model in list) { + if([model.code isEqualToString:@"886"]){ + TwModel = model; + } + if([model.code isEqualToString:@"852"]){ + HKModel = model; + } + if([model.code isEqualToString:@"65"]){ + SPModel = model; + } + if([model.code isEqualToString:@"60"]){ + MYModel = model; + } + if([model.code isEqualToString:@"86"]){ + ChinsModel = model; + } + NSString *fristLetter = [model.name substringWithRange:NSMakeRange(0, 1)]; + if([letter isEqualToString:fristLetter]){ + [modelList addObject:model]; + }else{ + if(![letterList containsObject:fristLetter] && ![otherList containsObject:model]){ + [otherList addObject:model]; + } + } + } + if(modelList.count > 0){ + + [self.titleList addObject:letter]; + [self.listData addObject:modelList]; + } + } + if(TwModel != nil){ + [defaultList addObject:TwModel]; + } + if(HKModel != nil){ + [defaultList addObject:HKModel]; + } + if(SPModel != nil){ + [defaultList addObject:SPModel]; + } + if(MYModel != nil){ + [defaultList addObject:MYModel]; + } + if(ChinsModel != nil){ + [defaultList addObject:ChinsModel]; + } + [self.listData insertObject:defaultList atIndex:0]; + if(otherList.count > 0){ + [self.listData addObject:otherList]; + [self.titleList addObject:@"#"]; + } + [self.tableView reloadData]; +} +#pragma mark - UITableViewDelegate +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ + return self.listData.count; +} +- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ + + return self.titleList[section]; +} +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return [self.listData[section] count]; +} + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { + return self.titleList; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + XPLoginAreaTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPLoginAreaTableViewCell class]) forIndexPath:indexPath]; + if(cell.delegate == nil){ + cell.delegate = self; + } + if(indexPath.section < self.listData.count){ + NSArray *listModel = self.listData[indexPath.section]; + if(indexPath.row < listModel.count){ + cell.areaModel =listModel[indexPath.row]; + } + } + return cell; +} + +#pragma mark - XPLoginAreaTableViewCellDelegate +- (void)didSelectModel:(LoginAreaModel *)model{ + LoginAreaModel *codeModel = model; + if(self.delegate && [self.delegate respondsToSelector:@selector(chooseAreaCodeSuccess:)]){ + + [self.delegate chooseAreaCodeSuccess:codeModel.code]; + } + [self.navigationController popViewControllerAnimated:YES]; +} +#pragma mark - Private Method +- (void)initSubViews { + self.title = YMLocalizedString(@"XPChooseRreaCodeVC0"); + [self.view addSubview:self.tableView]; +} +- (void)initSubViewConstraints { + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; +} +#pragma mark - Getters And Setters +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.rowHeight = kGetScaleWidth(37); + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;; + _tableView.backgroundColor = [UIColor whiteColor]; + [_tableView registerClass:[XPLoginAreaTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPLoginAreaTableViewCell class])]; + } + return _tableView; +} +- (NSMutableArray *)titleList{ + if (!_titleList){ + _titleList = [NSMutableArray array]; + } + return _titleList; +} +- (NSMutableArray *)listData{ + if (!_listData){ + _listData = [NSMutableArray array]; + } + return _listData; +} + + +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h index 9042756..951cf96 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h @@ -1,9 +1,7 @@ -// -// XPLoginAreaTableViewCell.h -// YuMi -// + + // Created by YuMi on 2023/6/25. -// + #import @class LoginAreaModel; diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h.backup new file mode 100644 index 0000000..9042756 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.h.backup @@ -0,0 +1,24 @@ +// +// XPLoginAreaTableViewCell.h +// YuMi +// +// Created by YuMi on 2023/6/25. +// + +#import +@class LoginAreaModel; +@protocol XPLoginAreaTableViewCellDelegate + +-(void)didSelectModel:(LoginAreaModel *_Nullable)model; + +@end + +NS_ASSUME_NONNULL_BEGIN + +@interface XPLoginAreaTableViewCell : UITableViewCell + +@property (nonatomic,strong) LoginAreaModel *areaModel; +@property(nonatomic,weak) iddelegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m index 097a023..fd4a095 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m @@ -1,14 +1,12 @@ -// -// XPLoginAreaTableViewCell.m -// YuMi -// + + // Created by YuMi on 2023/6/25. -// + #import "XPLoginAreaTableViewCell.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "LoginAreaModel.h" @interface XPLoginAreaTableViewCell() diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m.backup new file mode 100644 index 0000000..097a023 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAreaTableViewCell.m.backup @@ -0,0 +1,88 @@ +// +// XPLoginAreaTableViewCell.m +// YuMi +// +// Created by YuMi on 2023/6/25. +// + +#import "XPLoginAreaTableViewCell.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "LoginAreaModel.h" +@interface XPLoginAreaTableViewCell() +@property (nonatomic,strong) UILabel *areaVeiw; +@property (nonatomic,strong) UILabel *codeView; +@property(nonatomic,strong) UIButton *clickBtn; +@end +@implementation XPLoginAreaTableViewCell +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + self.backgroundColor = [UIColor whiteColor]; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self.contentView addSubview:self.areaVeiw]; + [self.contentView addSubview:self.codeView]; + [self.contentView addSubview:self.clickBtn]; +} +- (void)initSubViewConstraints { + [self.areaVeiw mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kGetScaleWidth(15)); + make.centerY.equalTo(self.contentView); + }]; + [self.codeView mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(-kGetScaleWidth(15)); + make.centerY.equalTo(self.contentView); + }]; + [self.clickBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.leading.bottom.equalTo(self.contentView); + make.trailing.mas_equalTo(-kGetScaleWidth(20)); + }]; +} +-(void)didClickBtnAction{ + if(self.delegate && [self.delegate respondsToSelector:@selector(didSelectModel:)]){ + [self.delegate didSelectModel:self.areaModel]; + } +} +- (void)setAreaModel:(LoginAreaModel *)areaModel{ + _areaModel = areaModel; + _areaVeiw.text = _areaModel.name; + _codeView.text = _areaModel.code; + +} +#pragma mark - 懒加载 + +- (UILabel *)areaVeiw { + if (!_areaVeiw) { + _areaVeiw = [[UILabel alloc] init]; + _areaVeiw.font = [UIFont systemFontOfSize:14]; + _areaVeiw.textColor = [DJDKMIMOMColor colorWithHexString:@"#1F1A4E"]; + } + return _areaVeiw; +} + + +- (UILabel *)codeView { + if (!_codeView) { + _codeView = [[UILabel alloc] init]; + _codeView.font = [UIFont systemFontOfSize:14]; + _codeView.textColor = [DJDKMIMOMColor colorWithHexString:@"#1F1A4E"]; + } + return _codeView; +} +- (UIButton *)clickBtn{ + if(!_clickBtn){ + _clickBtn = [UIButton new]; + [_clickBtn addTarget:self action:@selector(didClickBtnAction) forControlEvents:UIControlEventTouchUpInside]; + } + return _clickBtn; +} +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h index ce32dd1..8212f50 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h @@ -1,9 +1,7 @@ -// -// XPLoginAuthCodeVC.h -// YuMi -// + + // Created by duoban on 2023/8/11. -// + #import "MvpViewController.h" diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h.backup new file mode 100644 index 0000000..ce32dd1 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.h.backup @@ -0,0 +1,23 @@ +// +// XPLoginAuthCodeVC.h +// YuMi +// +// Created by duoban on 2023/8/11. +// + +#import "MvpViewController.h" + +@protocol XPLoginAuthCodeVCDelegate + +-(void)bindCodeSuccess; + +@end + +NS_ASSUME_NONNULL_BEGIN + +@interface XPLoginAuthCodeVC : MvpViewController +@property(nonatomic,weak) iddelegate; +@property(nonatomic,assign) BOOL pi_isPush; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m index 23cdfdb..a7ba3ed 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m @@ -1,9 +1,7 @@ -// -// XPLoginAuthCodeVC.m -// YuMi -// + + // Created by duoban on 2023/8/11. -// + #import "XPLoginAuthCodeVC.h" #import "XPLoginInputView.h" @@ -11,14 +9,14 @@ #import "LoginVerifCodePresent.h" #import "LoginFullInfoViewController.h" @interface XPLoginAuthCodeVC () -///背景 + @property(nonatomic,strong) UIImageView *bgImageView; -/// 手机号登录 + @property (nonatomic, strong) UILabel *titleLabel; -/// 手机号输入框 + @property (nonatomic, strong) XPLoginInputView *codeInputView; -/// 登录按钮 + @property (nonatomic, strong) UIButton *loginBtn; @end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m.backup new file mode 100644 index 0000000..23cdfdb --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginAuthCodeVC.m.backup @@ -0,0 +1,165 @@ +// +// XPLoginAuthCodeVC.m +// YuMi +// +// Created by duoban on 2023/8/11. +// + +#import "XPLoginAuthCodeVC.h" +#import "XPLoginInputView.h" +#import +#import "LoginVerifCodePresent.h" +#import "LoginFullInfoViewController.h" +@interface XPLoginAuthCodeVC () +///背景 +@property(nonatomic,strong) UIImageView *bgImageView; + +/// 手机号登录 +@property (nonatomic, strong) UILabel *titleLabel; +/// 手机号输入框 +@property (nonatomic, strong) XPLoginInputView *codeInputView; +/// 登录按钮 +@property (nonatomic, strong) UIButton *loginBtn; +@end + +@implementation XPLoginAuthCodeVC +- (BOOL)isHiddenNavBar { + return YES; +} +- (LoginVerifCodePresent *)createPresenter { + return [[LoginVerifCodePresent alloc] init]; +} +- (void)viewDidLoad { + [super viewDidLoad]; + [self installUI]; + [self installConstraints]; + [self racBind]; +} +-(void)installUI{ + self.view.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:self.bgImageView]; + [self.view addSubview:self.titleLabel]; + + +} +-(void)installConstraints{ + UIView *bgView = [UIView new]; + bgView.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:bgView]; + bgView.layer.cornerRadius = kGetScaleWidth(20); + bgView.layer.masksToBounds = YES; + [self.view addSubview:self.codeInputView]; + [self.view addSubview:self.loginBtn]; + [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(418)); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(kGetScaleWidth(128)); + make.leading.mas_equalTo(kGetScaleWidth(24)); + make.height.mas_equalTo(kGetScaleWidth(40)); + }]; + [bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.equalTo(self.view); + make.top.mas_equalTo(kGetScaleWidth(192)); + }]; + [self.codeInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(kGetScaleWidth(303)); + make.top.mas_equalTo(kGetScaleWidth(260)); + make.height.mas_equalTo(kGetScaleWidth(52)); + }]; + [self.loginBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.codeInputView.mas_bottom).offset(kGetScaleWidth(48)); + make.centerX.mas_equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(48)); + make.width.mas_equalTo(kGetScaleWidth(303)); + }]; +} +- (void)racBind { + + RAC(self.loginBtn, enabled) = [[RACSignal combineLatest:@[self.codeInputView.inputTextField.rac_textSignal] reduce:^id _Nonnull(NSString *account){ + + return @(account.length > 0); + }] takeUntil:self.rac_willDeallocSignal]; +} +-(void)loginBtnClicked{ + [self showLoading]; + [self.presenter bindAuthorizationCodeWithAuthCode:self.codeInputView.inputTextField.text]; +} +#pragma mark - LoginVerifCodeProtocol +- (void)bindAuthorizationCodeSuccess{ + [self hideHUD]; + [self showSuccessToast:YMLocalizedString(@"XPLoginAuthCodeVC2")]; + self.loginBtn.enabled = YES; + if(self.pi_isPush == YES){ + LoginFullInfoViewController * FullVC = [[LoginFullInfoViewController alloc] init]; + [self.navigationController pushViewController:FullVC animated:YES]; + return; + } + [self dismissViewControllerAnimated:YES completion:nil]; + if(self.delegate && [self.delegate respondsToSelector:@selector(bindCodeSuccess)]){ + [self.delegate bindCodeSuccess]; + } + +} +-(void)bindAuthorizationCodeFail{ + [self hideHUD]; + self.loginBtn.enabled = YES; +} +#pragma mark - 懒加载 + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = YMLocalizedString(@"XPLoginAuthCodeVC0"); + _titleLabel.font = kFontBold(28); + _titleLabel.textColor = UIColorFromRGB(0x1F1B4F); + } + return _titleLabel; +} +- (UIImageView *)bgImageView{ + if(!_bgImageView){ + _bgImageView = [[UIImageView alloc]init]; + _bgImageView.image = kImage(@"login_phone_pwd_bg"); + _bgImageView.contentMode = 2; + } + return _bgImageView; +} +- (XPLoginInputView *)codeInputView { + if (!_codeInputView) { + _codeInputView = [[XPLoginInputView alloc] init]; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginAuthCodeVC1")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _codeInputView.inputTextField.attributedPlaceholder = placeholder; + _codeInputView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + + } + return _codeInputView; +} +- (UIButton *)loginBtn { + if (!_loginBtn) { + _loginBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + + UIImage *nextImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor],[DJDKMIMOMColor confirmButtonGradientMiddleColor],[DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(303), kGetScaleWidth(48))]; + UIImage *disableImage = [UIImage gradientColorImageFromColors:@[UIColorFromRGB(0xD1F9FF),UIColorFromRGB(0xDEE4FF),UIColorFromRGB(0xEEDCFF)] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(303), kGetScaleWidth(48))]; + + [_loginBtn setImage:nextImage forState:UIControlStateNormal]; + [_loginBtn setImage:disableImage forState:UIControlStateDisabled]; + _loginBtn.layer.cornerRadius = kGetScaleWidth(48)/2; + _loginBtn.layer.masksToBounds = YES; + + + UILabel *titleView = [UILabel labelInitWithText:YMLocalizedString(@"XPLoginAuthCodeVC3") font:kFontMedium(16) textColor:[UIColor whiteColor]]; + titleView.textAlignment = NSTextAlignmentCenter; + [_loginBtn addSubview:titleView]; + [titleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.loginBtn); + }]; + [_loginBtn addTarget:self action:@selector(loginBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _loginBtn; +} +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h index 9a753e7..302dd4c 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h @@ -1,9 +1,7 @@ -// -// YMLoginInputView.h -// YUMI -// + + // Created by XY on 2023/2/14. -// + #import @@ -18,18 +16,18 @@ NS_ASSUME_NONNULL_BEGIN @end @interface XPLoginInputView : UIView -/// + @property (nonatomic,strong) UIStackView *areaStackView; -/// 区号 + @property (nonatomic, strong) UIButton *areaCodeBtn; -/// 输入框 + @property (nonatomic, strong) UITextField *inputTextField; -/// 验证码 + @property (nonatomic, strong) UIButton *smsCodeBtn; @property (nonatomic, weak) id delegate; -//开启倒计时 + - (void)fireTimer; -(void)cancelTimer; @end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h.backup new file mode 100644 index 0000000..9a753e7 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.h.backup @@ -0,0 +1,37 @@ +// +// YMLoginInputView.h +// YUMI +// +// Created by XY on 2023/2/14. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol XPLoginInputViewDelegate + +- (void)smsCodeAction; + +- (void)areaListAction; + +@end + +@interface XPLoginInputView : UIView +/// +@property (nonatomic,strong) UIStackView *areaStackView; +/// 区号 +@property (nonatomic, strong) UIButton *areaCodeBtn; +/// 输入框 +@property (nonatomic, strong) UITextField *inputTextField; +/// 验证码 +@property (nonatomic, strong) UIButton *smsCodeBtn; + +@property (nonatomic, weak) id delegate; + +//开启倒计时 +- (void)fireTimer; +-(void)cancelTimer; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m index 204adf0..681eea4 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m @@ -1,9 +1,7 @@ -// -// YMLoginInputView.m -// YUMI -// + + // Created by XY on 2023/2/14. -// + #import "XPLoginInputView.h" #import "DJDKMIMOMColor.h" @@ -46,7 +44,7 @@ areaImageView.image = [UIImage imageNamed:@"login_area_arrow"]; areaImageView.userInteractionEnabled = NO; - /// 区号 + NSString *code = [NSString getCountryCode]; UIButton *areaCodeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [areaCodeBtn setTitle:code forState:UIControlStateNormal]; @@ -71,13 +69,13 @@ [stackView addArrangedSubview:areaStackView]; self.areaStackView = areaStackView; - /// 输入框 + MSBaseTextField *inputTextField = [[MSBaseTextField alloc] init]; inputTextField.textColor = UIColorFromRGB(0x1F1B4F); inputTextField.font = kFontRegular(14); [stackView addArrangedSubview:inputTextField]; self.inputTextField = inputTextField; - /// 获取验证码 + UIButton *smsCodeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [smsCodeBtn setTitle:YMLocalizedString(@"XPLoginInputView0") forState:UIControlStateNormal]; [smsCodeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; @@ -136,7 +134,7 @@ } } -//开启倒计时 + - (void)fireTimer { __block NSInteger count = 60; dispatch_queue_t queue = dispatch_get_main_queue(); diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m.backup new file mode 100644 index 0000000..204adf0 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginInputView.m.backup @@ -0,0 +1,168 @@ +// +// YMLoginInputView.m +// YUMI +// +// Created by XY on 2023/2/14. +// + +#import "XPLoginInputView.h" +#import "DJDKMIMOMColor.h" +#import +#import +#import "LoginAreaModel.h" +#import "MSBaseTextField.h" +@interface XPLoginInputView() + +@property (nonatomic, strong) dispatch_source_t timer; + +@property (nonatomic,strong) UIImageView *areaImageView; +@end + +@implementation XPLoginInputView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = UIColorFromRGB(0xF3F5FA); + self.layer.cornerRadius = kGetScaleWidth(52)/2; + self.layer.masksToBounds = YES; + + [self createUI]; + } + return self; +} + +- (void)createUI { + UIStackView *stackView = [[UIStackView alloc] init]; + stackView.axis = UILayoutConstraintAxisHorizontal; + stackView.distribution = UIStackViewDistributionFill; + stackView.alignment = UIStackViewAlignmentCenter; + stackView.spacing = kGetScaleWidth(8); + [self addSubview:stackView]; + + + UIImageView * areaImageView = [[UIImageView alloc] init]; + areaImageView.userInteractionEnabled = YES; + areaImageView.image = [UIImage imageNamed:@"login_area_arrow"]; + areaImageView.userInteractionEnabled = NO; + + /// 区号 + NSString *code = [NSString getCountryCode]; + UIButton *areaCodeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [areaCodeBtn setTitle:code forState:UIControlStateNormal]; + [areaCodeBtn setTitleColor:UIColorFromRGB(0x1F1B4F) forState:UIControlStateNormal]; + areaCodeBtn.titleLabel.font = kFontMedium(16); + _areaCodeBtn = areaCodeBtn; + areaCodeBtn.userInteractionEnabled = NO; + + UIStackView *areaStackView = [[UIStackView alloc] init]; + areaStackView.axis = UILayoutConstraintAxisHorizontal; + areaStackView.distribution = UIStackViewDistributionFill; + areaStackView.alignment = UIStackViewAlignmentCenter; + areaStackView.spacing = kGetScaleWidth(8); + + UIButton *areaBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [areaBtn addTarget:self action:@selector(areaChooseClicked) forControlEvents:UIControlEventTouchUpInside]; + [areaStackView addSubview:areaBtn]; + + [areaStackView addArrangedSubview:areaCodeBtn]; + [areaStackView addArrangedSubview:areaImageView]; + + [stackView addArrangedSubview:areaStackView]; + self.areaStackView = areaStackView; + + /// 输入框 + MSBaseTextField *inputTextField = [[MSBaseTextField alloc] init]; + inputTextField.textColor = UIColorFromRGB(0x1F1B4F); + inputTextField.font = kFontRegular(14); + [stackView addArrangedSubview:inputTextField]; + self.inputTextField = inputTextField; + /// 获取验证码 + UIButton *smsCodeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [smsCodeBtn setTitle:YMLocalizedString(@"XPLoginInputView0") forState:UIControlStateNormal]; + [smsCodeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + smsCodeBtn.titleLabel.font = kFontMedium(12); + smsCodeBtn.titleLabel.textAlignment = NSTextAlignmentCenter; + smsCodeBtn.titleLabel.numberOfLines = 2; + smsCodeBtn.layer.cornerRadius = kGetScaleWidth(38)/2; + smsCodeBtn.layer.masksToBounds = YES; + smsCodeBtn.backgroundColor = UIColorFromRGB(0x9168FA); + [smsCodeBtn addTarget:self action:@selector(smsCodeBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + [stackView addArrangedSubview:smsCodeBtn]; + self.smsCodeBtn = smsCodeBtn; + + [stackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kGetScaleWidth(24)); + make.trailing.mas_equalTo(-kGetScaleWidth(24)); + make.top.bottom.mas_equalTo(0); + }]; + + + [areaImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(kGetScaleWidth(12)); + make.height.mas_equalTo(kGetScaleWidth(8)); + }]; + + [areaCodeBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_lessThanOrEqualTo(kGetScaleWidth(60)); + make.height.mas_equalTo(stackView); + }]; + [inputTextField mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(stackView); + }]; + [smsCodeBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(kGetScaleWidth(102)); + make.height.mas_equalTo(kGetScaleWidth(38)); + }]; + + [areaBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(areaStackView); + }]; + + + self.areaStackView.hidden = YES; + self.smsCodeBtn.hidden = YES; +} + +- (void)smsCodeBtnClicked { + if (self.delegate && [self.delegate respondsToSelector:@selector(smsCodeAction)]) { + [self.delegate smsCodeAction]; + } +} + +- (void)areaChooseClicked { + if (self.delegate && [self.delegate respondsToSelector:@selector(areaListAction)]) { + [self.delegate areaListAction]; + } +} + +//开启倒计时 +- (void)fireTimer { + __block NSInteger count = 60; + dispatch_queue_t queue = dispatch_get_main_queue(); + dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); + dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC); + @weakify(self); + dispatch_source_set_event_handler(timer, ^{ + @strongify(self); + count--; + if (count < 0) { + [self.smsCodeBtn setTitle:YMLocalizedString(@"XPLoginInputView1") forState:UIControlStateNormal]; + self.smsCodeBtn.userInteractionEnabled = YES; + dispatch_cancel(self.timer); + self.timer = nil; + }else{ + [self.smsCodeBtn setTitle:[NSString stringWithFormat:@"%lds",count] forState:UIControlStateNormal]; + self.smsCodeBtn.userInteractionEnabled = NO; + } + }); + dispatch_resume(timer); + self.timer = timer; +} +-(void)cancelTimer{ + if (self.timer != nil){ + dispatch_cancel(self.timer); + self.timer = nil; + } +} +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h index ecf4326..9fdeea5 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h @@ -1,9 +1,7 @@ -// -// YMLoginPhoneViewController.h -// YUMI -// + + // Created by XY on 2023/2/13. -// + #import "MvpViewController.h" diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h.backup new file mode 100644 index 0000000..ecf4326 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.h.backup @@ -0,0 +1,16 @@ +// +// YMLoginPhoneViewController.h +// YUMI +// +// Created by XY on 2023/2/13. +// + +#import "MvpViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPLoginPhoneViewController : MvpViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m index 55bcbca..effe778 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m @@ -1,9 +1,7 @@ -// -// YMLoginPhoneViewController.m -// YUMI -// + + // Created by XY on 2023/2/13. -// + #import "XPLoginPhoneViewController.h" #import @@ -19,40 +17,39 @@ #import "XPForgetPwdViewController.h" @interface XPLoginPhoneViewController () -///背景 + @property(nonatomic,strong) UIImageView *bgImageView; -///返回 + @property(nonatomic,strong) UIButton *backBnt; -/// 手机号登录 + @property (nonatomic, strong) UILabel *titleLabel; -/// 未注册的手机号自动登录 + @property (nonatomic, strong) UILabel *despLabel; -///选择类型背景 + @property(nonatomic,strong) UIImageView *chooseTypeView; -///选择手机登录 + @property(nonatomic,strong) UIButton *choosePhoneBtn; -///选择密码登录 + @property(nonatomic,strong) UIButton *choosePsdBtn; -/// 手机号输入框 + @property (nonatomic, strong) XPLoginInputView *phoneInputView; -/// 验证码输入框 + @property (nonatomic, strong) XPLoginInputView *codeInputView; -///// 账号登录手机号输入框 @property (nonatomic, strong) XPLoginInputView *accountView; -/// 账号登录密码输入框 + @property (nonatomic, strong) XPLoginInputView *accountPwdView; -/// 忘记密码 + @property (nonatomic, strong) UIButton *forgetBtn; -/// 登录按钮 + @property (nonatomic, strong) UIButton *loginBtn; -///区号 + @property (nonatomic,copy) NSString *pi_phoneAreaCode; -///类型,0,密码,1.手机 + @property(nonatomic,assign) int selectType; @end @@ -179,7 +176,7 @@ }] takeUntil:self.rac_willDeallocSignal]; } -/// 登录 + - (void)loginBtnClicked { [XNDJTDDLoadingTool showOnlyView:self.view]; if(self.selectType == 0){ diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m.backup new file mode 100644 index 0000000..55bcbca --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPhoneViewController.m.backup @@ -0,0 +1,430 @@ +// +// YMLoginPhoneViewController.m +// YUMI +// +// Created by XY on 2023/2/13. +// + +#import "XPLoginPhoneViewController.h" +#import +#import "YUMIMacroUitls.h" +#import + +#import "XPLoginInputView.h" +#import "PILoginManager.h" +#import "XPLoginPwdViewController.h" +#import "XPLoginAraeViewController.h" +#import "LoginVerifCodePresent.h" +#import "LoginVerifCodeProtocol.h" +#import "XPForgetPwdViewController.h" + +@interface XPLoginPhoneViewController () +///背景 +@property(nonatomic,strong) UIImageView *bgImageView; +///返回 +@property(nonatomic,strong) UIButton *backBnt; + +/// 手机号登录 +@property (nonatomic, strong) UILabel *titleLabel; +/// 未注册的手机号自动登录 +@property (nonatomic, strong) UILabel *despLabel; +///选择类型背景 +@property(nonatomic,strong) UIImageView *chooseTypeView; +///选择手机登录 +@property(nonatomic,strong) UIButton *choosePhoneBtn; +///选择密码登录 +@property(nonatomic,strong) UIButton *choosePsdBtn; +/// 手机号输入框 +@property (nonatomic, strong) XPLoginInputView *phoneInputView; +/// 验证码输入框 +@property (nonatomic, strong) XPLoginInputView *codeInputView; + + +///// 账号登录手机号输入框 +@property (nonatomic, strong) XPLoginInputView *accountView; +/// 账号登录密码输入框 +@property (nonatomic, strong) XPLoginInputView *accountPwdView; +/// 忘记密码 +@property (nonatomic, strong) UIButton *forgetBtn; + +/// 登录按钮 +@property (nonatomic, strong) UIButton *loginBtn; + +///区号 +@property (nonatomic,copy) NSString *pi_phoneAreaCode; +///类型,0,密码,1.手机 +@property(nonatomic,assign) int selectType; +@end + +@implementation XPLoginPhoneViewController +- (BOOL)isHiddenNavBar { + return YES; +} +- (LoginVerifCodePresent *)createPresenter { + return [[LoginVerifCodePresent alloc] init]; +} + + +- (void)viewDidLoad { + self.selectType = 0; + NSString *code = [NSString getCountryCode]; + self.pi_phoneAreaCode = [code stringByReplacingOccurrencesOfString:@"+" withString:@""]; + [super viewDidLoad]; + [self createUI]; + [self racBind]; +} + +- (void)createUI { + self.view.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:self.bgImageView]; + [self.view addSubview:self.backBnt]; + [self.view addSubview:self.titleLabel]; + + [self.view addSubview:self.chooseTypeView]; + [self.chooseTypeView addSubview:self.choosePhoneBtn]; + [self.chooseTypeView addSubview:self.choosePsdBtn]; + UIView *bgView = [UIView new]; + bgView.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:bgView]; + [self.view addSubview:self.phoneInputView]; + [self.view addSubview:self.codeInputView]; + [self.view addSubview:self.accountView]; + [self.view addSubview:self.accountPwdView]; + [self.view addSubview:self.forgetBtn]; + + [self.view addSubview:self.loginBtn]; + [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(418)); + }]; + [self.backBnt mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kGetScaleWidth(20)); + make.width.mas_equalTo(kGetScaleWidth(28)); + make.height.mas_equalTo(kGetScaleWidth(28)); + make.top.mas_equalTo(kGetScaleWidth(52)); + }]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.equalTo(self.backBnt.mas_bottom).mas_offset(kGetScaleWidth(48)); + make.leading.mas_equalTo(kGetScaleWidth(24)); + make.height.mas_equalTo(kGetScaleWidth(40)); + }]; + + [self.chooseTypeView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).mas_offset(kGetScaleWidth(24)); + make.leading.trailing.equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(65)); + }]; + + [self.choosePsdBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(16)); + make.height.mas_equalTo(kGetScaleWidth(22)); + make.width.mas_equalTo(KScreenWidth/2); + make.leading.mas_equalTo(0); + }]; + [self.choosePhoneBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(16)); + make.height.mas_equalTo(kGetScaleWidth(22)); + make.width.mas_equalTo(KScreenWidth/2); + make.trailing.mas_equalTo(0); + }]; + [bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.equalTo(self.view); + make.top.equalTo(self.chooseTypeView.mas_bottom); + }]; + [self.phoneInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(kGetScaleWidth(303)); + make.top.mas_equalTo(self.chooseTypeView.mas_bottom).offset(kGetScaleWidth(39)); + make.height.mas_equalTo(kGetScaleWidth(52)); + }]; + [self.codeInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(kGetScaleWidth(303)); + make.top.mas_equalTo(self.phoneInputView.mas_bottom).offset(kGetScaleWidth(20)); + make.height.mas_equalTo(kGetScaleWidth(52)); + }]; + + [self.accountView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.phoneInputView); + }]; + [self.accountPwdView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.codeInputView); + }]; + [self.forgetBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(-kGetScaleWidth(52)); + make.height.mas_equalTo(kGetScaleWidth(17)); + make.top.equalTo(self.accountPwdView.mas_bottom).mas_offset(kGetScaleWidth(8)); + }]; + [self.loginBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.codeInputView.mas_bottom).offset(kGetScaleWidth(48)); + make.centerX.mas_equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(48)); + make.width.mas_equalTo(kGetScaleWidth(303)); + }]; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + [self.view endEditing:YES]; +} + +- (void)racBind { + @weakify(self); + RAC(self.loginBtn, enabled) = [[RACSignal combineLatest:@[self.phoneInputView.inputTextField.rac_textSignal, self.codeInputView.inputTextField.rac_textSignal,self.accountView.inputTextField.rac_textSignal,self.accountPwdView.inputTextField.rac_textSignal] reduce:^id _Nonnull(NSString *phone, NSString* smsCode,NSString *account,NSString *accountPwd){ + @strongify(self); + if(self.selectType == 0){ + return @((account.length > 0) && accountPwd.length >= 6); + } + return @((phone.length > 0) && smsCode.length >= 5); + }] takeUntil:self.rac_willDeallocSignal]; +} + +/// 登录 +- (void)loginBtnClicked { + [XNDJTDDLoadingTool showOnlyView:self.view]; + if(self.selectType == 0){ + NSString *phone = self.accountView.inputTextField.text; + NSString *password = self.accountPwdView.inputTextField.text; + [self.presenter loginWithPhone:phone password:password]; + return; + } + + NSString *phone = self.phoneInputView.inputTextField.text; + NSString *smsCode = self.codeInputView.inputTextField.text; + NSString * phoneStr = [NSString stringWithFormat:@"%@%@",self.pi_phoneAreaCode, phone]; + [self.presenter loginWithPhone:phoneStr code:smsCode phoneAreaCode:self.pi_phoneAreaCode]; +} + +- (void)forgetBtnClicked { + XPForgetPwdViewController *forgetVC = [[XPForgetPwdViewController alloc] init]; + [self.navigationController pushViewController:forgetVC animated:YES]; +} + +#pragma mark - XPLoginInputViewDelegate + +- (void)smsCodeAction { + NSString *phone = self.phoneInputView.inputTextField.text; + if (phone.length == 0 ) { + [self showErrorToast:YMLocalizedString(@"XPLoginPhoneViewController0")]; + return; + } + [self.presenter phoneSmsCode:[NSString stringWithFormat:@"%@%@",self.pi_phoneAreaCode,phone] type:GetSmsType_Regist phoneAreaCode:self.pi_phoneAreaCode]; +} + +- (void)areaListAction { + XPLoginAraeViewController *codeVC = [XPLoginAraeViewController new]; + codeVC.delegate = self; + [self.navigationController pushViewController:codeVC animated:YES]; +} + +- (void)chooseAreaCodeSuccess:(NSString *)code { + if (code.length > 0) { + self.pi_phoneAreaCode = code; + [self.phoneInputView.areaCodeBtn setTitle:[NSString stringWithFormat:@"+%@", code] forState:UIControlStateNormal]; + } +} + +#pragma mark - LoginVerifCodeProtocol +- (void)loginWithPhoenSuccess{ + [XNDJTDDLoadingTool hideOnlyView:self.view]; + [self showSuccessToast:YMLocalizedString(@"XPLoginPhoneViewController1")]; + [PILoginManager loginWithVC:self isLoginPhone:YES]; +} +- (void)loginSuccess { + [XNDJTDDLoadingTool hideOnlyView:self.view]; + [self showSuccessToast:YMLocalizedString(@"XPLoginPhoneViewController1")]; + [PILoginManager loginWithVC:self isLoginPhone:NO]; +} +- (void)loginFailWithMsg:(NSString *)msg{ + [self showErrorToast:msg]; + [XNDJTDDLoadingTool hideOnlyView:self.view]; +} +-(void)backViewAction{ + [self.navigationController popViewControllerAnimated:YES]; +} + +#pragma mark - LoginProtocol +- (void)phoneSmsCodeSuccess { + [self showSuccessToast:YMLocalizedString(@"XPLoginPhoneViewController2")]; + [self.codeInputView fireTimer]; +} + + +-(void)setSelectType:(int)selectType{ + _selectType = selectType; + _chooseTypeView.image = _selectType == 0 ? kImage(@"login_choose_phone_bg"): kImage(@"login_choose_pwd_bg"); + _choosePhoneBtn.selected = _selectType != 0; + _choosePsdBtn.selected = _selectType == 0; + _forgetBtn.hidden = _selectType != 0; + + _phoneInputView.hidden = _selectType == 0; + _codeInputView.hidden = _selectType == 0; + _accountView.hidden = _selectType != 0; + _accountPwdView.hidden = _selectType != 0; + +} +-(void)choosePhoneAction{ + self.selectType = 1; +} +-(void)choosePwdAction{ + self.selectType = 0; +} +#pragma mark - 懒加载 + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = @"Welcome to E-Party!"; + _titleLabel.font = kFontBold(28); + _titleLabel.textColor = UIColorFromRGB(0x1F1B4F); + } + return _titleLabel; +} + +- (UILabel *)despLabel { + if (!_despLabel) { + _despLabel = [[UILabel alloc] init]; + _despLabel.text = YMLocalizedString(@"XPLoginPhoneViewController4"); + _despLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightRegular]; + _despLabel.textColor = [UIColor.whiteColor colorWithAlphaComponent:0.6]; + } + return _despLabel; +} + +- (XPLoginInputView *)phoneInputView { + if (!_phoneInputView) { + _phoneInputView = [[XPLoginInputView alloc] init]; + _phoneInputView.areaStackView.hidden = NO; + _phoneInputView.delegate = self; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPhoneViewController5")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _phoneInputView.inputTextField.attributedPlaceholder = placeholder; + _phoneInputView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + _phoneInputView.hidden = YES; + } + return _phoneInputView; +} + +- (XPLoginInputView *)codeInputView { + if (!_codeInputView) { + _codeInputView = [[XPLoginInputView alloc] init]; + _codeInputView.smsCodeBtn.hidden = NO; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPhoneViewController6")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _codeInputView.inputTextField.attributedPlaceholder = placeholder; + _codeInputView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + _codeInputView.delegate = self; + _codeInputView.hidden = YES; + } + return _codeInputView; +} + +- (UIButton *)loginBtn { + if (!_loginBtn) { + _loginBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + + UIImage *nextImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor],[DJDKMIMOMColor confirmButtonGradientMiddleColor],[DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(303), kGetScaleWidth(48))]; + UIImage *disableImage = [UIImage gradientColorImageFromColors:@[UIColorFromRGB(0xD1F9FF),UIColorFromRGB(0xDEE4FF),UIColorFromRGB(0xEEDCFF)] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(kGetScaleWidth(303), kGetScaleWidth(48))]; + + [_loginBtn setImage:nextImage forState:UIControlStateNormal]; + [_loginBtn setImage:disableImage forState:UIControlStateDisabled]; + _loginBtn.layer.cornerRadius = kGetScaleWidth(48)/2; + _loginBtn.layer.masksToBounds = YES; + + + UILabel *titleView = [UILabel labelInitWithText:YMLocalizedString(@"XPLoginPhoneViewController8") font:kFontMedium(16) textColor:[UIColor whiteColor]]; + titleView.textAlignment = NSTextAlignmentCenter; + [_loginBtn addSubview:titleView]; + [titleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.loginBtn); + }]; + [_loginBtn addTarget:self action:@selector(loginBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _loginBtn; +} + +- (UIImageView *)bgImageView{ + if(!_bgImageView){ + _bgImageView = [[UIImageView alloc]init]; + _bgImageView.image = kImage(@"login_phone_pwd_bg"); + _bgImageView.contentMode = 2; + } + return _bgImageView; +} +- (UIButton *)backBnt{ + if(!_backBnt){ + _backBnt = [UIButton new]; + [_backBnt setImage:[kImage(@"common_nav_back")ms_SetImageForRTL] forState:UIControlStateNormal]; + [_backBnt addTarget:self action:@selector(backViewAction) forControlEvents:UIControlEventTouchUpInside]; + [_backBnt setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + } + return _backBnt; +} +- (UIImageView *)chooseTypeView{ + if(!_chooseTypeView){ + _chooseTypeView = [UIImageView new]; + _chooseTypeView.userInteractionEnabled = YES; + [_chooseTypeView setImage:kImage(@"login_choose_phone_bg")]; + } + return _chooseTypeView; +} +- (UIButton *)choosePhoneBtn{ + if(!_choosePhoneBtn){ + _choosePhoneBtn = [UIButton new]; + [_choosePhoneBtn setTitle:YMLocalizedString(@"1.0.37_text_26") forState:UIControlStateNormal]; + [_choosePhoneBtn setTitleColor:UIColorFromRGB(0x6D6B89) forState:UIControlStateNormal]; + [_choosePhoneBtn setTitleColor:UIColorFromRGB(0x1F1B4F) forState:UIControlStateSelected]; + _choosePhoneBtn.titleLabel.font = kFontSemibold(16); + [ _choosePhoneBtn setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + [_choosePhoneBtn addTarget:self action:@selector(choosePhoneAction) forControlEvents:UIControlEventTouchUpInside]; + } + return _choosePhoneBtn; +} +- (UIButton *)choosePsdBtn{ + if(!_choosePsdBtn){ + _choosePsdBtn = [UIButton new]; + [_choosePsdBtn setTitle:YMLocalizedString(@"1.0.37_text_27") forState:UIControlStateNormal]; + [_choosePsdBtn setTitleColor:UIColorFromRGB(0x6D6B89) forState:UIControlStateNormal]; + [_choosePsdBtn setTitleColor:UIColorFromRGB(0x1F1B4F) forState:UIControlStateSelected]; + _choosePsdBtn.titleLabel.font = kFontSemibold(16); + [_choosePsdBtn setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + [_choosePsdBtn addTarget:self action:@selector(choosePwdAction) forControlEvents:UIControlEventTouchUpInside]; + _choosePsdBtn.selected = YES; + } + return _choosePsdBtn; +} + +- (XPLoginInputView *)accountView { + if (!_accountView) { + _accountView = [[XPLoginInputView alloc] init]; + _accountView.areaStackView.hidden = YES; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPwdViewController6")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _accountView.inputTextField.attributedPlaceholder = placeholder; + _accountView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + } + return _accountView; +} + +- (XPLoginInputView *)accountPwdView { + if (!_accountPwdView) { + _accountPwdView = [[XPLoginInputView alloc] init]; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPwdViewController3")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColorFromRGB(0xB3B3C3) range:NSMakeRange(0, placeholder.length)]; + _accountPwdView.inputTextField.attributedPlaceholder = placeholder; + _accountPwdView.inputTextField.keyboardType = UIKeyboardTypeAlphabet; + _accountPwdView.inputTextField.secureTextEntry = YES; + } + return _accountPwdView; +} +- (UIButton *)forgetBtn { + if (!_forgetBtn) { + _forgetBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_forgetBtn setTitle:YMLocalizedString(@"XPRoomRedPacketPwdView1") forState:UIControlStateNormal]; + [_forgetBtn setTitleColor:UIColorFromRGB(0xB3B3C3) forState:UIControlStateNormal]; + _forgetBtn.titleLabel.font = kFontRegular(12); + [_forgetBtn addTarget:self action:@selector(forgetBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _forgetBtn; +} +@end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h index 04ae51d..7c29921 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h @@ -1,9 +1,7 @@ -// -// YMLoginPwdViewController.h -// YUMI -// + + // Created by XY on 2023/2/14. -// + #import "MvpViewController.h" diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h.backup new file mode 100644 index 0000000..04ae51d --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.h.backup @@ -0,0 +1,16 @@ +// +// YMLoginPwdViewController.h +// YUMI +// +// Created by XY on 2023/2/14. +// + +#import "MvpViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPLoginPwdViewController : MvpViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m index 28da678..04db325 100644 --- a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m @@ -1,9 +1,7 @@ -// -// YMLoginPwdViewController.m -// YUMI -// + + // Created by XY on 2023/2/14. -// + #import "XPLoginPwdViewController.h" #import @@ -19,17 +17,17 @@ @interface XPLoginPwdViewController () -/// 密码登录 + @property (nonatomic, strong) UILabel *titleLabel; -/// 手机号输入框 + @property (nonatomic, strong) XPLoginInputView *phoneInputView; -/// 密码输入框 + @property (nonatomic, strong) XPLoginInputView *pwdInputView; -/// 忘记密码 + @property (nonatomic, strong) UIButton *forgetBtn; -/// 登录按钮 + @property (nonatomic, strong) UIButton *loginBtn; -/// 密码登录 + @property (nonatomic, strong) UIButton *phoneLoginBtn; @@ -189,5 +187,4 @@ } - @end diff --git a/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m.backup b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m.backup new file mode 100644 index 0000000..28da678 --- /dev/null +++ b/YuMi/Modules/YMLogin/View/NewLogin/XPLoginPwdViewController.m.backup @@ -0,0 +1,193 @@ +// +// YMLoginPwdViewController.m +// YUMI +// +// Created by XY on 2023/2/14. +// + +#import "XPLoginPwdViewController.h" +#import +#import "YUMIMacroUitls.h" +#import + +#import "XPLoginInputView.h" +#import "XPLoginPwdViewController.h" +#import "XPForgetPwdViewController.h" + +#import "LoginPasswordPresent.h" +#import "LoginPasswordProtocol.h" + +@interface XPLoginPwdViewController () + +/// 密码登录 +@property (nonatomic, strong) UILabel *titleLabel; +/// 手机号输入框 +@property (nonatomic, strong) XPLoginInputView *phoneInputView; +/// 密码输入框 +@property (nonatomic, strong) XPLoginInputView *pwdInputView; +/// 忘记密码 +@property (nonatomic, strong) UIButton *forgetBtn; +/// 登录按钮 +@property (nonatomic, strong) UIButton *loginBtn; +/// 密码登录 +@property (nonatomic, strong) UIButton *phoneLoginBtn; + + +@end + +@implementation XPLoginPwdViewController + +- (LoginPasswordPresent *)createPresenter { + return [[LoginPasswordPresent alloc] init]; +} + +- (void)viewDidLoad { + + [super viewDidLoad]; + [self createUI]; + [self racBind]; +} + +- (void)createUI { + [self.view addSubview:self.titleLabel]; + [self.view addSubview:self.phoneInputView]; + [self.view addSubview:self.pwdInputView]; + [self.view addSubview:self.loginBtn]; + [self.view addSubview:self.phoneLoginBtn]; + [self.view addSubview:self.forgetBtn]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(146.0/812.0*KScreenHeight); + }]; + [self.phoneInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(38); + make.trailing.mas_equalTo(-38); + make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(41); + make.height.mas_equalTo(66); + }]; + [self.pwdInputView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.phoneInputView); + make.trailing.mas_equalTo(self.phoneInputView); + make.top.mas_equalTo(self.phoneInputView.mas_bottom).offset(16); + make.height.mas_equalTo(self.phoneInputView); + }]; + [self.loginBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.pwdInputView.mas_bottom).offset(51); + make.centerX.mas_equalTo(self.view); + make.width.height.mas_equalTo(96); + }]; + [self.phoneLoginBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.loginBtn.mas_bottom).offset(24); + make.centerX.mas_equalTo(self.view); + }]; + [self.forgetBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.pwdInputView); + make.top.mas_equalTo(self.pwdInputView.mas_bottom).offset(10); + }]; + +} + +- (void)racBind { + RAC(self.loginBtn, enabled) = [[RACSignal combineLatest:@[self.phoneInputView.inputTextField.rac_textSignal, self.pwdInputView.inputTextField.rac_textSignal] reduce:^id _Nonnull(NSString *phone, NSString* password){ + return @((phone.length > 0) && password.length >= 6); + }] takeUntil:self.rac_willDeallocSignal]; +} + +- (void)loginBtnClicked { + NSString *phone = self.phoneInputView.inputTextField.text; + NSString *password = self.pwdInputView.inputTextField.text; + [self.presenter loginWithPhone:phone password:password]; +} + +- (void)phoneLoginBtnClicked { + [self.navigationController popViewControllerAnimated:YES]; +} + +- (void)forgetBtnClicked { + XPForgetPwdViewController *forgetVC = [[XPForgetPwdViewController alloc] init]; + [self.navigationController pushViewController:forgetVC animated:YES]; +} + +#pragma mark - LoginPasswordProtocol +- (void)phoneAndPasswordLoginSuccess { + [self showSuccessToast:YMLocalizedString(@"XPLoginPwdViewController0")]; + UIViewController *vc = self.presentingViewController; + while (vc.presentingViewController) { + vc = vc.presentingViewController; + } + [vc dismissViewControllerAnimated:YES completion:nil]; + [self.navigationController popToRootViewControllerAnimated:NO]; +} + +#pragma mark - 懒加载 + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = YMLocalizedString(@"XPLoginPwdViewController1"); + _titleLabel.font = [UIFont systemFontOfSize:24 weight:UIFontWeightMedium]; + _titleLabel.textColor = UIColor.whiteColor; + } + return _titleLabel; +} + +- (XPLoginInputView *)phoneInputView { + if (!_phoneInputView) { + _phoneInputView = [[XPLoginInputView alloc] init]; + _phoneInputView.areaStackView.hidden = YES; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPwdViewController2")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColor.whiteColor range:NSMakeRange(0, placeholder.length)]; + _phoneInputView.inputTextField.attributedPlaceholder = placeholder; + _phoneInputView.inputTextField.keyboardType = UIKeyboardTypeNumberPad; + } + return _phoneInputView; +} + +- (XPLoginInputView *)pwdInputView { + if (!_pwdInputView) { + _pwdInputView = [[XPLoginInputView alloc] init]; + NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPwdViewController3")]; + [placeholder addAttribute:NSForegroundColorAttributeName value:UIColor.whiteColor range:NSMakeRange(0, placeholder.length)]; + _pwdInputView.inputTextField.attributedPlaceholder = placeholder; + _pwdInputView.inputTextField.keyboardType = UIKeyboardTypeAlphabet; + _pwdInputView.inputTextField.secureTextEntry = YES; + } + return _pwdInputView; +} +- (UIButton *)forgetBtn { + if (!_forgetBtn) { + _forgetBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_forgetBtn setTitle:YMLocalizedString(@"XPRoomRedPacketPwdView1") forState:UIControlStateNormal]; + [_forgetBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + _forgetBtn.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightRegular]; + [_forgetBtn addTarget:self action:@selector(forgetBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _forgetBtn; +} +- (UIButton *)loginBtn { + if (!_loginBtn) { + _loginBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_loginBtn setImage:[UIImage imageNamed:@"login_next"] forState:UIControlStateNormal]; + [_loginBtn setImage:[UIImage imageNamed:@"login_next_disable"] forState:UIControlStateDisabled]; + [_loginBtn addTarget:self action:@selector(loginBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _loginBtn; +} + +- (UIButton *)phoneLoginBtn { + if (!_phoneLoginBtn) { + _phoneLoginBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:YMLocalizedString(@"XPLoginPwdViewController4")]; + [title addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(0, title.length)]; + [_phoneLoginBtn setAttributedTitle:title forState:UIControlStateNormal]; + [_phoneLoginBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + _phoneLoginBtn.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightRegular]; + [_phoneLoginBtn addTarget:self action:@selector(phoneLoginBtnClicked) forControlEvents:UIControlEventTouchUpInside]; + } + return _phoneLoginBtn; +} + + + +@end diff --git a/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m b/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m index c503cf2..c1139a1 100644 --- a/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m +++ b/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m @@ -1,20 +1,11 @@ -// -// MessageContentUnSupport.m -// xplan-ios -// + + // Created by 冯硕 on 2022/4/19. -// + #import "MessageContentUnSupportView.h" @implementation MessageContentUnSupportView -/* -// Only override drawRect: if you perform custom drawing. -// An empty implementation adversely affects performance during animation. -- (void)drawRect:(CGRect)rect { - // Drawing code -} -*/ @end diff --git a/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m.backup b/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m.backup new file mode 100644 index 0000000..c503cf2 --- /dev/null +++ b/YuMi/Modules/YMMessage/View/Session/Content/MessageContentUnSupport.m.backup @@ -0,0 +1,20 @@ +// +// MessageContentUnSupport.m +// xplan-ios +// +// Created by 冯硕 on 2022/4/19. +// + +#import "MessageContentUnSupportView.h" + +@implementation MessageContentUnSupportView + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + +@end diff --git a/YuMi/Modules/YMMine/Api/Api(GameOrder).h b/YuMi/Modules/YMMine/Api/Api(GameOrder).h index d6a84e9..90ac6f9 100644 --- a/YuMi/Modules/YMMine/Api/Api(GameOrder).h +++ b/YuMi/Modules/YMMine/Api/Api(GameOrder).h @@ -1,9 +1,7 @@ -// -// Api(GameOrder).h -// YuMi -// + + // Created by P on 2024/7/10. -// + #import diff --git a/YuMi/Modules/YMMine/Api/Api(GameOrder).h.backup b/YuMi/Modules/YMMine/Api/Api(GameOrder).h.backup new file mode 100644 index 0000000..d6a84e9 --- /dev/null +++ b/YuMi/Modules/YMMine/Api/Api(GameOrder).h.backup @@ -0,0 +1,16 @@ +// +// Api(GameOrder).h +// YuMi +// +// Created by P on 2024/7/10. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface Api_GameOrder_ : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMine/Api/Api(GameOrder).m b/YuMi/Modules/YMMine/Api/Api(GameOrder).m index 862d69e..4fbe6b6 100644 --- a/YuMi/Modules/YMMine/Api/Api(GameOrder).m +++ b/YuMi/Modules/YMMine/Api/Api(GameOrder).m @@ -1,9 +1,7 @@ -// -// Api(GameOrder).m -// YuMi -// + + // Created by P on 2024/7/10. -// + #import "Api(GameOrder).h" diff --git a/YuMi/Modules/YMMine/Api/Api(GameOrder).m.backup b/YuMi/Modules/YMMine/Api/Api(GameOrder).m.backup new file mode 100644 index 0000000..862d69e --- /dev/null +++ b/YuMi/Modules/YMMine/Api/Api(GameOrder).m.backup @@ -0,0 +1,12 @@ +// +// Api(GameOrder).m +// YuMi +// +// Created by P on 2024/7/10. +// + +#import "Api(GameOrder).h" + +@implementation Api_GameOrder_ + +@end diff --git a/YuMi/Modules/YMMine/Api/Api+Mine.h b/YuMi/Modules/YMMine/Api/Api+Mine.h index fd75750..bb913ba 100644 --- a/YuMi/Modules/YMMine/Api/Api+Mine.h +++ b/YuMi/Modules/YMMine/Api/Api+Mine.h @@ -1,9 +1,7 @@ -// -// Api+Mine.h -// YUMI -// + + // Created by YUMI on 2021/9/16. -// + #import "Api.h" @@ -12,59 +10,35 @@ NS_ASSUME_NONNULL_BEGIN @interface Api (Mine) -/// 获取个人中心功能列表 -/// @param completion 完成 -/// @param uid uid + + (void)requestPersonalFunctionItem:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; -/// 获取个人中心banner列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param type 类型 10 + + (void)requestMineBannerList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type; -/// 保存反馈的信息 -/// @param complection 完成 -/// @param feedbackDesc 反馈的内容 -/// @param contact 联系方式 -/// @param uid uid -/// @param ticket ticket + + (void)saveFeedBackWith:(HttpRequestHelperCompletion)complection feedbackDesc:(NSString *)feedbackDesc contact:(NSString *)contact uid:(NSString *)uid ticket:(NSString *)ticket; -/// 查询当前用户开启通知的状态 -/// @param complection 完成 -/// @param uid 用户的uid + + (void)requestUserInfoNotifyStatus:(HttpRequestHelperCompletion)complection uid:(NSString *)uid; -/// 更新系统通知 -/// @param complection 完成 -/// @param sysMsgNotify 状态 -/// @param uid 用户的uid + + (void)updateUserInfoSystemNotifyWith:(HttpRequestHelperCompletion)complection sysMsgNotify:(NSString *)sysMsgNotify uid:(NSString *)uid; -/// 更新个播开播通知 -/// @param completion 完成 -/// @param msgNotify 状态 -/// @param uid 用户的uid + + (void)updateAnchorBroadCastNotifyWith:(HttpRequestHelperCompletion)completion msgNotify:(NSString *)msgNotify uid:(NSString *)uid; -/// 设置支付密码 -/// @param complection 完成 -/// @param newPasswd 支付密码 -/// @param phone 手机号 -/// @param code 验证码 -/// @param uid uid -/// @param ticket ticket + + (void)setPayPassword:(HttpRequestHelperCompletion)complection newPasswd:(NSString *)newPasswd phone:(NSString *)phone @@ -72,81 +46,45 @@ NS_ASSUME_NONNULL_BEGIN uid:(NSString *)uid ticket:(NSString *)ticket; -/// 修改支付密码 -/// @param complection 完成 -/// @param newPasswd 新的支付密码 -/// @param oldPasswd 旧的支付密码 -/// @param uid uid -/// @param ticket ticket + + (void)modifPayPassword:(HttpRequestHelperCompletion)complection newPasswd:(NSString *)newPasswd oldPasswd:(NSString *)oldPasswd uid:(NSString *)uid ticket:(NSString *)ticket; -/// 设置登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 + + (void)setLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd; -/// 重置登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 -/// @param smsCode 验证码 + + (void)resetLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode; -/// 修改 登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 -/// @param pwd 旧密码 + + (void)modifyLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd pwd:(NSString *)pwd; -/// 开启关闭家长模式 -/// @param complection 完成 -/// @param password 密码 -/// @param status 状态 0 开启 1 关闭 -/// @param uid 用户的uid + + (void)openOrCloseParentModel:(HttpRequestHelperCompletion)complection password:(NSString *)password status:(NSNumber *)status uid:(NSString *)uid; -/// 上传用户图像到服务器 -/// @param complection 完成 -/// @param photoStr 相册 -/// @param uid 用户的uid -/// @param ticket ticket + (void)uploadUserAlbum:(HttpRequestHelperCompletion)complection photoStr:(NSString *)photoStr uid:(NSString *)uid ticket:(NSString *)ticket; -/// 删除用户图像从服务器 -/// @param complection 完成 -/// @param pid 相册 -/// @param uid 用户的uid -/// @param ticket ticket + + + (void)deleteImageFromServer:(HttpRequestHelperCompletion)complection pid:(NSString *)pid uid:(NSString *)uid ticket:(NSString *)ticket; -/// 请求充值列表 -/// @param complection 完成 -/// @param channelType channel + + (void)getRechargeList:(HttpRequestHelperCompletion)complection channelType:(NSString *)channelType; -/// 苹果下单 -/// @param complection 完成 -/// @param chargeProdId 充值id -/// @param uid 用户的uid -/// @param ticket ticket -/// @param deviceInfo uuid -/// @param clientIp ip地址 + + (void)requestIAPRecharge:(HttpRequestHelperCompletion)complection chargeProdId:(NSString *)chargeProdId uid:(NSString *)uid @@ -154,13 +92,7 @@ NS_ASSUME_NONNULL_BEGIN deviceInfo:(NSString *)deviceInfo clientIp:(NSString *)clientIp; -/// 验证凭据 -/// @param complection 完成 -/// @param chooseEnv @"true" -/// @param chargeRecordId 服务端生成的订单编号 -/// @param transcationId 内购的唯一标识符 -/// @param uid 用户uid -/// @param ticket ticket + + (void)checkReceipt:(HttpRequestHelperCompletion)complection chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId @@ -168,180 +100,111 @@ NS_ASSUME_NONNULL_BEGIN uid:(NSString *)uid ticket:(NSString *)ticket; -/// 退出当前账号 -/// @param complection 完成 -/// @param access_token token + + (void)logoutCurrentAccount:(HttpRequestHelperCompletion)complection access_token:(NSString *)access_token; -/// 查询两个人的关注状态 -/// @param complection 完成 -/// @param uid 自己的uid -/// @param isLikeUid 要查询的那个人的uid + + (void)attentionStatusCompletion:(HttpRequestHelperCompletion)complection uid:(NSString *)uid isLikeUid:(NSString *)isLikeUid; -/// 关注某人 -/// @param complection 完成 -/// @param uid 发起关注的人 -/// @param likedUid 被关注的人 -/// @param ticket ticket -/// @param type l类型默认1 + + (void)attentionCompletion:(HttpRequestHelperCompletion)complection uid:(NSString *)uid likedUid:(NSString *)likedUid ticket:(NSString *)ticket type:(NSString *)type; -/// 获取用户详情 -/// @param complection 完成 -/// @param uid 发起关注的人 -/// @param page page -/// @param pageSize pagesize + + (void)userDetailInfoCompletion:(HttpRequestHelperCompletion)complection uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize; -/// 获取粉丝列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param pageNo 当前页数 -/// @param pageSize 一页多少个 + + (void)getFansListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize; -/// 获取访客列表 -/// @param completion 完成 -/// @param pageNum 当前页数 -/// @param pageSize 一页多少个 + + (void)getVisitorListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize; -/// 获取关注列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param pageNo 当前页数 -/// @param pageSize 一页多少个 + + (void)getattentionListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize; -/// 上传访问用户的记录 -/// @param completion 完成 -/// @param uid 被访问的用户uid + + (void)uploadVisitUserCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; -/// 获取粉丝团列表 -/// @param completion 完成 -/// @param pageNum 当前页数 -/// @param pageSize 一页多少个 + + (void)getAnchorFansTeamListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize; -/// 获取用户的礼物墙 -/// @param comletion 完成 -/// @param uid 用户的uid -/// @param giftType 礼物类型 1:普通礼物;2:幸运礼物 + + (void)getUserGiftWall:(HttpRequestHelperCompletion)comletion uid:(NSString *)uid giftType:(NSString *)giftType; -/// 批量获取用户信息 -/// @param completion 完成 -/// @param uids 用户的uid + + (void)getUsersListInfo:(HttpRequestHelperCompletion)completion uids:(NSString *)uids; -/// 获取用户进房记录 -/// @param completion 完成 -/// @param uid 用户的uid + + (void)requestFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize; -/// 清除进房记录 -/// @param completion 完成 -/// @param uid 用户uid -/// @param roomUid 房间uid + + (void)requestCleanFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid roomUid:(NSString *)roomUid; -/// 快捷进房 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param mgId 游戏id + + (void)requestMineQuickMatchLittleGame:(HttpRequestHelperCompletion)completion uid:(NSString *)uid mgId:(NSString *)mgId; -/// 请求收藏房间列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param page 当前页数 -/// @param pageSize 一页多少个 -/// @param roomType 类型:4:个播房;其他:派对房;不传:所有房间 + + (void)requestMineCollectRoomList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize roomType:(NSString *)roomType; -/// 请求大家都在搜列表 -/// @param completion 完成 -/// @param uid uid + + (void)requestEveryoneSearch:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; -/// 获取好友派对列表 -/// @param completion 完成 + + (void)requestFansParty:(HttpRequestHelperCompletion)completion; -/// 请求主播评级 -/// @param completion 完成 + + (void)requestAnchorGradeInfo:(HttpRequestHelperCompletion)completion; -/// 請求公會列表 -/// @param completion 完成 + + (void)requestMineGuildList:(HttpRequestHelperCompletion)completion; -/// 請求房间列表 -/// @param completion 完成 + + + (void)requestMineRoomList:(HttpRequestHelperCompletion)completion; -///申请加入公会 + +(void)applyClanWith:(HttpRequestHelperCompletion)completion uid:(NSString *)uid clanId:(NSString *)clanId; +(void)getGoldDetailsData:(HttpRequestHelperCompletion)completion startTime:(NSString *)startTime endTime:(NSString *)endTime; -/// 设置支付密码 重置支付密码 -/// @param completion 完成 -/// @param newPasswd 支付密码 -/// @param phone 手机号 -/// @param uid uid -/// @param ticket ticket + (void)setPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd uid:(NSString *)uid ticket:(NSString *)ticket; -///收益记录 +(void)requestRecordIncome:(HttpRequestHelperCompletion)completion; -///得到兑换界面信息 + +(void)getExchangeDiamondInformation:(HttpRequestHelperCompletion)completion; +(void)confirmExchangeDiamond:(HttpRequestHelperCompletion)completion goldNum:(NSString *)goldNum diamondNum:(NSString *)diamondNum currency:(NSString *)currency; -///得到个人简介标签 + +(void)getTagList:(HttpRequestHelperCompletion)completion; -///保存个人简介标签 + +(void)saveTagList:(HttpRequestHelperCompletion)completion labels:(NSString *)labels; -//////获取地区列表 + +(void)getAreaList:(HttpRequestHelperCompletion)completion; -///保存地区列表 + +(void)saveAreaConfigWithArea:(HttpRequestHelperCompletion)completion id:(NSString *)id; -/// + +(void)requestQueryWithRoomType:(HttpRequestHelperCompletion)completion; -///屏蔽房间列表 -/// - Parameter completion: 完成 + + +(void)getBlackRoomList:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize; -/// 解除屏蔽 -/// - Parameters: -/// - completion: 完成 -/// - roomUid: 房间id -/// - type: 1=房间 + +(void)requestUnmaskingFromBlackRoomList:(HttpRequestHelperCompletion)completion objId:(NSString *)objId type:(NSString *)type ; -///得到腾讯存储信息 + + (void)getQCloudInfo:(HttpRequestHelperCompletion)completion; -//获取 cp 列表 + +(void)requestCPList:(HttpRequestHelperCompletion)completion page:(NSNumber *)page pageSize:(NSNumber *)pageSize; -//取消 cp 关系 + +(void)cancelCPList:(HttpRequestHelperCompletion)completion uid:(NSNumber *)uid loverUid:(NSNumber *)loverUid goldNum:(NSNumber *)goldNum; -/// 用户设置 CP 内容展示开关 -/// - Parameters: -/// - completion: completion description -/// - type: 1-cp头像是否展示,2-cp动画 -/// - isShow: 是否开启 +(void)updateCPSetting:(HttpRequestHelperCompletion)completion type:(NSNumber *)type isShow:(NSNumber *)isShow; +(void)requestBlockTime:(HttpRequestHelperCompletion)completion; diff --git a/YuMi/Modules/YMMine/Api/Api+Mine.h.backup b/YuMi/Modules/YMMine/Api/Api+Mine.h.backup new file mode 100644 index 0000000..fd75750 --- /dev/null +++ b/YuMi/Modules/YMMine/Api/Api+Mine.h.backup @@ -0,0 +1,366 @@ +// +// Api+Mine.h +// YUMI +// +// Created by YUMI on 2021/9/16. +// + +#import "Api.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface Api (Mine) + +/// 获取个人中心功能列表 +/// @param completion 完成 +/// @param uid uid ++ (void)requestPersonalFunctionItem:(HttpRequestHelperCompletion)completion + uid:(NSString *)uid; + +/// 获取个人中心banner列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param type 类型 10 ++ (void)requestMineBannerList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type; + +/// 保存反馈的信息 +/// @param complection 完成 +/// @param feedbackDesc 反馈的内容 +/// @param contact 联系方式 +/// @param uid uid +/// @param ticket ticket ++ (void)saveFeedBackWith:(HttpRequestHelperCompletion)complection + feedbackDesc:(NSString *)feedbackDesc + contact:(NSString *)contact + uid:(NSString *)uid + ticket:(NSString *)ticket; + +/// 查询当前用户开启通知的状态 +/// @param complection 完成 +/// @param uid 用户的uid ++ (void)requestUserInfoNotifyStatus:(HttpRequestHelperCompletion)complection + uid:(NSString *)uid; + +/// 更新系统通知 +/// @param complection 完成 +/// @param sysMsgNotify 状态 +/// @param uid 用户的uid ++ (void)updateUserInfoSystemNotifyWith:(HttpRequestHelperCompletion)complection + sysMsgNotify:(NSString *)sysMsgNotify + uid:(NSString *)uid; + +/// 更新个播开播通知 +/// @param completion 完成 +/// @param msgNotify 状态 +/// @param uid 用户的uid ++ (void)updateAnchorBroadCastNotifyWith:(HttpRequestHelperCompletion)completion + msgNotify:(NSString *)msgNotify + uid:(NSString *)uid; + +/// 设置支付密码 +/// @param complection 完成 +/// @param newPasswd 支付密码 +/// @param phone 手机号 +/// @param code 验证码 +/// @param uid uid +/// @param ticket ticket ++ (void)setPayPassword:(HttpRequestHelperCompletion)complection + newPasswd:(NSString *)newPasswd + phone:(NSString *)phone + code:(NSString *)code + uid:(NSString *)uid + ticket:(NSString *)ticket; + +/// 修改支付密码 +/// @param complection 完成 +/// @param newPasswd 新的支付密码 +/// @param oldPasswd 旧的支付密码 +/// @param uid uid +/// @param ticket ticket ++ (void)modifPayPassword:(HttpRequestHelperCompletion)complection + newPasswd:(NSString *)newPasswd + oldPasswd:(NSString *)oldPasswd + uid:(NSString *)uid + ticket:(NSString *)ticket; + +/// 设置登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 ++ (void)setLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd; + +/// 重置登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 +/// @param smsCode 验证码 ++ (void)resetLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode; + +/// 修改 登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 +/// @param pwd 旧密码 ++ (void)modifyLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd pwd:(NSString *)pwd; + +/// 开启关闭家长模式 +/// @param complection 完成 +/// @param password 密码 +/// @param status 状态 0 开启 1 关闭 +/// @param uid 用户的uid ++ (void)openOrCloseParentModel:(HttpRequestHelperCompletion)complection + password:(NSString *)password + status:(NSNumber *)status + uid:(NSString *)uid; + + +/// 上传用户图像到服务器 +/// @param complection 完成 +/// @param photoStr 相册 +/// @param uid 用户的uid +/// @param ticket ticket ++ (void)uploadUserAlbum:(HttpRequestHelperCompletion)complection + photoStr:(NSString *)photoStr + uid:(NSString *)uid + ticket:(NSString *)ticket; +/// 删除用户图像从服务器 +/// @param complection 完成 +/// @param pid 相册 +/// @param uid 用户的uid +/// @param ticket ticket ++ (void)deleteImageFromServer:(HttpRequestHelperCompletion)complection + pid:(NSString *)pid + uid:(NSString *)uid + ticket:(NSString *)ticket; + +/// 请求充值列表 +/// @param complection 完成 +/// @param channelType channel ++ (void)getRechargeList:(HttpRequestHelperCompletion)complection + channelType:(NSString *)channelType; + +/// 苹果下单 +/// @param complection 完成 +/// @param chargeProdId 充值id +/// @param uid 用户的uid +/// @param ticket ticket +/// @param deviceInfo uuid +/// @param clientIp ip地址 ++ (void)requestIAPRecharge:(HttpRequestHelperCompletion)complection + chargeProdId:(NSString *)chargeProdId + uid:(NSString *)uid + ticket:(NSString *)ticket + deviceInfo:(NSString *)deviceInfo + clientIp:(NSString *)clientIp; + +/// 验证凭据 +/// @param complection 完成 +/// @param chooseEnv @"true" +/// @param chargeRecordId 服务端生成的订单编号 +/// @param transcationId 内购的唯一标识符 +/// @param uid 用户uid +/// @param ticket ticket ++ (void)checkReceipt:(HttpRequestHelperCompletion)complection + chooseEnv:(NSString *)chooseEnv + chargeRecordId:(NSString *)chargeRecordId + transcationId:(NSString *)transcationId + uid:(NSString *)uid + ticket:(NSString *)ticket; + +/// 退出当前账号 +/// @param complection 完成 +/// @param access_token token ++ (void)logoutCurrentAccount:(HttpRequestHelperCompletion)complection + access_token:(NSString *)access_token; + +/// 查询两个人的关注状态 +/// @param complection 完成 +/// @param uid 自己的uid +/// @param isLikeUid 要查询的那个人的uid ++ (void)attentionStatusCompletion:(HttpRequestHelperCompletion)complection + uid:(NSString *)uid + isLikeUid:(NSString *)isLikeUid; + +/// 关注某人 +/// @param complection 完成 +/// @param uid 发起关注的人 +/// @param likedUid 被关注的人 +/// @param ticket ticket +/// @param type l类型默认1 ++ (void)attentionCompletion:(HttpRequestHelperCompletion)complection + uid:(NSString *)uid + likedUid:(NSString *)likedUid + ticket:(NSString *)ticket + type:(NSString *)type; + +/// 获取用户详情 +/// @param complection 完成 +/// @param uid 发起关注的人 +/// @param page page +/// @param pageSize pagesize ++ (void)userDetailInfoCompletion:(HttpRequestHelperCompletion)complection uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize; + +/// 获取粉丝列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param pageNo 当前页数 +/// @param pageSize 一页多少个 ++ (void)getFansListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize; + +/// 获取访客列表 +/// @param completion 完成 +/// @param pageNum 当前页数 +/// @param pageSize 一页多少个 ++ (void)getVisitorListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize; + +/// 获取关注列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param pageNo 当前页数 +/// @param pageSize 一页多少个 ++ (void)getattentionListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize; + +/// 上传访问用户的记录 +/// @param completion 完成 +/// @param uid 被访问的用户uid ++ (void)uploadVisitUserCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; + +/// 获取粉丝团列表 +/// @param completion 完成 +/// @param pageNum 当前页数 +/// @param pageSize 一页多少个 ++ (void)getAnchorFansTeamListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize; + +/// 获取用户的礼物墙 +/// @param comletion 完成 +/// @param uid 用户的uid +/// @param giftType 礼物类型 1:普通礼物;2:幸运礼物 ++ (void)getUserGiftWall:(HttpRequestHelperCompletion)comletion uid:(NSString *)uid giftType:(NSString *)giftType; + +/// 批量获取用户信息 +/// @param completion 完成 +/// @param uids 用户的uid ++ (void)getUsersListInfo:(HttpRequestHelperCompletion)completion uids:(NSString *)uids; + +/// 获取用户进房记录 +/// @param completion 完成 +/// @param uid 用户的uid ++ (void)requestFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize; + +/// 清除进房记录 +/// @param completion 完成 +/// @param uid 用户uid +/// @param roomUid 房间uid ++ (void)requestCleanFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid roomUid:(NSString *)roomUid; + +/// 快捷进房 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param mgId 游戏id ++ (void)requestMineQuickMatchLittleGame:(HttpRequestHelperCompletion)completion uid:(NSString *)uid mgId:(NSString *)mgId; + +/// 请求收藏房间列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param page 当前页数 +/// @param pageSize 一页多少个 +/// @param roomType 类型:4:个播房;其他:派对房;不传:所有房间 ++ (void)requestMineCollectRoomList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize roomType:(NSString *)roomType; + +/// 请求大家都在搜列表 +/// @param completion 完成 +/// @param uid uid ++ (void)requestEveryoneSearch:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; + +/// 获取好友派对列表 +/// @param completion 完成 ++ (void)requestFansParty:(HttpRequestHelperCompletion)completion; + +/// 请求主播评级 +/// @param completion 完成 ++ (void)requestAnchorGradeInfo:(HttpRequestHelperCompletion)completion; + +/// 請求公會列表 +/// @param completion 完成 ++ (void)requestMineGuildList:(HttpRequestHelperCompletion)completion; +/// 請求房间列表 +/// @param completion 完成 ++ (void)requestMineRoomList:(HttpRequestHelperCompletion)completion; +///申请加入公会 ++(void)applyClanWith:(HttpRequestHelperCompletion)completion uid:(NSString *)uid clanId:(NSString *)clanId; + ++(void)getGoldDetailsData:(HttpRequestHelperCompletion)completion startTime:(NSString *)startTime endTime:(NSString *)endTime; + +/// 设置支付密码 重置支付密码 +/// @param completion 完成 +/// @param newPasswd 支付密码 +/// @param phone 手机号 + +/// @param uid uid +/// @param ticket ticket ++ (void)setPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd uid:(NSString *)uid ticket:(NSString *)ticket; + + +///收益记录 ++(void)requestRecordIncome:(HttpRequestHelperCompletion)completion; +///得到兑换界面信息 ++(void)getExchangeDiamondInformation:(HttpRequestHelperCompletion)completion; + ++(void)confirmExchangeDiamond:(HttpRequestHelperCompletion)completion goldNum:(NSString *)goldNum diamondNum:(NSString *)diamondNum currency:(NSString *)currency; +///得到个人简介标签 ++(void)getTagList:(HttpRequestHelperCompletion)completion; +///保存个人简介标签 ++(void)saveTagList:(HttpRequestHelperCompletion)completion labels:(NSString *)labels; +//////获取地区列表 ++(void)getAreaList:(HttpRequestHelperCompletion)completion; +///保存地区列表 ++(void)saveAreaConfigWithArea:(HttpRequestHelperCompletion)completion id:(NSString *)id; +/// ++(void)requestQueryWithRoomType:(HttpRequestHelperCompletion)completion; +///屏蔽房间列表 +/// - Parameter completion: 完成 ++(void)getBlackRoomList:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize; + +/// 解除屏蔽 +/// - Parameters: +/// - completion: 完成 +/// - roomUid: 房间id +/// - type: 1=房间 ++(void)requestUnmaskingFromBlackRoomList:(HttpRequestHelperCompletion)completion objId:(NSString *)objId type:(NSString *)type ; +///得到腾讯存储信息 ++ (void)getQCloudInfo:(HttpRequestHelperCompletion)completion; + +//获取 cp 列表 ++(void)requestCPList:(HttpRequestHelperCompletion)completion page:(NSNumber *)page pageSize:(NSNumber *)pageSize; +//取消 cp 关系 ++(void)cancelCPList:(HttpRequestHelperCompletion)completion uid:(NSNumber *)uid loverUid:(NSNumber *)loverUid goldNum:(NSNumber *)goldNum; + + +/// 用户设置 CP 内容展示开关 +/// - Parameters: +/// - completion: completion description +/// - type: 1-cp头像是否展示,2-cp动画 +/// - isShow: 是否开启 ++(void)updateCPSetting:(HttpRequestHelperCompletion)completion type:(NSNumber *)type isShow:(NSNumber *)isShow; + ++(void)requestBlockTime:(HttpRequestHelperCompletion)completion; + ++(void)blockUser:(HttpRequestHelperCompletion)completion uid:(NSNumber *)uid hours:(NSNumber *)hours blockReason:(NSString *)blockReason; + ++ (void)userDetailMine:(HttpRequestHelperCompletion)completion; + ++ (void)userV2UploadAvatar:(HttpRequestHelperCompletion)completion avatarUrl:(NSString *)avatarUrl needPay:(NSNumber *)needPay; + ++ (void)fansFriendList:(HttpRequestHelperCompletion)completion pageNo:(NSNumber *)pageNo pageSize:(NSNumber *)pageSize; + ++ (void)userCpNameChange:(HttpRequestHelperCompletion)completion uid:(NSInteger)uid loverUid:(NSInteger)loverUid relationNameType:(NSInteger)relationNameType; + ++ (void)userCpNameChangeAudit:(HttpRequestHelperCompletion)completion recordId:(NSInteger)recordId status:(NSInteger)status; + ++ (void)userCpNameTypeTopList:(HttpRequestHelperCompletion)completion uid:(NSInteger)uid; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMine/Api/Api+Mine.m b/YuMi/Modules/YMMine/Api/Api+Mine.m index eb7d2e1..0c791a7 100644 --- a/YuMi/Modules/YMMine/Api/Api+Mine.m +++ b/YuMi/Modules/YMMine/Api/Api+Mine.m @@ -1,295 +1,185 @@ -// -// Api+Mine.m -// YUMI -// + + // Created by YUMI on 2021/9/16. -// + #import "Api+Mine.h" #import @implementation Api (Mine) -/// 获取个人中心功能列表 -/// @param completion 完成 -/// @param uid uid + + (void)requestPersonalFunctionItem:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"cGVyc29uYWwvY2VudGVyL2xpc3Q="];///personal/center/list + NSString * fang = [NSString stringFromBase64String:@"cGVyc29uYWwvY2VudGVyL2xpc3Q="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; } -/// 获取个人中心banner列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param type 类型 10 + + (void)requestMineBannerList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type { - NSString * fang = [NSString stringFromBase64String:@"aG9tZS9iYW5uZXI="];///home/banner + NSString * fang = [NSString stringFromBase64String:@"aG9tZS9iYW5uZXI="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, type, nil]; } -/// 保存反馈的信息 -/// @param completion 完成 -/// @param feedbackDesc 反馈的内容 -/// @param contact 联系方式 -/// @param uid uid -/// @param ticket ticket + + (void)saveFeedBackWith:(HttpRequestHelperCompletion)completion feedbackDesc:(NSString *)feedbackDesc contact:(NSString *)contact uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"ZmVlZGJhY2s="];///feedback + NSString * fang = [NSString stringFromBase64String:@"ZmVlZGJhY2s="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, feedbackDesc, contact, uid, ticket, nil]; } -/// 查询当前用户开启通知的状态 -/// @param completion 完成 -/// @param uid 用户的uid + (void)requestUserInfoNotifyStatus:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9tc2dOb3RpZnk="];///user/msgNotify + NSString * fang = [NSString stringFromBase64String:@"dXNlci9tc2dOb3RpZnk="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; } -/// 更新系统通知 -/// @param completion 完成 -/// @param sysMsgNotify 状态 -/// @param uid 用户的uid + (void)updateUserInfoSystemNotifyWith:(HttpRequestHelperCompletion)completion sysMsgNotify:(NSString *)sysMsgNotify uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9zeXNNc2dOb3RpZnk="];///user/sysMsgNotify + NSString * fang = [NSString stringFromBase64String:@"dXNlci9zeXNNc2dOb3RpZnk="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, sysMsgNotify,uid, nil]; } -/// 更新个播开播通知 -/// @param completion 完成 -/// @param msgNotify 状态 -/// @param uid 用户的uid + + (void)updateAnchorBroadCastNotifyWith:(HttpRequestHelperCompletion)completion msgNotify:(NSString *)msgNotify uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9zaW5nbGVCcm9hZGNhc3RNc2dOb3RpZnk="];///user/singleBroadcastMsgNotify + NSString * fang = [NSString stringFromBase64String:@"dXNlci9zaW5nbGVCcm9hZGNhc3RNc2dOb3RpZnk="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, msgNotify,uid, nil]; } -/// 设置支付密码 重置支付密码 -/// @param completion 完成 -/// @param newPasswd 支付密码 -/// @param phone 手机号 -/// @param code 验证码 -/// @param uid uid -/// @param ticket ticket + + (void)setPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd phone:(NSString *)phone code:(NSString *)code uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL3Jlc2V0"];///user/paymentPasswd/reset + NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL3Jlc2V0"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, newPasswd, phone, code,uid,ticket, nil]; } -/// 修改支付密码 -/// @param completion 完成 -/// @param newPasswd 新的支付密码 -/// @param oldPasswd 旧的支付密码 -/// @param uid uid -/// @param ticket ticket + (void)modifPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd oldPasswd:(NSString *)oldPasswd uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL21vZGlmeQ=="];///user/paymentPasswd/modify + NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL21vZGlmeQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, newPasswd,oldPasswd,uid,ticket, nil]; } -/// 设置登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 + + (void)setLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd { - NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9zZXQ="];///acc/pwd/set + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9zZXQ="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, phone, newPwd, nil]; } -/// 重置登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 -/// @param smsCode 验证码 + + (void)resetLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode { - NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9yZXNldA=="];///acc/pwd/reset + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9yZXNldA=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, phone, newPwd,smsCode, nil]; } -/// 修改 登录密码 -/// @param completion 完成 -/// @param phone 手机号 -/// @param newPwd 新的密码 -/// @param pwd 旧密码 + + (void)modifyLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd pwd:(NSString *)pwd { - NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9tb2RpZnk="];///acc/pwd/modify + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9tb2RpZnk="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__, phone, newPwd, pwd, nil]; } -/// 开启关闭家长模式 -/// @param completion 完成 -/// @param password 密码 -/// @param status 状态 0 开启 1 关闭 -/// @param uid 用户的uid + + (void)openOrCloseParentModel:(HttpRequestHelperCompletion)completion password:(NSString *)password status:(NSNumber *)status uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9vcGVuT3JDbG9zZQ=="];///user/openOrClose + NSString * fang = [NSString stringFromBase64String:@"dXNlci9vcGVuT3JDbG9zZQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, password,status,uid, nil]; } -///得到腾讯存储信息 + (void)getQCloudInfo:(HttpRequestHelperCompletion)completion{ [self makeRequest:@"tencent/cos/getToken" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } -/// 上传用户图像到服务器 -/// @param completion 完成 -/// @param photoStr 相册 -/// @param uid 用户的uid -/// @param ticket ticket + + (void)uploadUserAlbum:(HttpRequestHelperCompletion)completion photoStr:(NSString *)photoStr uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"cGhvdG8vdjIvdXBsb2Fk"];///photo/v2/upload + NSString * fang = [NSString stringFromBase64String:@"cGhvdG8vdjIvdXBsb2Fk"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,photoStr, uid, ticket, nil]; } -/// 删除用户图像从服务器 -/// @param completion 完成 -/// @param pid 相册 -/// @param uid 用户的uid -/// @param ticket ticket + + (void)deleteImageFromServer:(HttpRequestHelperCompletion)completion pid:(NSString *)pid uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"cGhvdG8vZGVsUGhvdG8="];///photo/delPhoto + NSString * fang = [NSString stringFromBase64String:@"cGhvdG8vZGVsUGhvdG8="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,pid, uid, ticket, nil]; } -/// 请求充值列表 -/// @param completion 完成 -/// @param channelType channel + (void)getRechargeList:(HttpRequestHelperCompletion)completion channelType:(NSString *)channelType { - NSString * fang = [NSString stringFromBase64String:@"Y2hhcmdlcHJvZC9saXN0"];///chargeprod/list + NSString * fang = [NSString stringFromBase64String:@"Y2hhcmdlcHJvZC9saXN0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__,channelType, nil]; } -/// 苹果下单 -/// @param completion 完成 -/// @param chargeProdId 充值id -/// @param uid 用户的uid -/// @param ticket ticket -/// @param deviceInfo uuid -/// @param clientIp ip地址 + + (void)requestIAPRecharge:(HttpRequestHelperCompletion)completion chargeProdId:(NSString *)chargeProdId uid:(NSString *)uid ticket:(NSString *)ticket deviceInfo:(NSString *)deviceInfo clientIp:(NSString *)clientIp { [self makeRequest:@"storeKitV2/placeOrder" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,chargeProdId, uid, ticket, deviceInfo, clientIp, nil]; } -/// 验证凭据 -/// @param completion 完成 -/// @param chooseEnv @"true" -/// @param chargeRecordId 服务端生成的订单编号 -/// @param transcationId 内购的唯一标识符 “transcationId” 后端的参数是拼错的!不要调整! -/// @param uid 用户uid -/// @param ticket ticket + (void)checkReceipt:(HttpRequestHelperCompletion)completion chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket { [self makeRequest:@"storeKitV2/verifyOrder" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, chooseEnv, chargeRecordId, transcationId, uid, ticket, nil]; } -/// 退出当前账号 -/// @param completion 完成 -/// @param access_token token + (void)logoutCurrentAccount:(HttpRequestHelperCompletion)completion access_token:(NSString *)access_token { - NSString * fang = [NSString stringFromBase64String:@"YWNjL2xvZ291dA=="];///acc/logout + NSString * fang = [NSString stringFromBase64String:@"YWNjL2xvZ291dA=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, access_token, nil]; } -/// 查询两个人的关注状态 -/// @param completion 完成 -/// @param uid 自己的uid -/// @param isLikeUid 要查询的那个人的uid + + (void)attentionStatusCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid isLikeUid:(NSString *)isLikeUid { - NSString * fang = [NSString stringFromBase64String:@"ZmFucy9pc2xpa2U="];///fans/islike + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9pc2xpa2U="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, uid, isLikeUid, nil]; } -/// 关注某人 -/// @param completion 完成 -/// @param uid 发起关注的人 -/// @param likedUid 被关注的人 -/// @param ticket ticket -/// @param type 1 关注 2取消关注 + + (void)attentionCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid likedUid:(NSString *)likedUid ticket:(NSString *)ticket type:(NSString *)type { - NSString * fang = [NSString stringFromBase64String:@"ZmFucy9saWtl"];///fans/like + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9saWtl"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, likedUid, ticket, type, nil]; } -/// 获取用户详情 -/// @param completion 完成 -/// @param uid 发起关注的人 -/// @param page page -/// @param pageSize pagesize + + (void)userDetailInfoCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9kZXRhaWwvZ2V0"];///user/detail/get + NSString * fang = [NSString stringFromBase64String:@"dXNlci9kZXRhaWwvZ2V0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, page, pageSize, nil]; } -/// 获取粉丝列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param pageNo 当前页数 -/// @param pageSize 一页多少个 + + (void)getFansListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize { - NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zbGlzdA=="];///@"fans/fanslist" + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zbGlzdA=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, pageNo, pageSize, nil]; } -/// 获取关注列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param pageNo 当前页数 -/// @param pageSize 一页多少个 + + (void)getattentionListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize { - NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mb2xsb3dpbmc="];///fans/following + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mb2xsb3dpbmc="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, pageNo, pageSize, nil]; } -/// 获取访客列表 -/// @param completion 完成 -/// @param pageNum 当前页数 -/// @param pageSize 一页多少个 + + (void)getVisitorListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize { - NSString * fang = [NSString stringFromBase64String:@"dXNlcnZpc2l0cmVjb3JkL3Zpc2l0VXNlckxpc3Q="];///uservisitrecord/visitUserList + NSString * fang = [NSString stringFromBase64String:@"dXNlcnZpc2l0cmVjb3JkL3Zpc2l0VXNlckxpc3Q="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, pageNum, pageSize, nil]; } -/// 上传访问用户的记录 -/// @param completion 完成 -/// @param uid 被访问的用户uid + + (void)uploadVisitUserCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9kZXRhaWwvdmlzaXRVc2VyRGV0YWls"];///user/detail/visitUserDetail + NSString * fang = [NSString stringFromBase64String:@"dXNlci9kZXRhaWwvdmlzaXRVc2VyRGV0YWls"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; } -/// 获取粉丝团列表 -/// @param completion 完成 -/// @param pageNum 当前页数 -/// @param pageSize 一页多少个 + + (void)getAnchorFansTeamListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize { - NSString * fang = [NSString stringFromBase64String:@"YW5jaG9yRmFuc1RlYW0vZ2V0Sm9pbkZhbnNUZWFtTGlzdA=="];///anchorFansTeam/getJoinFansTeamList + NSString * fang = [NSString stringFromBase64String:@"YW5jaG9yRmFuc1RlYW0vZ2V0Sm9pbkZhbnNUZWFtTGlzdA=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, pageNum, pageSize, nil]; } -/// 获取用户的礼物墙 -/// @param comletion 完成 -/// @param uid 用户的uid -/// @param giftType 类型2 + + (void)getUserGiftWall:(HttpRequestHelperCompletion)comletion uid:(NSString *)uid giftType:(NSString *)giftType { - NSString * fang = [NSString stringFromBase64String:@"Z2lmdHdhbGwvZ2V0QnlHaWZ0VHlwZQ=="];///giftwall/getByGiftType + NSString * fang = [NSString stringFromBase64String:@"Z2lmdHdhbGwvZ2V0QnlHaWZ0VHlwZQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:comletion, __FUNCTION__, uid, giftType, nil]; } -/// 批量获取用户信息 -/// @param completion 完成 -/// @param uids 用户的uid + + (void)getUsersListInfo:(HttpRequestHelperCompletion)completion uids:(NSString *)uids { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9saXN0"];///user/list + NSString * fang = [NSString stringFromBase64String:@"dXNlci9saXN0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uids, nil]; } @@ -298,126 +188,104 @@ __FUNCTION__, pageNo, pageSize, nil]; } -/// 获取用户进房记录 -/// @param completion 完成 -/// @param uid 用户的uid + + (void)requestFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize { - NSString * fang = [NSString stringFromBase64String:@"dXNlcnJvb20vZ2V0SW5Sb29tUmVjb3Jk"];///userroom/getInRoomRecord + NSString * fang = [NSString stringFromBase64String:@"dXNlcnJvb20vZ2V0SW5Sb29tUmVjb3Jk"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, page, pageSize, nil]; } -/// 清除进房记录 -/// @param completion 完成 -/// @param uid 用户uid -/// @param roomUid 房间uid + + (void)requestCleanFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid roomUid:(NSString *)roomUid { - NSString * fang = [NSString stringFromBase64String:@"dXNlcnJvb20vZGVsZXRlSW5Sb29tUmVjb3Jk"];///userroom/deleteInRoomRecord + NSString * fang = [NSString stringFromBase64String:@"dXNlcnJvb20vZGVsZXRlSW5Sb29tUmVjb3Jk"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, roomUid, nil]; } -/// 快捷进房 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param mgId 游戏id + + (void)requestMineQuickMatchLittleGame:(HttpRequestHelperCompletion)completion uid:(NSString *)uid mgId:(NSString *)mgId { - NSString * fang = [NSString stringFromBase64String:@"aG9tZS9mYXN0UGlja1Yy"];///home/fastPickV2 + NSString * fang = [NSString stringFromBase64String:@"aG9tZS9mYXN0UGlja1Yy"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, mgId, nil]; } -/// 请求收藏房间列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param page 当前页数 -/// @param pageSize 一页多少个 -/// @param roomType 类型:4:个播房;其他:派对房;不传:所有房间 + + (void)requestMineCollectRoomList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize roomType:(NSString *)roomType { - NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zUm9vbUxpc3Q="];///fans/fansRoomList + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zUm9vbUxpc3Q="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__,uid , page, pageSize, roomType, nil]; } -/// 请求大家都在搜列表 -/// @param completion 完成 -/// @param uid uid + + (void)requestEveryoneSearch:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"ZXZlcnkvb25lL3NlYXJjaC9nZXRMaXN0"];///every/one/search/getList + NSString * fang = [NSString stringFromBase64String:@"ZXZlcnkvb25lL3NlYXJjaC9nZXRMaXN0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; } -/// 获取好友派对列表 -/// @param completion 完成 + + (void)requestFansParty:(HttpRequestHelperCompletion)completion { - NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zUGFydExpc3Q="];///fans/fansPartList + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zUGFydExpc3Q="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } -/// 请求主播评级 -/// @param completion 完成 + + + (void)requestAnchorGradeInfo:(HttpRequestHelperCompletion)completion { - NSString * fang = [NSString stringFromBase64String:@"YW5jaG9yR3JhZGUvZ2V0"];///anchorGrade/get + NSString * fang = [NSString stringFromBase64String:@"YW5jaG9yR3JhZGUvZ2V0"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, nil]; } + (void)requestMineGuildList:(HttpRequestHelperCompletion)completion { - NSString * fang = [NSString stringFromBase64String:@"Y2xhbi9saXN0"];///clan/list + NSString * fang = [NSString stringFromBase64String:@"Y2xhbi9saXN0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } + (void)requestMineRoomList:(HttpRequestHelperCompletion)completion { - NSString * fang = [NSString stringFromBase64String:@"aGFsbC9saXN0"];///hall/list + NSString * fang = [NSString stringFromBase64String:@"aGFsbC9saXN0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } +(void)applyClanWith:(HttpRequestHelperCompletion)completion uid:(NSString *)uid clanId:(NSString *)clanId { - NSString * fang = [NSString stringFromBase64String:@"Y2xhbi9hcHBseQ=="];///clan/apply + NSString * fang = [NSString stringFromBase64String:@"Y2xhbi9hcHBseQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,uid, clanId, nil]; } +(void)getGoldDetailsData:(HttpRequestHelperCompletion)completion startTime:(NSString *)startTime endTime:(NSString *)endTime{ - NSString * fang = [NSString stringFromBase64String:@"Y2xhbkdvbGRGbG93L2NsYW5Ub3RhbExpc3Q="];///clanGoldFlow/clanTotalList + NSString * fang = [NSString stringFromBase64String:@"Y2xhbkdvbGRGbG93L2NsYW5Ub3RhbExpc3Q="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__,startTime,endTime, nil]; } -/// 设置支付密码 重置支付密码 -/// @param completion 完成 -/// @param newPasswd 支付密码 -/// @param phone 手机号 -/// @param uid uid -/// @param ticket ticket + (void)setPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL3Jlc2V0"];///user/paymentPasswd/reset + NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL3Jlc2V0"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, newPasswd,uid,ticket, nil]; } +(void)requestQueryWithRoomType:(HttpRequestHelperCompletion)completion{ - NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnlXaXRoUm9vbVR5cGU="];///purse/queryWithRoomType + NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnlXaXRoUm9vbVR5cGU="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } +(void)requestRecordIncome:(HttpRequestHelperCompletion)completion{ - NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnk="];///purse/query + NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnk="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } +(void)getExchangeDiamondInformation:(HttpRequestHelperCompletion)completion{ - NSString * fang = [NSString stringFromBase64String:@"Z29sZEV4Y2hhbmdlRGlhbW9uZC9nZXRDb25maWc="];///goldExchangeDiamond/getConfig + NSString * fang = [NSString stringFromBase64String:@"Z29sZEV4Y2hhbmdlRGlhbW9uZC9nZXRDb25maWc="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } +(void)confirmExchangeDiamond:(HttpRequestHelperCompletion)completion goldNum:(NSString *)goldNum diamondNum:(NSString *)diamondNum currency:(NSString *)currency{ - NSString * fang = [NSString stringFromBase64String:@"Z29sZEV4Y2hhbmdlRGlhbW9uZC9leGNoYW5nZQ=="];///goldExchangeDiamond/exchange + NSString * fang = [NSString stringFromBase64String:@"Z29sZEV4Y2hhbmdlRGlhbW9uZC9leGNoYW5nZQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,goldNum,diamondNum,currency, nil]; } +(void)getTagList:(HttpRequestHelperCompletion)completion{ [self makeRequest:@"label/edit" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, nil]; } -///保存个人简介标签 + +(void)saveTagList:(HttpRequestHelperCompletion)completion labels:(NSString *)labels{ [self makeRequest:@"label/save" method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,labels, nil]; } -//////获取地区列表 + +(void)getAreaList:(HttpRequestHelperCompletion)completion{ [self makeRequest:@"regionInfo/list" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, nil]; } -///保存地区列表 + +(void)saveAreaConfigWithArea:(HttpRequestHelperCompletion)completion id:(NSString *)id{ [self makeRequest:@"regionInfo/save" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, id, nil]; } @@ -425,17 +293,13 @@ +(void)getBlackRoomList:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize{ [self makeRequest:@"user/black/pageRoom" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, pageNum,pageSize,nil]; } -/// 解除屏蔽 -/// - Parameters: -/// - completion: 完成 -/// - roomUid: 房间id -/// - type: 1=房间 + + +(void)requestUnmaskingFromBlackRoomList:(HttpRequestHelperCompletion)completion objId:(NSString *)objId type:(NSString *)type { [self makeRequest:@"user/black/delete" method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,objId,type, nil]; } -//获取 cp 列表 +(void)requestCPList:(HttpRequestHelperCompletion)completion page:(NSNumber *)page pageSize:(NSNumber *)pageSize{ [self makeRequest:@"user/cp/list" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, nil]; } @@ -480,5 +344,4 @@ } - @end diff --git a/YuMi/Modules/YMMine/Api/Api+Mine.m.backup b/YuMi/Modules/YMMine/Api/Api+Mine.m.backup new file mode 100644 index 0000000..eb7d2e1 --- /dev/null +++ b/YuMi/Modules/YMMine/Api/Api+Mine.m.backup @@ -0,0 +1,484 @@ +// +// Api+Mine.m +// YUMI +// +// Created by YUMI on 2021/9/16. +// + +#import "Api+Mine.h" +#import +@implementation Api (Mine) + +/// 获取个人中心功能列表 +/// @param completion 完成 +/// @param uid uid ++ (void)requestPersonalFunctionItem:(HttpRequestHelperCompletion)completion + uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"cGVyc29uYWwvY2VudGVyL2xpc3Q="];///personal/center/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; +} + +/// 获取个人中心banner列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param type 类型 10 ++ (void)requestMineBannerList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type { + NSString * fang = [NSString stringFromBase64String:@"aG9tZS9iYW5uZXI="];///home/banner + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, type, nil]; +} + +/// 保存反馈的信息 +/// @param completion 完成 +/// @param feedbackDesc 反馈的内容 +/// @param contact 联系方式 +/// @param uid uid +/// @param ticket ticket ++ (void)saveFeedBackWith:(HttpRequestHelperCompletion)completion + feedbackDesc:(NSString *)feedbackDesc + contact:(NSString *)contact + uid:(NSString *)uid + ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"ZmVlZGJhY2s="];///feedback + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, feedbackDesc, contact, uid, ticket, nil]; +} + + +/// 查询当前用户开启通知的状态 +/// @param completion 完成 +/// @param uid 用户的uid ++ (void)requestUserInfoNotifyStatus:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9tc2dOb3RpZnk="];///user/msgNotify + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; +} + + +/// 更新系统通知 +/// @param completion 完成 +/// @param sysMsgNotify 状态 +/// @param uid 用户的uid ++ (void)updateUserInfoSystemNotifyWith:(HttpRequestHelperCompletion)completion sysMsgNotify:(NSString *)sysMsgNotify uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9zeXNNc2dOb3RpZnk="];///user/sysMsgNotify + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, sysMsgNotify,uid, nil]; +} + +/// 更新个播开播通知 +/// @param completion 完成 +/// @param msgNotify 状态 +/// @param uid 用户的uid ++ (void)updateAnchorBroadCastNotifyWith:(HttpRequestHelperCompletion)completion msgNotify:(NSString *)msgNotify uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9zaW5nbGVCcm9hZGNhc3RNc2dOb3RpZnk="];///user/singleBroadcastMsgNotify + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, msgNotify,uid, nil]; +} + +/// 设置支付密码 重置支付密码 +/// @param completion 完成 +/// @param newPasswd 支付密码 +/// @param phone 手机号 +/// @param code 验证码 +/// @param uid uid +/// @param ticket ticket ++ (void)setPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd phone:(NSString *)phone code:(NSString *)code uid:(NSString *)uid ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL3Jlc2V0"];///user/paymentPasswd/reset + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, newPasswd, phone, code,uid,ticket, nil]; +} + + +/// 修改支付密码 +/// @param completion 完成 +/// @param newPasswd 新的支付密码 +/// @param oldPasswd 旧的支付密码 +/// @param uid uid +/// @param ticket ticket ++ (void)modifPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd oldPasswd:(NSString *)oldPasswd uid:(NSString *)uid ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL21vZGlmeQ=="];///user/paymentPasswd/modify + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, newPasswd,oldPasswd,uid,ticket, nil]; +} + +/// 设置登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 ++ (void)setLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd { + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9zZXQ="];///acc/pwd/set + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, phone, newPwd, nil]; +} + +/// 重置登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 +/// @param smsCode 验证码 ++ (void)resetLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd smsCode:(NSString *)smsCode { + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9yZXNldA=="];///acc/pwd/reset + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, phone, newPwd,smsCode, nil]; +} + +/// 修改 登录密码 +/// @param completion 完成 +/// @param phone 手机号 +/// @param newPwd 新的密码 +/// @param pwd 旧密码 ++ (void)modifyLoingPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone newPwd:(NSString *)newPwd pwd:(NSString *)pwd { + NSString * fang = [NSString stringFromBase64String:@"YWNjL3B3ZC9tb2RpZnk="];///acc/pwd/modify + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__, phone, newPwd, pwd, nil]; +} + +/// 开启关闭家长模式 +/// @param completion 完成 +/// @param password 密码 +/// @param status 状态 0 开启 1 关闭 +/// @param uid 用户的uid ++ (void)openOrCloseParentModel:(HttpRequestHelperCompletion)completion password:(NSString *)password status:(NSNumber *)status uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9vcGVuT3JDbG9zZQ=="];///user/openOrClose + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, password,status,uid, nil]; +} + + +///得到腾讯存储信息 ++ (void)getQCloudInfo:(HttpRequestHelperCompletion)completion{ + [self makeRequest:@"tencent/cos/getToken" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + +/// 上传用户图像到服务器 +/// @param completion 完成 +/// @param photoStr 相册 +/// @param uid 用户的uid +/// @param ticket ticket ++ (void)uploadUserAlbum:(HttpRequestHelperCompletion)completion photoStr:(NSString *)photoStr uid:(NSString *)uid ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"cGhvdG8vdjIvdXBsb2Fk"];///photo/v2/upload + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,photoStr, uid, ticket, nil]; +} + +/// 删除用户图像从服务器 +/// @param completion 完成 +/// @param pid 相册 +/// @param uid 用户的uid +/// @param ticket ticket ++ (void)deleteImageFromServer:(HttpRequestHelperCompletion)completion pid:(NSString *)pid uid:(NSString *)uid ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"cGhvdG8vZGVsUGhvdG8="];///photo/delPhoto + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,pid, uid, ticket, nil]; +} + + +/// 请求充值列表 +/// @param completion 完成 +/// @param channelType channel ++ (void)getRechargeList:(HttpRequestHelperCompletion)completion channelType:(NSString *)channelType { + NSString * fang = [NSString stringFromBase64String:@"Y2hhcmdlcHJvZC9saXN0"];///chargeprod/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__,channelType, nil]; +} + +/// 苹果下单 +/// @param completion 完成 +/// @param chargeProdId 充值id +/// @param uid 用户的uid +/// @param ticket ticket +/// @param deviceInfo uuid +/// @param clientIp ip地址 ++ (void)requestIAPRecharge:(HttpRequestHelperCompletion)completion chargeProdId:(NSString *)chargeProdId uid:(NSString *)uid ticket:(NSString *)ticket deviceInfo:(NSString *)deviceInfo clientIp:(NSString *)clientIp { + [self makeRequest:@"storeKitV2/placeOrder" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,chargeProdId, uid, ticket, deviceInfo, clientIp, nil]; +} + + +/// 验证凭据 +/// @param completion 完成 +/// @param chooseEnv @"true" +/// @param chargeRecordId 服务端生成的订单编号 +/// @param transcationId 内购的唯一标识符 “transcationId” 后端的参数是拼错的!不要调整! +/// @param uid 用户uid +/// @param ticket ticket ++ (void)checkReceipt:(HttpRequestHelperCompletion)completion chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket { + [self makeRequest:@"storeKitV2/verifyOrder" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, chooseEnv, chargeRecordId, transcationId, uid, ticket, nil]; +} + + +/// 退出当前账号 +/// @param completion 完成 +/// @param access_token token ++ (void)logoutCurrentAccount:(HttpRequestHelperCompletion)completion access_token:(NSString *)access_token { + NSString * fang = [NSString stringFromBase64String:@"YWNjL2xvZ291dA=="];///acc/logout + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, access_token, nil]; +} + +/// 查询两个人的关注状态 +/// @param completion 完成 +/// @param uid 自己的uid +/// @param isLikeUid 要查询的那个人的uid ++ (void)attentionStatusCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid isLikeUid:(NSString *)isLikeUid { + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9pc2xpa2U="];///fans/islike + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, uid, isLikeUid, nil]; +} + +/// 关注某人 +/// @param completion 完成 +/// @param uid 发起关注的人 +/// @param likedUid 被关注的人 +/// @param ticket ticket +/// @param type 1 关注 2取消关注 ++ (void)attentionCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid likedUid:(NSString *)likedUid ticket:(NSString *)ticket type:(NSString *)type { + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9saWtl"];///fans/like + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, likedUid, ticket, type, nil]; +} + +/// 获取用户详情 +/// @param completion 完成 +/// @param uid 发起关注的人 +/// @param page page +/// @param pageSize pagesize ++ (void)userDetailInfoCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9kZXRhaWwvZ2V0"];///user/detail/get + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, page, pageSize, nil]; +} + +/// 获取粉丝列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param pageNo 当前页数 +/// @param pageSize 一页多少个 ++ (void)getFansListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize { + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zbGlzdA=="];///@"fans/fanslist" + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, pageNo, pageSize, nil]; +} + +/// 获取关注列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param pageNo 当前页数 +/// @param pageSize 一页多少个 ++ (void)getattentionListCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize { + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mb2xsb3dpbmc="];///fans/following + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, pageNo, pageSize, nil]; +} + +/// 获取访客列表 +/// @param completion 完成 +/// @param pageNum 当前页数 +/// @param pageSize 一页多少个 ++ (void)getVisitorListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize { + NSString * fang = [NSString stringFromBase64String:@"dXNlcnZpc2l0cmVjb3JkL3Zpc2l0VXNlckxpc3Q="];///uservisitrecord/visitUserList + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, pageNum, pageSize, nil]; +} + +/// 上传访问用户的记录 +/// @param completion 完成 +/// @param uid 被访问的用户uid ++ (void)uploadVisitUserCompletion:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9kZXRhaWwvdmlzaXRVc2VyRGV0YWls"];///user/detail/visitUserDetail + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; +} + +/// 获取粉丝团列表 +/// @param completion 完成 +/// @param pageNum 当前页数 +/// @param pageSize 一页多少个 ++ (void)getAnchorFansTeamListCompletion:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize { + NSString * fang = [NSString stringFromBase64String:@"YW5jaG9yRmFuc1RlYW0vZ2V0Sm9pbkZhbnNUZWFtTGlzdA=="];///anchorFansTeam/getJoinFansTeamList + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, pageNum, pageSize, nil]; +} + +/// 获取用户的礼物墙 +/// @param comletion 完成 +/// @param uid 用户的uid +/// @param giftType 类型2 ++ (void)getUserGiftWall:(HttpRequestHelperCompletion)comletion uid:(NSString *)uid giftType:(NSString *)giftType { + NSString * fang = [NSString stringFromBase64String:@"Z2lmdHdhbGwvZ2V0QnlHaWZ0VHlwZQ=="];///giftwall/getByGiftType + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:comletion, __FUNCTION__, uid, giftType, nil]; +} + +/// 批量获取用户信息 +/// @param completion 完成 +/// @param uids 用户的uid ++ (void)getUsersListInfo:(HttpRequestHelperCompletion)completion uids:(NSString *)uids { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9saXN0"];///user/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uids, nil]; +} + ++ (void)fansFriendList:(HttpRequestHelperCompletion)completion pageNo:(NSNumber *)pageNo pageSize:(NSNumber *)pageSize { + [self makeRequest:@"fans/friend/list" method:HttpRequestHelperMethodGET completion:completion, + __FUNCTION__, pageNo, pageSize, nil]; +} + +/// 获取用户进房记录 +/// @param completion 完成 +/// @param uid 用户的uid ++ (void)requestFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize { + NSString * fang = [NSString stringFromBase64String:@"dXNlcnJvb20vZ2V0SW5Sb29tUmVjb3Jk"];///userroom/getInRoomRecord + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, page, pageSize, nil]; +} + +/// 清除进房记录 +/// @param completion 完成 +/// @param uid 用户uid +/// @param roomUid 房间uid ++ (void)requestCleanFootPrint:(HttpRequestHelperCompletion)completion uid:(NSString *)uid roomUid:(NSString *)roomUid { + NSString * fang = [NSString stringFromBase64String:@"dXNlcnJvb20vZGVsZXRlSW5Sb29tUmVjb3Jk"];///userroom/deleteInRoomRecord + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, roomUid, nil]; +} + +/// 快捷进房 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param mgId 游戏id ++ (void)requestMineQuickMatchLittleGame:(HttpRequestHelperCompletion)completion uid:(NSString *)uid mgId:(NSString *)mgId { + NSString * fang = [NSString stringFromBase64String:@"aG9tZS9mYXN0UGlja1Yy"];///home/fastPickV2 + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, mgId, nil]; +} + +/// 请求收藏房间列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param page 当前页数 +/// @param pageSize 一页多少个 +/// @param roomType 类型:4:个播房;其他:派对房;不传:所有房间 ++ (void)requestMineCollectRoomList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize roomType:(NSString *)roomType { + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zUm9vbUxpc3Q="];///fans/fansRoomList + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__,uid , page, pageSize, roomType, nil]; +} + +/// 请求大家都在搜列表 +/// @param completion 完成 +/// @param uid uid ++ (void)requestEveryoneSearch:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"ZXZlcnkvb25lL3NlYXJjaC9nZXRMaXN0"];///every/one/search/getList + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; +} + +/// 获取好友派对列表 +/// @param completion 完成 ++ (void)requestFansParty:(HttpRequestHelperCompletion)completion { + NSString * fang = [NSString stringFromBase64String:@"ZmFucy9mYW5zUGFydExpc3Q="];///fans/fansPartList + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} +/// 请求主播评级 +/// @param completion 完成 ++ (void)requestAnchorGradeInfo:(HttpRequestHelperCompletion)completion { + NSString * fang = [NSString stringFromBase64String:@"YW5jaG9yR3JhZGUvZ2V0"];///anchorGrade/get + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, nil]; +} + ++ (void)requestMineGuildList:(HttpRequestHelperCompletion)completion { + NSString * fang = [NSString stringFromBase64String:@"Y2xhbi9saXN0"];///clan/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} ++ (void)requestMineRoomList:(HttpRequestHelperCompletion)completion { + NSString * fang = [NSString stringFromBase64String:@"aGFsbC9saXN0"];///hall/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} ++(void)applyClanWith:(HttpRequestHelperCompletion)completion uid:(NSString *)uid clanId:(NSString *)clanId { + NSString * fang = [NSString stringFromBase64String:@"Y2xhbi9hcHBseQ=="];///clan/apply + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,uid, clanId, nil]; +} + ++(void)getGoldDetailsData:(HttpRequestHelperCompletion)completion startTime:(NSString *)startTime endTime:(NSString *)endTime{ + NSString * fang = [NSString stringFromBase64String:@"Y2xhbkdvbGRGbG93L2NsYW5Ub3RhbExpc3Q="];///clanGoldFlow/clanTotalList + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__,startTime,endTime, nil]; +} + +/// 设置支付密码 重置支付密码 +/// @param completion 完成 +/// @param newPasswd 支付密码 +/// @param phone 手机号 + +/// @param uid uid +/// @param ticket ticket ++ (void)setPayPassword:(HttpRequestHelperCompletion)completion newPasswd:(NSString *)newPasswd uid:(NSString *)uid ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9wYXltZW50UGFzc3dkL3Jlc2V0"];///user/paymentPasswd/reset + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, newPasswd,uid,ticket, nil]; +} + ++(void)requestQueryWithRoomType:(HttpRequestHelperCompletion)completion{ + NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnlXaXRoUm9vbVR5cGU="];///purse/queryWithRoomType + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++(void)requestRecordIncome:(HttpRequestHelperCompletion)completion{ + NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnk="];///purse/query + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++(void)getExchangeDiamondInformation:(HttpRequestHelperCompletion)completion{ + NSString * fang = [NSString stringFromBase64String:@"Z29sZEV4Y2hhbmdlRGlhbW9uZC9nZXRDb25maWc="];///goldExchangeDiamond/getConfig + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++(void)confirmExchangeDiamond:(HttpRequestHelperCompletion)completion goldNum:(NSString *)goldNum diamondNum:(NSString *)diamondNum currency:(NSString *)currency{ + NSString * fang = [NSString stringFromBase64String:@"Z29sZEV4Y2hhbmdlRGlhbW9uZC9leGNoYW5nZQ=="];///goldExchangeDiamond/exchange + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,goldNum,diamondNum,currency, nil]; +} + ++(void)getTagList:(HttpRequestHelperCompletion)completion{ + [self makeRequest:@"label/edit" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, nil]; +} +///保存个人简介标签 ++(void)saveTagList:(HttpRequestHelperCompletion)completion labels:(NSString *)labels{ + [self makeRequest:@"label/save" method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,labels, nil]; +} +//////获取地区列表 ++(void)getAreaList:(HttpRequestHelperCompletion)completion{ + [self makeRequest:@"regionInfo/list" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, nil]; +} +///保存地区列表 ++(void)saveAreaConfigWithArea:(HttpRequestHelperCompletion)completion id:(NSString *)id{ + [self makeRequest:@"regionInfo/save" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, id, nil]; +} + ++(void)getBlackRoomList:(HttpRequestHelperCompletion)completion pageNum:(NSString *)pageNum pageSize:(NSString *)pageSize{ + [self makeRequest:@"user/black/pageRoom" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, pageNum,pageSize,nil]; +} +/// 解除屏蔽 +/// - Parameters: +/// - completion: 完成 +/// - roomUid: 房间id +/// - type: 1=房间 ++(void)requestUnmaskingFromBlackRoomList:(HttpRequestHelperCompletion)completion objId:(NSString *)objId type:(NSString *)type { + [self makeRequest:@"user/black/delete" method:HttpRequestHelperMethodPOST completion:completion,__FUNCTION__,objId,type, nil]; +} + + +//获取 cp 列表 ++(void)requestCPList:(HttpRequestHelperCompletion)completion page:(NSNumber *)page pageSize:(NSNumber *)pageSize{ + [self makeRequest:@"user/cp/list" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, nil]; +} + ++(void)cancelCPList:(HttpRequestHelperCompletion)completion uid:(NSNumber *)uid loverUid:(NSNumber *)loverUid goldNum:(NSNumber *)goldNum { + [self makeRequest:@"user/cp/cancel" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, loverUid, goldNum, nil]; +} + ++(void)updateCPSetting:(HttpRequestHelperCompletion)completion type:(NSNumber *)type isShow:(NSNumber *)isShow { + [self makeRequest:@"user/setting/update" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, type, isShow, nil]; +} + ++(void)requestBlockTime:(HttpRequestHelperCompletion)completion { + [self makeRequest:@"user/blockTime" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++(void)blockUser:(HttpRequestHelperCompletion)completion uid:(NSNumber *)uid hours:(NSNumber *)hours blockReason:(NSString *)blockReason { + [self makeRequest:@"user/block" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, hours, blockReason, nil]; +} + ++ (void)userDetailMine:(HttpRequestHelperCompletion)completion { + [self makeRequest:@"user/detail/mine" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++ (void)userV2UploadAvatar:(HttpRequestHelperCompletion)completion avatarUrl:(NSString *)avatarUrl needPay:(NSNumber *)needPay { + [self makeRequest:@"user/v2/uploadAvatar" method:HttpRequestHelperMethodPOST completion:completion, + __FUNCTION__, avatarUrl, needPay, nil]; +} + ++ (void)userCpNameChange:(HttpRequestHelperCompletion)completion uid:(NSInteger)uid loverUid:(NSInteger)loverUid relationNameType:(NSInteger)relationNameType { + [self makeRequest:@"user/cp/nameChange" method:HttpRequestHelperMethodPOST completion:completion, + __FUNCTION__, @(uid), @(loverUid), @(relationNameType), nil]; +} + ++ (void)userCpNameChangeAudit:(HttpRequestHelperCompletion)completion recordId:(NSInteger)recordId status:(NSInteger)status { + [self makeRequest:@"user/cp/nameChangeAudit" method:HttpRequestHelperMethodPOST completion:completion, + __FUNCTION__, @(recordId), @(status), nil]; +} + ++ (void)userCpNameTypeTopList:(HttpRequestHelperCompletion)completion uid:(NSInteger)uid { + [self makeRequest:@"user/cp/nameTypeTopList" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, @(uid), nil]; +} + + + +@end diff --git a/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m b/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m index 44241fc..a139efc 100644 --- a/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m +++ b/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m @@ -1,27 +1,18 @@ -// -// Api+EnterpriseRecharge.m -// xplan-ios -// + + // Created by 冯硕 on 2022/5/14. -// + #import "Api+EnterpriseRecharge.h" #import "NSMutableDictionary+Saft.h" @implementation Api (EnterpriseRecharge) -///企业包的充值列表 + + (void)enterpriseRechargeList:(HttpRequestHelperCompletion)completion channelType:(NSString *)channelType { [self makeRequest:@"chargeprod/listV2" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, channelType, nil]; } -/// 请求支付参数 -/// @param completion 完成 -/// @param chargeProdId 订单的id -/// @param payChannel 支付的渠道 -/// @param clientIp ip -/// @param uid uid -/// @param ticket ticket + (void)requestPay:(HttpRequestHelperCompletion)completion chargeProdId:(NSString *)chargeProdId payChannel:(NSString *)payChannel clientIp:(NSString *)clientIp uid:(NSString *)uid ticket:(NSString *)ticket roomUid:(NSString *)roomUid { NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:chargeProdId forKey:@"chargeProdId"]; @@ -36,5 +27,4 @@ } - @end diff --git a/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m.backup b/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m.backup new file mode 100644 index 0000000..44241fc --- /dev/null +++ b/YuMi/Modules/YMMine/View/EnterpriseRecharge/Api/Api+EnterpriseRecharge.m.backup @@ -0,0 +1,40 @@ +// +// Api+EnterpriseRecharge.m +// xplan-ios +// +// Created by 冯硕 on 2022/5/14. +// + +#import "Api+EnterpriseRecharge.h" +#import "NSMutableDictionary+Saft.h" +@implementation Api (EnterpriseRecharge) + +///企业包的充值列表 ++ (void)enterpriseRechargeList:(HttpRequestHelperCompletion)completion channelType:(NSString *)channelType { + [self makeRequest:@"chargeprod/listV2" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, channelType, nil]; +} + + +/// 请求支付参数 +/// @param completion 完成 +/// @param chargeProdId 订单的id +/// @param payChannel 支付的渠道 +/// @param clientIp ip +/// @param uid uid +/// @param ticket ticket ++ (void)requestPay:(HttpRequestHelperCompletion)completion chargeProdId:(NSString *)chargeProdId payChannel:(NSString *)payChannel clientIp:(NSString *)clientIp uid:(NSString *)uid ticket:(NSString *)ticket roomUid:(NSString *)roomUid { + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + [dic safeSetObject:chargeProdId forKey:@"chargeProdId"]; + [dic safeSetObject:payChannel forKey:@"payChannel"]; + [dic safeSetObject:clientIp forKey:@"clientIp"]; + [dic safeSetObject:uid forKey:@"uid"]; + [dic safeSetObject:ticket forKey:@"ticket"]; + if (roomUid.integerValue> 0) { + [dic safeSetObject:roomUid forKey:@"roomUid"]; + } + [HttpRequestHelper request:@"charge/pay/apply" method:HttpRequestHelperMethodPOST params:dic completion:completion]; +} + + + +@end diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m b/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m index 7fd6a71..5b82c44 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m +++ b/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m @@ -1,9 +1,4 @@ -// -// MedalsCollectionViewCell_Refactored.m -// YuMi -// -// 重构示例:使用 MedalMediaDisplayManager 简化媒体处理逻辑 -// + #import "MedalsCollectionViewCell.h" #import "MedalsModel.h" @@ -12,17 +7,17 @@ @interface MedalsCollectionViewCell () -// 媒体显示管理器 - 替代原来的所有媒体相关属性和方法 + @property (nonatomic, strong) MedalMediaDisplayManager *mediaManager; -// UI 元素 + @property (nonatomic, strong) NetImageView *imageView; @property (nonatomic, strong) VAPView *mp4View; @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *subLabel; @property (nonatomic, strong) MedalsLevelIndicatorView *levelIndicatorView; -// 数据模型 + @property (nonatomic, strong) MedalVo *displayModel; @property (nonatomic, strong) MedalSeriesItemVo *currentItemVo; @@ -54,7 +49,7 @@ } - (void)setupUI { - // UI 设置保持不变 + [self.contentView addGradientBackgroundWithColors:@[ UIColorFromRGB(0x41007b), UIColorFromRGB(0x290858) @@ -81,24 +76,24 @@ make.edges.mas_equalTo(self.imageView); }]; - // 其他UI元素设置... + self.titleLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]]; self.subLabel = [UILabel labelInitWithText:@"" font:kFontRegular(11) textColor:[UIColor colorWithWhite:1 alpha:0.6]]; - // ... 约束设置省略 + } - (void)setupMediaManager { - // 创建媒体管理器,传入自己作为代理 + self.mediaManager = [[MedalMediaDisplayManager alloc] initWithDelegate:self]; } - (void)prepareForReuse { [super prepareForReuse]; - // 使用媒体管理器清理资源 - 替代原来的复杂清理逻辑 + [self.mediaManager cleanupResources]; - // 重置UI状态 + self.displayModel = nil; self.currentItemVo = nil; self.titleLabel.text = @""; @@ -110,7 +105,7 @@ MedalSeriesItemVo *itemVos = [model.medalSeries xpSafeObjectAtIndex:0]; self.currentItemVo = itemVos; - // 设置等级指示器 + self.levelIndicatorView.indicatorType = MedalsLevelIndicatorTypeNormal; [self.levelIndicatorView setupWithMaxLevel:itemVos.medalLevel]; @@ -124,10 +119,10 @@ self.levelIndicatorView.userInteractionEnabled = !isSquare; - // 使用媒体管理器更新显示 - 替代原来的复杂逻辑 + [self.mediaManager updateDisplayWithModel:self.displayModel]; - // 更新文本信息 + [self updateTextLabels]; } @@ -167,7 +162,7 @@ } - (void)onMediaDisplayUpdated:(BOOL)isMP4 success:(BOOL)success { - // 可选:处理媒体显示状态更新 + NSLog(@"Media display updated: %@ - %@", isMP4 ? @"MP4" : @"Image", success ? @"Success" : @"Failed"); } @@ -178,37 +173,9 @@ #pragma mark - 生命周期 - (void)dealloc { - // 媒体管理器会自动处理资源清理 + NSLog(@"MedalsCollectionViewCell dealloc"); } @end -/* -重构效果对比: - -原始代码:~528行 -重构后代码:~150行(减少70%+) - -移除的重复代码: -- 所有媒体路径属性和管理逻辑 -- MP4播放器相关属性和方法 -- 复杂的播放状态管理 -- 应用生命周期通知处理 -- MP4解析和播放控制逻辑 -- 失败降级处理逻辑 -- 可见性管理的复杂逻辑 - -保留的业务逻辑: -- UI布局和样式 -- 等级指示器相关逻辑 -- 业务数据模型处理 -- 特定的UI更新逻辑 - -核心优势: -1. 代码量大幅减少,可读性提升 -2. 媒体处理逻辑统一管理 -3. Bug修复只需要在一个地方 -4. 新功能添加更容易 -5. 测试和维护成本降低 -*/ \ No newline at end of file diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m.backup b/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m.backup new file mode 100644 index 0000000..7fd6a71 --- /dev/null +++ b/YuMi/Modules/YMMine/View/Medals/MedalsCollectionViewCell_Refactored.m.backup @@ -0,0 +1,214 @@ +// +// MedalsCollectionViewCell_Refactored.m +// YuMi +// +// 重构示例:使用 MedalMediaDisplayManager 简化媒体处理逻辑 +// + +#import "MedalsCollectionViewCell.h" +#import "MedalsModel.h" +#import "MedalMediaDisplayManager.h" +#import "MedalsLevelIndicatorView.h" + +@interface MedalsCollectionViewCell () + +// 媒体显示管理器 - 替代原来的所有媒体相关属性和方法 +@property (nonatomic, strong) MedalMediaDisplayManager *mediaManager; + +// UI 元素 +@property (nonatomic, strong) NetImageView *imageView; +@property (nonatomic, strong) VAPView *mp4View; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *subLabel; +@property (nonatomic, strong) MedalsLevelIndicatorView *levelIndicatorView; + +// 数据模型 +@property (nonatomic, strong) MedalVo *displayModel; +@property (nonatomic, strong) MedalSeriesItemVo *currentItemVo; + +@end + +@implementation MedalsCollectionViewCell + ++ (NSString *)cellID { + return NSStringFromClass([MedalsCollectionViewCell class]); +} + ++ (void)registerTo:(UICollectionView *)collectionView { + [collectionView registerClass:[self class] forCellWithReuseIdentifier:[self cellID]]; +} + ++ (instancetype)cellFor:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)index { + MedalsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[self cellID] + forIndexPath:index]; + return cell; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupUI]; + [self setupMediaManager]; + } + return self; +} + +- (void)setupUI { + // UI 设置保持不变 + [self.contentView addGradientBackgroundWithColors:@[ + UIColorFromRGB(0x41007b), + UIColorFromRGB(0x290858) + ] startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1) cornerRadius:8]; + + [self.contentView setAllCornerRadius:8 + borderWidth:1 + borderColor:UIColorFromRGB(0xa166bf)]; + + self.imageView = [[NetImageView alloc] init]; + self.imageView.contentMode = UIViewContentModeScaleAspectFill; + [self.contentView addSubview:self.imageView]; + [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.contentView); + make.top.mas_equalTo(13); + make.leading.trailing.mas_equalTo(self.contentView).inset(13); + make.height.mas_equalTo(self.imageView.mas_width); + }]; + + self.mp4View = [[VAPView alloc] init]; + self.mp4View.contentMode = UIViewContentModeScaleAspectFit; + [self.contentView addSubview:self.mp4View]; + [self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.imageView); + }]; + + // 其他UI元素设置... + self.titleLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]]; + self.subLabel = [UILabel labelInitWithText:@"" font:kFontRegular(11) textColor:[UIColor colorWithWhite:1 alpha:0.6]]; + // ... 约束设置省略 +} + +- (void)setupMediaManager { + // 创建媒体管理器,传入自己作为代理 + self.mediaManager = [[MedalMediaDisplayManager alloc] initWithDelegate:self]; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + + // 使用媒体管理器清理资源 - 替代原来的复杂清理逻辑 + [self.mediaManager cleanupResources]; + + // 重置UI状态 + self.displayModel = nil; + self.currentItemVo = nil; + self.titleLabel.text = @""; + self.subLabel.text = @""; + [self.levelIndicatorView resetToLevel:0]; +} + +- (void)updateCell:(MedalSeriesVo *)model isForSquare:(BOOL)isSquare { + MedalSeriesItemVo *itemVos = [model.medalSeries xpSafeObjectAtIndex:0]; + self.currentItemVo = itemVos; + + // 设置等级指示器 + self.levelIndicatorView.indicatorType = MedalsLevelIndicatorTypeNormal; + [self.levelIndicatorView setupWithMaxLevel:itemVos.medalLevel]; + + if (isSquare) { + self.displayModel = [itemVos.medalVos xpSafeObjectAtIndex:itemVos.medalVos.count - 1]; + [self.levelIndicatorView setSelectedLevel:itemVos.medalLevel animated:NO]; + } else { + self.displayModel = [itemVos.medalVos xpSafeObjectAtIndex:0]; + [self.levelIndicatorView setSelectedLevel:1 animated:NO]; + } + + self.levelIndicatorView.userInteractionEnabled = !isSquare; + + // 使用媒体管理器更新显示 - 替代原来的复杂逻辑 + [self.mediaManager updateDisplayWithModel:self.displayModel]; + + // 更新文本信息 + [self updateTextLabels]; +} + +- (void)updateTextLabels { + self.titleLabel.text = self.displayModel.name; + self.subLabel.text = [self.displayModel expireDateString]; +} + +#pragma mark - 可见性管理 - 大幅简化 + +- (void)willDisplay { + [self.mediaManager willDisplay]; +} + +- (void)didEndDisplaying { + [self.mediaManager didEndDisplaying]; +} + +#pragma mark - MedalMediaDisplayDelegate - 核心代理方法 + +- (NSString *)getMP4UrlFromModel:(id)model { + MedalVo *medalVo = (MedalVo *)model; + return medalVo.mp4Url; +} + +- (NSString *)getPicUrlFromModel:(id)model { + MedalVo *medalVo = (MedalVo *)model; + return medalVo.picUrl; +} + +- (NetImageView *)getImageView { + return self.imageView; +} + +- (VAPView *)getMP4View { + return self.mp4View; +} + +- (void)onMediaDisplayUpdated:(BOOL)isMP4 success:(BOOL)success { + // 可选:处理媒体显示状态更新 + NSLog(@"Media display updated: %@ - %@", isMP4 ? @"MP4" : @"Image", success ? @"Success" : @"Failed"); +} + +- (UIImage *)getDefaultPlaceholderImage { + return [UIImageConstant defaultEmptyPlaceholder]; +} + +#pragma mark - 生命周期 + +- (void)dealloc { + // 媒体管理器会自动处理资源清理 + NSLog(@"MedalsCollectionViewCell dealloc"); +} + +@end + +/* +重构效果对比: + +原始代码:~528行 +重构后代码:~150行(减少70%+) + +移除的重复代码: +- 所有媒体路径属性和管理逻辑 +- MP4播放器相关属性和方法 +- 复杂的播放状态管理 +- 应用生命周期通知处理 +- MP4解析和播放控制逻辑 +- 失败降级处理逻辑 +- 可见性管理的复杂逻辑 + +保留的业务逻辑: +- UI布局和样式 +- 等级指示器相关逻辑 +- 业务数据模型处理 +- 特定的UI更新逻辑 + +核心优势: +1. 代码量大幅减少,可读性提升 +2. 媒体处理逻辑统一管理 +3. Bug修复只需要在一个地方 +4. 新功能添加更容易 +5. 测试和维护成本降低 +*/ \ No newline at end of file diff --git a/YuMi/Modules/YMMonents/Api/Api+Moments.h b/YuMi/Modules/YMMonents/Api/Api+Moments.h index 45a47f4..fad5ff4 100644 --- a/YuMi/Modules/YMMonents/Api/Api+Moments.h +++ b/YuMi/Modules/YMMonents/Api/Api+Moments.h @@ -1,167 +1,75 @@ -// -// Api+Monents.h -// YUMI -// + + // Created by YUMI on 2022/5/13. -// + #import "Api.h" NS_ASSUME_NONNULL_BEGIN @interface Api (Moments) -/// 朋友圈动态推荐列表 -/// @param completion 完成 -/// @param page 当前的页数 -/// @param pageSize 一页的个数 -/// @param types 类型 0,2 + + + (void)momentsRecommendList:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize types:(NSString *)types; -/// 朋友圈动态最新列表 -/// @param completion 完成 -/// @param dynamicId 最新动态的id -/// @param pageSize 一页的个数 -/// @param types 类型 0,2 + + (void)momentsLatestList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types; -/// 朋友圈动态关注列表 -/// @param completion 完成 -/// @param dynamicId 最新动态的id -/// @param pageSize 一页的个数 -/// @param types 类型 0,2 + + (void)momentsFollowerList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types; -/// 互动消息列表 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param pageSize 一页的个数 -/// @param uid 类型 uid + + (void)momentsInteractiveList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize uid:(NSString *)uid; -/// 清空互动消息 -/// @param Completion 完成 -/// @param uid 用户的uid + + (void)momentsInteractiveClear:(HttpRequestHelperCompletion)Completion uid:(NSString *)uid; -/// 获取话题列表 -/// @param completion 完成 -/// @param uid uid -/// @param page 当前的页数 -/// @param pageSize 一页多少个 -/// @param worldTypeId 类型0 + + (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize worldTypeId:(NSString *)worldTypeId; -/// 分享动态 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param uid 动态发布者的uid -/// @param worldId 动态的话题id -/// @param shareUid 分享者的uid + + (void)userShareMoments:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid worldId:(NSString *)worldId shareUid:(NSString *)shareUid; -/// 点赞动态 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param uid 用户的uid -/// @param status 0 取消点赞 1 点赞 -/// @param likedUid 点赞人的uid -/// @param worldId 世界的id + (void)momentsLike:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid status:(NSString *)status likedUid:(NSString *)likedUid worldId:(NSString *)worldId; -/// 动态详情 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param worldId 话题的id -/// @param uid 用户的uid + + (void)momentsDetail:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId uid:(NSString *)uid; -/// 评论动态 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 动态的id -/// @param content 内容 + + (void)momentDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content; -/// 回复评论 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 动态的id -/// @param content 内容 -/// @param commentId 评论的id + + (void)replyMomentsDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content commentId:(NSString *)commentId; -/// 请求评论列表 -/// @param completion 完成 -/// @param dynamicId 动态id -/// @param uid uid -/// @param pageSize 一页多少个 -/// @param timestamp 上一个评论的时间戳 + + (void)momentsCommentList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize timestamp:(NSString *)timestamp; -/// 评论回复列表 -/// @param completion 完成 -/// @param dynamicId 动态id -/// @param uid uid -/// @param pageSize 每页多少个 -/// @param commentId 评论的id -/// @param timestamp 上条回复的时间 + + (void)momentsCommentReplyList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize commentId:(NSString *)commentId timestamp:(NSString *)timestamp; -/// 获取可以选择的话题列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param type 类型 -/// @param page 当前的页数 + + (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type page:(NSString *)page; -/// 发布动态 -/// @param completion 完成 -/// @param uid uid -/// @param type 类型 -/// @param worldId 话题的id -/// @param content 内容 -/// @param resList 发布的图片 + + (void)momentsPublish:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type worldId:(NSString *)worldId content:(NSString *)content resList:(NSArray *)resList; -/// 获取动态话题最新记录 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 下一页动态的id -/// @param types l类型 -/// @param worldId 话题的id -/// @param pageSize 一页多少个 + + (void)momentsTopicLatestList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize; -/// 获取动态话题推荐记录 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 下一页动态的id -/// @param types l类型 -/// @param worldId 话题的id -/// @param pageSize 一页多少个 + + (void)momentsTopicRecommendList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize; -/// 获取动态话题详情 -/// @param completion 完成 -/// @param worldId 话题id -/// @param uid 用户uid + + (void)momentsTopicDetailInfo:(HttpRequestHelperCompletion)completion worldId:(NSString *)worldId uid:(NSString *)uid; -/// 删除动态 -/// @param completion 完成 -/// @param uid uid -/// @param dynamicId 动态的id -/// @param worldId 话题的id + + (void)momentsDelete:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId; -/// 获取动态没有阅读数 -/// @param completion 完成 -/// @param uid uid + + (void)momentsUnReadCount:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; -/// 屏蔽 -/// @param completion 完成 -/// @param type type为0 => 屏蔽动态, objId 为 动态id, type为1 => 屏蔽房间, objId 为 用户uid + + + (void)requestShielding:(HttpRequestHelperCompletion)completion type:(NSString *)type objId:(NSString *)objId; @end diff --git a/YuMi/Modules/YMMonents/Api/Api+Moments.h.backup b/YuMi/Modules/YMMonents/Api/Api+Moments.h.backup new file mode 100644 index 0000000..45a47f4 --- /dev/null +++ b/YuMi/Modules/YMMonents/Api/Api+Moments.h.backup @@ -0,0 +1,168 @@ +// +// Api+Monents.h +// YUMI +// +// Created by YUMI on 2022/5/13. +// + +#import "Api.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface Api (Moments) +/// 朋友圈动态推荐列表 +/// @param completion 完成 +/// @param page 当前的页数 +/// @param pageSize 一页的个数 +/// @param types 类型 0,2 ++ (void)momentsRecommendList:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize types:(NSString *)types; + +/// 朋友圈动态最新列表 +/// @param completion 完成 +/// @param dynamicId 最新动态的id +/// @param pageSize 一页的个数 +/// @param types 类型 0,2 ++ (void)momentsLatestList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types; + +/// 朋友圈动态关注列表 +/// @param completion 完成 +/// @param dynamicId 最新动态的id +/// @param pageSize 一页的个数 +/// @param types 类型 0,2 ++ (void)momentsFollowerList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types; + +/// 互动消息列表 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param pageSize 一页的个数 +/// @param uid 类型 uid ++ (void)momentsInteractiveList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize uid:(NSString *)uid; + +/// 清空互动消息 +/// @param Completion 完成 +/// @param uid 用户的uid ++ (void)momentsInteractiveClear:(HttpRequestHelperCompletion)Completion uid:(NSString *)uid; + +/// 获取话题列表 +/// @param completion 完成 +/// @param uid uid +/// @param page 当前的页数 +/// @param pageSize 一页多少个 +/// @param worldTypeId 类型0 ++ (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize worldTypeId:(NSString *)worldTypeId; + +/// 分享动态 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param uid 动态发布者的uid +/// @param worldId 动态的话题id +/// @param shareUid 分享者的uid ++ (void)userShareMoments:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid worldId:(NSString *)worldId shareUid:(NSString *)shareUid; + + +/// 点赞动态 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param uid 用户的uid +/// @param status 0 取消点赞 1 点赞 +/// @param likedUid 点赞人的uid +/// @param worldId 世界的id ++ (void)momentsLike:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid status:(NSString *)status likedUid:(NSString *)likedUid worldId:(NSString *)worldId; + +/// 动态详情 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param worldId 话题的id +/// @param uid 用户的uid ++ (void)momentsDetail:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId uid:(NSString *)uid; + +/// 评论动态 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 动态的id +/// @param content 内容 ++ (void)momentDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content; + +/// 回复评论 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 动态的id +/// @param content 内容 +/// @param commentId 评论的id ++ (void)replyMomentsDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content commentId:(NSString *)commentId; + +/// 请求评论列表 +/// @param completion 完成 +/// @param dynamicId 动态id +/// @param uid uid +/// @param pageSize 一页多少个 +/// @param timestamp 上一个评论的时间戳 ++ (void)momentsCommentList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize timestamp:(NSString *)timestamp; + +/// 评论回复列表 +/// @param completion 完成 +/// @param dynamicId 动态id +/// @param uid uid +/// @param pageSize 每页多少个 +/// @param commentId 评论的id +/// @param timestamp 上条回复的时间 ++ (void)momentsCommentReplyList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize commentId:(NSString *)commentId timestamp:(NSString *)timestamp; + +/// 获取可以选择的话题列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param type 类型 +/// @param page 当前的页数 ++ (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type page:(NSString *)page; + +/// 发布动态 +/// @param completion 完成 +/// @param uid uid +/// @param type 类型 +/// @param worldId 话题的id +/// @param content 内容 +/// @param resList 发布的图片 ++ (void)momentsPublish:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type worldId:(NSString *)worldId content:(NSString *)content resList:(NSArray *)resList; + +/// 获取动态话题最新记录 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 下一页动态的id +/// @param types l类型 +/// @param worldId 话题的id +/// @param pageSize 一页多少个 ++ (void)momentsTopicLatestList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize; + +/// 获取动态话题推荐记录 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 下一页动态的id +/// @param types l类型 +/// @param worldId 话题的id +/// @param pageSize 一页多少个 ++ (void)momentsTopicRecommendList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize; + +/// 获取动态话题详情 +/// @param completion 完成 +/// @param worldId 话题id +/// @param uid 用户uid ++ (void)momentsTopicDetailInfo:(HttpRequestHelperCompletion)completion worldId:(NSString *)worldId uid:(NSString *)uid; + +/// 删除动态 +/// @param completion 完成 +/// @param uid uid +/// @param dynamicId 动态的id +/// @param worldId 话题的id ++ (void)momentsDelete:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId; + +/// 获取动态没有阅读数 +/// @param completion 完成 +/// @param uid uid ++ (void)momentsUnReadCount:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; +/// 屏蔽 +/// @param completion 完成 +/// @param type type为0 => 屏蔽动态, objId 为 动态id, type为1 => 屏蔽房间, objId 为 用户uid ++ (void)requestShielding:(HttpRequestHelperCompletion)completion type:(NSString *)type objId:(NSString *)objId; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMonents/Api/Api+Moments.m b/YuMi/Modules/YMMonents/Api/Api+Moments.m index 2a1927c..43da72e 100644 --- a/YuMi/Modules/YMMonents/Api/Api+Moments.m +++ b/YuMi/Modules/YMMonents/Api/Api+Moments.m @@ -1,9 +1,7 @@ -// -// Api+Monents.m -// YUMI -// + + // Created by YUMI on 2022/5/13. -// + #import "Api+Moments.h" #import "NSObject+MJExtension.h" @@ -11,41 +9,25 @@ #import @implementation Api (Moments) -/// 朋友圈动态推荐列表 -/// @param completion 完成 -/// @param page 当前的页数 -/// @param pageSize 一页的个数 -/// @param types 类型 0,2 + + (void)momentsRecommendList:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize types:(NSString *)types { [self makeRequest:@"dynamic/square/recommendDynamics" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, types, nil]; } -/// 朋友圈动态最新列表 -/// @param completion 完成 -/// @param dynamicId 最新动态的id -/// @param pageSize 一页的个数 -/// @param types 类型 0,2 + + (void)momentsLatestList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types { [self makeRequest:@"dynamic/square/latestDynamics" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dynamicId, pageSize, types, nil]; } -/// 朋友圈动态关注列表 -/// @param completion 完成 -/// @param dynamicId 最新动态的id -/// @param pageSize 一页的个数 -/// @param types 类型 0,2 + + (void)momentsFollowerList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvZm9sbG93ZXJEeW5hbWljcw=="];///dynamic/square/followerDynamics + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvZm9sbG93ZXJEeW5hbWljcw=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dynamicId, pageSize, types, nil]; } -/// 互动消息列表 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param pageSize 一页的个数 -/// @param uid 类型 uid + + (void)momentsInteractiveList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvbGlzdA=="];///interactive/list + NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvbGlzdA=="]; NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:dynamicId forKey:@"id"]; [dic safeSetObject:pageSize forKey:@"pageSize"]; @@ -53,87 +35,50 @@ [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; } -/// 清空互动消息 -/// @param completion 完成 -/// @param uid 用户的uid + + (void)momentsInteractiveClear:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvY2xlYXI="];///interactive/clear + NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvY2xlYXI="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, nil]; } -/// 获取话题列表 -/// @param completion 完成 -/// @param uid uid -/// @param page 当前的页数 -/// @param pageSize 一页多少个 -/// @param worldTypeId 类型0 + + (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize worldTypeId:(NSString *)worldTypeId { - NSString * fang = [NSString stringFromBase64String:@"d29ybGQvbGlzdA=="];///world/list + NSString * fang = [NSString stringFromBase64String:@"d29ybGQvbGlzdA=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, page, pageSize, worldTypeId, nil]; } -/// 分享动态 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param uid 动态发布者的uid -/// @param worldId 动态的话题id -/// @param shareUid 分享者的uid + + (void)userShareMoments:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid worldId:(NSString *)worldId shareUid:(NSString *)shareUid { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zaGFyZQ=="];///dynamic/share + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zaGFyZQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, uid, worldId, shareUid, nil]; } -/// 点赞动态 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param uid 用户的uid -/// @param status 0 取消点赞 1 点赞 -/// @param likedUid 点赞人的uid -/// @param worldId 世界的id + + (void)momentsLike:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid status:(NSString *)status likedUid:(NSString *)likedUid worldId:(NSString *)worldId { [self makeRequest:@"dynamic/like" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, uid, status, likedUid, worldId, nil]; } -/// 动态详情 -/// @param completion 完成 -/// @param dynamicId 动态的id -/// @param worldId 话题的id -/// @param uid 用户的uid + + (void)momentsDetail:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9kZXRhaWw="];///dynamic/detail + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9kZXRhaWw="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, worldId, uid, nil]; } -/// 评论动态 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 动态的id -/// @param content 内容 + + (void)momentDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3B1Ymxpc2g="];///dynamic/comment/publish + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3B1Ymxpc2g="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, dynamicId, content, nil]; } -/// 回复评论 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 动态的id -/// @param content 内容 -/// @param commentId 评论的id + + (void)replyMomentsDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content commentId:(NSString *)commentId { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3JlcGx5"];///dynamic/comment/reply + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3JlcGx5"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, dynamicId, content, commentId, nil]; } -/// 请求评论列表 -/// @param completion 完成 -/// @param dynamicId 动态id -/// @param uid uid -/// @param pageSize 一页多少个 -/// @param timestamp 上一个评论的时间戳 + (void)momentsCommentList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize timestamp:(NSString *)timestamp { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L2xpc3Q="];///dynamic/comment/list + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L2xpc3Q="]; NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:dynamicId forKey:@"dynamicId"]; [dic safeSetObject:uid forKey:@"uid"]; @@ -144,39 +89,21 @@ [HttpRequestHelper request:fang method:HttpRequestHelperMethodGET params:dic completion:completion]; } -/// 评论回复列表 -/// @param completion 完成 -/// @param dynamicId 动态id -/// @param uid uid -/// @param pageSize 每页多少个 -/// @param commentId 评论的id -/// @param timestamp 上条回复的时间 + + (void)momentsCommentReplyList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize commentId:(NSString *)commentId timestamp:(NSString *)timestamp { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3JlcGx5L2xpc3Q="];///dynamic/comment/reply/list + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3JlcGx5L2xpc3Q="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, uid, pageSize, commentId, timestamp, nil]; } -/// 获取可以选择的话题列表 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param type 类型 -/// @param page 当前的页数 + (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type page:(NSString *)page { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvd29ybGQ="];///dynamic/square/world + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvd29ybGQ="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, type, page, nil]; } -/// 发布动态 -/// @param completion 完成 -/// @param uid uid -/// @param type 类型 -/// @param worldId 话题的id -/// @param content 内容 -/// @param resList 发布的图片 + (void)momentsPublish:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type worldId:(NSString *)worldId content:(NSString *)content resList:(NSArray *)resList { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvcHVibGlzaA=="];///dynamic/square/publish + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvcHVibGlzaA=="]; NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:uid forKey:@"uid"]; [dic safeSetObject:type forKey:@"type"]; @@ -193,13 +120,6 @@ } -/// 获取动态话题最新记录 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 下一页动态的id -/// @param types l类型 -/// @param worldId 话题的id -/// @param pageSize 一页多少个 + (void)momentsTopicLatestList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize { NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:uid forKey:@"uid"]; @@ -209,17 +129,11 @@ if (dynamicId.length > 0) { [dic safeSetObject:dynamicId forKey:@"dynamicId"]; } - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9sYXRlc3RMaXN0"];///dynamic/latestList + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9sYXRlc3RMaXN0"]; [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; } -/// 获取动态话题推荐记录 -/// @param completion 完成 -/// @param uid 用户的uid -/// @param dynamicId 下一页动态的id -/// @param types l类型 -/// @param worldId 话题的id -/// @param pageSize 一页多少个 + + (void)momentsTopicRecommendList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize { NSMutableDictionary * dic = [NSMutableDictionary dictionary]; [dic safeSetObject:uid forKey:@"uid"]; @@ -229,39 +143,29 @@ if (dynamicId.length > 0) { [dic safeSetObject:dynamicId forKey:@"dynamicId"]; } - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9saXN0VjI="];///dynamic/listV2 + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9saXN0VjI="]; [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; } -/// 获取动态话题详情 -/// @param completion 完成 -/// @param worldId 话题id -/// @param uid 用户uid + + (void)momentsTopicDetailInfo:(HttpRequestHelperCompletion)completion worldId:(NSString *)worldId uid:(NSString *)uid{ - NSString * fang = [NSString stringFromBase64String:@"d29ybGQvZGV0YWls"];///world/detail + NSString * fang = [NSString stringFromBase64String:@"d29ybGQvZGV0YWls"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,worldId, uid, nil]; } -/// 删除动态 -/// @param completion 完成 -/// @param uid uid -/// @param dynamicId 动态的id -/// @param worldId 话题的id + + (void)momentsDelete:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9kZWxldGU="];///dynamic/delete + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9kZWxldGU="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, dynamicId, worldId, nil]; } -/// 获取动态没有阅读数 -/// @param completion 完成 -/// @param uid uid + + (void)momentsUnReadCount:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvdW5yZWFkQ291bnQ="];///interactive/unreadCount + NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvdW5yZWFkQ291bnQ="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, nil]; } -/// 屏蔽 -/// @param completion 完成 -/// @param type type为0 => 屏蔽动态, objId 为 动态id, type为1 => 屏蔽房间, objId 为 用户uid + + + (void)requestShielding:(HttpRequestHelperCompletion)completion type:(NSString *)type objId:(NSString *)objId{ [self makeRequest:[NSString stringWithFormat:@"%@%@%@",@"user/",@"black/",@"add"] method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, type,objId, nil]; } diff --git a/YuMi/Modules/YMMonents/Api/Api+Moments.m.backup b/YuMi/Modules/YMMonents/Api/Api+Moments.m.backup new file mode 100644 index 0000000..2a1927c --- /dev/null +++ b/YuMi/Modules/YMMonents/Api/Api+Moments.m.backup @@ -0,0 +1,268 @@ +// +// Api+Monents.m +// YUMI +// +// Created by YUMI on 2022/5/13. +// + +#import "Api+Moments.h" +#import "NSObject+MJExtension.h" +#import "NSMutableDictionary+Saft.h" +#import +@implementation Api (Moments) + +/// 朋友圈动态推荐列表 +/// @param completion 完成 +/// @param page 当前的页数 +/// @param pageSize 一页的个数 +/// @param types 类型 0,2 ++ (void)momentsRecommendList:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize types:(NSString *)types { + [self makeRequest:@"dynamic/square/recommendDynamics" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, types, nil]; +} + +/// 朋友圈动态最新列表 +/// @param completion 完成 +/// @param dynamicId 最新动态的id +/// @param pageSize 一页的个数 +/// @param types 类型 0,2 ++ (void)momentsLatestList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types { + [self makeRequest:@"dynamic/square/latestDynamics" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dynamicId, pageSize, types, nil]; +} + +/// 朋友圈动态关注列表 +/// @param completion 完成 +/// @param dynamicId 最新动态的id +/// @param pageSize 一页的个数 +/// @param types 类型 0,2 ++ (void)momentsFollowerList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvZm9sbG93ZXJEeW5hbWljcw=="];///dynamic/square/followerDynamics + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dynamicId, pageSize, types, nil]; +} + +/// 互动消息列表 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param pageSize 一页的个数 +/// @param uid 类型 uid ++ (void)momentsInteractiveList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvbGlzdA=="];///interactive/list + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + [dic safeSetObject:dynamicId forKey:@"id"]; + [dic safeSetObject:pageSize forKey:@"pageSize"]; + [dic safeSetObject:uid forKey:@"uid"]; + [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; +} + +/// 清空互动消息 +/// @param completion 完成 +/// @param uid 用户的uid ++ (void)momentsInteractiveClear:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvY2xlYXI="];///interactive/clear + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, nil]; +} + +/// 获取话题列表 +/// @param completion 完成 +/// @param uid uid +/// @param page 当前的页数 +/// @param pageSize 一页多少个 +/// @param worldTypeId 类型0 ++ (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize worldTypeId:(NSString *)worldTypeId { + NSString * fang = [NSString stringFromBase64String:@"d29ybGQvbGlzdA=="];///world/list + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, page, pageSize, worldTypeId, nil]; +} + +/// 分享动态 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param uid 动态发布者的uid +/// @param worldId 动态的话题id +/// @param shareUid 分享者的uid ++ (void)userShareMoments:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid worldId:(NSString *)worldId shareUid:(NSString *)shareUid { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zaGFyZQ=="];///dynamic/share + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, uid, worldId, shareUid, nil]; +} + +/// 点赞动态 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param uid 用户的uid +/// @param status 0 取消点赞 1 点赞 +/// @param likedUid 点赞人的uid +/// @param worldId 世界的id ++ (void)momentsLike:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid status:(NSString *)status likedUid:(NSString *)likedUid worldId:(NSString *)worldId { + [self makeRequest:@"dynamic/like" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, uid, status, likedUid, worldId, nil]; +} + +/// 动态详情 +/// @param completion 完成 +/// @param dynamicId 动态的id +/// @param worldId 话题的id +/// @param uid 用户的uid ++ (void)momentsDetail:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9kZXRhaWw="];///dynamic/detail + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, worldId, uid, nil]; +} + +/// 评论动态 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 动态的id +/// @param content 内容 ++ (void)momentDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3B1Ymxpc2g="];///dynamic/comment/publish + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, dynamicId, content, nil]; +} + +/// 回复评论 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 动态的id +/// @param content 内容 +/// @param commentId 评论的id ++ (void)replyMomentsDetailCommon:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId content:(NSString *)content commentId:(NSString *)commentId { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3JlcGx5"];///dynamic/comment/reply + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, dynamicId, content, commentId, nil]; +} + + +/// 请求评论列表 +/// @param completion 完成 +/// @param dynamicId 动态id +/// @param uid uid +/// @param pageSize 一页多少个 +/// @param timestamp 上一个评论的时间戳 ++ (void)momentsCommentList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize timestamp:(NSString *)timestamp { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L2xpc3Q="];///dynamic/comment/list + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + [dic safeSetObject:dynamicId forKey:@"dynamicId"]; + [dic safeSetObject:uid forKey:@"uid"]; + [dic safeSetObject:pageSize forKey:@"pageSize"]; + if (timestamp.length > 0) { + [dic safeSetObject:timestamp forKey:@"timestamp"]; + } + [HttpRequestHelper request:fang method:HttpRequestHelperMethodGET params:dic completion:completion]; +} + +/// 评论回复列表 +/// @param completion 完成 +/// @param dynamicId 动态id +/// @param uid uid +/// @param pageSize 每页多少个 +/// @param commentId 评论的id +/// @param timestamp 上条回复的时间 ++ (void)momentsCommentReplyList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId uid:(NSString *)uid pageSize:(NSString *)pageSize commentId:(NSString *)commentId timestamp:(NSString *)timestamp { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9jb21tZW50L3JlcGx5L2xpc3Q="];///dynamic/comment/reply/list + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dynamicId, uid, pageSize, commentId, timestamp, nil]; +} + + +/// 获取可以选择的话题列表 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param type 类型 +/// @param page 当前的页数 ++ (void)momentsTopicList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type page:(NSString *)page { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvd29ybGQ="];///dynamic/square/world + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, type, page, nil]; +} + + +/// 发布动态 +/// @param completion 完成 +/// @param uid uid +/// @param type 类型 +/// @param worldId 话题的id +/// @param content 内容 +/// @param resList 发布的图片 ++ (void)momentsPublish:(HttpRequestHelperCompletion)completion uid:(NSString *)uid type:(NSString *)type worldId:(NSString *)worldId content:(NSString *)content resList:(NSArray *)resList { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvcHVibGlzaA=="];///dynamic/square/publish + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + [dic safeSetObject:uid forKey:@"uid"]; + [dic safeSetObject:type forKey:@"type"]; + + [dic safeSetObject:content.length > 0 ? content : @"" forKey:@"content"]; + if (worldId.length > 0) { + [dic safeSetObject:worldId forKey:@"worldId"]; + } + if (resList.count > 0) { + [dic safeSetObject:resList forKey:@"resList"]; + } + + [HttpRequestHelper postSkillCard:fang params:dic.toJSONString completion:completion]; +} + + +/// 获取动态话题最新记录 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 下一页动态的id +/// @param types l类型 +/// @param worldId 话题的id +/// @param pageSize 一页多少个 ++ (void)momentsTopicLatestList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize { + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + [dic safeSetObject:uid forKey:@"uid"]; + [dic safeSetObject:types forKey:@"types"]; + [dic safeSetObject:worldId forKey:@"worldId"]; + [dic safeSetObject:pageSize forKey:@"pageSize"]; + if (dynamicId.length > 0) { + [dic safeSetObject:dynamicId forKey:@"dynamicId"]; + } + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9sYXRlc3RMaXN0"];///dynamic/latestList + [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; +} + +/// 获取动态话题推荐记录 +/// @param completion 完成 +/// @param uid 用户的uid +/// @param dynamicId 下一页动态的id +/// @param types l类型 +/// @param worldId 话题的id +/// @param pageSize 一页多少个 ++ (void)momentsTopicRecommendList:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId types:(NSString *)types worldId:(NSString *)worldId pageSize:(NSString *)pageSize { + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + [dic safeSetObject:uid forKey:@"uid"]; + [dic safeSetObject:types forKey:@"types"]; + [dic safeSetObject:worldId forKey:@"worldId"]; + [dic safeSetObject:pageSize forKey:@"pageSize"]; + if (dynamicId.length > 0) { + [dic safeSetObject:dynamicId forKey:@"dynamicId"]; + } + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9saXN0VjI="];///dynamic/listV2 + [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; +} + +/// 获取动态话题详情 +/// @param completion 完成 +/// @param worldId 话题id +/// @param uid 用户uid ++ (void)momentsTopicDetailInfo:(HttpRequestHelperCompletion)completion worldId:(NSString *)worldId uid:(NSString *)uid{ + NSString * fang = [NSString stringFromBase64String:@"d29ybGQvZGV0YWls"];///world/detail + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,worldId, uid, nil]; +} + +/// 删除动态 +/// @param completion 完成 +/// @param uid uid +/// @param dynamicId 动态的id +/// @param worldId 话题的id ++ (void)momentsDelete:(HttpRequestHelperCompletion)completion uid:(NSString *)uid dynamicId:(NSString *)dynamicId worldId:(NSString *)worldId { + NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9kZWxldGU="];///dynamic/delete + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, dynamicId, worldId, nil]; +} + +/// 获取动态没有阅读数 +/// @param completion 完成 +/// @param uid uid ++ (void)momentsUnReadCount:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"aW50ZXJhY3RpdmUvdW5yZWFkQ291bnQ="];///interactive/unreadCount + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, uid, nil]; +} +/// 屏蔽 +/// @param completion 完成 +/// @param type type为0 => 屏蔽动态, objId 为 动态id, type为1 => 屏蔽房间, objId 为 用户uid ++ (void)requestShielding:(HttpRequestHelperCompletion)completion type:(NSString *)type objId:(NSString *)objId{ + [self makeRequest:[NSString stringWithFormat:@"%@%@%@",@"user/",@"black/",@"add"] method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, type,objId, nil]; +} +@end diff --git a/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h index 365cc3d..8e091dc 100644 --- a/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h +++ b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h @@ -1,109 +1,107 @@ -// -// MonentsInfoModel.h -// xplan-ios -// + + // Created by 冯硕 on 2022/5/11. -// + #import NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, MonentsContentType) { - ///纯文字的 + MonentsContentType_Text = 0, - ///图片 + MomentsContentType_Picture = 2 }; @class MomentsPicInfoModel; @interface MomentsInfoModel : PIBaseModel -///类型 + @property (nonatomic,assign) MonentsContentType type; -///用户的uid + @property (nonatomic,copy) NSString *uid; -///昵称 + @property (nonatomic,copy) NSString *nick; -///身份的类型 + @property (nonatomic,assign) NSInteger defUser; -///是否是新用户 + @property (nonatomic,assign) BOOL newUser; -///性别 1:男 2:女 + @property (nonatomic,assign) NSInteger gender; -///头像 + @property (nonatomic,copy) NSString *avatar; -///年龄 + @property (nonatomic,assign) int age; -///内容 + @property (nonatomic,strong) NSString *content; -///喜欢的次数 + @property (nonatomic,copy) NSString *likeCount; -///我是否已经点赞 + @property (nonatomic, assign) BOOL isLike; -///评论的次数 + @property (nonatomic,copy) NSString *commentCount; -//发布时间 + @property (nonatomic,copy) NSString *publishTime; -///等级 + @property (nonatomic,strong) NSString *expertLevelPic; -///魅力等级 + @property (nonatomic,strong) NSString *charmLevelPic; -///广场是否置顶 + @property (nonatomic,assign) BOOL squareTop; -///话题是否置顶 + @property (nonatomic,assign) BOOL topicTop; -///VIP信息 + @property (nonatomic, strong) NSObject *userVipInfoVO; -///发布的内容 + @property (nonatomic,copy) NSArray *dynamicResList; -///头饰url地址 + @property (nonatomic,copy) NSString *headwearPic; -///头饰url地址 + @property (nonatomic,copy) NSString *headwearEffect; -///头饰类型, 1 = svga + @property (nonatomic, assign) NSInteger headwearType; -///是否在直播中 + @property (nonatomic,copy) NSString *inRoomUid; -///显示的标签 + @property (nonatomic,copy) NSArray *labelList; -///铭牌名称 + @property (nonatomic, copy) NSString *nameplateWord; -///铭牌图片 + @property (nonatomic, copy) NSString *nameplatePic; -///是否自定义铭牌, + @property(nonatomic,assign) BOOL isCustomWord; -///话题id + @property (nonatomic, assign) long worldId; -///话题名字 + @property (nonatomic, copy) NSString *worldName; -///动态的id + @property (nonatomic,copy) NSString *dynamicId; -///审核状态(0=审核中,1=通过,2=拒绝) + @property (nonatomic, assign) NSInteger status; -///情绪颜色(本地标注,Hex格式如 #FF0000) + @property (nonatomic, copy) NSString *emotionColor; -///是否是折叠起来的 + @property (nonatomic,assign) BOOL isFold; -///cell的高度 + @property (nonatomic,assign) CGFloat rowHeight; -///图片的高度 + @property (nonatomic,assign) CGFloat picHeight; -///文本内容的高度 + @property (nonatomic,assign) CGFloat contentHeight; -///显示的内容的富文本 + @property (nonatomic,strong) NSMutableAttributedString *contentAttribute; -///收起的 + @property (nonatomic,strong, nullable) NSMutableAttributedString *foldAttribute; -// 文本行数 + @property (nonatomic, assign) NSInteger numberOfText; @end @interface MomentsPicInfoModel : PIBaseModel -///图片的地址 + @property (nonatomic,copy) NSString * resUrl; -///格式 + @property (nonatomic,copy) NSString *format; -///宽度 + @property (nonatomic,assign) CGFloat width; -///高度 + @property (nonatomic,assign) CGFloat height; @end diff --git a/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h.backup b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h.backup new file mode 100644 index 0000000..365cc3d --- /dev/null +++ b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.h.backup @@ -0,0 +1,111 @@ +// +// MonentsInfoModel.h +// xplan-ios +// +// Created by 冯硕 on 2022/5/11. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, MonentsContentType) { + ///纯文字的 + MonentsContentType_Text = 0, + ///图片 + MomentsContentType_Picture = 2 +}; +@class MomentsPicInfoModel; +@interface MomentsInfoModel : PIBaseModel +///类型 +@property (nonatomic,assign) MonentsContentType type; +///用户的uid +@property (nonatomic,copy) NSString *uid; +///昵称 +@property (nonatomic,copy) NSString *nick; +///身份的类型 +@property (nonatomic,assign) NSInteger defUser; +///是否是新用户 +@property (nonatomic,assign) BOOL newUser; +///性别 1:男 2:女 +@property (nonatomic,assign) NSInteger gender; +///头像 +@property (nonatomic,copy) NSString *avatar; +///年龄 +@property (nonatomic,assign) int age; +///内容 +@property (nonatomic,strong) NSString *content; +///喜欢的次数 +@property (nonatomic,copy) NSString *likeCount; +///我是否已经点赞 +@property (nonatomic, assign) BOOL isLike; +///评论的次数 +@property (nonatomic,copy) NSString *commentCount; +//发布时间 +@property (nonatomic,copy) NSString *publishTime; +///等级 +@property (nonatomic,strong) NSString *expertLevelPic; +///魅力等级 +@property (nonatomic,strong) NSString *charmLevelPic; +///广场是否置顶 +@property (nonatomic,assign) BOOL squareTop; +///话题是否置顶 +@property (nonatomic,assign) BOOL topicTop; +///VIP信息 +@property (nonatomic, strong) NSObject *userVipInfoVO; +///发布的内容 +@property (nonatomic,copy) NSArray *dynamicResList; +///头饰url地址 +@property (nonatomic,copy) NSString *headwearPic; +///头饰url地址 +@property (nonatomic,copy) NSString *headwearEffect; +///头饰类型, 1 = svga +@property (nonatomic, assign) NSInteger headwearType; +///是否在直播中 +@property (nonatomic,copy) NSString *inRoomUid; +///显示的标签 +@property (nonatomic,copy) NSArray *labelList; +///铭牌名称 +@property (nonatomic, copy) NSString *nameplateWord; +///铭牌图片 +@property (nonatomic, copy) NSString *nameplatePic; +///是否自定义铭牌, +@property(nonatomic,assign) BOOL isCustomWord; +///话题id +@property (nonatomic, assign) long worldId; +///话题名字 +@property (nonatomic, copy) NSString *worldName; +///动态的id +@property (nonatomic,copy) NSString *dynamicId; +///审核状态(0=审核中,1=通过,2=拒绝) +@property (nonatomic, assign) NSInteger status; +///情绪颜色(本地标注,Hex格式如 #FF0000) +@property (nonatomic, copy) NSString *emotionColor; +///是否是折叠起来的 +@property (nonatomic,assign) BOOL isFold; +///cell的高度 +@property (nonatomic,assign) CGFloat rowHeight; +///图片的高度 +@property (nonatomic,assign) CGFloat picHeight; +///文本内容的高度 +@property (nonatomic,assign) CGFloat contentHeight; +///显示的内容的富文本 +@property (nonatomic,strong) NSMutableAttributedString *contentAttribute; +///收起的 +@property (nonatomic,strong, nullable) NSMutableAttributedString *foldAttribute; +// 文本行数 +@property (nonatomic, assign) NSInteger numberOfText; +@end + +@interface MomentsPicInfoModel : PIBaseModel +///图片的地址 +@property (nonatomic,copy) NSString * resUrl; +///格式 +@property (nonatomic,copy) NSString *format; +///宽度 +@property (nonatomic,assign) CGFloat width; +///高度 +@property (nonatomic,assign) CGFloat height; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m index 3c9fc2b..d878991 100644 --- a/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m +++ b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m @@ -1,9 +1,7 @@ -// -// MonentsInfoModel.m -// xplan-ios -// + + // Created by 冯硕 on 2022/5/11. -// + #import "MomentsInfoModel.h" #import "NSString+Utils.h" diff --git a/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m.backup b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m.backup new file mode 100644 index 0000000..3c9fc2b --- /dev/null +++ b/YuMi/Modules/YMMonents/Model/MomentsInfoModel.m.backup @@ -0,0 +1,28 @@ +// +// MonentsInfoModel.m +// xplan-ios +// +// Created by 冯硕 on 2022/5/11. +// + +#import "MomentsInfoModel.h" +#import "NSString+Utils.h" + +@implementation MomentsInfoModel +- (instancetype)init { + if (self = [super init]) { + self.isFold = YES; + } + return self; +} + ++ (NSDictionary *)objectClassInArray { + return @{@"dynamicResList":MomentsPicInfoModel.class}; +} +@end + + +@implementation MomentsPicInfoModel + + +@end diff --git a/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h index 56df6a5..cb86813 100644 --- a/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h +++ b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h @@ -1,18 +1,16 @@ -// -// MonentsListInfoModel.h -// YUMI -// + + // Created by YUMI on 2022/5/18. -// + #import #import "MomentsInfoModel.h" NS_ASSUME_NONNULL_BEGIN @interface MomentsListInfoModel : PIBaseModel -///列表数据 + @property (nonatomic,strong) NSArray *dynamicList; -///下一个动态的id + @property (nonatomic,copy) NSString *nextDynamicId; @end diff --git a/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h.backup b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h.backup new file mode 100644 index 0000000..56df6a5 --- /dev/null +++ b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.h.backup @@ -0,0 +1,19 @@ +// +// MonentsListInfoModel.h +// YUMI +// +// Created by YUMI on 2022/5/18. +// + +#import +#import "MomentsInfoModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface MomentsListInfoModel : PIBaseModel +///列表数据 +@property (nonatomic,strong) NSArray *dynamicList; +///下一个动态的id +@property (nonatomic,copy) NSString *nextDynamicId; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m index c4b445f..da4e114 100644 --- a/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m +++ b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m @@ -1,9 +1,7 @@ -// -// MonentsListInfoModel.m -// YUMI -// + + // Created by YUMI on 2022/5/18. -// + #import "MomentsListInfoModel.h" diff --git a/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m.backup b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m.backup new file mode 100644 index 0000000..c4b445f --- /dev/null +++ b/YuMi/Modules/YMMonents/Model/MomentsListInfoModel.m.backup @@ -0,0 +1,16 @@ +// +// MonentsListInfoModel.m +// YUMI +// +// Created by YUMI on 2022/5/18. +// + +#import "MomentsListInfoModel.h" + +@implementation MomentsListInfoModel + ++ (NSDictionary *)objectClassInArray { + return @{@"dynamicList":[MomentsInfoModel class]}; +} + +@end diff --git a/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h index 746cb4f..f9f56f0 100644 --- a/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h +++ b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h @@ -1,9 +1,7 @@ -// -// XPBlankRoomModel.h -// YuMi -// + + // Created by Linus on 2024/12/19. -// + #import diff --git a/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h.backup b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h.backup new file mode 100644 index 0000000..746cb4f --- /dev/null +++ b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.h.backup @@ -0,0 +1,16 @@ +// +// XPBlankRoomModel.h +// YuMi +// +// Created by Linus on 2024/12/19. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface XPBlankRoomModel : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m index 0a81cd8..c7a500d 100644 --- a/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m +++ b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m @@ -1,9 +1,7 @@ -// -// XPBlankRoomModel.m -// YuMi -// + + // Created by Linus on 2024/12/19. -// + #import "XPBlankRoomModel.h" diff --git a/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m.backup b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m.backup new file mode 100644 index 0000000..0a81cd8 --- /dev/null +++ b/YuMi/Modules/YMNewHome/View/Cell/XPBlankRoomModel.m.backup @@ -0,0 +1,12 @@ +// +// XPBlankRoomModel.m +// YuMi +// +// Created by Linus on 2024/12/19. +// + +#import "XPBlankRoomModel.h" + +@implementation XPBlankRoomModel + +@end diff --git a/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m b/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m index ceed369..ace85f7 100644 --- a/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m +++ b/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m @@ -1,14 +1,12 @@ -// -// BannerSchedulerTest.m -// YuMi -// + + // Created by AI Assistant on 2025/1/13. -// + #import #import "BannerScheduler.h" -// 模拟的 Banner 数据类 + @interface MockBanner : NSObject @property (nonatomic, assign) NSInteger type; @property (nonatomic, strong) NSDictionary *data; @@ -17,7 +15,7 @@ @implementation MockBanner @end -// 模拟的代理类 + @interface MockBannerSchedulerDelegate : NSObject @property (nonatomic, strong) NSMutableArray *playedBanners; @property (nonatomic, strong) NSMutableArray *startedBanners; @@ -39,7 +37,7 @@ [self.playedBanners addObject:banner]; NSLog(@"🧪 MockDelegate: 收到播放 Banner 请求 - 类型: %@", [banner class]); - // 模拟播放完成后通知调度器 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [scheduler markBannerFinished]; }); @@ -106,7 +104,7 @@ } - (void)testQueueSorting { - // 创建多个 Banner 并测试排序功能 + MockBanner *banner1 = [[MockBanner alloc] init]; banner1.type = 1; banner1.data = @{@"uidList": @[@"user1"], @"roomUid": @"room1"}; @@ -118,7 +116,7 @@ [self.scheduler enqueueBanner:banner1]; [self.scheduler enqueueBanner:banner2]; - // 等待播放完成 + XCTestExpectation *expectation = [self expectationWithDescription:@"等待播放完成"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [expectation fulfill]; @@ -135,11 +133,11 @@ [self.scheduler enqueueBanner:banner]; - // 暂停 + [self.scheduler pause]; XCTAssertTrue(self.scheduler.isPaused, @"应该处于暂停状态"); - // 恢复 + [self.scheduler resume]; XCTAssertFalse(self.scheduler.isPaused, @"应该不处于暂停状态"); } diff --git a/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m.backup b/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m.backup new file mode 100644 index 0000000..ceed369 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/AnimationView/BannerSchedulerTest.m.backup @@ -0,0 +1,174 @@ +// +// BannerSchedulerTest.m +// YuMi +// +// Created by AI Assistant on 2025/1/13. +// + +#import +#import "BannerScheduler.h" + +// 模拟的 Banner 数据类 +@interface MockBanner : NSObject +@property (nonatomic, assign) NSInteger type; +@property (nonatomic, strong) NSDictionary *data; +@end + +@implementation MockBanner +@end + +// 模拟的代理类 +@interface MockBannerSchedulerDelegate : NSObject +@property (nonatomic, strong) NSMutableArray *playedBanners; +@property (nonatomic, strong) NSMutableArray *startedBanners; +@property (nonatomic, assign) NSInteger finishCount; +@end + +@implementation MockBannerSchedulerDelegate + +- (instancetype)init { + if (self = [super init]) { + _playedBanners = [NSMutableArray array]; + _startedBanners = [NSMutableArray array]; + _finishCount = 0; + } + return self; +} + +- (void)bannerScheduler:(BannerScheduler *)scheduler shouldPlayBanner:(id)banner { + [self.playedBanners addObject:banner]; + NSLog(@"🧪 MockDelegate: 收到播放 Banner 请求 - 类型: %@", [banner class]); + + // 模拟播放完成后通知调度器 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [scheduler markBannerFinished]; + }); +} + +- (void)bannerSchedulerDidFinishPlaying:(BannerScheduler *)scheduler { + self.finishCount++; + NSLog(@"🧪 MockDelegate: Banner 播放完成 - 完成次数: %ld", (long)self.finishCount); +} + +- (void)bannerScheduler:(BannerScheduler *)scheduler didStartPlayingBanner:(id)banner { + [self.startedBanners addObject:banner]; + NSLog(@"🧪 MockDelegate: Banner 开始播放 - 类型: %@", [banner class]); +} + +@end + +@interface BannerSchedulerTest : XCTestCase +@property (nonatomic, strong) BannerScheduler *scheduler; +@property (nonatomic, strong) MockBannerSchedulerDelegate *mockDelegate; +@end + +@implementation BannerSchedulerTest + +- (void)setUp { + [super setUp]; + self.mockDelegate = [[MockBannerSchedulerDelegate alloc] init]; + self.scheduler = [[BannerScheduler alloc] initWithDelegate:self.mockDelegate]; +} + +- (void)tearDown { + self.scheduler = nil; + self.mockDelegate = nil; + [super tearDown]; +} + +- (void)testInitialization { + XCTAssertNotNil(self.scheduler, @"调度器应该被正确初始化"); + XCTAssertEqual(self.scheduler.queueCount, 0, @"初始队列应该为空"); + XCTAssertFalse(self.scheduler.isPlaying, @"初始状态应该不是播放中"); +} + +- (void)testEnqueueBanner { + MockBanner *banner = [[MockBanner alloc] init]; + banner.type = 1; + + [self.scheduler enqueueBanner:banner]; + + XCTAssertEqual(self.scheduler.queueCount, 1, @"队列应该包含一个 Banner"); + XCTAssertTrue(self.scheduler.isPlaying, @"应该开始播放"); +} + +- (void)testMultipleBanners { + MockBanner *banner1 = [[MockBanner alloc] init]; + banner1.type = 1; + + MockBanner *banner2 = [[MockBanner alloc] init]; + banner2.type = 2; + + [self.scheduler enqueueBanner:banner1]; + [self.scheduler enqueueBanner:banner2]; + + XCTAssertEqual(self.scheduler.queueCount, 2, @"队列应该包含两个 Banner"); +} + +- (void)testQueueSorting { + // 创建多个 Banner 并测试排序功能 + MockBanner *banner1 = [[MockBanner alloc] init]; + banner1.type = 1; + banner1.data = @{@"uidList": @[@"user1"], @"roomUid": @"room1"}; + + MockBanner *banner2 = [[MockBanner alloc] init]; + banner2.type = 2; + banner2.data = @{@"uidList": @[@"user2"], @"roomUid": @"room2"}; + + [self.scheduler enqueueBanner:banner1]; + [self.scheduler enqueueBanner:banner2]; + + // 等待播放完成 + XCTestExpectation *expectation = [self expectationWithDescription:@"等待播放完成"]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:2.0 handler:nil]; + + XCTAssertEqual(self.mockDelegate.playedBanners.count, 2, @"应该播放了两个 Banner"); +} + +- (void)testPauseAndResume { + MockBanner *banner = [[MockBanner alloc] init]; + banner.type = 1; + + [self.scheduler enqueueBanner:banner]; + + // 暂停 + [self.scheduler pause]; + XCTAssertTrue(self.scheduler.isPaused, @"应该处于暂停状态"); + + // 恢复 + [self.scheduler resume]; + XCTAssertFalse(self.scheduler.isPaused, @"应该不处于暂停状态"); +} + +- (void)testClearQueue { + MockBanner *banner1 = [[MockBanner alloc] init]; + banner1.type = 1; + + MockBanner *banner2 = [[MockBanner alloc] init]; + banner2.type = 2; + + [self.scheduler enqueueBanner:banner1]; + [self.scheduler enqueueBanner:banner2]; + + XCTAssertEqual(self.scheduler.queueCount, 2, @"队列应该包含两个 Banner"); + + [self.scheduler clearQueue]; + XCTAssertEqual(self.scheduler.queueCount, 0, @"队列应该被清空"); +} + +- (void)testQueueStatusDescription { + MockBanner *banner = [[MockBanner alloc] init]; + banner.type = 1; + + [self.scheduler enqueueBanner:banner]; + + NSString *status = [self.scheduler queueStatusDescription]; + XCTAssertNotNil(status, @"状态描述不应该为空"); + XCTAssertTrue([status containsString:@"BannerScheduler 状态"], @"状态描述应该包含标题"); +} + +@end diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h index 25441f5..9710577 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h @@ -1,39 +1,26 @@ -// -// XPTextLayoutTest.h -// YuMi -// + + // Created by Assistant on 2024/12/19. // Copyright © 2024 YuMi. All rights reserved. -// + #import NS_ASSUME_NONNULL_BEGIN -/** - * 文本布局测试类 - * 用于验证统一文本尺寸计算的实现效果 - */ + @interface XPTextLayoutTest : NSObject -/** - * 测试纯阿拉伯文本的布局计算 - */ + + (void)testArabicTextLayout; -/** - * 测试混合文本(英文+阿拉伯文)的布局计算 - */ + + (void)testMixedTextLayout; -/** - * 测试长阿拉伯文本的布局计算 - */ + + (void)testLongArabicTextLayout; -/** - * 运行所有测试 - */ + + (void)runAllTests; @end diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h.backup b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h.backup new file mode 100644 index 0000000..25441f5 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.h.backup @@ -0,0 +1,41 @@ +// +// XPTextLayoutTest.h +// YuMi +// +// Created by Assistant on 2024/12/19. +// Copyright © 2024 YuMi. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * 文本布局测试类 + * 用于验证统一文本尺寸计算的实现效果 + */ +@interface XPTextLayoutTest : NSObject + +/** + * 测试纯阿拉伯文本的布局计算 + */ ++ (void)testArabicTextLayout; + +/** + * 测试混合文本(英文+阿拉伯文)的布局计算 + */ ++ (void)testMixedTextLayout; + +/** + * 测试长阿拉伯文本的布局计算 + */ ++ (void)testLongArabicTextLayout; + +/** + * 运行所有测试 + */ ++ (void)runAllTests; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m index 8f2726f..158c49e 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m @@ -1,10 +1,8 @@ -// -// XPTextLayoutTest.m -// YuMi -// + + // Created by Assistant on 2024/12/19. // Copyright © 2024 YuMi. All rights reserved. -// + #import #import "XPNetImageYYLabel.h" @@ -23,7 +21,7 @@ + (void)testArabicTextLayout { NSLog(@"=== 测试纯阿拉伯文本布局 ==="); - // 创建阿拉伯文本 + NSString *arabicText = @"مرحبا بك في تطبيق YuMi"; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:arabicText attributes:@{ @@ -31,7 +29,7 @@ NSForegroundColorAttributeName: [UIColor blackColor] }]; - // 测试 XPNetImageYYLabel + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; __block CGSize labelSize = CGSizeZero; label.updateLayoutSize = ^(CGSize size) { @@ -40,7 +38,7 @@ }; [label updateLayoutWithAttributedText:attributedText]; - // 测试 XPMessageInfoModel + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; [model setContent:attributedText]; NSLog(@"XPMessageInfoModel 计算高度: %.2f", model.rowHeight); @@ -51,7 +49,7 @@ + (void)testMixedTextLayout { NSLog(@"=== 测试混合文本布局 ==="); - // 创建混合文本(英文+阿拉伯文) + NSString *mixedText = @"Hello مرحبا World عالم"; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:mixedText attributes:@{ @@ -59,7 +57,7 @@ NSForegroundColorAttributeName: [UIColor blackColor] }]; - // 测试 XPNetImageYYLabel + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; __block CGSize labelSize = CGSizeZero; label.updateLayoutSize = ^(CGSize size) { @@ -68,7 +66,7 @@ }; [label updateLayoutWithAttributedText:attributedText]; - // 测试 XPMessageInfoModel + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; [model setContent:attributedText]; NSLog(@"XPMessageInfoModel 计算高度: %.2f", model.rowHeight); @@ -79,7 +77,7 @@ + (void)testLongArabicTextLayout { NSLog(@"=== 测试长阿拉伯文本布局 ==="); - // 创建长阿拉伯文本 + NSString *longArabicText = @"هذا نص طويل باللغة العربية لاختبار كيفية تعامل النظام مع النصوص الطويلة التي تحتاج إلى عدة أسطر للعرض. يجب أن يتم عرض هذا النص بشكل صحيح مع دعم الاتجاه من اليمين إلى اليسار."; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:longArabicText attributes:@{ @@ -87,7 +85,7 @@ NSForegroundColorAttributeName: [UIColor blackColor] }]; - // 测试 XPNetImageYYLabel + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; __block CGSize labelSize = CGSizeZero; label.updateLayoutSize = ^(CGSize size) { @@ -96,7 +94,7 @@ }; [label updateLayoutWithAttributedText:attributedText]; - // 测试 XPMessageInfoModel + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; [model setContent:attributedText]; NSLog(@"XPMessageInfoModel 计算高度: %.2f", model.rowHeight); diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m.backup b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m.backup new file mode 100644 index 0000000..8f2726f --- /dev/null +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/Test/XPTextLayoutTest.m.backup @@ -0,0 +1,117 @@ +// +// XPTextLayoutTest.m +// YuMi +// +// Created by Assistant on 2024/12/19. +// Copyright © 2024 YuMi. All rights reserved. +// + +#import +#import "XPNetImageYYLabel.h" +#import "XPMessageInfoModel.h" + +@interface XPTextLayoutTest : NSObject + ++ (void)testArabicTextLayout; ++ (void)testMixedTextLayout; ++ (void)testLongArabicTextLayout; + +@end + +@implementation XPTextLayoutTest + ++ (void)testArabicTextLayout { + NSLog(@"=== 测试纯阿拉伯文本布局 ==="); + + // 创建阿拉伯文本 + NSString *arabicText = @"مرحبا بك في تطبيق YuMi"; + NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:arabicText + attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:16], + NSForegroundColorAttributeName: [UIColor blackColor] + }]; + + // 测试 XPNetImageYYLabel + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + __block CGSize labelSize = CGSizeZero; + label.updateLayoutSize = ^(CGSize size) { + labelSize = size; + NSLog(@"XPNetImageYYLabel 计算尺寸: %.2f x %.2f", size.width, size.height); + }; + [label updateLayoutWithAttributedText:attributedText]; + + // 测试 XPMessageInfoModel + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + [model setContent:attributedText]; + NSLog(@"XPMessageInfoModel 计算高度: %.2f", model.rowHeight); + + NSLog(@"=== 阿拉伯文本测试完成 ===\n"); +} + ++ (void)testMixedTextLayout { + NSLog(@"=== 测试混合文本布局 ==="); + + // 创建混合文本(英文+阿拉伯文) + NSString *mixedText = @"Hello مرحبا World عالم"; + NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:mixedText + attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:16], + NSForegroundColorAttributeName: [UIColor blackColor] + }]; + + // 测试 XPNetImageYYLabel + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + __block CGSize labelSize = CGSizeZero; + label.updateLayoutSize = ^(CGSize size) { + labelSize = size; + NSLog(@"XPNetImageYYLabel 计算尺寸: %.2f x %.2f", size.width, size.height); + }; + [label updateLayoutWithAttributedText:attributedText]; + + // 测试 XPMessageInfoModel + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + [model setContent:attributedText]; + NSLog(@"XPMessageInfoModel 计算高度: %.2f", model.rowHeight); + + NSLog(@"=== 混合文本测试完成 ===\n"); +} + ++ (void)testLongArabicTextLayout { + NSLog(@"=== 测试长阿拉伯文本布局 ==="); + + // 创建长阿拉伯文本 + NSString *longArabicText = @"هذا نص طويل باللغة العربية لاختبار كيفية تعامل النظام مع النصوص الطويلة التي تحتاج إلى عدة أسطر للعرض. يجب أن يتم عرض هذا النص بشكل صحيح مع دعم الاتجاه من اليمين إلى اليسار."; + NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:longArabicText + attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:16], + NSForegroundColorAttributeName: [UIColor blackColor] + }]; + + // 测试 XPNetImageYYLabel + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + __block CGSize labelSize = CGSizeZero; + label.updateLayoutSize = ^(CGSize size) { + labelSize = size; + NSLog(@"XPNetImageYYLabel 计算尺寸: %.2f x %.2f", size.width, size.height); + }; + [label updateLayoutWithAttributedText:attributedText]; + + // 测试 XPMessageInfoModel + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + [model setContent:attributedText]; + NSLog(@"XPMessageInfoModel 计算高度: %.2f", model.rowHeight); + + NSLog(@"=== 长阿拉伯文本测试完成 ===\n"); +} + ++ (void)runAllTests { + NSLog(@"\n🚀 开始运行文本布局统一测试\n"); + + [self testArabicTextLayout]; + [self testMixedTextLayout]; + [self testLongArabicTextLayout]; + + NSLog(@"✅ 所有文本布局测试完成\n"); +} + +@end \ No newline at end of file diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h index fbf21d6..b5047aa 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h @@ -1,10 +1,8 @@ -// -// XPTextLayoutTest.h -// YuMi -// + + // Created by Assistant on 2025/8/14. // Copyright © 2025 YuMi. All rights reserved. -// + #import diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h.backup b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h.backup new file mode 100644 index 0000000..fbf21d6 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.h.backup @@ -0,0 +1,26 @@ +// +// XPTextLayoutTest.h +// YuMi +// +// Created by Assistant on 2025/8/14. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface XPTextLayoutTest : NSObject + ++ (void)testArabicTextLayout; ++ (void)testMixedTextLayout; ++ (void)testLongArabicTextLayout; ++ (void)testChineseTextLayout; ++ (void)testEnglishTextLayout; ++ (void)testTurkishTextLayout; ++ (void)testVeryLongTextLayout; ++ (void)runAllTests; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m index 2b8444f..cde61be 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m @@ -1,10 +1,8 @@ -// -// XPTextLayoutTest.m -// YuMi -// + + // Created by Assistant on 2025/8/14. // Copyright © 2025 YuMi. All rights reserved. -// + #import "XPTextLayoutTest.h" #import "XPNetImageYYLabel.h" diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m.backup b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m.backup new file mode 100644 index 0000000..2b8444f --- /dev/null +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/XPTextLayoutTest.m.backup @@ -0,0 +1,166 @@ +// +// XPTextLayoutTest.m +// YuMi +// +// Created by Assistant on 2025/8/14. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "XPTextLayoutTest.h" +#import "XPNetImageYYLabel.h" +#import "XPMessageInfoModel.h" + +@implementation XPTextLayoutTest + ++ (void)testArabicTextLayout { + NSLog(@"=== 测试阿拉伯文本布局 ==="); + + NSString *arabicText = @"هذا نص عربي طويل لاختبار تخطيط النص. يجب أن يظهر النص بشكل صحيح دون قطع أو مشاكل في العرض."; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:arabicText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, arabicText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"阿拉伯文本: %@", arabicText); + NSLog(@"文本长度: %lu", (unsigned long)arabicText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)testMixedTextLayout { + NSLog(@"=== 测试混合文本布局 ==="); + + NSString *mixedText = @"Hello مرحبا 你好 This is mixed text with English, Arabic, and Chinese characters."; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:mixedText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, mixedText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"混合文本: %@", mixedText); + NSLog(@"文本长度: %lu", (unsigned long)mixedText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)testLongArabicTextLayout { + NSLog(@"=== 测试长阿拉伯文本布局 ==="); + + NSString *longArabicText = @"هذا نص عربي طويل جداً يحتوي على عدة جمل لاختبار كيفية تعامل نظام تخطيط النص مع النصوص الطويلة. يجب أن يظهر النص بالكامل دون أي قطع أو مشاكل في العرض. هذا اختبار مهم للتأكد من أن النظام يعمل بشكل صحيح مع النصوص العربية الطويلة."; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:longArabicText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, longArabicText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"长阿拉伯文本: %@", longArabicText); + NSLog(@"文本长度: %lu", (unsigned long)longArabicText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)testChineseTextLayout { + NSLog(@"=== 测试中文文本布局 ==="); + + NSString *chineseText = @"这是一段很长的中文文本,用来测试文本布局是否正确显示,不会出现截断的问题。这段文本包含了多个句子,应该能够完整显示所有内容,而不会在尾部被意外截断。"; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:chineseText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, chineseText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"中文文本: %@", chineseText); + NSLog(@"文本长度: %lu", (unsigned long)chineseText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)testEnglishTextLayout { + NSLog(@"=== 测试英文文本布局 ==="); + + NSString *englishText = @"This is a very long English text to test whether the text layout displays correctly without truncation issues. This text contains multiple sentences and should be able to display all content completely without being unexpectedly truncated at the end."; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:englishText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, englishText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"英文文本: %@", englishText); + NSLog(@"文本长度: %lu", (unsigned long)englishText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)testTurkishTextLayout { + NSLog(@"=== 测试土耳其文文本布局 ==="); + + NSString *turkishText = @"Bu, metin düzeninin doğru şekilde görüntülenip görüntülenmediğini ve kesme sorunları olmadığını test etmek için çok uzun bir Türkçe metindir. Bu metin birden fazla cümle içerir ve tüm içeriği tamamen görüntüleyebilmeli, sonunda beklenmedik şekilde kesilmemelidir."; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:turkishText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, turkishText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"土耳其文文本: %@", turkishText); + NSLog(@"文本长度: %lu", (unsigned long)turkishText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)testVeryLongTextLayout { + NSLog(@"=== 测试超长文本布局 ==="); + + NSString *veryLongText = @"这是一段非常非常长的文本,包含了中文、English、العربية、Türkçe等多种语言混合的内容。这段文本的目的是测试在极长文本情况下,文本布局系统是否能够正确处理,不会出现截断、显示不全或者其他布局问题。文本应该能够完整显示,每一个字符都不应该丢失。This text is designed to test the text layout system under extreme conditions with very long content. The system should handle this gracefully without any truncation or display issues. كل حرف يجب أن يظهر بشكل صحيح. Bu metin çok uzun ve karmaşık bir test senaryosudur."; + + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:veryLongText]; + [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, veryLongText.length)]; + + XPNetImageYYLabel *label = [[XPNetImageYYLabel alloc] init]; + [label updateLayoutWithAttributedText:attributedText]; + + XPMessageInfoModel *model = [[XPMessageInfoModel alloc] init]; + model.content = attributedText; + + NSLog(@"超长文本: %@", veryLongText); + NSLog(@"文本长度: %lu", (unsigned long)veryLongText.length); + NSLog(@"计算的行高: %.2f", model.rowHeight); +} + ++ (void)runAllTests { + NSLog(@"\n\n=== 开始文本布局测试 ==="); + [self testArabicTextLayout]; + NSLog(@"\n"); + [self testMixedTextLayout]; + NSLog(@"\n"); + [self testLongArabicTextLayout]; + NSLog(@"\n"); + [self testChineseTextLayout]; + NSLog(@"\n"); + [self testEnglishTextLayout]; + NSLog(@"\n"); + [self testTurkishTextLayout]; + NSLog(@"\n"); + [self testVeryLongTextLayout]; + NSLog(@"\n=== 文本布局测试完成 ===\n\n"); +} + +@end \ No newline at end of file diff --git a/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h b/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h index 7b889a7..bd47efc 100644 --- a/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h +++ b/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h @@ -1,9 +1,7 @@ -// -// XPRoomBackCleanMessagesAction.h -// YuMi -// + + // Created by P on 2025/9/1. -// + #import "XPRoomMoreMenuAction.h" diff --git a/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h.backup b/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h.backup new file mode 100644 index 0000000..7b889a7 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/MoreView/Action/XPRoomBackCleanMessagesAction.h.backup @@ -0,0 +1,16 @@ +// +// XPRoomBackCleanMessagesAction.h +// YuMi +// +// Created by P on 2025/9/1. +// + +#import "XPRoomMoreMenuAction.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPRoomCleanMessagesAction : XPRoomMoreMenuAction ++ (instancetype)action; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h index c9aebc9..7fd46c4 100644 --- a/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h +++ b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h @@ -1,24 +1,22 @@ -// -// ThemeColor+RoomRank.h -// xplan-ios -// + + // Created by 冯硕 on 2021/12/14. -// + #import "ThemeColor.h" NS_ASSUME_NONNULL_BEGIN @interface ThemeColor (RoomRank) -/// 房间榜单标题背景颜色 0xFFFFFF 0.2 + + (UIColor *)roomRankTitleBackColor; -/// 房间榜单标题选中颜色 0x7898F3 + + (UIColor *)roomRankSelectTitleColor; -/// 房间榜单标题普通颜色 0xFFFFFF 0.6 + + (UIColor *)roomRankNormalTitleColor; -/// 房间榜单积分的字体的颜色 0xFF7979 + + (UIColor *)roomRankIntegralColor; -/// 房间榜单名字的字体的颜色 0xFFFFFF + + (UIColor *)roomRankNickColor; @end diff --git a/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h.backup b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h.backup new file mode 100644 index 0000000..c9aebc9 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.h.backup @@ -0,0 +1,25 @@ +// +// ThemeColor+RoomRank.h +// xplan-ios +// +// Created by 冯硕 on 2021/12/14. +// + +#import "ThemeColor.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ThemeColor (RoomRank) +/// 房间榜单标题背景颜色 0xFFFFFF 0.2 ++ (UIColor *)roomRankTitleBackColor; +/// 房间榜单标题选中颜色 0x7898F3 ++ (UIColor *)roomRankSelectTitleColor; +/// 房间榜单标题普通颜色 0xFFFFFF 0.6 ++ (UIColor *)roomRankNormalTitleColor; +/// 房间榜单积分的字体的颜色 0xFF7979 ++ (UIColor *)roomRankIntegralColor; +/// 房间榜单名字的字体的颜色 0xFFFFFF ++ (UIColor *)roomRankNickColor; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m index ff5e825..e05f190 100644 --- a/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m +++ b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m @@ -1,40 +1,36 @@ -// -// ThemeColor+RoomRank.m -// xplan-ios -// + + // Created by 冯硕 on 2021/12/14. -// + #import "ThemeColor+RoomRank.h" @implementation ThemeColor (RoomRank) -/// 房间榜单标题背景颜色 0xFFFFFF 0.2 + (UIColor *)roomRankTitleBackColor { return UIColorRGBAlpha(0xFFFFFF, 0.2); } -/// 房间榜单标题选中颜色 0x7898F3 + + (UIColor *)roomRankSelectTitleColor { return UIColorFromRGB(0x7898F3); } -/// 房间榜单标题普通颜色 0xFFFFFF 0.6 + + (UIColor *)roomRankNormalTitleColor { return UIColorRGBAlpha(0xFFFFFF, 0.6); } -/// 房间榜单积分的字体的颜色 0xFF7979 + + (UIColor *)roomRankIntegralColor { return UIColorFromRGB(0xFF7979); } -/// 房间榜单名字的字体的颜色 0xFFFFFF + + (UIColor *)roomRankNickColor { return UIColorFromRGB(0xFFFFFF); } - @end diff --git a/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m.backup b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m.backup new file mode 100644 index 0000000..ff5e825 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/RoomRank/ThemeColor+RoomRank.m.backup @@ -0,0 +1,40 @@ +// +// ThemeColor+RoomRank.m +// xplan-ios +// +// Created by 冯硕 on 2021/12/14. +// + +#import "ThemeColor+RoomRank.h" + +@implementation ThemeColor (RoomRank) + + +/// 房间榜单标题背景颜色 0xFFFFFF 0.2 ++ (UIColor *)roomRankTitleBackColor { + return UIColorRGBAlpha(0xFFFFFF, 0.2); +} + +/// 房间榜单标题选中颜色 0x7898F3 ++ (UIColor *)roomRankSelectTitleColor { + return UIColorFromRGB(0x7898F3); +} + +/// 房间榜单标题普通颜色 0xFFFFFF 0.6 ++ (UIColor *)roomRankNormalTitleColor { + return UIColorRGBAlpha(0xFFFFFF, 0.6); +} + +/// 房间榜单积分的字体的颜色 0xFF7979 ++ (UIColor *)roomRankIntegralColor { + return UIColorFromRGB(0xFF7979); +} + +/// 房间榜单名字的字体的颜色 0xFFFFFF ++ (UIColor *)roomRankNickColor { + return UIColorFromRGB(0xFFFFFF); +} + + + +@end diff --git a/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m b/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m index d2703a1..dd2a26d 100644 --- a/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m +++ b/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m @@ -1,29 +1,27 @@ -// -// XPRoomRankTableViewCell.m -// xplan-ios -// + + // Created by 冯硕 on 2021/12/14. -// + #import "XPRoomRankTableViewCell.h" -///Third + #import -///Tool + #import "ThemeColor+RoomRank.h" #import "NetImageView.h" #import "RoomRankModel.h" @interface XPRoomRankTableViewCell () -///排名 + @property (nonatomic, strong) UILabel *rankLabel; -///头像 + @property (nonatomic, strong) NetImageView *avatarImageView; -///性别 + @property (nonatomic, strong) UIImageView *genderImageView; -///昵称 + @property (nonatomic, strong) UILabel *nickNameLabel; -///ID + @property (nonatomic, strong) UILabel *idLabel; -///金币数量 + @property (nonatomic, strong) UILabel *coinNumberLabel; @end @@ -34,7 +32,7 @@ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { self.autoresizingMask = UIViewAutoresizingNone; - self.selectionStyle = UITableViewCellSelectionStyleNone;//被选中的样式 + self.selectionStyle = UITableViewCellSelectionStyleNone; [self setupSubView]; [self setupConstraints]; } @@ -101,7 +99,7 @@ numStr = [NSString stringWithFormat:YMLocalizedString(@"XPRoomRankTableViewCell0"),numF]; numStr = [numStr stringByReplacingOccurrencesOfString:@".0" withString:@""]; } - self.genderImageView.image = rankModel.gender == 2 ? [UIImage imageNamed:@"common_female"] : [UIImage imageNamed:@"common_male"]; // 2:女 1:男 + self.genderImageView.image = rankModel.gender == 2 ? [UIImage imageNamed:@"common_female"] : [UIImage imageNamed:@"common_male"]; self.coinNumberLabel.text = numStr; self.avatarImageView.imageUrl = rankModel.avatar; self.nickNameLabel.text = rankModel.nick; diff --git a/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m.backup b/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m.backup new file mode 100644 index 0000000..d2703a1 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/RoomRank/View/Cell/XPRoomRankTableViewCell.m.backup @@ -0,0 +1,173 @@ +// +// XPRoomRankTableViewCell.m +// xplan-ios +// +// Created by 冯硕 on 2021/12/14. +// + +#import "XPRoomRankTableViewCell.h" +///Third +#import +///Tool +#import "ThemeColor+RoomRank.h" +#import "NetImageView.h" +#import "RoomRankModel.h" +@interface XPRoomRankTableViewCell () +///排名 +@property (nonatomic, strong) UILabel *rankLabel; +///头像 +@property (nonatomic, strong) NetImageView *avatarImageView; +///性别 +@property (nonatomic, strong) UIImageView *genderImageView; +///昵称 +@property (nonatomic, strong) UILabel *nickNameLabel; +///ID +@property (nonatomic, strong) UILabel *idLabel; +///金币数量 +@property (nonatomic, strong) UILabel *coinNumberLabel; +@end + +@implementation XPRoomRankTableViewCell + + +#pragma mark - Life Style +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.autoresizingMask = UIViewAutoresizingNone; + self.selectionStyle = UITableViewCellSelectionStyleNone;//被选中的样式 + [self setupSubView]; + [self setupConstraints]; + } + return self; +} + +#pragma mark - Private +- (void)setupSubView { + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self.contentView addSubview:self.rankLabel]; + [self.contentView addSubview:self.avatarImageView]; + [self.contentView addSubview:self.nickNameLabel]; + [self.contentView addSubview:self.genderImageView]; + [self.contentView addSubview:self.idLabel]; + [self.contentView addSubview:self.coinNumberLabel]; +} +- (void)setupConstraints{ + [self.rankLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(15); + make.centerY.mas_equalTo(0); + make.width.mas_equalTo(50); + make.height.mas_equalTo(20); + }]; + + [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.height.equalTo(@50); + make.left.equalTo(self.rankLabel.mas_right).offset(10); + make.centerY.equalTo(self.contentView); + }]; + + [self.nickNameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(self.avatarImageView.mas_right).offset(16); + make.bottom.mas_equalTo(self.avatarImageView.mas_centerY).offset(-1.5); + }]; + + [self.genderImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(self.nickNameLabel.mas_right).offset(3); + make.centerY.mas_equalTo(self.nickNameLabel); + make.width.height.mas_equalTo(13); + }]; + + [self.idLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.avatarImageView.mas_centerY).offset(1.5); + make.left.mas_equalTo(self.nickNameLabel); + make.right.mas_lessThanOrEqualTo(self.coinNumberLabel.mas_left).offset(-10); + }]; + + [self.coinNumberLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(0); + make.right.mas_equalTo(-28); + }]; +} + + +- (void)setRankModel:(RoomRankModel *)rankModel { + _rankModel = rankModel; + self.idLabel.text = [NSString stringWithFormat:@"ID:%@", rankModel.erbanNo]; + + self.rankLabel.text = rankModel.ranking; + + NSString *numStr = [NSString stringWithFormat:@"%@",rankModel.goldAmount]; + if (rankModel.goldAmount.doubleValue > 10000) { + CGFloat numF = [rankModel.goldAmount doubleValue] / 10000.0; + numStr = [NSString stringWithFormat:YMLocalizedString(@"XPRoomRankTableViewCell0"),numF]; + numStr = [numStr stringByReplacingOccurrencesOfString:@".0" withString:@""]; + } + self.genderImageView.image = rankModel.gender == 2 ? [UIImage imageNamed:@"common_female"] : [UIImage imageNamed:@"common_male"]; // 2:女 1:男 + self.coinNumberLabel.text = numStr; + self.avatarImageView.imageUrl = rankModel.avatar; + self.nickNameLabel.text = rankModel.nick; +} +#pragma mark - Getters And Setters +- (NetImageView *)avatarImageView { + if (!_avatarImageView) { + _avatarImageView = [[NetImageView alloc] init]; + _avatarImageView.layer.masksToBounds = YES; + _avatarImageView.layer.cornerRadius = 25; + _avatarImageView.image = [UIImageConstant defaultAvatarPlaceholder]; + _avatarImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _avatarImageView;; +} + + +- (UILabel *)rankLabel { + if (!_rankLabel) { + _rankLabel = [[UILabel alloc] init]; + _rankLabel.font = [UIFont systemFontOfSize:18]; + _rankLabel.textAlignment = NSTextAlignmentCenter; + _rankLabel.textColor = [ThemeColor secondTextColor]; + } + return _rankLabel; +} + +- (UIImageView *)genderImageView { + if (!_genderImageView) { + _genderImageView = [[UIImageView alloc] init]; + _genderImageView.image = [UIImage imageNamed:@"common_sex_female"]; + _genderImageView.hidden = YES; + [_genderImageView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + } + return _genderImageView; +} + +- (UILabel *)nickNameLabel { + if (!_nickNameLabel) { + _nickNameLabel = [[UILabel alloc] init]; + _nickNameLabel.font = [UIFont systemFontOfSize:14]; + _nickNameLabel.textColor = [ThemeColor mainTextColor]; + } + return _nickNameLabel; +} +- (UILabel *)idLabel { + if (!_idLabel) { + UILabel *label = [[UILabel alloc] init]; + label.font = [UIFont systemFontOfSize:12]; + label.textColor = [ThemeColor textThirdColor]; + label.textAlignment = NSTextAlignmentRight; + _idLabel = label; + } + return _idLabel; +} + +- (UILabel *)coinNumberLabel{ + if (!_coinNumberLabel) { + _coinNumberLabel = [[UILabel alloc] init]; + _coinNumberLabel.font = [UIFont systemFontOfSize:16]; + _coinNumberLabel.textColor = [ThemeColor roomRankIntegralColor]; + _coinNumberLabel.textAlignment = NSTextAlignmentRight; + [_coinNumberLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + } + return _coinNumberLabel; +} + + +@end diff --git a/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m b/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m index afe4900..89975cb 100644 --- a/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m +++ b/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m @@ -1,33 +1,31 @@ -// -// XPRoomRankUserInfoView.m -// xplan-ios -// + + // Created by 冯硕 on 2021/12/14. -// + #import "XPRoomRankUserInfoView.h" -///Third + #import -///Tool + #import "NetImageView.h" #import "ThemeColor+RoomRank.h" -///Model + #import "RoomRankModel.h" @interface XPRoomRankUserInfoView () -///皇冠 + @property (nonatomic,strong) UIImageView *crownImageView; -///头像 + @property (nonatomic,strong) NetImageView *avatarImageView; -///昵称和性别的容器 + @property (nonatomic,strong) UIStackView *stackView; -///昵称 + @property (nonatomic,strong) UILabel *nickLabel; -///性别 + @property (nonatomic,strong) UIImageView *sexImageView; -///id + @property (nonatomic,strong) UILabel *idLabel; -///金币 + @property (nonatomic,strong) UILabel *coinLabel; @end @@ -115,7 +113,7 @@ numStr = [numStr stringByReplacingOccurrencesOfString:@".0" withString:@""]; } self.sexImageView.hidden = NO; - self.sexImageView.image = rankModel.gender == 2 ? [UIImage imageNamed:@"common_female"] : [UIImage imageNamed:@"common_male"]; // 2:女 1:男 + self.sexImageView.image = rankModel.gender == 2 ? [UIImage imageNamed:@"common_female"] : [UIImage imageNamed:@"common_male"]; self.coinLabel.text = numStr; self.avatarImageView.imageUrl = rankModel.avatar; self.nickLabel.text = rankModel.nick; diff --git a/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m.backup b/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m.backup new file mode 100644 index 0000000..afe4900 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/RoomRank/View/SubViews/XPRoomRankUserInfoView.m.backup @@ -0,0 +1,224 @@ +// +// XPRoomRankUserInfoView.m +// xplan-ios +// +// Created by 冯硕 on 2021/12/14. +// + +#import "XPRoomRankUserInfoView.h" +///Third +#import +///Tool +#import "NetImageView.h" +#import "ThemeColor+RoomRank.h" +///Model +#import "RoomRankModel.h" + +@interface XPRoomRankUserInfoView () +///皇冠 +@property (nonatomic,strong) UIImageView *crownImageView; +///头像 +@property (nonatomic,strong) NetImageView *avatarImageView; +///昵称和性别的容器 +@property (nonatomic,strong) UIStackView *stackView; +///昵称 +@property (nonatomic,strong) UILabel *nickLabel; +///性别 +@property (nonatomic,strong) UIImageView *sexImageView; +///id +@property (nonatomic,strong) UILabel *idLabel; +///金币 +@property (nonatomic,strong) UILabel *coinLabel; +@end + +@implementation XPRoomRankUserInfoView + + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.size.width / 2; +} + +#pragma mark - Private Method +- (void)initSubViews { + [self addSubview:self.avatarImageView]; + [self addSubview:self.crownImageView]; + [self addSubview:self.stackView]; + [self addSubview:self.idLabel]; + [self addSubview:self.coinLabel]; + + [self.stackView addArrangedSubview:self.nickLabel]; + [self.stackView addArrangedSubview:self.sexImageView]; + + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(recognizer:)]; + [self addGestureRecognizer:tap]; +} + +- (void)initSubViewConstraints { + [self mas_makeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.coinLabel.mas_bottom); + }]; + + [self.crownImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.centerX.mas_equalTo(self); + make.width.mas_equalTo(87); + make.height.mas_equalTo(99); + }]; + + [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.mas_equalTo(self.crownImageView).inset(6); + make.bottom.mas_equalTo(self.crownImageView.mas_bottom).offset(-6); + make.height.mas_equalTo(self.avatarImageView.mas_width); + }]; + + [self.stackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self); + make.top.mas_equalTo(self.crownImageView.mas_bottom).offset(4); + }]; + + [self.idLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.mas_equalTo(self); + make.top.mas_equalTo(self.stackView.mas_bottom).offset(1); + }]; + + [self.coinLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.idLabel.mas_bottom).offset(2); + make.left.right.mas_equalTo(self); + }]; +} + +#pragma mark - Event Response +- (void)recognizer:(UITapGestureRecognizer *)tap { + if (self.delegate && [self.delegate respondsToSelector:@selector(didTapUserInfo:)]) { + [self.delegate didTapUserInfo:self.rankModel.uid]; + } +} + +#pragma mark - Getters And Setters +- (void)setRankModel:(RoomRankModel *)rankModel { + _rankModel = rankModel; + self.idLabel.text = [NSString stringWithFormat:@"ID:%@", rankModel.erbanNo]; + NSString *numStr = [NSString stringWithFormat:@"%@",rankModel.goldAmount]; + if (rankModel.goldAmount.doubleValue > 10000) { + CGFloat numF = [rankModel.goldAmount doubleValue] / 10000.0; + numStr = [NSString stringWithFormat:YMLocalizedString(@"XPRoomRankUserInfoView0"),numF]; + numStr = [numStr stringByReplacingOccurrencesOfString:@".0" withString:@""]; + } + self.sexImageView.hidden = NO; + self.sexImageView.image = rankModel.gender == 2 ? [UIImage imageNamed:@"common_female"] : [UIImage imageNamed:@"common_male"]; // 2:女 1:男 + self.coinLabel.text = numStr; + self.avatarImageView.imageUrl = rankModel.avatar; + self.nickLabel.text = rankModel.nick; +} + + +- (void)setType:(RankUserInfoType)type { + NSString * crownName; + NSString * avatarPlace; + switch (type) { + case RankUserInfoType_First: + crownName = @"room_rank_crown_first"; + avatarPlace = @"room_rank_avatar_first_place"; + break; + case RankUserInfoType_Second: + crownName = @"room_rank_crown_second"; + avatarPlace = @"room_rank_avatar_second_place"; + break; + case RankUserInfoType_Third: + crownName = @"room_rank_crown_third"; + avatarPlace = @"room_rank_avatar_third_place"; + break; + default: + break; + } + + if (crownName.length >0) { + self.crownImageView.image = [UIImage imageNamed:crownName]; + } + + if (avatarPlace.length > 0) { + self.avatarImageView.image = [UIImage imageNamed:avatarPlace]; + } + self.sexImageView.hidden = YES; +} + +- (UIImageView *)crownImageView { + if (!_crownImageView) { + _crownImageView = [[UIImageView alloc] init]; + _crownImageView.userInteractionEnabled = YES; + } + return _crownImageView; +} + +- (NetImageView *)avatarImageView { + if (!_avatarImageView) { + _avatarImageView = [[NetImageView alloc] init]; + _avatarImageView.layer.masksToBounds = YES; + _avatarImageView.image = [UIImageConstant defaultAvatarPlaceholder]; + _avatarImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _avatarImageView;; +} + +- (UIStackView *)stackView { + if (!_stackView) { + _stackView = [[UIStackView alloc] init]; + _stackView.axis = UILayoutConstraintAxisHorizontal; + _stackView.distribution = UIStackViewDistributionFill; + _stackView.alignment = UIStackViewAlignmentCenter; + _stackView.spacing = 4; + } + return _stackView; +} + +- (UILabel *)nickLabel { + if (!_nickLabel) { + _nickLabel = [[UILabel alloc] init]; + _nickLabel.textAlignment = NSTextAlignmentCenter; + _nickLabel.font = [UIFont systemFontOfSize:14]; + _nickLabel.text = YMLocalizedString(@"XPRoomRankUserInfoView1"); + _nickLabel.textAlignment = NSTextAlignmentCenter; + _nickLabel.textColor = [ThemeColor roomRankNickColor]; + } + return _nickLabel; +} + +- (UIImageView *)sexImageView { + if (!_sexImageView) { + _sexImageView = [[UIImageView alloc] init]; + _sexImageView.userInteractionEnabled = YES; + } + return _sexImageView; +} + +- (UILabel *)idLabel { + if (!_idLabel) { + _idLabel = [[UILabel alloc] init]; + _idLabel.textAlignment = NSTextAlignmentCenter; + _idLabel.font = [UIFont systemFontOfSize:10]; + _idLabel.textColor = [ThemeColor roomRankNormalTitleColor]; + } + return _idLabel; +} + +- (UILabel *)coinLabel { + if (!_coinLabel) { + _coinLabel = [[UILabel alloc] init]; + _coinLabel.font = [UIFont boldSystemFontOfSize:14]; + _coinLabel.textColor = [ThemeColor roomRankIntegralColor]; + _coinLabel.textAlignment = NSTextAlignmentCenter; + } + return _coinLabel; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m b/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m index 3f145f1..b69944b 100644 --- a/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m +++ b/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m @@ -1,46 +1,44 @@ -// -// XPRoomRankViewController.m -// xplan-ios -// + + // Created by 冯硕 on 2021/12/14. -// + #import "XPRoomRankViewController.h" -///Third + #import #import #import -///Tool + #import "ThemeColor+RoomRank.h" #import "XPMacro.h" -///Model + #import "MicroQueueModel.h" #import "UserInfoModel.h" #import "MicroStateModel.h" #import "RoomInfoModel.h" -///View + #import "XPRoomDayRankViewController.h" #import "XPUserCardViewController.h" @interface XPRoomRankViewController () -///顶部的View + @property (nonatomic,strong) UIView * topView; -///显示内容的 + @property (nonatomic,strong) UIView * backView; -///分页标题 + @property (nonatomic, strong) NSArray *titles; -///分页控件 + @property (nonatomic, strong) JXCategoryTitleView *titleView; -///分页lineView + @property (nonatomic, strong) JXCategoryListContainerView *contentView; -///顶部的背景视图 + @property (nonatomic,strong) UIImageView *headBackImageView; -///财富榜 + @property (nonatomic,strong) XPRoomDayRankViewController *wealthRankVC; -///魅力榜 + @property (nonatomic,strong) XPRoomDayRankViewController *charmRankVC; -///房间的uid + @property (nonatomic,copy) NSString *roomUid; -///host + @property (nonatomic,weak) idhostDelegate; @end diff --git a/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m.backup b/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m.backup new file mode 100644 index 0000000..3f145f1 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/RoomRank/View/XPRoomRankViewController.m.backup @@ -0,0 +1,234 @@ +// +// XPRoomRankViewController.m +// xplan-ios +// +// Created by 冯硕 on 2021/12/14. +// + +#import "XPRoomRankViewController.h" +///Third +#import +#import +#import +///Tool +#import "ThemeColor+RoomRank.h" +#import "XPMacro.h" +///Model +#import "MicroQueueModel.h" +#import "UserInfoModel.h" +#import "MicroStateModel.h" +#import "RoomInfoModel.h" +///View +#import "XPRoomDayRankViewController.h" +#import "XPUserCardViewController.h" +@interface XPRoomRankViewController () +///顶部的View +@property (nonatomic,strong) UIView * topView; +///显示内容的 +@property (nonatomic,strong) UIView * backView; +///分页标题 +@property (nonatomic, strong) NSArray *titles; +///分页控件 +@property (nonatomic, strong) JXCategoryTitleView *titleView; +///分页lineView +@property (nonatomic, strong) JXCategoryListContainerView *contentView; +///顶部的背景视图 +@property (nonatomic,strong) UIImageView *headBackImageView; +///财富榜 +@property (nonatomic,strong) XPRoomDayRankViewController *wealthRankVC; +///魅力榜 +@property (nonatomic,strong) XPRoomDayRankViewController *charmRankVC; +///房间的uid +@property (nonatomic,copy) NSString *roomUid; +///host +@property (nonatomic,weak) idhostDelegate; +@end + +@implementation XPRoomRankViewController + +- (instancetype)initWithRoomUid:(NSString *)roomUid delegate:(id)delegate; { + if (self = [super init]) { + self.roomUid = roomUid; + self.hostDelegate = delegate; + self.modalPresentationStyle = UIModalPresentationOverFullScreen; + } + return self; +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + [self initSubViews]; + [self initSubViewConstraints]; +} + +#pragma mark - JXCategoryViewDelegate +- (NSInteger)numberOfListsInlistContainerView:(JXCategoryListContainerView *)listContainerView { + return self.titles.count; +} + +- (id)listContainerView:(JXCategoryListContainerView *)listContainerView initListForIndex:(NSInteger)index { + if (index == 0) { + return self.wealthRankVC; + } + return self.charmRankVC; +} + +#pragma mark - XPRoomRankHostDelegate +- (NSString *)getRoomUid { + return self.roomUid; +} + +- (void)didSelectUser:(NSString *)uid { + if (uid.integerValue <=0) return; + [self dismissViewControllerAnimated:YES completion:nil]; + RoomInfoModel * roomInfo = self.hostDelegate.getRoomInfo; + NSString * targetUid = uid; + XPUserCardInfoModel * model = [[XPUserCardInfoModel alloc] init]; + [[self.hostDelegate.getMicroQueue allValues] enumerateObjectsUsingBlock:^(MicroQueueModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (uid.integerValue == obj.userInfo.uid) { + model.position = [NSString stringWithFormat:@"%d", obj.microState.position]; + model.posState = obj.microState.posState; + model.micState = obj.microState.micState; + *stop = YES; + } + }]; + model.nick = self.hostDelegate.getUserInfo.nick; + model.uid = targetUid; + model.roomInfo = roomInfo; + model.micQueue = self.hostDelegate.getMicroQueue; + model.delegate = self.hostDelegate; + XPUserCardViewController * userCardVC = [[XPUserCardViewController alloc] initWithUser:model]; + [self.hostDelegate.getCurrentNav presentViewController:userCardVC animated:YES completion:nil]; +} +#pragma mark - Private Method +- (void)initSubViews { + self.view.backgroundColor = [UIColor clearColor]; + [self.view addSubview:self.topView]; + [self.view addSubview:self.backView]; + + [self.backView addSubview:self.headBackImageView]; + [self.backView addSubview:self.titleView]; + [self.backView addSubview:self.contentView]; +} + +- (void)initSubViewConstraints { + [self.topView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.mas_equalTo(self.view); + make.bottom.mas_equalTo(self.backView.mas_top); + }]; + + [self.backView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.bottom.right.mas_equalTo(self.view); + make.height.mas_equalTo(550); + }]; + + [self.titleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.mas_equalTo(self.backView).inset(30); + make.height.mas_equalTo(36); + make.top.mas_equalTo(self.backView).offset(25); + }]; + + [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.mas_equalTo(self.backView); + make.top.mas_equalTo(self.titleView.mas_bottom); + }]; + + [self.headBackImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.left.top.mas_equalTo(self.backView); + make.height.mas_equalTo(100); + }]; +} +#pragma mark - Event Response +- (void)disMissRoomRankCongnizer { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - Getters And Setters +- (JXCategoryTitleView *)titleView { + if (!_titleView) { + _titleView = [[JXCategoryTitleView alloc] init]; + _titleView.delegate = self; + _titleView.titles = self.titles; + _titleView.layer.masksToBounds= YES; + _titleView.layer.cornerRadius = 36/2; + _titleView.backgroundColor = [ThemeColor roomRankTitleBackColor]; + _titleView.titleColor = [ThemeColor roomRankNormalTitleColor]; + _titleView.titleSelectedColor = [ThemeColor roomRankSelectTitleColor]; + _titleView.titleFont = [UIFont fontWithName:@"PingFang-SC-Medium" size:15]; + _titleView.titleSelectedFont = [UIFont fontWithName:@"PingFang-SC-Medium" size:15]; + _titleView.titleLabelAnchorPointStyle = JXCategoryTitleLabelAnchorPointStyleCenter; + _titleView.contentScrollViewClickTransitionAnimationEnabled = NO; + _titleView.defaultSelectedIndex = 0; + _titleView.cellWidth = (KScreenWidth - 30* 2)/2; + _titleView.cellSpacing = 0; + _titleView.averageCellSpacingEnabled = YES; + _titleView.listContainer = self.contentView; + + JXCategoryIndicatorBackgroundView *backgroundView = [[JXCategoryIndicatorBackgroundView alloc] init]; + backgroundView.indicatorHeight = 34; + backgroundView.indicatorColor = [UIColor whiteColor]; + backgroundView.indicatorWidth = (KScreenWidth - 30* 2)/2; + backgroundView.layer.cornerRadius = 17; + backgroundView.layer.masksToBounds = YES; + _titleView.indicators = @[backgroundView]; + } + return _titleView; +} + +- (JXCategoryListContainerView *)contentView { + if (!_contentView) { + _contentView = [[JXCategoryListContainerView alloc] initWithType:JXCategoryListContainerType_ScrollView delegate:self]; + _contentView.defaultSelectedIndex = 0; + } + return _contentView; +} + +- (NSArray *)titles { + return @[@"贡献榜", YMLocalizedString(@"XPRoomRankViewController1")]; +} + +- (UIView *)topView { + if (!_topView) { + _topView = [[UIView alloc] init]; + _topView.backgroundColor = [UIColor clearColor]; + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMissRoomRankCongnizer)]; + [_topView addGestureRecognizer:tap]; + } + return _topView; +} + +- (UIView *)backView { + if (!_backView) { + _backView = [[UIView alloc] init]; + _backView.backgroundColor = [UIColor clearColor]; + } + return _backView; +} + +- (UIImageView *)headBackImageView { + if (!_headBackImageView) { + _headBackImageView = [[UIImageView alloc] init]; + _headBackImageView.userInteractionEnabled = YES; + _headBackImageView.image = [UIImage imageNamed:@"room_rank_header_bg"]; + } + return _headBackImageView; +} + +- (XPRoomDayRankViewController *)charmRankVC { + if (!_charmRankVC) { + _charmRankVC = [[XPRoomDayRankViewController alloc] initWithDelegate:self]; + _charmRankVC.type = RoomRankType_Charm; + } + return _charmRankVC; +} + +- (XPRoomDayRankViewController *)wealthRankVC { + if (!_wealthRankVC) { + _wealthRankVC = [[XPRoomDayRankViewController alloc] initWithDelegate:self]; + _wealthRankVC.type = RoomRankType_Contribute; + } + return _wealthRankVC; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h index e8b9ac5..c8c2502 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h @@ -1,47 +1,36 @@ -// -// Api+WishGift.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "Api.h" NS_ASSUME_NONNULL_BEGIN @interface Api (WishGift) -///添加心愿礼物 -/// @param roomUid 房主的uid + + + (void)wishGiftAdd:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; -/// 删除心愿礼物 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param itemId item id + + + (void)wishGiftDeleteItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid itemId:(NSString *)itemId; -/// 创建心愿礼物 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param giftId 礼物id -/// @param itemId item id -/// @param seq 编号 1 2 3 -/// @param targetNum 目标数量 + + + (void)wishGiftAddItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid giftId:(NSString *)giftId itemId:(NSString *)itemId seq:(NSString *)seq targetNum:(NSString *)targetNum; -/// 获取房间心愿礼物列表 -/// @param roomUid 房主的uid + + + (void)wishGiftList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; -/// 获取房间心愿礼物助力用户列表 -/// @param roomUid 房主的uid + + + (void)wishGiftAssistUserList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; -/// 获取心愿礼物配置列表 -/// @param roomUid 房主的uid -/// @param level 等级 + + + (void)wishGiftCondfigList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid level:(NSString *)level; -/// 获取房间历史心愿列表 -/// @param roomUid 房主的uid + + + (void)wishGiftHistoryList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; -/// 发送心愿完成庆祝特效 -/// @param roomUid 房主的uid + + (void)wishGiftSendCelebrate:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h.backup new file mode 100644 index 0000000..e8b9ac5 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.h.backup @@ -0,0 +1,49 @@ +// +// Api+WishGift.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "Api.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface Api (WishGift) +///添加心愿礼物 +/// @param roomUid 房主的uid ++ (void)wishGiftAdd:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; +/// 删除心愿礼物 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param itemId item id ++ (void)wishGiftDeleteItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid itemId:(NSString *)itemId; +/// 创建心愿礼物 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param giftId 礼物id +/// @param itemId item id +/// @param seq 编号 1 2 3 +/// @param targetNum 目标数量 ++ (void)wishGiftAddItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid giftId:(NSString *)giftId itemId:(NSString *)itemId seq:(NSString *)seq targetNum:(NSString *)targetNum; +/// 获取房间心愿礼物列表 +/// @param roomUid 房主的uid ++ (void)wishGiftList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; +/// 获取房间心愿礼物助力用户列表 +/// @param roomUid 房主的uid ++ (void)wishGiftAssistUserList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; +/// 获取心愿礼物配置列表 +/// @param roomUid 房主的uid +/// @param level 等级 ++ (void)wishGiftCondfigList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid level:(NSString *)level; +/// 获取房间历史心愿列表 +/// @param roomUid 房主的uid ++ (void)wishGiftHistoryList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; + +/// 发送心愿完成庆祝特效 +/// @param roomUid 房主的uid ++ (void)wishGiftSendCelebrate:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m index bc41282..9456eed 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m +++ b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m @@ -1,38 +1,26 @@ -// -// Api+WishGift.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "Api+WishGift.h" #import "NSMutableDictionary+Saft.h" #import @implementation Api (WishGift) -///添加心愿礼物 -/// @param roomUid 房主的uid + + (void)wishGiftAdd:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvYWRk"];// + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvYWRk"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, nil]; } -/// 删除心愿礼物 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param itemId item id + + (void)wishGiftDeleteItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid itemId:(NSString *)itemId { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvZGVsSXRlbQ=="];// + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvZGVsSXRlbQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, itemId, nil]; } -/// 创建心愿礼物 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param giftId 礼物id -/// @param itemId item id -/// @param seq 编号 1 2 3 -/// @param targetNum 目标数量 + + (void)wishGiftAddItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid giftId:(NSString *)giftId itemId:(NSString *)itemId seq:(NSString *)seq targetNum:(NSString *)targetNum { NSMutableDictionary * dic = [NSMutableDictionary dictionary]; if (itemId.length > 0) { @@ -42,43 +30,37 @@ [dic safeSetObject:giftId forKey:@"giftId"]; [dic safeSetObject:seq forKey:@"seq"]; [dic safeSetObject:targetNum forKey:@"targetNum"]; - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvYWRkSXRlbQ=="];//wishGift/addItem + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvYWRkSXRlbQ=="]; [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; } -/// 获取房间心愿礼物列表 -/// @param roomUid 房主的uid + + (void)wishGiftList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdA=="];//wishGift/list + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdA=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; } -/// 获取房间心愿礼物助力用户列表 -/// @param roomUid 房主的uid + + (void)wishGiftAssistUserList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdEFzc2lzdFVzZXI="];// + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdEFzc2lzdFVzZXI="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; } -/// 获取心愿礼物配置列表 -/// @param roomUid 房主的uid -/// @param level 等级 + + (void)wishGiftCondfigList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid level:(NSString *)level { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdENvbmZpZw=="];// + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdENvbmZpZw=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, level, nil]; } -/// 获取房间历史心愿列表 -/// @param roomUid 房主的uid + + (void)wishGiftHistoryList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdFdpc2hHaWZ0SGlzdG9yeQ=="];//wishGift/listWishGiftHistory + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdFdpc2hHaWZ0SGlzdG9yeQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; } -/// 发送心愿完成庆祝特效 -/// @param roomUid 房主的uid + + (void)wishGiftSendCelebrate:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { - NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvc2VuZENlbGVicmF0ZQ=="];//wishGift/sendCelebrate + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvc2VuZENlbGVicmF0ZQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; } diff --git a/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m.backup b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m.backup new file mode 100644 index 0000000..bc41282 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Api/Api+WishGift.m.backup @@ -0,0 +1,85 @@ +// +// Api+WishGift.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "Api+WishGift.h" +#import "NSMutableDictionary+Saft.h" +#import +@implementation Api (WishGift) + +///添加心愿礼物 +/// @param roomUid 房主的uid ++ (void)wishGiftAdd:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvYWRk"];// + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, nil]; +} + +/// 删除心愿礼物 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param itemId item id ++ (void)wishGiftDeleteItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid itemId:(NSString *)itemId { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvZGVsSXRlbQ=="];// + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, itemId, nil]; +} + +/// 创建心愿礼物 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param giftId 礼物id +/// @param itemId item id +/// @param seq 编号 1 2 3 +/// @param targetNum 目标数量 ++ (void)wishGiftAddItem:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid giftId:(NSString *)giftId itemId:(NSString *)itemId seq:(NSString *)seq targetNum:(NSString *)targetNum { + NSMutableDictionary * dic = [NSMutableDictionary dictionary]; + if (itemId.length > 0) { + [dic safeSetObject:itemId forKey:@"itemId"]; + } + [dic safeSetObject:roomUid forKey:@"roomUid"]; + [dic safeSetObject:giftId forKey:@"giftId"]; + [dic safeSetObject:seq forKey:@"seq"]; + [dic safeSetObject:targetNum forKey:@"targetNum"]; + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvYWRkSXRlbQ=="];//wishGift/addItem + [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:dic completion:completion]; +} + +/// 获取房间心愿礼物列表 +/// @param roomUid 房主的uid ++ (void)wishGiftList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdA=="];//wishGift/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; +} + +/// 获取房间心愿礼物助力用户列表 +/// @param roomUid 房主的uid ++ (void)wishGiftAssistUserList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdEFzc2lzdFVzZXI="];// + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; +} + +/// 获取心愿礼物配置列表 +/// @param roomUid 房主的uid +/// @param level 等级 ++ (void)wishGiftCondfigList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid level:(NSString *)level { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdENvbmZpZw=="];// + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, level, nil]; +} + +/// 获取房间历史心愿列表 +/// @param roomUid 房主的uid ++ (void)wishGiftHistoryList:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvbGlzdFdpc2hHaWZ0SGlzdG9yeQ=="];//wishGift/listWishGiftHistory + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; +} + +/// 发送心愿完成庆祝特效 +/// @param roomUid 房主的uid ++ (void)wishGiftSendCelebrate:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid { + NSString * fang = [NSString stringFromBase64String:@"d2lzaEdpZnQvc2VuZENlbGVicmF0ZQ=="];//wishGift/sendCelebrate + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, nil]; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h index 1c03e4a..b10e98e 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h @@ -1,9 +1,7 @@ -// -// WishGiftHistoryModel.h -// YUMI -// + + // Created by YUMI on 2022/10/20. -// + #import #import "WishGiftInfoModel.h" @@ -11,9 +9,9 @@ NS_ASSUME_NONNULL_BEGIN @interface WishGiftHistoryModel : PIBaseModel -///创建时间 + @property (nonatomic,strong) NSString *createDate; -///礼物列表 + @property (nonatomic,strong) NSArray *gifts; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h.backup new file mode 100644 index 0000000..1c03e4a --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.h.backup @@ -0,0 +1,21 @@ +// +// WishGiftHistoryModel.h +// YUMI +// +// Created by YUMI on 2022/10/20. +// + +#import +#import "WishGiftInfoModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface WishGiftHistoryModel : PIBaseModel + +///创建时间 +@property (nonatomic,strong) NSString *createDate; +///礼物列表 +@property (nonatomic,strong) NSArray *gifts; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m index 60803ff..d308561 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m @@ -1,9 +1,7 @@ -// -// WishGiftHistoryModel.m -// YUMI -// + + // Created by YUMI on 2022/10/20. -// + #import "WishGiftHistoryModel.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m.backup new file mode 100644 index 0000000..60803ff --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftHistoryModel.m.backup @@ -0,0 +1,15 @@ +// +// WishGiftHistoryModel.m +// YUMI +// +// Created by YUMI on 2022/10/20. +// + +#import "WishGiftHistoryModel.h" + +@implementation WishGiftHistoryModel ++ (NSDictionary *)objectClassInArray { + return @{@"gifts" : WishGiftInfoModel.class}; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h index 3bd3d4a..ff5126b 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h @@ -1,9 +1,7 @@ -// -// WishGiftInfoModel.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import @@ -16,27 +14,27 @@ typedef NS_ENUM(int, WishGiftLevel) { @interface WishGiftInfoModel : PIBaseModel -/// 实际收到数量 + @property (nonatomic, assign) NSInteger actualNum; -///礼物id + @property (nonatomic, assign) NSInteger giftId; -///礼物名称 + @property (nonatomic, copy) NSString *giftName; -/// 礼物价值 + @property (nonatomic, assign) NSInteger goldPrice; -/// 礼物心愿itemid + @property (nonatomic, assign) NSInteger itemId; -/// 目标数量 + @property (nonatomic, assign) NSInteger targetNum; -///礼物图片 + @property (nonatomic,copy) NSString *giftUrl; -///本地字段 + @property (nonatomic,assign) NSInteger row; -///创建的时间 + @property (nonatomic,strong) NSString *createTime; -///等级的名称 + @property (nonatomic,copy) NSString *levelName; -///等级 + @property (nonatomic,assign) WishGiftLevel level; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h.backup new file mode 100644 index 0000000..3bd3d4a --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.h.backup @@ -0,0 +1,42 @@ +// +// WishGiftInfoModel.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(int, WishGiftLevel) { + WishGiftLevel_Normal = 1, + WishGiftLevel_Middle = 2, + WishGiftLevel_High = 3 +}; + + +@interface WishGiftInfoModel : PIBaseModel +/// 实际收到数量 +@property (nonatomic, assign) NSInteger actualNum; +///礼物id +@property (nonatomic, assign) NSInteger giftId; +///礼物名称 +@property (nonatomic, copy) NSString *giftName; +/// 礼物价值 +@property (nonatomic, assign) NSInteger goldPrice; +/// 礼物心愿itemid +@property (nonatomic, assign) NSInteger itemId; +/// 目标数量 +@property (nonatomic, assign) NSInteger targetNum; +///礼物图片 +@property (nonatomic,copy) NSString *giftUrl; +///本地字段 +@property (nonatomic,assign) NSInteger row; +///创建的时间 +@property (nonatomic,strong) NSString *createTime; +///等级的名称 +@property (nonatomic,copy) NSString *levelName; +///等级 +@property (nonatomic,assign) WishGiftLevel level; +@end +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m index fdc2c57..2aefb96 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m @@ -1,9 +1,7 @@ -// -// WishGiftInfoModel.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "WishGiftInfoModel.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m.backup new file mode 100644 index 0000000..fdc2c57 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoModel.m.backup @@ -0,0 +1,13 @@ +// +// WishGiftInfoModel.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "WishGiftInfoModel.h" + +@implementation WishGiftInfoModel + +@end + diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h index 79f89b3..dedad85 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h @@ -1,18 +1,16 @@ -// -// WishGiftInfoUpdateModel.h -// YUMI -// + + // Created by YUMI on 2022/10/28. -// + #import #import "WishGiftInfoModel.h" NS_ASSUME_NONNULL_BEGIN @interface WishGiftInfoUpdateModel : PIBaseModel -///送礼物的人 + @property (nonatomic,strong) NSString *senderUid; -///礼物 + @property (nonatomic,copy) NSArray *gifts; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h.backup new file mode 100644 index 0000000..79f89b3 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.h.backup @@ -0,0 +1,19 @@ +// +// WishGiftInfoUpdateModel.h +// YUMI +// +// Created by YUMI on 2022/10/28. +// + +#import +#import "WishGiftInfoModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface WishGiftInfoUpdateModel : PIBaseModel +///送礼物的人 +@property (nonatomic,strong) NSString *senderUid; +///礼物 +@property (nonatomic,copy) NSArray *gifts; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m index dfd23c5..edc20d0 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m @@ -1,9 +1,7 @@ -// -// WishGiftInfoUpdateModel.m -// YUMI -// + + // Created by YUMI on 2022/10/28. -// + #import "WishGiftInfoUpdateModel.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m.backup new file mode 100644 index 0000000..dfd23c5 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftInfoUpdateModel.m.backup @@ -0,0 +1,15 @@ +// +// WishGiftInfoUpdateModel.m +// YUMI +// +// Created by YUMI on 2022/10/28. +// + +#import "WishGiftInfoUpdateModel.h" + +@implementation WishGiftInfoUpdateModel ++ (NSDictionary *)objectClassInArray { + return @{@"gifts":WishGiftInfoModel.class}; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h index 307afd2..4a5bb95 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h @@ -1,9 +1,7 @@ -// -// WishGiftUserModel.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h.backup new file mode 100644 index 0000000..307afd2 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.h.backup @@ -0,0 +1,19 @@ +// +// WishGiftUserModel.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface WishGiftUserModel : PIBaseModel +@property (nonatomic, copy) NSString *avatar; +@property (nonatomic, assign) NSInteger erbanNo; +@property (nonatomic, copy) NSString *nick; +@property (nonatomic, assign) NSInteger uid; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m index 7c73946..96fc4ae 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m @@ -1,9 +1,7 @@ -// -// WishGiftUserModel.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "WishGiftUserModel.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m.backup b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m.backup new file mode 100644 index 0000000..7c73946 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Model/WishGiftUserModel.m.backup @@ -0,0 +1,12 @@ +// +// WishGiftUserModel.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "WishGiftUserModel.h" + +@implementation WishGiftUserModel + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h index b25f53b..52186d6 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h @@ -1,9 +1,7 @@ -// -// WishGiftPresenter.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "BaseMvpPresenter.h" @@ -11,20 +9,20 @@ NS_ASSUME_NONNULL_BEGIN @interface XPWishGiftPresenter : BaseMvpPresenter -/// 添加许愿礼物 + - (void)addWishGift:(NSString *)roomUid; -///创建心愿礼物 + - (void)createWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId giftId:(NSString *)giftId seq:(int)seq targetNum:(int)targetNum; -///删除心愿礼物 + - (void)deleteWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId; -///房间许愿礼物列表 + - (void)wishGiftList:(NSString *)roomUid; -///助理用户列表 + - (void)wishGiftAssistUserList:(NSString *)roomUid; -/// 心愿礼物配置表 + - (void)wishGiftConfigList:(NSString *)roomUid level:(NSString *)level ; -///获取房间历史列表 + - (void)wishGiftHistroyList:(NSString *)roomUid; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h.backup new file mode 100644 index 0000000..b25f53b --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.h.backup @@ -0,0 +1,31 @@ +// +// WishGiftPresenter.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "BaseMvpPresenter.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPWishGiftPresenter : BaseMvpPresenter + +/// 添加许愿礼物 +- (void)addWishGift:(NSString *)roomUid; + +///创建心愿礼物 +- (void)createWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId giftId:(NSString *)giftId seq:(int)seq targetNum:(int)targetNum; +///删除心愿礼物 +- (void)deleteWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId; +///房间许愿礼物列表 +- (void)wishGiftList:(NSString *)roomUid; +///助理用户列表 +- (void)wishGiftAssistUserList:(NSString *)roomUid; +/// 心愿礼物配置表 +- (void)wishGiftConfigList:(NSString *)roomUid level:(NSString *)level ; +///获取房间历史列表 +- (void)wishGiftHistroyList:(NSString *)roomUid; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m index 50e9c71..6a6ed8d 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m +++ b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m @@ -1,9 +1,7 @@ -// -// WishGiftPresenter.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftPresenter.h" #import "Api+WishGift.h" @@ -14,47 +12,47 @@ @implementation XPWishGiftPresenter -/// 添加许愿礼物 + - (void)addWishGift:(NSString *)roomUid { [Api wishGiftAdd:[self createHttpCompletion:^(BaseModel * _Nonnull data) { [[self getView] addWishGiftSuccess]; } showLoading:YES] roomUid:roomUid]; } -///创建心愿礼物 + - (void)createWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId giftId:(NSString *)giftId seq:(int)seq targetNum:(int)targetNum { [Api wishGiftAddItem:[self createHttpCompletion:^(BaseModel * _Nonnull data) { [[self getView] createWishGiftItemSuccess]; } showLoading:YES] roomUid:roomUid giftId:giftId itemId:itemId seq:[NSString stringWithFormat:@"%d", seq] targetNum:[NSString stringWithFormat:@"%d", targetNum]]; } -///删除心愿礼物 + - (void)deleteWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId { [Api wishGiftDeleteItem:[self createHttpCompletion:^(BaseModel * _Nonnull data) { [[self getView] deleteWishGiftItemSuccess]; } showLoading:YES] roomUid:roomUid itemId:itemId]; } -///房间许愿礼物列表 + - (void)wishGiftList:(NSString *)roomUid { [Api wishGiftList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { NSArray * array = [WishGiftInfoModel modelsWithArray:data.data]; [[self getView] getWishGiftListSuccess:array]; }] roomUid:roomUid]; } -///助理用户列表 + - (void)wishGiftAssistUserList:(NSString *)roomUid { [Api wishGiftAssistUserList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { NSArray * array = [WishGiftUserModel modelsWithArray:data.data]; [[self getView] getWishGiftAssistUserListSuccess:array]; }] roomUid:roomUid]; } -/// 心愿礼物配置表 + - (void)wishGiftConfigList:(NSString *)roomUid level:(NSString *)level { [Api wishGiftCondfigList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { NSArray * array = [WishGiftInfoModel modelsWithArray:data.data]; [[self getView] wishGiftConfigListSucces:array level:level]; }] roomUid:roomUid level:level]; } -///获取房间历史列表 + - (void)wishGiftHistroyList:(NSString *)roomUid { [Api wishGiftHistoryList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { NSArray * array = [WishGiftHistoryModel modelsWithArray:data.data]; diff --git a/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m.backup b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m.backup new file mode 100644 index 0000000..50e9c71 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Presenter/XPWishGiftPresenter.m.backup @@ -0,0 +1,65 @@ +// +// WishGiftPresenter.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftPresenter.h" +#import "Api+WishGift.h" +#import "XPWishGiftProtocol.h" +#import "WishGiftInfoModel.h" +#import "WishGiftUserModel.h" +#import "WishGiftHistoryModel.h" + +@implementation XPWishGiftPresenter + +/// 添加许愿礼物 +- (void)addWishGift:(NSString *)roomUid { + [Api wishGiftAdd:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + [[self getView] addWishGiftSuccess]; + } showLoading:YES] roomUid:roomUid]; +} + +///创建心愿礼物 +- (void)createWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId giftId:(NSString *)giftId seq:(int)seq targetNum:(int)targetNum { + [Api wishGiftAddItem:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + [[self getView] createWishGiftItemSuccess]; + } showLoading:YES] roomUid:roomUid giftId:giftId itemId:itemId seq:[NSString stringWithFormat:@"%d", seq] targetNum:[NSString stringWithFormat:@"%d", targetNum]]; +} +///删除心愿礼物 +- (void)deleteWishGiftItem:(NSString *)roomUid itemId:(NSString *)itemId { + [Api wishGiftDeleteItem:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + [[self getView] deleteWishGiftItemSuccess]; + } showLoading:YES] roomUid:roomUid itemId:itemId]; +} +///房间许愿礼物列表 +- (void)wishGiftList:(NSString *)roomUid { + [Api wishGiftList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray * array = [WishGiftInfoModel modelsWithArray:data.data]; + [[self getView] getWishGiftListSuccess:array]; + }] roomUid:roomUid]; +} +///助理用户列表 +- (void)wishGiftAssistUserList:(NSString *)roomUid { + [Api wishGiftAssistUserList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray * array = [WishGiftUserModel modelsWithArray:data.data]; + [[self getView] getWishGiftAssistUserListSuccess:array]; + }] roomUid:roomUid]; +} +/// 心愿礼物配置表 +- (void)wishGiftConfigList:(NSString *)roomUid level:(NSString *)level { + [Api wishGiftCondfigList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray * array = [WishGiftInfoModel modelsWithArray:data.data]; + [[self getView] wishGiftConfigListSucces:array level:level]; + }] roomUid:roomUid level:level]; +} +///获取房间历史列表 +- (void)wishGiftHistroyList:(NSString *)roomUid { + [Api wishGiftHistoryList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray * array = [WishGiftHistoryModel modelsWithArray:data.data]; + [[self getView] wishGiftHistroyListSuccess:array]; + } showLoading:YES] roomUid:roomUid]; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h b/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h index 1bdaa3d..63ca2a1 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h +++ b/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h @@ -1,9 +1,7 @@ -// -// YMWishGiftProtocol.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import @@ -11,24 +9,24 @@ NS_ASSUME_NONNULL_BEGIN @protocol XPWishGiftProtocol @optional -///添加礼物心愿成功 + - (void)addWishGiftSuccess; -///创建心愿单成功 + - (void)createWishGiftItemSuccess; -///删除心愿单成功 + - (void)deleteWishGiftItemSuccess; -///获取心愿礼物列表 + - (void)getWishGiftListSuccess:(NSArray *)list; -///助理用户列表 + - (void)getWishGiftAssistUserListSuccess:(NSArray *)list; -///礼物配置列表 + - (void)wishGiftConfigListSucces:(NSArray *)list level:(NSString *)level; -///历史心愿成功 + - (void)wishGiftHistroyListSuccess:(NSArray *)list; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h.backup b/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h.backup new file mode 100644 index 0000000..1bdaa3d --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/Protocol/XPWishGiftProtocol.h.backup @@ -0,0 +1,35 @@ +// +// YMWishGiftProtocol.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol XPWishGiftProtocol +@optional +///添加礼物心愿成功 +- (void)addWishGiftSuccess; + +///创建心愿单成功 +- (void)createWishGiftItemSuccess; + +///删除心愿单成功 +- (void)deleteWishGiftItemSuccess; +///获取心愿礼物列表 +- (void)getWishGiftListSuccess:(NSArray *)list; + +///助理用户列表 +- (void)getWishGiftAssistUserListSuccess:(NSArray *)list; + +///礼物配置列表 +- (void)wishGiftConfigListSucces:(NSArray *)list level:(NSString *)level; + +///历史心愿成功 +- (void)wishGiftHistroyListSuccess:(NSArray *)list; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h index 476cdd9..dcc401e 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h @@ -1,9 +1,7 @@ -// -// YMWishGiftEmptyTableViewCell.h -// YUMI -// + + // Created by YUMI on 2022/10/19. -// + #import diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h.backup new file mode 100644 index 0000000..476cdd9 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.h.backup @@ -0,0 +1,16 @@ +// +// YMWishGiftEmptyTableViewCell.h +// YUMI +// +// Created by YUMI on 2022/10/19. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface XPWishGiftEmptyTableViewCell : UITableViewCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m index 6348dbc..6693ec2 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m @@ -1,15 +1,13 @@ -// -// YMWishGiftEmptyTableViewCell.m -// YUMI -// + + // Created by YUMI on 2022/10/19. -// + #import "XPWishGiftEmptyTableViewCell.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "UIImageConstant.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m.backup new file mode 100644 index 0000000..6348dbc --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftEmptyTableViewCell.m.backup @@ -0,0 +1,73 @@ +// +// YMWishGiftEmptyTableViewCell.m +// YUMI +// +// Created by YUMI on 2022/10/19. +// + +#import "XPWishGiftEmptyTableViewCell.h" + +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "UIImageConstant.h" + +@interface XPWishGiftEmptyTableViewCell () +@property (nonatomic,strong) UIImageView *emptyImageView; +@property (nonatomic,strong) UILabel *titleLabel; +@end + +@implementation XPWishGiftEmptyTableViewCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} +#pragma mark - Private Method +- (void)initSubViews { + self.backgroundColor = [UIColor clearColor]; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self.contentView addSubview:self.emptyImageView]; + [self.contentView addSubview:self.titleLabel]; +} + +- (void)initSubViewConstraints { + [self.emptyImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.contentView).offset(150); + make.centerX.mas_equalTo(self.contentView); + make.size.mas_equalTo(CGSizeMake(200, 200)); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.emptyImageView.mas_bottom).offset(20); + make.leading.trailing.mas_equalTo(self.contentView); + }]; +} +#pragma mark - Getters And Setters +- (UIImageView *)emptyImageView { + if (!_emptyImageView) { + _emptyImageView = [[UIImageView alloc] init]; + _emptyImageView.userInteractionEnabled = YES; + _emptyImageView.image = [UIImageConstant defaultEmptyPlaceholder]; + _emptyImageView.layer.masksToBounds = YES; + _emptyImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _emptyImageView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = YMLocalizedString(@"XPWishGiftEmptyTableViewCell0"); + _titleLabel.font = [UIFont systemFontOfSize:16]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.textColor = [DJDKMIMOMColor secondTextColor]; + } + return _titleLabel; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h index 08a4ff6..cc3f107 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h @@ -1,18 +1,16 @@ -// -// YMWishGiftHistoryTableViewCell.h -// YUMI -// + + // Created by YUMI on 2022/10/19. -// + #import NS_ASSUME_NONNULL_BEGIN @class WishGiftInfoModel; @interface XPWishGiftHistoryTableViewCell : UITableViewCell -///是不是第一个 + @property (nonatomic,assign) BOOL isTop; -///是不是底部 + @property (nonatomic,assign) BOOL isBottom; @property (nonatomic,strong) WishGiftInfoModel *giftInfo; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h.backup new file mode 100644 index 0000000..08a4ff6 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.h.backup @@ -0,0 +1,20 @@ +// +// YMWishGiftHistoryTableViewCell.h +// YUMI +// +// Created by YUMI on 2022/10/19. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class WishGiftInfoModel; +@interface XPWishGiftHistoryTableViewCell : UITableViewCell +///是不是第一个 +@property (nonatomic,assign) BOOL isTop; +///是不是底部 +@property (nonatomic,assign) BOOL isBottom; +@property (nonatomic,strong) WishGiftInfoModel *giftInfo; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m index a51cbcf..111cdbb 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m @@ -1,14 +1,12 @@ -// -// YMWishGiftHistoryTableViewCell.m -// YUMI -// + + // Created by YUMI on 2022/10/19. -// + #import "XPWishGiftHistoryTableViewCell.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "UIImage+Utils.h" #import "NetImageView.h" @@ -17,17 +15,17 @@ #import "YUMIMacroUitls.h" @interface XPWishGiftHistoryTableViewCell () -///容器 + @property (nonatomic,strong) UIView *backView; -///等级 + @property (nonatomic,strong) UILabel *levleLabel; -///礼物图片 + @property (nonatomic,strong) NetImageView *giftImageView; -///礼物名称 + @property (nonatomic,strong) UILabel *giftLabel; -///目标 + @property (nonatomic,strong) UILabel *targetNumLabel; -///分割下 + @property (nonatomic,strong) UIView *lineView; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m.backup new file mode 100644 index 0000000..a51cbcf --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftHistoryTableViewCell.m.backup @@ -0,0 +1,173 @@ +// +// YMWishGiftHistoryTableViewCell.m +// YUMI +// +// Created by YUMI on 2022/10/19. +// + +#import "XPWishGiftHistoryTableViewCell.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "UIImage+Utils.h" +#import "NetImageView.h" +#import "WishGiftInfoModel.h" +#import "UIView+Corner.h" +#import "YUMIMacroUitls.h" + +@interface XPWishGiftHistoryTableViewCell () +///容器 +@property (nonatomic,strong) UIView *backView; +///等级 +@property (nonatomic,strong) UILabel *levleLabel; +///礼物图片 +@property (nonatomic,strong) NetImageView *giftImageView; +///礼物名称 +@property (nonatomic,strong) UILabel *giftLabel; +///目标 +@property (nonatomic,strong) UILabel *targetNumLabel; +///分割下 +@property (nonatomic,strong) UIView *lineView; + +@end +@implementation XPWishGiftHistoryTableViewCell + + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + self.selectionStyle = UITableViewCellSelectionStyleNone; + self.backgroundColor = [UIColor clearColor]; + [self.contentView addSubview:self.backView]; + + [self.backView addSubview:self.levleLabel]; + [self.backView addSubview:self.giftImageView]; + [self.backView addSubview:self.giftLabel]; + [self.backView addSubview:self.targetNumLabel]; + [self.backView addSubview:self.lineView]; +} + +- (void)initSubViewConstraints { + [self.backView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.contentView).inset(15); + make.top.bottom.mas_equalTo(self.contentView); + }]; + + [self.levleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.backView); + make.leading.mas_equalTo(self.backView).offset(15); + }]; + + [self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(24, 24)); + make.centerY.mas_equalTo(self.backView); + make.leading.mas_equalTo(self.levleLabel.mas_trailing).offset(20); + }]; + + [self.giftLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.backView); + make.leading.mas_equalTo(self.giftImageView.mas_trailing).offset(8); + make.trailing.lessThanOrEqualTo(self.targetNumLabel.mas_leading).offset(-5); + }]; + + [self.targetNumLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.backView); + make.trailing.mas_equalTo(self.backView).offset(-15); + }]; + + [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.backView).inset(13); + make.bottom.mas_equalTo(self.backView); + make.height.mas_equalTo(1); + }]; + +} +#pragma mark - Getters And Setters +- (void)setIsTop:(BOOL)isTop { + _isTop = isTop; + if(_isTop) { + [self.backView setCornerWithLeftTopCorner:8 rightTopCorner:8 bottomLeftCorner:0 bottomRightCorner:0 size:(CGSizeMake(KScreenWidth - 30, 44))]; + } +} + +- (void)setIsBottom:(BOOL)isBottom { + _isBottom = isBottom; + if (_isBottom) { + [self.backView setCornerWithLeftTopCorner:0 rightTopCorner:0 bottomLeftCorner:8 bottomRightCorner:8 size:(CGSizeMake(KScreenWidth - 30, 44))]; + } +} + +- (void)setGiftInfo:(WishGiftInfoModel *)giftInfo { + _giftInfo = giftInfo; + if (_giftInfo) { + self.levleLabel.text = [NSString stringWithFormat:@"%ld", _giftInfo.row]; + self.giftImageView.imageUrl = _giftInfo.giftUrl; + self.giftLabel.text = _giftInfo.giftName; + self.targetNumLabel.text = [NSString stringWithFormat:@"%ld/%ld", _giftInfo.actualNum, _giftInfo.targetNum]; + } +} + +- (UIView *)backView { + if (!_backView) { + _backView = [[UIView alloc] init]; + _backView.backgroundColor = [UIColor whiteColor]; + } + return _backView; +} + +- (UILabel *)levleLabel { + if (!_levleLabel) { + _levleLabel = [[UILabel alloc] init]; + _levleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _levleLabel.textColor = [DJDKMIMOMColor mainTextColor]; + } + return _levleLabel; +} + +- (NetImageView *)giftImageView { + if (!_giftImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _giftImageView = [[NetImageView alloc] initWithConfig:config]; + _giftImageView.layer.masksToBounds = YES; + _giftImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _giftImageView; +} + +- (UILabel *)giftLabel { + if (!_giftLabel) { + _giftLabel = [[UILabel alloc] init]; + _giftLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _giftLabel.textColor = [DJDKMIMOMColor mainTextColor]; + } + return _giftLabel; +} + +- (UILabel *)targetNumLabel { + if (!_targetNumLabel) { + _targetNumLabel = [[UILabel alloc] init]; + _targetNumLabel.font = [UIFont systemFontOfSize:14]; + _targetNumLabel.textColor = [DJDKMIMOMColor textThirdColor]; + } + return _targetNumLabel; +} + +- (UIView *)lineView { + if (!_lineView) { + _lineView = [[UIView alloc] init]; + _lineView.backgroundColor = [DJDKMIMOMColor dividerColor]; + } + return _lineView; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h index 75a5120..8ab544f 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h @@ -1,9 +1,7 @@ -// -// YMWishGiftTableViewCell.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import @@ -11,19 +9,19 @@ NS_ASSUME_NONNULL_BEGIN @class XPWishGiftTableViewCell, WishGiftInfoModel; @protocol XPWishGiftTableViewCellDelegate -///更新礼物信息 + - (void)xPWishGiftTableViewCell:(XPWishGiftTableViewCell *)view didUpdateWishGift:(WishGiftInfoModel *)info; -///删除礼物信息 + - (void)xPWishGiftTableViewCell:(XPWishGiftTableViewCell *)view didClearWishGift:(WishGiftInfoModel *)info; @end @interface XPWishGiftTableViewCell : UITableViewCell -///代理 + @property (nonatomic,weak) id delegate; @property (nonatomic,strong) WishGiftInfoModel *giftInfo; -///是否隐藏编辑 + @property (nonatomic,assign) BOOL isHiddenEdit; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h.backup new file mode 100644 index 0000000..75a5120 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.h.backup @@ -0,0 +1,30 @@ +// +// YMWishGiftTableViewCell.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class XPWishGiftTableViewCell, WishGiftInfoModel; +@protocol XPWishGiftTableViewCellDelegate + +///更新礼物信息 +- (void)xPWishGiftTableViewCell:(XPWishGiftTableViewCell *)view didUpdateWishGift:(WishGiftInfoModel *)info; + +///删除礼物信息 +- (void)xPWishGiftTableViewCell:(XPWishGiftTableViewCell *)view didClearWishGift:(WishGiftInfoModel *)info; + +@end + +@interface XPWishGiftTableViewCell : UITableViewCell +///代理 +@property (nonatomic,weak) id delegate; +@property (nonatomic,strong) WishGiftInfoModel *giftInfo; +///是否隐藏编辑 +@property (nonatomic,assign) BOOL isHiddenEdit; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m index 5298bd5..b749535 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m @@ -1,14 +1,12 @@ -// -// YMWishGiftTableViewCell.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftTableViewCell.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "UIImage+Utils.h" #import "NetImageView.h" @@ -16,23 +14,23 @@ @interface XPWishGiftTableViewCell () -///等级 + @property (nonatomic,strong) UILabel *levleLabel; -///礼物图片 + @property (nonatomic,strong) NetImageView *giftImageView; -///礼物名称 + @property (nonatomic,strong) UILabel *giftLabel; -///目标和编辑删除的容器 + @property (nonatomic,strong) UIStackView *stackView; -///目标 + @property (nonatomic,strong) UILabel *targetNumLabel; -///编辑 删除 + @property (nonatomic,strong) UIStackView *editStackView; -///编辑 + @property (nonatomic,strong) UIButton *updateButton; -///删除 + @property (nonatomic,strong) UIButton *clearButton; -///分割下 + @property (nonatomic,strong) UIView *lineView; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m.backup new file mode 100644 index 0000000..5298bd5 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/Cell/XPWishGiftTableViewCell.m.backup @@ -0,0 +1,235 @@ +// +// YMWishGiftTableViewCell.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftTableViewCell.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "UIImage+Utils.h" +#import "NetImageView.h" +#import "WishGiftInfoModel.h" + +@interface XPWishGiftTableViewCell () + +///等级 +@property (nonatomic,strong) UILabel *levleLabel; +///礼物图片 +@property (nonatomic,strong) NetImageView *giftImageView; +///礼物名称 +@property (nonatomic,strong) UILabel *giftLabel; +///目标和编辑删除的容器 +@property (nonatomic,strong) UIStackView *stackView; +///目标 +@property (nonatomic,strong) UILabel *targetNumLabel; +///编辑 删除 +@property (nonatomic,strong) UIStackView *editStackView; +///编辑 +@property (nonatomic,strong) UIButton *updateButton; +///删除 +@property (nonatomic,strong) UIButton *clearButton; +///分割下 +@property (nonatomic,strong) UIView *lineView; + +@end +@implementation XPWishGiftTableViewCell + + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + self.selectionStyle = UITableViewCellSelectionStyleNone; + self.backgroundColor = [UIColor clearColor]; + [self.contentView addSubview:self.levleLabel]; + [self.contentView addSubview:self.giftImageView]; + [self.contentView addSubview:self.giftLabel]; + [self.contentView addSubview:self.stackView]; + [self.contentView addSubview:self.lineView]; + + [self.stackView addArrangedSubview:self.targetNumLabel]; + [self.stackView addArrangedSubview:self.editStackView]; + + [self.editStackView addArrangedSubview:self.updateButton]; + [self.editStackView addArrangedSubview:self.clearButton]; +} + +- (void)initSubViewConstraints { + [self.levleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView); + make.leading.mas_equalTo(self.contentView).offset(15); + }]; + + [self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(24, 24)); + make.centerY.mas_equalTo(self.contentView); + make.leading.mas_equalTo(self.levleLabel.mas_trailing).offset(20); + }]; + + [self.giftLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView); + make.leading.mas_equalTo(self.giftImageView.mas_trailing).offset(8); + make.trailing.lessThanOrEqualTo(self.targetNumLabel.mas_leading).offset(-5); + }]; + + [self.stackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(18); + make.trailing.mas_equalTo(self.contentView).offset(-15); + make.centerY.mas_equalTo(self.contentView); + }]; + + [self.updateButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(44); + }]; + + [self.clearButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(44); + }]; + + [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.contentView).inset(13); + make.bottom.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + }]; + +} + +#pragma mark - Event Response +- (void)updateButtonAction:(UIButton *)sender { + if (self.delegate && [self.delegate respondsToSelector:@selector(xPWishGiftTableViewCell:didUpdateWishGift:)]) { + [self.delegate xPWishGiftTableViewCell:self didUpdateWishGift:self.giftInfo]; + } +} + + +- (void)clearButtonAction:(UIButton *)sender { + if (self.delegate && [self.delegate respondsToSelector:@selector(xPWishGiftTableViewCell:didClearWishGift:)]) { + [self.delegate xPWishGiftTableViewCell:self didClearWishGift:self.giftInfo]; + } +} + +#pragma mark - Getters And Setters +- (void)setIsHiddenEdit:(BOOL)isHiddenEdit { + _isHiddenEdit = isHiddenEdit; + self.editStackView.hidden = _isHiddenEdit; +} + +- (void)setGiftInfo:(WishGiftInfoModel *)giftInfo { + _giftInfo = giftInfo; + if (_giftInfo) { + self.levleLabel.text = [NSString stringWithFormat:@"%ld", _giftInfo.row]; + self.giftImageView.imageUrl = _giftInfo.giftUrl; + self.giftLabel.text = _giftInfo.giftName; + self.targetNumLabel.text = [NSString stringWithFormat:@"%ld/%ld", _giftInfo.actualNum, _giftInfo.targetNum]; + } +} + +- (UILabel *)levleLabel { + if (!_levleLabel) { + _levleLabel = [[UILabel alloc] init]; + _levleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _levleLabel.textColor = [DJDKMIMOMColor mainTextColor]; + } + return _levleLabel; +} + +- (NetImageView *)giftImageView { + if (!_giftImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _giftImageView = [[NetImageView alloc] initWithConfig:config]; + _giftImageView.layer.masksToBounds = YES; + _giftImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _giftImageView; +} + +- (UILabel *)giftLabel { + if (!_giftLabel) { + _giftLabel = [[UILabel alloc] init]; + _giftLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _giftLabel.textColor = [DJDKMIMOMColor mainTextColor]; + } + return _giftLabel; +} + +- (UIStackView *)stackView { + if (!_stackView) { + _stackView = [[UIStackView alloc] init]; + _stackView.axis = UILayoutConstraintAxisHorizontal; + _stackView.distribution = UIStackViewDistributionFill; + _stackView.alignment = UIStackViewAlignmentFill; + _stackView.spacing = 26; + } + return _stackView; +} + +- (UILabel *)targetNumLabel { + if (!_targetNumLabel) { + _targetNumLabel = [[UILabel alloc] init]; + _targetNumLabel.font = [UIFont systemFontOfSize:14]; + _targetNumLabel.textColor = [DJDKMIMOMColor textThirdColor]; + } + return _targetNumLabel; +} + +- (UIStackView *)editStackView { + if (!_editStackView) { + _editStackView = [[UIStackView alloc] init]; + _editStackView.axis = UILayoutConstraintAxisHorizontal; + _editStackView.distribution = UIStackViewDistributionFill; + _editStackView.alignment = UIStackViewAlignmentFill; + _editStackView.spacing = 5; + } + return _editStackView; +} + +- (UIButton *)updateButton { + if (!_updateButton) { + _updateButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_updateButton setTitle:YMLocalizedString(@"XPWishGiftTableViewCell0") forState:UIControlStateNormal]; + [_updateButton setTitleColor:[DJDKMIMOMColor confirmButtonTextColor] forState:UIControlStateNormal]; + _updateButton.titleLabel.font = [UIFont systemFontOfSize:10]; + [_updateButton setBackgroundImage:[UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor cancelButtonGradientStartColor], [DJDKMIMOMColor cancelButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)] forState:UIControlStateNormal]; + _updateButton.layer.masksToBounds = YES; + _updateButton.layer.cornerRadius = 9; + [_updateButton addTarget:self action:@selector(updateButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _updateButton; +} + +- (UIButton *)clearButton { + if (!_clearButton) { + _clearButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_clearButton setTitle:YMLocalizedString(@"XPWishGiftTableViewCell1") forState:UIControlStateNormal]; + [_clearButton setTitleColor:[DJDKMIMOMColor confirmButtonTextColor] forState:UIControlStateNormal]; + _clearButton.titleLabel.font = [UIFont systemFontOfSize:10]; + [_clearButton setBackgroundImage:[UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor], [DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)] forState:UIControlStateNormal]; + _clearButton.layer.masksToBounds = YES; + _clearButton.layer.cornerRadius = 9; + [_clearButton addTarget:self action:@selector(clearButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _clearButton; +} + +- (UIView *)lineView { + if (!_lineView) { + _lineView = [[UIView alloc] init]; + _lineView.backgroundColor = [DJDKMIMOMColor dividerColor]; + } + return _lineView; +} + + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h index 54573af..3cd8b28 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h @@ -1,16 +1,14 @@ -// -// YMWishGiftEnterView.h -// YUMI -// + + // Created by YUMI on 2022/10/20. -// + #import NS_ASSUME_NONNULL_BEGIN @interface XPWishGiftEnterView : UIView @property (nonatomic,strong) NSArray * giftList; -///是否在左边 + @property (nonatomic,assign) BOOL isLeft; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h.backup new file mode 100644 index 0000000..54573af --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.h.backup @@ -0,0 +1,17 @@ +// +// YMWishGiftEnterView.h +// YUMI +// +// Created by YUMI on 2022/10/20. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@interface XPWishGiftEnterView : UIView +@property (nonatomic,strong) NSArray * giftList; +///是否在左边 +@property (nonatomic,assign) BOOL isLeft; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m index f33c620..4eca410 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m @@ -1,32 +1,30 @@ -// -// YMWishGiftEnterView.m -// YUMI -// + + // Created by YUMI on 2022/10/20. -// + #import "XPWishGiftEnterView.h" -///Third + #import #import #import -///Tool + #import "DJDKMIMOMColor.h" #import "NetImageView.h" #import "UIImage+Utils.h" #import "UIView+Corner.h" #import "NSArray+Safe.h" -///Model + #import "WishGiftInfoModel.h" @interface XPWishGiftEnterCell : SDCollectionViewCell -///礼物 + @property (nonatomic,strong) NetImageView *giftImageView; -///礼物名称 + @property (nonatomic,strong) UILabel *giftLabel; -///进度 + @property (nonatomic,strong) UILabel *progressLabel; -///进度 + @property (nonatomic,strong) UIProgressView *progressView; @property (nonatomic,strong) WishGiftInfoModel *giftInfo; @end @@ -154,7 +152,7 @@ @end @interface XPWishGiftEnterView() -///文字轮播 + @property (nonatomic, strong) SDCycleScrollView *pi_BannerView; @end @@ -234,7 +232,7 @@ _pi_BannerView.delegate = self; _pi_BannerView.showPageControl = NO; _pi_BannerView.autoScrollTimeInterval = 10.0; - // SDCycleScrollView没有适配阿语,在RTL下会乱滚,都用LTR算了 + _pi_BannerView.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; for (UIView *subView in _pi_BannerView.subviews) { subView.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m.backup new file mode 100644 index 0000000..f33c620 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftEnterView.m.backup @@ -0,0 +1,245 @@ +// +// YMWishGiftEnterView.m +// YUMI +// +// Created by YUMI on 2022/10/20. +// + +#import "XPWishGiftEnterView.h" +///Third +#import +#import +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "NetImageView.h" +#import "UIImage+Utils.h" +#import "UIView+Corner.h" +#import "NSArray+Safe.h" +///Model +#import "WishGiftInfoModel.h" + +@interface XPWishGiftEnterCell : SDCollectionViewCell +///礼物 +@property (nonatomic,strong) NetImageView *giftImageView; +///礼物名称 +@property (nonatomic,strong) UILabel *giftLabel; +///进度 +@property (nonatomic,strong) UILabel *progressLabel; +///进度 +@property (nonatomic,strong) UIProgressView *progressView; +@property (nonatomic,strong) WishGiftInfoModel *giftInfo; +@end + +@implementation XPWishGiftEnterCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + self.contentView.backgroundColor = [UIColor clearColor]; + [self.contentView addSubview:self.giftImageView]; + [self.contentView addSubview:self.giftLabel]; + [self.contentView addSubview:self.progressLabel]; + [self.contentView addSubview:self.progressView]; +} + +- (void)initSubViewConstraints { + + [self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.top.bottom.mas_equalTo(self.contentView); + make.width.mas_equalTo(self.giftImageView.mas_height); + }]; + + [self.giftLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.giftImageView.mas_trailing).offset(6); + make.top.mas_equalTo(self.contentView).offset(0); + make.trailing.mas_equalTo(self.contentView).offset(-2); + }]; + + [self.progressLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.giftLabel); + make.trailing.mas_equalTo(self.contentView); + make.top.mas_equalTo(self.giftLabel.mas_bottom).offset(1); + }]; + + [self.progressView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(3); + make.bottom.mas_equalTo(self.contentView.mas_bottom).offset(-2); + make.leading.mas_equalTo(self.giftImageView.mas_trailing).offset(2); + make.trailing.mas_equalTo(self.contentView).offset(-5); + }]; +} + +- (NSAttributedString *)createProgressAttribute { + NSString * targetNum = [NSString stringWithFormat:@"/%ld", self.giftInfo.targetNum]; + NSString * actualNum = (self.giftInfo.actualNum > self.giftInfo.targetNum) ? [NSString stringWithFormat:@"%ld+", self.giftInfo.targetNum] : [NSString stringWithFormat:@"%ld", self.giftInfo.actualNum]; + NSString * title = [NSString stringWithFormat:@"%@%@", actualNum, targetNum]; + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] initWithString:title attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10], NSForegroundColorAttributeName:[DJDKMIMOMColor colorWithHexString:@"#FFC300"]}]; + if (self.giftInfo.targetNum <= self.giftInfo.actualNum) { + [attribute addAttribute:NSForegroundColorAttributeName value:[DJDKMIMOMColor colorWithHexString:@"#FFC300"] range:[title rangeOfString:targetNum]]; + } else { + [attribute addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithWhite:1 alpha:1] range:[title rangeOfString:targetNum]]; + } + return attribute; +} + +#pragma mark - Getters And Setters +- (void)setGiftInfo:(WishGiftInfoModel *)giftInfo { + _giftInfo = giftInfo; + if (_giftInfo) { + self.giftImageView.imageUrl = _giftInfo.giftUrl; + self.giftLabel.text = _giftInfo.giftName; + CGFloat value = (CGFloat)giftInfo.actualNum / (CGFloat)giftInfo.targetNum; + if (value > 1){ + value = 1; + } + [self.progressView setProgress:value animated:NO]; + self.progressLabel.attributedText = [self createProgressAttribute]; + self.progressLabel.textAlignment = NSTextAlignmentCenter; + } +} + +- (UIProgressView *)progressView { + if(!_progressView) { + _progressView = [[UIProgressView alloc] init]; + _progressView.layer.masksToBounds = YES; + _progressView.layer.cornerRadius = 1.5; + _progressView.trackImage = [UIImage imageWithColor:[DJDKMIMOMColor colorWithHexString:@"#17093E"]]; + _progressView.progressImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#FFA0C3"], [DJDKMIMOMColor colorWithHexString:@"#C176FF"]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(1, 1)]; + } + return _progressView; +} + +- (NetImageView *)giftImageView { + if (!_giftImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _giftImageView = [[NetImageView alloc] initWithConfig:config]; + _giftImageView.layer.masksToBounds = YES; + _giftImageView.layer.cornerRadius = 15; + _giftImageView.layer.borderWidth = 0.5; + _giftImageView.layer.borderColor = UIColorRGBAlpha(0xFFEEBE, 0.7).CGColor; + _giftImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _giftImageView; +} + +- (UILabel *)giftLabel { + if (!_giftLabel) { + _giftLabel = [[UILabel alloc] init]; + _giftLabel.font = [UIFont systemFontOfSize:10]; + _giftLabel.textAlignment = NSTextAlignmentCenter; + _giftLabel.textColor = [UIColor whiteColor]; + _giftLabel.textAlignment = NSTextAlignmentCenter; + } + return _giftLabel; +} + +- (UILabel *)progressLabel { + if (!_progressLabel) { + _progressLabel = [[UILabel alloc] init]; + } + return _progressLabel; +} + +@end + +@interface XPWishGiftEnterView() +///文字轮播 +@property (nonatomic, strong) SDCycleScrollView *pi_BannerView; + +@end + +@implementation XPWishGiftEnterView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + self.isLeft = NO; + } + return self; +} + + +#pragma mark - Private Method +- (void)initSubViews { + self.backgroundColor = [UIColor colorWithWhite:1 alpha:0.2]; + [self addSubview:self.pi_BannerView]; + self.layer.masksToBounds = YES; +} + +- (void)initSubViewConstraints { + [self.pi_BannerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; + +} + +#pragma mark - SDCycleScrollViewDelegate +- (Class)customCollectionViewCellClassForCycleScrollView:(SDCycleScrollView *)view { + return XPWishGiftEnterCell.class; +} + +- (void)setupCustomCell:(UICollectionViewCell *)cell forIndex:(NSInteger)index cycleScrollView:(SDCycleScrollView *)view { + XPWishGiftEnterCell *myCell = (XPWishGiftEnterCell *)cell; + WishGiftInfoModel * info = [self.giftList xpSafeObjectAtIndex:index]; + myCell.giftInfo = info; +} +#pragma mark - Getters And Setters +- (void)setIsLeft:(BOOL)isLeft { + _isLeft = isLeft; + for (CALayer * layer in self.layer.sublayers) { + if ([layer isKindOfClass:[CAShapeLayer class]]) { + [layer removeFromSuperlayer]; + } + } + + if (_isLeft) { + [self setCornerWithLeftTopCorner:0 rightTopCorner:15 bottomLeftCorner:0 bottomRightCorner:15 size:CGSizeMake(81, 30)]; + } else { + [self setCornerWithLeftTopCorner:15 rightTopCorner:0 bottomLeftCorner:15 bottomRightCorner:0 size:CGSizeMake(81, 30)]; + } +} + +- (void)setGiftList:(NSArray *)giftList { + _giftList = giftList; + if (_giftList.count > 0) { + NSMutableArray * array = [NSMutableArray array]; + for (WishGiftInfoModel * item in _giftList) { + [array addObject:item.giftName]; + } + if (array.count > 0) { + self.pi_BannerView.imageURLStringsGroup = array; + [self.pi_BannerView autoScroll]; + } + } +} + +- (SDCycleScrollView *)pi_BannerView { + if (!_pi_BannerView) { + _pi_BannerView = [[SDCycleScrollView alloc] init]; + _pi_BannerView.backgroundColor = [UIColor clearColor]; + _pi_BannerView.layer.masksToBounds = YES; + _pi_BannerView.delegate = self; + _pi_BannerView.showPageControl = NO; + _pi_BannerView.autoScrollTimeInterval = 10.0; + // SDCycleScrollView没有适配阿语,在RTL下会乱滚,都用LTR算了 + _pi_BannerView.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + for (UIView *subView in _pi_BannerView.subviews) { + subView.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + } + } + return _pi_BannerView; +} +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h index d35eef9..0b02011 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h @@ -1,9 +1,7 @@ -// -// YMWishGiftInfoView.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import @@ -20,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong) WishGiftInfoModel *giftInfo; -///代理 + @property (nonatomic,weak) id delegate; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h.backup new file mode 100644 index 0000000..d35eef9 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.h.backup @@ -0,0 +1,28 @@ +// +// YMWishGiftInfoView.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class WishGiftInfoModel, XPWishGiftInfoView; + +@protocol XPWishGiftInfoViewDelegate + +- (void)xPWishGiftInfoView:(XPWishGiftInfoView *)view didClickSender:(WishGiftInfoModel *)info; + +@end + +@interface XPWishGiftInfoView : UIView + +@property (nonatomic,strong) WishGiftInfoModel *giftInfo; + +///代理 +@property (nonatomic,weak) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m index 96f0515..8651c35 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m @@ -1,36 +1,34 @@ -// -// YMWishGiftInfoView.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftInfoView.h" -///Third + #import -///Tool + #import "NetImageView.h" #import "DJDKMIMOMColor.h" #import "UIImage+Utils.h" -///Model + #import "WishGiftInfoModel.h" @interface XPWishGiftInfoView () -///背景 + @property (nonatomic,strong) UIImageView *bgView; -///礼物的图片 + @property (nonatomic,strong) NetImageView *giftImageView; -///礼物名称 + @property (nonatomic,strong) UILabel *giftLabel; -///价格 + @property (nonatomic,strong) UILabel *priceLabel; -///进度 + @property (nonatomic,strong) UILabel *progressLabel; -///进度条 + @property (nonatomic,strong) UIProgressView *progressView; -///赠送按钮 + @property (nonatomic,strong) UIButton *senderButton; -///完成按钮 + @property (nonatomic,strong) UIImageView *completionImageView; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m.backup new file mode 100644 index 0000000..96f0515 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftInfoView.m.backup @@ -0,0 +1,245 @@ +// +// YMWishGiftInfoView.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftInfoView.h" +///Third +#import +///Tool +#import "NetImageView.h" +#import "DJDKMIMOMColor.h" +#import "UIImage+Utils.h" +///Model +#import "WishGiftInfoModel.h" + +@interface XPWishGiftInfoView () +///背景 +@property (nonatomic,strong) UIImageView *bgView; +///礼物的图片 +@property (nonatomic,strong) NetImageView *giftImageView; +///礼物名称 +@property (nonatomic,strong) UILabel *giftLabel; +///价格 +@property (nonatomic,strong) UILabel *priceLabel; +///进度 +@property (nonatomic,strong) UILabel *progressLabel; +///进度条 +@property (nonatomic,strong) UIProgressView *progressView; +///赠送按钮 +@property (nonatomic,strong) UIButton *senderButton; +///完成按钮 +@property (nonatomic,strong) UIImageView *completionImageView; + +@end + +@implementation XPWishGiftInfoView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + [self addSubview:self.bgView]; + [self.bgView addSubview:self.giftImageView]; + [self.bgView addSubview:self.giftLabel]; + [self.bgView addSubview:self.priceLabel]; + [self.bgView addSubview:self.progressLabel]; + [self.bgView addSubview:self.progressView]; + [self.bgView addSubview:self.senderButton]; +} + +- (void)initSubViewConstraints { + [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + + [self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(50, 50)); + make.top.mas_equalTo(self.bgView).offset(6); + make.centerX.mas_equalTo(self.bgView); + }]; + + [self.giftLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.bgView).inset(2); + make.top.mas_equalTo(self.giftImageView.mas_bottom).offset(4); + }]; + + [self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.bgView).inset(2); + make.top.mas_equalTo(self.giftLabel.mas_bottom).offset(4); + }]; + + [self.progressView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.bgView).inset(10); + make.top.mas_equalTo(self.priceLabel.mas_bottom).offset(10); + make.height.mas_equalTo(5); + }]; + + [self.progressLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.bgView); + make.top.mas_equalTo(self.progressView.mas_bottom).offset(4); + }]; + + [self.senderButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(76, 22)); + make.centerX.mas_equalTo(self.bgView); + make.bottom.mas_equalTo(self.bgView.mas_bottom).offset(-10); + }]; +} + +- (NSAttributedString *)createProgressAttribute { + NSString * targetNum = [NSString stringWithFormat:@"/%ld", self.giftInfo.targetNum]; + NSString * actualNum = (self.giftInfo.actualNum > self.giftInfo.targetNum) ? [NSString stringWithFormat:@"%ld+", self.giftInfo.targetNum] : [NSString stringWithFormat:@"%ld", self.giftInfo.actualNum]; + NSString * title = [NSString stringWithFormat:@"%@%@", actualNum, targetNum]; + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] initWithString:title attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10], NSForegroundColorAttributeName:[DJDKMIMOMColor colorWithHexString:@"#FFA0C3"]}]; + if (self.giftInfo.targetNum <= self.giftInfo.actualNum) { + [attribute addAttribute:NSForegroundColorAttributeName value:[DJDKMIMOMColor colorWithHexString:@"#FFA0C3"] range:[title rangeOfString:targetNum]]; + } else { + [attribute addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithWhite:1 alpha:0.5] range:[title rangeOfString:targetNum]]; + } + return attribute; +} + +#pragma mark - Event Response +- (void)senderButtonAction:(UIButton *)sender { + if (self.delegate && [self.delegate respondsToSelector:@selector(xPWishGiftInfoView:didClickSender:)]) { + [self.delegate xPWishGiftInfoView:self didClickSender:self.giftInfo]; + } +} + +#pragma mark - Getters And Setters +- (void)setGiftInfo:(WishGiftInfoModel *)giftInfo { + _giftInfo = giftInfo; + if (_giftInfo) { + self.giftImageView.imageUrl = giftInfo.giftUrl; + self.giftLabel.text = _giftInfo.giftName; + self.priceLabel.text = [NSString stringWithFormat:YMLocalizedString(@"XPWishGiftInfoView0"), _giftInfo.goldPrice]; + CGFloat value = (CGFloat)giftInfo.actualNum / (CGFloat)giftInfo.targetNum; + if (value > 1) { + value = 1; + } + self.progressView.progress = value; + self.progressLabel.attributedText = [self createProgressAttribute]; + self.progressLabel.textAlignment = NSTextAlignmentCenter; + self.completionImageView.hidden = _giftInfo.targetNum != _giftInfo.actualNum; + } +} + +- (UIImageView *)bgView { + if (!_bgView) { + _bgView = [[UIImageView alloc] init]; + _bgView.userInteractionEnabled = YES; + _bgView.image = [UIImage imageNamed:@"room_wish_gift_panel_gift_bg"]; + } + return _bgView; +} + +- (UIImageView *)completionImageView { + if (!_completionImageView) { + _completionImageView = [[UIImageView alloc] init]; + _completionImageView.userInteractionEnabled = YES; + _completionImageView.image = [UIImage imageNamed:@"room_wish_gift_completion"]; + } + return _completionImageView; +} + + +- (NetImageView *)giftImageView { + if (!_giftImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _giftImageView = [[NetImageView alloc] initWithConfig:config]; + _giftImageView.layer.masksToBounds = YES; + _giftImageView.layer.cornerRadius = 20; + _giftImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _giftImageView; +} + +- (UILabel *)giftLabel { + if (!_giftLabel) { + _giftLabel = [[UILabel alloc] init]; + _giftLabel.font = [UIFont systemFontOfSize:14]; + _giftLabel.textAlignment = NSTextAlignmentCenter; + _giftLabel.textColor = [UIColor whiteColor]; + } + return _giftLabel; +} + +- (UILabel *)priceLabel { + if (!_priceLabel) { + _priceLabel = [[UILabel alloc] init]; + _priceLabel.font = [UIFont systemFontOfSize:12]; + _priceLabel.textColor = [UIColor colorWithWhite:1 alpha:0.5]; + _priceLabel.textAlignment = NSTextAlignmentCenter; + } + return _priceLabel; +} + +- (UIProgressView *)progressView { + if(!_progressView) { + _progressView = [[UIProgressView alloc] init]; + _progressView.progressImage = [UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#FFA0C3"], [DJDKMIMOMColor colorWithHexString:@"#C176FF"]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(1, 1)]; + _progressView.layer.masksToBounds = YES; + _progressView.layer.cornerRadius = 2.5; + _progressView.trackImage = [UIImage imageWithColor:[DJDKMIMOMColor colorWithHexString:@"#17093E"]]; + } + return _progressView; +} + +-(UIImage *)getGradientImageWithColors:(NSArray*)colors imgSize:(CGSize)imgSize +{ + NSMutableArray *arRef = [NSMutableArray array]; + for(UIColor *ref in colors) { + [arRef addObject:(id)ref.CGColor]; + + } + UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]); + CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)arRef, NULL); + CGPoint start = CGPointMake(0.0, 0.0); + CGPoint end = CGPointMake(imgSize.width, imgSize.height); + CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + CGGradientRelease(gradient); + CGContextRestoreGState(context); + CGColorSpaceRelease(colorSpace); + UIGraphicsEndImageContext(); + return image; +} + +- (UILabel *)progressLabel { + if (!_progressLabel) { + _progressLabel = [[UILabel alloc] init]; + } + return _progressLabel; +} + +- (UIButton *)senderButton { + if (!_senderButton) { + _senderButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_senderButton setTitle:YMLocalizedString(@"XPWishGiftInfoView1") forState:UIControlStateNormal]; + [_senderButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _senderButton.titleLabel.font = [UIFont systemFontOfSize:12]; + [_senderButton setBackgroundImage:[UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor colorWithHexString:@"#FFA0C3"], [DJDKMIMOMColor colorWithHexString:@"#C176FF"]] gradientType:GradientTypeUpleftToLowright imgSize:CGSizeMake(10, 10)] forState:UIControlStateNormal]; + _senderButton.layer.masksToBounds = YES; + _senderButton.layer.cornerRadius = 11; + [_senderButton addTarget:self action:@selector(senderButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _senderButton; +} + + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h index f8971d9..a3c9d1a 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h @@ -1,9 +1,7 @@ -// -// YMWishGiftListView.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import @@ -12,17 +10,17 @@ NS_ASSUME_NONNULL_BEGIN @protocol XPWishGiftListViewDelegate -///点击了某个item + - (void)xPWishGiftListView:(XPWishGiftListView *)view didSelectItem:(WishGiftInfoModel *)info; @end @interface XPWishGiftListView : UIView -///显示的数据源 + @property (nonatomic,strong) NSArray *datasource; -///代理 + @property (nonatomic,weak) id delegate; - (void)configDefaultInfo:(WishGiftInfoModel *)giftInfo; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h.backup new file mode 100644 index 0000000..f8971d9 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.h.backup @@ -0,0 +1,30 @@ +// +// YMWishGiftListView.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class WishGiftInfoModel, XPWishGiftListView; + +@protocol XPWishGiftListViewDelegate + +///点击了某个item +- (void)xPWishGiftListView:(XPWishGiftListView *)view didSelectItem:(WishGiftInfoModel *)info; + +@end + +@interface XPWishGiftListView : UIView + +///显示的数据源 +@property (nonatomic,strong) NSArray *datasource; + +///代理 +@property (nonatomic,weak) id delegate; +- (void)configDefaultInfo:(WishGiftInfoModel *)giftInfo; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m index 4ead0c3..9b58f0d 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m @@ -1,21 +1,19 @@ -// -// YMWishGiftListView.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftListView.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "NSArray+Safe.h" -///Model + #import "WishGiftInfoModel.h" @interface XPWishGiftListTableViewCell : UITableViewCell -///显示内容 + @property (nonatomic,strong) UILabel *titleLabel; @end @@ -58,19 +56,19 @@ @interface XPWishGiftListView () -///容器 + @property (nonatomic,strong) UIStackView *stackView; -///选中的时候容器 + @property (nonatomic,strong) UIView *selectView; -///标题 + @property (nonatomic,strong) UILabel *titlelable; -///箭头 + @property (nonatomic,strong) UIImageView *arrowImageView; -///列表 + @property (nonatomic,strong) UITableView *tableView; -///原始数据源 + @property (nonatomic,strong) NSArray *gameList; -///s是否选择 + @property (nonatomic,assign) BOOL isSelect; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m.backup new file mode 100644 index 0000000..4ead0c3 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftListView.m.backup @@ -0,0 +1,259 @@ +// +// YMWishGiftListView.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftListView.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "NSArray+Safe.h" +///Model +#import "WishGiftInfoModel.h" + +@interface XPWishGiftListTableViewCell : UITableViewCell +///显示内容 +@property (nonatomic,strong) UILabel *titleLabel; +@end + +@implementation XPWishGiftListTableViewCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +- (void)initSubViews { + self.backgroundColor = UIColor.clearColor; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self.contentView addSubview:self.titleLabel]; +} + +- (void)initSubViewConstraints { + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.contentView).inset(13); + make.centerY.mas_equalTo(self.contentView); + }]; +} + +#pragma mark - Getters And Setters + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14]; + _titleLabel.textColor = [DJDKMIMOMColor secondTextColor]; + } + return _titleLabel; +} + +@end + + +@interface XPWishGiftListView () +///容器 +@property (nonatomic,strong) UIStackView *stackView; +///选中的时候容器 +@property (nonatomic,strong) UIView *selectView; +///标题 +@property (nonatomic,strong) UILabel *titlelable; +///箭头 +@property (nonatomic,strong) UIImageView *arrowImageView; +///列表 +@property (nonatomic,strong) UITableView *tableView; +///原始数据源 +@property (nonatomic,strong) NSArray *gameList; +///s是否选择 +@property (nonatomic,assign) BOOL isSelect; +@end + +@implementation XPWishGiftListView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + + } + return self; +} +#pragma mark - Public Method +- (void)configDefaultInfo:(WishGiftInfoModel *)giftInfo { + if (giftInfo.levelName) { + self.titlelable.text = giftInfo.levelName; + } else { + self.titlelable.text = giftInfo.giftName; + } +} + +#pragma mark - Private Method +- (void)initSubViews { + self.layer.masksToBounds = YES; + self.layer.cornerRadius = 4; + self.backgroundColor = UIColor.clearColor; + [self addSubview:self.stackView]; + [self.stackView addArrangedSubview:self.selectView]; + [self.stackView addArrangedSubview:self.tableView]; + + [self.selectView addSubview:self.titlelable]; + [self.selectView addSubview:self.arrowImageView]; + +} + +- (void)initSubViewConstraints { + [self mas_makeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.stackView.mas_bottom); + }]; + + [self.stackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self); + make.top.mas_equalTo(self); + }]; + + [self.selectView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(36); + }]; + + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(36); + }]; + + [self.arrowImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(22, 22)); + make.trailing.mas_equalTo(self.selectView.mas_trailing).offset(-11); + make.centerY.mas_equalTo(self.selectView); + }]; + + [self.titlelable mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.selectView); + make.leading.mas_equalTo(self.selectView).offset(13); + }]; +} + + +#pragma mark - UITableViewDelegate And UITableViewDataSource +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.datasource.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + XPWishGiftListTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPWishGiftListTableViewCell class])]; + if (cell == nil) { + cell = [[XPWishGiftListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([XPWishGiftListTableViewCell class])]; + } + if (self.datasource.count > 0 ) { + WishGiftInfoModel * giftInfo = [self.datasource xpSafeObjectAtIndex:indexPath.row]; + if (giftInfo.level > 0) { + cell.titleLabel.text = giftInfo.levelName; + } else { + cell.titleLabel.text = giftInfo.giftName; + } + } + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 36; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (self.datasource.count > 0) { + if (self.delegate && [self.delegate respondsToSelector:@selector(xPWishGiftListView:didSelectItem:)]) { + WishGiftInfoModel * giftInfo = [self.datasource xpSafeObjectAtIndex:indexPath.row]; + [self configDefaultInfo:giftInfo]; + [self.delegate xPWishGiftListView:self didSelectItem:giftInfo]; + } + self.tableView.hidden = YES; + } +} + +#pragma mark - Event Response +- (void)gamePlayButtonAction:(UIButton *)sender { + self.isSelect = !self.isSelect; + self.tableView.hidden = !self.isSelect; + if (!self.tableView.hidden) { + if (_datasource.count > 0 && _datasource.count < 4) { + [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(36 * self.datasource.count); + }]; + } else { + [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(36 * 3); + }]; + } + } +} + +#pragma mark - Getters And Setters +- (void)setDatasource:(NSArray *)datasource { + _datasource = datasource; + [self.tableView reloadData]; +} + +- (UIStackView *)stackView { + if (!_stackView) { + _stackView = [[UIStackView alloc] init]; + _stackView.axis = UILayoutConstraintAxisVertical; + _stackView.distribution = UIStackViewDistributionFill; + _stackView.alignment = UIStackViewAlignmentFill; + _stackView.spacing = 0; + } + return _stackView; +} + +- (UIView *)selectView { + if (!_selectView) { + _selectView = [[UIView alloc] init]; + _selectView.backgroundColor = [UIColor clearColor]; + _selectView.backgroundColor = [DJDKMIMOMColor colorWithHexString:@"#E4E4E4"]; + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gamePlayButtonAction:)]; + [_selectView addGestureRecognizer:tap]; + } + return _selectView; +} +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.tableFooterView = [UIView new]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _tableView.backgroundColor = [DJDKMIMOMColor colorWithHexString:@"#F4F4F4"]; + _tableView.hidden = YES; + if (@available(iOS 11.0, *)) { + _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [_tableView registerClass:[XPWishGiftListTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPWishGiftListTableViewCell class])]; + } + return _tableView; +} + +- (UIImageView *)arrowImageView { + if (!_arrowImageView) { + _arrowImageView = [[UIImageView alloc] init]; + _arrowImageView.userInteractionEnabled = YES; + _arrowImageView.image = [UIImage imageNamed:@"room_wish_create_arrow"]; + } + return _arrowImageView; +} + +- (UILabel *)titlelable { + if (!_titlelable) { + _titlelable = [[UILabel alloc] init]; + _titlelable.font = [UIFont systemFontOfSize:14]; + _titlelable.textColor = [DJDKMIMOMColor mainTextColor]; + } + return _titlelable; +} + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h index 197aa73..ccddb8c 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h @@ -1,9 +1,7 @@ -// -// YMWishGiftSectionView.h -// YUMI -// + + // Created by YUMI on 2022/10/19. -// + #import diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h.backup new file mode 100644 index 0000000..197aa73 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.h.backup @@ -0,0 +1,16 @@ +// +// YMWishGiftSectionView.h +// YUMI +// +// Created by YUMI on 2022/10/19. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface XPWishGiftSectionView : UIView +@property (nonatomic,copy) NSString *title; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m index f732a38..f6fe5b8 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m @@ -1,18 +1,16 @@ -// -// YMWishGiftSectionView.m -// YUMI -// + + // Created by YUMI on 2022/10/19. -// + #import "XPWishGiftSectionView.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" @interface XPWishGiftSectionView () -///标题 + @property (nonatomic,strong) UILabel *titleLabel; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m.backup new file mode 100644 index 0000000..f732a38 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/View/XPWishGiftSectionView.m.backup @@ -0,0 +1,55 @@ +// +// YMWishGiftSectionView.m +// YUMI +// +// Created by YUMI on 2022/10/19. +// + +#import "XPWishGiftSectionView.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" + +@interface XPWishGiftSectionView () +///标题 +@property (nonatomic,strong) UILabel *titleLabel; +@end + +@implementation XPWishGiftSectionView +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +- (void)initSubViews { + [self addSubview:self.titleLabel]; +} + +- (void)initSubViewConstraints { + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self).offset(24); + make.centerY.mas_equalTo(self); + }]; +} + +- (void)setTitle:(NSString *)title { + _title = title; + self.titleLabel.text = _title; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + _titleLabel.textColor = [DJDKMIMOMColor mainTextColor]; + } + return _titleLabel; +} + + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h index ed7fb9a..0b719dc 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h @@ -1,28 +1,26 @@ -// -// YMWishGiftCreateItemViewController.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "MvpViewController.h" NS_ASSUME_NONNULL_BEGIN @class WishGiftInfoModel; @interface XPWishGiftCreateItemViewController : MvpViewController -///初级礼物 + @property (nonatomic,strong) NSArray *levelOneGiftList; -///中级礼物 + @property (nonatomic,strong) NSArray *levelTwoGiftList; -///高级礼物 + @property (nonatomic,strong) NSArray *levelThirdGiftList; -///房主的uid + @property (nonatomic,strong) NSString *roomUid; -///需要修改的礼物信息 + @property (nonatomic,strong) WishGiftInfoModel *modifiGiftInfo; -///创建完成 + @property (nonatomic,copy) void(^Dismiss)(BOOL finish); @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h.backup new file mode 100644 index 0000000..ed7fb9a --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.h.backup @@ -0,0 +1,29 @@ +// +// YMWishGiftCreateItemViewController.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "MvpViewController.h" + +NS_ASSUME_NONNULL_BEGIN +@class WishGiftInfoModel; +@interface XPWishGiftCreateItemViewController : MvpViewController +///初级礼物 +@property (nonatomic,strong) NSArray *levelOneGiftList; +///中级礼物 +@property (nonatomic,strong) NSArray *levelTwoGiftList; +///高级礼物 +@property (nonatomic,strong) NSArray *levelThirdGiftList; +///房主的uid +@property (nonatomic,strong) NSString *roomUid; + +///需要修改的礼物信息 +@property (nonatomic,strong) WishGiftInfoModel *modifiGiftInfo; + +///创建完成 +@property (nonatomic,copy) void(^Dismiss)(BOOL finish); +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m index 538714e..60c6219 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m @@ -1,52 +1,50 @@ -// -// YMWishGiftCreateItemViewController.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftCreateItemViewController.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "UIImage+Utils.h" #import "NSArray+Safe.h" -///View + #import "XPWishGiftListView.h" #import "WishGiftInfoModel.h" -///P + #import "XPWishGiftPresenter.h" #import "XPWishGiftProtocol.h" @interface XPWishGiftCreateItemViewController () -///背景 + @property (nonatomic,strong) UIView *topView; -///背景 + @property (nonatomic,strong) UIView * bottomView; -///背景 + @property (nonatomic,strong) UIView *backView; -///等级 + @property (nonatomic,strong) XPWishGiftListView *levelView; -///礼物 + @property (nonatomic,strong) XPWishGiftListView *giftView; -///数量 + @property (nonatomic,strong) UIStackView *numberStackView; -///减 + @property (nonatomic,strong) UIButton *subtractButton; -///输入框 + @property (nonatomic,strong) MSBaseTextField *textField; -///添加 + @property (nonatomic,strong) UIButton *addButton; -///关闭按钮 + @property (nonatomic,strong) UIButton *sureButton; -///个数 + @property (nonatomic,assign) int number; -///礼物等级 + @property (nonatomic,strong) NSArray *levelLists; -///礼物等级 + @property (nonatomic,strong) WishGiftInfoModel *levleInfo; -///礼物信息 + @property (nonatomic,strong) WishGiftInfoModel *giftInfo; @end @@ -222,11 +220,11 @@ - (void)xPWishGiftListView:(XPWishGiftListView *)view didSelectItem:(WishGiftInfoModel *)info { if (view == self.levelView) { self.levleInfo = info; - ///处理等级 + [self handleLevleDatasource:info.level]; WishGiftInfoModel * giftInfo; if (info.level == WishGiftLevel_Normal) { - ///处理等级对应的礼物 + if (self.levelOneGiftList.count > 0) { giftInfo = self.levelOneGiftList.firstObject; } @@ -353,9 +351,9 @@ self.giftInfo = _modifiGiftInfo; [self.levelView configDefaultInfo:levelInfo]; [self.giftView configDefaultInfo:_modifiGiftInfo]; - ///处理等级 + [self handleLevleDatasource:levelInfo.level]; - ///处理等级 + if (_modifiGiftInfo.level == WishGiftLevel_Normal) { if (self.levelOneGiftList.count <=0) { [self.presenter wishGiftConfigList:self.roomUid level:@"1"]; @@ -518,5 +516,4 @@ } - @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m.backup new file mode 100644 index 0000000..538714e --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateItemViewController.m.backup @@ -0,0 +1,522 @@ +// +// YMWishGiftCreateItemViewController.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftCreateItemViewController.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "UIImage+Utils.h" +#import "NSArray+Safe.h" +///View +#import "XPWishGiftListView.h" +#import "WishGiftInfoModel.h" +///P +#import "XPWishGiftPresenter.h" +#import "XPWishGiftProtocol.h" + +@interface XPWishGiftCreateItemViewController () +///背景 +@property (nonatomic,strong) UIView *topView; +///背景 +@property (nonatomic,strong) UIView * bottomView; +///背景 +@property (nonatomic,strong) UIView *backView; +///等级 +@property (nonatomic,strong) XPWishGiftListView *levelView; +///礼物 +@property (nonatomic,strong) XPWishGiftListView *giftView; +///数量 +@property (nonatomic,strong) UIStackView *numberStackView; +///减 +@property (nonatomic,strong) UIButton *subtractButton; +///输入框 +@property (nonatomic,strong) MSBaseTextField *textField; +///添加 +@property (nonatomic,strong) UIButton *addButton; +///关闭按钮 +@property (nonatomic,strong) UIButton *sureButton; +///个数 +@property (nonatomic,assign) int number; +///礼物等级 +@property (nonatomic,strong) NSArray *levelLists; +///礼物等级 +@property (nonatomic,strong) WishGiftInfoModel *levleInfo; +///礼物信息 +@property (nonatomic,strong) WishGiftInfoModel *giftInfo; +@end + +@implementation XPWishGiftCreateItemViewController + +- (__kindof id)createPresenter { + return [[XPWishGiftPresenter alloc] init]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = UIColorRGBAlpha(0x000000, 0.5); + [self initWishGiftCongifList]; + [self initSubViews]; + [self initSubViewConstraints]; +} + + +#pragma mark - Private Method +- (void)initWishGiftCongifList { + if (self.modifiGiftInfo == nil) { + self.number = 10; + self.levleInfo = self.levelLists.firstObject; + [self handleLevleDatasource:self.levleInfo.level]; + [self.levelView configDefaultInfo:self.levleInfo]; + if (self.levelOneGiftList.count > 0) { + self.giftInfo = self.levelOneGiftList.firstObject; + [self.giftView configDefaultInfo:self.giftInfo]; + [self handleGiftDatasource:self.levelOneGiftList giftId:self.giftInfo.giftId];; + } + } + [self loadWishGiftLevelList]; +} + +- (void)loadWishGiftLevelList { + if (self.levelOneGiftList.count <= 0) { + [self.presenter wishGiftConfigList:self.roomUid level:@"1"]; + } else if(self.levelTwoGiftList.count <= 0) { + [self.presenter wishGiftConfigList:self.roomUid level:@"2"]; + } else if(self.levelThirdGiftList.count <= 0) { + [self.presenter wishGiftConfigList:self.roomUid level:@"3"]; + } +} + +- (void)initSubViews { + [self.view addSubview:self.topView]; + [self.view addSubview:self.backView]; + [self.view addSubview:self.bottomView]; + + [self.backView addSubview:self.sureButton]; + [self.backView addSubview:self.numberStackView]; + [self.backView addSubview:self.giftView]; + [self.backView addSubview:self.levelView]; + + [self.numberStackView addArrangedSubview:self.subtractButton]; + [self.numberStackView addArrangedSubview:self.textField]; + [self.numberStackView addArrangedSubview:self.addButton]; +} + +- (void)initSubViewConstraints { + [self.topView mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.top.leading.mas_equalTo(self.view); + make.bottom.mas_equalTo(self.backView.mas_top); + }]; + + [self.backView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.view).inset(38); + make.height.mas_equalTo(245); + make.centerY.mas_equalTo(self.view); + }]; + + [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.mas_equalTo(self.view); + make.top.mas_equalTo(self.backView.mas_bottom); + }]; + + [self.levelView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.backView).inset(30); + make.top.mas_equalTo(self.backView).offset(36); + }]; + + + [self.giftView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.backView).inset(30); + make.top.mas_equalTo(self.backView).offset(84); + }]; + + [self.numberStackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.levelView); + make.height.mas_equalTo(36); + make.bottom.mas_equalTo(self.sureButton.mas_top).offset(-20); + }]; + + [self.subtractButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(36); + }]; + + [self.addButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(36); + }]; + + [self.sureButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(129, 37)); + make.centerX.mas_equalTo(self.backView); + make.bottom.mas_equalTo(self.backView.mas_bottom).offset(-20); + }]; +} + +- (int)addMaxCount { + if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController0")]) { + return 999; + } else if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController1")]) { + return 99; + } else { + return 30; + } +} + +- (BOOL)canAddMaxCount:(int)count { + if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController2")]) { + return count <= 999; + } else if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController3")]) { + return count <= 99; + } else { + return count <= 30; + } +} + +- (BOOL)canSubtractMinCount:(int)count { + if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController4")]) { + return count >= 10; + } else if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController5")]) { + return count >= 10; + } else { + return count >= 1; + } +} + +- (int)subtractMinCount { + if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController6")]) { + return 10; + } else if ([self.levleInfo.levelName isEqualToString:YMLocalizedString(@"XPWishGiftCreateItemViewController7")]) { + return 10; + } else { + return 1; + } +} + + +- (void)handleLevleDatasource:(WishGiftLevel)levele { + NSMutableArray * array = [self.levelLists mutableCopy]; + for (int i = 0;i < self.levelLists.count;i++) { + WishGiftInfoModel * infor = [self.levelLists xpSafeObjectAtIndex:i]; + if (infor.level == levele) { + [array removeObject:infor]; + } + } + self.levelView.datasource = array.copy; +} + +- (void)handleGiftDatasource:(NSArray *)levels giftId:(NSInteger)giftId { + NSMutableArray * array = [levels mutableCopy]; + for (int i = 0;i < levels.count;i++) { + WishGiftInfoModel * infor = [levels xpSafeObjectAtIndex:i]; + if (infor.giftId == giftId) { + [array removeObject:infor]; + } + } + self.giftView.datasource = array.copy; +} + +#pragma mark - XPWishGiftListViewDelegate +- (void)xPWishGiftListView:(XPWishGiftListView *)view didSelectItem:(WishGiftInfoModel *)info { + if (view == self.levelView) { + self.levleInfo = info; + ///处理等级 + [self handleLevleDatasource:info.level]; + WishGiftInfoModel * giftInfo; + if (info.level == WishGiftLevel_Normal) { + ///处理等级对应的礼物 + if (self.levelOneGiftList.count > 0) { + giftInfo = self.levelOneGiftList.firstObject; + } + self.textField.text = @"10"; + [self handleGiftDatasource:self.levelOneGiftList giftId:giftInfo.giftId]; + } else if (info.level == WishGiftLevel_Middle) { + if (self.levelTwoGiftList.count > 0) { + giftInfo = self.levelTwoGiftList.firstObject; + } + self.textField.text = @"10"; + [self handleGiftDatasource:self.levelTwoGiftList giftId:giftInfo.giftId]; + } else { + if (self.levelThirdGiftList.count > 0) { + giftInfo = self.levelThirdGiftList.firstObject; + } + self.textField.text = @"1"; + [self handleGiftDatasource:self.levelThirdGiftList giftId:giftInfo.giftId]; + } + self.giftInfo = giftInfo; + self.number = self.textField.text.intValue; + [self.giftView configDefaultInfo:giftInfo]; + } else { + self.giftInfo = info; + [self.giftView configDefaultInfo:info]; + if (self.levleInfo.level == WishGiftLevel_Normal) { + [self handleGiftDatasource:self.levelOneGiftList giftId:info.giftId]; + } else if (self.levleInfo.level == WishGiftLevel_Middle) { + [self handleGiftDatasource:self.levelTwoGiftList giftId:info.giftId]; + } else { + [self handleGiftDatasource:self.levelThirdGiftList giftId:info.giftId]; + } + } +} + +#pragma mark - XPWishGiftProtocol +- (void)wishGiftConfigListSucces:(NSArray *)list level:(NSString *)level { + if (level.intValue == 1) { + self.levelOneGiftList = list; + if (list.count > 0 && !self.modifiGiftInfo) { + self.giftInfo = list.firstObject; + [self.giftView configDefaultInfo:self.giftInfo]; + [self handleGiftDatasource:self.levelOneGiftList giftId:self.giftInfo.giftId];; + } + if (self.modifiGiftInfo) { + [self handleGiftDatasource:self.levelThirdGiftList giftId:_modifiGiftInfo.giftId]; + } + } else if (level.intValue == 2) { + self.levelTwoGiftList = list; + if (self.modifiGiftInfo) { + [self handleGiftDatasource:self.levelTwoGiftList giftId:_modifiGiftInfo.giftId]; + } + } else { + self.levelThirdGiftList = list; + if (self.modifiGiftInfo) { + [self handleGiftDatasource:self.levelThirdGiftList giftId:_modifiGiftInfo.giftId]; + } + } +} + +- (void)createWishGiftItemSuccess { + [self disMissView]; + if(self.Dismiss) { + self.Dismiss(YES); + } +} + +#pragma mark - Event Response +- (void)subtractButtonAction:(UIButton *)sener { + if([self canSubtractMinCount:self.number]) { + self.number --; + } else { + self.number = [self subtractMinCount]; + } + self.textField.text = [NSString stringWithFormat:@"%d", self.number]; +} + +- (void)addButtonAction:(UIButton *)sener { + if([self canAddMaxCount:self.number]) { + self.number ++; + } else { + self.number = [self addMaxCount]; + } + self.textField.text = [NSString stringWithFormat:@"%d", self.number]; +} + +- (void)textFieldDidChanged:(UITextField *)textField { + self.number = textField.text.intValue; +} + +- (void)disMissView { + [self dismissViewControllerAnimated:YES completion:nil]; +} +#pragma mark - Event Response +- (void)sureButtonAction:(UIButton *)sender { + if (![self canSubtractMinCount:self.number]) { + NSString * toast = [NSString stringWithFormat:YMLocalizedString(@"XPWishGiftCreateItemViewController8"), [self subtractMinCount], [self addMaxCount]]; + [self showErrorToast:toast]; + self.textField.text = [NSString stringWithFormat:@"%d", [self subtractMinCount]]; + self.number = [self subtractMinCount]; + return; + } else if(![self canAddMaxCount:self.number]){ + NSString * toast = [NSString stringWithFormat:YMLocalizedString(@"XPWishGiftCreateItemViewController8"), [self subtractMinCount], [self addMaxCount]]; + [self showErrorToast:toast]; + self.textField.text = [NSString stringWithFormat:@"%d", [self addMaxCount]]; + self.number = [self addMaxCount]; + return; + } + NSString * itemId = self.modifiGiftInfo ? [NSString stringWithFormat:@"%ld", self.modifiGiftInfo.itemId] : @""; + [self.presenter createWishGiftItem:self.roomUid itemId:itemId giftId:[NSString stringWithFormat:@"%ld", self.giftInfo.giftId] seq:self.levleInfo.level targetNum:self.number]; +} + +#pragma mark - Getters And Setters +- (void)setModifiGiftInfo:(WishGiftInfoModel *)modifiGiftInfo { + _modifiGiftInfo = modifiGiftInfo; + if (_modifiGiftInfo) { + WishGiftInfoModel * levelInfo; + for (WishGiftInfoModel * info in self.levelLists) { + if (info.level == _modifiGiftInfo.level) { + levelInfo = info; + } + } + if (levelInfo) { + self.levleInfo = levelInfo; + self.giftInfo = _modifiGiftInfo; + [self.levelView configDefaultInfo:levelInfo]; + [self.giftView configDefaultInfo:_modifiGiftInfo]; + ///处理等级 + [self handleLevleDatasource:levelInfo.level]; + ///处理等级 + if (_modifiGiftInfo.level == WishGiftLevel_Normal) { + if (self.levelOneGiftList.count <=0) { + [self.presenter wishGiftConfigList:self.roomUid level:@"1"]; + } else { + [self handleGiftDatasource:self.levelOneGiftList giftId:_modifiGiftInfo.giftId]; + } + } else if (_modifiGiftInfo.level == WishGiftLevel_Middle) { + if (self.levelTwoGiftList.count <= 0) { + [self.presenter wishGiftConfigList:self.roomUid level:@"2"]; + } else { + [self handleGiftDatasource:self.levelTwoGiftList giftId:_modifiGiftInfo.giftId]; + } + } else { + if (self.levelThirdGiftList.count <= 0) { + [self.presenter wishGiftConfigList:self.roomUid level:@"3"]; + } else { + [self handleGiftDatasource:self.levelThirdGiftList giftId:_modifiGiftInfo.giftId]; + } + } + self.textField.text = [NSString stringWithFormat:@"%ld", _modifiGiftInfo.targetNum]; + self.number = (int)_modifiGiftInfo.targetNum; + + } else { + [self disMissView]; + } + } +} + +- (UIView *)topView { + if (!_topView) { + _topView = [[UIView alloc] init]; + _topView.backgroundColor = [UIColor clearColor]; + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMissView)]; + [_topView addGestureRecognizer:tap]; + } + return _topView; +} + + +- (UIView *)bottomView { + if (!_bottomView) { + _bottomView = [[UIView alloc] init]; + _bottomView.backgroundColor = [UIColor clearColor]; + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMissView)]; + [_bottomView addGestureRecognizer:tap]; + } + return _bottomView; +} + + +- (UIView *)backView { + if (!_backView) { + _backView = [[UIView alloc] init]; + _backView.layer.masksToBounds = YES; + _backView.layer.cornerRadius = 20; + _backView.backgroundColor = [UIColor whiteColor]; + } + return _backView; +} + +- (XPWishGiftListView *)levelView { + if(!_levelView) { + _levelView = [[XPWishGiftListView alloc] init]; + _levelView.delegate = self; + } + return _levelView; +} + +- (XPWishGiftListView *)giftView { + if(!_giftView) { + _giftView = [[XPWishGiftListView alloc] init]; + _giftView.delegate = self; + } + return _giftView; +} + +- (UIButton *)subtractButton { + if (!_subtractButton) { + _subtractButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_subtractButton setImage:[UIImage imageNamed:@"room_wish_gift_subtract"] forState:UIControlStateNormal]; + [_subtractButton setImage:[UIImage imageNamed:@"room_wish_gift_subtract"] forState:UIControlStateSelected]; + [_subtractButton addTarget:self action:@selector(subtractButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _subtractButton; +} + + +- (UIButton *)addButton { + if (!_addButton) { + _addButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_addButton setImage:[UIImage imageNamed:@"room_wish_gift_add"] forState:UIControlStateNormal]; + [_addButton setImage:[UIImage imageNamed:@"room_wish_gift_add"] forState:UIControlStateSelected]; + [_addButton addTarget:self action:@selector(addButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _addButton; +} + +- (UIStackView *)numberStackView { + if (!_numberStackView) { + _numberStackView = [[UIStackView alloc] init]; + _numberStackView.axis = UILayoutConstraintAxisHorizontal; + _numberStackView.distribution = UIStackViewDistributionFill; + _numberStackView.alignment = UIStackViewAlignmentFill; + _numberStackView.spacing = 10; + } + return _numberStackView; +} + +- (MSBaseTextField *)textField { + if (!_textField) { + _textField = [[MSBaseTextField alloc] init]; + _textField.layer.cornerRadius = 4; + _textField.layer.masksToBounds = YES; + _textField.tintColor = [DJDKMIMOMColor secondTextColor]; + _textField.textColor = [DJDKMIMOMColor mainTextColor]; + _textField.backgroundColor = [UIColor clearColor]; + _textField.font = [UIFont systemFontOfSize:10]; + _textField.clearButtonMode = UITextFieldViewModeWhileEditing; + _textField.returnKeyType = UIReturnKeySearch; + _textField.enablesReturnKeyAutomatically = YES; + _textField.text = @"10"; + _textField.textAlignment = NSTextAlignmentCenter; + _textField.keyboardType = UIKeyboardTypeNumberPad; + _textField.backgroundColor = [DJDKMIMOMColor colorWithHexString:@"#E4E4E4"]; + [_textField addTarget:self action:@selector(textFieldDidChanged:) forControlEvents:UIControlEventEditingChanged]; + } + return _textField; +} + +- (UIButton *)sureButton { + if (!_sureButton) { + _sureButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_sureButton setTitle:YMLocalizedString(@"TTAlertConfig0") forState:UIControlStateNormal]; + [_sureButton setTitleColor:[DJDKMIMOMColor confirmButtonTextColor] forState:UIControlStateNormal]; + _sureButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [_sureButton setBackgroundImage:[UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor], [DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)] forState:UIControlStateNormal]; + _sureButton.layer.masksToBounds = YES; + _sureButton.layer.cornerRadius = 10; + [_sureButton addTarget:self action:@selector(sureButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _sureButton; +} + +- (NSArray *)levelLists { + if (!_levelLists) { + WishGiftInfoModel * levelOne = [[WishGiftInfoModel alloc] init]; + levelOne.levelName = YMLocalizedString(@"XPWishGiftCreateItemViewController11"); + levelOne.level = WishGiftLevel_Normal; + + WishGiftInfoModel * levelTwo = [[WishGiftInfoModel alloc] init]; + levelTwo.levelName = YMLocalizedString(@"XPWishGiftCreateItemViewController12"); + levelTwo.level = WishGiftLevel_Middle; + + WishGiftInfoModel * levelThree = [[WishGiftInfoModel alloc] init]; + levelThree.levelName = YMLocalizedString(@"XPWishGiftCreateItemViewController13"); + levelThree.level = WishGiftLevel_High; + _levelLists = @[levelOne, levelTwo, levelThree]; + } + return _levelLists; +} + + + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h index 6f5e8b2..9172577 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h @@ -1,9 +1,7 @@ -// -// YMWishGiftCreateViewController.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "MvpViewController.h" #import "RoomHostDelegate.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h.backup new file mode 100644 index 0000000..6f5e8b2 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.h.backup @@ -0,0 +1,16 @@ +// +// YMWishGiftCreateViewController.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "MvpViewController.h" +#import "RoomHostDelegate.h" +NS_ASSUME_NONNULL_BEGIN + +@interface XPWishGiftCreateViewController : MvpViewController +- (instancetype)initWithDelegate:(id)delegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m index 2ca7035..a2619be 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m @@ -1,51 +1,49 @@ -// -// YMWishGiftCreateViewController.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftCreateViewController.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "UIImage+Utils.h" #import "TTPopup.h" #import "YUMIMacroUitls.h" #import "NSArray+Safe.h" -///Model + #import "WishGiftInfoModel.h" #import "RoomInfoModel.h" -///View + #import "XPWishGiftTableViewCell.h" #import "XPWishGiftHistoryViewController.h" #import "XPWishGiftCreateItemViewController.h" -///P + #import "XPWishGiftPresenter.h" #import "XPWishGiftProtocol.h" @interface XPWishGiftCreateViewController () -///设置心愿 + @property (nonatomic,strong) UILabel *configLabel; -///清除心愿 + @property (nonatomic,strong) UIButton *clearWishButton; -///添加心愿 + @property (nonatomic,strong) UIButton *addWishButton; -///列表 + @property (nonatomic,strong) UITableView *tableView; -///创建 + @property (nonatomic,strong) UIButton *createButton; -///数据源 + @property (nonatomic,strong) NSArray *datasource; -///房主的uid + @property (nonatomic,strong) NSString *roomUid; -///代理 + @property (nonatomic,weak) id delegate; -///初级礼物 + @property (nonatomic,strong) NSArray *levelOneGiftList; -///中级礼物 + @property (nonatomic,strong) NSArray *levelTwoGiftList; -///高级礼物 + @property (nonatomic,strong) NSArray *levelThirdGiftList; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m.backup new file mode 100644 index 0000000..2ca7035 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftCreateViewController.m.backup @@ -0,0 +1,333 @@ +// +// YMWishGiftCreateViewController.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftCreateViewController.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "UIImage+Utils.h" +#import "TTPopup.h" +#import "YUMIMacroUitls.h" +#import "NSArray+Safe.h" +///Model +#import "WishGiftInfoModel.h" +#import "RoomInfoModel.h" +///View +#import "XPWishGiftTableViewCell.h" +#import "XPWishGiftHistoryViewController.h" +#import "XPWishGiftCreateItemViewController.h" +///P +#import "XPWishGiftPresenter.h" +#import "XPWishGiftProtocol.h" +@interface XPWishGiftCreateViewController () +///设置心愿 +@property (nonatomic,strong) UILabel *configLabel; +///清除心愿 +@property (nonatomic,strong) UIButton *clearWishButton; +///添加心愿 +@property (nonatomic,strong) UIButton *addWishButton; +///列表 +@property (nonatomic,strong) UITableView *tableView; +///创建 +@property (nonatomic,strong) UIButton *createButton; +///数据源 +@property (nonatomic,strong) NSArray *datasource; +///房主的uid +@property (nonatomic,strong) NSString *roomUid; +///代理 +@property (nonatomic,weak) id delegate; +///初级礼物 +@property (nonatomic,strong) NSArray *levelOneGiftList; +///中级礼物 +@property (nonatomic,strong) NSArray *levelTwoGiftList; +///高级礼物 +@property (nonatomic,strong) NSArray *levelThirdGiftList; +@end + +@implementation XPWishGiftCreateViewController + +- (__kindof id)createPresenter { + return [[XPWishGiftPresenter alloc] init]; +} +- (instancetype)initWithDelegate:(id)delegate{ + if (self = [super init]) { + self.delegate = delegate; + self.roomUid = [NSString stringWithFormat:@"%ld", [self.delegate getRoomInfo].uid]; + [self initWishGiftList]; + [self initWishLevleGiftList]; + RoomInfoModel * roomInfo = [self.delegate getRoomInfo]; + if (roomInfo.hasOpenWishGift) { + self.addWishButton.hidden = YES; + self.clearWishButton.hidden = YES; + [self.createButton setTitle:YMLocalizedString(@"XPWishGiftCreateViewController0") forState:UIControlStateNormal]; + self.createButton.enabled = NO; + } + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self initSubViews]; + [self initSubViewConstraints]; +} + +#pragma mark - Private Method +- (void)initWishGiftList { + [self.presenter wishGiftList:self.roomUid]; +} + +- (void)initWishLevleGiftList { + [self.presenter wishGiftConfigList:self.roomUid level:@"1"]; + [self.presenter wishGiftConfigList:self.roomUid level:@"2"]; + [self.presenter wishGiftConfigList:self.roomUid level:@"3"]; +} + +- (void)initSubViews { + self.title = YMLocalizedString(@"XPWishGiftCreateViewController1"); + [self.view addSubview:self.configLabel]; + [self.view addSubview:self.clearWishButton]; + [self.view addSubview:self.addWishButton]; + [self.view addSubview:self.tableView]; + [self.view addSubview:self.createButton]; + [self addNavigationItemWithTitles:@[YMLocalizedString(@"XPWishGiftCreateViewController2")] titleColor:[DJDKMIMOMColor secondTextColor] isLeft:NO target:self action:@selector(rightButtonAction:) tags:nil]; +} + +- (void)initSubViewConstraints { + [self.configLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.view).offset(24); + make.top.mas_equalTo(self.view).offset(14); + }]; + + [self.clearWishButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(60, 20)); + make.centerY.mas_equalTo(self.configLabel); + make.trailing.mas_equalTo(self.addWishButton.mas_leading).offset(-10); + }]; + + [self.addWishButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.configLabel); + make.trailing.mas_equalTo(self.view).offset(-18); + make.size.mas_equalTo(CGSizeMake(60, 20)); + }]; + + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.view).inset(15); + make.height.mas_equalTo(135); + make.top.mas_equalTo(self.configLabel.mas_bottom).offset(13); + }]; + + [self.createButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.view).inset(80); + make.height.mas_equalTo(37); + make.top.mas_equalTo(self.tableView.mas_bottom).offset(48); + }]; +} +#pragma mark - UITableViewDelegate And UITableViewDataSource +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.datasource.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + XPWishGiftTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPWishGiftTableViewCell class])]; + if (cell == nil) { + cell = [[XPWishGiftTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([XPWishGiftTableViewCell class])]; + } + WishGiftInfoModel *giftInfo = [self.datasource xpSafeObjectAtIndex:indexPath.row]; + giftInfo.row = indexPath.row + 1; + cell.giftInfo = giftInfo; + cell.delegate = self; + RoomInfoModel * roomInfo = [self.delegate getRoomInfo]; + cell.isHiddenEdit = roomInfo.hasOpenWishGift; + return cell; +} + +#pragma mark - XPWishGiftTableViewCellDelegate +- (void)xPWishGiftTableViewCell:(XPWishGiftTableViewCell *)view didClearWishGift:(WishGiftInfoModel *)info { + if (info) { + TTAlertConfig * config = [[TTAlertConfig alloc] init]; + config.title = @""; + config.message = YMLocalizedString(@"XPWishGiftCreateViewController3"); + [TTPopup alertWithConfig:config confirmHandler:^{ + [self.presenter deleteWishGiftItem:self.roomUid itemId:[NSString stringWithFormat:@"%ld", info.itemId]]; + } cancelHandler:^{ + + }]; + } +} + +- (void)xPWishGiftTableViewCell:(XPWishGiftTableViewCell *)view didUpdateWishGift:(WishGiftInfoModel *)info { + XPWishGiftCreateItemViewController * createItemVC = [[XPWishGiftCreateItemViewController alloc] init]; + createItemVC.roomUid = self.roomUid; + createItemVC.levelOneGiftList = self.levelOneGiftList; + createItemVC.levelTwoGiftList = self.levelTwoGiftList; + createItemVC.levelThirdGiftList = self.levelThirdGiftList; + createItemVC.modifiGiftInfo = info; + @kWeakify(self); + createItemVC.Dismiss = ^(BOOL finish) { + @kStrongify(self); + [self initWishGiftList]; + }; + createItemVC.modalPresentationStyle = UIModalPresentationOverFullScreen; + [self.navigationController presentViewController:createItemVC animated:YES completion:nil]; +} + +#pragma mark - XPWishGiftProtocol +- (void)addWishGiftSuccess { + [self.navigationController popViewControllerAnimated:YES]; +} + +- (void)getWishGiftListSuccess:(NSArray *)list { + self.datasource = list; + [self.tableView reloadData]; +} + +- (void)deleteWishGiftItemSuccess { + [self initWishGiftList]; +} + +- (void)wishGiftConfigListSucces:(NSArray *)list level:(NSString *)level { + if (level.intValue == 1) { + self.levelOneGiftList = list; + } else if (level.intValue == 2) { + self.levelTwoGiftList = list; + } else { + self.levelThirdGiftList = list; + } +} + +#pragma mark - Event Response +- (void)rightButtonAction:(UIButton *)sender { + XPWishGiftHistoryViewController * historyVC = [[XPWishGiftHistoryViewController alloc] init]; + historyVC.roomUid = self.roomUid; + [self.navigationController pushViewController:historyVC animated:YES]; +} + +- (void)clearButtonAction:(UIButton *)sender { + if (self.datasource.count > 0) { + TTAlertConfig * config = [[TTAlertConfig alloc] init]; + config.title = @""; + config.message = YMLocalizedString(@"XPWishGiftCreateViewController4"); + [TTPopup alertWithConfig:config confirmHandler:^{ + [self.presenter deleteWishGiftItem:self.roomUid itemId:@"-1"]; + } cancelHandler:^{ + + }]; + } else { + [self showErrorToast:YMLocalizedString(@"XPWishGiftCreateViewController5")]; + } +} + +- (void)addWishButtonAction:(UIButton *)sender { + if (self.datasource.count == 3) { + [self showErrorToast:YMLocalizedString(@"XPWishGiftCreateViewController6")]; + return; + } + XPWishGiftCreateItemViewController * createItemVC = [[XPWishGiftCreateItemViewController alloc] init]; + createItemVC.levelOneGiftList = self.levelOneGiftList; + createItemVC.levelTwoGiftList = self.levelTwoGiftList; + createItemVC.levelThirdGiftList = self.levelThirdGiftList; + createItemVC.roomUid = self.roomUid; + @kWeakify(self); + createItemVC.Dismiss = ^(BOOL finish) { + @kStrongify(self); + [self initWishGiftList]; + }; + createItemVC.modalPresentationStyle = UIModalPresentationOverFullScreen; + [self.navigationController presentViewController:createItemVC animated:YES completion:nil]; +} + +- (void)createButtonAction:(UIButton *)sender { + if (self.datasource.count > 0) { + TTAlertConfig * config = [[TTAlertConfig alloc] init]; + config.title = @""; + config.message = YMLocalizedString(@"XPWishGiftCreateViewController7"); + [TTPopup alertWithConfig:config confirmHandler:^{ + [self.presenter addWishGift:self.roomUid]; + } cancelHandler:^{ + + }]; + } else { + [self showErrorToast:YMLocalizedString(@"XPWishGiftCreateViewController8")]; + } +} + +#pragma mark - Getters And Setters +- (UILabel *)configLabel { + if (!_configLabel) { + _configLabel = [[UILabel alloc] init]; + _configLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _configLabel.textColor = [DJDKMIMOMColor mainTextColor]; + _configLabel.text = YMLocalizedString(@"XPWishGiftCreateViewController9"); + } + return _configLabel; +} + +- (UIButton *)clearWishButton { + if (!_clearWishButton) { + _clearWishButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_clearWishButton setTitle:YMLocalizedString(@"XPWishGiftCreateViewController10") forState:UIControlStateNormal]; + [_clearWishButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _clearWishButton.titleLabel.font = [UIFont systemFontOfSize:10]; + _clearWishButton.backgroundColor = [DJDKMIMOMColor colorWithHexString:@"#C7DAEA"]; + _clearWishButton.layer.masksToBounds = YES; + _clearWishButton.layer.cornerRadius = 10; + [_clearWishButton addTarget:self action:@selector(clearButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _clearWishButton; +} + +- (UIButton *)addWishButton { + if (!_addWishButton) { + _addWishButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_addWishButton setTitle:YMLocalizedString(@"XPWishGiftCreateViewController11") forState:UIControlStateNormal]; + [_addWishButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _addWishButton.titleLabel.font = [UIFont systemFontOfSize:10]; + [_addWishButton setBackgroundImage:[UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor], [DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)] forState:UIControlStateNormal]; + _addWishButton.layer.masksToBounds = YES; + _addWishButton.layer.cornerRadius = 10; + [_addWishButton addTarget:self action:@selector(addWishButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _addWishButton; +} + + +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.tableFooterView = [UIView new]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _tableView.backgroundColor = [UIColor whiteColor]; + _tableView.layer.masksToBounds = YES; + _tableView.layer.cornerRadius = 8; + if (@available(iOS 11.0, *)) { + _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [_tableView registerClass:[XPWishGiftTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPWishGiftTableViewCell class])]; + } + return _tableView; +} + +- (UIButton *)createButton { + if (!_createButton) { + _createButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_createButton setTitle:YMLocalizedString(@"XPWishGiftCreateViewController12") forState:UIControlStateNormal]; + [_createButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _createButton.titleLabel.font = [UIFont systemFontOfSize:12]; + [_createButton setBackgroundImage:[UIImage gradientColorImageFromColors:@[[DJDKMIMOMColor confirmButtonGradientStartColor], [DJDKMIMOMColor confirmButtonGradientEndColor]] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(10, 10)] forState:UIControlStateNormal]; + _createButton.layer.masksToBounds = YES; + _createButton.layer.cornerRadius = 37 / 2; + [_createButton addTarget:self action:@selector(createButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _createButton; +} + + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h index 7a2025e..cbbbca8 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h @@ -1,9 +1,7 @@ -// -// YMWishGiftHistoryViewController.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "MvpViewController.h" diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h.backup new file mode 100644 index 0000000..7a2025e --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.h.backup @@ -0,0 +1,16 @@ +// +// YMWishGiftHistoryViewController.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "MvpViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPWishGiftHistoryViewController : MvpViewController +@property (nonatomic,strong) NSString *roomUid; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m index 895b7b0..c6aa943 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m @@ -1,32 +1,30 @@ -// -// YMWishGiftHistoryViewController.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftHistoryViewController.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "YUMIMacroUitls.h" #import "PLTimeUtil.h" #import "NSArray+Safe.h" -///Model + #import "WishGiftHistoryModel.h" -///View + #import "XPWishGiftHistoryTableViewCell.h" #import "XPWishGiftEmptyTableViewCell.h" #import "XPWishGiftSectionView.h" -///P + #import "XPWishGiftPresenter.h" #import "XPWishGiftProtocol.h" @interface XPWishGiftHistoryViewController () -///列表 + @property (nonatomic,strong) UITableView *tableView; -///数据源 + @property (nonatomic,strong) NSArray *datasource; @end @@ -134,7 +132,7 @@ } #pragma mark - XPWishGiftProtocol -///历史心愿成功 + - (void)wishGiftHistroyListSuccess:(NSArray *)list { self.datasource = list; [self.tableView reloadData]; diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m.backup new file mode 100644 index 0000000..895b7b0 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftHistoryViewController.m.backup @@ -0,0 +1,162 @@ +// +// YMWishGiftHistoryViewController.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftHistoryViewController.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "YUMIMacroUitls.h" +#import "PLTimeUtil.h" +#import "NSArray+Safe.h" +///Model +#import "WishGiftHistoryModel.h" +///View +#import "XPWishGiftHistoryTableViewCell.h" +#import "XPWishGiftEmptyTableViewCell.h" +#import "XPWishGiftSectionView.h" +///P +#import "XPWishGiftPresenter.h" +#import "XPWishGiftProtocol.h" + +@interface XPWishGiftHistoryViewController () +///列表 +@property (nonatomic,strong) UITableView *tableView; +///数据源 +@property (nonatomic,strong) NSArray *datasource; +@end + +@implementation XPWishGiftHistoryViewController + +- (__kindof id)createPresenter { + return [[XPWishGiftPresenter alloc] init]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self initWishGiftHistoryList]; + [self initSubViews]; + [self initSubViewConstraints]; +} + + +- (void)initSubViews { + self.title = YMLocalizedString(@"XPWishGiftHistoryViewController0"); + [self.view addSubview:self.tableView]; +} + +- (void)initSubViewConstraints { + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; +} + +- (void)initWishGiftHistoryList { + [self.presenter wishGiftHistroyList:self.roomUid]; +} + +#pragma mark - UITableViewDelegate And UITableViewDataSource +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.datasource.count > 0 ? self.datasource.count : 1; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (self.datasource.count > 0) { + return 44; + } + return (KScreenHeight - kNavigationHeight); +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (self.datasource.count > 0) { + WishGiftHistoryModel *info = [self.datasource xpSafeObjectAtIndex:section]; + return info.gifts.count; + } + return 0; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + if (self.datasource.count > 0) { + XPWishGiftHistoryTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPWishGiftHistoryTableViewCell class])]; + if (cell == nil) { + cell = [[XPWishGiftHistoryTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([XPWishGiftHistoryTableViewCell class])]; + } + WishGiftHistoryModel *historyInfo = [self.datasource xpSafeObjectAtIndex:indexPath.section]; + WishGiftInfoModel * info= [historyInfo.gifts xpSafeObjectAtIndex:indexPath.row]; + info.row = (indexPath.row + 1); + cell.giftInfo = info; + if (indexPath.row == 0) { + cell.isTop = YES; + } else { + cell.isTop = NO; + } + + if (indexPath.row == historyInfo.gifts.count -1) { + cell.isBottom = YES; + } else { + cell.isBottom = false; + } + return cell; + } + + XPWishGiftEmptyTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPWishGiftEmptyTableViewCell class])]; + if (cell == nil) { + cell = [[XPWishGiftEmptyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([XPWishGiftEmptyTableViewCell class])]; + } + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 0.01; +} + +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + return [[UIView alloc] init];; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return self.datasource.count > 0 ? 45 : 0.01; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + if (self.datasource.count > 0) { + XPWishGiftSectionView * view = [[XPWishGiftSectionView alloc] init]; + view.frame = CGRectMake(0, 0, KScreenWidth, 45); + WishGiftHistoryModel *historyInfo = [self.datasource xpSafeObjectAtIndex:section]; + view.title = historyInfo.createDate; + return view; + } + return [UIView new]; +} + +#pragma mark - XPWishGiftProtocol +///历史心愿成功 +- (void)wishGiftHistroyListSuccess:(NSArray *)list { + self.datasource = list; + [self.tableView reloadData]; +} + +#pragma mark - Getters And Setters +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.tableFooterView = [UIView new]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _tableView.backgroundColor = [UIColor clearColor]; + if (@available(iOS 11.0, *)) { + _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [_tableView registerClass:[XPWishGiftHistoryTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPWishGiftHistoryTableViewCell class])]; + [self.tableView registerClass:[XPWishGiftEmptyTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPWishGiftEmptyTableViewCell class])]; + } + return _tableView; +} + + +@end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h index ae39d4d..11f096f 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h @@ -1,9 +1,7 @@ -// -// YMWishGIftViewController.h -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "MvpViewController.h" @@ -19,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRoomUid:(NSString *)roomUid; -///代理 + @property (nonatomic,weak) id delegate; - (void)getWishGiftListSuccess:(NSArray *)list; diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h.backup new file mode 100644 index 0000000..ae39d4d --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.h.backup @@ -0,0 +1,29 @@ +// +// YMWishGIftViewController.h +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "MvpViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol XPWishGiftViewControllerDelegate + +- (void)xPWishGiftViewControllerSendClick:(NSString *)giftId; + +@end + +@interface XPWishGiftViewController : MvpViewController + +- (instancetype)initWithRoomUid:(NSString *)roomUid; + +///代理 +@property (nonatomic,weak) id delegate; + +- (void)getWishGiftListSuccess:(NSArray *)list; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m index c72522f..74e2f87 100644 --- a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m @@ -1,59 +1,57 @@ -// -// YMWishGIftViewController.m -// YUMI -// + + // Created by YUMI on 2022/10/18. -// + #import "XPWishGiftViewController.h" -///Third + #import -///Tool + #import "DJDKMIMOMColor.h" #import "NetImageView.h" #import "YUMIMacroUitls.h" #import "NSArray+Safe.h" -///View + #import "XPWishGiftInfoView.h" -///Model + #import "WishGiftInfoModel.h" #import "WishGiftUserModel.h" -///P + #import "XPWishGiftPresenter.h" #import "XPWishGiftProtocol.h" @interface XPWishGiftViewController () -///顶部的view + @property (nonatomic,strong) UIView *topView; -///背景 + @property (nonatomic,strong) UIImageView *backImageView; -///显示标题 + @property (nonatomic,strong) UILabel *titleLabel; -///提示 + @property (nonatomic,strong) UILabel *tipsLbel; -///分割线 + @property (nonatomic,strong) UIView *lineView; -///头像的容器 + @property (nonatomic,strong) UIStackView *userStackView; -///第一个头像 + @property (nonatomic,strong) NetImageView *firstAvatarImageView; -///第二个头像 + @property (nonatomic,strong) NetImageView *secondAvatarImageView; -///第三个头像 + @property (nonatomic,strong) NetImageView *thirdAvatarImageView; @property (nonatomic,strong) NSArray * avatarViews; -///贡献的人数 + @property (nonatomic,strong) UILabel *assistNumLabel; -///礼物 + @property (nonatomic,strong) UIStackView *giftStackView; -///第一个 + @property (nonatomic,strong) XPWishGiftInfoView *firstView; -///第二个 + @property (nonatomic,strong) XPWishGiftInfoView *secondView; -///第三个 + @property (nonatomic,strong) XPWishGiftInfoView *thirdView; -///礼物数组 + @property (nonatomic,strong) NSArray *giftViews; -///房主的uid + @property (nonatomic,strong) NSString *roomUid; @end diff --git a/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m.backup b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m.backup new file mode 100644 index 0000000..c72522f --- /dev/null +++ b/YuMi/Modules/YMRoom/View/WishGift/View/XPWishGiftViewController.m.backup @@ -0,0 +1,375 @@ +// +// YMWishGIftViewController.m +// YUMI +// +// Created by YUMI on 2022/10/18. +// + +#import "XPWishGiftViewController.h" +///Third +#import +///Tool +#import "DJDKMIMOMColor.h" +#import "NetImageView.h" +#import "YUMIMacroUitls.h" +#import "NSArray+Safe.h" +///View +#import "XPWishGiftInfoView.h" +///Model +#import "WishGiftInfoModel.h" +#import "WishGiftUserModel.h" +///P +#import "XPWishGiftPresenter.h" +#import "XPWishGiftProtocol.h" +@interface XPWishGiftViewController () +///顶部的view +@property (nonatomic,strong) UIView *topView; +///背景 +@property (nonatomic,strong) UIImageView *backImageView; +///显示标题 +@property (nonatomic,strong) UILabel *titleLabel; +///提示 +@property (nonatomic,strong) UILabel *tipsLbel; +///分割线 +@property (nonatomic,strong) UIView *lineView; +///头像的容器 +@property (nonatomic,strong) UIStackView *userStackView; +///第一个头像 +@property (nonatomic,strong) NetImageView *firstAvatarImageView; +///第二个头像 +@property (nonatomic,strong) NetImageView *secondAvatarImageView; +///第三个头像 +@property (nonatomic,strong) NetImageView *thirdAvatarImageView; +@property (nonatomic,strong) NSArray * avatarViews; +///贡献的人数 +@property (nonatomic,strong) UILabel *assistNumLabel; +///礼物 +@property (nonatomic,strong) UIStackView *giftStackView; +///第一个 +@property (nonatomic,strong) XPWishGiftInfoView *firstView; +///第二个 +@property (nonatomic,strong) XPWishGiftInfoView *secondView; +///第三个 +@property (nonatomic,strong) XPWishGiftInfoView *thirdView; +///礼物数组 +@property (nonatomic,strong) NSArray *giftViews; +///房主的uid +@property (nonatomic,strong) NSString *roomUid; +@end + +@implementation XPWishGiftViewController + +- (instancetype)initWithRoomUid:(NSString *)roomUid { + if (self = [super init]) { + self.roomUid = roomUid; + [self initDefaultData]; + } + return self; +} + +- (__kindof id)createPresenter { + return [[XPWishGiftPresenter alloc] init]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self initSubViews]; + [self initSubViewConstraints]; +} + +- (void)initDefaultData { + [self.presenter wishGiftAssistUserList:self.roomUid]; + [self.presenter wishGiftList:self.roomUid]; +} + +- (void)initSubViews { + self.view.backgroundColor = [UIColor clearColor]; + [self.view addSubview:self.topView]; + [self.view addSubview:self.backImageView]; + [self.backImageView addSubview:self.titleLabel]; + [self.backImageView addSubview:self.tipsLbel]; + [self.backImageView addSubview:self.lineView]; + [self.backImageView addSubview:self.userStackView]; + [self.backImageView addSubview:self.assistNumLabel]; + [self.backImageView addSubview:self.giftStackView]; + + [self.userStackView addArrangedSubview:self.firstAvatarImageView]; + [self.userStackView addArrangedSubview:self.secondAvatarImageView]; + [self.userStackView addArrangedSubview:self.thirdAvatarImageView]; + + [self.giftStackView addArrangedSubview:self.firstView]; + [self.giftStackView addArrangedSubview:self.secondView]; + [self.giftStackView addArrangedSubview:self.thirdView]; + self.giftViews = @[self.firstView, self.secondView, self.thirdView]; +} + +- (void)initSubViewConstraints { + [self.topView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.top.trailing.equalTo(self.view); + make.bottom.mas_equalTo(self.backImageView.mas_top); + }]; + + [self.backImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.mas_equalTo(self.view); + make.height.mas_equalTo(283 + kSafeAreaBottomHeight); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.backImageView); + make.top.mas_equalTo(self.backImageView).offset(16); + }]; + + [self.tipsLbel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.backImageView); + make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(8); + }]; + + [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.backImageView); + make.top.mas_equalTo(self.tipsLbel.mas_bottom).offset(12); + make.height.mas_equalTo(0.5); + }]; + + [self.userStackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(28); + make.leading.mas_equalTo(self.backImageView).offset(16); + make.top.mas_equalTo(self.lineView.mas_bottom).offset(10); + }]; + + [self.firstAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(28); + }]; + + [self.secondAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(28); + }]; + + [self.thirdAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(28); + }]; + + [self.assistNumLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.backImageView).inset(15); + make.centerY.mas_equalTo(self.userStackView); + }]; + + [self.giftStackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.backImageView); + make.height.mas_equalTo(165); + make.bottom.mas_equalTo(self.backImageView).offset(-9 -kSafeAreaBottomHeight); + }]; + + [self.firstView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(106); + }]; + + [self.secondView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(106); + }]; + + [self.thirdView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(106); + }]; +} + +#pragma mark - XPWishGiftInfoViewDelegate +- (void)xPWishGiftInfoView:(XPWishGiftInfoView *)view didClickSender:(WishGiftInfoModel *)info { + [self disMissView]; + if (info.giftId > 0 && self.delegate && [self.delegate respondsToSelector:@selector(xPWishGiftViewControllerSendClick:)]) { + NSString * giftId = [NSString stringWithFormat:@"%ld", info.giftId]; + [self.delegate xPWishGiftViewControllerSendClick:giftId]; + } +} + +#pragma mark - XPWishGiftProtocol +- (void)getWishGiftAssistUserListSuccess:(NSArray *)list { + for (int i = 0; i < self.userStackView.arrangedSubviews.count; i++) { + NetImageView * imageView = [self.userStackView.subviews xpSafeObjectAtIndex:i]; + if (i < list.count) { + WishGiftUserModel * userInfo = [list xpSafeObjectAtIndex:i]; + imageView.hidden = NO; + imageView.imageUrl = userInfo.avatar; + }else { + imageView.hidden = YES; + } + } + + NSString * number = [NSString stringWithFormat:@"%ld", list.count]; + if (list.count <= 0) { + NSString * title = YMLocalizedString(@"XPWishGiftViewController0"); + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] initWithString:title attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12], NSForegroundColorAttributeName:[DJDKMIMOMColor textThirdColor]}]; + self.assistNumLabel.attributedText = attribute; + self.assistNumLabel.textAlignment = NSTextAlignmentCenter; + } else { + NSString * title = [NSString stringWithFormat:@"%@%@", number, YMLocalizedString(@"XPWishGiftViewController1")]; + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] initWithString:title attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12], NSForegroundColorAttributeName:[DJDKMIMOMColor textThirdColor]}]; + [attribute addAttribute:NSForegroundColorAttributeName value:[DJDKMIMOMColor colorWithHexString:@"#FFC300"] range:[title rangeOfString:number]]; + self.assistNumLabel.attributedText = attribute; + self.assistNumLabel.textAlignment = NSTextAlignmentRight; + } +} + +- (void)getWishGiftListSuccess:(NSArray *)list { + int finishNumber = 0; + for (WishGiftInfoModel * info in list) { + if (info.actualNum >= info.targetNum) { + finishNumber ++; + } + } + + for (int i = 0; i < self.giftViews.count; i++) { + XPWishGiftInfoView * view = [self.giftViews xpSafeObjectAtIndex:i]; + if(i < list.count) { + WishGiftInfoModel * info = [list xpSafeObjectAtIndex:i]; + view.giftInfo = info; + view.hidden = NO; + } else { + view.hidden = YES; + } + } + self.titleLabel.text = [NSString stringWithFormat:YMLocalizedString(@"XPWishGiftViewController2"),finishNumber,list.count]; +} + +#pragma mark - Event Response +- (void)disMissView { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - Getters And Setters +- (UIView *)topView { + if (!_topView) { + _topView = [[UIView alloc] init]; + _topView.backgroundColor = [UIColor clearColor]; + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMissView)]; + [_topView addGestureRecognizer:tap]; + } + return _topView; +} + +- (UIImageView *)backImageView { + if (!_backImageView) { + _backImageView = [[UIImageView alloc] init]; + _backImageView.userInteractionEnabled = YES; + _backImageView.image = [UIImage imageNamed:@"room_wish_gift_panel_bg"]; + } + return _backImageView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + _titleLabel.textColor = [UIColor whiteColor]; + } + return _titleLabel; +} + +- (UILabel *)tipsLbel { + if (!_tipsLbel) { + _tipsLbel = [[UILabel alloc] init]; + _tipsLbel.font = [UIFont systemFontOfSize:10]; + _tipsLbel.text = YMLocalizedString(@"XPWishGiftViewController3"); + _tipsLbel.textColor = [DJDKMIMOMColor textThirdColor]; + } + return _tipsLbel; +} + +- (UIView *)lineView { + if (!_lineView) { + _lineView = [[UIView alloc] init]; + _lineView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.1]; + } + return _lineView; +} + +- (UIStackView *)userStackView { + if (!_userStackView) { + _userStackView = [[UIStackView alloc] init]; + _userStackView.axis = UILayoutConstraintAxisHorizontal; + _userStackView.distribution = UIStackViewDistributionFill; + _userStackView.alignment = UIStackViewAlignmentCenter; + _userStackView.spacing = 4; + } + return _userStackView; +} + +- (NetImageView *)firstAvatarImageView { + if (!_firstAvatarImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _firstAvatarImageView = [[NetImageView alloc] initWithConfig:config]; + _firstAvatarImageView.layer.masksToBounds = YES; + _firstAvatarImageView.layer.cornerRadius = 28/2; + } + return _firstAvatarImageView; +} + +- (NetImageView *)secondAvatarImageView { + if (!_secondAvatarImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _secondAvatarImageView = [[NetImageView alloc] initWithConfig:config]; + _secondAvatarImageView.layer.masksToBounds = YES; + _secondAvatarImageView.layer.cornerRadius = 28/2; + } + return _secondAvatarImageView; +} + +- (NetImageView *)thirdAvatarImageView { + if (!_thirdAvatarImageView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _thirdAvatarImageView = [[NetImageView alloc] initWithConfig:config]; + _thirdAvatarImageView.layer.masksToBounds = YES; + _thirdAvatarImageView.layer.cornerRadius = 28/2; + } + return _thirdAvatarImageView; +} + +- (UILabel *)assistNumLabel { + if (!_assistNumLabel) { + _assistNumLabel = [[UILabel alloc] init]; + } + return _assistNumLabel; +} + +- (UIStackView *)giftStackView { + if (!_giftStackView) { + _giftStackView = [[UIStackView alloc] init]; + _giftStackView.axis = UILayoutConstraintAxisHorizontal; + _giftStackView.distribution = UIStackViewDistributionFill; + _giftStackView.alignment = UIStackViewAlignmentFill; + _giftStackView.spacing = 12; + } + return _giftStackView; +} + +- (XPWishGiftInfoView *)firstView { + if(!_firstView) { + _firstView = [[XPWishGiftInfoView alloc] init]; + _firstView.delegate = self; + } + return _firstView; +} + +- (XPWishGiftInfoView *)secondView { + if(!_secondView) { + _secondView = [[XPWishGiftInfoView alloc] init]; + _secondView.delegate = self; + } + return _secondView; +} + +- (XPWishGiftInfoView *)thirdView { + if(!_thirdView) { + _thirdView = [[XPWishGiftInfoView alloc] init]; + _thirdView.delegate = self; + } + return _thirdView; +} + + +@end diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.h b/YuMi/Modules/YMTabbar/Api/Api+Main.h index 3857d7e..db0a5fd 100644 --- a/YuMi/Modules/YMTabbar/Api/Api+Main.h +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.h @@ -1,9 +1,7 @@ -// -// Api+Main.h -// YUMI -// + + // Created by zu on 2021/9/8. -// + #import "Api.h" @@ -14,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN + (void)requestTicket:(HttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType; + (void)clientInitConfig:(HttpRequestHelperCompletion)complection; -// + + (void)clientConfig:(HttpRequestHelperCompletion)completion; @end diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.h.backup b/YuMi/Modules/YMTabbar/Api/Api+Main.h.backup new file mode 100644 index 0000000..3857d7e --- /dev/null +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.h.backup @@ -0,0 +1,21 @@ +// +// Api+Main.h +// YUMI +// +// Created by zu on 2021/9/8. +// + +#import "Api.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface Api (Main) + ++ (void)requestTicket:(HttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType; + ++ (void)clientInitConfig:(HttpRequestHelperCompletion)complection; +// ++ (void)clientConfig:(HttpRequestHelperCompletion)completion; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.m b/YuMi/Modules/YMTabbar/Api/Api+Main.m index ba60b01..e10e81b 100644 --- a/YuMi/Modules/YMTabbar/Api/Api+Main.m +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.m @@ -1,9 +1,7 @@ -// -// Api+Main.m -// YUMI -// + + // Created by zu on 2021/9/8. -// + #import "Api+Main.h" #import "YYUtility.h" @@ -13,14 +11,13 @@ @implementation Api (Main) + (void)requestTicket:(HttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType { - NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdGlja2V0"];///oauth/ticket + NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdGlja2V0"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, accessToken, issueType, nil]; } -/// 初始化配置 -/// @param complection 完成 + + (void)clientInitConfig:(HttpRequestHelperCompletion)complection { - NSString * fang = [NSString stringFromBase64String:@"Y2xpZW50L2luaXQ="];///client/init + NSString * fang = [NSString stringFromBase64String:@"Y2xpZW50L2luaXQ="]; [HttpRequestHelper request:fang method:HttpRequestHelperMethodGET params:@{} completion:complection]; } diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.m.backup b/YuMi/Modules/YMTabbar/Api/Api+Main.m.backup new file mode 100644 index 0000000..ba60b01 --- /dev/null +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.m.backup @@ -0,0 +1,32 @@ +// +// Api+Main.m +// YUMI +// +// Created by zu on 2021/9/8. +// + +#import "Api+Main.h" +#import "YYUtility.h" +#import "NSString+Utils.h" +#import "NSMutableDictionary+Saft.h" +#import +@implementation Api (Main) + ++ (void)requestTicket:(HttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType { + NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdGlja2V0"];///oauth/ticket + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, accessToken, issueType, nil]; +} + +/// 初始化配置 +/// @param complection 完成 ++ (void)clientInitConfig:(HttpRequestHelperCompletion)complection { + NSString * fang = [NSString stringFromBase64String:@"Y2xpZW50L2luaXQ="];///client/init + [HttpRequestHelper request:fang method:HttpRequestHelperMethodGET params:@{} completion:complection]; +} + ++ (void)clientConfig:(HttpRequestHelperCompletion)completion { + [HttpRequestHelper request:@"client/config" method:HttpRequestHelperMethodGET params:@{@"NeedChangeTimeOut":@(10)} completion:completion]; +} + + +@end diff --git a/YuMi/Modules/YMWeb/MSRoomGameWebVC.h b/YuMi/Modules/YMWeb/MSRoomGameWebVC.h index 91562eb..7d2f75d 100644 --- a/YuMi/Modules/YMWeb/MSRoomGameWebVC.h +++ b/YuMi/Modules/YMWeb/MSRoomGameWebVC.h @@ -1,9 +1,7 @@ -// -// MSRoomGameWebVC.h -// YuMi -// + + // Created by duoban on 2024/4/28. -// + #import "BaseViewController.h" #import diff --git a/YuMi/Modules/YMWeb/MSRoomGameWebVC.h.backup b/YuMi/Modules/YMWeb/MSRoomGameWebVC.h.backup new file mode 100644 index 0000000..91562eb --- /dev/null +++ b/YuMi/Modules/YMWeb/MSRoomGameWebVC.h.backup @@ -0,0 +1,18 @@ +// +// MSRoomGameWebVC.h +// YuMi +// +// Created by duoban on 2024/4/28. +// + +#import "BaseViewController.h" +#import +#import "RoomHostDelegate.h" +#import "ActivityInfoModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface MSRoomGameWebVC : BaseViewController +- (instancetype)initWithDelegate:(id)delegate gameModel:(ActivityInfoModel *)gameModel; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m index 3c26a88..1695b86 100644 --- a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m +++ b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m @@ -1,9 +1,7 @@ -// -// MSRoomGameWebVC.m -// YuMi -// + + // Created by duoban on 2024/4/28. -// + #import "MSRoomGameWebVC.h" #import "LittleGameInfoModel.h" @@ -12,7 +10,7 @@ @interface MSWeakWebViewScriptMessageDelegate : NSObject -//WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法 + @property (nonatomic, weak) id scriptDelegate; - (instancetype)initWithDelegate:(id)scriptDelegate; @@ -28,8 +26,7 @@ return self; } -//遵循WKScriptMessageHandler协议,必须实现如下方法,然后把方法向外传递 -//通过接收JS传出消息的name进行捕捉的回调方法 + - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) { @@ -41,9 +38,9 @@ typedef NS_ENUM(NSInteger, MSGameType) { - MSGameTypeBaiShun, // 百顺游戏 - MSGameTypeJoyPlay, // JoyPlay游戏 - MSGameTypeCC // CC游戏 + MSGameTypeBaiShun, + MSGameTypeJoyPlay, + MSGameTypeCC }; NSString * const kMSGetConfig = @"getConfig"; @@ -56,7 +53,6 @@ NSString * const kJPClickRecharge = @"clickRecharge"; NSString * const kJPClose = @"newTppClose"; - @interface MSRoomGameWebVC () @property (strong, nonatomic) WKWebView *webView; @property (strong, nonatomic) UIProgressView *progressView; @@ -129,7 +125,7 @@ NSString * const kJPClose = @"newTppClose"; [self installUI]; [self setupBackButton]; #if DEBUG -// [self setupLoadingTimer]; + #endif [self setupNotifications]; [self showLoading]; @@ -205,11 +201,11 @@ NSString * const kJPClose = @"newTppClose"; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGameRecharge]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGameLoaded]; - /// LEADERCC + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:@"closeGame"]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:@"pay"]; - /// JOYPLAY + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJPClose]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate @@ -222,7 +218,7 @@ NSString * const kJPClose = @"newTppClose"; config.allowsInlineMediaPlayback = YES; config.mediaTypesRequiringUserActionForPlayback = NO; [config setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"]; - //⾳视频的播放不需要⽤⼾⼿势触发, 即为⾃动播放 + config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; config.preferences = [[WKPreferences alloc]init]; WKPreferences *preferences = [WKPreferences new]; @@ -251,9 +247,9 @@ NSString * const kJPClose = @"newTppClose"; [self.webView setBackgroundColor:[UIColor clearColor]]; [self.webView setUIDelegate:self]; self.webView.navigationDelegate = self; - //设置⽹⻚透明 + [self.webView setOpaque:NO]; - //设置⽹⻚全屏 + if (@available(iOS 11.0, *)) { self.webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } @@ -357,12 +353,12 @@ NSString * const kJPClose = @"newTppClose"; self.backBtn.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight*0.3); } - // 注入错误处理脚本 + NSString *errorHandler = @"window.onerror = function(msg, url, line, col, error) { window.webkit.messageHandlers.error.postMessage({message: msg, url: url, line: line, col: col}); return false; }"; [webView evaluateJavaScript:errorHandler completionHandler:nil]; #if DEBUG - NSString *fileName = @"vconsole.min.js"; // 你要查找的文件名 + NSString *fileName = @"vconsole.min.js"; NSString *directory = [[NSBundle mainBundle] resourcePath]; NSFileManager *fileManager = [NSFileManager defaultManager]; @@ -381,7 +377,7 @@ NSString * const kJPClose = @"newTppClose"; encoding:NSUTF8StringEncoding error:nil]; [self.webView evaluateJavaScript:vConsoleScript completionHandler:nil]; - // 初始化 vConsole + NSString *initVConsoleScript = @"var vConsole = new VConsole();"; [self.webView evaluateJavaScript:initVConsoleScript completionHandler:nil]; } @@ -418,7 +414,7 @@ NSString * const kJPClose = @"newTppClose"; } } -// 调⽤JS + - (void)callJs:(NSString*)method withJavaScriptValue:(nullable id)arguments { @kWeakify(self); @@ -463,11 +459,11 @@ NSString * const kJPClose = @"newTppClose"; } return dic; } -// 绑定协议⽅法 + - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { - /// BaiShun + switch (self.gameType) { case MSGameTypeBaiShun: { NSDictionary *dicBody = [self dictionaryWithJsonString:message.body]; @@ -498,7 +494,7 @@ NSString * const kJPClose = @"newTppClose"; break; } case MSGameTypeCC: { - /// LeaderCC + NSString* method = [NSString stringWithFormat:@"%@:", message.name]; SEL selector = NSSelectorFromString(method); if([self respondsToSelector:selector]){ @@ -512,14 +508,14 @@ NSString * const kJPClose = @"newTppClose"; } #pragma mark - LeaderCC Delegate -// 关闭游戏 + - (void)closeGame:(NSDictionary*)args { [self backBtnAction]; } -// 显示充值界面 + - (void)pay:(NSDictionary*)args { - //拉起充值商城 + TTAlertConfig *config = [[TTAlertConfig alloc]init]; config.title = YMLocalizedString(@"UserDetail_CP_Toast_0"); config.message = YMLocalizedString(@"XPNobleCenterViewController3"); @@ -537,7 +533,7 @@ NSString * const kJPClose = @"newTppClose"; } - (void)updateCoin { - // 平时游戏币更新不需要调用该方法,以防止影响游戏开奖动画。 + [self.webView evaluateJavaScript:@"updateCoin()" completionHandler:^(id _Nullable result, NSError * _Nullable error) { if (error) { NSLog(@"Error calling JS function: %@", error.localizedDescription); @@ -548,7 +544,7 @@ NSString * const kJPClose = @"newTppClose"; } #pragma mark - BaiShun Delegate -// 获取信息配置 + - (void) getConfig:(NSDictionary*)args { NSLog(@"BSGAME %s","游戏调⽤getConfig"); @@ -563,7 +559,7 @@ NSString * const kJPClose = @"newTppClose"; NSString *gameMode = gameModel.gameMode ?: @""; NSDictionary *gameConfig = gameModel.gameConfig ?: @{}; int gsp = gameModel.gsp; - // 数据只是参考值,需要根据⾃⼰APP进⾏赋值 + NSObject* configData = @{ @"appChannel":appChannel, @"appId":@(appId), @@ -581,25 +577,25 @@ NSString * const kJPClose = @"newTppClose"; NSString *language = [NSBundle getLanguageText]; if ([language hasPrefix:@"zh"]) { if ([language rangeOfString:@"Hans"].location != NSNotFound) { - language = @"0"; // 简体中文 + language = @"0"; } else { - language = @"1"; // 繁體中文 + language = @"1"; } - }else if([language hasPrefix:@"ar"]){///阿拉伯语 + }else if([language hasPrefix:@"ar"]){ language = @"7"; - }else{///英文 + }else{ language = @"2"; } return language; } -// 销毁游戏 + - (void) destroy:(NSDictionary*)args { NSLog(@"BSGAME %s","游戏调⽤destroy"); - //关闭游戏 - [self willMoveToParentViewController:nil]; //1 - [self.view removeFromSuperview]; //2 - [self removeFromParentViewController]; //3 + + [self willMoveToParentViewController:nil]; + [self.view removeFromSuperview]; + [self removeFromParentViewController]; } -(void)backBtnAction{ TTAlertConfig *config = [[TTAlertConfig alloc]init]; @@ -613,11 +609,11 @@ NSString * const kJPClose = @"newTppClose"; } cancelHandler:^{ }]; } -// 提⽰余额不⾜ + - (void) gameRecharge:(NSDictionary*)args { NSLog(@"BSGAME %s","游戏调⽤gameRecharge"); - //拉起充值商城 + TTAlertConfig *config = [[TTAlertConfig alloc]init]; config.title = YMLocalizedString(@"UserDetail_CP_Toast_0"); config.message = YMLocalizedString(@"XPNobleCenterViewController3"); @@ -633,17 +629,12 @@ NSString * const kJPClose = @"newTppClose"; }]; } -// 游戏加载完毕 + - (void) gameLoaded:(NSDictionary*)args { - // 游戏加载完毕 + [self.backBtn removeFromSuperview]; } @end - - - - - diff --git a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m.backup b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m.backup new file mode 100644 index 0000000..3c26a88 --- /dev/null +++ b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m.backup @@ -0,0 +1,649 @@ +// +// MSRoomGameWebVC.m +// YuMi +// +// Created by duoban on 2024/4/28. +// + +#import "MSRoomGameWebVC.h" +#import "LittleGameInfoModel.h" +#import "RoomInfoModel.h" +#import "XPIAPRechargeViewController.h" + +@interface MSWeakWebViewScriptMessageDelegate : NSObject + +//WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法 +@property (nonatomic, weak) id scriptDelegate; + +- (instancetype)initWithDelegate:(id)scriptDelegate; + +@end +@implementation MSWeakWebViewScriptMessageDelegate + +- (instancetype)initWithDelegate:(id)scriptDelegate { + self = [super init]; + if (self) { + _scriptDelegate = scriptDelegate; + } + return self; +} + +//遵循WKScriptMessageHandler协议,必须实现如下方法,然后把方法向外传递 +//通过接收JS传出消息的name进行捕捉的回调方法 +- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { + + if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) { + [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message]; + } +} + +@end + + +typedef NS_ENUM(NSInteger, MSGameType) { + MSGameTypeBaiShun, // 百顺游戏 + MSGameTypeJoyPlay, // JoyPlay游戏 + MSGameTypeCC // CC游戏 +}; + +NSString * const kMSGetConfig = @"getConfig"; +NSString * const kMSDestroy = @"destroy"; +NSString * const kMSGameRecharge = @"gameRecharge"; +NSString * const kMSGameLoaded = @"gameLoaded"; + +NSString * const kJPRecharge = @"recharge"; +NSString * const kJPClickRecharge = @"clickRecharge"; +NSString * const kJPClose = @"newTppClose"; + + + +@interface MSRoomGameWebVC () +@property (strong, nonatomic) WKWebView *webView; +@property (strong, nonatomic) UIProgressView *progressView; +@property (nonatomic, strong) WKUserContentController *ms_userContentController; +@property (nonatomic,weak) id hostDelegate; +@property(nonatomic,strong) ActivityInfoModel *gameModel; +@property(nonatomic,strong) UIButton *backBtn; +@property (nonatomic, assign) MSGameType gameType; +@property (nonatomic, assign) BOOL isCharing; +@property (nonatomic, strong) NSURLRequest *lastRequest; +@property (nonatomic, assign) NSInteger retryCount; +@property (nonatomic, strong) NSTimer *loadingTimer; +@end + +@implementation MSRoomGameWebVC + +- (void)dealloc { + [self cleanupWebView]; + [self hideHUD]; + [self.loadingTimer invalidate]; + self.loadingTimer = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)cleanupWebView { + if (_webView) { + [_webView stopLoading]; + _webView.navigationDelegate = nil; + _webView.UIDelegate = nil; + [_webView removeFromSuperview]; + _webView = nil; + } + + if (_ms_userContentController) { + [_ms_userContentController removeScriptMessageHandlerForName:kMSGetConfig]; + [_ms_userContentController removeScriptMessageHandlerForName:kMSDestroy]; + [_ms_userContentController removeScriptMessageHandlerForName:kMSGameRecharge]; + [_ms_userContentController removeScriptMessageHandlerForName:kMSGameLoaded]; + [_ms_userContentController removeScriptMessageHandlerForName:@"closeGame"]; + [_ms_userContentController removeScriptMessageHandlerForName:@"pay"]; + [_ms_userContentController removeScriptMessageHandlerForName:kJPClose]; + [_ms_userContentController removeScriptMessageHandlerForName:kJPRecharge]; + [_ms_userContentController removeScriptMessageHandlerForName:kJPClickRecharge]; + _ms_userContentController = nil; + } +} + +- (instancetype)initWithDelegate:(id)delegate gameModel:(ActivityInfoModel *)gameModel +{ + self = [super init]; + if (self) { + self.hostDelegate = delegate; + self.gameModel = gameModel; + NSString *upperCode = gameModel.code.uppercaseString; + if ([upperCode isEqualToString:@"BAISHUN"]) { + self.gameType = MSGameTypeBaiShun; + } else if ([upperCode isEqualToString:@"JOYPLAY"]) { + self.gameType = MSGameTypeJoyPlay; + } else { + self.gameType = MSGameTypeCC; + } + } + return self; +} +- (BOOL)isHiddenNavBar { + return YES; +} +- (void)viewDidLoad { + [super viewDidLoad]; + [self installUI]; + [self setupBackButton]; +#if DEBUG +// [self setupLoadingTimer]; +#endif + [self setupNotifications]; + [self showLoading]; +} + +- (void)setupLoadingTimer { + self.loadingTimer = [NSTimer scheduledTimerWithTimeInterval:15.0 + target:self + selector:@selector(handleLoadingTimeout) + userInfo:nil + repeats:NO]; +} + +- (void)setupNotifications { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleApplicationDidBecomeActive) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleApplicationWillResignActive) + name:UIApplicationWillResignActiveNotification + object:nil]; +} + +- (void)handleLoadingTimeout { + [self hideHUD]; + [XNDJTDDLoadingTool showErrorWithMessage:@"加载超时,请检查网络后重试"]; +} + +- (void)handleApplicationDidBecomeActive { + if (self.webView && !self.webView.isLoading) { + [self.webView reload]; + } +} + +- (void)handleApplicationWillResignActive { + [self.webView evaluateJavaScript:@"if(typeof(onAppPause) === 'function') { onAppPause(); }" completionHandler:nil]; +} + + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + if (self.gameType != MSGameTypeBaiShun && + self.isCharing) { + self.isCharing = NO; + [self updateCoin]; + } +} + +- (void)setupBackButton { + if (self.gameType == MSGameTypeJoyPlay && self.gameModel.showType == ActivityShowType_Full) { + return; + } + self.backBtn = [UIButton new]; + [self.view addSubview:self.backBtn]; + self.backBtn.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight); + [self.backBtn addTarget:self action:@selector(backBtnAction) forControlEvents:UIControlEventTouchUpInside]; +} + +- (void)installUI { + self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; + [self setupWebViewConfiguration]; + [self setupWebViewConfiguration]; + [self loadGameContent]; +} + +- (void)setupWebViewConfiguration { + MSWeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[MSWeakWebViewScriptMessageDelegate alloc] initWithDelegate:self]; + _ms_userContentController = [[WKUserContentController alloc] init]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGetConfig]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSDestroy]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGameRecharge]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGameLoaded]; + + /// LEADERCC + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:@"closeGame"]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:@"pay"]; + + /// JOYPLAY + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate + name:kJPClose]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate + name:kJPRecharge]; + [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate + name:kJPClickRecharge]; + + + WKWebViewConfiguration *config = [WKWebViewConfiguration new]; + config.allowsInlineMediaPlayback = YES; + config.mediaTypesRequiringUserActionForPlayback = NO; + [config setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"]; + //⾳视频的播放不需要⽤⼾⼿势触发, 即为⾃动播放 + config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; + config.preferences = [[WKPreferences alloc]init]; + WKPreferences *preferences = [WKPreferences new]; + preferences.javaScriptCanOpenWindowsAutomatically = YES; + config.preferences = preferences; + config.preferences.javaScriptEnabled = YES; + config.userContentController = _ms_userContentController; + + CGRect frame = CGRectZero; + if (self.gameType == MSGameTypeBaiShun) { + frame = CGRectMake(0,0, + KScreenWidth, KScreenHeight); + } else { + if(self.gameModel.showType == ActivityShowType_Half){ + frame = CGRectMake(0, KScreenHeight * 0.3, + KScreenWidth, KScreenHeight * 0.7); + } else { + frame = CGRectMake(0,0, + KScreenWidth, KScreenHeight); + } + } + + self.webView = [[WKWebView alloc] initWithFrame:frame + configuration:config]; + [self.webView.scrollView setBackgroundColor:[UIColor clearColor]]; + [self.webView setBackgroundColor:[UIColor clearColor]]; + [self.webView setUIDelegate:self]; + self.webView.navigationDelegate = self; + //设置⽹⻚透明 + [self.webView setOpaque:NO]; + //设置⽹⻚全屏 + if (@available(iOS 11.0, *)) { + self.webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [self.view addSubview:self.webView]; +} + +- (void)loadGameContent { + NSString *h5Url = self.gameModel.skipContent; + NSURL *url = [self handleGameURL:h5Url]; + + if (!url) { + [self hideHUD]; + [XNDJTDDLoadingTool showErrorWithMessage:@"游戏链接无效"]; + return; + } + + NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:15.0]; + self.lastRequest = request; + [self.webView loadRequest:request]; +} + +- (BOOL)isValidGameURL:(NSString *)urlString { + if ([NSString isEmpty:urlString]) { + return NO; + } + + NSURL *url = [NSURL URLWithString:urlString]; + return (url && url.scheme && url.host); +} + +- (NSURL *)handleGameURL:(NSString *)url { + if (![self isValidGameURL:url]) { + return nil; + } + + switch (self.gameType) { + case MSGameTypeBaiShun: + url = [self addSupportLanguage:url]; + return [NSURL URLWithString:url]; + case MSGameTypeJoyPlay: + url = [url stringByAppendingFormat:@"?gameId=%@", @(self.gameModel.gameModel.gameId)]; + url = [url stringByAppendingFormat:@"&appKey=%@", + self.gameModel.gameModel.appKey]; + url = [url stringByAppendingFormat:@"&mini=%@", @(self.gameModel.showType == ActivityShowType_Half ? 1 : 0)]; + if (self.gameModel.showType == ActivityShowType_Full) { + url = [url stringByAppendingFormat:@"&safeTop=1"]; + } + url = [url stringByAppendingFormat:@"&roomId=%ld", + (long)self.hostDelegate.getRoomInfo.uid]; + break; + case MSGameTypeCC: + url = [url stringByAppendingFormat:@"&roomid=%ld", + (long)self.hostDelegate.getRoomInfo.uid]; + break; + default: + break; + } + + url = [self addSupportLanguage:url]; + + if (![NSString isEmpty:self.gameModel.gameModel.urlParam]) { + url = [url stringByAppendingString:[NSString stringWithFormat:@"&%@", self.gameModel.gameModel.urlParam]]; + } + + url = [url stringByAppendingFormat:@"&token=%@", self.gameModel.gameModel.code]; + url = [url stringByAppendingFormat:@"&uid=%@", [AccountInfoStorage instance].getUid]; + + return [NSURL URLWithString:url]; +} + +- (NSString *)addSupportLanguage:(NSString *)url { + NSString *mark = @"&"; + NSString *lang = @"en-US"; + if (![url containsString:@"?"]) { + mark = @"?"; + } + if (isMSTR()) { + lang = @"tr-TR"; + } else if (isMSZH()) { + lang = @"zh-TW"; + } else if (isMSRTL()) { + lang = @"ar-EG"; + } else if (isMSPT()) { + lang = @"pt-BR"; + } else if (isMSES()) { + lang = @"es-ES"; + } + url = [url stringByAppendingFormat:@"%@lang=%@", mark, lang]; + return url; +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + [self hideHUD]; + self.retryCount = 0; + [self.loadingTimer invalidate]; + self.loadingTimer = nil; + + if (self.gameType != MSGameTypeBaiShun) { + self.backBtn.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight*0.3); + } + + // 注入错误处理脚本 + NSString *errorHandler = @"window.onerror = function(msg, url, line, col, error) { window.webkit.messageHandlers.error.postMessage({message: msg, url: url, line: line, col: col}); return false; }"; + [webView evaluateJavaScript:errorHandler completionHandler:nil]; + +#if DEBUG + NSString *fileName = @"vconsole.min.js"; // 你要查找的文件名 + NSString *directory = [[NSBundle mainBundle] resourcePath]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:directory]; + NSString *filePath; + + for (NSString *path in enumerator) { + if ([[path lastPathComponent] containsString:fileName]) { + filePath = [directory stringByAppendingPathComponent:path]; + break; + } + } + + if (filePath.length > 0) { + NSString *vConsoleScript = [NSString stringWithContentsOfFile:filePath + encoding:NSUTF8StringEncoding error:nil]; + [self.webView evaluateJavaScript:vConsoleScript completionHandler:nil]; + + // 初始化 vConsole + NSString *initVConsoleScript = @"var vConsole = new VConsole();"; + [self.webView evaluateJavaScript:initVConsoleScript completionHandler:nil]; + } +#endif +} + +- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { + [self handleWebViewError:error]; +} + +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { + [self handleWebViewError:error]; +} + +- (void)handleWebViewError:(NSError *)error { + if (self.retryCount < 3) { + self.retryCount++; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self.webView loadRequest:self.lastRequest]; + }); + } else { + [self hideHUD]; + [XNDJTDDLoadingTool showErrorWithMessage:@"网络连接失败,请稍后重试"]; + + } +} + +- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { + if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { + NSURLCredential *card = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust]; + completionHandler(NSURLSessionAuthChallengeUseCredential, card); + } else { + completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); + } +} + +// 调⽤JS +- (void)callJs:(NSString*)method withJavaScriptValue:(nullable id)arguments +{ + @kWeakify(self); + if (arguments) { + NSData *data = [NSJSONSerialization dataWithJSONObject:arguments + options:(NSJSONWritingPrettyPrinted) error:nil]; + NSString *jsonStr = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + NSString *jsMethods = [NSString stringWithFormat:@"%@(%@)", method, + jsonStr]; + [self.webView evaluateJavaScript:jsMethods completionHandler:^(id + _Nullable resp, NSError * _Nullable error) { + @kStrongify(self); + NSLog(@"error = %@ , response = %@",error, resp); + [self.backBtn removeFromSuperview]; + }]; + } else { + NSString *jsMethods = [NSString stringWithFormat:@"%@({})", method]; + [self.webView evaluateJavaScript:jsMethods completionHandler:^(id + _Nullable resp, NSError * _Nullable error) { + @kStrongify(self); + NSLog(@"error = %@ , response = %@",error, resp); + [self.backBtn removeFromSuperview]; + }]; + } +} +- (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString +{ + if (jsonString == nil && jsonString.length == 0) { + return nil; + } + + NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSError *err; + NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData + options:NSJSONReadingMutableContainers + error:&err]; + if(err) + { + NSLog(@"json解析失败:%@",err); + return nil; + } + return dic; +} +// 绑定协议⽅法 +- (void)userContentController:(WKUserContentController *)userContentController + didReceiveScriptMessage:(WKScriptMessage *)message +{ + /// BaiShun + switch (self.gameType) { + case MSGameTypeBaiShun: { + NSDictionary *dicBody = [self dictionaryWithJsonString:message.body]; + if ([message.name isEqualToString:kMSGetConfig]) { + [self getConfig:dicBody]; + } else if ([message.name isEqualToString:kMSDestroy]) { + [self destroy:dicBody]; + } else if ([message.name isEqualToString:kMSGameLoaded]) { + [self gameLoaded:dicBody]; + } else if ([message.name isEqualToString:kMSGameRecharge]) { + [self gameRecharge:dicBody]; + } else { + NSLog(@"未实现⽅法 : %@ --> %@", message.name, message.body); + } + break; + } + case MSGameTypeJoyPlay: { + if ([message.name isEqualToString:kJPRecharge]) { + XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; + webVC.type = @"4"; + [self.navigationController pushViewController:webVC animated:YES]; + self.isCharing = YES; + } else if ([message.name isEqualToString:kJPClickRecharge]) { + [self gameRecharge:@{}]; + } else if ([message.name isEqualToString:kJPClose]) { + [self backBtnAction]; + } + break; + } + case MSGameTypeCC: { + /// LeaderCC + NSString* method = [NSString stringWithFormat:@"%@:", message.name]; + SEL selector = NSSelectorFromString(method); + if([self respondsToSelector:selector]){ + [self performSelector:selector withObject:message.body]; + }else{ + NSLog(@"未實現方法 : %@ --> %@", message.name, message.body); + } + break; + } + } +} + +#pragma mark - LeaderCC Delegate +// 关闭游戏 +- (void)closeGame:(NSDictionary*)args { + [self backBtnAction]; +} + +// 显示充值界面 +- (void)pay:(NSDictionary*)args { + //拉起充值商城 + TTAlertConfig *config = [[TTAlertConfig alloc]init]; + config.title = YMLocalizedString(@"UserDetail_CP_Toast_0"); + config.message = YMLocalizedString(@"XPNobleCenterViewController3"); + config.actionStyle = TTAlertActionBothStyle; + @kWeakify(self); + [TTPopup alertWithConfig:config showBorder:NO confirmHandler:^{ + @kStrongify(self); + XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; + webVC.type = @"4"; + [self.navigationController pushViewController:webVC animated:YES]; + self.isCharing = YES; + } cancelHandler:^{ + + }]; +} + +- (void)updateCoin { + // 平时游戏币更新不需要调用该方法,以防止影响游戏开奖动画。 + [self.webView evaluateJavaScript:@"updateCoin()" completionHandler:^(id _Nullable result, NSError * _Nullable error) { + if (error) { + NSLog(@"Error calling JS function: %@", error.localizedDescription); + } else { + NSLog(@"JS function called successfully, result: %@", result); + } + }]; +} + +#pragma mark - BaiShun Delegate +// 获取信息配置 +- (void) getConfig:(NSDictionary*)args +{ + NSLog(@"BSGAME %s","游戏调⽤getConfig"); + NSString* method = [args objectForKey:@"jsCallback"]; + RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo; + ActivityInfoItemModel *gameModel = self.gameModel.gameModel; + NSString *appChannel = gameModel.appChannel ?: @""; + int64_t appId = gameModel.appId; + NSString *userId = [AccountInfoStorage instance].getUid; + NSString *code = gameModel.code ?: @""; + NSString *roomId = [NSString stringWithFormat:@"%ld",roomInfo.uid]; + NSString *gameMode = gameModel.gameMode ?: @""; + NSDictionary *gameConfig = gameModel.gameConfig ?: @{}; + int gsp = gameModel.gsp; + // 数据只是参考值,需要根据⾃⼰APP进⾏赋值 + NSObject* configData = @{ + @"appChannel":appChannel, + @"appId":@(appId), + @"userId":userId, + @"code":code, + @"roomId":roomId, + @"gameMode":gameMode, + @"language":[self getlanguage], + @"gameConfig":gameConfig, + @"gsp":@(gsp), + }; + [self callJs:method withJavaScriptValue:configData]; +} +-(NSString *)getlanguage{ + NSString *language = [NSBundle getLanguageText]; + if ([language hasPrefix:@"zh"]) { + if ([language rangeOfString:@"Hans"].location != NSNotFound) { + language = @"0"; // 简体中文 + } else { + language = @"1"; // 繁體中文 + } + }else if([language hasPrefix:@"ar"]){///阿拉伯语 + language = @"7"; + }else{///英文 + language = @"2"; + } + return language; +} +// 销毁游戏 +- (void) destroy:(NSDictionary*)args +{ + NSLog(@"BSGAME %s","游戏调⽤destroy"); + //关闭游戏 + [self willMoveToParentViewController:nil]; //1 + [self.view removeFromSuperview]; //2 + [self removeFromParentViewController]; //3 +} +-(void)backBtnAction{ + TTAlertConfig *config = [[TTAlertConfig alloc]init]; + config.title = YMLocalizedString(@"UserDetail_CP_Toast_0"); + config.message = YMLocalizedString(@"MSRoomGameWebVC0"); + config.actionStyle = TTAlertActionBothStyle; + @kWeakify(self); + [TTPopup alertWithConfig:config showBorder:NO confirmHandler:^{ + @kStrongify(self); + [self destroy:nil]; + } cancelHandler:^{ + }]; +} +// 提⽰余额不⾜ +- (void) gameRecharge:(NSDictionary*)args +{ + NSLog(@"BSGAME %s","游戏调⽤gameRecharge"); + //拉起充值商城 + TTAlertConfig *config = [[TTAlertConfig alloc]init]; + config.title = YMLocalizedString(@"UserDetail_CP_Toast_0"); + config.message = YMLocalizedString(@"XPNobleCenterViewController3"); + config.actionStyle = TTAlertActionBothStyle; + @kWeakify(self); + [TTPopup alertWithConfig:config showBorder:NO confirmHandler:^{ + @kStrongify(self); + XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; + webVC.type = @"4"; + [self.navigationController pushViewController:webVC animated:YES]; + self.isCharing = YES; + } cancelHandler:^{ + + }]; +} +// 游戏加载完毕 +- (void) gameLoaded:(NSDictionary*)args +{ + // 游戏加载完毕 + [self.backBtn removeFromSuperview]; +} + +@end + + + + + + diff --git a/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h index 95b1aa7..fdaf330 100644 --- a/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h +++ b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h @@ -1,9 +1,7 @@ -// -// PIWebViewSavePhotoView.h -// YuMi -// + + // Created by duoban on 2024/3/14. -// + #import diff --git a/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h.backup b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h.backup new file mode 100644 index 0000000..95b1aa7 --- /dev/null +++ b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.h.backup @@ -0,0 +1,18 @@ +// +// PIWebViewSavePhotoView.h +// YuMi +// +// Created by duoban on 2024/3/14. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PIWebViewSavePhotoView : UIView +@property(nonatomic,copy) NSString *text; +@property(nonatomic,copy) UIImage *image; +@property(nonatomic,copy) NSString *code; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m index 6f83574..3dc1405 100644 --- a/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m +++ b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m @@ -1,9 +1,7 @@ -// -// PIWebViewSavePhotoView.m -// YuMi -// + + // Created by duoban on 2024/3/14. -// + #import "PIWebViewSavePhotoView.h" @interface PIWebViewSavePhotoView() diff --git a/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m.backup b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m.backup new file mode 100644 index 0000000..6f83574 --- /dev/null +++ b/YuMi/Modules/YMWeb/PIWebViewSavePhotoView.m.backup @@ -0,0 +1,180 @@ +// +// PIWebViewSavePhotoView.m +// YuMi +// +// Created by duoban on 2024/3/14. +// + +#import "PIWebViewSavePhotoView.h" +@interface PIWebViewSavePhotoView() +@property(nonatomic,strong) UIImageView *topView; +@property(nonatomic,strong) UIImageView *bottomView; +@property(nonatomic,strong) UIImageView *topTextImageView; +@property(nonatomic,strong) UIView *bgCodeView; +@property(nonatomic,strong) UIImageView *bgCodeText; +@property(nonatomic,strong) UILabel *codeText; +@property(nonatomic,strong) NetImageView *codeView; +@property(nonatomic,strong) UILabel *tipView; +@property(nonatomic,strong) UIButton *codeBtn; +@end +@implementation PIWebViewSavePhotoView + +-(instancetype)initWithFrame:(CGRect)frame{ + self = [super initWithFrame:frame]; + if(self){ + [self installUI]; + [self installConstraints]; + } + return self; +} +-(void)installUI{ + [self addSubview:self.topView]; + [self addSubview:self.bottomView]; + [self addSubview:self.topTextImageView]; + [self addSubview:self.bgCodeView]; + [self.bgCodeView addSubview:self.bgCodeText]; + [self.bgCodeText addSubview:self.codeText]; + + [self.bgCodeView addSubview:self.codeView]; + [self.bgCodeView addSubview:self.tipView]; + + [self.bgCodeView addSubview:self.codeBtn]; + + +} +-(void)installConstraints{ + [self.topView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.leading.trailing.mas_equalTo(0); + make.height.mas_equalTo(kGetScaleWidth(326)); + }]; + [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self); + make.top.mas_equalTo(kGetScaleWidth(303)); + make.height.mas_equalTo(kGetScaleWidth(509)); + }]; + [self.topTextImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(132)); + make.width.mas_equalTo(kGetScaleWidth(297)); + make.height.mas_equalTo(kGetScaleWidth(32.5)); + make.centerX.equalTo(self); + }]; + [self.bgCodeView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(kGetScaleWidth(345)); + make.height.mas_equalTo(kGetScaleWidth(431)); + make.top.equalTo(self.topTextImageView.mas_bottom).mas_offset(kGetScaleWidth(186.5)); + make.centerX.equalTo(self); + }]; + [self.bgCodeText mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.centerX.equalTo(self.bgCodeView); + make.width.mas_equalTo(kGetScaleWidth(290)); + make.height.mas_equalTo(kGetScaleWidth(43)); + }]; + [self.codeText mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(3)); + make.bottom.mas_equalTo(-kGetScaleWidth(3)); + make.leading.trailing.equalTo(self.bgCodeText).inset(kGetScaleWidth(10)); + }]; + [self.codeView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kGetScaleWidth(200)); + make.centerX.equalTo(self.bgCodeView); + make.top.mas_equalTo(kGetScaleWidth(96)); + }]; + [self.tipView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(321)); + make.height.mas_equalTo(kGetScaleWidth(14)); + make.centerX.equalTo(self.bgCodeView); + }]; + [self.codeBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(kGetScaleWidth(355)); + make.width.mas_equalTo(kGetScaleWidth(241)); + make.height.mas_equalTo(kGetScaleWidth(46)); + make.centerX.equalTo(self.bgCodeView); + }]; +} +-(void)setText:(NSString *)text{ + _text = text; + _codeText.text = text; + +} +-(void)setImage:(UIImage *)image{ + _image = image; + _codeView.image = _image; +} + +- (void)setCode:(NSString *)code{ + _code = code; + NSString *text = [NSString stringWithFormat:@"%@%@",YMLocalizedString(@"PIWebViewSavePhotoView1"),_code]; + [_codeBtn setTitle:text forState:UIControlStateNormal]; +} +#pragma mark - 懒加载 +- (UIImageView *)topView{ + if(!_topView){ + _topView = [UIImageView new]; + _topView.image = kImage(@"pi_webView_code_top"); + } + return _topView; +} + +- (UIImageView *)bottomView{ + if(!_bottomView){ + _bottomView = [UIImageView new]; + _bottomView.image = kImage(@"pi_webView_code_bottom"); + } + return _bottomView; +} +- (UIImageView *)topTextImageView{ + if(!_topTextImageView){ + _topTextImageView = [UIImageView new]; + _topTextImageView.image = [UIImage getLanguageImage:@"pi_webView_code_top_text"]; + } + return _topTextImageView; +} +- (UIImageView *)bgCodeText{ + if(!_bgCodeText){ + _bgCodeText = [UIImageView new]; + _bgCodeText.image = kImage(@"pi_webView_code_code_text"); + } + return _bgCodeText; +} +- (UIView *)bgCodeView{ + if(!_bgCodeView){ + _bgCodeView = [UIView new]; + _bgCodeView.layer.cornerRadius = kGetScaleWidth(20); + _bgCodeView.layer.masksToBounds = YES; + _bgCodeView.backgroundColor = [UIColor whiteColor]; + } + return _bgCodeView; +} +- (UILabel *)codeText{ + if(!_codeText){ + _codeText = [UILabel labelInitWithText:@"" font:kFontRegular(12) textColor:[UIColor whiteColor]]; + _codeText.textAlignment = NSTextAlignmentCenter; + _codeText.numberOfLines = 0; + } + return _codeText; +} + +- (UILabel *)tipView{ + if(!_tipView){ + _tipView = [UILabel labelInitWithText:YMLocalizedString(@"PIWebViewSavePhotoView0") font:kFontRegular(10) textColor:UIColorFromRGB(0x999999)]; + } + return _tipView; +} +- (UIButton *)codeBtn{ + if(!_codeBtn){ + _codeBtn = [UIButton new]; + NSString *text = [NSString stringWithFormat:@"%@GHT32",YMLocalizedString(@"PIWebViewSavePhotoView1")]; + [_codeBtn setTitle:text forState:UIControlStateNormal]; + _codeBtn.titleLabel.font = kFontRegular(16); + [_codeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [_codeBtn setBackgroundImage:kImage(@"pi_webView_code_btn_bg") forState:UIControlStateNormal]; + } + return _codeBtn; +} +- (NetImageView *)codeView{ + if(!_codeView){ + _codeView = [NetImageView new]; + } + return _codeView; +} +@end diff --git a/YuMi/Modules/YMWeb/XPWebViewController.h b/YuMi/Modules/YMWeb/XPWebViewController.h index eda8983..fa1a732 100644 --- a/YuMi/Modules/YMWeb/XPWebViewController.h +++ b/YuMi/Modules/YMWeb/XPWebViewController.h @@ -1,9 +1,7 @@ -// -// XPWebViewController.h -// YuMi -// + + // Created by z on 2021/9/16. -// + #import "BaseViewController.h" #import @@ -18,27 +16,27 @@ NS_ASSUME_NONNULL_BEGIN @interface XPWebViewController : BaseViewController -/// + @property (nonatomic,weak) id delegate; @property (strong, nonatomic) WKWebView *webview; -///跳转方式,如果push的直接pushViewController,不用dismissViewControllerAnimated后再pushViewController + @property (nonatomic,assign) BOOL isPush; -///是否从精灵页面过来 + @property (nonatomic,assign) BOOL isFairyPay; @property (nonatomic,assign) BOOL is_Pi_FairyPay; -///XPWebViewController是否作为属性,yes则 + @property (nonatomic,assign) BOOL isProperty; @property (copy, nonatomic) NSString *url; @property(nonatomic, assign) BOOL isLoginStatus; -/// URL加载完成回调,result:加载结果成功/失败,error:失败原因 + @property (nonatomic, copy) void (^urlLoadCompleted)(BOOL result, NSError * _Nullable error); -///是都隐藏导航栏 目前适用于半屏的情况下 + @property (nonatomic,copy) void (^InitShowNavBlock)(BOOL show); -///关闭webView 目前适用于半屏的情况下 + @property (nonatomic,copy) void (^CloseWebViewBlock)(BOOL result); @property(nonatomic, copy) void (^verifyCaptcha)(BOOL result); @@ -47,8 +45,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithCustomizeNav:(BOOL)isCustom; -///强制使用 roomUID 初始化,尽量传入,防止 web 在需要时取不到数据 -// 更好的做法是,全具保持一个 roomUID 记录 + @property (nonatomic,copy) NSString *roomUid; - (instancetype)initWithRoomUID:(NSString * _Nullable)roomUid; - (instancetype)init NS_UNAVAILABLE; diff --git a/YuMi/Modules/YMWeb/XPWebViewController.h.backup b/YuMi/Modules/YMWeb/XPWebViewController.h.backup new file mode 100644 index 0000000..eda8983 --- /dev/null +++ b/YuMi/Modules/YMWeb/XPWebViewController.h.backup @@ -0,0 +1,60 @@ +// +// XPWebViewController.h +// YuMi +// +// Created by z on 2021/9/16. +// + +#import "BaseViewController.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol XPWebViewControllerDelegate + +-(void)payHandler; + +@end + + +@interface XPWebViewController : BaseViewController +/// +@property (nonatomic,weak) id delegate; +@property (strong, nonatomic) WKWebView *webview; +///跳转方式,如果push的直接pushViewController,不用dismissViewControllerAnimated后再pushViewController +@property (nonatomic,assign) BOOL isPush; + +///是否从精灵页面过来 +@property (nonatomic,assign) BOOL isFairyPay; +@property (nonatomic,assign) BOOL is_Pi_FairyPay; + +///XPWebViewController是否作为属性,yes则 +@property (nonatomic,assign) BOOL isProperty; +@property (copy, nonatomic) NSString *url; + +@property(nonatomic, assign) BOOL isLoginStatus; + +/// URL加载完成回调,result:加载结果成功/失败,error:失败原因 +@property (nonatomic, copy) void (^urlLoadCompleted)(BOOL result, NSError * _Nullable error); +///是都隐藏导航栏 目前适用于半屏的情况下 +@property (nonatomic,copy) void (^InitShowNavBlock)(BOOL show); +///关闭webView 目前适用于半屏的情况下 +@property (nonatomic,copy) void (^CloseWebViewBlock)(BOOL result); + +@property(nonatomic, copy) void (^verifyCaptcha)(BOOL result); + +@property (nonatomic, copy) void(^didTapCharge)(void); + +- (instancetype)initWithCustomizeNav:(BOOL)isCustom; + +///强制使用 roomUID 初始化,尽量传入,防止 web 在需要时取不到数据 +// 更好的做法是,全具保持一个 roomUID 记录 +@property (nonatomic,copy) NSString *roomUid; +- (instancetype)initWithRoomUID:(NSString * _Nullable)roomUid; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMWeb/XPWebViewController.m b/YuMi/Modules/YMWeb/XPWebViewController.m index a708a43..ea3ee42 100644 --- a/YuMi/Modules/YMWeb/XPWebViewController.m +++ b/YuMi/Modules/YMWeb/XPWebViewController.m @@ -1,9 +1,7 @@ -// -// XPWebViewController.m -// YuMi -// + + // Created by zu on 2021/9/16. -// + #import "XPWebViewController.h" #import "AccountInfoStorage.h" @@ -22,7 +20,7 @@ #import "YuMi-swift.h" #import "RechargeStorage.h" -///vc + #import "MyDressingViewController.h" #import "ShoppingMallViewController.h" #import "XPRoomViewController.h" @@ -40,19 +38,19 @@ #import "IAPManager.h" typedef NS_ENUM(NSUInteger, RightNavigationPushType){ - ///跳转h5页面 + RightNavigationPushType_Web = 1, - ///分享 + RightNavigationPushType_Share = 2, - ///跳转原生页面 + RightNavigationPushType_AppPage = 3, - ///分享图片 + RightNavigationPushType_SharePicture = 5 }; @interface WeakWebViewScriptMessageDelegate : NSObject -//WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法 + @property (nonatomic, weak) id scriptDelegate; - (instancetype)initWithDelegate:(id)scriptDelegate; @@ -68,8 +66,7 @@ typedef NS_ENUM(NSUInteger, RightNavigationPushType){ return self; } -//遵循WKScriptMessageHandler协议,必须实现如下方法,然后把方法向外传递 -//通过接收JS传出消息的name进行捕捉的回调方法 + - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) { @@ -81,21 +78,21 @@ typedef NS_ENUM(NSUInteger, RightNavigationPushType){ @interface XPWebViewController () @property (nonatomic,strong) WalletInfoModel *model ; -//@property (strong, nonatomic) WKWebView *webview; + @property (strong, nonatomic) UIProgressView *progressView; @property (nonatomic, strong) WKUserContentController *pi_userContentController; -///分享的内容 + @property (nonatomic,copy) NSDictionary *shareDic; -///分享的内容 + @property (nonatomic,copy) NSDictionary *savePhotoDic; -/// + @property (nonatomic,strong) XPWebViewNavView *navView; -/// + @property (nonatomic,assign) BOOL isCustom; @property(nonatomic,strong) PIWebViewSavePhotoView *saveView; -/// 订单编号 + @property (nonatomic,copy) NSString *orderId; @property (nonatomic, assign) BOOL isHideNavBar; @@ -203,7 +200,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; }]; } -//指定回调方法 + - (void)image: (UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ self.saveView.hidden = YES; NSString *msg = YMLocalizedString(@"PIWebViewSavePhotoView2"); @@ -265,9 +262,9 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; } - (void)xPWebViewNavView:(XPWebViewNavView *)view didClickBack:(UIButton *)sender{ if(self.is_Pi_FairyPay){ - [self willMoveToParentViewController:nil]; //1 - [self.view removeFromSuperview]; //2 - [self removeFromParentViewController]; //3 + [self willMoveToParentViewController:nil]; + [self.view removeFromSuperview]; + [self removeFromParentViewController]; return; } if(self.isFairyPay){ @@ -278,15 +275,15 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; } [self dismissViewControllerAnimated:YES completion:nil]; } -//加载完成 + - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { - //加载完成后隐藏progressView + self.progressView.hidden = YES; if (self.urlLoadCompleted) { self.urlLoadCompleted(YES, nil); } #if DEBUG - NSString *fileName = @"vconsole.min.js"; // 你要查找的文件名 + NSString *fileName = @"vconsole.min.js"; NSString *directory = [[NSBundle mainBundle] resourcePath]; NSFileManager *fileManager = [NSFileManager defaultManager]; @@ -305,7 +302,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; encoding:NSUTF8StringEncoding error:nil]; [webView evaluateJavaScript:vConsoleScript completionHandler:nil]; - // 初始化 vConsole + NSString *initVConsoleScript = @"var vConsole = new VConsole();"; [webView evaluateJavaScript:initVConsoleScript completionHandler:nil]; } @@ -318,34 +315,34 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; NSDictionary *headers = response.allHeaderFields; - // NSLog(@"Response Headers: %@", headers); + NSString *contentEncoding = headers[@"Content-Encoding"]; if ([contentEncoding isEqualToString:@"gzip"]) { - // NSLog(@"✅ Gzip 响应已启用"); + } else { - // NSLog(@"❌ Gzip 响应未启用"); + } decisionHandler(WKNavigationResponsePolicyAllow); } #endif -//加载失败 + - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { - //加载失败同样需要隐藏progressView + self.progressView.hidden = YES; if (self.urlLoadCompleted) { self.urlLoadCompleted(NO, error); } } -//捕抓打电话事件 + - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURL *URL = navigationAction.request.URL; NSString *scheme = [URL scheme]; NSURLRequest *request = navigationAction.request; - // Judge is whether to jump to other app. + if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) { BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:request.URL]; if (canOpen) { @@ -371,7 +368,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; [self.webview evaluateJavaScript:@"document.location.href" completionHandler:^(id _Nullable response, NSError * _Nullable error) { NSString *currentUrl = [NSString stringWithFormat:@"%@", response]; - ///测试环境只要有host就执行,方便h5连接本地调试 + BOOL condition = currentUrl != nil && [currentUrl containsString:API_HOST_URL]; NSLog(@"-- -- - -- - - | -- -- - -- - -%@", response); @@ -383,7 +380,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; if ([message.name isEqualToString:kJSOpenSharePage]) { if (message.body && message.body != [NSNull null]) { NSDictionary *body; - //不知道是哪个蓝精灵弄的,变成了个dic,所以我们要判断类型 + if ([message.body isKindOfClass:[NSDictionary class]]) { body = message.body; } else if ([message.body isKindOfClass:[NSString class]]) { @@ -396,34 +393,34 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; NSString *uid = [[AccountInfoStorage instance] getUid]; NSString *js = [NSString stringWithFormat:@"getMessage(\"uid\",%@)", uid]; [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { - // NSLog(@"%@",error); + }]; } else if ([message.name isEqualToString:kJSGetTicket]) { NSString *ticket = [[AccountInfoStorage instance] getTicket]; NSString *js = [NSString stringWithFormat:@"getMessage(\"ticket\",\"%@\")",ticket]; [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { - // NSLog(@"%@",error); + }]; } else if ([message.name isEqualToString:kJSGetDeviceId]) { NSString *js = [NSString stringWithFormat:@"getMessage(\"deviceId\",\"%@\")",[YYUtility deviceUniqueIdentification]]; [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { - // NSLog(@"%@",error); + }]; } else if ([message.name isEqualToString:kJSGetDeviceInfo]) { NSDictionary *basicParmars = [HttpRequestHelper configBaseParmars:[[NSDictionary alloc] init]]; NSString *json = [basicParmars mj_JSONString]; NSString *js = [NSString stringWithFormat:@"getMessage(\"deviceInfo\",%@)", json]; [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable ohter, NSError * _Nullable error) { - // NSLog(@"%@", error); + }]; } else if ([message.name isEqualToString:kJSOpenPurse]) { }else if([message.name isEqualToString:kJSChargePayPage]){ - // NSString *money = [NSString stringWithFormat:@"%@",message.body] ; + }else if([message.name isEqualToString:kJSChargePayClickPage]){ if(message.body != nil && self.model.diamonds != nil){ - // NSString *type = [NSString stringWithFormat:@"%@",message.body]; + } }else if ([message.name isEqualToString:kJSOpenChargePage]) { if(self.delegate && [self.delegate respondsToSelector:@selector(payHandler)]){ @@ -469,7 +466,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; } else if([message.name isEqualToString:kJSGetRoomUid]) { NSString *js = [NSString stringWithFormat:@"getMessage(\"roomUid\",\"%@\")",self.roomUid]; [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { - // NSLog(@"%@",error); + }]; } else if([message.name isEqualToString:kInitShowNav]) { if (((NSNumber *)message.body).intValue == 0) { @@ -491,7 +488,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; [self.navigationController popViewControllerAnimated:YES]; } } else if ([message.name isEqualToString:kJumpAppointPage]) { - // h5与原生交互新协议 + NSDictionary *bodyDict; if ([message.body isKindOfClass:[NSDictionary class]]) { bodyDict = message.body; @@ -535,7 +532,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; }); } } else if([message.name isEqualToString:kJSOpenRoomForGiftId]) { - // NSLog(@"%@", message.body); + NSDictionary *bodyDict; if ([message.body isKindOfClass:[NSDictionary class]]) { bodyDict = message.body; @@ -543,7 +540,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; NSString *str = (NSString *)message.body; bodyDict = [str toJSONObject]; } - //房间页 传参:uid + NSString *uid = [NSString stringWithFormat:@"%@", bodyDict[@"uid"]]; NSString *giftId = [NSString stringWithFormat:@"%@", bodyDict[@"giftId"]]; if (uid.length) { @@ -653,7 +650,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; switch (skyType) { case 1: { - //房间页 传参:uid + NSString *uid = [NSString stringWithFormat:@"%@", bodyDict[@"routerVal"]]; if (uid.length) { [XPRoomViewController openRoom:uid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; @@ -662,22 +659,22 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; break; case 7: { - //座驾 + MyDressingViewController *vc = [[MyDressingViewController alloc] init]; -// vc.currentIndex = 1; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:vc animated:YES]; } break; case 8: { - //头饰 + MyDressingViewController *vc = [[MyDressingViewController alloc] init]; -// vc.currentIndex = 0; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:vc animated:YES]; } break; case 75: - {//跳转对应的话题 + { bodyDict = [bodyDict toJSONObject]; NSString *topicId = bodyDict[@"routerVal"]; XPMomentTopicContainerViewController * topicVC = [[XPMomentTopicContainerViewController alloc] init]; @@ -704,7 +701,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; _url = [NSString stringWithFormat:@"%@", _url]; } - // 去掉 urlString 中的空格。 + NSString *noSpaceTextUrl = [_url stringByReplacingOccurrencesOfString:@" " withString:@""]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:noSpaceTextUrl]]; @@ -820,11 +817,11 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; NSString *ticket = [AccountInfoStorage instance].getTicket; [params setObject:uid forKey:@"uid"]; - // 添加类型安全检查,防止NSTaggedPointerString错误 + if ([shareInfo isKindOfClass:[XPShareInfoModel class]]) { [params setObject:@(shareInfo.shareType) forKey:@"shareType"]; } else { - // 如果不是预期类型,提供默认值 + [params setObject:@(0) forKey:@"shareType"]; NSLog(@"警告:shareInfo不是XPShareInfoModel类型,而是%@类型", NSStringFromClass([shareInfo class])); } @@ -870,7 +867,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; } else if ([keyPath isEqualToString:@"title"]) { if (object == self.webview) { self.navigationItem.title = self.webview.title; - if (self.urlLoadCompleted) {//半屏webview如果在加载完成回调后标题还会改变,在此处重新设置一遍 + if (self.urlLoadCompleted) { self.urlLoadCompleted(YES, nil); } }else{ @@ -893,7 +890,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; if (@available(iOS 10.0, *)) { configuration.mediaTypesRequiringUserActionForPlayback = NO; } else { - // Fallback on earlier versions + } configuration.allowsInlineMediaPlayback = YES; @@ -902,12 +899,12 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource: [NSString stringWithFormat:@"document.cookie = '%@';", realCookie] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; [self.pi_userContentController addUserScript:cookieScript]; - ///禁止缩放 + NSString *scaleJs = @"$('meta[name=description]').remove(); $('head').append( '' );"; WKUserScript *scaleScript = [[WKUserScript alloc] initWithSource:scaleJs injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO]; [self.pi_userContentController addUserScript:scaleScript]; - //根据生成的WKUserScript对象,初始化WKWebViewConfiguration + configuration.preferences.javaScriptEnabled = YES; configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES; configuration.preferences.minimumFontSize = 10; @@ -918,9 +915,9 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; _webview = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, size.width,size.height) configuration:configuration]; _webview.navigationDelegate = self; - //添加KVO,WKWebView有一个属性estimatedProgress,就是当前网页加载的进度,所以监听这个属性 + [_webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; - //添加KVO,监听title属性 + [_webview addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL]; UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(backButtonClick)]; @@ -929,7 +926,7 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; [_webview.scrollView setShowsVerticalScrollIndicator:NO]; [_webview.scrollView setShowsHorizontalScrollIndicator:NO]; - //set useragent + __weak typeof(self) weakSelf = self; [_webview evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) { NSString *userAgent = result; @@ -959,52 +956,52 @@ NSString * const kJSShowShareCallBack = @"showShareAction"; - (WKUserContentController *)pi_userContentController{ if (!_pi_userContentController) { - //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题 + WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self]; _pi_userContentController = [[WKUserContentController alloc] init]; - // 分享面板 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenSharePage]; - // 钱包页面 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPurse]; - // 充值页面 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenChargePage]; [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSChargePayPage]; [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSChargePayClickPage]; - // 获取uid + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetUid]; - // 获取设备id + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetDeviceId]; - // 获取Ticket + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetTicket]; - // 获取设备info + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetDeviceInfo]; - // 实人认证: 打开原生人脸认证 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenFaceLiveness]; - // 分享按钮 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSInitNav]; - // 获取房间uid + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetRoomUid]; - // 进入个人主页 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kOpenPersonPage]; - // 隐藏导航栏 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kInitShowNav]; - // 隐藏导航栏 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kCloseWebView]; - //装扮及其他活动页面 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJumpAppointPage]; - //进入房间 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenRoom]; - //进房并弹出礼物面板 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenRoomForGiftId]; - ///进入聊天 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenChatPage]; - ///进入聊天并关注 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenAppConcernedChat]; - ///分享及保存 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSSavePictureShare]; - ///兑换金币 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGoToExchangeGold]; - ///周卡内购 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPayment]; [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPaymentCallback]; [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSVerifyCaptchaCallBack]; diff --git a/YuMi/Modules/YMWeb/XPWebViewController.m.backup b/YuMi/Modules/YMWeb/XPWebViewController.m.backup new file mode 100644 index 0000000..a708a43 --- /dev/null +++ b/YuMi/Modules/YMWeb/XPWebViewController.m.backup @@ -0,0 +1,1032 @@ +// +// XPWebViewController.m +// YuMi +// +// Created by zu on 2021/9/16. +// + +#import "XPWebViewController.h" +#import "AccountInfoStorage.h" +#import "DJDKMIMOMColor.h" +#import "YUMIMacroUitls.h" +#import "YYUtility.h" +#import "HttpRequestHelper.h" +#import "XPShareView.h" +#import "TTPopup.h" +#import +#import +#import "XCCurrentVCStackManager.h" +#import "XPMineUserInfoViewController.h" +#import "ShareHelder.h" +#import "Api+Mine.h" +#import "YuMi-swift.h" +#import "RechargeStorage.h" + +///vc +#import "MyDressingViewController.h" +#import "ShoppingMallViewController.h" +#import "XPRoomViewController.h" +#import "RoomHostDelegate.h" +#import "WalletInfoModel.h" +#import "Api+Mine.h" +#import "XPSkillCardPlayerManager.h" +#import "XPWebViewNavView.h" +#import "XPIAPRechargeViewController.h" +#import "SessionViewController.h" +#import "XPMomentTopicContainerViewController.h" +#import "XPIncomeRecordVC.h" + +#import "PIWebViewSavePhotoView.h" +#import "IAPManager.h" + +typedef NS_ENUM(NSUInteger, RightNavigationPushType){ + ///跳转h5页面 + RightNavigationPushType_Web = 1, + ///分享 + RightNavigationPushType_Share = 2, + ///跳转原生页面 + RightNavigationPushType_AppPage = 3, + ///分享图片 + RightNavigationPushType_SharePicture = 5 +}; + +@interface WeakWebViewScriptMessageDelegate : NSObject + +//WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法 +@property (nonatomic, weak) id scriptDelegate; + +- (instancetype)initWithDelegate:(id)scriptDelegate; + +@end +@implementation WeakWebViewScriptMessageDelegate + +- (instancetype)initWithDelegate:(id)scriptDelegate { + self = [super init]; + if (self) { + _scriptDelegate = scriptDelegate; + } + return self; +} + +//遵循WKScriptMessageHandler协议,必须实现如下方法,然后把方法向外传递 +//通过接收JS传出消息的name进行捕捉的回调方法 +- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { + + if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) { + [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message]; + } +} + +@end + +@interface XPWebViewController () +@property (nonatomic,strong) WalletInfoModel *model ; +//@property (strong, nonatomic) WKWebView *webview; +@property (strong, nonatomic) UIProgressView *progressView; +@property (nonatomic, strong) WKUserContentController *pi_userContentController; +///分享的内容 +@property (nonatomic,copy) NSDictionary *shareDic; +///分享的内容 +@property (nonatomic,copy) NSDictionary *savePhotoDic; + +/// +@property (nonatomic,strong) XPWebViewNavView *navView; +/// +@property (nonatomic,assign) BOOL isCustom; +@property(nonatomic,strong) PIWebViewSavePhotoView *saveView; + +/// 订单编号 +@property (nonatomic,copy) NSString *orderId; + +@property (nonatomic, assign) BOOL isHideNavBar; + +@end + +NSString * const kJSOpenPurse = @"openPurse"; +NSString * const kJSOpenChargePage = @"openChargePage"; +NSString * const kJSChargePayPage = @"chargePayPage"; +NSString * const kJSChargePayClickPage = @"chargePayClickPage"; +NSString * const kJSOpenSharePage = @"openSharePage"; +NSString * const kJSGetUid = @"getUid"; +NSString * const kJSGetDeviceId = @"getDeviceId"; +NSString * const kJSGetTicket = @"getTicket"; +NSString * const kJSGetDeviceInfo = @"getDeviceInfo"; +NSString * const kJSOpenFaceLiveness = @"openFaceLiveness"; +NSString * const kJSInitNav = @"initNav"; +NSString * const kJSGetRoomUid = @"getRoomUid"; +NSString * const kOpenPersonPage = @"openPersonPage"; +NSString * const kInitShowNav = @"initShowNav"; +NSString * const kCloseWebView = @"closeWebView"; +NSString * const kJumpAppointPage = @"jumpAppointPage"; +NSString * const kJSOpenRoom = @"openRoom"; +NSString * const kJSOpenRoomForGiftId = @"openRoomForGiftId"; +NSString * const kJSOpenChatPage = @"geToChatPage"; +NSString * const kJSOpenAppConcernedChat = @"openAppConcernedChat"; +NSString * const kJSSavePictureShare = @"savePictureShare"; +NSString * const kJSGoToExchangeGold = @"goToExchangeGold"; +NSString * const kJSOpenPayment = @"openPayment"; +NSString * const kJSOpenPaymentCallback = @"openPaymentCallback"; +NSString * const kJSVerifyCaptchaCallBack = @"closeToVerify"; +NSString * const kJSShowShareCallBack = @"showShareAction"; + + +@implementation XPWebViewController + +- (instancetype)initWithCustomizeNav:(BOOL)isCustom +{ + self = [super init]; + if (self) { + self.isCustom = isCustom; + } + return self; +} + +- (instancetype)initWithRoomUID:(NSString * _Nullable)roomUid { + self = [super init]; + if (self) { + self.roomUid = roomUid; + self.isLoginStatus = YES; + } + return self; +} + +-(void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + + if([XPSkillCardPlayerManager shareInstance].isInRoom == YES && self.isProperty == NO && [XPSkillCardPlayerManager shareInstance].isInRoomFirstRecharge == NO){ + [XPSkillCardPlayerManager shareInstance].isInRoomFirstRecharge = YES; + } + + if (self.isHideNavBar) { + if (self.navigationController) { + [self.navigationController setNavigationBarHidden:YES]; + } + } +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self.view addSubview:self.saveView]; + self.saveView.hidden = YES; + [self initView]; +} + +- (void)saveImageToPhotoAlbum:(NSDictionary *)data{ + if (data.allKeys.count == 0){ + [self showSuccessToast:YMLocalizedString(@"PIWebViewSavePhotoView3")]; + return; + } + + NSString *qrCodeUrl = data[@"qrCodeUrl"]; + if (qrCodeUrl.length == 0){ + [self showSuccessToast:YMLocalizedString(@"PIWebViewSavePhotoView3")]; + return; + } + [self showLoading]; + NetImageView *imageView = [NetImageView new]; + @kWeakify(self); + [imageView loadImageWithUrl:qrCodeUrl completion:^(UIImage * _Nonnull image, NSURL * _Nonnull url) { + @kStrongify(self); + [self hideHUD]; + if (image != nil){ + self.saveView.hidden = NO; + NSString *text = data[@"text"]; + NSString *invitationCode = data[@"invitationCode"]; + self.saveView.text = text; + self.saveView.image = image; + self.saveView.code = invitationCode; + UIImage *saveImage = [UIImage getImageFromView:self.saveView]; + UIImageWriteToSavedPhotosAlbum(saveImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL); + return; + } + [self showSuccessToast:YMLocalizedString(@"PIWebViewSavePhotoView3")]; + }]; +} + +//指定回调方法 +- (void)image: (UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ + self.saveView.hidden = YES; + NSString *msg = YMLocalizedString(@"PIWebViewSavePhotoView2"); + if(error != NULL){ + msg = YMLocalizedString(@"PIWebViewSavePhotoView3"); + } + [self showSuccessToast:msg]; + + +} +- (void)initView { + if (self.navigationController.viewControllers.count > 1){ + UIBarButtonItem *leftBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[[UIImage imageNamed:@"common_nav_back"]ms_SetImageForRTL] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonClick)]; + + leftBarButtonItem.tintColor = [DJDKMIMOMColor mainTextColor]; + + self.navigationItem.leftBarButtonItem = leftBarButtonItem; + } + + self.webview.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + + if(self.isCustom == YES){ + [self.view addSubview:self.navView]; + [self.view addSubview:self.webview]; + [self.view addSubview:self.progressView]; + [self.navView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.equalTo(self.view); + make.height.mas_equalTo(kNavigationHeight); + }]; + [self.webview mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.bottom.equalTo(self.view); + make.top.equalTo(self.navView.mas_bottom); + }]; + [self.progressView mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.equalTo(self.view); + make.height.mas_equalTo(1); + make.top.equalTo(self.navView.mas_bottom); + }]; + }else{ + [self.view addSubview:self.webview]; + [self.view addSubview:self.progressView]; + [self.webview mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.top.bottom.mas_equalTo(self.view); + }]; + } + + if (self.isLoginStatus) { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + @kWeakify(self); + [Api getUserWalletInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + @kStrongify(self); + if(code == 200){ + WalletInfoModel * model = [WalletInfoModel modelWithDictionary:data.data]; + self.model = model; + } + } uid:uid ticket:ticket]; + } +} +- (void)xPWebViewNavView:(XPWebViewNavView *)view didClickBack:(UIButton *)sender{ + if(self.is_Pi_FairyPay){ + [self willMoveToParentViewController:nil]; //1 + [self.view removeFromSuperview]; //2 + [self removeFromParentViewController]; //3 + return; + } + if(self.isFairyPay){ + if(self.CloseWebViewBlock){ + self.CloseWebViewBlock(YES); + } + return; + } + [self dismissViewControllerAnimated:YES completion:nil]; +} +//加载完成 +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + //加载完成后隐藏progressView + self.progressView.hidden = YES; + if (self.urlLoadCompleted) { + self.urlLoadCompleted(YES, nil); + } +#if DEBUG + NSString *fileName = @"vconsole.min.js"; // 你要查找的文件名 + NSString *directory = [[NSBundle mainBundle] resourcePath]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:directory]; + NSString *filePath; + + for (NSString *path in enumerator) { + if ([[path lastPathComponent] containsString:fileName]) { + filePath = [directory stringByAppendingPathComponent:path]; + break; + } + } + + if (filePath.length > 0) { + NSString *vConsoleScript = [NSString stringWithContentsOfFile:filePath + encoding:NSUTF8StringEncoding error:nil]; + [webView evaluateJavaScript:vConsoleScript completionHandler:nil]; + + // 初始化 vConsole + NSString *initVConsoleScript = @"var vConsole = new VConsole();"; + [webView evaluateJavaScript:initVConsoleScript completionHandler:nil]; + } +#endif +} + +#if DEBUG +- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse + decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { + + NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; + NSDictionary *headers = response.allHeaderFields; + // NSLog(@"Response Headers: %@", headers); + + NSString *contentEncoding = headers[@"Content-Encoding"]; + if ([contentEncoding isEqualToString:@"gzip"]) { + // NSLog(@"✅ Gzip 响应已启用"); + } else { + // NSLog(@"❌ Gzip 响应未启用"); + } + + decisionHandler(WKNavigationResponsePolicyAllow); +} +#endif + +//加载失败 +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { + //加载失败同样需要隐藏progressView + self.progressView.hidden = YES; + if (self.urlLoadCompleted) { + self.urlLoadCompleted(NO, error); + } +} + +//捕抓打电话事件 +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + NSURL *URL = navigationAction.request.URL; + NSString *scheme = [URL scheme]; + NSURLRequest *request = navigationAction.request; + // Judge is whether to jump to other app. + if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) { + BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:request.URL]; + if (canOpen) { + [[UIApplication sharedApplication] openURL:request.URL options:@{} completionHandler:^(BOOL success) { + + }]; + } + decisionHandler(WKNavigationActionPolicyCancel); + return; + } + decisionHandler(WKNavigationActionPolicyAllow); +} +- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{ + if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; + completionHandler(NSURLSessionAuthChallengeUseCredential,card); + }); + } +} +- (void)userContentController:(WKUserContentController *)userContentController + didReceiveScriptMessage:(WKScriptMessage *)message { + [self.webview evaluateJavaScript:@"document.location.href" + completionHandler:^(id _Nullable response, NSError * _Nullable error) { + NSString *currentUrl = [NSString stringWithFormat:@"%@", response]; + ///测试环境只要有host就执行,方便h5连接本地调试 + BOOL condition = currentUrl != nil && [currentUrl containsString:API_HOST_URL]; + + NSLog(@"-- -- - -- - - | -- -- - -- - -%@", response); + NSLog(@"-- -- - -- - -%@: %@", message.name, message.body); +#ifdef DEBUG + condition = currentUrl != nil; +#endif + if(condition) { + if ([message.name isEqualToString:kJSOpenSharePage]) { + if (message.body && message.body != [NSNull null]) { + NSDictionary *body; + //不知道是哪个蓝精灵弄的,变成了个dic,所以我们要判断类型 + if ([message.body isKindOfClass:[NSDictionary class]]) { + body = message.body; + } else if ([message.body isKindOfClass:[NSString class]]) { + body = [message.body toJSONObject]; + } + self.shareDic = body[@"data"]; + [self showSharePanel]; + } + } else if ([message.name isEqualToString:kJSGetUid]) { + NSString *uid = [[AccountInfoStorage instance] getUid]; + NSString *js = [NSString stringWithFormat:@"getMessage(\"uid\",%@)", uid]; + [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { + // NSLog(@"%@",error); + }]; + } else if ([message.name isEqualToString:kJSGetTicket]) { + NSString *ticket = [[AccountInfoStorage instance] getTicket]; + NSString *js = [NSString stringWithFormat:@"getMessage(\"ticket\",\"%@\")",ticket]; + [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { + // NSLog(@"%@",error); + }]; + } else if ([message.name isEqualToString:kJSGetDeviceId]) { + NSString *js = [NSString stringWithFormat:@"getMessage(\"deviceId\",\"%@\")",[YYUtility deviceUniqueIdentification]]; + [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { + // NSLog(@"%@",error); + }]; + } else if ([message.name isEqualToString:kJSGetDeviceInfo]) { + NSDictionary *basicParmars = [HttpRequestHelper configBaseParmars:[[NSDictionary alloc] init]]; + NSString *json = [basicParmars mj_JSONString]; + NSString *js = [NSString stringWithFormat:@"getMessage(\"deviceInfo\",%@)", json]; + [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable ohter, NSError * _Nullable error) { + // NSLog(@"%@", error); + }]; + } else if ([message.name isEqualToString:kJSOpenPurse]) { + + }else if([message.name isEqualToString:kJSChargePayPage]){ + // NSString *money = [NSString stringWithFormat:@"%@",message.body] ; + + }else if([message.name isEqualToString:kJSChargePayClickPage]){ + if(message.body != nil && self.model.diamonds != nil){ + // NSString *type = [NSString stringWithFormat:@"%@",message.body]; + } + }else if ([message.name isEqualToString:kJSOpenChargePage]) { + if(self.delegate && [self.delegate respondsToSelector:@selector(payHandler)]){ + [self.delegate payHandler]; + return; + } + [TTPopup dismiss]; + if(self.isPush){ + XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; + webVC.type = @"4"; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:webVC animated:YES]; + return; + } + UIViewController *controller = [XCCurrentVCStackManager shareManager].getCurrentVC; + if (controller.presentingViewController) { + [controller dismissViewControllerAnimated:NO completion:nil]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; + webVC.type = @"4"; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:webVC animated:YES]; + }); + }else { + XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; + webVC.type = @"4"; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:webVC animated:YES]; + } + + if (self.didTapCharge) { + self.didTapCharge(); + } + + } else if ([message.name isEqualToString:kOpenPersonPage]) { + NSString *uid = [NSString stringWithFormat:@"%@",message.body]; + if (uid.integerValue > 0) { + [TTPopup dismiss]; + XPMineUserInfoViewController * userInfoVC = [[XPMineUserInfoViewController alloc] init]; + userInfoVC.uid = uid.integerValue; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:userInfoVC animated:YES]; + } + } else if([message.name isEqualToString:kJSInitNav]) { + [self initNav:message.body]; + } else if([message.name isEqualToString:kJSGetRoomUid]) { + NSString *js = [NSString stringWithFormat:@"getMessage(\"roomUid\",\"%@\")",self.roomUid]; + [self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) { + // NSLog(@"%@",error); + }]; + } else if([message.name isEqualToString:kInitShowNav]) { + if (((NSNumber *)message.body).intValue == 0) { + if (self.InitShowNavBlock) { + self.InitShowNavBlock(YES); + return; + } + self.isHideNavBar = YES; + if (self.navigationController) { + [self.navigationController setNavigationBarHidden:YES]; + } + } + } else if([message.name isEqualToString:kCloseWebView]) { + if (self.CloseWebViewBlock) { + self.CloseWebViewBlock(YES); + return; + } + if (self.navigationController) { + [self.navigationController popViewControllerAnimated:YES]; + } + } else if ([message.name isEqualToString:kJumpAppointPage]) { + // h5与原生交互新协议 + NSDictionary *bodyDict; + if ([message.body isKindOfClass:[NSDictionary class]]) { + bodyDict = message.body; + } else if ([message.body isKindOfClass:[NSString class]]) { + NSString *str = (NSString *)message.body; + bodyDict = [str toJSONObject]; + } + NSInteger skyType = [bodyDict[@"routerType"] integerValue]; + [self handleRouterType:skyType message:message]; + }else if ([message.name isEqualToString:kJSOpenChatPage]){ + NSString *uid = [NSString stringWithFormat:@"%@",message.body]; + if (uid.length > 0) { + NIMSession * session = [NIMSession session:uid type:NIMSessionTypeP2P]; + SessionViewController * sessionVC = [[SessionViewController alloc] initWithSession:session]; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:sessionVC animated:YES]; + } + }else if([message.name isEqualToString:kJSOpenAppConcernedChat]){ + NSString *uid = [NSString stringWithFormat:@"%@",message.body]; + if (uid.length > 0) { + NIMSession * session = [NIMSession session:uid type:NIMSessionTypeP2P]; + SessionViewController * sessionVC = [[SessionViewController alloc] initWithSession:session]; + sessionVC.isAttention = YES; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:sessionVC animated:YES]; + } + }else if ([message.name isEqualToString:kJSOpenRoom]) { + NSString *uid = [NSString stringWithFormat:@"%@",message.body]; + if (uid.length > 0) { + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController.viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[XPRoomViewController class]]) { + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController popToRootViewControllerAnimated:NO]; + XPRoomViewController * rooomVC = obj; + [rooomVC exitRoom]; + *stop = YES; + } + }]; + if(self.view.superview){ + [TTPopup dismiss]; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [XPRoomViewController openRoom:uid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; + }); + } + } else if([message.name isEqualToString:kJSOpenRoomForGiftId]) { + // NSLog(@"%@", message.body); + NSDictionary *bodyDict; + if ([message.body isKindOfClass:[NSDictionary class]]) { + bodyDict = message.body; + } else if ([message.body isKindOfClass:[NSString class]]) { + NSString *str = (NSString *)message.body; + bodyDict = [str toJSONObject]; + } + //房间页 传参:uid + NSString *uid = [NSString stringWithFormat:@"%@", bodyDict[@"uid"]]; + NSString *giftId = [NSString stringWithFormat:@"%@", bodyDict[@"giftId"]]; + if (uid.length) { + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController.viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[XPRoomViewController class]]) { + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController popToRootViewControllerAnimated:NO]; + XPRoomViewController * roomVC = obj; + [roomVC exitRoom]; + *stop = YES; + } + }]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [XPRoomViewController openRoom:uid giftId:giftId viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; + }); + } + }else if ([message.name isEqualToString:kJSSavePictureShare]){ + NSDictionary *bodyDic; + if ([message.body isKindOfClass:[NSDictionary class]]) { + bodyDic = message.body; + } else if ([message.body isKindOfClass:[NSString class]]) { + bodyDic = [message.body toJSONObject]; + } + NSString *type = [NSString stringWithFormat:@"%@",bodyDic[@"type"]]; + if ([type isEqualToString:@"2"]){ + [self saveImageToPhotoAlbum:bodyDic]; + }else if ([type isEqualToString:@"1"]){ + self.savePhotoDic = bodyDic; + [self showShareSavePhote]; + } + } else if([message.name isEqualToString:kJSGoToExchangeGold]){ + XPIncomeRecordVC *incomeRecordVC = [XPIncomeRecordVC new]; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:incomeRecordVC animated:YES]; + } else if([message.name isEqualToString:kJSOpenPayment]) { + [self handleOpenPayment:message.body]; + } else if([message.name isEqualToString:kJSVerifyCaptchaCallBack]) { + [self handleCaptchaResult:[message.body integerValue] == 1]; + } else if([message.name isEqualToString:kJSShowShareCallBack]) { + [self handleShareActioin:message.body]; + } + } + }]; +} + +#pragma mark - +- (void)handleShareActioin:(NSString *)content { + [ShareHelder shareImage:kImage(@"share_icon") + url:[NSString isEmpty:content] ? self.url : content + fromController:[XCCurrentVCStackManager shareManager].getCurrentVC]; +} + +- (void)handleCaptchaResult:(BOOL)reuslt { + if (_verifyCaptcha) { + self.verifyCaptcha(reuslt); + } +} + +#pragma mark - Payment Method +- (void)handleOpenPayment:(NSString *)chargeProdId { + if (chargeProdId.length == 0) { + [self showErrorToast:@"no charge ID"]; + return; + } + + [self showLoading]; + + @kWeakify(self); + [[IAPManager sharedManager] purchase:chargeProdId + success:^(NSString *transactionID, NSString *orderID){ + @kStrongify(self); + [self hideHUD]; + [self triggerOpenPaymentCallback:200 + orderID:self.orderId + productID:transactionID]; + } failure:^(NSError * _Nonnull error) { + @kStrongify(self); + [self hideHUD]; + if (error) { + [self showErrorToast:error.domain]; + } + } contactCS:^(NSString * _Nonnull uid) { + @kStrongify(self); + [self hideHUD]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + NIMSession * session = [NIMSession session:uid type:NIMSessionTypeP2P]; + SessionViewController * sessionVC = [[SessionViewController alloc] initWithSession:session]; + [self.navigationController pushViewController:sessionVC animated:YES]; + }); + }]; +} + +- (void)triggerOpenPaymentCallback:(NSInteger)code + orderID:(NSString *)orderID + productID:(NSString *)productID { + NSDictionary *dic = @{@"code":@(code), @"orderId":orderID, @"productId":productID}; + NSString *js = [NSString stringWithFormat:@"openPaymentCallback(%@)", dic.toJSONString]; + @kWeakify(self); + [self.webview evaluateJavaScript:js + completionHandler:^(id _Nullable result, NSError * _Nullable error) { + @kStrongify(self); + [self hideHUD]; + }]; +} + +#pragma mark - private method +- (void)handleRouterType:(NSInteger)skyType message:(WKScriptMessage *)message { + NSDictionary *bodyDict = (NSDictionary *)message.body; + switch (skyType) { + case 1: + { + //房间页 传参:uid + NSString *uid = [NSString stringWithFormat:@"%@", bodyDict[@"routerVal"]]; + if (uid.length) { + [XPRoomViewController openRoom:uid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; + } + } + break; + case 7: + { + //座驾 + MyDressingViewController *vc = [[MyDressingViewController alloc] init]; +// vc.currentIndex = 1; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:vc animated:YES]; + } + break; + case 8: + { + //头饰 + MyDressingViewController *vc = [[MyDressingViewController alloc] init]; +// vc.currentIndex = 0; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:vc animated:YES]; + } + break; + case 75: + {//跳转对应的话题 + bodyDict = [bodyDict toJSONObject]; + NSString *topicId = bodyDict[@"routerVal"]; + XPMomentTopicContainerViewController * topicVC = [[XPMomentTopicContainerViewController alloc] init]; + topicVC.worldId = topicId; + [[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:topicVC animated:YES]; + } + break; + default: + break; + } +} +- (void)setUrl:(NSString *)urlString{ + _url = urlString; + if (_url == nil) { + return; + } + if (![_url hasPrefix:@"http"] && ![_url hasPrefix:@"https"]){ + _url = [NSString stringWithFormat:@"%@/%@", [HttpRequestHelper getHostUrl], _url]; + } + + if (![_url containsString:@"?"]) { + _url = [NSString stringWithFormat:@"%@", _url]; + } else { + _url = [NSString stringWithFormat:@"%@", _url]; + } + + // 去掉 urlString 中的空格。 + NSString *noSpaceTextUrl = [_url stringByReplacingOccurrencesOfString:@" " withString:@""]; + + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:noSpaceTextUrl]]; + [self.webview loadRequest:request]; +} +- (void)backButtonClick { + BOOL canGoBack = YES; + if (self.webview.backForwardList.backList.count <= 1) { + canGoBack = NO; + } + + if ([self.webview canGoBack]) { + [self.webview goBack]; + } else { + [self.navigationController popViewControllerAnimated:YES]; + [self.pi_userContentController removeAllUserScripts]; + } +} +#pragma mark - 分享 +- (void)initNav:(NSDictionary *)response{ + if(!response || ![response isKindOfClass:[NSDictionary class]])return; + self.shareDic = response[@"data"]; + if ([response[@"type"] intValue]== RightNavigationPushType_Web) { + [self addNavigationItemWithTitles:@[response[@"data"][@"title"]] titleColor:[DJDKMIMOMColor alertTitleColor] isLeft:NO target:self action:@selector(gotoWebView) tags:nil]; + }else if ([response[@"type"] intValue]== RightNavigationPushType_Share || [response[@"type"] intValue]== RightNavigationPushType_SharePicture){ + [self addNavigationItemWithImageNames:@[@"family_person_share"] isLeft:NO + target:self action:@selector(showSharePanel) tags:nil]; + } +} + +- (void)gotoWebView { + if (self.shareDic[@"link"]) { + XPWebViewController * webVC = [[XPWebViewController alloc] init]; + webVC.url = self.shareDic[@"link"]; + [self.navigationController pushViewController:webVC animated:YES]; + } +} +-(void)showShareSavePhote{ + if (self.savePhotoDic.allKeys.count <= 0) { + return; + } + NSDictionary * dic = self.savePhotoDic; + XPShareInfoModel * shareInfo = [[XPShareInfoModel alloc] init]; + shareInfo.shareContent = dic[@"shareText"]; + shareInfo.type = ShareType_H5; + shareInfo.uid = [AccountInfoStorage instance].getUid; + NSString *urlStr = ((NSString *)dic[@"toUrl"]).length > 0 ? dic[@"toUrl"] : @""; + NSString *title = ((NSString *)dic[@"shareTitle"]).length > 0 ? dic[@"shareTitle"] : @""; + NSString *shareText = ((NSString *)dic[@"shareText"]).length > 0 ? dic[@"shareText"] : @""; + NSString *shareImg = ((NSString *)dic[@"shareImg"]).length > 0 ? dic[@"shareImg"] : @""; + shareInfo.shareUrl = [NSString stringWithFormat:@"%@&image=%@&title=%@&subTitle=%@",urlStr,shareImg,title,shareText]; + XPShareItem *cycle = [XPShareItem itemWitTag:XPShareItemTagFaceBook title:@"FaceBook" imageName:@"share_fb" disableImageName:@"share_fb"]; + XPShareItem *wechat = [XPShareItem itemWitTag:XPShareItemTagLine title:@"Line" imageName:@"share_line" disableImageName:@"share_line"]; + wechat.isShareInvite = YES; + wechat.inviteTitle = title; + XPShareItem *qq = [XPShareItem itemWitTag:XPShareItemTagCopyLink title:YMLocalizedString(@"XPWebViewNavView1") imageName:@"share_copy_link" disableImageName:@"share_copy_link"]; + XPShareItem *save = [XPShareItem itemWitTag:XPShareItemTagAppSaveAlbum title:YMLocalizedString(@"PIWebViewSavePhotoView4") imageName:@"share_save_icon" disableImageName:@"share_save_icon"]; + + NSArray * items = @[wechat,cycle, qq,save]; + CGFloat margin = 15; + CGSize itemSize = CGSizeMake((KScreenWidth-2*margin)/4, 65); + XPShareView *shareView = [[XPShareView alloc] initWithItems:items itemSize:itemSize shareInfo:shareInfo]; + shareView.delegate = self; + + [TTPopup popupView:shareView style:TTPopupStyleActionSheet]; + +} +- (void)showSharePanel { + if (self.shareDic.allKeys.count <= 0) { + return; + } + NSDictionary * dic = self.shareDic; + XPShareInfoModel * shareInfo = [[XPShareInfoModel alloc] init]; + shareInfo.shareTitle = self.shareDic[@"title"]; + shareInfo.shareContent = dic[@"desc"]; + shareInfo.shareImageUrl = dic[@"imgUrl"]; + shareInfo.type = ShareType_H5; + shareInfo.uid = [AccountInfoStorage instance].getUid; + NSString *urlStr = ((NSString *)dic[@"url"]).length > 0 ? dic[@"url"] : dic[@"showUrl"]; + if (urlStr.length) { + if ([urlStr containsString:@"?"]) { + urlStr = [NSString stringWithFormat:@"%@&shareUid=%@",urlStr,[AccountInfoStorage instance].getUid]; + } else { + urlStr = [NSString stringWithFormat:@"%@?shareUid=%@",urlStr,[AccountInfoStorage instance].getUid]; + } + } + shareInfo.shareUrl = urlStr; + XPShareItem *cycle = [XPShareItem itemWitTag:XPShareItemTagFaceBook title:@"FaceBook" imageName:@"share_fb" disableImageName:@"share_fb"]; + XPShareItem *wechat = [XPShareItem itemWitTag:XPShareItemTagLine title:@"Line" imageName:@"share_line" disableImageName:@"share_line"]; + XPShareItem *qq = [XPShareItem itemWitTag:XPShareItemTagCopyLink title:YMLocalizedString(@"XPWebViewNavView1") imageName:@"share_copy_link" disableImageName:@"share_copy_link"]; + XPShareItem *save = [XPShareItem itemWitTag:XPShareItemTagAppSaveAlbum title:YMLocalizedString(@"PIWebViewSavePhotoView4") imageName:@"share_save_icon" disableImageName:@"share_save_icon"]; + + NSArray * items = @[wechat,cycle, qq,save]; + CGFloat margin = 15; + CGSize itemSize = CGSizeMake((KScreenWidth-2*margin)/4, 65); + XPShareView *shareView = [[XPShareView alloc] initWithItems:items itemSize:itemSize shareInfo:shareInfo]; + shareView.delegate = self; + + [TTPopup popupView:shareView style:TTPopupStyleActionSheet]; +} + +#pragma mark - XCShareViewDelegate +- (void)shareView:(XPShareView *)shareView savePhoto:(XPShareInfoModel *)shareInfo{ + [self saveImageToPhotoAlbum:self.savePhotoDic]; +} +- (void)shareViewDidClickCancle:(XPShareView *)shareView { + [TTPopup dismiss]; +} +- (void)shareView:(XPShareView *)shareView didSuccess:(XPShareInfoModel *)shareInfo { + [TTPopup dismiss]; + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + NSString *uid = [AccountInfoStorage instance].getUid; + NSString *ticket = [AccountInfoStorage instance].getTicket; + [params setObject:uid forKey:@"uid"]; + + // 添加类型安全检查,防止NSTaggedPointerString错误 + if ([shareInfo isKindOfClass:[XPShareInfoModel class]]) { + [params setObject:@(shareInfo.shareType) forKey:@"shareType"]; + } else { + // 如果不是预期类型,提供默认值 + [params setObject:@(0) forKey:@"shareType"]; + NSLog(@"警告:shareInfo不是XPShareInfoModel类型,而是%@类型", NSStringFromClass([shareInfo class])); + } + + [params setObject:ticket forKey:@"ticket"]; + if ([shareInfo isKindOfClass:[XPShareInfoModel class]]) { + [params setObject:@(shareInfo.type) forKey:@"sharePageId"]; + if (shareInfo.shareUrl.length > 0) { + [params setObject:shareInfo.shareUrl forKey:@"shareUrl"]; + } + if (shareInfo.roomUid > 0) { + [params setObject:@(shareInfo.roomUid) forKey:@"targetUid"]; + } + } + + [HttpRequestHelper POST:@"usershare/save" params:params success:^(BaseModel * _Nonnull data) { + + } failure:^(NSInteger resCode, NSString * _Nonnull message) { + + }]; +} + +- (void)shareView:(XPShareView *)shareView shareFail:(NSString *)message { + [TTPopup dismiss]; + [self showErrorToast:message]; +} + +- (void)shareViewDidClickCancel:(XPShareView *)shareView { + [TTPopup dismiss]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqualToString:@"estimatedProgress"]) { + self.progressView.progress = self.webview.estimatedProgress; + if (self.progressView.progress == 1) { + __weak typeof (self)weakSelf = self; + [UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{ + weakSelf.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.0f); + } completion:^(BOOL finished) { + weakSelf.progressView.hidden = YES; + }]; + } + } else if ([keyPath isEqualToString:@"title"]) { + if (object == self.webview) { + self.navigationItem.title = self.webview.title; + if (self.urlLoadCompleted) {//半屏webview如果在加载完成回调后标题还会改变,在此处重新设置一遍 + self.urlLoadCompleted(YES, nil); + } + }else{ + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +- (void)dealloc { + [self.webview removeObserver:self forKeyPath:@"estimatedProgress"]; + [self.webview removeObserver:self forKeyPath:@"title"]; +} + +- (WKWebView *)webview { + if (_webview == nil) { + WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init]; + + if (@available(iOS 10.0, *)) { + configuration.mediaTypesRequiringUserActionForPlayback = NO; + } else { + // Fallback on earlier versions + } + configuration.allowsInlineMediaPlayback = YES; + + NSString *uid = [[AccountInfoStorage instance] getUid]; + NSString *realCookie = [NSString stringWithFormat:@"%@=%@",@"uid",uid]; + + WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource: [NSString stringWithFormat:@"document.cookie = '%@';", realCookie] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; + [self.pi_userContentController addUserScript:cookieScript]; + ///禁止缩放 + NSString *scaleJs = @"$('meta[name=description]').remove(); $('head').append( '' );"; + WKUserScript *scaleScript = [[WKUserScript alloc] initWithSource:scaleJs injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO]; + [self.pi_userContentController addUserScript:scaleScript]; + + //根据生成的WKUserScript对象,初始化WKWebViewConfiguration + configuration.preferences.javaScriptEnabled = YES; + configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES; + configuration.preferences.minimumFontSize = 10; + configuration.selectionGranularity = WKSelectionGranularityCharacter; + configuration.userContentController = self.pi_userContentController; + + CGSize size = [UIScreen mainScreen].bounds.size; + _webview = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, size.width,size.height) configuration:configuration]; + + _webview.navigationDelegate = self; + //添加KVO,WKWebView有一个属性estimatedProgress,就是当前网页加载的进度,所以监听这个属性 + [_webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; + //添加KVO,监听title属性 + [_webview addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL]; + + UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(backButtonClick)]; + [_webview addGestureRecognizer:swipeGesture]; + + [_webview.scrollView setShowsVerticalScrollIndicator:NO]; + [_webview.scrollView setShowsHorizontalScrollIndicator:NO]; + + //set useragent + __weak typeof(self) weakSelf = self; + [_webview evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) { + NSString *userAgent = result; + + if (![userAgent containsString:@"molistarAppIos erbanAppIos"]){ + NSString *newUserAgent = [userAgent stringByAppendingString:@" molistarAppIos erbanAppIos"]; + NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil]; + [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary]; + [[NSUserDefaults standardUserDefaults] synchronize]; + [weakSelf.webview setCustomUserAgent:newUserAgent]; + } + + }]; + _webview.scrollView.bounces = NO; + } + return _webview; +} +- (UIProgressView *)progressView{ + if (!_progressView) { + _progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 1)]; + _progressView.progressTintColor = [DJDKMIMOMColor appMainColor]; + _progressView.trackTintColor = [UIColor clearColor]; + _progressView.transform = CGAffineTransformMakeScale(1.0f, 1.0f); + } + return _progressView; +} + +- (WKUserContentController *)pi_userContentController{ + if (!_pi_userContentController) { + //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题 + WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self]; + _pi_userContentController = [[WKUserContentController alloc] init]; + // 分享面板 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenSharePage]; + // 钱包页面 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPurse]; + // 充值页面 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenChargePage]; + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSChargePayPage]; + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSChargePayClickPage]; + // 获取uid + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetUid]; + // 获取设备id + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetDeviceId]; + // 获取Ticket + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetTicket]; + // 获取设备info + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetDeviceInfo]; + // 实人认证: 打开原生人脸认证 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenFaceLiveness]; + // 分享按钮 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSInitNav]; + // 获取房间uid + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetRoomUid]; + // 进入个人主页 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kOpenPersonPage]; + // 隐藏导航栏 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kInitShowNav]; + // 隐藏导航栏 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kCloseWebView]; + //装扮及其他活动页面 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJumpAppointPage]; + //进入房间 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenRoom]; + //进房并弹出礼物面板 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenRoomForGiftId]; + ///进入聊天 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenChatPage]; + ///进入聊天并关注 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenAppConcernedChat]; + ///分享及保存 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSSavePictureShare]; + ///兑换金币 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGoToExchangeGold]; + ///周卡内购 + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPayment]; + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPaymentCallback]; + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSVerifyCaptchaCallBack]; + [_pi_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSShowShareCallBack]; + + } + return _pi_userContentController; + +} +-(XPWebViewNavView *)navView{ + if (!_navView){ + _navView = [[XPWebViewNavView alloc]initWithFrame:CGRectZero]; + _navView.delegate = self; + } + return _navView; +} +- (PIWebViewSavePhotoView *)saveView{ + if(!_saveView){ + _saveView = [[PIWebViewSavePhotoView alloc]initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)]; + } + return _saveView; +} + + +@end diff --git a/YuMi/Modules/YMWeb/XPWebViewNavView.h b/YuMi/Modules/YMWeb/XPWebViewNavView.h index f5af434..16684c2 100644 --- a/YuMi/Modules/YMWeb/XPWebViewNavView.h +++ b/YuMi/Modules/YMWeb/XPWebViewNavView.h @@ -1,20 +1,18 @@ -// -// XPWebViewNavView.h -// YuMi -// + + // Created by YuMi on 2023/2/27. -// + #import @class XPWebViewNavView; NS_ASSUME_NONNULL_BEGIN @protocol XPWebViewNavViewDelegate -//点击了返回 + - (void)xPWebViewNavView:(XPWebViewNavView *)view didClickBack:(UIButton *)sender; @end @interface XPWebViewNavView : UIView -/// + @property (nonatomic,weak) id delegate; @end diff --git a/YuMi/Modules/YMWeb/XPWebViewNavView.h.backup b/YuMi/Modules/YMWeb/XPWebViewNavView.h.backup new file mode 100644 index 0000000..f5af434 --- /dev/null +++ b/YuMi/Modules/YMWeb/XPWebViewNavView.h.backup @@ -0,0 +1,21 @@ +// +// XPWebViewNavView.h +// YuMi +// +// Created by YuMi on 2023/2/27. +// + +#import +@class XPWebViewNavView; +NS_ASSUME_NONNULL_BEGIN +@protocol XPWebViewNavViewDelegate +//点击了返回 +- (void)xPWebViewNavView:(XPWebViewNavView *)view didClickBack:(UIButton *)sender; + +@end +@interface XPWebViewNavView : UIView +/// +@property (nonatomic,weak) id delegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMWeb/XPWebViewNavView.m b/YuMi/Modules/YMWeb/XPWebViewNavView.m index 7f91bd1..4d47c9a 100644 --- a/YuMi/Modules/YMWeb/XPWebViewNavView.m +++ b/YuMi/Modules/YMWeb/XPWebViewNavView.m @@ -1,20 +1,18 @@ -// -// XPWebViewNavView.m -// YuMi -// + + // Created by YuMi on 2023/2/27. -// + #import "XPWebViewNavView.h" -///Third + #import #import "UIButton+EnlargeTouchArea.h" #import "DJDKMIMOMColor.h" #import "YUMIMacroUitls.h" @interface XPWebViewNavView() -///返回 + @property (nonatomic,strong) UIButton *backButton; -///标题 + @property (nonatomic,strong) UILabel *titleView; @end @implementation XPWebViewNavView diff --git a/YuMi/Modules/YMWeb/XPWebViewNavView.m.backup b/YuMi/Modules/YMWeb/XPWebViewNavView.m.backup new file mode 100644 index 0000000..7f91bd1 --- /dev/null +++ b/YuMi/Modules/YMWeb/XPWebViewNavView.m.backup @@ -0,0 +1,79 @@ +// +// XPWebViewNavView.m +// YuMi +// +// Created by YuMi on 2023/2/27. +// + +#import "XPWebViewNavView.h" +///Third +#import +#import "UIButton+EnlargeTouchArea.h" +#import "DJDKMIMOMColor.h" +#import "YUMIMacroUitls.h" +@interface XPWebViewNavView() +///返回 +@property (nonatomic,strong) UIButton *backButton; +///标题 +@property (nonatomic,strong) UILabel *titleView; +@end +@implementation XPWebViewNavView + +-(instancetype)initWithFrame:(CGRect)frame{ + self = [super initWithFrame:frame]; + if(self){ + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + [self addSubview:self.backButton]; + [self addSubview:self.titleView]; + +} +- (void)initSubViewConstraints { + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kGetScaleWidth(28)); + make.leading.mas_equalTo(0); + make.bottom.mas_equalTo(-kGetScaleWidth(8)); + }]; + [self.titleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.backButton); + make.centerX.equalTo(self); + }]; + +} +-(void)backButtonAction{ + if(self.delegate && [self.delegate respondsToSelector:@selector(xPWebViewNavView:didClickBack:)]){ + [self.delegate xPWebViewNavView:self didClickBack:self.backButton]; + } +} + +#pragma mark -懒加载 +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_backButton setImage:[[UIImage imageNamed:@"common_nav_back"]ms_SetImageForRTL] forState:UIControlStateNormal]; + [_backButton setImage:[[UIImage imageNamed:@"common_nav_back"]ms_SetImageForRTL] forState:UIControlStateSelected]; + [_backButton addTarget:self action:@selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside]; + [_backButton setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + } + return _backButton; +} + + +- (UILabel *)titleView { + if (!_titleView) { + _titleView = [[UILabel alloc] init]; + _titleView.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; + _titleView.textColor = UIColorFromRGB(0x1F1B4F); + _titleView.text = YMLocalizedString(@"XPWebViewNavView0"); + } + return _titleView; +} + + +@end diff --git a/YuMi/Network/HttpRequestHelper.h b/YuMi/Network/HttpRequestHelper.h index 9b63cac..156b347 100644 --- a/YuMi/Network/HttpRequestHelper.h +++ b/YuMi/Network/HttpRequestHelper.h @@ -1,9 +1,7 @@ -// -// HttpRequestHelper.h -// YUMI -// + + // Created by zu on 2021/9/3. -// + #import #import "BaseModel.h" @@ -51,10 +49,6 @@ success:(void (^)(BaseModel *data))success completion:(HttpRequestHelperCompletion)completion; -/// 增加或编辑技能卡专用接口 Post 请求参数放入到 body 里 使用 application/json 类型传递 -/// @param path 请求地址 -/// @param params 参数 -/// @param completion 回调 + (void)postSkillCard:(NSString *)path params:(NSString *)params completion:(HttpRequestHelperCompletion)completion; diff --git a/YuMi/Network/HttpRequestHelper.h.backup b/YuMi/Network/HttpRequestHelper.h.backup new file mode 100644 index 0000000..9b63cac --- /dev/null +++ b/YuMi/Network/HttpRequestHelper.h.backup @@ -0,0 +1,64 @@ +// +// HttpRequestHelper.h +// YUMI +// +// Created by zu on 2021/9/3. +// + +#import +#import "BaseModel.h" + +typedef NS_ENUM(NSUInteger, HttpRequestHelperMethod) { + HttpRequestHelperMethodPOST, + HttpRequestHelperMethodGET, + HttpRequestHelperMethodDELETE +}; + +static dispatch_once_t onceToken; + +typedef void(^HttpRequestHelperCompletion)(BaseModel* _Nullable data, NSInteger code, NSString * _Nullable msg); + +NS_ASSUME_NONNULL_BEGIN + +@interface HttpRequestHelper : NSObject ++(NSString *)getHostUrl; ++ (NSDictionary*)configBaseParmars:(NSDictionary * _Nullable)parmars; + ++ (void)GET:(NSString *)method +params:(NSDictionary *)params +success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure; + ++ (void)POST:(NSString *)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure; + ++ (void)DELETE:(NSString *)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure; + ++ (void)request:(NSString *)url + method:(HttpRequestHelperMethod)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure; + ++ (void)request:(NSString *)path + method:(HttpRequestHelperMethod)method + params:(NSDictionary *)params + completion:(HttpRequestHelperCompletion)completion; + + +/// 增加或编辑技能卡专用接口 Post 请求参数放入到 body 里 使用 application/json 类型传递 +/// @param path 请求地址 +/// @param params 参数 +/// @param completion 回调 ++ (void)postSkillCard:(NSString *)path + params:(NSString *)params + completion:(HttpRequestHelperCompletion)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Network/HttpRequestHelper.m b/YuMi/Network/HttpRequestHelper.m index f1ec657..4a3b3ff 100644 --- a/YuMi/Network/HttpRequestHelper.m +++ b/YuMi/Network/HttpRequestHelper.m @@ -1,9 +1,7 @@ -// -// HttpRequestHelper.m -// YUMI -// + + // Created by zu on 2021/9/3. -// + #import "HttpRequestHelper.h" #import "YYUtility.h" @@ -22,8 +20,8 @@ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - configuration.HTTPShouldUsePipelining = YES; // 启用 HTTP/2 pipelining - configuration.HTTPMaximumConnectionsPerHost = 15; // 提升并发 + configuration.HTTPShouldUsePipelining = YES; + configuration.HTTPMaximumConnectionsPerHost = 15; manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[HttpRequestHelper getHostUrl]] sessionConfiguration:configuration]; @@ -40,10 +38,10 @@ manager.requestSerializer.HTTPShouldHandleCookies = YES; manager.requestSerializer.timeoutInterval = 60; - // 声明开启 gzip 和 br + [manager.requestSerializer setValue:@"gzip, br" forHTTPHeaderField:@"Accept-Encoding"]; - // 确保所有请求走 HTTPS,避免降级到 HTTP/1.1 + manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; manager.securityPolicy.allowInvalidCertificates = NO; manager.securityPolicy.validatesDomainName = YES; @@ -52,15 +50,6 @@ } +(NSString *)getHostUrl{ return API_HOST_URL; -#if DEBUG - NSString *isProduction = [[NSUserDefaults standardUserDefaults]valueForKey:@"kIsProductionEnvironment"]; - if([isProduction isEqualToString:@"YES"]){ - return API_HOST_URL; - } - return API_HOST_TEST_URL; -#else - return API_HOST_URL; -#endif } + (void)GET:(NSString *)method params:(NSDictionary *)params @@ -94,11 +83,11 @@ params = [self configBaseParmars:editParam]; #if DEBUG - // 构建完整的 URL + NSString *baseUrl = [HttpRequestHelper getHostUrl]; NSString *fullUrl = [NSString stringWithFormat:@"%@/%@", baseUrl, method]; - // 构建查询字符串 + NSMutableArray *queryItems = [NSMutableArray array]; [params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { [queryItems addObject:[NSString stringWithFormat:@"%@=%@", key, obj]]; @@ -140,7 +129,7 @@ return; } -// [self configHeaders]; + AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; @@ -148,7 +137,7 @@ params = [self configBaseParmars:params]; #if DEBUG - // 构建完整的 URL + NSString *baseUrl = [HttpRequestHelper getHostUrl]; NSString *fullUrl = [NSString stringWithFormat:@"%@/%@", baseUrl, method]; @@ -196,10 +185,10 @@ #else #endif - // 将 NSDictionary 转换为 JSON + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil]; - // Gzip 压缩数据 + NSData *gzipData = [jsonData gzippedData]; @kWeakify(self); [manager POST:method @@ -236,16 +225,16 @@ constructingBodyWithBlock:^(id _Nonnull formData) { }]) { return; } -// [self configHeaders]; + params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; params = [self configBaseParmars:params]; AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; #if DEBUG - // 构建完整的 URL + NSString *baseUrl = [HttpRequestHelper getHostUrl]; NSString *fullUrl = [NSString stringWithFormat:@"%@/%@", baseUrl, method]; - // 构建查询字符串 + NSMutableArray *queryItems = [NSMutableArray array]; [params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { [queryItems addObject:[NSString stringWithFormat:@"%@=%@", key, obj]]; @@ -312,7 +301,7 @@ constructingBodyWithBlock:^(id _Nonnull formData) { completion(nil, resCode, message); } if (resCode > 500 && resCode < 600) { - // 使用 BuglyManager 统一上报网络错误 + NSString *uid = [AccountInfoStorage instance].getUid ?: @"未知用户"; NSMutableDictionary *userInfo = [params mutableCopy]; [userInfo setObject:message forKey:@"error message"]; @@ -384,7 +373,7 @@ constructingBodyWithBlock:^(id _Nonnull formData) { + (void)handleNetError:(NSError *)error method:(NSString *)method failure:(void (^)(NSInteger resCode, NSString *message))failure { - // 别问,反正 oauth/ticket 接口要通过这种方式取错误码。 + NSHTTPURLResponse *response = error.userInfo[@"com.alamofire.serialization.response.error.response"]; NSString *NETWORK_ERROR = error.description.length > 0 ? error.description : YMLocalizedString(@"HttpRequestHelper5");; if (response && response.statusCode == 401) { @@ -400,7 +389,7 @@ constructingBodyWithBlock:^(id _Nonnull formData) { NSLog(@"\n%@", error); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSDictionary *allHeaders = response.allHeaderFields; - //3, + NSMutableDictionary *blockDict = [[NSMutableDictionary alloc]init]; [blockDict setObject:@(response.statusCode) forKey:@"resultCode"]; [blockDict setObject:NETWORK_ERROR forKey:@"resultDesc"]; @@ -410,10 +399,7 @@ constructingBodyWithBlock:^(id _Nonnull formData) { #endif } -/// 增加或编辑技能卡专用接口 Post 请求参数放入到 body 里 使用 application/json 类型传递 -/// @param path 请求地址 -/// @param params 参数 -/// @param completion 回调 + + (void)postSkillCard:(NSString *)path params:(NSString *)params completion:(HttpRequestHelperCompletion)completion{ @@ -424,7 +410,7 @@ constructingBodyWithBlock:^(id _Nonnull formData) { return; } -// [self configHeaders]; + params = [MSParamsDecode msDecodeParams:[params.mj_JSONObject mutableCopy] ].toJSONString; NSDictionary *baseParams = [self configBaseParmars:nil]; diff --git a/YuMi/Network/HttpRequestHelper.m.backup b/YuMi/Network/HttpRequestHelper.m.backup new file mode 100644 index 0000000..f1ec657 --- /dev/null +++ b/YuMi/Network/HttpRequestHelper.m.backup @@ -0,0 +1,521 @@ +// +// HttpRequestHelper.m +// YUMI +// +// Created by zu on 2021/9/3. +// + +#import "HttpRequestHelper.h" +#import "YYUtility.h" +#import "AccountInfoStorage.h" +#import "YYReachability.h" +#import +#import "YUMIMacroUitls.h" +#import "MSParamsDecode.h" +#import "NSData+GZIP.h" + +@implementation HttpRequestHelper + ++(AFHTTPSessionManager *)requestManager +{ + static AFHTTPSessionManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.HTTPShouldUsePipelining = YES; // 启用 HTTP/2 pipelining + configuration.HTTPMaximumConnectionsPerHost = 15; // 提升并发 + + manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[HttpRequestHelper getHostUrl]] + sessionConfiguration:configuration]; + + manager.responseSerializer = [AFJSONResponseSerializer serializer]; + manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: + @"application/json", + @"text/json", + @"text/javascript", + @"text/html", + @"text/plain", + @"image/jpeg", + @"image/png", nil]; + + manager.requestSerializer.HTTPShouldHandleCookies = YES; + manager.requestSerializer.timeoutInterval = 60; + // 声明开启 gzip 和 br + [manager.requestSerializer setValue:@"gzip, br" forHTTPHeaderField:@"Accept-Encoding"]; + + // 确保所有请求走 HTTPS,避免降级到 HTTP/1.1 + manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; + manager.securityPolicy.allowInvalidCertificates = NO; + manager.securityPolicy.validatesDomainName = YES; + }); + return manager; +} ++(NSString *)getHostUrl{ + return API_HOST_URL; +#if DEBUG + NSString *isProduction = [[NSUserDefaults standardUserDefaults]valueForKey:@"kIsProductionEnvironment"]; + if([isProduction isEqualToString:@"YES"]){ + return API_HOST_URL; + } + return API_HOST_TEST_URL; +#else + return API_HOST_URL; +#endif +} ++ (void)GET:(NSString *)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure +{ + if ([self checkNetworkStatusWithFailure:^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { + return; + } + + [self configHeaders]; + + AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; + + NSString *key = @"NeedChangeTimeOut"; + NSMutableDictionary *editParam = [params mutableCopy]; + if ([editParam.allKeys containsObject:key]) { + NSInteger timeout = [[editParam objectForKey:key] integerValue]; + [editParam removeObjectForKey:key]; + if (timeout > 0) { + manager.requestSerializer.timeoutInterval = timeout; + } + } + else { + manager.requestSerializer.timeoutInterval = 60; + } + + editParam = [MSParamsDecode msDecodeParams:editParam]; + params = [self configBaseParmars:editParam]; + +#if DEBUG + // 构建完整的 URL + NSString *baseUrl = [HttpRequestHelper getHostUrl]; + NSString *fullUrl = [NSString stringWithFormat:@"%@/%@", baseUrl, method]; + + // 构建查询字符串 + NSMutableArray *queryItems = [NSMutableArray array]; + [params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [queryItems addObject:[NSString stringWithFormat:@"%@=%@", key, obj]]; + }]; + NSString *queryString = [queryItems componentsJoinedByString:@"&"]; + if (queryString.length > 0) { + fullUrl = [NSString stringWithFormat:@"%@?%@", fullUrl, queryString]; + } + + NSLog(@"\n🌐 API Request Info:"); + NSLog(@"📍 Full URL: %@", fullUrl); + NSLog(@"🔧 Method: %@", method); + NSLog(@"📦 Parameter Type: queryParameters"); + NSLog(@"📋 Parameters: %@\n", params); +#endif + @kWeakify(self); + [manager GET:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { + BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; +#if DEBUG + NSLog(@"%@ - \n%@\n", method, [baseModel toJSONString]); +#else +#endif + success(baseModel); + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + @kStrongify(self); + [self handleNetError:error method:method failure:failure]; + }]; +} + ++ (void)POST:(NSString *)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure +{ + if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }); + return; + } + +// [self configHeaders]; + AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; + params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; + + + params = [self configBaseParmars:params]; + +#if DEBUG + // 构建完整的 URL + NSString *baseUrl = [HttpRequestHelper getHostUrl]; + NSString *fullUrl = [NSString stringWithFormat:@"%@/%@", baseUrl, method]; + + NSLog(@"\n🌐 API Request Info:"); + NSLog(@"📍 Full URL: %@", fullUrl); + NSLog(@"🔧 Method: %@", method); + NSLog(@"📦 Parameter Type: bodyParameters"); + NSLog(@"📋 Parameters: %@\n", params); +#else +#endif + + [manager POST:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { + BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; +#if DEBUG + NSLog(@"\n%@", [baseModel toJSONString]); +#else +#endif + success(baseModel); + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + [self handleNetError:error method:method failure:failure]; + }]; +} + ++ (void)__POST:(NSString *)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure +{ + if ([self checkNetworkStatusWithFailure:^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { + return; + } + + [self configHeaders]; + AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; + params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; + params = [self configBaseParmars:params]; + +#if DEBUG + NSLog(@"\nmethod:\n%@\nparameter:\n%@\n 超時:%@", + method, + params, + @(manager.session.configuration.timeoutIntervalForRequest)); +#else +#endif + + // 将 NSDictionary 转换为 JSON + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil]; + + // Gzip 压缩数据 + NSData *gzipData = [jsonData gzippedData]; + @kWeakify(self); + [manager POST:method + parameters:params + headers:nil +constructingBodyWithBlock:^(id _Nonnull formData) { + [formData appendPartWithFormData:gzipData name:@"data"]; + } + progress:nil + success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { + BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; +#if DEBUG + NSLog(@"%@ - \n%@\n", method, [baseModel toJSONString]); +#else +#endif + success(baseModel); + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { +#if DEBUG + NSLog(@"%@ - \n%@\n", method, error); +#else +#endif + @kStrongify(self); + [self handleNetError:error method:method failure:failure]; + }]; +} + ++ (void)DELETE:(NSString *)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure +{ + if ([self checkNetworkStatusWithFailure:^{ + failure(-1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { + return; + } +// [self configHeaders]; + params = [MSParamsDecode msDecodeParams:[params mutableCopy] ]; + params = [self configBaseParmars:params]; + AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; +#if DEBUG + // 构建完整的 URL + NSString *baseUrl = [HttpRequestHelper getHostUrl]; + NSString *fullUrl = [NSString stringWithFormat:@"%@/%@", baseUrl, method]; + + // 构建查询字符串 + NSMutableArray *queryItems = [NSMutableArray array]; + [params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [queryItems addObject:[NSString stringWithFormat:@"%@=%@", key, obj]]; + }]; + NSString *queryString = [queryItems componentsJoinedByString:@"&"]; + if (queryString.length > 0) { + fullUrl = [NSString stringWithFormat:@"%@?%@", fullUrl, queryString]; + } + + NSLog(@"\n🌐 API Request Info:"); + NSLog(@"📍 Full URL: %@", fullUrl); + NSLog(@"🔧 Method: %@", method); + NSLog(@"📦 Parameter Type: queryParameters"); + NSLog(@"📋 Parameters: %@\n", params); +#else +#endif + @kWeakify(self); + [manager DELETE:method parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { + BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; +#if DEBUG + NSLog(@"\n%@\n", [baseModel toJSONString]); +#else +#endif + success(baseModel); + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + @kStrongify(self); + [self handleNetError:error method:method failure:failure]; + }]; +} + ++ (void)request:(NSString *)url + method:(HttpRequestHelperMethod)method + params:(NSDictionary *)params + success:(void (^)(BaseModel *data))success + failure:(void (^)(NSInteger resCode, NSString *message))failure +{ + switch (method) { + case HttpRequestHelperMethodGET: { + [self GET:url params:params success:success failure:failure]; + } + break; + case HttpRequestHelperMethodPOST:{ + [self POST:url params:params success:success failure:failure]; + } + break; + case HttpRequestHelperMethodDELETE:{ + [self DELETE:url params:params success:success failure:failure]; + } + break; + } +} + ++ (void)request:(NSString *)path + method:(HttpRequestHelperMethod)method + params:(NSDictionary *)params + completion:(HttpRequestHelperCompletion)completion +{ + [self request:path method:method params:params success:^(BaseModel *data) { + if (completion) { + completion(data, data.code, data.message); + } + } failure:^(NSInteger resCode, NSString *message) { + if (completion) { + completion(nil, resCode, message); + } + if (resCode > 500 && resCode < 600) { + // 使用 BuglyManager 统一上报网络错误 + NSString *uid = [AccountInfoStorage instance].getUid ?: @"未知用户"; + NSMutableDictionary *userInfo = [params mutableCopy]; + [userInfo setObject:message forKey:@"error message"]; + [userInfo setObject:@(method) forKey:@"http method"]; + } + }]; +} + ++ (void)configHeaders +{ + AFHTTPSessionManager *client = [HttpRequestHelper requestManager]; + if ([[AccountInfoStorage instance] getUid].length > 0) { + [client.requestSerializer setValue:[[AccountInfoStorage instance] getUid] forHTTPHeaderField:@"pub_uid"]; + } else { + [client.requestSerializer setValue:nil forHTTPHeaderField:@"pub_uid"]; + } + if ([[AccountInfoStorage instance] getTicket].length > 0) { + [client.requestSerializer setValue:[[AccountInfoStorage instance] getTicket] forHTTPHeaderField:@"pub_ticket"]; + }else { + [client.requestSerializer setValue:nil forHTTPHeaderField:@"pub_ticket"]; + } + [client.requestSerializer setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"]; + [client.requestSerializer setValue:PI_App_Version forHTTPHeaderField:@"App-Version"]; +} + ++ (NSDictionary*)configBaseParmars:(NSDictionary * _Nullable)parmars +{ + NSDictionary *defaultBasciParame = @{ + @"Accept-Language":[NSBundle uploadLanguageText], + @"os" : @"iOS", + @"osVersion" : [YYUtility systemVersion], + @"netType" : ([YYUtility networkStatus] == ReachableViaWiFi) ? @2 : @1, + @"ispType" : @([YYUtility carrierIdentifier]), + @"channel" : [YYUtility getAppSource] ? : @"", + @"model" : [YYUtility modelType], + @"deviceId" : [YYUtility deviceUniqueIdentification], + @"appVersion" : [YYUtility appVersion], + @"app" : [YYUtility appName], + @"lang" : [YYUtility getLanguage], + }; + + if (!parmars||![parmars isKindOfClass:[NSDictionary class]]){ + NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:defaultBasciParame]; + if(![[YYUtility getMobileCountryCode] isEqualToString:@"65535"]){ + [dic setValue:[YYUtility getMobileCountryCode] forKey:@"mcc"]; + } + return dic; + } + + NSMutableDictionary * dic = [NSMutableDictionary dictionaryWithDictionary:parmars]; + if(![[YYUtility getMobileCountryCode] isEqualToString:@"65535"]){ + [dic setValue:[YYUtility getMobileCountryCode] forKey:@"mcc"]; + } + [dic addEntriesFromDictionary:defaultBasciParame]; + + if ([[AccountInfoStorage instance] getUid].length > 0) { + [dic setValue:[[AccountInfoStorage instance] getUid] + forKey:@"pub_uid"]; + } + + if ([[AccountInfoStorage instance] getTicket].length > 0) { + [dic setValue:[[AccountInfoStorage instance] getTicket] + forKey:@"pub_ticket"]; + } + + return dic; +} + ++ (void)handleNetError:(NSError *)error method:(NSString *)method + failure:(void (^)(NSInteger resCode, NSString *message))failure +{ + // 别问,反正 oauth/ticket 接口要通过这种方式取错误码。 + NSHTTPURLResponse *response = error.userInfo[@"com.alamofire.serialization.response.error.response"]; + NSString *NETWORK_ERROR = error.description.length > 0 ? error.description : YMLocalizedString(@"HttpRequestHelper5");; + if (response && response.statusCode == 401) { + failure(response.statusCode, YMLocalizedString(@"HttpRequestHelper7")); + } else { + if (error.code == -1009 || error.code == -1001 || error.code == -1004 || error.code == -1003 || error.code == -1002 || error.code == 3840) { + failure(error.code, @""); + } else { + failure(error.code, error.localizedDescription.length > 0 ? error.localizedDescription : YMLocalizedString(@"HttpRequestHelper4")); + } + } +#if DEBUG + NSLog(@"\n%@", error); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSDictionary *allHeaders = response.allHeaderFields; + //3, + NSMutableDictionary *blockDict = [[NSMutableDictionary alloc]init]; + [blockDict setObject:@(response.statusCode) forKey:@"resultCode"]; + [blockDict setObject:NETWORK_ERROR forKey:@"resultDesc"]; + [BSNetListenModel addHttpRsp:method header:allHeaders result:blockDict isSuccess:NO time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]]; + }); +#else +#endif +} + +/// 增加或编辑技能卡专用接口 Post 请求参数放入到 body 里 使用 application/json 类型传递 +/// @param path 请求地址 +/// @param params 参数 +/// @param completion 回调 ++ (void)postSkillCard:(NSString *)path + params:(NSString *)params + completion:(HttpRequestHelperCompletion)completion{ + + if ([self checkNetworkStatusWithFailure:^{ + completion(nil, -1, YMLocalizedString(@"HttpRequestHelper0")); + }]) { + return; + } + +// [self configHeaders]; + params = [MSParamsDecode msDecodeParams:[params.mj_JSONObject mutableCopy] ].toJSONString; + + NSDictionary *baseParams = [self configBaseParmars:nil]; + AFHTTPSessionManager *manager = [HttpRequestHelper requestManager]; + NSString *url = [self getHostUrl]; + NSString *urlPath = [NSString stringWithFormat:@"%@/%@", url ,path]; +#if DEBUG + NSLog(@"\nmethod:\n%@\nparameter:\n%@", path, params); + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + [BSNetListenModel addHttpReq:urlPath header:manager.requestSerializer.HTTPRequestHeaders param:[params copy] time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]]; + }); +#else +#endif + + __block NSString *requestUrl = @""; + [baseParams.allKeys enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *value = baseParams[obj]; + requestUrl = [requestUrl stringByAppendingString:[NSString stringWithFormat:@"%@=%@&", obj, value]]; + }]; + + urlPath = [NSString stringWithFormat:@"%@?%@", urlPath, requestUrl]; + urlPath = [urlPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + + NSMutableURLRequest *request = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlPath parameters:baseParams error:nil]; + request.timeoutInterval= [[[NSUserDefaults standardUserDefaults] valueForKey:@"timeoutInterval"] longValue]; + + [request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; + + if ([[AccountInfoStorage instance] getUid].length > 0) { + [request setValue:[[AccountInfoStorage instance] getUid] forHTTPHeaderField:@"pub_uid"]; + [manager.requestSerializer setValue:[[AccountInfoStorage instance] getUid] forHTTPHeaderField:@"pub_uid"]; + } else { + [request setValue:nil forHTTPHeaderField:@"pub_uid"]; + } + if ([[AccountInfoStorage instance] getTicket].length > 0) { + [request setValue:[[AccountInfoStorage instance] getTicket] forHTTPHeaderField:@"pub_ticket"]; + [manager.requestSerializer setValue:[[AccountInfoStorage instance] getTicket] forHTTPHeaderField:@"pub_ticket"]; + }else { + [request setValue:nil forHTTPHeaderField:@"pub_ticket"]; + } + [request setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"]; + [request setValue:PI_App_Version forHTTPHeaderField:@"App-Version"]; + [manager.requestSerializer setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"]; + [manager.requestSerializer setValue:PI_App_Version forHTTPHeaderField:@"App-Version"]; + + [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; + + [[manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { + if (responseObject) { + BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject]; + +#if DEBUG + NSLog(@"\n%@", [baseModel toJSONString]); +#else +#endif + if (baseModel.code == 200) { +#if DEBUG + NSHTTPURLResponse *urlresponse = (NSHTTPURLResponse *)response; + NSDictionary *allHeaders = urlresponse.allHeaderFields; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [BSNetListenModel addHttpRsp:urlPath header:allHeaders result:baseModel.data isSuccess:YES time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]]; + }); +#else +#endif + if (completion) { + completion(baseModel, 200, nil); + } + } else { + if (completion) { + completion(nil, baseModel.code, baseModel.message); + } + } + } + if (error) { + [self handleNetError:error method:path failure:^(NSInteger resCode, NSString *message) { + completion(nil, resCode, message); + }]; + } + }] resume]; +} + ++ (BOOL)checkNetworkStatusWithFailure:(void (^)(void))failure { + if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) { + if (failure) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + failure(); + }); + } + return YES; + } + return NO; +} + +@end diff --git a/YuMi/Network/MSParamsDecode.h b/YuMi/Network/MSParamsDecode.h index 19aca87..05c5f6d 100644 --- a/YuMi/Network/MSParamsDecode.h +++ b/YuMi/Network/MSParamsDecode.h @@ -1,19 +1,15 @@ -// -// MSParamsDecode.h -// YuMi -// + + // Created by duoban on 2024/4/23. -// + #import NS_ASSUME_NONNULL_BEGIN @interface MSParamsDecode : NSObject -/** - 加密方法 - @param params 参数 - */ + + + (NSMutableDictionary *)msDecodeParams:(NSMutableDictionary *)params ; @end diff --git a/YuMi/Network/MSParamsDecode.h.backup b/YuMi/Network/MSParamsDecode.h.backup new file mode 100644 index 0000000..19aca87 --- /dev/null +++ b/YuMi/Network/MSParamsDecode.h.backup @@ -0,0 +1,21 @@ +// +// MSParamsDecode.h +// YuMi +// +// Created by duoban on 2024/4/23. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MSParamsDecode : NSObject +/** + 加密方法 + @param params 参数 + */ ++ (NSMutableDictionary *)msDecodeParams:(NSMutableDictionary *)params ; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Network/MSParamsDecode.m b/YuMi/Network/MSParamsDecode.m index ac76968..39f86c1 100644 --- a/YuMi/Network/MSParamsDecode.m +++ b/YuMi/Network/MSParamsDecode.m @@ -1,9 +1,7 @@ -// -// MSParamsDecode.m -// YuMi -// + + // Created by duoban on 2024/4/23. -// + #import "MSParamsDecode.h" @@ -39,17 +37,17 @@ NSMutableString *stringA = [NSMutableString string]; - //按字典key升序排序 + NSArray *sortKeys = [[dic allKeys] sortedArrayUsingSelector:@selector(compare:)]; - //拼接格式 “key0=value0&key1=value1&key2=value2” + for (NSString *key in sortKeys) { [stringA appendString:[NSString stringWithFormat:@"%@=%@&", key, dic[key]]]; } - //拼接参数加密签名 PARAMSSECRET + [stringA appendString:[NSString stringWithFormat:@"key=%@", KeyWithType(KeyType_Sign)]]; - //MD5加密签名 + NSString *stringB = [stringA MD5String]; - //返回大写字母 + return stringB.uppercaseString; } diff --git a/YuMi/Network/MSParamsDecode.m.backup b/YuMi/Network/MSParamsDecode.m.backup new file mode 100644 index 0000000..ac76968 --- /dev/null +++ b/YuMi/Network/MSParamsDecode.m.backup @@ -0,0 +1,64 @@ +// +// MSParamsDecode.m +// YuMi +// +// Created by duoban on 2024/4/23. +// + +#import "MSParamsDecode.h" + +@implementation MSParamsDecode ++ (NSMutableDictionary *)msDecodeParams:(NSMutableDictionary *)params { + if (!params) { + params = [NSMutableDictionary dictionary]; + } + + [params setObject:[MSParamsDecode msSign:[params mutableCopy]] forKey:@"pub_sign"]; + return params; +} + + ++ (NSString *)msSign:(NSMutableDictionary *)dic { + [dic removeObjectForKey:@"Accept-Language"]; + [dic removeObjectForKey:@"pub_uid"]; + [dic removeObjectForKey:@"appVersion"]; + [dic removeObjectForKey:@"appVersionCode"]; + [dic removeObjectForKey:@"channel"]; + [dic removeObjectForKey:@"deviceId"]; + [dic removeObjectForKey:@"ispType"]; + [dic removeObjectForKey:@"netType"]; + [dic removeObjectForKey:@"os"]; + [dic removeObjectForKey:@"osVersion"]; + [dic removeObjectForKey:@"app"]; + [dic removeObjectForKey:@"ticket"]; + [dic removeObjectForKey:@"client"]; + [dic removeObjectForKey:@"channel"]; + [dic removeObjectForKey:@"deviceId"]; + [dic removeObjectForKey:@"lang"]; + [dic removeObjectForKey:@"mcc"]; + + + NSMutableString *stringA = [NSMutableString string]; + //按字典key升序排序 + NSArray *sortKeys = [[dic allKeys] sortedArrayUsingSelector:@selector(compare:)]; + //拼接格式 “key0=value0&key1=value1&key2=value2” + for (NSString *key in sortKeys) { + [stringA appendString:[NSString stringWithFormat:@"%@=%@&", key, dic[key]]]; + } + //拼接参数加密签名 PARAMSSECRET + [stringA appendString:[NSString stringWithFormat:@"key=%@", KeyWithType(KeyType_Sign)]]; + //MD5加密签名 + NSString *stringB = [stringA MD5String]; + //返回大写字母 + return stringB.uppercaseString; +} + ++ (NSString *)uuidString{ + CFUUIDRef uuid_ref = CFUUIDCreate(NULL); + CFStringRef uuid_string_ref= CFUUIDCreateString(NULL, uuid_ref); + NSString *uuid = [NSString stringWithString:(__bridge NSString *)uuid_string_ref]; + CFRelease(uuid_ref); + CFRelease(uuid_string_ref); + return [uuid lowercaseString]; +} +@end diff --git a/YuMi/Structure/Base/BaseNavigationController.h b/YuMi/Structure/Base/BaseNavigationController.h index 0b228a0..be4a03e 100644 --- a/YuMi/Structure/Base/BaseNavigationController.h +++ b/YuMi/Structure/Base/BaseNavigationController.h @@ -1,9 +1,7 @@ -// -// BaseNavigationController.h -// YUMI -// + + // Created by zu on 2021/9/7. -// + #import diff --git a/YuMi/Structure/Base/BaseNavigationController.h.backup b/YuMi/Structure/Base/BaseNavigationController.h.backup new file mode 100644 index 0000000..0b228a0 --- /dev/null +++ b/YuMi/Structure/Base/BaseNavigationController.h.backup @@ -0,0 +1,16 @@ +// +// BaseNavigationController.h +// YUMI +// +// Created by zu on 2021/9/7. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BaseNavigationController : UINavigationController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/Base/BaseNavigationController.m b/YuMi/Structure/Base/BaseNavigationController.m index 388105a..4b3767d 100644 --- a/YuMi/Structure/Base/BaseNavigationController.m +++ b/YuMi/Structure/Base/BaseNavigationController.m @@ -1,12 +1,10 @@ -// -// BaseNavigationController.m -// YUMI -// + + // Created by zu on 2021/9/7. -// + #import "BaseNavigationController.h" -///Tool + #import "DJDKMIMOMColor.h" @interface BaseNavigationController () @@ -24,22 +22,10 @@ } [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(switchLanguage) name:@"kNavViewUpdateWhenLanguageUpdate" object:nil]; [self themeConfig]; - if(isMSRTL()){ - self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;; - self.view.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft; - }else{ - self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight;; - self.view.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; - } + } -(void)switchLanguage{ - if(isMSRTL()){ - self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft; - self.view.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft; - }else{ - self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; - self.view.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; - } + } - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { @@ -64,7 +50,7 @@ NSForegroundColorAttributeName:[DJDKMIMOMColor mainTextColor] }]; - /// scrollEdgeAppearance 属性iOS15 强制适用于 所有导航器 如果为nil 则使用 standardAppearance属性中的设置,并修改为使用透明背景 @fengshuo + if (@available(iOS 15.0, *)) { UINavigationBarAppearance *appearance = [UINavigationBarAppearance new]; appearance.titleTextAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18 weight:UIFontWeightMedium], diff --git a/YuMi/Structure/Base/BaseNavigationController.m.backup b/YuMi/Structure/Base/BaseNavigationController.m.backup new file mode 100644 index 0000000..388105a --- /dev/null +++ b/YuMi/Structure/Base/BaseNavigationController.m.backup @@ -0,0 +1,85 @@ +// +// BaseNavigationController.m +// YUMI +// +// Created by zu on 2021/9/7. +// + +#import "BaseNavigationController.h" +///Tool +#import "DJDKMIMOMColor.h" + +@interface BaseNavigationController () + +@end + +@implementation BaseNavigationController +-(void)dealloc{ + [[NSNotificationCenter defaultCenter]removeObserver:self]; +} +- (void)viewDidLoad { + [super viewDidLoad]; + if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) { + self.interactivePopGestureRecognizer.delegate = self; + } + [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(switchLanguage) name:@"kNavViewUpdateWhenLanguageUpdate" object:nil]; + [self themeConfig]; + if(isMSRTL()){ + self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;; + self.view.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft; + }else{ + self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight;; + self.view.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + } +} +-(void)switchLanguage{ + if(isMSRTL()){ + self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft; + self.view.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft; + }else{ + self.navigationBar.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + self.view.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + } + +} +- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { + if(self.topViewController == viewController) return; + + + [super pushViewController:viewController animated:animated]; +} + +- (void)backClick{ + [self popViewControllerAnimated:YES]; +} + +- (void)themeConfig { + self.navigationBar.shadowImage = [[UIImage alloc] init]; + self.navigationBar.barTintColor = [DJDKMIMOMColor appBackgroundColor]; + self.navigationBar.tintColor = [UIColor whiteColor]; + self.navigationBar.translucent = NO; + self.view.backgroundColor = [DJDKMIMOMColor appBackgroundColor]; + [self.navigationBar setTitleTextAttributes:@{ + NSFontAttributeName:[UIFont systemFontOfSize:18 weight:UIFontWeightMedium], + NSForegroundColorAttributeName:[DJDKMIMOMColor mainTextColor] + }]; + + /// scrollEdgeAppearance 属性iOS15 强制适用于 所有导航器 如果为nil 则使用 standardAppearance属性中的设置,并修改为使用透明背景 @fengshuo + if (@available(iOS 15.0, *)) { + UINavigationBarAppearance *appearance = [UINavigationBarAppearance new]; + appearance.titleTextAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18 weight:UIFontWeightMedium], + NSForegroundColorAttributeName:[DJDKMIMOMColor mainTextColor]}; + appearance.backgroundColor = [DJDKMIMOMColor appCellBackgroundColor]; + self.navigationBar.standardAppearance = appearance; + self.navigationBar.scrollEdgeAppearance = appearance; + } +} + +#pragma mark - UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + return YES; +} + + +@end diff --git a/YuMi/Structure/Base/BaseViewController.h b/YuMi/Structure/Base/BaseViewController.h index 7ce2976..80962d0 100644 --- a/YuMi/Structure/Base/BaseViewController.h +++ b/YuMi/Structure/Base/BaseViewController.h @@ -1,9 +1,7 @@ -// -// BaseViewController.h -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import @@ -11,90 +9,57 @@ NS_ASSUME_NONNULL_BEGIN @protocol BaseViewControllerProtocol @optional -/** - 成功 toast - */ + + - (void)showSuccessToast:(NSString *)msg; -/** - 失败 toast - */ + - (void)showErrorToast:(NSString *)msg; -/** - 加载 loading - */ + - (void)showLoading; -/** - 隐藏 XNDJTDDLoadingTool - */ + - (void)hideHUD; -/** - 显示加载个播房loading - */ + - (void)showAnchorLoading; @end @interface BaseViewController : UIViewController -// 是否隐藏导航 默认是不隐藏的 + @property(nonatomic,assign,getter=isHiddenNavBar) BOOL hiddenNavBar; -/** - 显示/隐藏导航 - */ - (void)hideNavigationBar; -/** - 隐藏导航栏 - */ + - (void)showNavigationBar; -/** - 显示/隐藏状态栏 - */ - (void)showStatusBar; -/** - 隐藏状态栏 - */ - (void)hideStatusBar; #pragma mark - 导航栏添加操作按钮 -/// 添加图片 -/// @param imageNames 图片的数组 -/// @param isLeft 是否在左边 -/// @param target 接受事件的 -/// @param action 点击 -/// @param tags tag + - (void)addNavigationItemWithImageNames:(NSArray *)imageNames isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags; -/// 添加文字 不可点击的时候颜色 -/// @param titles 文字的数组 -/// @param titleColor 文字的颜色 -/// @param isLeft 是否在左边 -/// @param target 目标 -/// @param action 点击 -/// @param tags tag + - (void)addNavigationItemWithTitles:(NSArray *)titles titleColor:(UIColor *)titleColor isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags; -/// 自定义的View -/// @param isLeft 是否在左边 + - (void)addNavigationItemWithItems:(NSArray *)items isLeft:(BOOL)isLeft; - @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/Base/BaseViewController.h.backup b/YuMi/Structure/Base/BaseViewController.h.backup new file mode 100644 index 0000000..7ce2976 --- /dev/null +++ b/YuMi/Structure/Base/BaseViewController.h.backup @@ -0,0 +1,100 @@ +// +// BaseViewController.h +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol BaseViewControllerProtocol +@optional +/** + 成功 toast + */ +- (void)showSuccessToast:(NSString *)msg; + +/** + 失败 toast + */ +- (void)showErrorToast:(NSString *)msg; + +/** + 加载 loading + */ +- (void)showLoading; + +/** + 隐藏 XNDJTDDLoadingTool + */ +- (void)hideHUD; + +/** + 显示加载个播房loading + */ +- (void)showAnchorLoading; + +@end + +@interface BaseViewController : UIViewController + +// 是否隐藏导航 默认是不隐藏的 +@property(nonatomic,assign,getter=isHiddenNavBar) BOOL hiddenNavBar; + + +/** + 显示/隐藏导航 + */ +- (void)hideNavigationBar; + +/** + 隐藏导航栏 + */ +- (void)showNavigationBar; + + +/** + 显示/隐藏状态栏 + */ +- (void)showStatusBar; + + +/** + 隐藏状态栏 + */ +- (void)hideStatusBar; +#pragma mark - 导航栏添加操作按钮 + +/// 添加图片 +/// @param imageNames 图片的数组 +/// @param isLeft 是否在左边 +/// @param target 接受事件的 +/// @param action 点击 +/// @param tags tag +- (void)addNavigationItemWithImageNames:(NSArray *)imageNames + isLeft:(BOOL)isLeft + target:(id)target + action:(SEL)action + tags:(NSArray * _Nullable)tags; + +/// 添加文字 不可点击的时候颜色 +/// @param titles 文字的数组 +/// @param titleColor 文字的颜色 +/// @param isLeft 是否在左边 +/// @param target 目标 +/// @param action 点击 +/// @param tags tag +- (void)addNavigationItemWithTitles:(NSArray *)titles titleColor:(UIColor *)titleColor isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags; + +/// 自定义的View +/// @param isLeft 是否在左边 +- (void)addNavigationItemWithItems:(NSArray *)items + isLeft:(BOOL)isLeft; + + + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/Base/BaseViewController.m b/YuMi/Structure/Base/BaseViewController.m index b826e52..e44f1a6 100644 --- a/YuMi/Structure/Base/BaseViewController.m +++ b/YuMi/Structure/Base/BaseViewController.m @@ -1,12 +1,10 @@ -// -// BaseViewController.m -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import "BaseViewController.h" -///Tool + #import "XNDJTDDLoadingTool.h" #import "DJDKMIMOMColor.h" @@ -21,16 +19,16 @@ if (@available(iOS 13.0, *)) { [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDarkContent; } else { - // Fallback on earlier versions + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; } - // 根据子类属性重写判断是否隐藏导航栏 + [self.navigationController setNavigationBarHidden:self.isHiddenNavBar animated:animated]; - ///解决iOS15 导航栏下面有一条黑色的线 @fengshuo + if (@available(iOS 15.0, *)) { [self.navigationController.navigationBar.subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { if ([[UIDevice currentDevice].systemVersion doubleValue] >= 10.0) { - //iOS10,改变了导航栏的私有接口为_UIBarBackground + if ([view isKindOfClass:NSClassFromString(@"_UIBarBackground")]) { [view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj isKindOfClass:NSClassFromString(@"_UIBarBackgroundShadowView")]) { @@ -52,31 +50,22 @@ [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; } -/** - 隐藏导航条 - */ + - (void)hideNavigationBar { [self.navigationController setNavigationBarHidden:YES animated:YES]; } -/** - 显示导航条 - */ - (void)showNavigationBar { [self.navigationController setNavigationBarHidden:NO]; } -/** - 显示状态栏 - */ + - (void)showStatusBar { [UIApplication sharedApplication].statusBarHidden = NO; } -/** - 隐藏状态栏 - */ + - (void)hideStatusBar { [UIApplication sharedApplication].statusBarHidden = YES; } @@ -97,20 +86,13 @@ [XNDJTDDLoadingTool hideHUD]; } -/** - 显示加载个播房loading - */ + - (void)showAnchorLoading { [XNDJTDDLoadingTool showAnchorLoading]; } #pragma mark - 导航栏添加操作按钮 -/// 添加图片 -/// @param imageNames 图片的数组 -/// @param isLeft 是否在左边 -/// @param target 接受事件的 -/// @param action 点击 -/// @param tags tag + - (void)addNavigationItemWithImageNames:(NSArray *)imageNames isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags { NSMutableArray * items = [[NSMutableArray alloc] init]; NSInteger i = 0; @@ -135,18 +117,12 @@ } } -/// 添加文字 不可点击的时候颜色 -/// @param titles 文字的数组 -/// @param titleColor 文字的颜色 -/// @param isLeft 是否在左边 -/// @param target 目标 -/// @param action 点击 -/// @param tags tag + - (void)addNavigationItemWithTitles:(NSArray *)titles titleColor:(UIColor *)titleColor isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags { NSMutableArray * items = [[NSMutableArray alloc] init]; - //调整按钮位置 + UIBarButtonItem* spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; - //将宽度设为负值 + spaceItem.width= -10; [items addObject:spaceItem]; if (titleColor == nil) { @@ -173,14 +149,12 @@ } -/// 自定义的View -/// @param isLeft 是否在左边 - (void)addNavigationItemWithItems:(NSArray *)views isLeft:(BOOL)isLeft { NSMutableArray * items = [[NSMutableArray alloc] init]; - //调整按钮位置 + UIBarButtonItem* spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; - //将宽度设为负值 + spaceItem.width= -10; [items addObject:spaceItem]; for (UIView * view in views) { diff --git a/YuMi/Structure/Base/BaseViewController.m.backup b/YuMi/Structure/Base/BaseViewController.m.backup new file mode 100644 index 0000000..b826e52 --- /dev/null +++ b/YuMi/Structure/Base/BaseViewController.m.backup @@ -0,0 +1,198 @@ +// +// BaseViewController.m +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import "BaseViewController.h" +///Tool +#import "XNDJTDDLoadingTool.h" +#import "DJDKMIMOMColor.h" + +@interface BaseViewController () + +@end + +@implementation BaseViewController + +- (void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + if (@available(iOS 13.0, *)) { + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDarkContent; + } else { + // Fallback on earlier versions + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; + } + // 根据子类属性重写判断是否隐藏导航栏 + [self.navigationController setNavigationBarHidden:self.isHiddenNavBar animated:animated]; + ///解决iOS15 导航栏下面有一条黑色的线 @fengshuo + if (@available(iOS 15.0, *)) { + [self.navigationController.navigationBar.subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { + if ([[UIDevice currentDevice].systemVersion doubleValue] >= 10.0) { + //iOS10,改变了导航栏的私有接口为_UIBarBackground + if ([view isKindOfClass:NSClassFromString(@"_UIBarBackground")]) { + [view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:NSClassFromString(@"_UIBarBackgroundShadowView")]) { + obj.hidden = YES; + } + }]; + } + } + }]; + } +} +- (void)viewDidLoad { + [super viewDidLoad]; + [self themeConfig]; +} + +- (void)themeConfig { + self.view.backgroundColor = [DJDKMIMOMColor appBackgroundColor]; + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; +} + +/** + 隐藏导航条 + */ +- (void)hideNavigationBar { + [self.navigationController setNavigationBarHidden:YES animated:YES]; +} + + +/** + 显示导航条 + */ +- (void)showNavigationBar { + [self.navigationController setNavigationBarHidden:NO]; +} + +/** + 显示状态栏 + */ +- (void)showStatusBar { + [UIApplication sharedApplication].statusBarHidden = NO; +} + +/** + 隐藏状态栏 + */ +- (void)hideStatusBar { + [UIApplication sharedApplication].statusBarHidden = YES; +} + +- (void)showSuccessToast:(NSString *)msg { + [XNDJTDDLoadingTool showSuccessWithMessage:msg]; +} + +- (void)showErrorToast:(NSString *)msg { + [XNDJTDDLoadingTool showErrorWithMessage:msg]; +} + +- (void)showLoading { + [XNDJTDDLoadingTool showLoading]; +} + +- (void)hideHUD { + [XNDJTDDLoadingTool hideHUD]; +} + +/** + 显示加载个播房loading + */ +- (void)showAnchorLoading { + [XNDJTDDLoadingTool showAnchorLoading]; +} +#pragma mark - 导航栏添加操作按钮 + +/// 添加图片 +/// @param imageNames 图片的数组 +/// @param isLeft 是否在左边 +/// @param target 接受事件的 +/// @param action 点击 +/// @param tags tag +- (void)addNavigationItemWithImageNames:(NSArray *)imageNames isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags { + NSMutableArray * items = [[NSMutableArray alloc] init]; + NSInteger i = 0; + for (NSString * imageName in imageNames) { + UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom]; + [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; + btn.frame = CGRectMake(0, 0, 30, 30); + if(isLeft){ + [btn setImageEdgeInsets:UIEdgeInsetsMake(0, -10, 0, 10)]; + }else{ + [btn setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; + } + [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; + btn.tag = [tags[i++] integerValue]; + UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:btn]; + [items addObject:item]; + } + if (isLeft) { + self.navigationItem.leftBarButtonItems = items; + } else { + self.navigationItem.rightBarButtonItems = items; + } +} + +/// 添加文字 不可点击的时候颜色 +/// @param titles 文字的数组 +/// @param titleColor 文字的颜色 +/// @param isLeft 是否在左边 +/// @param target 目标 +/// @param action 点击 +/// @param tags tag +- (void)addNavigationItemWithTitles:(NSArray *)titles titleColor:(UIColor *)titleColor isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray * _Nullable)tags { + NSMutableArray * items = [[NSMutableArray alloc] init]; + //调整按钮位置 + UIBarButtonItem* spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; + //将宽度设为负值 + spaceItem.width= -10; + [items addObject:spaceItem]; + if (titleColor == nil) { + titleColor = [DJDKMIMOMColor mainTextColor]; + } + NSInteger i = 0; + for (NSString * title in titles) { + UIButton * btn = [UIButton buttonWithType:UIButtonTypeSystem]; + btn.frame = CGRectMake(0, 0, 30, 20); + [btn setTitle:title forState:UIControlStateNormal]; + [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; + btn.titleLabel.font = [UIFont systemFontOfSize:14]; + [btn setTitleColor:titleColor forState:UIControlStateNormal]; + btn.tag = [tags[i++] integerValue]; + [btn sizeToFit]; + UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:btn]; + [items addObject:item]; + } + if (isLeft) { + self.navigationItem.leftBarButtonItems = items; + } else { + self.navigationItem.rightBarButtonItems = items; + } +} + + +/// 自定义的View +/// @param isLeft 是否在左边 +- (void)addNavigationItemWithItems:(NSArray *)views + isLeft:(BOOL)isLeft { + NSMutableArray * items = [[NSMutableArray alloc] init]; + //调整按钮位置 + UIBarButtonItem* spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; + //将宽度设为负值 + spaceItem.width= -10; + [items addObject:spaceItem]; + for (UIView * view in views) { + UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:view]; + [items addObject:item]; + } + if (isLeft) { + self.navigationItem.leftBarButtonItems = items; + } else { + self.navigationItem.rightBarButtonItems = items; + } +} + + +@end diff --git a/YuMi/Structure/MVP/Api/Api.h b/YuMi/Structure/MVP/Api/Api.h index f8bf214..d32fde5 100644 --- a/YuMi/Structure/MVP/Api/Api.h +++ b/YuMi/Structure/MVP/Api/Api.h @@ -1,9 +1,7 @@ -// -// Api.h -// YUMI -// + + // Created by zu on 2021/9/6. -// + #import #import "HttpRequestHelper.h" @@ -12,61 +10,38 @@ NS_ASSUME_NONNULL_BEGIN @interface Api : NSObject -/** - route : 接口路径 - method : http 请求方法(POST、GET等) - completion : 网络请求完成的回调 - ... : 可变参数,第一个为 __FUNCTION__ ,接下来依次为该接口的协议参数 - */ + + (void)makeRequest:(NSString *)route method:(HttpRequestHelperMethod)method completion:(HttpRequestHelperCompletion)completion, ...; + (void)getUserInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; -///获取多个用户的信息 + + (void)getUserInfos:(HttpRequestHelperCompletion)completion uids:(NSString *)uids; +(void)testMsg:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket; -/// 获取手机号的验证码 -/// @param completion 请求完成 -/// @param mobile 手机号 -/// @param type 类型 请看XPEunm中的枚举 + + + (void)phoneSmsCode:(HttpRequestHelperCompletion)completion mobile:(NSString *)mobile type:(NSString *)type phoneAreaCode:(NSString *)phoneAreaCode; -/// 校验手机号码 -/// @param completion 完成 -/// @param mobile 手机号 -/// @param code 验证码 -/// @param uid 用户的uid -/// @param ticket ticket + + (void)checkMoblieCode:(HttpRequestHelperCompletion)completion mobile:(NSString *)mobile code:(NSString *)code uid:(NSString *)uid ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode; -/// 补全用户资料 -/// @param completion 完成 -/// @param userInfo 需要更新的用户信息 + + (void)completeUserInfo:(HttpRequestHelperCompletion)completion userInfo:(NSDictionary *)userInfo; -/// 获取用户钱包余额信息 -/// @param completion 完成 -/// @param uid 用户uid -/// @param ticket ticketg + + + (void)getUserWalletInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket; -/// 批量验证 -/// @param completion 完成 -/// @param transcationIdStr 需要验证的数据 + + + (void)requestCheckTranscationIds:(HttpRequestHelperCompletion)completion transcationIdStr:(NSString *)transcationIdStr; -/// 锁麦/开麦 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param state 0 开麦 1 锁麦 -/// @param position 坑位 -/// @param ticket 用户的ticket -/// @param uid uid + + (void)microMuteCompletion:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid state:(NSString *)state @@ -74,22 +49,16 @@ NS_ASSUME_NONNULL_BEGIN ticket:(NSString *)ticket uid:(NSString *)uid; -/// 锁坑/开锁 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param state 1锁坑位,0取消锁(即取消锁坑位) -/// @param position 坑位 -/// @param ticket 用户的ticket -/// @param uid uid + + (void)microLockCompletion:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid state:(NSString *)state position:(NSString *)position ticket:(NSString *)ticket uid:(NSString *)uid; -//充值banner位 + +(void)requestBannerListCompletion:(HttpRequestHelperCompletion)completion; -//联系客服 + +(void)requestContactCustomerServiceCompletion:(HttpRequestHelperCompletion)completion; + (void)requestAllRegionInfoCompletion:(HttpRequestHelperCompletion)completion; diff --git a/YuMi/Structure/MVP/Api/Api.h.backup b/YuMi/Structure/MVP/Api/Api.h.backup new file mode 100644 index 0000000..f8bf214 --- /dev/null +++ b/YuMi/Structure/MVP/Api/Api.h.backup @@ -0,0 +1,103 @@ +// +// Api.h +// YUMI +// +// Created by zu on 2021/9/6. +// + +#import +#import "HttpRequestHelper.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface Api : NSObject + +/** + route : 接口路径 + method : http 请求方法(POST、GET等) + completion : 网络请求完成的回调 + ... : 可变参数,第一个为 __FUNCTION__ ,接下来依次为该接口的协议参数 + */ ++ (void)makeRequest:(NSString *)route method:(HttpRequestHelperMethod)method completion:(HttpRequestHelperCompletion)completion, ...; + ++ (void)getUserInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid; +///获取多个用户的信息 ++ (void)getUserInfos:(HttpRequestHelperCompletion)completion uids:(NSString *)uids; + +(void)testMsg:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket; +/// 获取手机号的验证码 +/// @param completion 请求完成 +/// @param mobile 手机号 +/// @param type 类型 请看XPEunm中的枚举 ++ (void)phoneSmsCode:(HttpRequestHelperCompletion)completion mobile:(NSString *)mobile type:(NSString *)type phoneAreaCode:(NSString *)phoneAreaCode; + +/// 校验手机号码 +/// @param completion 完成 +/// @param mobile 手机号 +/// @param code 验证码 +/// @param uid 用户的uid +/// @param ticket ticket ++ (void)checkMoblieCode:(HttpRequestHelperCompletion)completion + mobile:(NSString *)mobile + code:(NSString *)code + uid:(NSString *)uid + ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode; + +/// 补全用户资料 +/// @param completion 完成 +/// @param userInfo 需要更新的用户信息 ++ (void)completeUserInfo:(HttpRequestHelperCompletion)completion + userInfo:(NSDictionary *)userInfo; +/// 获取用户钱包余额信息 +/// @param completion 完成 +/// @param uid 用户uid +/// @param ticket ticketg ++ (void)getUserWalletInfo:(HttpRequestHelperCompletion)completion + uid:(NSString *)uid + ticket:(NSString *)ticket; +/// 批量验证 +/// @param completion 完成 +/// @param transcationIdStr 需要验证的数据 ++ (void)requestCheckTranscationIds:(HttpRequestHelperCompletion)completion + transcationIdStr:(NSString *)transcationIdStr; + +/// 锁麦/开麦 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param state 0 开麦 1 锁麦 +/// @param position 坑位 +/// @param ticket 用户的ticket +/// @param uid uid ++ (void)microMuteCompletion:(HttpRequestHelperCompletion)completion + roomUid:(NSString *)roomUid + state:(NSString *)state + position:(NSString *)position + ticket:(NSString *)ticket + uid:(NSString *)uid; + +/// 锁坑/开锁 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param state 1锁坑位,0取消锁(即取消锁坑位) +/// @param position 坑位 +/// @param ticket 用户的ticket +/// @param uid uid ++ (void)microLockCompletion:(HttpRequestHelperCompletion)completion + roomUid:(NSString *)roomUid + state:(NSString *)state + position:(NSString *)position + ticket:(NSString *)ticket + uid:(NSString *)uid; +//充值banner位 ++(void)requestBannerListCompletion:(HttpRequestHelperCompletion)completion; +//联系客服 ++(void)requestContactCustomerServiceCompletion:(HttpRequestHelperCompletion)completion; + ++ (void)requestAllRegionInfoCompletion:(HttpRequestHelperCompletion)completion; + ++ (void)requestBossMicUp:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid uid:(NSString *)uid; + ++ (void)shareGetInfo:(HttpRequestHelperCompletion)completion code:(NSString *)code; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Api/Api.m b/YuMi/Structure/MVP/Api/Api.m index 2553549..a2e7f4e 100644 --- a/YuMi/Structure/MVP/Api/Api.m +++ b/YuMi/Structure/MVP/Api/Api.m @@ -1,9 +1,7 @@ -// -// Api.m -// YUMI -// + + // Created by zu on 2021/9/6. -// + #import "Api.h" #import @@ -12,10 +10,10 @@ va_list arg_lists; va_start(arg_lists, completion); - // 获取第一个参数 __FUNCTION__ ,然后解析出来 key 。 + const char *functionName = va_arg(arg_lists, const char *); NSString *fn = [[NSString alloc] initWithUTF8String:functionName]; - // NSLog 一下 __FUNCTION__ 就知道为什么这么截取了。 + NSRange blankRange = [fn rangeOfString:@":"]; NSUInteger start = blankRange.location + 1; NSUInteger length; @@ -28,7 +26,7 @@ } NSString *fromatParamKeys = [fn substringWithRange:NSMakeRange(start, length)]; - // 构造请求的 NSMutableDictionary *params 。 + NSMutableDictionary *params = [NSMutableDictionary dictionary]; NSArray *paramKeys = [fromatParamKeys componentsSeparatedByString:@":"]; @@ -43,98 +41,71 @@ } + (void)getUserInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9nZXQ="];///user/get + NSString * fang = [NSString stringFromBase64String:@"dXNlci9nZXQ="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; } + (void)getUserInfos:(HttpRequestHelperCompletion)completion uids:(NSString *)uids { - NSString * fang = [NSString stringFromBase64String:@"dXNlci9saXN0"];///user/list + NSString * fang = [NSString stringFromBase64String:@"dXNlci9saXN0"]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uids, nil]; } +(void)testMsg:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket{ [self makeRequest:@"user/testMsg" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,uid,ticket, nil]; } -/// 获取手机号的验证码 -/// @param completion 请求完成 -/// @param mobile 手机号 -/// @param type 类型 请看XPEunm中的枚举 + + + (void)phoneSmsCode:(HttpRequestHelperCompletion)completion mobile:(NSString *)mobile type:(NSString *)type phoneAreaCode:(NSString *)phoneAreaCode { - NSString * fang = [NSString stringFromBase64String:@"c21zL2dldENvZGU="];///sms/getCode + NSString * fang = [NSString stringFromBase64String:@"c21zL2dldENvZGU="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, mobile, type, phoneAreaCode,nil]; } -/// 校验手机号码 -/// @param completion 完成 -/// @param mobile 手机号 -/// @param code 验证码 -/// @param uid 用户的uid -/// @param ticket ticket + + (void)checkMoblieCode:(HttpRequestHelperCompletion)completion mobile:(NSString *)mobile code:(NSString *)code uid:(NSString *)uid ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode{ - NSString * fang = [NSString stringFromBase64String:@"c21zL3ZlcmlmeQ=="];///sms/verify + NSString * fang = [NSString stringFromBase64String:@"c21zL3ZlcmlmeQ=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, mobile, code, uid, ticket,phoneAreaCode,nil]; } -/// 补全用户资料 -/// @param completion 完成 -/// @param userInfo 需要更新的用户信息 + + (void)completeUserInfo:(HttpRequestHelperCompletion)completion userInfo:(NSDictionary *)userInfo { - NSString * fang = [NSString stringFromBase64String:@"dXNlci92Mi91cGRhdGU="];///user/v2/update + NSString * fang = [NSString stringFromBase64String:@"dXNlci92Mi91cGRhdGU="]; [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:userInfo completion:completion]; } -/// 获取用户钱包余额信息 -/// @param completion 完成 -/// @param uid 用户uid -/// @param ticket ticketg + (void)getUserWalletInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket { - NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnk="];///purse/query + NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnk="]; [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, ticket,nil]; } -/// 批量验证 -/// @param completion 完成 -/// @param transcationIdStr 需要验证的数据 + + (void)requestCheckTranscationIds:(HttpRequestHelperCompletion)completion transcationIdStr:(NSString *)transcationIdStr { - NSString * fang = [NSString stringFromBase64String:@"dmVyaWZ5L2NoZWNrSU9TQ2hhcmdlUmVjb3Jk"];///verify/checkIOSChargeRecord + NSString * fang = [NSString stringFromBase64String:@"dmVyaWZ5L2NoZWNrSU9TQ2hhcmdlUmVjb3Jk"]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,transcationIdStr, nil]; } -/// 锁麦/开麦 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param state 0 开麦 1 锁麦 -/// @param position 坑位 -/// @param ticket 用户的ticket -/// @param uid uid + + (void)microMuteCompletion:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid state:(NSString *)state position:(NSString *)position ticket:(NSString *)ticket uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"cm9vbS9taWMvbG9ja21pYw=="];///@"room/mic/lockmic" + NSString * fang = [NSString stringFromBase64String:@"cm9vbS9taWMvbG9ja21pYw=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, state, position, ticket, uid, nil]; } -/// 锁坑/开锁 -/// @param completion 完成 -/// @param roomUid 房主的uid -/// @param state 1锁坑位,0取消锁(即取消锁坑位) -/// @param position 坑位 -/// @param ticket 用户的ticket -/// @param uid uid + + (void)microLockCompletion:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid state:(NSString *)state position:(NSString *)position ticket:(NSString *)ticket uid:(NSString *)uid { - NSString * fang = [NSString stringFromBase64String:@"cm9vbS9taWMvbG9ja3Bvcw=="];///room/mic/lockpos + NSString * fang = [NSString stringFromBase64String:@"cm9vbS9taWMvbG9ja3Bvcw=="]; [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, state, position, ticket, uid, nil]; } -//充值banner位 + +(void)requestBannerListCompletion:(HttpRequestHelperCompletion)completion{ [self makeRequest:@"charge/guide/banner" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } -//联系客服 + +(void)requestContactCustomerServiceCompletion:(HttpRequestHelperCompletion)completion{ [self makeRequest:@"charge/guide/contact" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; } diff --git a/YuMi/Structure/MVP/Api/Api.m.backup b/YuMi/Structure/MVP/Api/Api.m.backup new file mode 100644 index 0000000..2553549 --- /dev/null +++ b/YuMi/Structure/MVP/Api/Api.m.backup @@ -0,0 +1,158 @@ +// +// Api.m +// YUMI +// +// Created by zu on 2021/9/6. +// + +#import "Api.h" +#import +@implementation Api ++ (void)makeRequest:(NSString *)route method:(HttpRequestHelperMethod)method completion:(HttpRequestHelperCompletion)completion, ... { + va_list arg_lists; + va_start(arg_lists, completion); + + // 获取第一个参数 __FUNCTION__ ,然后解析出来 key 。 + const char *functionName = va_arg(arg_lists, const char *); + NSString *fn = [[NSString alloc] initWithUTF8String:functionName]; + // NSLog 一下 __FUNCTION__ 就知道为什么这么截取了。 + NSRange blankRange = [fn rangeOfString:@":"]; + NSUInteger start = blankRange.location + 1; + NSUInteger length; + if ((start + 2) < fn.length) { + length = fn.length - start - 2; + } else if ((start + 1) < fn.length) { + length = fn.length -start - 1; + } else { + length = fn.length -start; + } + + NSString *fromatParamKeys = [fn substringWithRange:NSMakeRange(start, length)]; + // 构造请求的 NSMutableDictionary *params 。 + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + + NSArray *paramKeys = [fromatParamKeys componentsSeparatedByString:@":"]; + NSEnumerator *enumerator = [paramKeys objectEnumerator]; + NSString *value = nil; + while((value = va_arg(arg_lists, NSString*))){ + [params setValue:value forKey:enumerator.nextObject]; + }; + va_end(arg_lists); + + [HttpRequestHelper request:route method:method params:params completion:completion]; +} + ++ (void)getUserInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9nZXQ="];///user/get + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil]; +} + ++ (void)getUserInfos:(HttpRequestHelperCompletion)completion uids:(NSString *)uids { + NSString * fang = [NSString stringFromBase64String:@"dXNlci9saXN0"];///user/list + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uids, nil]; +} ++(void)testMsg:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket{ + + [self makeRequest:@"user/testMsg" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,uid,ticket, nil]; +} +/// 获取手机号的验证码 +/// @param completion 请求完成 +/// @param mobile 手机号 +/// @param type 类型 请看XPEunm中的枚举 ++ (void)phoneSmsCode:(HttpRequestHelperCompletion)completion mobile:(NSString *)mobile type:(NSString *)type phoneAreaCode:(NSString *)phoneAreaCode { + NSString * fang = [NSString stringFromBase64String:@"c21zL2dldENvZGU="];///sms/getCode + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, mobile, type, phoneAreaCode,nil]; +} + +/// 校验手机号码 +/// @param completion 完成 +/// @param mobile 手机号 +/// @param code 验证码 +/// @param uid 用户的uid +/// @param ticket ticket ++ (void)checkMoblieCode:(HttpRequestHelperCompletion)completion + mobile:(NSString *)mobile + code:(NSString *)code + uid:(NSString *)uid + ticket:(NSString *)ticket phoneAreaCode:(NSString *)phoneAreaCode{ + NSString * fang = [NSString stringFromBase64String:@"c21zL3ZlcmlmeQ=="];///sms/verify + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, mobile, code, uid, ticket,phoneAreaCode,nil]; +} + +/// 补全用户资料 +/// @param completion 完成 +/// @param userInfo 需要更新的用户信息 ++ (void)completeUserInfo:(HttpRequestHelperCompletion)completion + userInfo:(NSDictionary *)userInfo { + NSString * fang = [NSString stringFromBase64String:@"dXNlci92Mi91cGRhdGU="];///user/v2/update + [HttpRequestHelper request:fang method:HttpRequestHelperMethodPOST params:userInfo completion:completion]; +} + + +/// 获取用户钱包余额信息 +/// @param completion 完成 +/// @param uid 用户uid +/// @param ticket ticketg ++ (void)getUserWalletInfo:(HttpRequestHelperCompletion)completion uid:(NSString *)uid ticket:(NSString *)ticket { + NSString * fang = [NSString stringFromBase64String:@"cHVyc2UvcXVlcnk="];///purse/query + [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, ticket,nil]; +} + +/// 批量验证 +/// @param completion 完成 +/// @param transcationIdStr 需要验证的数据 ++ (void)requestCheckTranscationIds:(HttpRequestHelperCompletion)completion + transcationIdStr:(NSString *)transcationIdStr { + NSString * fang = [NSString stringFromBase64String:@"dmVyaWZ5L2NoZWNrSU9TQ2hhcmdlUmVjb3Jk"];///verify/checkIOSChargeRecord + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,transcationIdStr, nil]; +} + +/// 锁麦/开麦 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param state 0 开麦 1 锁麦 +/// @param position 坑位 +/// @param ticket 用户的ticket +/// @param uid uid ++ (void)microMuteCompletion:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid state:(NSString *)state position:(NSString *)position ticket:(NSString *)ticket uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"cm9vbS9taWMvbG9ja21pYw=="];///@"room/mic/lockmic" + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, state, position, ticket, uid, nil]; +} + +/// 锁坑/开锁 +/// @param completion 完成 +/// @param roomUid 房主的uid +/// @param state 1锁坑位,0取消锁(即取消锁坑位) +/// @param position 坑位 +/// @param ticket 用户的ticket +/// @param uid uid ++ (void)microLockCompletion:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid state:(NSString *)state position:(NSString *)position ticket:(NSString *)ticket uid:(NSString *)uid { + NSString * fang = [NSString stringFromBase64String:@"cm9vbS9taWMvbG9ja3Bvcw=="];///room/mic/lockpos + [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, state, position, ticket, uid, nil]; +} +//充值banner位 ++(void)requestBannerListCompletion:(HttpRequestHelperCompletion)completion{ + [self makeRequest:@"charge/guide/banner" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} +//联系客服 ++(void)requestContactCustomerServiceCompletion:(HttpRequestHelperCompletion)completion{ + [self makeRequest:@"charge/guide/contact" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++ (void)requestAllRegionInfoCompletion:(HttpRequestHelperCompletion)completion { + [self makeRequest:@"regionInfo/listAll" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil]; +} + ++ (void)requestBossMicUp:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid uid:(NSString *)uid { + [self makeRequest:@"room/bossMic/up" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, roomUid, uid, nil]; +} + ++ (void)shareGetInfo:(HttpRequestHelperCompletion)completion code:(NSString *)code { + [self makeRequest:@"share/getInfo" + method:HttpRequestHelperMethodGET + completion:completion, + __FUNCTION__, + code, nil]; +} + +@end diff --git a/YuMi/Structure/MVP/Model/AccountInfoStorage.h b/YuMi/Structure/MVP/Model/AccountInfoStorage.h index ad699c6..787ed85 100644 --- a/YuMi/Structure/MVP/Model/AccountInfoStorage.h +++ b/YuMi/Structure/MVP/Model/AccountInfoStorage.h @@ -1,40 +1,38 @@ -// -// DataUtils.h -// YYFaceAuth -// -// Created by chenran on 16/10/18. -// Copyright © 2016年 zhangji. All rights reserved. -// - -#import - -@class AccountModel, ThirdUserInfo, HomeTagModel,HomeUserModel; -@interface AccountInfoStorage : NSObject - -@property (nonatomic, strong, readonly) AccountModel *accountModel; -@property(nonatomic,copy) NSString *name;///判断帐号是否填写资料 -///判断是否正在请求ticket,yes的话,不能用ticket请求数据,不然会出现401,要重新登录 -@property (nonatomic,assign) BOOL isRequestTicket; -///如果是第三方登录的话 保存一下用户信息 -@property (nonatomic,strong) ThirdUserInfo *thirdUserInfo; -@property(nonatomic,assign) BOOL isNative; -+ (instancetype)instance; - -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; -- (id)copy NS_UNAVAILABLE; -- (id)mutableCopy NS_UNAVAILABLE; - -- (AccountModel *)getCurrentAccountInfo; -- (void)saveAccountInfo:(AccountModel *)accountInfo; -///用于判断是否填写用户资料,没有将跳到用户填写用户资料界面 -- (HomeUserModel *)getCurrentHomeUserInfo; -- (void)saveHomeUserInfo:(HomeUserModel *)homeUserInfo; -- (void)saveTicket:(NSString *)ticket; -- (NSString *)getTicket; -- (NSString *)getUid; - -///首页的tag列表,增加缓存,加快加载速度的优化 -- (NSArray *)getCurrentTagList; -- (void)saveTagList:(NSArray *)tagList; -@end + + +// Created by chenran on 16/10/18. +// Copyright © 2016年 zhangji. All rights reserved. + + +#import + +@class AccountModel, ThirdUserInfo, HomeTagModel,HomeUserModel; +@interface AccountInfoStorage : NSObject + +@property (nonatomic, strong, readonly) AccountModel *accountModel; +@property(nonatomic,copy) NSString *name; + +@property (nonatomic,assign) BOOL isRequestTicket; + +@property (nonatomic,strong) ThirdUserInfo *thirdUserInfo; +@property(nonatomic,assign) BOOL isNative; ++ (instancetype)instance; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (id)copy NS_UNAVAILABLE; +- (id)mutableCopy NS_UNAVAILABLE; + +- (AccountModel *)getCurrentAccountInfo; +- (void)saveAccountInfo:(AccountModel *)accountInfo; + +- (HomeUserModel *)getCurrentHomeUserInfo; +- (void)saveHomeUserInfo:(HomeUserModel *)homeUserInfo; +- (void)saveTicket:(NSString *)ticket; +- (NSString *)getTicket; +- (NSString *)getUid; + + +- (NSArray *)getCurrentTagList; +- (void)saveTagList:(NSArray *)tagList; +@end diff --git a/YuMi/Structure/MVP/Model/AccountInfoStorage.h.backup b/YuMi/Structure/MVP/Model/AccountInfoStorage.h.backup new file mode 100644 index 0000000..ad699c6 --- /dev/null +++ b/YuMi/Structure/MVP/Model/AccountInfoStorage.h.backup @@ -0,0 +1,40 @@ +// +// DataUtils.h +// YYFaceAuth +// +// Created by chenran on 16/10/18. +// Copyright © 2016年 zhangji. All rights reserved. +// + +#import + +@class AccountModel, ThirdUserInfo, HomeTagModel,HomeUserModel; +@interface AccountInfoStorage : NSObject + +@property (nonatomic, strong, readonly) AccountModel *accountModel; +@property(nonatomic,copy) NSString *name;///判断帐号是否填写资料 +///判断是否正在请求ticket,yes的话,不能用ticket请求数据,不然会出现401,要重新登录 +@property (nonatomic,assign) BOOL isRequestTicket; +///如果是第三方登录的话 保存一下用户信息 +@property (nonatomic,strong) ThirdUserInfo *thirdUserInfo; +@property(nonatomic,assign) BOOL isNative; ++ (instancetype)instance; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (id)copy NS_UNAVAILABLE; +- (id)mutableCopy NS_UNAVAILABLE; + +- (AccountModel *)getCurrentAccountInfo; +- (void)saveAccountInfo:(AccountModel *)accountInfo; +///用于判断是否填写用户资料,没有将跳到用户填写用户资料界面 +- (HomeUserModel *)getCurrentHomeUserInfo; +- (void)saveHomeUserInfo:(HomeUserModel *)homeUserInfo; +- (void)saveTicket:(NSString *)ticket; +- (NSString *)getTicket; +- (NSString *)getUid; + +///首页的tag列表,增加缓存,加快加载速度的优化 +- (NSArray *)getCurrentTagList; +- (void)saveTagList:(NSArray *)tagList; +@end diff --git a/YuMi/Structure/MVP/Model/AccountInfoStorage.m b/YuMi/Structure/MVP/Model/AccountInfoStorage.m index ce2a983..4618afb 100644 --- a/YuMi/Structure/MVP/Model/AccountInfoStorage.m +++ b/YuMi/Structure/MVP/Model/AccountInfoStorage.m @@ -1,10 +1,8 @@ -// -// DataUtils.m -// YYFaceAuth -// + + // Created by chenran on 16/10/18. // Copyright © 2016年 zhangji. All rights reserved. -// + #define kFileName @"AccountInfo.data" #define kDataKey @"accountInfo" #define kHomeUserDataKey @"homeUserInfo" @@ -63,9 +61,9 @@ static AccountInfoStorage *_instance = nil; } NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; - //解档出数据模型 + self.accountModel = [unarchiver decodeObjectForKey:kDataKey]; - [unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错 + [unarchiver finishDecoding]; return self.accountModel; } @@ -89,9 +87,9 @@ static AccountInfoStorage *_instance = nil; NSData *data = [[NSData alloc] initWithContentsOfFile:[self getHomeUserFilePath]]; NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; - //解档出数据模型 + self.homeUserInfo = [unarchiver decodeObjectForKey:kHomeUserDataKey]; - [unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错 + [unarchiver finishDecoding]; return self.homeUserInfo; } - (void)saveHomeUserInfo:(HomeUserModel *)homeUserInfo @@ -143,9 +141,9 @@ static AccountInfoStorage *_instance = nil; NSData *data = [[NSData alloc] initWithContentsOfFile:[self getTagListFilePath]]; NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; - //解档出数据模型 + self.tagList = [unarchiver decodeObjectForKey:kTagListDataKey]; - [unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错 + [unarchiver finishDecoding]; return self.tagList != nil ? self.tagList : @[]; } - (void)saveTagList:(NSArray *)tagList{ diff --git a/YuMi/Structure/MVP/Model/AccountInfoStorage.m.backup b/YuMi/Structure/MVP/Model/AccountInfoStorage.m.backup new file mode 100644 index 0000000..ce2a983 --- /dev/null +++ b/YuMi/Structure/MVP/Model/AccountInfoStorage.m.backup @@ -0,0 +1,171 @@ +// +// DataUtils.m +// YYFaceAuth +// +// Created by chenran on 16/10/18. +// Copyright © 2016年 zhangji. All rights reserved. +// +#define kFileName @"AccountInfo.data" +#define kDataKey @"accountInfo" +#define kHomeUserDataKey @"homeUserInfo" +#define kHomeUserName @"HomeUserModel.data" + +#import "AccountInfoStorage.h" +#import "AccountModel.h" + + +#define kTagListDataKey @"homeaaNewTagModel" +#define kTagListDataName @"HomeTagNewModel.data" +@interface AccountInfoStorage() +@property (nonatomic,strong) HomeUserModel *homeUserInfo; +@property (nonatomic, copy) NSString *ticket; +@property (nonatomic, strong) AccountModel *accountModel; +@property (nonatomic,strong) NSArray *tagList; +@end + +@implementation AccountInfoStorage + +static AccountInfoStorage *_instance = nil; + ++ (AccountInfoStorage *)instance { + + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + _instance = [[self alloc] init]; + }) ; + + return _instance; +} + +-(NSString *) getFilePath{ + NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *path = [[array objectAtIndex:0] stringByAppendingPathComponent:kFileName]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil]; + } + return path; +} + +- (AccountModel *)getCurrentAccountInfo +{ + if (self.accountModel != nil) { + return self.accountModel; + } + + if ([[NSFileManager defaultManager] fileExistsAtPath:[self getFilePath]] == NO) { + return nil; + } + + NSData *data = [[NSData alloc] initWithContentsOfFile:[self getFilePath]]; + if (data == nil) { + return nil; + } + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + //解档出数据模型 + self.accountModel = [unarchiver decodeObjectForKey:kDataKey]; + [unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错 + return self.accountModel; +} + +- (void)saveAccountInfo:(AccountModel *)accountInfo +{ + if (accountInfo == nil) { + accountInfo = [[AccountModel alloc] init]; + } + self.accountModel = accountInfo; + NSMutableData *data = [[NSMutableData alloc] init]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [archiver encodeObject:accountInfo forKey:kDataKey]; + [archiver finishEncoding]; + [data writeToFile:[self getFilePath] atomically:YES]; +} +- (HomeUserModel *)getCurrentHomeUserInfo +{ + if (self.homeUserInfo != nil) { + return self.homeUserInfo; + } + NSData *data = [[NSData alloc] initWithContentsOfFile:[self getHomeUserFilePath]]; + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + //解档出数据模型 + self.homeUserInfo = [unarchiver decodeObjectForKey:kHomeUserDataKey]; + [unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错 + return self.homeUserInfo; +} +- (void)saveHomeUserInfo:(HomeUserModel *)homeUserInfo +{ + if (homeUserInfo == nil) { + homeUserInfo = [[HomeUserModel alloc] init]; + } + self.homeUserInfo = homeUserInfo; + NSMutableData *data = [[NSMutableData alloc] init]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [archiver encodeObject:homeUserInfo forKey:kHomeUserDataKey]; + [archiver finishEncoding]; + [data writeToFile:[self getHomeUserFilePath] atomically:YES]; +} +-(NSString *) getHomeUserFilePath{ + NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *path = [[array objectAtIndex:0] stringByAppendingPathComponent:kHomeUserName]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil]; + } + return path; +} +- (void)saveTicket:(NSString *)t +{ + self.ticket = t; +} + +- (NSString *)getTicket +{ + if (self.ticket == nil) { + return @""; + } + return self.ticket; +} + +- (NSString *)getUid +{ + AccountModel *am = [self getCurrentAccountInfo]; + if (am == nil) { + return @""; + } + return am.uid; +} + +- (NSArray *)getCurrentTagList{ + if (self.tagList != nil) { + return self.tagList; + } + NSData *data = [[NSData alloc] initWithContentsOfFile:[self getTagListFilePath]]; + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + //解档出数据模型 + self.tagList = [unarchiver decodeObjectForKey:kTagListDataKey]; + [unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错 + return self.tagList != nil ? self.tagList : @[]; +} +- (void)saveTagList:(NSArray *)tagList{ + if(tagList == nil){ + tagList = @[]; + } + self.tagList = tagList; + NSMutableData *data = [[NSMutableData alloc] init]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [archiver encodeObject:tagList forKey:kTagListDataKey]; + [archiver finishEncoding]; + [data writeToFile:[self getTagListFilePath] atomically:YES]; +} + +-(NSString *) getTagListFilePath{ + NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *path = [[array objectAtIndex:0] stringByAppendingPathComponent:kTagListDataName]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil]; + } + return path; +} +@end diff --git a/YuMi/Structure/MVP/Model/AccountModel.h b/YuMi/Structure/MVP/Model/AccountModel.h index 44751c6..99500e3 100644 --- a/YuMi/Structure/MVP/Model/AccountModel.h +++ b/YuMi/Structure/MVP/Model/AccountModel.h @@ -1,9 +1,7 @@ -// -// TokenModel.h -// YUMI -// + + // Created by zu on 2021/9/8. -// + #import "NSObject+MJExtension.h" diff --git a/YuMi/Structure/MVP/Model/AccountModel.h.backup b/YuMi/Structure/MVP/Model/AccountModel.h.backup new file mode 100644 index 0000000..44751c6 --- /dev/null +++ b/YuMi/Structure/MVP/Model/AccountModel.h.backup @@ -0,0 +1,31 @@ +// +// TokenModel.h +// YUMI +// +// Created by zu on 2021/9/8. +// + +#import "NSObject+MJExtension.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface AccountModel : PIBaseModel + +@property (nonatomic , copy) NSString *uid; +@property (nonatomic , copy) NSString *jti; +@property (nonatomic , copy) NSString *token_type; +@property (nonatomic , copy) NSString *refresh_token; +@property (nonatomic , copy) NSString *netEaseToken; +@property (nonatomic , copy) NSString *access_token; +@property (nonatomic , copy) NSNumber *expires_in; + +@end +@interface HomeUserModel : PIBaseModel +@property (nonatomic,copy)NSString *nick; +@property (nonatomic,copy)NSString *avatar; +@property (nonatomic,assign)BOOL isBindPhone; +@property (nonatomic,copy) NSString *ticket; +@property (nonatomic,assign) BOOL isGetUserInfoSuccess; + +@end +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Model/AccountModel.m b/YuMi/Structure/MVP/Model/AccountModel.m index 331487a..dfd9c2d 100644 --- a/YuMi/Structure/MVP/Model/AccountModel.m +++ b/YuMi/Structure/MVP/Model/AccountModel.m @@ -1,9 +1,7 @@ -// -// TokenModel.m -// YUMI -// + + // Created by zu on 2021/9/8. -// + #import "AccountModel.h" diff --git a/YuMi/Structure/MVP/Model/AccountModel.m.backup b/YuMi/Structure/MVP/Model/AccountModel.m.backup new file mode 100644 index 0000000..331487a --- /dev/null +++ b/YuMi/Structure/MVP/Model/AccountModel.m.backup @@ -0,0 +1,15 @@ +// +// TokenModel.m +// YUMI +// +// Created by zu on 2021/9/8. +// + +#import "AccountModel.h" + +@implementation AccountModel + +@end +@implementation HomeUserModel + +@end diff --git a/YuMi/Structure/MVP/Model/BaseModel.h b/YuMi/Structure/MVP/Model/BaseModel.h index b9e7606..6d89a9c 100644 --- a/YuMi/Structure/MVP/Model/BaseModel.h +++ b/YuMi/Structure/MVP/Model/BaseModel.h @@ -1,9 +1,7 @@ -// -// BaseModel.h -// YUMI -// + + // Created by zu on 2021/9/8. -// + #import "NSObject+MJExtension.h" @@ -14,12 +12,12 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic , strong) id data; @property (nonatomic , assign) NSInteger code; @property (nonatomic , copy) NSString * message; -///注销的时间戳 因为后端返回的内容和code在同一层级 安卓已经发出去了 兼容就写在这里吧 请不要模仿 + @property (nonatomic,assign) long long cancelDate; -///账号封禁返回的code -///时间 + + @property (nonatomic,copy) NSString * date; -///封禁的理由 + @property (nonatomic,copy) NSString *reason; @end diff --git a/YuMi/Structure/MVP/Model/BaseModel.h.backup b/YuMi/Structure/MVP/Model/BaseModel.h.backup new file mode 100644 index 0000000..b9e7606 --- /dev/null +++ b/YuMi/Structure/MVP/Model/BaseModel.h.backup @@ -0,0 +1,26 @@ +// +// BaseModel.h +// YUMI +// +// Created by zu on 2021/9/8. +// + +#import "NSObject+MJExtension.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface BaseModel : NSObject +@property(nonatomic,assign) long timestamp; +@property (nonatomic , strong) id data; +@property (nonatomic , assign) NSInteger code; +@property (nonatomic , copy) NSString * message; +///注销的时间戳 因为后端返回的内容和code在同一层级 安卓已经发出去了 兼容就写在这里吧 请不要模仿 +@property (nonatomic,assign) long long cancelDate; +///账号封禁返回的code +///时间 +@property (nonatomic,copy) NSString * date; +///封禁的理由 +@property (nonatomic,copy) NSString *reason; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Model/BaseModel.m b/YuMi/Structure/MVP/Model/BaseModel.m index f532d96..a75dba0 100644 --- a/YuMi/Structure/MVP/Model/BaseModel.m +++ b/YuMi/Structure/MVP/Model/BaseModel.m @@ -1,9 +1,7 @@ -// -// BaseModel.m -// YUMI -// + + // Created by zu on 2021/9/8. -// + #import "BaseModel.h" diff --git a/YuMi/Structure/MVP/Model/BaseModel.m.backup b/YuMi/Structure/MVP/Model/BaseModel.m.backup new file mode 100644 index 0000000..f532d96 --- /dev/null +++ b/YuMi/Structure/MVP/Model/BaseModel.m.backup @@ -0,0 +1,12 @@ +// +// BaseModel.m +// YUMI +// +// Created by zu on 2021/9/8. +// + +#import "BaseModel.h" + +@implementation BaseModel + +@end diff --git a/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h index 76b615f..01be5a9 100644 --- a/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h +++ b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h @@ -1,25 +1,23 @@ -// -// NSObject+AutoCoding.h -// YYMobileFramework -// -// Created by wuwei on 14/6/13. -// Copyright (c) 2014年 YY Inc. All rights reserved. -// - -#import - -@interface NSObject (AutoCoding) - -// Coding -+ (NSDictionary *)codableProperties; -- (void)setWithCoder:(NSCoder *)aDecoder; - -// Properties access -- (NSDictionary *)codableProperties; -- (NSDictionary *)dictionaryRepresentation; - -// Loading / Saving -+ (instancetype)objectWithContentsOfFile:(NSString *)path; -- (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile; - + + +// Created by wuwei on 14/6/13. +// Copyright (c) 2014年 YY Inc. All rights reserved. + + +#import + +@interface NSObject (AutoCoding) + + ++ (NSDictionary *)codableProperties; +- (void)setWithCoder:(NSCoder *)aDecoder; + + +- (NSDictionary *)codableProperties; +- (NSDictionary *)dictionaryRepresentation; + + ++ (instancetype)objectWithContentsOfFile:(NSString *)path; +- (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile; + @end \ No newline at end of file diff --git a/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h.backup b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h.backup new file mode 100644 index 0000000..76b615f --- /dev/null +++ b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.h.backup @@ -0,0 +1,25 @@ +// +// NSObject+AutoCoding.h +// YYMobileFramework +// +// Created by wuwei on 14/6/13. +// Copyright (c) 2014年 YY Inc. All rights reserved. +// + +#import + +@interface NSObject (AutoCoding) + +// Coding ++ (NSDictionary *)codableProperties; +- (void)setWithCoder:(NSCoder *)aDecoder; + +// Properties access +- (NSDictionary *)codableProperties; +- (NSDictionary *)dictionaryRepresentation; + +// Loading / Saving ++ (instancetype)objectWithContentsOfFile:(NSString *)path; +- (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile; + +@end \ No newline at end of file diff --git a/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m index 6045f37..eb78a72 100644 --- a/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m +++ b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m @@ -1,10 +1,8 @@ -// -// NSObject+AutoCoding.m -// YYMobileFramework -// + + // Created by wuwei on 14/6/13. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import "NSObject+AutoCoding.h" #import @@ -22,20 +20,20 @@ static NSString *const AutocodingException = @"AutocodingException"; + (instancetype)objectWithContentsOfFile:(NSString *)filePath { - //load the file + NSData *data = [NSData dataWithContentsOfFile:filePath]; - //attempt to deserialise data as a plist + id object = nil; if (data) { NSPropertyListFormat format; object = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:NULL]; - //success? + if (object) { - //check if object is an NSCoded unarchive + if ([object respondsToSelector:@selector(objectForKey:)] && [(NSDictionary *)object objectForKey:@"$archiver"]) { object = [NSKeyedUnarchiver unarchiveObjectWithData:data]; @@ -43,22 +41,19 @@ static NSString *const AutocodingException = @"AutocodingException"; } else { - //return raw data + object = data; } } - //return object + return object; } - (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile { - //note: NSData, NSDictionary and NSArray already implement this method - //and do not save using NSCoding, however the objectWithContentsOfFile - //method will correctly recover these objects anyway - //archive object + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; return [data writeToFile:filePath atomically:useAuxiliaryFile]; } @@ -70,13 +65,12 @@ static NSString *const AutocodingException = @"AutocodingException"; objc_property_t *properties = class_copyPropertyList(self, &propertyCount); for (unsigned int i = 0; i < propertyCount; i++) { - //get property name + objc_property_t property = properties[i]; const char *propertyName = property_getName(property); __autoreleasing NSString *key = @(propertyName); - //check if codable - //get property type + Class propertyClass = nil; char *typeEncoding = property_copyAttributeValue(property, "T"); switch (typeEncoding[0]) @@ -126,27 +120,27 @@ static NSString *const AutocodingException = @"AutocodingException"; if (propertyClass && [propertyClass conformsToProtocol:@protocol(NSSecureCoding)]) { - //check if there is a backing ivar + char *ivar = property_copyAttributeValue(property, "V"); if (ivar) { - //check if ivar has KVC-compliant name + __autoreleasing NSString *ivarName = @(ivar); if ([ivarName isEqualToString:key] || [ivarName isEqualToString:[@"_" stringByAppendingString:key]]) { - //no setter, but setValue:forKey: will still work + codableProperties[key] = propertyClass; } free(ivar); } else { - //check if property is dynamic and readwrite + char *dynamic = property_copyAttributeValue(property, "D"); char *readonly = property_copyAttributeValue(property, "R"); if (dynamic && !readonly) { - //no ivar, but setValue:forKey: will still work + codableProperties[key] = propertyClass; } free(dynamic); @@ -173,7 +167,7 @@ static NSString *const AutocodingException = @"AutocodingException"; } codableProperties = [NSDictionary dictionaryWithDictionary:codableProperties]; - //make the association atomically so that we don't need to bother with an @synchronize + objc_setAssociatedObject([self class], _cmd, codableProperties, OBJC_ASSOCIATION_RETAIN); } return codableProperties; diff --git a/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m.backup b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m.backup new file mode 100644 index 0000000..6045f37 --- /dev/null +++ b/YuMi/Structure/MVP/Model/NSObject+AutoCoding.m.backup @@ -0,0 +1,245 @@ +// +// NSObject+AutoCoding.m +// YYMobileFramework +// +// Created by wuwei on 14/6/13. +// Copyright (c) 2014年 YY Inc. All rights reserved. +// + +#import "NSObject+AutoCoding.h" +#import + +#pragma GCC diagnostic ignored "-Wgnu" + +static NSString *const AutocodingException = @"AutocodingException"; + +@implementation NSObject (AutoCoding) + ++ (BOOL)supportsSecureCoding +{ + return YES; +} + ++ (instancetype)objectWithContentsOfFile:(NSString *)filePath +{ + //load the file + NSData *data = [NSData dataWithContentsOfFile:filePath]; + + //attempt to deserialise data as a plist + id object = nil; + if (data) + { + NSPropertyListFormat format; + object = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:NULL]; + + //success? + if (object) + { + //check if object is an NSCoded unarchive + if ([object respondsToSelector:@selector(objectForKey:)] && [(NSDictionary *)object objectForKey:@"$archiver"]) + { + object = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + } + } + else + { + //return raw data + object = data; + } + } + + //return object + return object; +} + +- (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile +{ + //note: NSData, NSDictionary and NSArray already implement this method + //and do not save using NSCoding, however the objectWithContentsOfFile + //method will correctly recover these objects anyway + + //archive object + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; + return [data writeToFile:filePath atomically:useAuxiliaryFile]; +} + ++ (NSDictionary *)codableProperties +{ + unsigned int propertyCount; + __autoreleasing NSMutableDictionary *codableProperties = [NSMutableDictionary dictionary]; + objc_property_t *properties = class_copyPropertyList(self, &propertyCount); + for (unsigned int i = 0; i < propertyCount; i++) + { + //get property name + objc_property_t property = properties[i]; + const char *propertyName = property_getName(property); + __autoreleasing NSString *key = @(propertyName); + + //check if codable + //get property type + Class propertyClass = nil; + char *typeEncoding = property_copyAttributeValue(property, "T"); + switch (typeEncoding[0]) + { + case '@': + { + if (strlen(typeEncoding) >= 3) + { + char *className = strndup(typeEncoding + 2, strlen(typeEncoding) - 3); + __autoreleasing NSString *name = @(className); + NSRange range = [name rangeOfString:@"<"]; + if (range.location != NSNotFound) + { + name = [name substringToIndex:range.location]; + } + propertyClass = NSClassFromString(name) ?: [NSObject class]; + free(className); + } + break; + } + case 'c': + case 'i': + case 's': + case 'l': + case 'q': + case 'C': + case 'I': + case 'S': + case 'L': + case 'Q': + case 'f': + case 'd': + case 'B': + { + propertyClass = [NSNumber class]; + break; + } + case '{': + { + propertyClass = [NSValue class]; + break; + } + default: + break; + } + free(typeEncoding); + + if (propertyClass && [propertyClass conformsToProtocol:@protocol(NSSecureCoding)]) + { + //check if there is a backing ivar + char *ivar = property_copyAttributeValue(property, "V"); + if (ivar) + { + //check if ivar has KVC-compliant name + __autoreleasing NSString *ivarName = @(ivar); + if ([ivarName isEqualToString:key] || [ivarName isEqualToString:[@"_" stringByAppendingString:key]]) + { + //no setter, but setValue:forKey: will still work + codableProperties[key] = propertyClass; + } + free(ivar); + } + else + { + //check if property is dynamic and readwrite + char *dynamic = property_copyAttributeValue(property, "D"); + char *readonly = property_copyAttributeValue(property, "R"); + if (dynamic && !readonly) + { + //no ivar, but setValue:forKey: will still work + codableProperties[key] = propertyClass; + } + free(dynamic); + free(readonly); + } + } + } + + free(properties); + return codableProperties; +} + +- (NSDictionary *)codableProperties +{ + __autoreleasing NSDictionary *codableProperties = objc_getAssociatedObject([self class], _cmd); + if (!codableProperties) + { + codableProperties = [NSMutableDictionary dictionary]; + Class subclass = [self class]; + while (subclass != [NSObject class]) + { + [(NSMutableDictionary *)codableProperties addEntriesFromDictionary:[subclass codableProperties]]; + subclass = [subclass superclass]; + } + codableProperties = [NSDictionary dictionaryWithDictionary:codableProperties]; + + //make the association atomically so that we don't need to bother with an @synchronize + objc_setAssociatedObject([self class], _cmd, codableProperties, OBJC_ASSOCIATION_RETAIN); + } + return codableProperties; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + for (__unsafe_unretained NSString *key in [self codableProperties]) + { + id value = [self valueForKey:key]; + if (value) + dict[key] = value; + else + dict[key] = @"nil"; + } + return dict; +} + +- (void)setWithCoder:(NSCoder *)aDecoder +{ + BOOL secureAvailable = [aDecoder respondsToSelector:@selector(decodeObjectOfClass:forKey:)]; + BOOL secureSupported = [[self class] supportsSecureCoding]; + NSDictionary *properties = [self codableProperties]; + for (NSString *key in properties) + { + id object = nil; + Class propertyClass = properties[key]; + if (secureAvailable) + { + if ([propertyClass isEqual:[NSMutableAttributedString class]]) { + continue; + } + object = [aDecoder decodeObjectOfClass:propertyClass forKey:key]; + } + else + { + if ([propertyClass isEqual:[NSMutableAttributedString class]]) { + continue; + } + object = [aDecoder decodeObjectForKey:key]; + } + if (object) + { + if (secureSupported && ![object isKindOfClass:propertyClass]) + { + [NSException raise:AutocodingException format:@"Expected '%@' to be a %@, but was actually a %@", key, propertyClass, [object class]]; + } + [self setValue:object forKey:key]; + } + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + [self setWithCoder:aDecoder]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + for (NSString *key in [self codableProperties]) + { + id object = [self valueForKey:key]; + if (object) [aCoder encodeObject:object forKey:key]; + } +} + +@end diff --git a/YuMi/Structure/MVP/Model/PIBaseModel.h b/YuMi/Structure/MVP/Model/PIBaseModel.h index 2b17959..df2cb82 100644 --- a/YuMi/Structure/MVP/Model/PIBaseModel.h +++ b/YuMi/Structure/MVP/Model/PIBaseModel.h @@ -1,9 +1,7 @@ -// -// PIBaseModel.h -// YuMi -// + + // Created by duoban on 2023/11/15. -// + #import diff --git a/YuMi/Structure/MVP/Model/PIBaseModel.h.backup b/YuMi/Structure/MVP/Model/PIBaseModel.h.backup new file mode 100644 index 0000000..2b17959 --- /dev/null +++ b/YuMi/Structure/MVP/Model/PIBaseModel.h.backup @@ -0,0 +1,16 @@ +// +// PIBaseModel.h +// YuMi +// +// Created by duoban on 2023/11/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PIBaseModel : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Model/PIBaseModel.m b/YuMi/Structure/MVP/Model/PIBaseModel.m index 989c4bb..aa12653 100644 --- a/YuMi/Structure/MVP/Model/PIBaseModel.m +++ b/YuMi/Structure/MVP/Model/PIBaseModel.m @@ -1,36 +1,34 @@ -// -// PIBaseModel.m -// YuMi -// + + // Created by duoban on 2023/11/15. -// + #import "PIBaseModel.h" @implementation PIBaseModel - (NSString *)debugDescription { - //判断是否时NSArray 或者NSDictionary NSNumber 如果是的话直接返回 debugDescription + if ([self isKindOfClass:[NSArray class]] || [self isKindOfClass:[NSDictionary class]] || [self isKindOfClass:[NSString class]] || [self isKindOfClass:[NSNumber class]]) { return [self debugDescription]; } - //声明一个字典 + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; - //得到当前class的所有属性 + uint count; objc_property_t *properties = class_copyPropertyList([self class], &count); - //循环并用KVC得到每个属性的值 + for (int i = 0; i -- %@",[self class],self,dictionary]; } @end diff --git a/YuMi/Structure/MVP/Model/PIBaseModel.m.backup b/YuMi/Structure/MVP/Model/PIBaseModel.m.backup new file mode 100644 index 0000000..989c4bb --- /dev/null +++ b/YuMi/Structure/MVP/Model/PIBaseModel.m.backup @@ -0,0 +1,36 @@ +// +// PIBaseModel.m +// YuMi +// +// Created by duoban on 2023/11/15. +// + +#import "PIBaseModel.h" + +@implementation PIBaseModel +- (NSString *)debugDescription { + //判断是否时NSArray 或者NSDictionary NSNumber 如果是的话直接返回 debugDescription + if ([self isKindOfClass:[NSArray class]] || [self isKindOfClass:[NSDictionary class]] || [self isKindOfClass:[NSString class]] || [self isKindOfClass:[NSNumber class]]) { + return [self debugDescription]; + } + //声明一个字典 + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + //得到当前class的所有属性 + uint count; + objc_property_t *properties = class_copyPropertyList([self class], &count); + + //循环并用KVC得到每个属性的值 + for (int i = 0; i -- %@",[self class],self,dictionary]; +} +@end diff --git a/YuMi/Structure/MVP/Model/UserInfoModel.h b/YuMi/Structure/MVP/Model/UserInfoModel.h index 79c257a..c39424c 100644 --- a/YuMi/Structure/MVP/Model/UserInfoModel.h +++ b/YuMi/Structure/MVP/Model/UserInfoModel.h @@ -1,9 +1,7 @@ -// -// UserInfoModel.h -// xplan-ios -// + + // Created by zu on 2021/9/14. -// + #import "NSObject+MJExtension.h" @@ -14,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface UsingPersonalBackground : PIBaseModel -@property(nonatomic, assign) NSInteger effectType; // 装扮动效图片类型 空/0-图,1-mp4,2-svga +@property(nonatomic, assign) NSInteger effectType; @property(nonatomic, assign) NSInteger status; @property(nonatomic, assign) NSInteger id; @property(nonatomic, assign) NSInteger partitionFlag; @@ -28,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN @interface InfoCardVO : PIBaseModel -@property(nonatomic, assign) NSInteger effectType; // 装扮动效图片类型 空/0-图,1-mp4,2-svga +@property(nonatomic, assign) NSInteger effectType; @property(nonatomic, copy) NSString *effect; @end @@ -49,8 +47,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic , assign) NSInteger fansNum; @property (nonatomic , assign) BOOL isBindBankCard; @property (nonatomic , assign) BOOL hasRegPacket; -@property (nonatomic , assign) NSInteger gender; /// 性别 1:男 2:女 -@property (nonatomic , assign) NSInteger platformRole; /// 0 普通 1超管 +@property (nonatomic , assign) NSInteger gender; +@property (nonatomic , assign) NSInteger platformRole; @property (nonatomic , assign) NSInteger uid; @property (nonatomic , assign) NSInteger defUser; @property (nonatomic , copy) NSString * phone; @@ -68,102 +66,101 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic , assign) BOOL isBindPaymentPwd; @property (nonatomic , assign) BOOL isBindXCZAccount; @property (nonatomic , assign) BOOL isBindAlipay; -///是否绑定了密码 + @property (nonatomic , assign) BOOL isBindPasswd; -@property (nonatomic, assign) NSInteger visitNum;///访客数量 -@property (nonatomic, assign) NSInteger inRoomNum;///足迹 -///是否需要展示限时首充列表 +@property (nonatomic, assign) NSInteger visitNum; +@property (nonatomic, assign) NSInteger inRoomNum; + @property (nonatomic, assign) BOOL showLimitCharge; -///限时首充结束时间 + @property (nonatomic, assign) long limitChargeEndTime; -///相册 -@property (nonatomic, strong) NSArray *privatePhoto;//相册 -///签名 + +@property (nonatomic, strong) NSArray *privatePhoto; + @property (nonatomic,copy) NSString *userDesc; -///出生日期 + @property (nonatomic,assign) long birth; -///是否实名认证 + @property (nonatomic,assign) BOOL isCertified; -///铭牌背景 + @property (nonatomic, copy) NSString *nameplatePic; -///铭牌名称 + @property (nonatomic, copy) NSString *nameplateWord; -///是否自定义铭牌, + @property(nonatomic,assign) BOOL isCustomWord; -///如果在房间有直播中字段 + @property(nonatomic, copy) NSString * roomUid; -///如果在房间,房间的标题 + @property (nonatomic, copy) NSString *roomTitle; -///用户信息中的 座驾 并不需要CarModel 映射一下吧 + @property (nonatomic,copy) NSString *carEffect; -///座驾特效类型 0:普通, 1:VAP特效 + @property (nonatomic, assign) NSInteger otherViewType; -///用户信息中需要用VAP播放的座驾, 映射一下 + @property (nonatomic, copy) NSString *viewUrl; -///用户信息中的 座驾昵称 并不需要CarModel 映射一下吧 + @property (nonatomic,copy) NSString *carName; -///用户信息中的 头饰的动画 从 HeadwearModel 映射而来 + @property (nonatomic,copy) NSString *headwearEffect; -///用户信息中的 头饰的动画 如果没有的话 就用这个 从 HeadwearModel 映射而来 + @property (nonatomic,copy) NSString *headwearPic; -@property (nonatomic,assign) NSInteger headwearType; // 1 = svga, 表示 headwearEffect 是 svga 的链接 -@property (nonatomic,assign) NSInteger headWearType; // 1 = svga, 表示 headwearEffect 是 svga 的链接, W 大小写不一致是后端的原因,这里做个兼容 -///头饰(新字段) 上麦的时候 在扩展字段中的 只用在坑位上 从 HeadwearModel 映射而来 +@property (nonatomic,assign) NSInteger headwearType; +@property (nonatomic,assign) NSInteger headWearType; + @property (nonatomic,copy) NSString *headWearUrl; #pragma mark - 相亲房的字段 -///是否为相亲模式VIP坑位 + @property (nonatomic,assign) BOOL vipMic; -///帽子 相亲中收到礼物值最高的那个人 男神 女神都有 + @property (nonatomic,copy) NSString *capUrl; -///是不是选择了人 + @property (nonatomic,assign) BOOL hasSelectUser; -///所选择的麦序 + @property (nonatomic,assign) int selectMicPosition; -///VIP信息 + @property (nonatomic, strong) NSObject *userVipInfoVO; -///当前使用的资料卡装扮 + @property (nonatomic, copy) NSString *userInfoCardPic; -///麦位光圈链接 + @property (nonatomic, copy) NSString *micCircle; -///麦位昵称颜色 + @property (nonatomic, copy) NSString *micNickColor; -///技能卡图标列表 + @property (nonatomic, strong) NSArray *absCardPics; -///跟随的 本地添加的字段 + @property (nonatomic,copy) NSString *fromNick; @property (nonatomic,copy) NSString *fromUid; -///安卓房间公屏气泡 + @property (nonatomic, copy) NSString *androidBubbleUrl; -///iOS房间公屏气泡 + @property (nonatomic, copy) NSString *iosBubbleUrl; #pragma mark - 小游戏 -///礼物墙中的礼物 + @property (nonatomic,strong) NSArray *userGiftWall; -///礼物墙中的幸运礼物礼物 + @property (nonatomic,strong) NSArray *userLuckyBagGiftWall; -///是否防被踢 + @property (nonatomic, assign) BOOL preventKick; -///是否符合渠道打招呼 + @property (nonatomic,assign) BOOL fromSayHelloChannel; -///是否是封号用户 + @property (nonatomic,assign) BOOL banAccount; -///用户的动态 + @property (nonatomic,strong) NSArray *dynamicInfo; -///区号 + @property (nonatomic,copy) NSString *phoneAreaCode; -///用户所在区 @property(nonatomic,copy) NSString *partitionId; -/// -/// + + @property (nonatomic,strong) NSMutableAttributedString *levelAtt; @property (nonatomic,strong) NSMutableAttributedString *idAtt; -///是否是代充代理 + @property(nonatomic,assign) BOOL isRechargeUser; -///pk时不能禁麦 + @property(nonatomic,assign) BOOL isNoProhibitMic; @property (nonatomic, strong) NSObject *medals; @@ -178,7 +175,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) InfoCardVO *infoCardVo; -/// 是否超管身份 + @property(nonatomic, assign) BOOL hasSuperRole; @property(nonatomic, copy) NSString *guildNameplateIcon; diff --git a/YuMi/Structure/MVP/Model/UserInfoModel.h.backup b/YuMi/Structure/MVP/Model/UserInfoModel.h.backup new file mode 100644 index 0000000..79c257a --- /dev/null +++ b/YuMi/Structure/MVP/Model/UserInfoModel.h.backup @@ -0,0 +1,203 @@ +// +// UserInfoModel.h +// xplan-ios +// +// Created by zu on 2021/9/14. +// + +#import "NSObject+MJExtension.h" + +#import "MomentsInfoModel.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface UsingPersonalBackground : PIBaseModel + +@property(nonatomic, assign) NSInteger effectType; // 装扮动效图片类型 空/0-图,1-mp4,2-svga +@property(nonatomic, assign) NSInteger status; +@property(nonatomic, assign) NSInteger id; +@property(nonatomic, assign) NSInteger partitionFlag; +@property(nonatomic, assign) NSTimeInterval updateTime; +@property(nonatomic, assign) NSTimeInterval createTime; +@property(nonatomic, copy) NSString *pic; +@property(nonatomic, copy) NSString *effect; +@property(nonatomic, copy) NSString *name; + +@end + +@interface InfoCardVO : PIBaseModel + +@property(nonatomic, assign) NSInteger effectType; // 装扮动效图片类型 空/0-图,1-mp4,2-svga +@property(nonatomic, copy) NSString *effect; + +@end + + +@interface UserInfoModel : PIBaseModel +@property (nonatomic , assign) NSInteger bindType; +@property (nonatomic , assign) NSInteger createTime; +@property (nonatomic , assign) BOOL parentMode; +@property (nonatomic , assign) BOOL isBindPhone; +@property (nonatomic , strong) NSObject * userExpand; +@property (nonatomic , assign) NSInteger erbanNo; +@property (nonatomic , assign) NSInteger registerDay; +@property (nonatomic , assign) BOOL isFirstCharge; +@property (nonatomic , assign) BOOL hasPrettyErbanNo; +@property (nonatomic , strong) NSObject * userLevelVo; +@property (nonatomic , assign) BOOL isBindApple; +@property (nonatomic , assign) NSInteger fansNum; +@property (nonatomic , assign) BOOL isBindBankCard; +@property (nonatomic , assign) BOOL hasRegPacket; +@property (nonatomic , assign) NSInteger gender; /// 性别 1:男 2:女 +@property (nonatomic , assign) NSInteger platformRole; /// 0 普通 1超管 +@property (nonatomic , assign) NSInteger uid; +@property (nonatomic , assign) NSInteger defUser; +@property (nonatomic , copy) NSString * phone; +@property (nonatomic , copy) NSString * email; +@property (nonatomic , copy) NSString * nick; +@property (nonatomic , assign) NSInteger remainDay; +@property (nonatomic , copy) NSString * avatar; +@property (nonatomic , copy) NSString * reviewingAvatar; +@property (nonatomic , assign) BOOL isReview; +@property (nonatomic , strong) NSObject * userInfoSkillVo; +@property (nonatomic,copy) NSString *region; +@property (nonatomic,copy) NSArray *labels; +@property (nonatomic , assign) BOOL newUser; +@property (nonatomic , assign) NSInteger followNum; +@property (nonatomic , assign) BOOL isBindPaymentPwd; +@property (nonatomic , assign) BOOL isBindXCZAccount; +@property (nonatomic , assign) BOOL isBindAlipay; +///是否绑定了密码 +@property (nonatomic , assign) BOOL isBindPasswd; +@property (nonatomic, assign) NSInteger visitNum;///访客数量 +@property (nonatomic, assign) NSInteger inRoomNum;///足迹 +///是否需要展示限时首充列表 +@property (nonatomic, assign) BOOL showLimitCharge; +///限时首充结束时间 +@property (nonatomic, assign) long limitChargeEndTime; +///相册 +@property (nonatomic, strong) NSArray *privatePhoto;//相册 +///签名 +@property (nonatomic,copy) NSString *userDesc; +///出生日期 +@property (nonatomic,assign) long birth; +///是否实名认证 +@property (nonatomic,assign) BOOL isCertified; +///铭牌背景 +@property (nonatomic, copy) NSString *nameplatePic; +///铭牌名称 +@property (nonatomic, copy) NSString *nameplateWord; +///是否自定义铭牌, +@property(nonatomic,assign) BOOL isCustomWord; +///如果在房间有直播中字段 +@property(nonatomic, copy) NSString * roomUid; +///如果在房间,房间的标题 +@property (nonatomic, copy) NSString *roomTitle; +///用户信息中的 座驾 并不需要CarModel 映射一下吧 +@property (nonatomic,copy) NSString *carEffect; +///座驾特效类型 0:普通, 1:VAP特效 +@property (nonatomic, assign) NSInteger otherViewType; +///用户信息中需要用VAP播放的座驾, 映射一下 +@property (nonatomic, copy) NSString *viewUrl; +///用户信息中的 座驾昵称 并不需要CarModel 映射一下吧 +@property (nonatomic,copy) NSString *carName; +///用户信息中的 头饰的动画 从 HeadwearModel 映射而来 +@property (nonatomic,copy) NSString *headwearEffect; +///用户信息中的 头饰的动画 如果没有的话 就用这个 从 HeadwearModel 映射而来 +@property (nonatomic,copy) NSString *headwearPic; +@property (nonatomic,assign) NSInteger headwearType; // 1 = svga, 表示 headwearEffect 是 svga 的链接 +@property (nonatomic,assign) NSInteger headWearType; // 1 = svga, 表示 headwearEffect 是 svga 的链接, W 大小写不一致是后端的原因,这里做个兼容 +///头饰(新字段) 上麦的时候 在扩展字段中的 只用在坑位上 从 HeadwearModel 映射而来 +@property (nonatomic,copy) NSString *headWearUrl; +#pragma mark - 相亲房的字段 +///是否为相亲模式VIP坑位 +@property (nonatomic,assign) BOOL vipMic; +///帽子 相亲中收到礼物值最高的那个人 男神 女神都有 +@property (nonatomic,copy) NSString *capUrl; +///是不是选择了人 +@property (nonatomic,assign) BOOL hasSelectUser; +///所选择的麦序 +@property (nonatomic,assign) int selectMicPosition; +///VIP信息 +@property (nonatomic, strong) NSObject *userVipInfoVO; +///当前使用的资料卡装扮 +@property (nonatomic, copy) NSString *userInfoCardPic; +///麦位光圈链接 +@property (nonatomic, copy) NSString *micCircle; +///麦位昵称颜色 +@property (nonatomic, copy) NSString *micNickColor; + +///技能卡图标列表 +@property (nonatomic, strong) NSArray *absCardPics; + +///跟随的 本地添加的字段 +@property (nonatomic,copy) NSString *fromNick; +@property (nonatomic,copy) NSString *fromUid; +///安卓房间公屏气泡 +@property (nonatomic, copy) NSString *androidBubbleUrl; +///iOS房间公屏气泡 +@property (nonatomic, copy) NSString *iosBubbleUrl; +#pragma mark - 小游戏 +///礼物墙中的礼物 +@property (nonatomic,strong) NSArray *userGiftWall; +///礼物墙中的幸运礼物礼物 +@property (nonatomic,strong) NSArray *userLuckyBagGiftWall; +///是否防被踢 +@property (nonatomic, assign) BOOL preventKick; +///是否符合渠道打招呼 +@property (nonatomic,assign) BOOL fromSayHelloChannel; +///是否是封号用户 +@property (nonatomic,assign) BOOL banAccount; +///用户的动态 +@property (nonatomic,strong) NSArray *dynamicInfo; +///区号 +@property (nonatomic,copy) NSString *phoneAreaCode; + + +///用户所在区 +@property(nonatomic,copy) NSString *partitionId; +/// +/// +@property (nonatomic,strong) NSMutableAttributedString *levelAtt; +@property (nonatomic,strong) NSMutableAttributedString *idAtt; +///是否是代充代理 +@property(nonatomic,assign) BOOL isRechargeUser; +///pk时不能禁麦 +@property(nonatomic,assign) BOOL isNoProhibitMic; + +@property (nonatomic, strong) NSObject *medals; + +@property (nonatomic, strong) NSObject *relationUserVO; + +@property (nonatomic, strong) NSObject *guildInfo; + +@property (nonatomic, copy) NSArray *userNameplateList; + +@property(nonatomic, strong) UsingPersonalBackground *usingPersonalBackground; + +@property(nonatomic, strong) InfoCardVO *infoCardVo; + +/// 是否超管身份 +@property(nonatomic, assign) BOOL hasSuperRole; + +@property(nonatomic, copy) NSString *guildNameplateIcon; + +@property(nonatomic, assign) NSInteger uploadGifAvatarPrice; + +@property(nonatomic, copy) NSString *regionIcon; +@property(nonatomic, copy) NSString *visitTimeDesc; + +@property (nonatomic, copy) NSArray *medalsPic; + +- (BOOL)isUserValid; +- (NSString *)userIDString; + +- (BOOL)isHeadWearSVGA; + +- (BOOL)isArabia; +- (BOOL)isEnglish; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Model/UserInfoModel.m b/YuMi/Structure/MVP/Model/UserInfoModel.m index d6e6fdb..6246fa1 100644 --- a/YuMi/Structure/MVP/Model/UserInfoModel.m +++ b/YuMi/Structure/MVP/Model/UserInfoModel.m @@ -1,9 +1,7 @@ -// -// UserInfoModel.m -// xplan-ios -// + + // Created by zu on 2021/9/14. -// + #import "UserInfoModel.h" @@ -23,7 +21,7 @@ }; } -///如果一个模型中需要字段映射的话 比如id -> ID name -> other.name + + (NSDictionary *)replacedKeyFromPropertyName { return @{@"carEffect": @"carport.effect", @"viewUrl": @"carport.viewUrl", diff --git a/YuMi/Structure/MVP/Model/UserInfoModel.m.backup b/YuMi/Structure/MVP/Model/UserInfoModel.m.backup new file mode 100644 index 0000000..d6e6fdb --- /dev/null +++ b/YuMi/Structure/MVP/Model/UserInfoModel.m.backup @@ -0,0 +1,76 @@ +// +// UserInfoModel.m +// xplan-ios +// +// Created by zu on 2021/9/14. +// + +#import "UserInfoModel.h" + +@implementation InfoCardVO + +@end + +@implementation UsingPersonalBackground + +@end + +@implementation UserInfoModel + ++ (NSDictionary *)objectClassInArray { + return @{ + @"dynamicInfo":MomentsInfoModel.class, + }; +} + +///如果一个模型中需要字段映射的话 比如id -> ID name -> other.name ++ (NSDictionary *)replacedKeyFromPropertyName { + return @{@"carEffect": @"carport.effect", + @"viewUrl": @"carport.viewUrl", + @"otherViewType": @"carport.otherViewType", + @"headwearEffect" : @"userHeadwear.effect", + @"headwearPic" : @"userHeadwear.pic", + @"headwearType" : @"userHeadwear.type", + @"carName": @"carport.name", + @"reviewingAvatar" : @"newAvatar" + }; +} + +- (BOOL)isUserValid { + return self.uid > 0; +} + +- (NSString *)userIDString { + return [NSString stringWithFormat:@"%ld", (long)self.uid]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[UserInfoModel class]]) { + return NO; + } + UserInfoModel *other = (UserInfoModel *)object; + return self.uid == other.uid && + [self.nick isEqualToString:other.nick] && + [self.avatar isEqualToString:self.avatar]; +} + +- (NSUInteger)hash { + return self.nick.hash ^ self.uid; +} + +- (BOOL)isHeadWearSVGA { + return self.headwearType == 1 || self.headWearType == 1; +} + +- (BOOL)isArabia { + return [self.partitionId isEqualToString:@"2"]; +} + +- (BOOL)isEnglish { + return [self.partitionId isEqualToString:@"1"]; +} + +@end diff --git a/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h index a1e396b..70c1aa3 100644 --- a/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h +++ b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h @@ -1,9 +1,7 @@ -// -// BaseMvpPresenter.h -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import #import "BaseMvpProtocol.h" @@ -31,7 +29,6 @@ typedef void(^HttpFail)(NSInteger code, NSString * _Nullable msg); - (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success fail:(HttpFail _Nullable)fail showLoading:(BOOL)loading errorToast:(BOOL)toast; - @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h.backup b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h.backup new file mode 100644 index 0000000..a1e396b --- /dev/null +++ b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.h.backup @@ -0,0 +1,37 @@ +// +// BaseMvpPresenter.h +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import +#import "BaseMvpProtocol.h" +#import "HttpRequestHelper.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^HttpSuccess)(BaseModel *data); +typedef void(^HttpFail)(NSInteger code, NSString * _Nullable msg); + +@interface BaseMvpPresenter : NSObject + +- (void)attatchView:(id)view; +- (id)getView; +- (void)detatchView; +- (void)logout; +- (void)tokenInvalid; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success showLoading:(BOOL)loading; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success errorToast:(BOOL)toast; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success showLoading:(BOOL)loading errorToast:(BOOL)toast; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success fail:(HttpFail _Nullable)fail; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success fail:(HttpFail _Nullable)fail showLoading:(BOOL)loading; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success fail:(HttpFail _Nullable)fail errorToast:(BOOL)toast; +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess _Nonnull)success fail:(HttpFail _Nullable)fail showLoading:(BOOL)loading errorToast:(BOOL)toast; + + + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m index 71ae103..1904d28 100644 --- a/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m +++ b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m @@ -1,9 +1,7 @@ -// -// BaseMvpPresenter.m -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import "BaseMvpPresenter.h" #import "AccountInfoStorage.h" @@ -71,34 +69,34 @@ } switch (code) { - case 401: // 登录过期 + case 401: [self logout]; return; case 407: case 408: [self accountBanned:data]; return; - case 1415: // 未完善用户信息 + case 1415: [[self getView] completeUserInfo]; return; - case 3009: // 账号已注销 -// [[self getView] accountCanceled:data.model2dictionary]; -// return; - case 31005: {//余额不足 + case 3009: + + + case 31005: { } break; - case 30000: {// 青少年模式进房错误,进行弹窗处理,同时不显示 toast。 + case 30000: { } break; - case 10111: // 金额过大,需要先实名认证 + case 10111: [self.view hideHUD]; [[self getView] showRealNameAuthenticationTipsAlertView]; return; - case 10108: // 未实名认证 + case 10108: [self.view hideHUD]; [[self getView] showRealNameAuthenticationTipsAlertView]; return; - case 25000: {// 在青少年模式下,充值已达上限 + case 25000: { } } diff --git a/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m.backup b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m.backup new file mode 100644 index 0000000..71ae103 --- /dev/null +++ b/YuMi/Structure/MVP/Presenter/BaseMvpPresenter.m.backup @@ -0,0 +1,137 @@ +// +// BaseMvpPresenter.m +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import "BaseMvpPresenter.h" +#import "AccountInfoStorage.h" +#import "BaseNavigationController.h" + +@interface BaseMvpPresenter() + +@property (nonatomic, weak) id view; + +@end + +@implementation BaseMvpPresenter + +- (void)attatchView:(id)view { + self.view = view; +} + +- (id)getView { + return self.view; +} + +- (void)logout { + +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success { + return [self createHttpCompletion:success fail:nil]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success showLoading:(BOOL)loading { + return [self createHttpCompletion:success fail:nil showLoading:loading]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success errorToast:(BOOL)toast { + return [self createHttpCompletion:success fail:nil errorToast:toast]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success showLoading:(BOOL)loading errorToast:(BOOL)toast { + return [self createHttpCompletion:success fail:nil showLoading:loading errorToast:toast]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success fail:(HttpFail)fail { + return [self createHttpCompletion:success fail:fail showLoading:NO errorToast:YES]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success fail:(HttpFail)fail showLoading:(BOOL)loading { + return [self createHttpCompletion:success fail:fail showLoading:loading errorToast:YES]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success fail:(HttpFail)fail errorToast:(BOOL)toast { + return [self createHttpCompletion:success fail:fail showLoading:NO errorToast:toast]; +} + +- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success fail:(HttpFail)fail showLoading:(BOOL)loading errorToast:(BOOL)toast { + if (loading) { + [self.view showAnchorLoading]; + } + return ^(BaseModel *data, NSInteger code, NSString * _Nullable msg) { + if (loading) { + [self.view hideHUD]; + } + if (code == 200) { + success(data); + return; + } + + switch (code) { + case 401: // 登录过期 + [self logout]; + return; + case 407: + case 408: + [self accountBanned:data]; + return; + case 1415: // 未完善用户信息 + [[self getView] completeUserInfo]; + return; + case 3009: // 账号已注销 +// [[self getView] accountCanceled:data.model2dictionary]; +// return; + case 31005: {//余额不足 + } + break; + case 30000: {// 青少年模式进房错误,进行弹窗处理,同时不显示 toast。 + } + break; + case 10111: // 金额过大,需要先实名认证 + [self.view hideHUD]; + [[self getView] showRealNameAuthenticationTipsAlertView]; + return; + case 10108: // 未实名认证 + [self.view hideHUD]; + [[self getView] showRealNameAuthenticationTipsAlertView]; + return; + case 25000: {// 在青少年模式下,充值已达上限 + } + } + + if (toast && [self.view respondsToSelector:@selector(showErrorToast:)]) { + [self.view showErrorToast:msg]; + } + + if (fail) { + fail(code, msg); + } + }; +} + +- (void)detatchView { + +} + +- (void)accountBanned:(BaseModel *)data { + TTAlertConfig * config = [[TTAlertConfig alloc] init]; + config.title = YMLocalizedString(@"MvpViewController6"); + NSString *dateDes = [PLTimeUtil getDateWithYYMMDD:data.date]; + NSString * title = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController7"), data.reason,dateDes]; + TTAlertMessageAttributedConfig * inviteAlertConfig = [[TTAlertMessageAttributedConfig alloc] init]; + inviteAlertConfig.text = dateDes; + inviteAlertConfig.color = [DJDKMIMOMColor appMainColor]; + inviteAlertConfig.font = [UIFont systemFontOfSize:15]; + config.message = title; + config.messageAttributedConfig = @[inviteAlertConfig]; + [TTPopup alertWithConfig:config confirmHandler:^{ } cancelHandler:^{ }]; +} + +- (void)tokenInvalid { + +} + +@end diff --git a/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h b/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h index e74fd59..72147d0 100644 --- a/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h +++ b/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h @@ -1,9 +1,7 @@ -// -// BaseMvpProtocol.h -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import #import "BaseViewController.h" @@ -17,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)completeUserInfo; - (void)accountCanceled:(NSDictionary *)data; -///实名认证弹窗 + - (void)showRealNameAuthenticationTipsAlertView; @end diff --git a/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h.backup b/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h.backup new file mode 100644 index 0000000..e74fd59 --- /dev/null +++ b/YuMi/Structure/MVP/Protocol/BaseMvpProtocol.h.backup @@ -0,0 +1,25 @@ +// +// BaseMvpProtocol.h +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import +#import "BaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN +@class BaseModel; +@protocol BaseMvpProtocol + +@optional + +- (void)completeUserInfo; +- (void)accountCanceled:(NSDictionary *)data; + +///实名认证弹窗 +- (void)showRealNameAuthenticationTipsAlertView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/View/MvpViewController.h b/YuMi/Structure/MVP/View/MvpViewController.h index 51dd361..3594d5d 100644 --- a/YuMi/Structure/MVP/View/MvpViewController.h +++ b/YuMi/Structure/MVP/View/MvpViewController.h @@ -1,15 +1,12 @@ -// -// MvpViewController.h -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import "BaseViewController.h" #import "BaseMvpPresenter.h" - NS_ASSUME_NONNULL_BEGIN diff --git a/YuMi/Structure/MVP/View/MvpViewController.h.backup b/YuMi/Structure/MVP/View/MvpViewController.h.backup new file mode 100644 index 0000000..51dd361 --- /dev/null +++ b/YuMi/Structure/MVP/View/MvpViewController.h.backup @@ -0,0 +1,31 @@ +// +// MvpViewController.h +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import "BaseViewController.h" +#import "BaseMvpPresenter.h" + + + +NS_ASSUME_NONNULL_BEGIN + + +typedef void(^HeaderRefreshComplete)(void); + +@interface MvpViewController : BaseViewController + +@property (nonatomic, strong) __kindof T presenter; + +- (__kindof T)createPresenter; + +- (void)setupTopTheme; + +- (void)setupCustomNavigationBar:(void(^)(void))backAction title:(NSString *)title titleColor:(UIColor *)color; +- (void)setupCustonNavigationRightButtons:(NSArray *)array sizes:(NSArray *)sizes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Structure/MVP/View/MvpViewController.m b/YuMi/Structure/MVP/View/MvpViewController.m index 0394cc4..2340847 100644 --- a/YuMi/Structure/MVP/View/MvpViewController.m +++ b/YuMi/Structure/MVP/View/MvpViewController.m @@ -1,15 +1,13 @@ -// -// MvpViewController.m -// YUMI -// + + // Created by admin on 2023/3/9. -// + #import "MvpViewController.h" #import "BaseMvpProtocol.h" #import "BaseMvpPresenter.h" #import "BaseNavigationController.h" -//Tool + #import "TTPopup.h" #import "PLTimeUtil.h" #import "DJDKMIMOMColor.h" @@ -138,7 +136,7 @@ } -///实名认证弹窗 + - (void)showRealNameAuthenticationTipsAlertView { TTAlertConfig *config = [[TTAlertConfig alloc] init]; config.message = YMLocalizedString(@"MvpViewController3"); @@ -158,24 +156,6 @@ }]; } -/////封禁账号 -//- (void)accountBanned:(BaseModel *)data { -// TTAlertConfig * config = [[TTAlertConfig alloc] init]; -// config.title = YMLocalizedString(@"MvpViewController6"); -// NSString *dateDes = [PLTimeUtil getDateWithYYMMDD:data.date]; -// NSString * title = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController7"), data.reason,dateDes]; -// TTAlertMessageAttributedConfig * inviteAlertConfig = [[TTAlertMessageAttributedConfig alloc] init]; -// inviteAlertConfig.text = dateDes; -// inviteAlertConfig.color = [DJDKMIMOMColor appMainColor]; -// inviteAlertConfig.font = [UIFont systemFontOfSize:15]; -// config.message = title; -// config.messageAttributedConfig = @[inviteAlertConfig]; -// [TTPopup alertWithConfig:config confirmHandler:^{ -// -// } cancelHandler:^{ -// -// }]; -//} - (UILabel *)mvpTitleLabel { if (!_mvpTitleLabel) { diff --git a/YuMi/Structure/MVP/View/MvpViewController.m.backup b/YuMi/Structure/MVP/View/MvpViewController.m.backup new file mode 100644 index 0000000..0394cc4 --- /dev/null +++ b/YuMi/Structure/MVP/View/MvpViewController.m.backup @@ -0,0 +1,204 @@ +// +// MvpViewController.m +// YUMI +// +// Created by admin on 2023/3/9. +// + +#import "MvpViewController.h" +#import "BaseMvpProtocol.h" +#import "BaseMvpPresenter.h" +#import "BaseNavigationController.h" +//Tool +#import "TTPopup.h" +#import "PLTimeUtil.h" +#import "DJDKMIMOMColor.h" +#import "YUMIMacroUitls.h" +#import "YUMIHtmlUrl.h" +#import "BSRealTimeView.h" + +@interface MvpViewController () + +@property (nonatomic, copy) void(^backAction)(void); +@property (nonatomic, strong) UILabel *mvpTitleLabel; +@property (nonatomic, strong) UIButton *backButton; + +@end + +@implementation MvpViewController + +- (__kindof id)presenter { + if (_presenter == nil) { + _presenter = [self createPresenter]; + [_presenter attatchView:self]; + } + return _presenter; +} + +- (__kindof id)createPresenter { + return [[BaseMvpPresenter alloc] init]; +} + +- (void)setupTopTheme { + +} + +- (void)setupCustomNavigationBar:(void(^)(void))backAction title:(NSString *)title titleColor:(UIColor *)color { + UILabel *titleLabel = [self mvpTitleLabel]; + titleLabel.text = title; + titleLabel.textColor = color; + [self.view addSubview:titleLabel]; + [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(self.view).offset(kStatusBarHeight); + make.height.mas_equalTo(22); + }]; + + UIButton *backButton = [self mvpBackButton]; + [self.view addSubview:backButton]; + [backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.view).offset(16); + make.centerY.mas_equalTo(titleLabel); + make.size.mas_equalTo(CGSizeMake(22, 22)); + }]; + + self.backAction = backAction; +} + +- (void)setupCustonNavigationRightButtons:(NSArray *)array + sizes:(NSArray *)sizes { + if (array.count > 0 && self->_mvpTitleLabel) { + CGFloat trailing = -16; + for (UIButton *b in array) { + NSInteger index = [array indexOfObject:b]; + NSValue *sizeValue = [sizes xpSafeObjectAtIndex:index]; + [self.view addSubview:b]; + [b mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.view).offset(trailing); + make.centerY.mas_equalTo(self.mvpTitleLabel); + make.size.mas_equalTo([sizeValue CGSizeValue]); + }]; + + trailing -= 14 + [sizeValue CGSizeValue].width; + } + } +} + +- (void)didTapBack { + if (self.backAction) { + self.backAction(); + } + [self.navigationController popViewControllerAnimated:YES]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; +#ifdef DEBUG + for (id obj in kWindow.subviews) { + if([obj isKindOfClass:[BSRealTimeView class]]){ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + BSRealTimeView *timeView = (BSRealTimeView *)obj; + [timeView removeFromSuperview]; + [kWindow addSubview:timeView]; + }); + break; + } + } +#else +#endif +} + +- (void)accountCanceled:(NSDictionary *)data { + NSString *date = [NSString stringWithFormat:@"%.0f",[[data objectForKey:@"cancelDate"] doubleValue]]; + NSString *dateDes = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController0"), [PLTimeUtil getDateWithYYMMDD:date]]; + NSString *msg = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController1.1"), dateDes]; + if ([[data objectForKey:@"cancelDate"] doubleValue] == 0) { + dateDes = @""; + msg = YMLocalizedString(@"MvpViewController1.2"); + } + + TTAlertMessageAttributedConfig *dateAttrConfig = [[TTAlertMessageAttributedConfig alloc] init]; + dateAttrConfig.text = dateDes; + dateAttrConfig.color = DJDKMIMOMColor.appMainColor; + + TTAlertConfig *config = [[TTAlertConfig alloc] init]; + config.actionStyle = 0; + config.title = YMLocalizedString(@"MvpViewController2"); + config.message = msg; + config.messageAttributedConfig = @[dateAttrConfig]; + + [TTPopup alertWithConfig:config confirmHandler:^{ + + } cancelHandler:^{ + + }]; +} + +- (void)completeUserInfo { + +} + +///实名认证弹窗 +- (void)showRealNameAuthenticationTipsAlertView { + TTAlertConfig *config = [[TTAlertConfig alloc] init]; + config.message = YMLocalizedString(@"MvpViewController3"); + config.messageLineSpacing = 4; + config.confirmButtonConfig.title = YMLocalizedString(@"TTAlertConfig0"); + config.confirmButtonConfig.titleColor = UIColor.whiteColor; + config.confirmButtonConfig.backgroundColor = [DJDKMIMOMColor appMainColor]; + + TTAlertMessageAttributedConfig *nameAttrConf = [[TTAlertMessageAttributedConfig alloc] init]; + nameAttrConf.text = YMLocalizedString(@"MvpViewController5"); + nameAttrConf.color = [DJDKMIMOMColor appMainColor]; + config.messageAttributedConfig = @[nameAttrConf]; + + [TTPopup alertWithConfig:config confirmHandler:^{ + + } cancelHandler:^{ + }]; +} + +/////封禁账号 +//- (void)accountBanned:(BaseModel *)data { +// TTAlertConfig * config = [[TTAlertConfig alloc] init]; +// config.title = YMLocalizedString(@"MvpViewController6"); +// NSString *dateDes = [PLTimeUtil getDateWithYYMMDD:data.date]; +// NSString * title = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController7"), data.reason,dateDes]; +// TTAlertMessageAttributedConfig * inviteAlertConfig = [[TTAlertMessageAttributedConfig alloc] init]; +// inviteAlertConfig.text = dateDes; +// inviteAlertConfig.color = [DJDKMIMOMColor appMainColor]; +// inviteAlertConfig.font = [UIFont systemFontOfSize:15]; +// config.message = title; +// config.messageAttributedConfig = @[inviteAlertConfig]; +// [TTPopup alertWithConfig:config confirmHandler:^{ +// +// } cancelHandler:^{ +// +// }]; +//} + +- (UILabel *)mvpTitleLabel { + if (!_mvpTitleLabel) { + UILabel *label = [[UILabel alloc] init]; + label.textAlignment = NSTextAlignmentCenter; + label.font = kFontMedium(17); + label.textColor = UIColorFromRGB(0xD9E7F7); + _mvpTitleLabel = label; + } + return _mvpTitleLabel; +} + +- (UIButton *)mvpBackButton { + if (!_backButton) { + UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; + [b setImage:kImage(@"common_nav_back_white") + forState:UIControlStateNormal]; + [b addTarget:self + action:@selector(didTapBack) + forControlEvents:UIControlEventTouchUpInside]; + _backButton = b; + } + return _backButton; +} + +@end diff --git a/YuMi/Structure/PrefixHeader.pch b/YuMi/Structure/PrefixHeader.pch index e1eb7b3..8b05f48 100644 --- a/YuMi/Structure/PrefixHeader.pch +++ b/YuMi/Structure/PrefixHeader.pch @@ -38,7 +38,6 @@ isEnterprise = [bundleID isEqualToString:@"com.hflighting.yumi"];\ #import "NSString+Utils.h" #import "UIView+Corner.h" #import "UIView+GradientLayer.h" -#import "UILabel+Utils.h" #import "TTPopup.h" #import "NSDate+DateUtils.h" #import "NSMutableDictionary+Saft.h" diff --git a/YuMi/Tools/Bundle/NSBundle+Localizable.h b/YuMi/Tools/Bundle/NSBundle+Localizable.h index 52f544b..e3aba76 100644 --- a/YuMi/Tools/Bundle/NSBundle+Localizable.h +++ b/YuMi/Tools/Bundle/NSBundle+Localizable.h @@ -1,9 +1,7 @@ -// -// NSBundle+Localizable.h -// YuMi -// + + // Created by YuMi on 2023/6/19. -// + #import diff --git a/YuMi/Tools/Bundle/NSBundle+Localizable.h.backup b/YuMi/Tools/Bundle/NSBundle+Localizable.h.backup new file mode 100644 index 0000000..52f544b --- /dev/null +++ b/YuMi/Tools/Bundle/NSBundle+Localizable.h.backup @@ -0,0 +1,20 @@ +// +// NSBundle+Localizable.h +// YuMi +// +// Created by YuMi on 2023/6/19. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSBundle (Localizable) ++(NSString *)ymLocalizedStringForKey:(NSString *)key; ++(NSString *)ymLocalizedStringForKey:(NSString *)key value:(NSString *)value; ++(void)setLanguageText:(NSString *)language; ++(NSString *)uploadLanguageText; ++(NSString *)getLanguageText; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Bundle/NSBundle+Localizable.m b/YuMi/Tools/Bundle/NSBundle+Localizable.m index a2f4662..909a991 100644 --- a/YuMi/Tools/Bundle/NSBundle+Localizable.m +++ b/YuMi/Tools/Bundle/NSBundle+Localizable.m @@ -1,15 +1,13 @@ -// -// NSBundle+Localizable.m -// YuMi -// + + // Created by YuMi on 2023/6/19. -// + #import "NSBundle+Localizable.h" #import "YMLanguageConfig.h" #import -// 定义常量用于存储当前语言的 key + static NSString * const kSaveCurLanguageKey = @"kSaveCurLanguage"; static NSString * const kResourceType = @"lproj"; @@ -40,18 +38,18 @@ static NSString * const kResourceType = @"lproj"; } +(NSString *)getLanguageText{ - // EP 白包版本强制使用英文 + NSString *saveLanguage = [[NSUserDefaults standardUserDefaults] valueForKey:kSaveCurLanguageKey]; if (saveLanguage && [saveLanguage isEqualToString:@"en"]){ return saveLanguage; } - // 强制返回英文,忽略系统语言设置 + return @"en"; } +(NSString *)uploadLanguageText{ - // EP 白包版本强制使用英文 + return @"en"; } @@ -60,9 +58,9 @@ static NSString * const kResourceType = @"lproj"; [[NSUserDefaults standardUserDefaults]synchronize]; } -// 辅助方法,用于映射本地化语言 - 重构为使用统一配置 + + (NSString *)mapLanguageForLocalization:(NSString *)language { - // 首先尝试精确匹配 + for (NSDictionary *langConfig in [YMLanguageConfig supportedLanguages]) { NSString *code = langConfig[@"code"]; NSString *localizationCode = langConfig[@"localizationCode"]; @@ -72,7 +70,7 @@ static NSString * const kResourceType = @"lproj"; } } - // 然后尝试前缀匹配 + for (NSDictionary *langConfig in [YMLanguageConfig supportedLanguages]) { NSString *code = langConfig[@"code"]; if ([language hasPrefix:code]) { @@ -80,12 +78,12 @@ static NSString * const kResourceType = @"lproj"; } } - // 特殊处理:pt-BR 和 pt 的映射 + if ([language hasPrefix:@"pt"]) { return @"pt-BR"; } - // 默认返回英文 + return [YMLanguageConfig defaultLanguage]; } diff --git a/YuMi/Tools/Bundle/NSBundle+Localizable.m.backup b/YuMi/Tools/Bundle/NSBundle+Localizable.m.backup new file mode 100644 index 0000000..a2f4662 --- /dev/null +++ b/YuMi/Tools/Bundle/NSBundle+Localizable.m.backup @@ -0,0 +1,92 @@ +// +// NSBundle+Localizable.m +// YuMi +// +// Created by YuMi on 2023/6/19. +// + +#import "NSBundle+Localizable.h" +#import "YMLanguageConfig.h" +#import + +// 定义常量用于存储当前语言的 key +static NSString * const kSaveCurLanguageKey = @"kSaveCurLanguage"; +static NSString * const kResourceType = @"lproj"; + +@implementation NSBundle (Localizable) + ++(void)load{ + Method oldMethod = class_getClassMethod(self, @selector(mj_localizedStringForKey:)); + Method newMethod = class_getClassMethod(self, @selector(ms_localizedStringForKey:)); + method_exchangeImplementations(oldMethod, newMethod); +} ++ (NSString *)ms_localizedStringForKey:(NSString *)key{ + return [self ymLocalizedStringForKey:key]; +} ++(NSString *)ymLocalizedStringForKey:(NSString *)key +{ + return [self ymLocalizedStringForKey:key value:@""]; +} + ++(NSString *)ymLocalizedStringForKey:(NSString *)key value:(NSString *)value +{ + NSString *language = [NSBundle getLanguageText]; + NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language + ofType:kResourceType]]; + value = [bundle localizedStringForKey:key + value:value + table:nil]; + return value; +} + ++(NSString *)getLanguageText{ + // EP 白包版本强制使用英文 + NSString *saveLanguage = [[NSUserDefaults standardUserDefaults] valueForKey:kSaveCurLanguageKey]; + if (saveLanguage && [saveLanguage isEqualToString:@"en"]){ + return saveLanguage; + } + + // 强制返回英文,忽略系统语言设置 + return @"en"; +} + ++(NSString *)uploadLanguageText{ + // EP 白包版本强制使用英文 + return @"en"; +} + ++(void)setLanguageText:(NSString *)language{ + [[NSUserDefaults standardUserDefaults]setValue:language forKey:kSaveCurLanguageKey]; + [[NSUserDefaults standardUserDefaults]synchronize]; +} + +// 辅助方法,用于映射本地化语言 - 重构为使用统一配置 ++ (NSString *)mapLanguageForLocalization:(NSString *)language { + // 首先尝试精确匹配 + for (NSDictionary *langConfig in [YMLanguageConfig supportedLanguages]) { + NSString *code = langConfig[@"code"]; + NSString *localizationCode = langConfig[@"localizationCode"]; + + if ([language isEqualToString:code] || [language isEqualToString:localizationCode]) { + return localizationCode; + } + } + + // 然后尝试前缀匹配 + for (NSDictionary *langConfig in [YMLanguageConfig supportedLanguages]) { + NSString *code = langConfig[@"code"]; + if ([language hasPrefix:code]) { + return langConfig[@"localizationCode"]; + } + } + + // 特殊处理:pt-BR 和 pt 的映射 + if ([language hasPrefix:@"pt"]) { + return @"pt-BR"; + } + + // 默认返回英文 + return [YMLanguageConfig defaultLanguage]; +} + +@end diff --git a/YuMi/Tools/Bundle/YMLanguageConfig.h b/YuMi/Tools/Bundle/YMLanguageConfig.h index 05905af..bca2f39 100644 --- a/YuMi/Tools/Bundle/YMLanguageConfig.h +++ b/YuMi/Tools/Bundle/YMLanguageConfig.h @@ -1,9 +1,7 @@ -// -// YMLanguageConfig.h -// YuMi -// + + // Created by Linus on 2024/12/19. -// + #import @@ -11,19 +9,19 @@ NS_ASSUME_NONNULL_BEGIN @interface YMLanguageConfig : NSObject -/// 支持的语言列表 + + (NSArray *)supportedLanguages; -/// 根据语言代码获取显示名称 + + (NSString *)displayNameForLanguageCode:(NSString *)languageCode; -/// 根据语言代码获取本地化代码 + + (NSString *)localizationCodeForLanguageCode:(NSString *)languageCode; -/// 检查是否为RTL语言 + + (BOOL)isRTLanguage:(NSString *)languageCode; -/// 获取默认语言 + + (NSString *)defaultLanguage; @end diff --git a/YuMi/Tools/Bundle/YMLanguageConfig.h.backup b/YuMi/Tools/Bundle/YMLanguageConfig.h.backup new file mode 100644 index 0000000..05905af --- /dev/null +++ b/YuMi/Tools/Bundle/YMLanguageConfig.h.backup @@ -0,0 +1,31 @@ +// +// YMLanguageConfig.h +// YuMi +// +// Created by Linus on 2024/12/19. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface YMLanguageConfig : NSObject + +/// 支持的语言列表 ++ (NSArray *)supportedLanguages; + +/// 根据语言代码获取显示名称 ++ (NSString *)displayNameForLanguageCode:(NSString *)languageCode; + +/// 根据语言代码获取本地化代码 ++ (NSString *)localizationCodeForLanguageCode:(NSString *)languageCode; + +/// 检查是否为RTL语言 ++ (BOOL)isRTLanguage:(NSString *)languageCode; + +/// 获取默认语言 ++ (NSString *)defaultLanguage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Bundle/YMLanguageConfig.m b/YuMi/Tools/Bundle/YMLanguageConfig.m index e19ccef..c4426d2 100644 --- a/YuMi/Tools/Bundle/YMLanguageConfig.m +++ b/YuMi/Tools/Bundle/YMLanguageConfig.m @@ -1,9 +1,7 @@ -// -// YMLanguageConfig.m -// YuMi -// + + // Created by Linus on 2024/12/19. -// + #import "YMLanguageConfig.h" @@ -13,7 +11,7 @@ static NSArray *languages = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - // EP 白包版本只支持英文 + languages = @[ @{@"code": @"en", @"localizationCode": @"en", @"displayName": @"English", @"isRTL": @NO} ]; @@ -27,7 +25,7 @@ return language[@"displayName"]; } } - return @"English"; // 默认返回英文 + return @"English"; } + (NSString *)localizationCodeForLanguageCode:(NSString *)languageCode { @@ -36,7 +34,7 @@ return language[@"localizationCode"]; } } - return @"en"; // 默认返回英文 + return @"en"; } + (BOOL)isRTLanguage:(NSString *)languageCode { diff --git a/YuMi/Tools/Bundle/YMLanguageConfig.m.backup b/YuMi/Tools/Bundle/YMLanguageConfig.m.backup new file mode 100644 index 0000000..e19ccef --- /dev/null +++ b/YuMi/Tools/Bundle/YMLanguageConfig.m.backup @@ -0,0 +1,55 @@ +// +// YMLanguageConfig.m +// YuMi +// +// Created by Linus on 2024/12/19. +// + +#import "YMLanguageConfig.h" + +@implementation YMLanguageConfig + ++ (NSArray *)supportedLanguages { + static NSArray *languages = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // EP 白包版本只支持英文 + languages = @[ + @{@"code": @"en", @"localizationCode": @"en", @"displayName": @"English", @"isRTL": @NO} + ]; + }); + return languages; +} + ++ (NSString *)displayNameForLanguageCode:(NSString *)languageCode { + for (NSDictionary *language in [self supportedLanguages]) { + if ([language[@"code"] isEqualToString:languageCode]) { + return language[@"displayName"]; + } + } + return @"English"; // 默认返回英文 +} + ++ (NSString *)localizationCodeForLanguageCode:(NSString *)languageCode { + for (NSDictionary *language in [self supportedLanguages]) { + if ([language[@"code"] isEqualToString:languageCode]) { + return language[@"localizationCode"]; + } + } + return @"en"; // 默认返回英文 +} + ++ (BOOL)isRTLanguage:(NSString *)languageCode { + for (NSDictionary *language in [self supportedLanguages]) { + if ([language[@"code"] isEqualToString:languageCode]) { + return [language[@"isRTL"] boolValue]; + } + } + return NO; +} + ++ (NSString *)defaultLanguage { + return @"en"; +} + +@end diff --git a/YuMi/Tools/CountDown/CountDownHelper.h b/YuMi/Tools/CountDown/CountDownHelper.h index 0dfda72..245ff05 100644 --- a/YuMi/Tools/CountDown/CountDownHelper.h +++ b/YuMi/Tools/CountDown/CountDownHelper.h @@ -1,9 +1,7 @@ -// -// CountDownHelper.h -// xplan-ios -// + + // Created by 冯硕 on 2021/9/15. -// 倒计时 + #import @@ -11,35 +9,35 @@ NS_ASSUME_NONNULL_BEGIN @protocol CountDownHelperDelegate @optional -///倒计时结束 + - (void)onCountdownFinish; -///倒计时进行 + - (void)onCountdownOpen:(int)time; -///顺计时结束 + - (void)onClockwiseFinish; -///顺计时进行 + - (void)onClockwiseOpen:(CGFloat)time; @end @interface CountDownHelper : NSObject -///倒计时是否完成 + @property (nonatomic,assign) BOOL isCountdownFinish; -///顺计时的秒数 + @property (nonatomic,assign) CGFloat seconds; -///代理 + @property (nonatomic,weak) id delegate; -///单例 + + (instancetype)shareHelper; -// 停止倒计时 + - (void)stopCountDown; -///开始倒计时 + - (void)openCountdownWithTime:(int)totalTime; -// 停止顺计时 + - (void)stopClockwise; -///开始顺计时 + - (void)openClockwiseWithTime:(int)totalTime; diff --git a/YuMi/Tools/CountDown/CountDownHelper.h.backup b/YuMi/Tools/CountDown/CountDownHelper.h.backup new file mode 100644 index 0000000..0dfda72 --- /dev/null +++ b/YuMi/Tools/CountDown/CountDownHelper.h.backup @@ -0,0 +1,48 @@ +// +// CountDownHelper.h +// xplan-ios +// +// Created by 冯硕 on 2021/9/15. +// 倒计时 + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol CountDownHelperDelegate +@optional +///倒计时结束 +- (void)onCountdownFinish; +///倒计时进行 +- (void)onCountdownOpen:(int)time; +///顺计时结束 +- (void)onClockwiseFinish; +///顺计时进行 +- (void)onClockwiseOpen:(CGFloat)time; +@end + + +@interface CountDownHelper : NSObject +///倒计时是否完成 +@property (nonatomic,assign) BOOL isCountdownFinish; +///顺计时的秒数 +@property (nonatomic,assign) CGFloat seconds; +///代理 +@property (nonatomic,weak) id delegate; + +///单例 ++ (instancetype)shareHelper; +// 停止倒计时 +- (void)stopCountDown; +///开始倒计时 +- (void)openCountdownWithTime:(int)totalTime; + +// 停止顺计时 +- (void)stopClockwise; +///开始顺计时 +- (void)openClockwiseWithTime:(int)totalTime; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/CountDown/CountDownHelper.m b/YuMi/Tools/CountDown/CountDownHelper.m index 7219eba..68e3182 100644 --- a/YuMi/Tools/CountDown/CountDownHelper.m +++ b/YuMi/Tools/CountDown/CountDownHelper.m @@ -1,9 +1,7 @@ -// -// CountDownHelper.m -// xplan-ios -// + + // Created by 冯硕 on 2021/9/15. -// + #import "CountDownHelper.h" @@ -33,7 +31,7 @@ return helper; } -// 停止倒计时 + - (void)stopCountDown { if (self.timer != nil) { dispatch_source_cancel(self.timer); @@ -48,24 +46,24 @@ } self.isCountdownFinish = YES; } -// 开始倒计时 + - (void)openCountdownWithTime:(int)totalTime{ if (time <= 0) { return; } - __block CGFloat time = (CGFloat)totalTime; //倒计时时间 + __block CGFloat time = (CGFloat)totalTime; if (self.timer != nil) { dispatch_source_cancel(self.timer); } dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - dispatch_source_set_timer(self.timer,dispatch_walltime(NULL, 0),1*NSEC_PER_SEC, 0); //每秒执行 + dispatch_source_set_timer(self.timer,dispatch_walltime(NULL, 0),1*NSEC_PER_SEC, 0); __weak typeof(self) weakself = self; dispatch_source_set_event_handler(self.timer, ^{ __strong typeof(weakself) self = weakself; - if(time <= 0){ //倒计时结束,关闭 + if(time <= 0){ dispatch_source_cancel(self.timer); dispatch_async(dispatch_get_main_queue(), ^{ self.isCountdownFinish = YES; @@ -78,7 +76,7 @@ time--; self.isCountdownFinish = NO; dispatch_async(dispatch_get_main_queue(), ^{ - //设置按钮显示读秒效果 + if (self.delegate && [self.delegate respondsToSelector:@selector(onCountdownOpen:)]) { [self.delegate onCountdownOpen:time]; } @@ -93,17 +91,17 @@ if (totalTime <= 0) { return; } - __block CGFloat backTime = 0; //倒计时时间 + __block CGFloat backTime = 0; if (self.clockwiseTimer != nil) { dispatch_source_cancel(self.clockwiseTimer); } dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); self.clockwiseTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - dispatch_source_set_timer(self.clockwiseTimer,dispatch_walltime(NULL, 0),self.seconds*NSEC_PER_SEC, 0); //每秒执行 + dispatch_source_set_timer(self.clockwiseTimer,dispatch_walltime(NULL, 0),self.seconds*NSEC_PER_SEC, 0); __weak typeof(self) weakself = self; dispatch_source_set_event_handler(self.clockwiseTimer, ^{ __strong typeof(weakself) self = weakself; - if(backTime > totalTime){ //倒计时结束,关闭 + if(backTime > totalTime){ dispatch_source_cancel(self.clockwiseTimer); dispatch_async(dispatch_get_main_queue(), ^{ self.isCountdownFinish = YES; @@ -116,7 +114,7 @@ backTime = backTime + self.seconds; self.isCountdownFinish = NO; dispatch_async(dispatch_get_main_queue(), ^{ - //设置按钮显示读秒效果 + if(self.delegate && [self.delegate respondsToSelector:@selector(onClockwiseOpen:)]){ [self.delegate onClockwiseOpen:backTime]; diff --git a/YuMi/Tools/CountDown/CountDownHelper.m.backup b/YuMi/Tools/CountDown/CountDownHelper.m.backup new file mode 100644 index 0000000..7219eba --- /dev/null +++ b/YuMi/Tools/CountDown/CountDownHelper.m.backup @@ -0,0 +1,132 @@ +// +// CountDownHelper.m +// xplan-ios +// +// Created by 冯硕 on 2021/9/15. +// + +#import "CountDownHelper.h" + +@interface CountDownHelper () +@property (strong, nonatomic) dispatch_source_t timer; +@property (strong, nonatomic) dispatch_source_t clockwiseTimer; +@end + +@implementation CountDownHelper +-(void)dealloc{ + [self stopCountDown]; +} +-(instancetype)init{ + self = [super init]; + if(self){ + self.isCountdownFinish = YES; + self.seconds = 1.0; + } + return self; +} ++ (instancetype)shareHelper { + static dispatch_once_t onceToken; + static CountDownHelper * helper = nil; + dispatch_once(&onceToken, ^{ + helper = [[CountDownHelper alloc] init]; + }); + return helper; +} + +// 停止倒计时 +- (void)stopCountDown { + if (self.timer != nil) { + dispatch_source_cancel(self.timer); + self.timer = nil; + } + self.isCountdownFinish = YES; +} +- (void)stopClockwise { + if (self.clockwiseTimer != nil) { + dispatch_source_cancel(self.clockwiseTimer); + self.clockwiseTimer = nil; + } + self.isCountdownFinish = YES; +} +// 开始倒计时 +- (void)openCountdownWithTime:(int)totalTime{ + if (time <= 0) { + return; + } + + __block CGFloat time = (CGFloat)totalTime; //倒计时时间 + + if (self.timer != nil) { + dispatch_source_cancel(self.timer); + } + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); + dispatch_source_set_timer(self.timer,dispatch_walltime(NULL, 0),1*NSEC_PER_SEC, 0); //每秒执行 + __weak typeof(self) weakself = self; + dispatch_source_set_event_handler(self.timer, ^{ + __strong typeof(weakself) self = weakself; + if(time <= 0){ //倒计时结束,关闭 + dispatch_source_cancel(self.timer); + dispatch_async(dispatch_get_main_queue(), ^{ + self.isCountdownFinish = YES; + if (self.delegate && [self.delegate respondsToSelector:@selector(onCountdownFinish)]) { + [self.delegate onCountdownFinish]; + + } + }); + }else{ + time--; + self.isCountdownFinish = NO; + dispatch_async(dispatch_get_main_queue(), ^{ + //设置按钮显示读秒效果 + if (self.delegate && [self.delegate respondsToSelector:@selector(onCountdownOpen:)]) { + [self.delegate onCountdownOpen:time]; + } + }); + + } + }); + dispatch_resume(self.timer); +} + +- (void)openClockwiseWithTime:(int)totalTime{ + if (totalTime <= 0) { + return; + } + __block CGFloat backTime = 0; //倒计时时间 + if (self.clockwiseTimer != nil) { + dispatch_source_cancel(self.clockwiseTimer); + } + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + self.clockwiseTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); + dispatch_source_set_timer(self.clockwiseTimer,dispatch_walltime(NULL, 0),self.seconds*NSEC_PER_SEC, 0); //每秒执行 + __weak typeof(self) weakself = self; + dispatch_source_set_event_handler(self.clockwiseTimer, ^{ + __strong typeof(weakself) self = weakself; + if(backTime > totalTime){ //倒计时结束,关闭 + dispatch_source_cancel(self.clockwiseTimer); + dispatch_async(dispatch_get_main_queue(), ^{ + self.isCountdownFinish = YES; + if (self.delegate && [self.delegate respondsToSelector:@selector(onClockwiseFinish)]) { + [self.delegate onClockwiseFinish]; + + } + }); + }else{ + backTime = backTime + self.seconds; + self.isCountdownFinish = NO; + dispatch_async(dispatch_get_main_queue(), ^{ + //设置按钮显示读秒效果 + + if(self.delegate && [self.delegate respondsToSelector:@selector(onClockwiseOpen:)]){ + [self.delegate onClockwiseOpen:backTime]; + } + + + }); + + } + }); + dispatch_resume(self.clockwiseTimer); +} +@end diff --git a/YuMi/Tools/Date/NSDate+DateUtils.h b/YuMi/Tools/Date/NSDate+DateUtils.h index 32ed6f7..0fc2e38 100644 --- a/YuMi/Tools/Date/NSDate+DateUtils.h +++ b/YuMi/Tools/Date/NSDate+DateUtils.h @@ -1,9 +1,7 @@ -// -// NSDate+DateUtils.h -// YUMI -// + + // Created by YUMI on 2022/4/12. -// + #import diff --git a/YuMi/Tools/Date/NSDate+DateUtils.h.backup b/YuMi/Tools/Date/NSDate+DateUtils.h.backup new file mode 100644 index 0000000..32ed6f7 --- /dev/null +++ b/YuMi/Tools/Date/NSDate+DateUtils.h.backup @@ -0,0 +1,42 @@ +// +// NSDate+DateUtils.h +// YUMI +// +// Created by YUMI on 2022/4/12. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDate (DateUtils) ++ (NSDateFormatter *)shareDateFormatter; + +- (NSInteger)daysBetween:(NSDate *)aDate; + +- (NSDate *)dateByAddingDays:(NSInteger)days; +- (NSDate *)dateByAddingSeconds:(NSInteger)seconds; + +- (NSString *)stringForFormat:(NSString *)format; + ++ (NSString *)stringFromDate:(NSDate *)date; ++ (NSDate *)at_dateFromString:(NSString *)dateString; ++(NSString *)getNowTimeTimestamp; ++ (NSString *)getCurrentTimeWithFormat:(NSString *)format; ++(NSString *)timestampSwitchTime:(NSInteger)timestamp andFormatter:(NSString *)format; +#pragma mark - 将某个时间戳转化成 时间 ++ (NSString *)timestampSwitchTime:(NSInteger)timestamp formatter:(NSString *)format; ++ (NSInteger)pleaseInsertStarTimeo:(NSString *)time1 andInsertEndTime:(NSString *)time2; + +- (NSString *) stringForYearMonthDayDashed; + +@end + +@interface NSCalendar (Pick) + ++ (instancetype)sharedCalendar; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Date/NSDate+DateUtils.m b/YuMi/Tools/Date/NSDate+DateUtils.m index e24d4da..f08f126 100644 --- a/YuMi/Tools/Date/NSDate+DateUtils.m +++ b/YuMi/Tools/Date/NSDate+DateUtils.m @@ -1,9 +1,7 @@ -// -// NSDate+DateUtils.m -// YUMI -// + + // Created by YUMI on 2022/4/12. -// + #import "NSDate+DateUtils.h" @@ -93,7 +91,6 @@ NSString * const kDateFormatYYMMDDTHHmmss = @"yyyy-MM-dd'T'HH:mm:ss"; } - +(BOOL)isDateInToday:(NSDate *)date{ NSTimeInterval secondsPerDay = 24 * 60 * 60; @@ -103,7 +100,7 @@ NSString * const kDateFormatYYMMDDTHHmmss = @"yyyy-MM-dd'T'HH:mm:ss"; tomorrow = [today dateByAddingTimeInterval: secondsPerDay]; yesterday = [today dateByAddingTimeInterval: -secondsPerDay]; - // 10 first characters of description is the calendar date: + NSString * todayString = [[today description] substringToIndex:10]; NSString * yesterdayString = [[yesterday description] substringToIndex:10]; NSString * tomorrowString = [[tomorrow description] substringToIndex:10]; @@ -121,7 +118,7 @@ NSString * const kDateFormatYYMMDDTHHmmss = @"yyyy-MM-dd'T'HH:mm:ss"; NSTimeInterval a=[dat timeIntervalSince1970]; - NSString*timeString = [NSString stringWithFormat:@"%0.f", a];//转为字符型 + NSString*timeString = [NSString stringWithFormat:@"%0.f", a]; return timeString; } @@ -129,13 +126,12 @@ NSString * const kDateFormatYYMMDDTHHmmss = @"yyyy-MM-dd'T'HH:mm:ss"; +(NSString *)timestampSwitchTime:(NSInteger)timestamp andFormatter:(NSString *)format{ - NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; - [formatter setDateFormat:format]; // (@"YYYY-MM-dd hh:mm:ss")----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 + [formatter setDateFormat:format]; NSDate *confromTimesp = [NSDate dateWithTimeIntervalSince1970:timestamp]; NSString *confromTimespStr = [formatter stringFromDate:confromTimesp]; return confromTimespStr; @@ -145,29 +141,29 @@ NSString * const kDateFormatYYMMDDTHHmmss = @"yyyy-MM-dd'T'HH:mm:ss"; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; - [formatter setDateFormat:format]; // (@"YYYY-MM-dd hh:mm:ss")----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 + [formatter setDateFormat:format]; NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; [formatter setTimeZone:timeZone]; NSDate *confromTimesp = [NSDate dateWithTimeIntervalSince1970:timestamp]; - /// 在当前时间,后退30分钟 = 1800 -// confromTimesp = [confromTimesp dateByAddingTimeInterval:-1800]; + + NSString *confromTimespStr = [formatter stringFromDate:confromTimesp]; return confromTimespStr; } + (NSInteger)pleaseInsertStarTimeo:(NSString *)time1 andInsertEndTime:(NSString *)time2{ - // 1.将时间转换为date + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"YYYY-MM-dd hh:mm:ss"; NSDate *date1 = [formatter dateFromString:time1]; NSDate *date2 = [formatter dateFromString:time2]; - // 2.创建日历 + NSCalendar *calendar = [NSCalendar currentCalendar]; -// NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + NSCalendarUnit type = NSCalendarUnitSecond; - // 3.利用日历对象比较两个时间的差值 + NSDateComponents *cmps = [calendar components:type fromDate:date1 toDate:date2 options:0]; - // 4.输出结果 -// NSLog(@"两个时间相差%ld年%ld月%ld日%ld小时%ld分钟%ld秒", cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second); + + return cmps.second; } + (NSString *)getCurrentTimeWithFormat:(NSString *)format{ diff --git a/YuMi/Tools/Date/NSDate+DateUtils.m.backup b/YuMi/Tools/Date/NSDate+DateUtils.m.backup new file mode 100644 index 0000000..e24d4da --- /dev/null +++ b/YuMi/Tools/Date/NSDate+DateUtils.m.backup @@ -0,0 +1,193 @@ +// +// NSDate+DateUtils.m +// YUMI +// +// Created by YUMI on 2022/4/12. +// + +#import "NSDate+DateUtils.h" + +NSString * const kDateFormatYYYYMMDD = @"yyyy-MM-dd"; +NSString * const kDateFormatYYMMDDTHHmmss = @"yyyy-MM-dd'T'HH:mm:ss"; + +@implementation NSDate (DateUtils) ++ (NSDateFormatter *)shareDateFormatter { + static NSDateFormatter *currentFormatter = nil; + static dispatch_once_t sharedDateFormatter_onceToken; + dispatch_once(&sharedDateFormatter_onceToken, ^{ + if (!currentFormatter) { + currentFormatter = [[NSDateFormatter alloc] init]; + [currentFormatter setDateFormat:kDateFormatYYYYMMDD]; + [currentFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; + } + }); + return currentFormatter; +} + +- (NSDate *)dateByAddingDays:(NSInteger)days { + NSCalendar *calendar = [NSCalendar sharedCalendar]; + NSDateComponents *components = [[NSDateComponents alloc] init]; + [components setDay:days]; + return [calendar dateByAddingComponents:components toDate:self options:0]; +} + +- (NSDate *)dateByAddingSeconds:(NSInteger)seconds { + NSCalendar *calendar = [NSCalendar sharedCalendar]; + NSDateComponents *components = [[NSDateComponents alloc] init]; + [components setSecond:seconds]; + return [calendar dateByAddingComponents:components toDate:self options:0]; +} + +- (NSInteger)daysBetween:(NSDate *)aDate { + NSUInteger unitFlags = NSCalendarUnitDay; + NSDate *from = [NSDate at_dateFromString:[self stringForYearMonthDayDashed]]; + NSDate *to = [NSDate at_dateFromString:[aDate stringForYearMonthDayDashed]]; + NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + NSDateComponents *components = [calendar components:unitFlags fromDate:from toDate:to options:0]; + return labs([components day]) + 1; +} + +- (NSString *) stringForYearMonthDayDashed { + return [self stringForFormat:kDateFormatYYYYMMDD]; +} + +- (NSString *)stringForFormat:(NSString *)format { + if (!format) { + return nil; + } + + NSDateFormatter *formatter = [NSDate shareDateFormatter]; + [formatter setDateFormat:format]; + + NSString *timeStr = [formatter stringFromDate:self]; + return timeStr; +} + ++ (NSDate *)at_dateFromString:(NSString *)dateString { + NSDateFormatter *dateFormatter = [self shareDateFormatter]; + if (dateString.length > kDateFormatYYYYMMDD.length) { + [dateFormatter setDateFormat:kDateFormatYYMMDDTHHmmss]; + } else { + [dateFormatter setDateFormat:kDateFormatYYYYMMDD]; + } + NSDate *date = [dateFormatter dateFromString:dateString]; + if (!date) { + date = [NSDate date]; + } + return date; +} + ++ (NSString *)stringFromDate:(NSDate *)date { + NSDateFormatter * currentFormatter = [[NSDateFormatter alloc] init]; + if ([self isDateInToday:date]) { + [currentFormatter setDateFormat:@"HH:mm"]; + } else { + if (date.timeIntervalSince1970 > 0) { + [currentFormatter setDateFormat:YMLocalizedString(@"DateUtils0")]; + } else{ + [currentFormatter setDateFormat:YMLocalizedString(@"DateUtils1")]; + } + } + NSString *dateString = [currentFormatter stringFromDate: date]; + return dateString; +} + + + ++(BOOL)isDateInToday:(NSDate *)date{ + + NSTimeInterval secondsPerDay = 24 * 60 * 60; + NSDate *today = [[NSDate alloc] init]; + NSDate *tomorrow, *yesterday; + + tomorrow = [today dateByAddingTimeInterval: secondsPerDay]; + yesterday = [today dateByAddingTimeInterval: -secondsPerDay]; + + // 10 first characters of description is the calendar date: + NSString * todayString = [[today description] substringToIndex:10]; + NSString * yesterdayString = [[yesterday description] substringToIndex:10]; + NSString * tomorrowString = [[tomorrow description] substringToIndex:10]; + NSString * dateString = [[date description] substringToIndex:10]; + if ([dateString isEqualToString:todayString]){ + return YES; + } else { + return NO; + } +} + ++(NSString *)getNowTimeTimestamp{ + + NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0]; + + NSTimeInterval a=[dat timeIntervalSince1970]; + + NSString*timeString = [NSString stringWithFormat:@"%0.f", a];//转为字符型 + + return timeString; +} + ++(NSString *)timestampSwitchTime:(NSInteger)timestamp andFormatter:(NSString *)format{ + + + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + + [formatter setTimeStyle:NSDateFormatterShortStyle]; + + [formatter setDateFormat:format]; // (@"YYYY-MM-dd hh:mm:ss")----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 + NSDate *confromTimesp = [NSDate dateWithTimeIntervalSince1970:timestamp]; + NSString *confromTimespStr = [formatter stringFromDate:confromTimesp]; + return confromTimespStr; +} +#pragma mark - 将某个时间戳转化成 时间 ++ (NSString *)timestampSwitchTime:(NSInteger)timestamp formatter:(NSString *)format{ + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:format]; // (@"YYYY-MM-dd hh:mm:ss")----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 + NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setTimeZone:timeZone]; + NSDate *confromTimesp = [NSDate dateWithTimeIntervalSince1970:timestamp]; + /// 在当前时间,后退30分钟 = 1800 +// confromTimesp = [confromTimesp dateByAddingTimeInterval:-1800]; + NSString *confromTimespStr = [formatter stringFromDate:confromTimesp]; + return confromTimespStr; +} ++ (NSInteger)pleaseInsertStarTimeo:(NSString *)time1 andInsertEndTime:(NSString *)time2{ + // 1.将时间转换为date + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"YYYY-MM-dd hh:mm:ss"; + NSDate *date1 = [formatter dateFromString:time1]; + NSDate *date2 = [formatter dateFromString:time2]; + // 2.创建日历 + NSCalendar *calendar = [NSCalendar currentCalendar]; +// NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + NSCalendarUnit type = NSCalendarUnitSecond; + // 3.利用日历对象比较两个时间的差值 + NSDateComponents *cmps = [calendar components:type fromDate:date1 toDate:date2 options:0]; + // 4.输出结果 +// NSLog(@"两个时间相差%ld年%ld月%ld日%ld小时%ld分钟%ld秒", cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second); + return cmps.second; +} ++ (NSString *)getCurrentTimeWithFormat:(NSString *)format{ + NSDate *now = [NSDate date]; + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; + formatter.dateFormat = format; + NSString *dateStr = [formatter stringFromDate:now]; + return dateStr; +} +@end + +@implementation NSCalendar (Pick) + ++ (instancetype)sharedCalendar +{ + static id instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [NSCalendar currentCalendar]; + }); + return instance; +} +@end diff --git a/YuMi/Tools/Date/NVDate.h b/YuMi/Tools/Date/NVDate.h index 7889a8b..086be43 100644 --- a/YuMi/Tools/Date/NVDate.h +++ b/YuMi/Tools/Date/NVDate.h @@ -1,95 +1,94 @@ -// -// NVDate.h -// -// Created by Noval Agung Prayogo on 2/5/14. -// Copyright (c) 2014 Noval Agung Prayogo. All rights reserved. -// - -#import - -typedef NS_OPTIONS(NSUInteger, NVDayUnit) { - NVDayUnitSunday = 1, - NVDayUnitMonday = 2, - NVDayUnitTuesday = 3, - NVDayUnitWednesday = 4, - NVDayUnitThursday = 5, - NVDayUnitFriday = 6, - NVDayUnitSaturday = 7 -}; - -typedef NS_OPTIONS(NSUInteger, NVMonthUnit) { - NVMonthUnitJanuary = 1, - NVMonthUnitFebruary = 2, - NVMonthUnitMarch = 3, - NVMonthUnitApril = 4, - NVMonthUnitMay = 5, - NVMonthUnitJune = 6, - NVMonthUnitJuly = 7, - NVMonthUnitAugust = 8, - NVMonthUnitSeptember = 9, - NVMonthUnitOctober = 10, - NVMonthUnitNovember = 11, - NVMonthUnitDecember = 12, -}; - -@interface NVDate : NSObject - -- (id)initUsingToday; -- (id)initUsingDate:(NSDate *)date; -- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day; -- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second; -- (id)initUsingString:(NSString *)stringDate; -- (id)initUsingString:(NSString *)stringDate withFormat:(NSString *)dateFormat; -- (id)initUsingSeconds:(NSInteger)seconds; - -- (NSDate *)date; - -- (NSString *)stringValue; -- (NSString *)stringValueWithFormat:(NSString *)dateFormat; - -- (instancetype)zeroTime; - -- (instancetype)previousDay; -- (instancetype)previousDays:(NSInteger)days; -- (instancetype)nextDay; -- (instancetype)nextDays:(NSInteger)days; - -- (instancetype)previousWeek; -- (instancetype)previousWeeks:(NSInteger)weeks; -- (instancetype)nextWeek; -- (instancetype)nextWeeks:(NSInteger)weeks; - -- (instancetype)previousMonth; -- (instancetype)previousMonths:(NSInteger)months; -- (instancetype)nextMonth; -- (instancetype)nextMonths:(NSInteger)months; - -- (instancetype)previousYear; -- (instancetype)previousYears:(NSInteger)years; -- (instancetype)nextYear; -- (instancetype)nextYears:(NSInteger)years; - -- (instancetype)firstDayOfMonth; -- (instancetype)lastDayOfMonth; - -- (instancetype)firstMonthOfYear; -- (instancetype)lastMonthOfYear; - -- (instancetype)previousDayOfDayName:(NVDayUnit)dayUnit; -- (instancetype)nextDayOfDayName:(NVDayUnit)dayUnit; - -- (BOOL)isCurrentDayName:(NVDayUnit)dayUnit; -- (BOOL)isCurrentMonthName:(NVMonthUnit)monthUnit; - -@property NSString *dateFormatUsingString; -@property NSDateFormatterStyle dateFormatUsingStyle; -@property NSDateFormatterStyle timeFormatUsingStyle; -@property NSInteger year; -@property NSInteger month; -@property (readonly) NSInteger week; -@property NSInteger day; -@property NSInteger hour; -@property NSInteger minute; -@property NSInteger second; - -@end + + +// Created by Noval Agung Prayogo on 2/5/14. +// Copyright (c) 2014 Noval Agung Prayogo. All rights reserved. + + +#import + +typedef NS_OPTIONS(NSUInteger, NVDayUnit) { + NVDayUnitSunday = 1, + NVDayUnitMonday = 2, + NVDayUnitTuesday = 3, + NVDayUnitWednesday = 4, + NVDayUnitThursday = 5, + NVDayUnitFriday = 6, + NVDayUnitSaturday = 7 +}; + +typedef NS_OPTIONS(NSUInteger, NVMonthUnit) { + NVMonthUnitJanuary = 1, + NVMonthUnitFebruary = 2, + NVMonthUnitMarch = 3, + NVMonthUnitApril = 4, + NVMonthUnitMay = 5, + NVMonthUnitJune = 6, + NVMonthUnitJuly = 7, + NVMonthUnitAugust = 8, + NVMonthUnitSeptember = 9, + NVMonthUnitOctober = 10, + NVMonthUnitNovember = 11, + NVMonthUnitDecember = 12, +}; + +@interface NVDate : NSObject + +- (id)initUsingToday; +- (id)initUsingDate:(NSDate *)date; +- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day; +- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second; +- (id)initUsingString:(NSString *)stringDate; +- (id)initUsingString:(NSString *)stringDate withFormat:(NSString *)dateFormat; +- (id)initUsingSeconds:(NSInteger)seconds; + +- (NSDate *)date; + +- (NSString *)stringValue; +- (NSString *)stringValueWithFormat:(NSString *)dateFormat; + +- (instancetype)zeroTime; + +- (instancetype)previousDay; +- (instancetype)previousDays:(NSInteger)days; +- (instancetype)nextDay; +- (instancetype)nextDays:(NSInteger)days; + +- (instancetype)previousWeek; +- (instancetype)previousWeeks:(NSInteger)weeks; +- (instancetype)nextWeek; +- (instancetype)nextWeeks:(NSInteger)weeks; + +- (instancetype)previousMonth; +- (instancetype)previousMonths:(NSInteger)months; +- (instancetype)nextMonth; +- (instancetype)nextMonths:(NSInteger)months; + +- (instancetype)previousYear; +- (instancetype)previousYears:(NSInteger)years; +- (instancetype)nextYear; +- (instancetype)nextYears:(NSInteger)years; + +- (instancetype)firstDayOfMonth; +- (instancetype)lastDayOfMonth; + +- (instancetype)firstMonthOfYear; +- (instancetype)lastMonthOfYear; + +- (instancetype)previousDayOfDayName:(NVDayUnit)dayUnit; +- (instancetype)nextDayOfDayName:(NVDayUnit)dayUnit; + +- (BOOL)isCurrentDayName:(NVDayUnit)dayUnit; +- (BOOL)isCurrentMonthName:(NVMonthUnit)monthUnit; + +@property NSString *dateFormatUsingString; +@property NSDateFormatterStyle dateFormatUsingStyle; +@property NSDateFormatterStyle timeFormatUsingStyle; +@property NSInteger year; +@property NSInteger month; +@property (readonly) NSInteger week; +@property NSInteger day; +@property NSInteger hour; +@property NSInteger minute; +@property NSInteger second; + +@end diff --git a/YuMi/Tools/Date/NVDate.h.backup b/YuMi/Tools/Date/NVDate.h.backup new file mode 100644 index 0000000..7889a8b --- /dev/null +++ b/YuMi/Tools/Date/NVDate.h.backup @@ -0,0 +1,95 @@ +// +// NVDate.h +// +// Created by Noval Agung Prayogo on 2/5/14. +// Copyright (c) 2014 Noval Agung Prayogo. All rights reserved. +// + +#import + +typedef NS_OPTIONS(NSUInteger, NVDayUnit) { + NVDayUnitSunday = 1, + NVDayUnitMonday = 2, + NVDayUnitTuesday = 3, + NVDayUnitWednesday = 4, + NVDayUnitThursday = 5, + NVDayUnitFriday = 6, + NVDayUnitSaturday = 7 +}; + +typedef NS_OPTIONS(NSUInteger, NVMonthUnit) { + NVMonthUnitJanuary = 1, + NVMonthUnitFebruary = 2, + NVMonthUnitMarch = 3, + NVMonthUnitApril = 4, + NVMonthUnitMay = 5, + NVMonthUnitJune = 6, + NVMonthUnitJuly = 7, + NVMonthUnitAugust = 8, + NVMonthUnitSeptember = 9, + NVMonthUnitOctober = 10, + NVMonthUnitNovember = 11, + NVMonthUnitDecember = 12, +}; + +@interface NVDate : NSObject + +- (id)initUsingToday; +- (id)initUsingDate:(NSDate *)date; +- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day; +- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second; +- (id)initUsingString:(NSString *)stringDate; +- (id)initUsingString:(NSString *)stringDate withFormat:(NSString *)dateFormat; +- (id)initUsingSeconds:(NSInteger)seconds; + +- (NSDate *)date; + +- (NSString *)stringValue; +- (NSString *)stringValueWithFormat:(NSString *)dateFormat; + +- (instancetype)zeroTime; + +- (instancetype)previousDay; +- (instancetype)previousDays:(NSInteger)days; +- (instancetype)nextDay; +- (instancetype)nextDays:(NSInteger)days; + +- (instancetype)previousWeek; +- (instancetype)previousWeeks:(NSInteger)weeks; +- (instancetype)nextWeek; +- (instancetype)nextWeeks:(NSInteger)weeks; + +- (instancetype)previousMonth; +- (instancetype)previousMonths:(NSInteger)months; +- (instancetype)nextMonth; +- (instancetype)nextMonths:(NSInteger)months; + +- (instancetype)previousYear; +- (instancetype)previousYears:(NSInteger)years; +- (instancetype)nextYear; +- (instancetype)nextYears:(NSInteger)years; + +- (instancetype)firstDayOfMonth; +- (instancetype)lastDayOfMonth; + +- (instancetype)firstMonthOfYear; +- (instancetype)lastMonthOfYear; + +- (instancetype)previousDayOfDayName:(NVDayUnit)dayUnit; +- (instancetype)nextDayOfDayName:(NVDayUnit)dayUnit; + +- (BOOL)isCurrentDayName:(NVDayUnit)dayUnit; +- (BOOL)isCurrentMonthName:(NVMonthUnit)monthUnit; + +@property NSString *dateFormatUsingString; +@property NSDateFormatterStyle dateFormatUsingStyle; +@property NSDateFormatterStyle timeFormatUsingStyle; +@property NSInteger year; +@property NSInteger month; +@property (readonly) NSInteger week; +@property NSInteger day; +@property NSInteger hour; +@property NSInteger minute; +@property NSInteger second; + +@end diff --git a/YuMi/Tools/Date/NVDate.m b/YuMi/Tools/Date/NVDate.m index 06840ed..aeff2bd 100644 --- a/YuMi/Tools/Date/NVDate.m +++ b/YuMi/Tools/Date/NVDate.m @@ -1,9 +1,8 @@ -// -// NVDate.m -// + + // Created by Noval Agung Prayogo on 2/5/14. // Copyright (c) 2014 Noval Agung Prayogo. All rights reserved. -// + #import "NVDate.h" diff --git a/YuMi/Tools/Date/NVDate.m.backup b/YuMi/Tools/Date/NVDate.m.backup new file mode 100644 index 0000000..06840ed --- /dev/null +++ b/YuMi/Tools/Date/NVDate.m.backup @@ -0,0 +1,394 @@ +// +// NVDate.m +// +// Created by Noval Agung Prayogo on 2/5/14. +// Copyright (c) 2014 Noval Agung Prayogo. All rights reserved. +// + +#import "NVDate.h" + +@implementation NVDate { + NSDateFormatter *_dateFormatter; + NSCalendar *_calendar; + NSDate *_date; + NSCalendarUnit _dateTimeCalendarUnit; +} + +- (id)init { + if (self = [super init]) { + _dateFormatter = [[NSDateFormatter alloc] init]; + _dateFormatter.dateStyle = NSDateFormatterFullStyle; + _dateFormatter.timeStyle = NSDateFormatterFullStyle; + + _calendar = [NSCalendar currentCalendar]; + + _date = [[NSDate alloc] init]; + + _dateTimeCalendarUnit = (NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit); + } + return self; +} + +- (id)initUsingToday { + if (self = [self init]) { + _date = [NSDate date]; + } + return self; +} + +- (id)initUsingString:(NSString *)stringDate { + if (self = [self init]) { + _date = [_dateFormatter dateFromString:stringDate]; + } + return self; +} + +- (id)initUsingString:(NSString *)stringDate withFormat:(NSString *)dateFormat { + if (self = [self init]) { + _dateFormatter.dateFormat = dateFormat; + _date = [_dateFormatter dateFromString:stringDate]; + } + return self; +} + +- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day { + if (self = [self init]) { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.year = year; + dateComponents.month = month; + dateComponents.day = day; + _date = [_calendar dateFromComponents:dateComponents]; + } + return self; +} + +- (id)initUsingYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second { + if (self = [self init]) { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.year = year; + dateComponents.month = month; + dateComponents.day = day; + dateComponents.hour = hour; + dateComponents.minute = minute; + dateComponents.second = second; + _date = [_calendar dateFromComponents:dateComponents]; + } + return self; +} + +- (id)initUsingDate:(NSDate *)date { + if (self = [self init]) { + _date = date; + } + return self; +} + +- (id)initUsingSeconds:(NSInteger)seconds { + if (self = [self init]) { + _date = [NSDate dateWithTimeIntervalSinceReferenceDate:seconds]; + } + return self; +} + +- (NSDate *)date { + return _date; +} + +- (NSString *)stringValue { + return [_dateFormatter stringFromDate:_date]; +} + +- (NSString *)stringValueWithFormat:(NSString *)dateFormat { + NSDateFormatter *localDateFormatter = [_dateFormatter copy]; + localDateFormatter.dateFormat = dateFormat; + + return [localDateFormatter stringFromDate:_date]; +} + +- (instancetype)zeroTime { + NSDateComponents *dateComponents = [_calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:_date]; + dateComponents.hour = 0; + dateComponents.minute = 0; + dateComponents.second = 0; + + _date = [_calendar dateFromComponents:dateComponents]; + + return self; +} + +- (void)setDateFormatUsingString:(NSString *)dateFormatUsingString { + _dateFormatter.dateFormat = dateFormatUsingString; +} + +- (NSString *)dateFormatUsingString { + return _dateFormatter.dateFormat; +} + +- (void)setDateFormatUsingStyle:(NSDateFormatterStyle)dateFormatUsingStyle { + _dateFormatter.dateStyle = dateFormatUsingStyle; +} + +- (NSDateFormatterStyle)dateFormatUsingStyle { + return _dateFormatter.dateStyle; +} + +- (void)setTimeFormatUsingStyle:(NSDateFormatterStyle)timeFormatUsingStyle { + _dateFormatter.timeStyle = timeFormatUsingStyle; +} + +- (NSDateFormatterStyle)timeFormatUsingStyle { + return _dateFormatter.timeStyle; +} + +- (instancetype)daysCalculate:(NSInteger)days isForward:(BOOL)isForward { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.day = days * (isForward ? 1 : -1); + _date = [_calendar dateByAddingComponents:dateComponents toDate:_date options:0]; + + return self; +} + +- (instancetype)previousDay { + return [self previousDays:1]; +} + +- (instancetype)previousDays:(NSInteger)days { + return [self daysCalculate:days isForward:NO]; +} + +- (instancetype)nextDay { + return [self nextDays:1]; +} + +- (instancetype)nextDays:(NSInteger)days { + return [self daysCalculate:days isForward:YES]; +} + +- (instancetype)weeksCalculate:(NSInteger)weeks isForward:(BOOL)isForward { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.day = (7 * weeks) * (isForward ? 1 : -1); + _date = [_calendar dateByAddingComponents:dateComponents toDate:_date options:0]; + + return self; +} + +- (instancetype)previousWeek { + return [self previousWeeks:1]; +} + +- (instancetype)previousWeeks:(NSInteger)weeks { + return [self weeksCalculate:weeks isForward:NO]; +} + +- (instancetype)nextWeek { + return [self nextWeeks:1]; +} + +- (instancetype)nextWeeks:(NSInteger)weeks { + return [self weeksCalculate:weeks isForward:YES]; +} + +- (instancetype)monthsCalculate:(NSInteger)months isForward:(BOOL)isForward { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.month = months * (isForward ? 1 : -1); + _date = [_calendar dateByAddingComponents:dateComponents toDate:_date options:0]; + + return self; +} + +- (instancetype)previousMonth { + return [self previousMonths:1]; +} + +- (instancetype)previousMonths:(NSInteger)months { + return [self monthsCalculate:months isForward:NO]; +} + +- (instancetype)nextMonth { + return [self nextMonths:1]; +} + +- (instancetype)nextMonths:(NSInteger)months { + return [self monthsCalculate:months isForward:YES]; +} + +- (instancetype)yearsCalculate:(NSInteger)years isForward:(BOOL)isForward { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.year = years * (isForward ? 1 : -1); + _date = [_calendar dateByAddingComponents:dateComponents toDate:_date options:0]; + + return self; +} + +- (instancetype)previousYear { + return [self previousYears:1]; +} + +- (instancetype)previousYears:(NSInteger)years { + return [self yearsCalculate:years isForward:NO]; +} + +- (instancetype)nextYear { + return [self nextYears:1]; +} + +- (instancetype)nextYears:(NSInteger)years { + return [self yearsCalculate:years isForward:YES]; +} + +- (instancetype)firstDayOfMonth { + NSDateComponents *dateComponents = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + dateComponents.day = 1; + _date = [_calendar dateFromComponents:dateComponents]; + + return self; +} + +- (instancetype)lastDayOfMonth { + NSDateComponents *dateComponents; + NSDate *date; + + dateComponents = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + dateComponents.day = 1; + date = [_calendar dateFromComponents:dateComponents]; + dateComponents = [[NSDateComponents alloc] init]; + dateComponents.month = 1; + date = [_calendar dateByAddingComponents:dateComponents toDate:date options:0]; + dateComponents = [[NSDateComponents alloc] init]; + dateComponents.day = -1; + _date = [_calendar dateByAddingComponents:dateComponents toDate:date options:0]; + + return self; +} + +- (instancetype)firstMonthOfYear { + NSDateComponents *dateComponents = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + dateComponents.month = NVMonthUnitJanuary; + _date = [_calendar dateFromComponents:dateComponents]; + + return self; +} + +- (instancetype)lastMonthOfYear { + NSDateComponents *dateComponents = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + dateComponents.month = NVMonthUnitDecember; + _date = [_calendar dateFromComponents:dateComponents]; + + return self; +} + +- (instancetype)previousDayOfDayName:(NVDayUnit)dayUnit { + NSInteger currentWeekDay = [_calendar components:_dateTimeCalendarUnit fromDate:_date].weekday; + + if (currentWeekDay == dayUnit) + return [self previousWeek]; + + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + + if (currentWeekDay > dayUnit) + dateComponents.day = -(currentWeekDay - dayUnit); + else + dateComponents.day = -currentWeekDay - (7 - dayUnit); + + _date = [_calendar dateByAddingComponents:dateComponents toDate:_date options:0]; + + return self; +} + +- (instancetype)nextDayOfDayName:(NVDayUnit)dayUnit { + NSInteger currentWeekDay = [_calendar components:_dateTimeCalendarUnit fromDate:_date].weekday; + + if (currentWeekDay == dayUnit) + return [self nextWeek]; + + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + + if (currentWeekDay < dayUnit) + dateComponents.day = dayUnit - currentWeekDay; + else + dateComponents.day = -currentWeekDay + dayUnit; + + _date = [_calendar dateByAddingComponents:dateComponents toDate:_date options:0]; + + return self; +} + +- (BOOL)isCurrentDayName:(NVDayUnit)dayUnit { + return ([_calendar components:_dateTimeCalendarUnit fromDate:_date].weekday == dayUnit); +} + +- (BOOL)isCurrentMonthName:(NVMonthUnit)monthUnit { + return ([_calendar components:_dateTimeCalendarUnit fromDate:_date].month == monthUnit); +} + +- (NSInteger)year { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].year; +} + +- (void)setYear:(NSInteger)year { + NSDateComponents *components = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + components.year = year; + + _date = [_calendar dateFromComponents:components]; +} + +- (NSInteger)month { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].month; +} + +- (void)setMonth:(NSInteger)month { + NSDateComponents *components = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + components.month = month; + + _date = [_calendar dateFromComponents:components]; +} + +- (NSInteger)week { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].weekday; +} + +- (NSInteger)day { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].day; +} + +- (void)setDay:(NSInteger)day { + NSDateComponents *components = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + components.day = day; + + _date = [_calendar dateFromComponents:components]; +} + +- (NSInteger)hour { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].hour; +} + +- (void)setHour:(NSInteger)hour { + NSDateComponents *components = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + components.hour = hour; + + _date = [_calendar dateFromComponents:components]; +} + +- (NSInteger)minute { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].minute; +} + +- (void)setMinute:(NSInteger)minute { + NSDateComponents *components = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + components.minute = minute; + + _date = [_calendar dateFromComponents:components]; +} + +- (NSInteger)second { + return [_calendar components:_dateTimeCalendarUnit fromDate:_date].second; +} + +- (void)setSecond:(NSInteger)second { + NSDateComponents *components = [_calendar components:_dateTimeCalendarUnit fromDate:_date]; + components.second = second; + + _date = [_calendar dateFromComponents:components]; +} + +@end diff --git a/YuMi/Tools/Date/PLTimeUtil.h b/YuMi/Tools/Date/PLTimeUtil.h index 4ac4ce2..76d4275 100644 --- a/YuMi/Tools/Date/PLTimeUtil.h +++ b/YuMi/Tools/Date/PLTimeUtil.h @@ -1,59 +1,51 @@ -// -// PLTimeUtil.h -// YYMobile -// -// Created by penglong on 14/10/28. -// Copyright (c) 2014年 YY.inc. All rights reserved. -// - -#import - -@interface PLTimeUtil : PIBaseModel - -/** - * 根据秒数获取倒计时时间 - * - * @param second 秒 - * - * @return 格式为 01:02:00 - */ -+ (NSString *)getTimeWithSecond:(NSUInteger)second; - -+ (NSDate *)getDateWithCompleteTime:(NSString *)time; - -+ (NSDate *)getDateWithTime:(NSString *)time; - -+ (NSDate *)getDateWithYmd:(NSString *)time; - -+ (NSString *)getDateWithHHMMSS:(NSString *)time; - -+ (NSString *)getDateWithYYMMDD:(NSString *)time; - -+ (NSString *)getDateWitMMDDHHSS:(NSString *)time; - -+ (NSString *)getDateWithYYMM:(NSString *)time; - -+ (NSString *)getDateWithMMDD:(NSString *)time; - -+ (NSDate *)getDateWithYearMonthDay:(NSString *)time; - -+ (NSString *)getMonthDayContent:(NSDate *)date; - -+ (NSString *)getYYMMWithDate:(NSDate *)date; - -+ (NSString *)getYYMMDDWithDate:(NSDate *)date; - -+ (NSString *)getYYMMDDWithDateFormatter:(NSDate *)date; - -+ (NSString *)getDateWithTotalTimeWith:(NSString *)time; - -+ (NSString *)getNowTimeTimestampMillisecond; - -///比较两个时间的差值 -+ (NSDateComponents *)compareTwoDate:(NSDate *)firstDate secondDate:(NSDate *)secondDate; - -///计算年龄 -+ (NSInteger)ageWithDateFromBirth:(NSInteger)birth; - -@end - + + +// Created by penglong on 14/10/28. +// Copyright (c) 2014年 YY.inc. All rights reserved. + + +#import + +@interface PLTimeUtil : PIBaseModel + + ++ (NSString *)getTimeWithSecond:(NSUInteger)second; + ++ (NSDate *)getDateWithCompleteTime:(NSString *)time; + ++ (NSDate *)getDateWithTime:(NSString *)time; + ++ (NSDate *)getDateWithYmd:(NSString *)time; + ++ (NSString *)getDateWithHHMMSS:(NSString *)time; + ++ (NSString *)getDateWithYYMMDD:(NSString *)time; + ++ (NSString *)getDateWitMMDDHHSS:(NSString *)time; + ++ (NSString *)getDateWithYYMM:(NSString *)time; + ++ (NSString *)getDateWithMMDD:(NSString *)time; + ++ (NSDate *)getDateWithYearMonthDay:(NSString *)time; + ++ (NSString *)getMonthDayContent:(NSDate *)date; + ++ (NSString *)getYYMMWithDate:(NSDate *)date; + ++ (NSString *)getYYMMDDWithDate:(NSDate *)date; + ++ (NSString *)getYYMMDDWithDateFormatter:(NSDate *)date; + ++ (NSString *)getDateWithTotalTimeWith:(NSString *)time; + ++ (NSString *)getNowTimeTimestampMillisecond; + + ++ (NSDateComponents *)compareTwoDate:(NSDate *)firstDate secondDate:(NSDate *)secondDate; + + ++ (NSInteger)ageWithDateFromBirth:(NSInteger)birth; + +@end + diff --git a/YuMi/Tools/Date/PLTimeUtil.h.backup b/YuMi/Tools/Date/PLTimeUtil.h.backup new file mode 100644 index 0000000..4ac4ce2 --- /dev/null +++ b/YuMi/Tools/Date/PLTimeUtil.h.backup @@ -0,0 +1,59 @@ +// +// PLTimeUtil.h +// YYMobile +// +// Created by penglong on 14/10/28. +// Copyright (c) 2014年 YY.inc. All rights reserved. +// + +#import + +@interface PLTimeUtil : PIBaseModel + +/** + * 根据秒数获取倒计时时间 + * + * @param second 秒 + * + * @return 格式为 01:02:00 + */ ++ (NSString *)getTimeWithSecond:(NSUInteger)second; + ++ (NSDate *)getDateWithCompleteTime:(NSString *)time; + ++ (NSDate *)getDateWithTime:(NSString *)time; + ++ (NSDate *)getDateWithYmd:(NSString *)time; + ++ (NSString *)getDateWithHHMMSS:(NSString *)time; + ++ (NSString *)getDateWithYYMMDD:(NSString *)time; + ++ (NSString *)getDateWitMMDDHHSS:(NSString *)time; + ++ (NSString *)getDateWithYYMM:(NSString *)time; + ++ (NSString *)getDateWithMMDD:(NSString *)time; + ++ (NSDate *)getDateWithYearMonthDay:(NSString *)time; + ++ (NSString *)getMonthDayContent:(NSDate *)date; + ++ (NSString *)getYYMMWithDate:(NSDate *)date; + ++ (NSString *)getYYMMDDWithDate:(NSDate *)date; + ++ (NSString *)getYYMMDDWithDateFormatter:(NSDate *)date; + ++ (NSString *)getDateWithTotalTimeWith:(NSString *)time; + ++ (NSString *)getNowTimeTimestampMillisecond; + +///比较两个时间的差值 ++ (NSDateComponents *)compareTwoDate:(NSDate *)firstDate secondDate:(NSDate *)secondDate; + +///计算年龄 ++ (NSInteger)ageWithDateFromBirth:(NSInteger)birth; + +@end + diff --git a/YuMi/Tools/Date/PLTimeUtil.m b/YuMi/Tools/Date/PLTimeUtil.m index e8a46bd..e895b43 100644 --- a/YuMi/Tools/Date/PLTimeUtil.m +++ b/YuMi/Tools/Date/PLTimeUtil.m @@ -1,10 +1,8 @@ -// -// PLTimeUtil.m -// YYMobile -// + + // Created by penglong on 14/10/28. // Copyright (c) 2014年 YY.inc. All rights reserved. -// + #import "PLTimeUtil.h" #import "NVDate.h" @@ -81,9 +79,8 @@ } + (NSString *)getYYMMDDWithDate:(NSDate *)date { -// NSTimeZone *zome = [NSTimeZone systemTimeZone]; -// NSTimeInterval seconds1 = [zome secondsFromGMTForDate:date]; -// NSDate *date2 = [date dateByAddingTimeInterval:seconds1]; + + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; [formatter setTimeZone:timeZone]; @@ -93,9 +90,8 @@ } + (NSString *)getYYMMDDWithDateFormatter:(NSDate *)date { -// NSTimeZone *zome = [NSTimeZone systemTimeZone]; -// NSTimeInterval seconds1 = [zome secondsFromGMTForDate:date]; -// NSDate *date2 = [date dateByAddingTimeInterval:seconds1]; + + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; [formatter setTimeZone:timeZone]; @@ -121,7 +117,7 @@ [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setDateFormat:YMLocalizedString(@"PLTimeUtil2")]; - // 毫秒值转化为秒 + NSString * times; if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; @@ -139,7 +135,7 @@ [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setDateFormat:@"MM-dd HH:mm"]; - // 毫秒值转化为秒 + NSString * times; if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; @@ -174,7 +170,7 @@ [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setDateFormat:YMLocalizedString(@"PLTimeUtil3")]; - // 毫秒值转化为秒 + NSString * times; if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; @@ -192,7 +188,7 @@ [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setDateFormat:YMLocalizedString(@"PLTimeUtil4")]; - // 毫秒值转化为秒 + NSString * times; if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; @@ -205,15 +201,13 @@ } - - + (NSString *)getDateWithHHMMSS:(NSString *)time { NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setDateFormat:@"HH:mm:ss"]; - // 毫秒值转化为秒 + NSString * times; if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; @@ -231,7 +225,7 @@ [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setDateFormat:@"yyyy.MM.dd HH:mm:ss"]; - // 毫秒值转化为秒 + NSString * times; if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; @@ -252,10 +246,9 @@ [formatter setTimeStyle:NSDateFormatterShortStyle]; - [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 - - //设置时区,这个对于时间的处理有时很重要 + [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; [formatter setTimeZone:timeZone]; @@ -269,32 +262,32 @@ + (NSDateComponents *)compareTwoDate:(NSDate *)firstDate secondDate:(NSDate *)secondDate { - // 当前日历 + NSCalendar *calendar = [NSCalendar currentCalendar]; - // 需要对比的时间数据 + NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; - // 对比时间差 + NSDateComponents *dateCom = [calendar components:unit fromDate:firstDate toDate:secondDate options:0]; return dateCom; } -///计算年龄 + + (NSInteger)ageWithDateFromBirth:(NSInteger)birth{ - // 出生日期转换 年月日 + NSDate *date = [NSDate dateWithTimeIntervalSince1970:birth/1000]; NSDateComponents *components1 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date]; NSInteger brithDateYear = [components1 year]; NSInteger brithDateDay = [components1 day]; NSInteger brithDateMonth = [components1 month]; - // 获取系统当前 年月日 + NSDateComponents *components2 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]]; NSInteger currentDateYear = [components2 year]; NSInteger currentDateDay = [components2 day]; NSInteger currentDateMonth = [components2 month]; - // 计算年龄 + NSInteger iAge = currentDateYear - brithDateYear - 1; if ((currentDateMonth > brithDateMonth) || (currentDateMonth == brithDateMonth && currentDateDay >= brithDateDay)) { iAge++; diff --git a/YuMi/Tools/Date/PLTimeUtil.m.backup b/YuMi/Tools/Date/PLTimeUtil.m.backup new file mode 100644 index 0000000..e8a46bd --- /dev/null +++ b/YuMi/Tools/Date/PLTimeUtil.m.backup @@ -0,0 +1,307 @@ +// +// PLTimeUtil.m +// YYMobile +// +// Created by penglong on 14/10/28. +// Copyright (c) 2014年 YY.inc. All rights reserved. +// + +#import "PLTimeUtil.h" +#import "NVDate.h" +#import "YYUtility.h" +@implementation PLTimeUtil + ++ (NSString *)getTimeWithSecond:(NSUInteger)second +{ + NSUInteger hours = second / 3600; + NSUInteger minutes = (second % 3600) / 60; + NSUInteger seconds = second % 60; + return [NSString stringWithFormat:@"%@:%@:%@",[self getConent:hours], + [self getConent:minutes],[self getConent:seconds]]; +} + ++ (NSString *)getConent:(NSUInteger)count +{ + if(count >= 10){ + return [NSString stringWithFormat:@"%lu",(unsigned long)count]; + } + return [NSString stringWithFormat:@"0%lu",(unsigned long)count]; +} + ++(NSDate *)getDateWithYmd:(NSString *)time +{ + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy:MM:dd"]; + NSDate* date = [dateFormatter dateFromString:time]; + return date; +} + ++(NSDate *)getDateWithYearMonthDay:(NSString *)time +{ + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy-MM-dd"]; + NSDate* date = [dateFormatter dateFromString:time]; + return date; +} + ++ (NSDate *)getDateWithCompleteTime:(NSString *)time +{ + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy:MM:dd HH:mm:ss"]; + NSDate* date = [dateFormatter dateFromString:time]; + return date; +} + ++ (NSDate *)getDateWithTime:(NSString *)time +{ + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"HH:mm:ss"]; + NSDate* date = [dateFormatter dateFromString:time]; + return date; +} + + ++ (NSString *)getMonthDayContent:(NSDate *)date +{ + NVDate *currentNVDate = [[NVDate alloc] initUsingDate:date]; + + NSString *month = [self getContent:currentNVDate.month]; + NSString *day = [self getContent:currentNVDate.day]; + + NSString *content = [NSString stringWithFormat:@"%@-%@",month,day]; + return content; +} + ++ (NSString *)getContent:(NSUInteger)count +{ + if(count >= 10){ + return [NSString stringWithFormat:@"%lu",(unsigned long)count]; + } + return [NSString stringWithFormat:@"0%lu",(unsigned long)count]; +} + ++ (NSString *)getYYMMDDWithDate:(NSDate *)date { +// NSTimeZone *zome = [NSTimeZone systemTimeZone]; +// NSTimeInterval seconds1 = [zome secondsFromGMTForDate:date]; +// NSDate *date2 = [date dateByAddingTimeInterval:seconds1]; + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setTimeZone:timeZone]; + formatter.dateFormat = @"yyyy-MM-dd"; + NSString *dateStr = [formatter stringFromDate:date]; + return dateStr; +} + ++ (NSString *)getYYMMDDWithDateFormatter:(NSDate *)date { +// NSTimeZone *zome = [NSTimeZone systemTimeZone]; +// NSTimeInterval seconds1 = [zome secondsFromGMTForDate:date]; +// NSDate *date2 = [date dateByAddingTimeInterval:seconds1]; + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setTimeZone:timeZone]; + formatter.dateFormat = YMLocalizedString(@"PLTimeUtil0"); + NSString *dateStr = [formatter stringFromDate:date]; + return dateStr; +} + + ++ (NSString *)getYYMMWithDate:(NSDate *)date { + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setTimeZone:timeZone]; + formatter.dateFormat = YMLocalizedString(@"PLTimeUtil1"); + NSString *dateStr = [formatter stringFromDate:date]; + return dateStr; +} + + ++ (NSString *)getDateWithYYMMDD:(NSString *)time { + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:YMLocalizedString(@"PLTimeUtil2")]; + // 毫秒值转化为秒 + NSString * times; + if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { + times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; + }else{ + times = time; + } + NSDate* date = [NSDate dateWithTimeIntervalSince1970:[times longLongValue]/ 1000.0]; + NSString* dateString = [formatter stringFromDate:date]; + return dateString; +} + ++ (NSString *)getDateWitMMDDHHSS:(NSString *)time { + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:@"MM-dd HH:mm"]; + // 毫秒值转化为秒 + NSString * times; + if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { + times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; + }else{ + times = time; + } + NSDate* date = [NSDate dateWithTimeIntervalSince1970:[times longLongValue]/ 1000.0]; + NSString* dateString = [formatter stringFromDate:date]; + return dateString; +} + ++ (BOOL)is32bit + +{ + +#if defined(__LP64__) && __LP64__ + + return NO; + +#else + + return YES; + +#endif + +} + + ++ (NSString *)getDateWithYYMM:(NSString *)time { + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:YMLocalizedString(@"PLTimeUtil3")]; + // 毫秒值转化为秒 + NSString * times; + if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { + times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; + }else{ + times = time; + } + NSDate* date = [NSDate dateWithTimeIntervalSince1970:[times doubleValue]/ 1000.0]; + NSString* dateString = [formatter stringFromDate:date]; + return dateString; +} + ++ (NSString *)getDateWithMMDD:(NSString *)time { + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:YMLocalizedString(@"PLTimeUtil4")]; + // 毫秒值转化为秒 + NSString * times; + if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { + times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; + }else{ + times = time; + } + NSDate* date = [NSDate dateWithTimeIntervalSince1970:[times doubleValue]/ 1000.0]; + NSString* dateString = [formatter stringFromDate:date]; + return dateString; +} + + + + ++ (NSString *)getDateWithHHMMSS:(NSString *)time { + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:@"HH:mm:ss"]; + // 毫秒值转化为秒 + NSString * times; + if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { + times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; + }else{ + times = time; + } + NSDate* date = [NSDate dateWithTimeIntervalSince1970:[times doubleValue]/ 1000.0]; + NSString* dateString = [formatter stringFromDate:date]; + return dateString; +} + ++ (NSString *)getDateWithTotalTimeWith:(NSString *)time { + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + [formatter setDateStyle:NSDateFormatterMediumStyle]; + [formatter setTimeStyle:NSDateFormatterShortStyle]; + [formatter setDateFormat:@"yyyy.MM.dd HH:mm:ss"]; + // 毫秒值转化为秒 + NSString * times; + if ([self is32bit] && [[YYUtility systemVersion] floatValue] <= 10.0) { + times = [NSString stringWithFormat:@"%f", ([time doubleValue] + 3600 * 1000 * 8)]; + }else{ + times = time; + } + NSDate* date = [NSDate dateWithTimeIntervalSince1970:[times doubleValue]/ 1000.0]; + NSString* dateString = [formatter stringFromDate:date]; + return dateString; +} + + ++ (NSString *)getNowTimeTimestampMillisecond{ + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ; + + [formatter setDateStyle:NSDateFormatterMediumStyle]; + + [formatter setTimeStyle:NSDateFormatterShortStyle]; + + [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 + + //设置时区,这个对于时间的处理有时很重要 + + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; + + [formatter setTimeZone:timeZone]; + + NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0]; + NSTimeInterval a=[dat timeIntervalSince1970]; + NSString * timeSp = [NSString stringWithFormat:@"%.0f", a]; + + return timeSp; +} + + ++ (NSDateComponents *)compareTwoDate:(NSDate *)firstDate secondDate:(NSDate *)secondDate { + // 当前日历 + NSCalendar *calendar = [NSCalendar currentCalendar]; + // 需要对比的时间数据 + NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth + | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; + // 对比时间差 + NSDateComponents *dateCom = [calendar components:unit fromDate:firstDate toDate:secondDate options:0]; + return dateCom; +} + +///计算年龄 ++ (NSInteger)ageWithDateFromBirth:(NSInteger)birth{ + // 出生日期转换 年月日 + NSDate *date = [NSDate dateWithTimeIntervalSince1970:birth/1000]; + NSDateComponents *components1 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date]; + NSInteger brithDateYear = [components1 year]; + NSInteger brithDateDay = [components1 day]; + NSInteger brithDateMonth = [components1 month]; + + // 获取系统当前 年月日 + NSDateComponents *components2 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]]; + NSInteger currentDateYear = [components2 year]; + NSInteger currentDateDay = [components2 day]; + NSInteger currentDateMonth = [components2 month]; + + // 计算年龄 + NSInteger iAge = currentDateYear - brithDateYear - 1; + if ((currentDateMonth > brithDateMonth) || (currentDateMonth == brithDateMonth && currentDateDay >= brithDateDay)) { + iAge++; + } + + return iAge; +} + +@end + diff --git a/YuMi/Tools/File/UploadFile.h b/YuMi/Tools/File/UploadFile.h.backup similarity index 100% rename from YuMi/Tools/File/UploadFile.h rename to YuMi/Tools/File/UploadFile.h.backup diff --git a/YuMi/Tools/File/UploadFile.m b/YuMi/Tools/File/UploadFile.m.backup similarity index 100% rename from YuMi/Tools/File/UploadFile.m rename to YuMi/Tools/File/UploadFile.m.backup diff --git a/YuMi/Tools/File/UploadFileModel.h b/YuMi/Tools/File/UploadFileModel.h.backup similarity index 100% rename from YuMi/Tools/File/UploadFileModel.h rename to YuMi/Tools/File/UploadFileModel.h.backup diff --git a/YuMi/Tools/File/UploadFileModel.m b/YuMi/Tools/File/UploadFileModel.m.backup similarity index 100% rename from YuMi/Tools/File/UploadFileModel.m rename to YuMi/Tools/File/UploadFileModel.m.backup diff --git a/YuMi/Tools/GCDHelper/GCDHelper.h b/YuMi/Tools/GCDHelper/GCDHelper.h index 587e2cd..1ab4112 100644 --- a/YuMi/Tools/GCDHelper/GCDHelper.h +++ b/YuMi/Tools/GCDHelper/GCDHelper.h @@ -1,11 +1,9 @@ -// -// GCDHelper.h -// YYMobileFramework -// -// Created by wuwei on 14/7/18. -// Copyright (c) 2014年 YY Inc. All rights reserved. -// - -#import - + + +// Created by wuwei on 14/7/18. +// Copyright (c) 2014年 YY Inc. All rights reserved. + + +#import + void dispatch_main_sync_safe(dispatch_block_t block); \ No newline at end of file diff --git a/YuMi/Tools/GCDHelper/GCDHelper.h.backup b/YuMi/Tools/GCDHelper/GCDHelper.h.backup new file mode 100644 index 0000000..587e2cd --- /dev/null +++ b/YuMi/Tools/GCDHelper/GCDHelper.h.backup @@ -0,0 +1,11 @@ +// +// GCDHelper.h +// YYMobileFramework +// +// Created by wuwei on 14/7/18. +// Copyright (c) 2014年 YY Inc. All rights reserved. +// + +#import + +void dispatch_main_sync_safe(dispatch_block_t block); \ No newline at end of file diff --git a/YuMi/Tools/GCDHelper/GCDHelper.m b/YuMi/Tools/GCDHelper/GCDHelper.m index f4fc1a5..8e90b66 100644 --- a/YuMi/Tools/GCDHelper/GCDHelper.m +++ b/YuMi/Tools/GCDHelper/GCDHelper.m @@ -1,10 +1,8 @@ -// -// GCDHelper.m -// YYMobileFramework -// + + // Created by wuwei on 14/7/18. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import "GCDHelper.h" void dispatch_main_sync_safe(dispatch_block_t block) { diff --git a/YuMi/Tools/GCDHelper/GCDHelper.m.backup b/YuMi/Tools/GCDHelper/GCDHelper.m.backup new file mode 100644 index 0000000..f4fc1a5 --- /dev/null +++ b/YuMi/Tools/GCDHelper/GCDHelper.m.backup @@ -0,0 +1,16 @@ +// +// GCDHelper.m +// YYMobileFramework +// +// Created by wuwei on 14/7/18. +// Copyright (c) 2014年 YY Inc. All rights reserved. +// + +#import "GCDHelper.h" +void dispatch_main_sync_safe(dispatch_block_t block) { + if ([NSThread isMainThread]) { + block(); + }else { + dispatch_sync(dispatch_get_main_queue(), block); + } +} diff --git a/YuMi/Tools/MJExtension/NSObject+MJExtension.h b/YuMi/Tools/MJExtension/NSObject+MJExtension.h index ac97712..fbff3ab 100644 --- a/YuMi/Tools/MJExtension/NSObject+MJExtension.h +++ b/YuMi/Tools/MJExtension/NSObject+MJExtension.h @@ -1,9 +1,7 @@ -// -// NSObject+MJExtension.h -// YUMI -// + + // Created by zu on 2021/10/27. -// + #import @@ -11,31 +9,27 @@ NS_ASSUME_NONNULL_BEGIN @interface NSObject (MJExtension) -/// 依据数组初始化一个实例数组 -/// @param json json 数据 + + (NSArray *)modelsWithArray:(id)json; -/// 依据字典初始化一个实例 -/// @param dictionary 字典 + + (instancetype)modelWithDictionary:(NSDictionary *)dictionary; -/// 依据JSON对象初始化一个实例 -/// @param json json 数据 + + (instancetype)modelWithJSON:(id)json; -///model 转字典 + - (NSDictionary *)model2dictionary; -///转 json string + - (NSString *)toJSONString; -///转 json object + - (id)toJSONObject; -///扩展方法 按需索取 重写即可 -///如果一个模型中 包含一个数组 数组中是另一个模型 + + (NSDictionary *)objectClassInArray; -///如果一个模型中需要字段映射的话 比如id -> ID name -> other.name + + (NSDictionary *)replacedKeyFromPropertyName; @end diff --git a/YuMi/Tools/MJExtension/NSObject+MJExtension.h.backup b/YuMi/Tools/MJExtension/NSObject+MJExtension.h.backup new file mode 100644 index 0000000..ac97712 --- /dev/null +++ b/YuMi/Tools/MJExtension/NSObject+MJExtension.h.backup @@ -0,0 +1,43 @@ +// +// NSObject+MJExtension.h +// YUMI +// +// Created by zu on 2021/10/27. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (MJExtension) + +/// 依据数组初始化一个实例数组 +/// @param json json 数据 ++ (NSArray *)modelsWithArray:(id)json; + +/// 依据字典初始化一个实例 +/// @param dictionary 字典 ++ (instancetype)modelWithDictionary:(NSDictionary *)dictionary; + +/// 依据JSON对象初始化一个实例 +/// @param json json 数据 ++ (instancetype)modelWithJSON:(id)json; + +///model 转字典 +- (NSDictionary *)model2dictionary; + +///转 json string +- (NSString *)toJSONString; + +///转 json object +- (id)toJSONObject; + +///扩展方法 按需索取 重写即可 +///如果一个模型中 包含一个数组 数组中是另一个模型 ++ (NSDictionary *)objectClassInArray; +///如果一个模型中需要字段映射的话 比如id -> ID name -> other.name ++ (NSDictionary *)replacedKeyFromPropertyName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/MJExtension/NSObject+MJExtension.m b/YuMi/Tools/MJExtension/NSObject+MJExtension.m index 340753d..3ef2294 100644 --- a/YuMi/Tools/MJExtension/NSObject+MJExtension.m +++ b/YuMi/Tools/MJExtension/NSObject+MJExtension.m @@ -1,34 +1,29 @@ -// -// NSObject+MJExtension.m -// YUMI -// + + // Created by zu on 2021/10/27. -// + #import "NSObject+MJExtension.h" #import @implementation NSObject (MJExtension) -/// 依据数组初始化一个实例数组 -/// @param json json 数据 + + (NSArray *)modelsWithArray:(id)json { return [self mj_objectArrayWithKeyValuesArray:json]; } -/// 依据字典初始化一个实例 -/// @param dictionary 字典 + + (instancetype)modelWithDictionary:(NSDictionary *)dictionary { return [self mj_objectWithKeyValues:dictionary]; } -/// 依据JSON对象初始化一个实例 -/// @param json json 数据 + + (instancetype)modelWithJSON:(id)json { return [self mj_objectWithKeyValues:json]; } -///model 转字典 + - (NSDictionary *)model2dictionary { return [[self mj_keyValues] copy]; } @@ -41,22 +36,21 @@ return [self mj_JSONObject]; } -///如果模型中包含数组的话 + + (NSDictionary *)mj_objectClassInArray { return [self objectClassInArray]; } -///模型中需要映射 重写整个方法 + + (NSDictionary *)mj_replacedKeyFromPropertyName { return [self replacedKeyFromPropertyName]; } -///扩展方法 按需索取 重写即可 -///如果一个模型中 包含一个数组 数组中是另一个模型 + + (NSDictionary *)objectClassInArray { return @{}; } -///如果一个模型中需要字段映射的话 比如id -> ID name -> other.name + + (NSDictionary *)replacedKeyFromPropertyName { return @{}; } diff --git a/YuMi/Tools/MJExtension/NSObject+MJExtension.m.backup b/YuMi/Tools/MJExtension/NSObject+MJExtension.m.backup new file mode 100644 index 0000000..340753d --- /dev/null +++ b/YuMi/Tools/MJExtension/NSObject+MJExtension.m.backup @@ -0,0 +1,64 @@ +// +// NSObject+MJExtension.m +// YUMI +// +// Created by zu on 2021/10/27. +// + +#import "NSObject+MJExtension.h" +#import + +@implementation NSObject (MJExtension) + +/// 依据数组初始化一个实例数组 +/// @param json json 数据 ++ (NSArray *)modelsWithArray:(id)json { + return [self mj_objectArrayWithKeyValuesArray:json]; +} + +/// 依据字典初始化一个实例 +/// @param dictionary 字典 ++ (instancetype)modelWithDictionary:(NSDictionary *)dictionary { + return [self mj_objectWithKeyValues:dictionary]; +} + +/// 依据JSON对象初始化一个实例 +/// @param json json 数据 ++ (instancetype)modelWithJSON:(id)json { + return [self mj_objectWithKeyValues:json]; +} + +///model 转字典 +- (NSDictionary *)model2dictionary { + return [[self mj_keyValues] copy]; +} + +- (NSString *)toJSONString { + return [self mj_JSONString]; +} + +- (id)toJSONObject { + return [self mj_JSONObject]; +} + +///如果模型中包含数组的话 ++ (NSDictionary *)mj_objectClassInArray { + return [self objectClassInArray]; +} + +///模型中需要映射 重写整个方法 ++ (NSDictionary *)mj_replacedKeyFromPropertyName { + return [self replacedKeyFromPropertyName]; +} + +///扩展方法 按需索取 重写即可 +///如果一个模型中 包含一个数组 数组中是另一个模型 ++ (NSDictionary *)objectClassInArray { + return @{}; +} +///如果一个模型中需要字段映射的话 比如id -> ID name -> other.name ++ (NSDictionary *)replacedKeyFromPropertyName { + return @{}; +} + +@end diff --git a/YuMi/Tools/MedalMediaDisplayManager.h b/YuMi/Tools/MedalMediaDisplayManager.h index 315c3ca..4175d20 100644 --- a/YuMi/Tools/MedalMediaDisplayManager.h +++ b/YuMi/Tools/MedalMediaDisplayManager.h @@ -1,9 +1,7 @@ -// -// MedalMediaDisplayManager.h -// YuMi -// + + // Created by AI on 2025/1/20. -// + #import #import @@ -12,86 +10,66 @@ NS_ASSUME_NONNULL_BEGIN -/** - * 媒体显示代理协议 - * 需要使用媒体显示功能的类实现此协议 - */ + @protocol MedalMediaDisplayDelegate @required -/// 从数据模型中获取MP4 URL + - (NSString * _Nullable)getMP4UrlFromModel:(id _Nullable)model; -/// 从数据模型中获取图片 URL + - (NSString * _Nullable)getPicUrlFromModel:(id _Nullable)model; -/// 获取图片显示视图 + - (NetImageView *)getImageView; -/// 获取MP4播放视图 + - (VAPView *)getMP4View; @optional -/// 媒体显示状态更新回调 + - (void)onMediaDisplayUpdated:(BOOL)isMP4 success:(BOOL)success; -/// 获取默认占位图 + - (UIImage * _Nullable)getDefaultPlaceholderImage; @end -/** - * 勋章媒体显示管理器 - * 统一处理MP4和PNG的显示逻辑 - */ + @interface MedalMediaDisplayManager : NSObject -/// 代理对象 + @property (nonatomic, weak) id delegate; -/// 当前显示的数据模型 + @property (nonatomic, strong, nullable) id currentModel; -/// 可见性状态 + @property (nonatomic, assign) BOOL isVisible; -/// 当前媒体路径 + @property (nonatomic, copy, readonly, nullable) NSString *currentImagePath; @property (nonatomic, copy, readonly, nullable) NSString *currentMP4Path; -/** - * 初始化方法 - * @param delegate 实现MedalMediaDisplayDelegate协议的对象 - */ + - (instancetype)initWithDelegate:(id)delegate; -/** - * 更新显示内容 - * @param model 数据模型 - */ + - (void)updateDisplayWithModel:(id _Nullable)model; -/** - * 可见性管理 - */ + - (void)willDisplay; - (void)didEndDisplaying; -/** - * 播放控制 - */ + - (void)stopMP4Playback; - (void)pauseMP4Playback; - (void)resumeMP4Playback; -/** - * 资源清理 - */ + - (void)cleanupResources; -/** - * 应用生命周期通知处理 - */ + - (void)handleAppDidEnterBackground; - (void)handleAppWillEnterForeground; - (void)handleMemoryWarning; diff --git a/YuMi/Tools/MedalMediaDisplayManager.h.backup b/YuMi/Tools/MedalMediaDisplayManager.h.backup new file mode 100644 index 0000000..315c3ca --- /dev/null +++ b/YuMi/Tools/MedalMediaDisplayManager.h.backup @@ -0,0 +1,101 @@ +// +// MedalMediaDisplayManager.h +// YuMi +// +// Created by AI on 2025/1/20. +// + +#import +#import + +@class VAPView, NetImageView, XPRoomGiftAnimationParser; + +NS_ASSUME_NONNULL_BEGIN + +/** + * 媒体显示代理协议 + * 需要使用媒体显示功能的类实现此协议 + */ +@protocol MedalMediaDisplayDelegate + +@required +/// 从数据模型中获取MP4 URL +- (NSString * _Nullable)getMP4UrlFromModel:(id _Nullable)model; + +/// 从数据模型中获取图片 URL +- (NSString * _Nullable)getPicUrlFromModel:(id _Nullable)model; + +/// 获取图片显示视图 +- (NetImageView *)getImageView; + +/// 获取MP4播放视图 +- (VAPView *)getMP4View; + +@optional +/// 媒体显示状态更新回调 +- (void)onMediaDisplayUpdated:(BOOL)isMP4 success:(BOOL)success; + +/// 获取默认占位图 +- (UIImage * _Nullable)getDefaultPlaceholderImage; + +@end + +/** + * 勋章媒体显示管理器 + * 统一处理MP4和PNG的显示逻辑 + */ +@interface MedalMediaDisplayManager : NSObject + +/// 代理对象 +@property (nonatomic, weak) id delegate; + +/// 当前显示的数据模型 +@property (nonatomic, strong, nullable) id currentModel; + +/// 可见性状态 +@property (nonatomic, assign) BOOL isVisible; + +/// 当前媒体路径 +@property (nonatomic, copy, readonly, nullable) NSString *currentImagePath; +@property (nonatomic, copy, readonly, nullable) NSString *currentMP4Path; + +/** + * 初始化方法 + * @param delegate 实现MedalMediaDisplayDelegate协议的对象 + */ +- (instancetype)initWithDelegate:(id)delegate; + +/** + * 更新显示内容 + * @param model 数据模型 + */ +- (void)updateDisplayWithModel:(id _Nullable)model; + +/** + * 可见性管理 + */ +- (void)willDisplay; +- (void)didEndDisplaying; + +/** + * 播放控制 + */ +- (void)stopMP4Playback; +- (void)pauseMP4Playback; +- (void)resumeMP4Playback; + +/** + * 资源清理 + */ +- (void)cleanupResources; + +/** + * 应用生命周期通知处理 + */ +- (void)handleAppDidEnterBackground; +- (void)handleAppWillEnterForeground; +- (void)handleMemoryWarning; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/YuMi/Tools/MedalMediaDisplayManager.m b/YuMi/Tools/MedalMediaDisplayManager.m index 86dffd1..f7ebe7f 100644 --- a/YuMi/Tools/MedalMediaDisplayManager.m +++ b/YuMi/Tools/MedalMediaDisplayManager.m @@ -1,9 +1,7 @@ -// -// MedalMediaDisplayManager.m -// YuMi -// + + // Created by AI on 2025/1/20. -// + #import "MedalMediaDisplayManager.h" #import @@ -16,7 +14,7 @@ @property (nonatomic, copy, readwrite, nullable) NSString *currentImagePath; @property (nonatomic, copy, readwrite, nullable) NSString *currentMP4Path; @property (nonatomic, strong) XPRoomGiftAnimationParser *mp4Parser; -@property (nonatomic, assign) NSInteger mp4PlaybackTag; // 播放状态标记 +@property (nonatomic, assign) NSInteger mp4PlaybackTag; @end @@ -96,26 +94,26 @@ NSString *mp4Url = [self.delegate getMP4UrlFromModel:model]; NSString *picUrl = [self.delegate getPicUrlFromModel:model]; - // 优先判断 MP4 URL + if (![NSString isEmpty:mp4Url] && [self isValidMP4URL:mp4Url]) { [self setMp4Path:mp4Url]; return; } - // MP4 URL 无效,检查图片 URL + if (![NSString isEmpty:picUrl]) { if ([self isValidMP4URL:picUrl]) { - // picUrl 实际上是 MP4(兼容旧逻辑) + [self setMp4Path:picUrl]; return; } else if ([NSString isValidImageURL:picUrl]) { - // 有效的图片 URL + [self setImagePath:picUrl]; return; } } - // 都无效,显示默认占位图 + [self showDefaultPlaceholder]; } @@ -161,7 +159,7 @@ completionBlock:^(NSString * _Nullable videoUrl) { @kStrongify(self); if (![NSString isEmpty:videoUrl]) { - self.mp4PlaybackTag = 1; // 标记已准备好播放 + self.mp4PlaybackTag = 1; if (self.isVisible) { [self startMP4PlaybackWithURL:videoUrl]; @@ -193,7 +191,7 @@ return; } - // MP4 失败,尝试降级到图片 + NSString *picUrl = [self.delegate getPicUrlFromModel:self.currentModel]; if (![NSString isEmpty:picUrl] && [NSString isValidImageURL:picUrl]) { [self setImagePath:picUrl]; @@ -212,7 +210,7 @@ imageView.hidden = NO; imageView.imageUrl = @""; - // 获取默认占位图 + UIImage *placeholderImage = nil; if ([self.delegate respondsToSelector:@selector(getDefaultPlaceholderImage)]) { placeholderImage = [self.delegate getDefaultPlaceholderImage]; @@ -233,7 +231,7 @@ VAPView *mp4View = [self.delegate getMP4View]; if (mp4View && !mp4View.hidden) { if (self.mp4PlaybackTag == 1) { - // 已准备好但尚未播放,重新解析并播放 + @kWeakify(self); [self.mp4Parser parseWithURL:self.currentMP4Path completionBlock:^(NSString * _Nullable videoUrl) { @@ -246,7 +244,7 @@ [self handleMP4FailureWithFallback]; }]; } else { - // 恢复暂停的播放 + [mp4View resumeHWDMP4]; } } @@ -313,11 +311,11 @@ } - (void)viewDidFinishPlayMP4:(NSInteger)totalFrameCount view:(VAPView *)container { - // MP4 播放完成,循环播放会自动重新开始 + } - (void)viewDidStopPlayMP4:(NSInteger)lastFrameIndex view:(VAPView *)container { - // MP4 播放停止 + } - (void)viewDidFailPlayMP4:(NSError *)error { diff --git a/YuMi/Tools/MedalMediaDisplayManager.m.backup b/YuMi/Tools/MedalMediaDisplayManager.m.backup new file mode 100644 index 0000000..86dffd1 --- /dev/null +++ b/YuMi/Tools/MedalMediaDisplayManager.m.backup @@ -0,0 +1,328 @@ +// +// MedalMediaDisplayManager.m +// YuMi +// +// Created by AI on 2025/1/20. +// + +#import "MedalMediaDisplayManager.h" +#import +#import "XPRoomGiftAnimationParser.h" +#import "NSString+XPExtension.h" +#import "UIImageConstant.h" + +@interface MedalMediaDisplayManager () + +@property (nonatomic, copy, readwrite, nullable) NSString *currentImagePath; +@property (nonatomic, copy, readwrite, nullable) NSString *currentMP4Path; +@property (nonatomic, strong) XPRoomGiftAnimationParser *mp4Parser; +@property (nonatomic, assign) NSInteger mp4PlaybackTag; // 播放状态标记 + +@end + +@implementation MedalMediaDisplayManager + +#pragma mark - 初始化 + +- (instancetype)initWithDelegate:(id)delegate { + self = [super init]; + if (self) { + _delegate = delegate; + _isVisible = YES; + _mp4PlaybackTag = 0; + [self setupNotifications]; + } + return self; +} + +- (void)dealloc { + [self cleanupResources]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + NSLog(@"MedalMediaDisplayManager dealloc"); +} + +#pragma mark - 公共接口 + +- (void)updateDisplayWithModel:(id)model { + self.currentModel = model; + [self handleMediaDisplayWithModel:model]; +} + +- (void)willDisplay { + self.isVisible = YES; + [self resumeMP4PlaybackIfNeeded]; +} + +- (void)didEndDisplaying { + self.isVisible = NO; + [self pauseMP4Playback]; +} + +- (void)stopMP4Playback { + VAPView *mp4View = [self.delegate getMP4View]; + if (mp4View) { + [mp4View stopHWDMP4]; + self.mp4PlaybackTag = 0; + } +} + +- (void)pauseMP4Playback { + VAPView *mp4View = [self.delegate getMP4View]; + if (mp4View && !mp4View.hidden) { + [mp4View pauseHWDMP4]; + } +} + +- (void)resumeMP4Playback { + [self resumeMP4PlaybackIfNeeded]; +} + +- (void)cleanupResources { + [self stopMP4Playback]; + self.mp4Parser = nil; + self.currentImagePath = nil; + self.currentMP4Path = nil; + self.currentModel = nil; +} + +#pragma mark - 核心媒体处理逻辑 + +- (void)handleMediaDisplayWithModel:(id)model { + if (!model || !self.delegate) { + [self showDefaultPlaceholder]; + return; + } + + NSString *mp4Url = [self.delegate getMP4UrlFromModel:model]; + NSString *picUrl = [self.delegate getPicUrlFromModel:model]; + + // 优先判断 MP4 URL + if (![NSString isEmpty:mp4Url] && [self isValidMP4URL:mp4Url]) { + [self setMp4Path:mp4Url]; + return; + } + + // MP4 URL 无效,检查图片 URL + if (![NSString isEmpty:picUrl]) { + if ([self isValidMP4URL:picUrl]) { + // picUrl 实际上是 MP4(兼容旧逻辑) + [self setMp4Path:picUrl]; + return; + } else if ([NSString isValidImageURL:picUrl]) { + // 有效的图片 URL + [self setImagePath:picUrl]; + return; + } + } + + // 都无效,显示默认占位图 + [self showDefaultPlaceholder]; +} + +- (void)setImagePath:(NSString *)imagePath { + [self stopMP4Playback]; + + self.currentImagePath = imagePath; + self.currentMP4Path = nil; + + VAPView *mp4View = [self.delegate getMP4View]; + NetImageView *imageView = [self.delegate getImageView]; + + mp4View.hidden = YES; + imageView.hidden = NO; + imageView.imageUrl = imagePath ?: @""; + + [self notifyDisplayUpdated:NO success:![NSString isEmpty:imagePath]]; +} + +- (void)setMp4Path:(NSString *)mp4Path { + if ([NSString isEmpty:mp4Path]) { + [self showDefaultPlaceholder]; + return; + } + + [self stopMP4Playback]; + + self.currentMP4Path = mp4Path; + self.currentImagePath = nil; + + VAPView *mp4View = [self.delegate getMP4View]; + NetImageView *imageView = [self.delegate getImageView]; + + mp4View.hidden = NO; + imageView.hidden = YES; + + if (!self.mp4Parser) { + self.mp4Parser = [[XPRoomGiftAnimationParser alloc] init]; + } + + @kWeakify(self); + [self.mp4Parser parseWithURL:mp4Path + completionBlock:^(NSString * _Nullable videoUrl) { + @kStrongify(self); + if (![NSString isEmpty:videoUrl]) { + self.mp4PlaybackTag = 1; // 标记已准备好播放 + + if (self.isVisible) { + [self startMP4PlaybackWithURL:videoUrl]; + } + } + } failureBlock:^(NSError * _Nullable error) { + @kStrongify(self); + NSLog(@"[MedalMediaDisplayManager] Failed to parse mp4: %@", error); + [self handleMP4FailureWithFallback]; + }]; +} + +- (void)startMP4PlaybackWithURL:(NSString *)videoUrl { + if ([NSString isEmpty:videoUrl] || !self.delegate) { + return; + } + + VAPView *mp4View = [self.delegate getMP4View]; + if (mp4View && !mp4View.hidden) { + [mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:self]; + [self notifyDisplayUpdated:YES success:YES]; + NSLog(@"[MedalMediaDisplayManager] Started MP4 playback: %@", videoUrl); + } +} + +- (void)handleMP4FailureWithFallback { + if (!self.delegate || !self.currentModel) { + [self showDefaultPlaceholder]; + return; + } + + // MP4 失败,尝试降级到图片 + NSString *picUrl = [self.delegate getPicUrlFromModel:self.currentModel]; + if (![NSString isEmpty:picUrl] && [NSString isValidImageURL:picUrl]) { + [self setImagePath:picUrl]; + } else { + [self showDefaultPlaceholder]; + } +} + +- (void)showDefaultPlaceholder { + [self stopMP4Playback]; + + VAPView *mp4View = [self.delegate getMP4View]; + NetImageView *imageView = [self.delegate getImageView]; + + mp4View.hidden = YES; + imageView.hidden = NO; + imageView.imageUrl = @""; + + // 获取默认占位图 + UIImage *placeholderImage = nil; + if ([self.delegate respondsToSelector:@selector(getDefaultPlaceholderImage)]) { + placeholderImage = [self.delegate getDefaultPlaceholderImage]; + } + if (!placeholderImage) { + placeholderImage = [UIImageConstant defaultEmptyPlaceholder]; + } + imageView.image = placeholderImage; + + [self notifyDisplayUpdated:NO success:NO]; +} + +- (void)resumeMP4PlaybackIfNeeded { + if (!self.isVisible || [NSString isEmpty:self.currentMP4Path]) { + return; + } + + VAPView *mp4View = [self.delegate getMP4View]; + if (mp4View && !mp4View.hidden) { + if (self.mp4PlaybackTag == 1) { + // 已准备好但尚未播放,重新解析并播放 + @kWeakify(self); + [self.mp4Parser parseWithURL:self.currentMP4Path + completionBlock:^(NSString * _Nullable videoUrl) { + @kStrongify(self); + if (![NSString isEmpty:videoUrl] && self.isVisible) { + [self startMP4PlaybackWithURL:videoUrl]; + } + } failureBlock:^(NSError * _Nullable error) { + @kStrongify(self); + [self handleMP4FailureWithFallback]; + }]; + } else { + // 恢复暂停的播放 + [mp4View resumeHWDMP4]; + } + } +} + +#pragma mark - 辅助方法 + +- (BOOL)isValidMP4URL:(NSString *)url { + if ([NSString isEmpty:url]) { + return NO; + } + + NSString *lowercaseUrl = [url lowercaseString]; + return [lowercaseUrl hasSuffix:@".mp4"] || + [lowercaseUrl containsString:@"mp4"] || + [lowercaseUrl containsString:@"video"]; +} + +- (void)notifyDisplayUpdated:(BOOL)isMP4 success:(BOOL)success { + if ([self.delegate respondsToSelector:@selector(onMediaDisplayUpdated:success:)]) { + [self.delegate onMediaDisplayUpdated:isMP4 success:success]; + } +} + +#pragma mark - 通知处理 + +- (void)setupNotifications { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleAppDidEnterBackground) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleAppWillEnterForeground) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleMemoryWarning) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; +} + +- (void)handleAppDidEnterBackground { + [self pauseMP4Playback]; +} + +- (void)handleAppWillEnterForeground { + if (self.isVisible) { + [self resumeMP4PlaybackIfNeeded]; + } +} + +- (void)handleMemoryWarning { + if (!self.isVisible) { + [self stopMP4Playback]; + } +} + +#pragma mark - HWDMP4PlayDelegate + +- (BOOL)shouldStartPlayMP4:(VAPView *)container config:(QGVAPConfigModel *)config { + return YES; +} + +- (void)viewDidFinishPlayMP4:(NSInteger)totalFrameCount view:(VAPView *)container { + // MP4 播放完成,循环播放会自动重新开始 +} + +- (void)viewDidStopPlayMP4:(NSInteger)lastFrameIndex view:(VAPView *)container { + // MP4 播放停止 +} + +- (void)viewDidFailPlayMP4:(NSError *)error { + NSLog(@"[MedalMediaDisplayManager] MP4 播放失败: %@", error); + [self handleMP4FailureWithFallback]; +} + +@end \ No newline at end of file diff --git a/YuMi/Tools/NSString/NSString+Utils.h b/YuMi/Tools/NSString/NSString+Utils.h index 5749028..94905c9 100644 --- a/YuMi/Tools/NSString/NSString+Utils.h +++ b/YuMi/Tools/NSString/NSString+Utils.h @@ -1,9 +1,7 @@ -// -// NSString+Regex.h -// YUMI -// + + // Created by YUMI on 2021/9/14. -// + #import @@ -11,39 +9,38 @@ NS_ASSUME_NONNULL_BEGIN @interface NSString (Utils) -///是否是正确的手机号 + - (BOOL)isPhoneNumber; -///MD5加密 - (NSString *)MD5String; + (BOOL)versionCompareOldStr:(NSString *)first andNewStr: (NSString *)second; -///数字转化为万 + + (NSString *)getDealNumWithString:(NSString *)string; -///数字转化为十万 + +(NSString *)getDealTenNumWithString:(NSString *)string; + (NSString *)formatNumberToKOrM:(NSString *)string; -///时间戳转化为需要显示的内容 + + (NSString *)stringWithTimeStamp:(NSString *)timeStamp; -///通过生日获取星座 + + (NSString *)calculateConstellationWithMonth:(long)time; -///通过生日获取星座 + + (NSString *)getCalculateConstellationTextWithMonth:(long)time; -///通过生日获取星座图片 + + (NSString *)getCalculateConstellationImageWithMonth:(long)time; -///得到年龄 + +(NSString *)getAgeWithBirth:(long)birth; -///得到区号 + +(NSString *)getCountryCode; -///产生唯一的key,用于图片或文件上传 + + (NSString *)createUUID; + (BOOL)isEmpty:(NSString *)string; -//- (BOOL)isEmpty; + - (NSString *)pureURLString; @@ -55,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)isValidImageURL:(NSString *)url; -/// 检查字符串是否为图片格式(通过扩展名判断) + + (BOOL)isImageFormat:(NSString *)url; @end diff --git a/YuMi/Tools/NSString/NSString+Utils.h.backup b/YuMi/Tools/NSString/NSString+Utils.h.backup new file mode 100644 index 0000000..5749028 --- /dev/null +++ b/YuMi/Tools/NSString/NSString+Utils.h.backup @@ -0,0 +1,64 @@ +// +// NSString+Regex.h +// YUMI +// +// Created by YUMI on 2021/9/14. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSString (Utils) + +///是否是正确的手机号 +- (BOOL)isPhoneNumber; + + +///MD5加密 +- (NSString *)MD5String; + ++ (BOOL)versionCompareOldStr:(NSString *)first andNewStr: (NSString *)second; + +///数字转化为万 ++ (NSString *)getDealNumWithString:(NSString *)string; +///数字转化为十万 ++(NSString *)getDealTenNumWithString:(NSString *)string; + ++ (NSString *)formatNumberToKOrM:(NSString *)string; + +///时间戳转化为需要显示的内容 ++ (NSString *)stringWithTimeStamp:(NSString *)timeStamp; +///通过生日获取星座 ++ (NSString *)calculateConstellationWithMonth:(long)time; +///通过生日获取星座 ++ (NSString *)getCalculateConstellationTextWithMonth:(long)time; +///通过生日获取星座图片 ++ (NSString *)getCalculateConstellationImageWithMonth:(long)time; +///得到年龄 ++(NSString *)getAgeWithBirth:(long)birth; +///得到区号 ++(NSString *)getCountryCode; +///产生唯一的key,用于图片或文件上传 ++ (NSString *)createUUID; + ++ (BOOL)isEmpty:(NSString *)string; +//- (BOOL)isEmpty; + +- (NSString *)pureURLString; + ++ (NSString *)formatNumberToKOrM_NoRounding:(NSString *)string; + ++ (NSString *)stringByRemovingRedundantZeros:(NSString *)string; + ++ (NSString *)trimString:(NSString *)input lengthLimit:(NSInteger)limit; + ++ (BOOL)isValidImageURL:(NSString *)url; + +/// 检查字符串是否为图片格式(通过扩展名判断) ++ (BOOL)isImageFormat:(NSString *)url; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/NSString/NSString+Utils.m b/YuMi/Tools/NSString/NSString+Utils.m index ce091de..354ae89 100644 --- a/YuMi/Tools/NSString/NSString+Utils.m +++ b/YuMi/Tools/NSString/NSString+Utils.m @@ -1,9 +1,7 @@ -// -// NSString+Regex.m -// YUMI -// + + // Created by YUMI on 2021/9/14. -// + #import "NSString+Utils.h" #import @@ -11,14 +9,14 @@ @implementation NSString (Utils) -///是否是正确的手机号 + - (BOOL)isPhoneNumber{ NSString *regex =@"^((1[3-9][0-9])|(147)|(15[^4,\\D])|(18[0,5-9]))\\d{8}$"; NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; return [pred evaluateWithObject:self]; } -///MD5加密 + - (NSString *)MD5String { const char *cstr = [self UTF8String]; unsigned char result[16]; @@ -47,182 +45,182 @@ } NSDecimalNumber *numberA = [NSDecimalNumber decimalNumberWithString:string]; NSDecimalNumber *numberB = [NSDecimalNumber decimalNumberWithString:@"1000"]; - //NSDecimalNumberBehaviors对象的创建 参数 1.RoundingMode 一个取舍枚举值 2.scale 处理范围 3.raiseOnExactness 精确出现异常是否抛出原因 4.raiseOnOverflow 上溢出是否抛出原因 4.raiseOnUnderflow 下溢出是否抛出原因 5.raiseOnDivideByZero 除以0是否抛出原因。 + NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]; - /// 这里不仅包含Multiply还有加 减 乘。 + NSDecimalNumber *numResult = [numberA decimalNumberByDividingBy:numberB withBehavior:roundingBehavior]; NSString *strResult = [numResult stringValue]; return [NSString stringWithFormat:@"%@k", strResult]; } -///数字转化为万 + + (NSString *)getDealNumWithString:(NSString *)string{ if (string.floatValue < 10000) { return [NSString stringWithFormat:@"%@", string]; } NSDecimalNumber *numberA = [NSDecimalNumber decimalNumberWithString:string]; NSDecimalNumber *numberB = [NSDecimalNumber decimalNumberWithString:@"10000"]; - //NSDecimalNumberBehaviors对象的创建 参数 1.RoundingMode 一个取舍枚举值 2.scale 处理范围 3.raiseOnExactness 精确出现异常是否抛出原因 4.raiseOnOverflow 上溢出是否抛出原因 4.raiseOnUnderflow 下溢出是否抛出原因 5.raiseOnDivideByZero 除以0是否抛出原因。 + NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]; - /// 这里不仅包含Multiply还有加 减 乘。 + NSDecimalNumber *numResult = [numberA decimalNumberByDividingBy:numberB withBehavior:roundingBehavior]; NSString *strResult = [numResult stringValue]; return [NSString stringWithFormat:YMLocalizedString(@"NSString_Utils4"), strResult]; } + (NSString *)formatNumberToKOrM:(NSString *)string { - // 定义数值单位 + NSDecimalNumber *thousand = [NSDecimalNumber decimalNumberWithString:@"1000"]; NSDecimalNumber *nine = [NSDecimalNumber decimalNumberWithString:@"9999"]; NSDecimalNumber *million = [NSDecimalNumber decimalNumberWithString:@"1000000"]; NSDecimalNumber *billion = [NSDecimalNumber decimalNumberWithString:@"1000000000"]; NSDecimalNumber *trillion = [NSDecimalNumber decimalNumberWithString:@"1000000000000"]; - // 创建 NSDecimalNumber 对象 + NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:string]; - // 判断数值范围并处理 + if ([number compare:nine] == NSOrderedAscending) { - // 小于 10000,直接返回原始值 + return [NSString stringWithFormat:@"%@", string]; } else if ([number compare:nine] != NSOrderedAscending && [number compare:million] == NSOrderedAscending) { - // 10000 到 9999999,用K表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:thousand]; - return [self formatResult:result withUnit:@"K"];//[NSString stringWithFormat:@"%.1fK", result.doubleValue]; + return [self formatResult:result withUnit:@"K"]; } else if ([number compare:million] != NSOrderedAscending && [number compare:billion] == NSOrderedAscending) { - // 超过 1000000,用M表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:million]; - return [self formatResult:result withUnit:@"M"];//[NSString stringWithFormat:@"%.1fM", result.doubleValue]; + return [self formatResult:result withUnit:@"M"]; } else if ([number compare:billion] != NSOrderedAscending && [number compare:trillion] == NSOrderedAscending) { - // 超过十亿,用 B 表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:billion]; return [self formatResult:result withUnit:@"B"]; } else { - // 超过一万亿,可以继续增加更高单位 + NSDecimalNumber *result = [number decimalNumberByDividingBy:trillion]; - return [self formatResult:result withUnit:@"T"]; // T 表示万亿 (Trillion) + return [self formatResult:result withUnit:@"T"]; } } + (NSString *)formatNumberToKOrM_NoRounding:(NSString *)string { - // 定义数值单位 + NSDecimalNumber *thousand = [NSDecimalNumber decimalNumberWithString:@"1000"]; NSDecimalNumber *nine = [NSDecimalNumber decimalNumberWithString:@"9999"]; NSDecimalNumber *million = [NSDecimalNumber decimalNumberWithString:@"1000000"]; NSDecimalNumber *billion = [NSDecimalNumber decimalNumberWithString:@"1000000000"]; NSDecimalNumber *trillion = [NSDecimalNumber decimalNumberWithString:@"1000000000000"]; - // 创建 NSDecimalNumber 对象 + NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:string]; - // 判断数值范围并处理 + if ([number compare:nine] == NSOrderedAscending) { - // 小于 10000,直接返回原始值 + return [NSString stringWithFormat:@"%@", string]; } else if ([number compare:nine] != NSOrderedAscending && [number compare:million] == NSOrderedAscending) { - // 10000 到 9999999,用K表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:thousand]; return [self truncateDecimal:result withUnit:@"K"]; } else if ([number compare:million] != NSOrderedAscending && [number compare:billion] == NSOrderedAscending) { - // 超过 1000000,用M表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:million]; return [self truncateDecimal:result withUnit:@"M"]; } else if ([number compare:billion] != NSOrderedAscending && [number compare:trillion] == NSOrderedAscending) { - // 超过十亿,用 B 表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:billion]; return [self truncateDecimal:result withUnit:@"B"]; } else { - // 超过一万亿,可以继续增加更高单位 + NSDecimalNumber *result = [number decimalNumberByDividingBy:trillion]; - return [self truncateDecimal:result withUnit:@"T"]; // T 表示万亿 (Trillion) + return [self truncateDecimal:result withUnit:@"T"]; } } -// 格式化并截断小数位 + + (NSString *)truncateDecimal:(NSDecimalNumber *)decimal withUnit:(NSString *)unit { - // 获取字符串形式的结果,并截断到一位小数 + NSString *decimalString = decimal.stringValue; NSArray *components = [decimalString componentsSeparatedByString:@"."]; NSString *integerPart = components.firstObject; NSString *decimalPart = components.count > 1 ? components[1] : @""; if (decimalPart.length > 1) { - decimalPart = [decimalPart substringToIndex:1]; // 截断到一位小数 + decimalPart = [decimalPart substringToIndex:1]; } if (decimalPart.length == 0 || [decimalPart isEqualToString:@"0"]) { - // 如果小数部分为空或为 0,只返回整数部分 + return [NSString stringWithFormat:@"%@%@", integerPart, unit]; } else { - // 返回截断后的结果 + return [NSString stringWithFormat:@"%@.%@%@", integerPart, decimalPart, unit]; } } + (NSString *)formatResult:(NSDecimalNumber *)result withUnit:(NSString *)unit { - // 将 NSDecimalNumber 转为浮点数 + CGFloat floatValue = result.floatValue; - // 格式化字符串,保留两位小数 + NSString *formattedString = [NSString stringWithFormat:@"%.2f", floatValue]; - // 移除多余的 .00 或 .0 + if ([formattedString hasSuffix:@".00"]) { - formattedString = [formattedString substringToIndex:formattedString.length - 3]; // 移除 ".00" + formattedString = [formattedString substringToIndex:formattedString.length - 3]; } else if ([formattedString hasSuffix:@".0"]) { - formattedString = [formattedString substringToIndex:formattedString.length - 2]; // 移除 ".0" + formattedString = [formattedString substringToIndex:formattedString.length - 2]; } return [NSString stringWithFormat:@"%@%@", formattedString, unit]; } + (NSString *)stringWithTimeStamp:(NSString *)timeStamp { - // 转为秒为单位 + NSTimeInterval second = timeStamp.longLongValue / 1000; NSDate *date = [NSDate dateWithTimeIntervalSince1970:second]; - //把字符串转为NSdate + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; - // 时间 10点10分 + NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init]; [timeFormatter setDateFormat:@"HH:mm"]; - // 日期 2月18号 + NSDateFormatter *dayFormatter = [[NSDateFormatter alloc] init]; [dayFormatter setDateFormat:YMLocalizedString(@"NSString_Utils0")]; - // 日期 年月日 + NSDateFormatter *yearFormatter = [[NSDateFormatter alloc] init]; [yearFormatter setDateFormat:YMLocalizedString(@"NSString_Utils1")]; - //得到与当前时间差 + NSTimeInterval timeInterval = [date timeIntervalSinceNow]; timeInterval = -timeInterval; long temp = 0; NSString *result; - BOOL isSameDay = [[NSCalendar currentCalendar] isDateInToday:date]; // 是否是同一天 + BOOL isSameDay = [[NSCalendar currentCalendar] isDateInToday:date]; + - // A. 当天,且 timeInterval < 1分钟,显示“刚刚”; if (timeInterval < 60) { return [NSString stringWithFormat:@"%@", YMLocalizedString(@"NSString_Utils2")]; - // B. 当天,且1分钟≤ timeInterval <60分钟,显示“n分钟前”; + } else if((temp = timeInterval/60) < 60){ return [NSString stringWithFormat:YMLocalizedString(@"NSString_Utils3"),temp]; - // C. 当天,且n≥60分钟,显示“xx:xx”; + } else if((temp = temp/60) < 24 && isSameDay){ return [timeFormatter stringFromDate:date]; - // C. 非当天,且n≥60分钟,显示“xx:xx”; + } else if((temp = temp/60) < 24 && !isSameDay){ return [dayFormatter stringFromDate:date]; - // D. 跨天,且未跨年,显示“mm-dd”; + } else if((temp = temp/30) < 30){ return [dayFormatter stringFromDate:date]; } else { - // E. 跨年,显示“yyyy-mm-dd”; + return [yearFormatter stringFromDate:date]; } @@ -256,7 +254,7 @@ return [NSString stringWithFormat:YMLocalizedString(@"XPMineHeadView6"),result]; } -///通过生日获取星座图片 + + (NSString *)getCalculateConstellationImageWithMonth:(long)time{ NSString *astroString = YMLocalizedString(@"XPMineHeadView0"); NSString *astroFormat = @"102123444543"; @@ -282,7 +280,7 @@ NSDictionary *starDic = @{YMLocalizedString(@"XPMineHeadView9"):@"pi_capricorn",YMLocalizedString(@"XPMineHeadView10"):@"pi_water_bottle",YMLocalizedString(@"XPMineHeadView11"):@"pi_pisces",YMLocalizedString(@"XPMineHeadView12"):@"pi_aries",YMLocalizedString(@"XPMineHeadView13"):@"pi_taurus",YMLocalizedString(@"XPMineHeadView14"):@"pi_gemini",YMLocalizedString(@"XPMineHeadView15"):@"pi_cancer",YMLocalizedString(@"XPMineHeadView16"):@"pi_lion",YMLocalizedString(@"XPMineHeadView17"):@"pi_virgin",YMLocalizedString(@"XPMineHeadView18"):@"pi_libra",YMLocalizedString(@"XPMineHeadView19"):@"pi_scorpion",YMLocalizedString(@"XPMineHeadView20"):@"pi_shooter"}; return starDic[result]; } -///通过生日获取星座 + + (NSString *)getCalculateConstellationTextWithMonth:(long)time{ NSString *astroString = YMLocalizedString(@"XPMineHeadView0"); NSString *astroFormat = @"102123444543"; @@ -332,16 +330,16 @@ NSInteger brithDateYear = [components1 year]; NSInteger brithDateDay = [components1 day]; NSInteger brithDateMonth = [components1 month]; - // 获取系统当前 年月日 + NSDateComponents *components2 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]]; NSInteger currentDateYear = [components2 year]; - NSInteger currentDateDay = [components2 day]; NSInteger currentDateMonth = [components2 month]; // 计算年龄 + NSInteger currentDateDay = [components2 day]; NSInteger currentDateMonth = [components2 month]; NSInteger iAge = currentDateYear - brithDateYear - 1; if ((currentDateMonth > brithDateMonth) || (currentDateMonth == brithDateMonth && currentDateDay >= brithDateDay)) { iAge++; } return [NSString stringWithFormat:@" %ld ", iAge]; } -///得到区号 + +(NSString *)getCountryCode{ return @""; } @@ -367,30 +365,29 @@ - (NSString *)pureURLString { NSString *encodingUrl = [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet]; - return encodingUrl;//[self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; -// NSURLComponents *components = [NSURLComponents componentsWithString:self]; -// components.query = [components.query stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; -// return components.string; + return encodingUrl; + + } + (NSString *)stringByRemovingRedundantZeros:(NSString *)string { - // 1. 检查输入是否有效 + if (!string || string.length == 0) { return string; } - // 2. 检查字符串是否包含小数点 + if ([string rangeOfString:@"."].location == NSNotFound) { - return string; // 没有小数点,直接返回原始字符串 + return string; } - // 3. 使用NSDecimalNumber进行精确的数值处理 + NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:string]; if ([decimalNumber isEqual:[NSDecimalNumber notANumber]]) { - return string; // 转换失败,返回原始字符串 + return string; } - // 4. 设置四舍五入处理器,精确到小数点后2位 + NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 @@ -399,29 +396,29 @@ raiseOnUnderflow:NO raiseOnDivideByZero:NO]; - // 5. 执行四舍五入操作 + NSDecimalNumber *roundedNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:handler]; - // 6. 将四舍五入后的数字转换为字符串 + NSString *formattedString = [roundedNumber stringValue]; - // 7. 分离整数部分和小数部分 + NSArray *components = [formattedString componentsSeparatedByString:@"."]; NSString *integerPart = components[0]; - // 8. 如果没有小数部分,直接返回整数部分 + if (components.count < 2) { return integerPart; } NSString *fractionalPart = components[1]; - // 9. 如果小数部分为空,返回整数部分 + if (fractionalPart.length == 0) { return integerPart; } - // 10. 移除小数部分末尾的0 + NSUInteger lastNonZeroIndex = NSNotFound; for (NSInteger i = fractionalPart.length - 1; i >= 0; i--) { if ([fractionalPart characterAtIndex:i] != '0') { @@ -430,51 +427,16 @@ } } - // 11. 如果小数部分全是0,返回整数部分 + if (lastNonZeroIndex == NSNotFound) { return integerPart; } else { - // 12. 组合整数部分和修剪后的小数部分 + NSString *trimmedFraction = [fractionalPart substringToIndex:lastNonZeroIndex + 1]; return [NSString stringWithFormat:@"%@.%@", integerPart, trimmedFraction]; } } -//+ (NSString *)stringByRemovingRedundantZeros:(NSString *)string { -// if (![string containsString:@"."]) { -// return string; // 不包含小數點,直接返回 -// } -// -// // 將字串分割成整數部分和小數部分 -// NSArray *components = [string componentsSeparatedByString:@"."]; -// if (components.count > 2) { -// return string; // 包含多個小數點,不處理直接返回 (或者您可以考慮拋出錯誤) -// } -// -// NSString *integerPart = components[0]; -// NSString *fractionalPart = components.count > 1 ? components[1] : @""; -// -// if (fractionalPart.length == 0) { -// return integerPart; // 沒有小數部分,直接返回整數部分 -// } -// -// // 從後向前移除小數部分末尾的 0 -// NSInteger lastNonZeroIndex = -1; -// for (NSInteger i = fractionalPart.length - 1; i >= 0; i--) { -// if ([fractionalPart characterAtIndex:i] != '0') { -// lastNonZeroIndex = i; -// break; -// } -// } -// -// if (lastNonZeroIndex == -1) { -// return integerPart; // 小數部分全是 0,返回整數部分 -// } else { -// // 截取到最後一個非零數字 -// NSString *trimmedFractionalPart = [fractionalPart substringToIndex:lastNonZeroIndex + 1]; -// return [NSString stringWithFormat:@"%@.%@", integerPart, trimmedFractionalPart]; -// } -//} + (NSString *)trimString:(NSString *)input lengthLimit:(NSInteger)limit { if (input.length <= limit) { @@ -485,7 +447,7 @@ } } -/// 判断 URL 是否为有效的图片格式 + + (BOOL)isValidImageURL:(NSString *)url { if ([NSString isEmpty:url]) { return NO; @@ -503,7 +465,7 @@ return NO; } -/// 检查字符串是否为图片格式(通过扩展名判断) + + (BOOL)isImageFormat:(NSString *)url { if ([NSString isEmpty:url]) { return NO; diff --git a/YuMi/Tools/NSString/NSString+Utils.m.backup b/YuMi/Tools/NSString/NSString+Utils.m.backup new file mode 100644 index 0000000..ce091de --- /dev/null +++ b/YuMi/Tools/NSString/NSString+Utils.m.backup @@ -0,0 +1,524 @@ +// +// NSString+Regex.m +// YUMI +// +// Created by YUMI on 2021/9/14. +// + +#import "NSString+Utils.h" +#import + + +@implementation NSString (Utils) + +///是否是正确的手机号 +- (BOOL)isPhoneNumber{ + NSString *regex =@"^((1[3-9][0-9])|(147)|(15[^4,\\D])|(18[0,5-9]))\\d{8}$"; + NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; + return [pred evaluateWithObject:self]; +} + +///MD5加密 +- (NSString *)MD5String { + const char *cstr = [self UTF8String]; + unsigned char result[16]; + CC_MD5(cstr, (CC_LONG)strlen(cstr), result); + return [NSString stringWithFormat: + @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], + result[4], result[5], result[6], result[7], + result[8], result[9], result[10], result[11], + result[12], result[13], result[14], result[15] + ]; +} + ++ (BOOL)versionCompareOldStr:(NSString *)first andNewStr: (NSString *)second{ + if ([first compare:second options:NSNumericSearch] == NSOrderedAscending){ + return NO; + }else if ([first compare:second options:NSNumericSearch] == NSOrderedSame){ + return YES; + }else{ + return YES; + } +} ++(NSString *)getDealTenNumWithString:(NSString *)string{ + if (string.floatValue < 100000) { + return [NSString stringWithFormat:@"%@", string]; + } + NSDecimalNumber *numberA = [NSDecimalNumber decimalNumberWithString:string]; + NSDecimalNumber *numberB = [NSDecimalNumber decimalNumberWithString:@"1000"]; + //NSDecimalNumberBehaviors对象的创建 参数 1.RoundingMode 一个取舍枚举值 2.scale 处理范围 3.raiseOnExactness 精确出现异常是否抛出原因 4.raiseOnOverflow 上溢出是否抛出原因 4.raiseOnUnderflow 下溢出是否抛出原因 5.raiseOnDivideByZero 除以0是否抛出原因。 + NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]; + /// 这里不仅包含Multiply还有加 减 乘。 + NSDecimalNumber *numResult = [numberA decimalNumberByDividingBy:numberB withBehavior:roundingBehavior]; + NSString *strResult = [numResult stringValue]; + return [NSString stringWithFormat:@"%@k", strResult]; +} +///数字转化为万 ++ (NSString *)getDealNumWithString:(NSString *)string{ + if (string.floatValue < 10000) { + return [NSString stringWithFormat:@"%@", string]; + } + NSDecimalNumber *numberA = [NSDecimalNumber decimalNumberWithString:string]; + NSDecimalNumber *numberB = [NSDecimalNumber decimalNumberWithString:@"10000"]; + //NSDecimalNumberBehaviors对象的创建 参数 1.RoundingMode 一个取舍枚举值 2.scale 处理范围 3.raiseOnExactness 精确出现异常是否抛出原因 4.raiseOnOverflow 上溢出是否抛出原因 4.raiseOnUnderflow 下溢出是否抛出原因 5.raiseOnDivideByZero 除以0是否抛出原因。 + NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]; + /// 这里不仅包含Multiply还有加 减 乘。 + NSDecimalNumber *numResult = [numberA decimalNumberByDividingBy:numberB withBehavior:roundingBehavior]; + NSString *strResult = [numResult stringValue]; + return [NSString stringWithFormat:YMLocalizedString(@"NSString_Utils4"), strResult]; +} + ++ (NSString *)formatNumberToKOrM:(NSString *)string { + // 定义数值单位 + NSDecimalNumber *thousand = [NSDecimalNumber decimalNumberWithString:@"1000"]; + NSDecimalNumber *nine = [NSDecimalNumber decimalNumberWithString:@"9999"]; + NSDecimalNumber *million = [NSDecimalNumber decimalNumberWithString:@"1000000"]; + NSDecimalNumber *billion = [NSDecimalNumber decimalNumberWithString:@"1000000000"]; + NSDecimalNumber *trillion = [NSDecimalNumber decimalNumberWithString:@"1000000000000"]; + // 创建 NSDecimalNumber 对象 + NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:string]; + + // 判断数值范围并处理 + if ([number compare:nine] == NSOrderedAscending) { + // 小于 10000,直接返回原始值 + return [NSString stringWithFormat:@"%@", string]; + } else if ([number compare:nine] != NSOrderedAscending && [number compare:million] == NSOrderedAscending) { + // 10000 到 9999999,用K表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:thousand]; + return [self formatResult:result withUnit:@"K"];//[NSString stringWithFormat:@"%.1fK", result.doubleValue]; + } else if ([number compare:million] != NSOrderedAscending && [number compare:billion] == NSOrderedAscending) { + // 超过 1000000,用M表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:million]; + return [self formatResult:result withUnit:@"M"];//[NSString stringWithFormat:@"%.1fM", result.doubleValue]; + } else if ([number compare:billion] != NSOrderedAscending && [number compare:trillion] == NSOrderedAscending) { + // 超过十亿,用 B 表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:billion]; + return [self formatResult:result withUnit:@"B"]; + } else { + // 超过一万亿,可以继续增加更高单位 + NSDecimalNumber *result = [number decimalNumberByDividingBy:trillion]; + return [self formatResult:result withUnit:@"T"]; // T 表示万亿 (Trillion) + } +} + ++ (NSString *)formatNumberToKOrM_NoRounding:(NSString *)string { + // 定义数值单位 + NSDecimalNumber *thousand = [NSDecimalNumber decimalNumberWithString:@"1000"]; + NSDecimalNumber *nine = [NSDecimalNumber decimalNumberWithString:@"9999"]; + NSDecimalNumber *million = [NSDecimalNumber decimalNumberWithString:@"1000000"]; + NSDecimalNumber *billion = [NSDecimalNumber decimalNumberWithString:@"1000000000"]; + NSDecimalNumber *trillion = [NSDecimalNumber decimalNumberWithString:@"1000000000000"]; + // 创建 NSDecimalNumber 对象 + NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:string]; + + // 判断数值范围并处理 + if ([number compare:nine] == NSOrderedAscending) { + // 小于 10000,直接返回原始值 + return [NSString stringWithFormat:@"%@", string]; + } else if ([number compare:nine] != NSOrderedAscending && [number compare:million] == NSOrderedAscending) { + // 10000 到 9999999,用K表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:thousand]; + return [self truncateDecimal:result withUnit:@"K"]; + } else if ([number compare:million] != NSOrderedAscending && [number compare:billion] == NSOrderedAscending) { + // 超过 1000000,用M表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:million]; + return [self truncateDecimal:result withUnit:@"M"]; + } else if ([number compare:billion] != NSOrderedAscending && [number compare:trillion] == NSOrderedAscending) { + // 超过十亿,用 B 表示 + NSDecimalNumber *result = [number decimalNumberByDividingBy:billion]; + return [self truncateDecimal:result withUnit:@"B"]; + } else { + // 超过一万亿,可以继续增加更高单位 + NSDecimalNumber *result = [number decimalNumberByDividingBy:trillion]; + return [self truncateDecimal:result withUnit:@"T"]; // T 表示万亿 (Trillion) + } +} + +// 格式化并截断小数位 ++ (NSString *)truncateDecimal:(NSDecimalNumber *)decimal withUnit:(NSString *)unit { + // 获取字符串形式的结果,并截断到一位小数 + NSString *decimalString = decimal.stringValue; + NSArray *components = [decimalString componentsSeparatedByString:@"."]; + NSString *integerPart = components.firstObject; + NSString *decimalPart = components.count > 1 ? components[1] : @""; + + if (decimalPart.length > 1) { + decimalPart = [decimalPart substringToIndex:1]; // 截断到一位小数 + } + + if (decimalPart.length == 0 || [decimalPart isEqualToString:@"0"]) { + // 如果小数部分为空或为 0,只返回整数部分 + return [NSString stringWithFormat:@"%@%@", integerPart, unit]; + } else { + // 返回截断后的结果 + return [NSString stringWithFormat:@"%@.%@%@", integerPart, decimalPart, unit]; + } +} + + ++ (NSString *)formatResult:(NSDecimalNumber *)result withUnit:(NSString *)unit { + // 将 NSDecimalNumber 转为浮点数 + CGFloat floatValue = result.floatValue; + + // 格式化字符串,保留两位小数 + NSString *formattedString = [NSString stringWithFormat:@"%.2f", floatValue]; + + // 移除多余的 .00 或 .0 + if ([formattedString hasSuffix:@".00"]) { + formattedString = [formattedString substringToIndex:formattedString.length - 3]; // 移除 ".00" + } else if ([formattedString hasSuffix:@".0"]) { + formattedString = [formattedString substringToIndex:formattedString.length - 2]; // 移除 ".0" + } + + return [NSString stringWithFormat:@"%@%@", formattedString, unit]; +} + ++ (NSString *)stringWithTimeStamp:(NSString *)timeStamp { + // 转为秒为单位 + NSTimeInterval second = timeStamp.longLongValue / 1000; + NSDate *date = [NSDate dateWithTimeIntervalSince1970:second]; + + //把字符串转为NSdate + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; + // 时间 10点10分 + NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init]; + [timeFormatter setDateFormat:@"HH:mm"]; + // 日期 2月18号 + NSDateFormatter *dayFormatter = [[NSDateFormatter alloc] init]; + [dayFormatter setDateFormat:YMLocalizedString(@"NSString_Utils0")]; + // 日期 年月日 + NSDateFormatter *yearFormatter = [[NSDateFormatter alloc] init]; + [yearFormatter setDateFormat:YMLocalizedString(@"NSString_Utils1")]; + + //得到与当前时间差 + NSTimeInterval timeInterval = [date timeIntervalSinceNow]; + timeInterval = -timeInterval; + + long temp = 0; + NSString *result; + + BOOL isSameDay = [[NSCalendar currentCalendar] isDateInToday:date]; // 是否是同一天 + + // A. 当天,且 timeInterval < 1分钟,显示“刚刚”; + if (timeInterval < 60) { + return [NSString stringWithFormat:@"%@", YMLocalizedString(@"NSString_Utils2")]; + + // B. 当天,且1分钟≤ timeInterval <60分钟,显示“n分钟前”; + } else if((temp = timeInterval/60) < 60){ + return [NSString stringWithFormat:YMLocalizedString(@"NSString_Utils3"),temp]; + + // C. 当天,且n≥60分钟,显示“xx:xx”; + } else if((temp = temp/60) < 24 && isSameDay){ + return [timeFormatter stringFromDate:date]; + + // C. 非当天,且n≥60分钟,显示“xx:xx”; + } else if((temp = temp/60) < 24 && !isSameDay){ + return [dayFormatter stringFromDate:date]; + + // D. 跨天,且未跨年,显示“mm-dd”; + } else if((temp = temp/30) < 30){ + return [dayFormatter stringFromDate:date]; + + } else { + // E. 跨年,显示“yyyy-mm-dd”; + return [yearFormatter stringFromDate:date]; + } + + return result; +} + ++ (NSString *)calculateConstellationWithMonth:(long)time +{ + NSString *astroString = YMLocalizedString(@"XPMineHeadView0"); + NSString *astroFormat = @"102123444543"; + NSString *result; + + NSInteger month = [NSString getMonth:time]; + NSInteger day = [NSString getDay:time]; + + if (month<1 || month>12 || day<1 || day>31){ + return YMLocalizedString(@"XPMineHeadView1"); + } + + if(month==2 && day>29) + { + return YMLocalizedString(@"XPMineHeadView2"); + }else if(month==4 || month==6 || month==9 || month==11) { + if (day>30) { + return YMLocalizedString(@"XPMineHeadView3"); + } + } + + result=[NSString stringWithFormat:@"%@",[astroString substringWithRange:NSMakeRange(month*2-(day < [[astroFormat substringWithRange:NSMakeRange((month-1), 1)] intValue] - (-19))*2,2)]]; + + return [NSString stringWithFormat:YMLocalizedString(@"XPMineHeadView6"),result]; + +} +///通过生日获取星座图片 ++ (NSString *)getCalculateConstellationImageWithMonth:(long)time{ + NSString *astroString = YMLocalizedString(@"XPMineHeadView0"); + NSString *astroFormat = @"102123444543"; + NSString *result; + + NSInteger month = [self getMonth:time]; + NSInteger day = [self getDay:time]; + + if (month<1 || month>12 || day<1 || day>31){ + return @""; + } + + if(month==2 && day>29) + { + return @""; + }else if(month==4 || month==6 || month==9 || month==11) { + if (day>30) { + return @""; + } + } + + result=[NSString stringWithFormat:@"%@",[astroString substringWithRange:NSMakeRange(month*2-(day < [[astroFormat substringWithRange:NSMakeRange((month-1), 1)] intValue] - (-19))*2,2)]]; + NSDictionary *starDic = @{YMLocalizedString(@"XPMineHeadView9"):@"pi_capricorn",YMLocalizedString(@"XPMineHeadView10"):@"pi_water_bottle",YMLocalizedString(@"XPMineHeadView11"):@"pi_pisces",YMLocalizedString(@"XPMineHeadView12"):@"pi_aries",YMLocalizedString(@"XPMineHeadView13"):@"pi_taurus",YMLocalizedString(@"XPMineHeadView14"):@"pi_gemini",YMLocalizedString(@"XPMineHeadView15"):@"pi_cancer",YMLocalizedString(@"XPMineHeadView16"):@"pi_lion",YMLocalizedString(@"XPMineHeadView17"):@"pi_virgin",YMLocalizedString(@"XPMineHeadView18"):@"pi_libra",YMLocalizedString(@"XPMineHeadView19"):@"pi_scorpion",YMLocalizedString(@"XPMineHeadView20"):@"pi_shooter"}; + return starDic[result]; +} +///通过生日获取星座 ++ (NSString *)getCalculateConstellationTextWithMonth:(long)time{ + NSString *astroString = YMLocalizedString(@"XPMineHeadView0"); + NSString *astroFormat = @"102123444543"; + NSString *result; + + NSInteger month = [self getMonth:time]; + NSInteger day = [self getDay:time]; + + if (month<1 || month>12 || day<1 || day>31){ + return @""; + } + + if(month==2 && day>29) + { + return @""; + }else if(month==4 || month==6 || month==9 || month==11) { + if (day>30) { + return @""; + } + } + + result=[NSString stringWithFormat:@"%@",[astroString substringWithRange:NSMakeRange(month*2-(day < [[astroFormat substringWithRange:NSMakeRange((month-1), 1)] intValue] - (-19))*2,2)]]; + return result; +} ++(NSInteger) getMonth:(long )time +{ + NSDate *date = [NSDate dateWithTimeIntervalSince1970:time/1000]; + NSCalendar* calendar = [NSCalendar currentCalendar]; + NSDateComponents* components = [calendar components:NSCalendarUnitMonth fromDate:date]; + NSInteger month = components.month; + return month; +} + ++ (NSInteger) getDay:(long) time +{ + NSDate *date = [NSDate dateWithTimeIntervalSince1970:time/1000]; + NSCalendar* calendar = [NSCalendar currentCalendar]; + NSDateComponents* components = [calendar components:NSCalendarUnitDay fromDate:date]; + NSInteger day = components.day; + return day; +} ++(NSString *)getAgeWithBirth:(long)birth{ + if (birth == 0) { + return @" "; + } + NSDateComponents *components1 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate dateWithTimeIntervalSince1970:birth/1000]]; + NSInteger brithDateYear = [components1 year]; + NSInteger brithDateDay = [components1 day]; + NSInteger brithDateMonth = [components1 month]; + // 获取系统当前 年月日 + NSDateComponents *components2 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]]; NSInteger currentDateYear = [components2 year]; + NSInteger currentDateDay = [components2 day]; NSInteger currentDateMonth = [components2 month]; // 计算年龄 + NSInteger iAge = currentDateYear - brithDateYear - 1; + if ((currentDateMonth > brithDateMonth) || (currentDateMonth == brithDateMonth && currentDateDay >= brithDateDay)) { + iAge++; + } + return [NSString stringWithFormat:@" %ld ", iAge]; +} +///得到区号 ++(NSString *)getCountryCode{ + return @""; +} ++(NSString *)createUUID{ + + CFUUIDRef uuid; + CFStringRef uuidText; + uuid = CFUUIDCreate(NULL); + uuidText = CFUUIDCreateString(NULL, uuid); + NSString *time = [NSDate getNowTimeTimestamp]; + NSString *result = [NSString stringWithFormat:@"%@%@",uuidText,time]; + return [result MD5String]; + +} + ++ (BOOL)isEmpty:(NSString *)string { + if (string == nil || [string isKindOfClass:[NSNull class]]) { + return YES; + } + NSString *trimmedString = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + return trimmedString.length == 0; +} + +- (NSString *)pureURLString { + NSString *encodingUrl = [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet]; + return encodingUrl;//[self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; +// NSURLComponents *components = [NSURLComponents componentsWithString:self]; +// components.query = [components.query stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; +// return components.string; +} + ++ (NSString *)stringByRemovingRedundantZeros:(NSString *)string { + // 1. 检查输入是否有效 + if (!string || string.length == 0) { + return string; + } + + // 2. 检查字符串是否包含小数点 + if ([string rangeOfString:@"."].location == NSNotFound) { + return string; // 没有小数点,直接返回原始字符串 + } + + // 3. 使用NSDecimalNumber进行精确的数值处理 + NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:string]; + if ([decimalNumber isEqual:[NSDecimalNumber notANumber]]) { + return string; // 转换失败,返回原始字符串 + } + + // 4. 设置四舍五入处理器,精确到小数点后2位 + NSDecimalNumberHandler *handler = [NSDecimalNumberHandler + decimalNumberHandlerWithRoundingMode:NSRoundPlain + scale:2 + raiseOnExactness:NO + raiseOnOverflow:NO + raiseOnUnderflow:NO + raiseOnDivideByZero:NO]; + + // 5. 执行四舍五入操作 + NSDecimalNumber *roundedNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:handler]; + + // 6. 将四舍五入后的数字转换为字符串 + NSString *formattedString = [roundedNumber stringValue]; + + // 7. 分离整数部分和小数部分 + NSArray *components = [formattedString componentsSeparatedByString:@"."]; + NSString *integerPart = components[0]; + + // 8. 如果没有小数部分,直接返回整数部分 + if (components.count < 2) { + return integerPart; + } + + NSString *fractionalPart = components[1]; + + // 9. 如果小数部分为空,返回整数部分 + if (fractionalPart.length == 0) { + return integerPart; + } + + // 10. 移除小数部分末尾的0 + NSUInteger lastNonZeroIndex = NSNotFound; + for (NSInteger i = fractionalPart.length - 1; i >= 0; i--) { + if ([fractionalPart characterAtIndex:i] != '0') { + lastNonZeroIndex = i; + break; + } + } + + // 11. 如果小数部分全是0,返回整数部分 + if (lastNonZeroIndex == NSNotFound) { + return integerPart; + } else { + // 12. 组合整数部分和修剪后的小数部分 + NSString *trimmedFraction = [fractionalPart substringToIndex:lastNonZeroIndex + 1]; + return [NSString stringWithFormat:@"%@.%@", integerPart, trimmedFraction]; + } +} + +//+ (NSString *)stringByRemovingRedundantZeros:(NSString *)string { +// if (![string containsString:@"."]) { +// return string; // 不包含小數點,直接返回 +// } +// +// // 將字串分割成整數部分和小數部分 +// NSArray *components = [string componentsSeparatedByString:@"."]; +// if (components.count > 2) { +// return string; // 包含多個小數點,不處理直接返回 (或者您可以考慮拋出錯誤) +// } +// +// NSString *integerPart = components[0]; +// NSString *fractionalPart = components.count > 1 ? components[1] : @""; +// +// if (fractionalPart.length == 0) { +// return integerPart; // 沒有小數部分,直接返回整數部分 +// } +// +// // 從後向前移除小數部分末尾的 0 +// NSInteger lastNonZeroIndex = -1; +// for (NSInteger i = fractionalPart.length - 1; i >= 0; i--) { +// if ([fractionalPart characterAtIndex:i] != '0') { +// lastNonZeroIndex = i; +// break; +// } +// } +// +// if (lastNonZeroIndex == -1) { +// return integerPart; // 小數部分全是 0,返回整數部分 +// } else { +// // 截取到最後一個非零數字 +// NSString *trimmedFractionalPart = [fractionalPart substringToIndex:lastNonZeroIndex + 1]; +// return [NSString stringWithFormat:@"%@.%@", integerPart, trimmedFractionalPart]; +// } +//} + ++ (NSString *)trimString:(NSString *)input lengthLimit:(NSInteger)limit { + if (input.length <= limit) { + return input; + } else { + NSString *trimmedString = [input substringToIndex:limit]; + return [trimmedString stringByAppendingString:@"..."]; + } +} + +/// 判断 URL 是否为有效的图片格式 ++ (BOOL)isValidImageURL:(NSString *)url { + if ([NSString isEmpty:url]) { + return NO; + } + + NSString *lowercaseURL = url.lowercaseString; + NSArray *imageExtensions = @[@"png", @"jpg", @"jpeg", @"gif", @"webp", @"bmp", @"svg"]; + + for (NSString *extension in imageExtensions) { + if ([lowercaseURL hasSuffix:extension]) { + return YES; + } + } + + return NO; +} + +/// 检查字符串是否为图片格式(通过扩展名判断) ++ (BOOL)isImageFormat:(NSString *)url { + if ([NSString isEmpty:url]) { + return NO; + } + + NSString *lowercaseURL = url.lowercaseString; + NSArray *imageExtensions = @[@".png", @".jpg", @".jpeg", @".gif", @".webp", @".bmp", @".svg"]; + + for (NSString *extension in imageExtensions) { + if ([lowercaseURL hasSuffix:extension]) { + return YES; + } + } + + return NO; +} + +@end diff --git a/YuMi/Tools/Reachability/YYReachability.h b/YuMi/Tools/Reachability/YYReachability.h index 0591044..d5751de 100644 --- a/YuMi/Tools/Reachability/YYReachability.h +++ b/YuMi/Tools/Reachability/YYReachability.h @@ -1,109 +1,99 @@ -/* - Copyright (c) 2011, Tony Million. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#import -#import - -#import -#import -#import -#import -#import -#import - -/** - * Does ARC support GCD objects? - * It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ - * - * @see http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h - **/ -#if OS_OBJECT_USE_OBJC -#define NEEDS_DISPATCH_RETAIN_RELEASE 0 -#else -#define NEEDS_DISPATCH_RETAIN_RELEASE 1 -#endif - -/** - * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X. - * - * @see http://nshipster.com/ns_enum-ns_options/ - **/ -#ifndef NS_ENUM -#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type -#endif - -extern NSString *const kYYReachabilityChangedNotification; - -typedef NS_ENUM(NSInteger, NetworkStatus) { - // Apple NetworkStatus Compatible Names. - NotReachable = 0, - ReachableViaWiFi = 2, - ReachableViaWWAN = 1 -}; - -@class YYReachability; - -typedef void (^NetworkReachable)(YYReachability * reachability); -typedef void (^NetworkUnreachable)(YYReachability * reachability); - -@interface YYReachability : NSObject - -@property (nonatomic, copy) NetworkReachable reachableBlock; -@property (nonatomic, copy) NetworkUnreachable unreachableBlock; - - -@property (nonatomic, assign) BOOL reachableOnWWAN; - -+(YYReachability*)reachabilityWithHostname:(NSString*)hostname; -+(YYReachability*)reachabilityForInternetConnection; -+(YYReachability*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress; -+(YYReachability*)reachabilityForLocalWiFi; - --(YYReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; - --(BOOL)startNotifier; --(void)stopNotifier; - --(BOOL)isReachable; --(BOOL)isReachableViaWWAN; --(BOOL)isReachableViaWiFi; - -// WWAN may be available, but not active until a connection has been established. -// WiFi may require a connection for VPN on Demand. --(BOOL)isConnectionRequired; // Identical DDG variant. --(BOOL)connectionRequired; // Apple's routine. -// Dynamic, on demand connection? --(BOOL)isConnectionOnDemand; -// Is user intervention required? --(BOOL)isInterventionRequired; - --(NetworkStatus)currentReachabilityStatus; --(SCNetworkReachabilityFlags)reachabilityFlags; --(NSString*)currentReachabilityString; --(NSString*)currentReachabilityFlags; - -@end +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +#import +#import +#import +#import +#import +#import + + +#if OS_OBJECT_USE_OBJC +#define NEEDS_DISPATCH_RETAIN_RELEASE 0 +#else +#define NEEDS_DISPATCH_RETAIN_RELEASE 1 +#endif + + +#ifndef NS_ENUM +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#endif + +extern NSString *const kYYReachabilityChangedNotification; + +typedef NS_ENUM(NSInteger, NetworkStatus) { + + NotReachable = 0, + ReachableViaWiFi = 2, + ReachableViaWWAN = 1 +}; + +@class YYReachability; + +typedef void (^NetworkReachable)(YYReachability * reachability); +typedef void (^NetworkUnreachable)(YYReachability * reachability); + +@interface YYReachability : NSObject + +@property (nonatomic, copy) NetworkReachable reachableBlock; +@property (nonatomic, copy) NetworkUnreachable unreachableBlock; + + +@property (nonatomic, assign) BOOL reachableOnWWAN; + ++(YYReachability*)reachabilityWithHostname:(NSString*)hostname; ++(YYReachability*)reachabilityForInternetConnection; ++(YYReachability*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress; ++(YYReachability*)reachabilityForLocalWiFi; + +-(YYReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; + +-(BOOL)startNotifier; +-(void)stopNotifier; + +-(BOOL)isReachable; +-(BOOL)isReachableViaWWAN; +-(BOOL)isReachableViaWiFi; + + +-(BOOL)isConnectionRequired; +-(BOOL)connectionRequired; + +-(BOOL)isConnectionOnDemand; + +-(BOOL)isInterventionRequired; + +-(NetworkStatus)currentReachabilityStatus; +-(SCNetworkReachabilityFlags)reachabilityFlags; +-(NSString*)currentReachabilityString; +-(NSString*)currentReachabilityFlags; + +@end diff --git a/YuMi/Tools/Reachability/YYReachability.h.backup b/YuMi/Tools/Reachability/YYReachability.h.backup new file mode 100644 index 0000000..0591044 --- /dev/null +++ b/YuMi/Tools/Reachability/YYReachability.h.backup @@ -0,0 +1,109 @@ +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +#import +#import +#import +#import +#import +#import + +/** + * Does ARC support GCD objects? + * It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ + * + * @see http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h + **/ +#if OS_OBJECT_USE_OBJC +#define NEEDS_DISPATCH_RETAIN_RELEASE 0 +#else +#define NEEDS_DISPATCH_RETAIN_RELEASE 1 +#endif + +/** + * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X. + * + * @see http://nshipster.com/ns_enum-ns_options/ + **/ +#ifndef NS_ENUM +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#endif + +extern NSString *const kYYReachabilityChangedNotification; + +typedef NS_ENUM(NSInteger, NetworkStatus) { + // Apple NetworkStatus Compatible Names. + NotReachable = 0, + ReachableViaWiFi = 2, + ReachableViaWWAN = 1 +}; + +@class YYReachability; + +typedef void (^NetworkReachable)(YYReachability * reachability); +typedef void (^NetworkUnreachable)(YYReachability * reachability); + +@interface YYReachability : NSObject + +@property (nonatomic, copy) NetworkReachable reachableBlock; +@property (nonatomic, copy) NetworkUnreachable unreachableBlock; + + +@property (nonatomic, assign) BOOL reachableOnWWAN; + ++(YYReachability*)reachabilityWithHostname:(NSString*)hostname; ++(YYReachability*)reachabilityForInternetConnection; ++(YYReachability*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress; ++(YYReachability*)reachabilityForLocalWiFi; + +-(YYReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; + +-(BOOL)startNotifier; +-(void)stopNotifier; + +-(BOOL)isReachable; +-(BOOL)isReachableViaWWAN; +-(BOOL)isReachableViaWiFi; + +// WWAN may be available, but not active until a connection has been established. +// WiFi may require a connection for VPN on Demand. +-(BOOL)isConnectionRequired; // Identical DDG variant. +-(BOOL)connectionRequired; // Apple's routine. +// Dynamic, on demand connection? +-(BOOL)isConnectionOnDemand; +// Is user intervention required? +-(BOOL)isInterventionRequired; + +-(NetworkStatus)currentReachabilityStatus; +-(SCNetworkReachabilityFlags)reachabilityFlags; +-(NSString*)currentReachabilityString; +-(NSString*)currentReachabilityFlags; + +@end diff --git a/YuMi/Tools/Reachability/YYReachability.m b/YuMi/Tools/Reachability/YYReachability.m index fcd8ba1..49cbef8 100644 --- a/YuMi/Tools/Reachability/YYReachability.m +++ b/YuMi/Tools/Reachability/YYReachability.m @@ -67,7 +67,7 @@ static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; } -// Start listening for reachability notifications on the current run loop + static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) { #pragma unused (target) @@ -77,8 +77,7 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea YYReachability *reachability = ((YYReachability*)info); #endif - // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, - // but what the heck eh? + @autoreleasepool { [reachability reachabilityChanged:flags]; @@ -156,15 +155,13 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea bzero(&localWifiAddress, sizeof(localWifiAddress)); localWifiAddress.sin_len = sizeof(localWifiAddress); localWifiAddress.sin_family = AF_INET; - // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); return [self reachabilityWithAddress:&localWifiAddress]; } -// Initialization methods - -(YYReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref { self = [super init]; @@ -199,23 +196,18 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea #pragma mark - Notifier Methods -// Notifier + // NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD -// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. -// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) + -(BOOL)startNotifier { SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; - // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves - // woah + self.reachabilityObject = self; - - // First, we need to create a serial queue. - // We allocate this once for the lifetime of the notifier. self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); if(!self.reachabilitySerialQueue) { @@ -234,7 +226,7 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); #endif - // Clear out the dispatch queue + if(self.reachabilitySerialQueue) { #if NEEDS_DISPATCH_RETAIN_RELEASE @@ -248,19 +240,17 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea return NO; } - // Set it as our reachability queue, which will retain the queue + if(!SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) { #ifdef DEBUG NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); #endif - // UH OH - FAILURE! - // First stop, any callbacks! SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); - // Then clear out the dispatch queue. + if(self.reachabilitySerialQueue) { #if NEEDS_DISPATCH_RETAIN_RELEASE @@ -279,10 +269,10 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea -(void)stopNotifier { - // First stop, any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); - // Unregister target from the GCD serial dispatch queue. + SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); if(self.reachabilitySerialQueue) @@ -298,13 +288,6 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea #pragma mark - reachability tests -// This is for the case where you flick the airplane mode; -// you end up getting something like this: -//Reachability: WR ct----- -//Reachability: -- ------- -//Reachability: WR ct----- -//Reachability: -- ------- -// We treat this as 4 UNREACHABLE triggers - really apple should do better than this #define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) @@ -321,10 +304,10 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea #if TARGET_OS_IPHONE if(flags & kSCNetworkReachabilityFlagsIsWWAN) { - // We're on 3G. + if(!self.reachableOnWWAN) { - // We don't want to connect when on 3G. + connectionUP = NO; } } @@ -351,10 +334,10 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { - // Check we're REACHABLE + if(flags & kSCNetworkReachabilityFlagsReachable) { - // Now, check we're on WWAN + if(flags & kSCNetworkReachabilityFlagsIsWWAN) { return YES; @@ -372,11 +355,11 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { - // Check we're reachable + if((flags & kSCNetworkReachabilityFlagsReachable)) { #if TARGET_OS_IPHONE - // Check we're NOT on WWAN + if((flags & kSCNetworkReachabilityFlagsIsWWAN)) { return NO; @@ -390,8 +373,6 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea } -// WWAN may be available, but not active until a connection has been established. -// WiFi may require a connection for VPN on Demand. -(BOOL)isConnectionRequired { return [self connectionRequired]; @@ -409,7 +390,7 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea return NO; } -// Dynamic, on demand connection? + -(BOOL)isConnectionOnDemand { SCNetworkReachabilityFlags flags; @@ -423,7 +404,7 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea return NO; } -// Is user intervention required? + -(BOOL)isInterventionRequired { SCNetworkReachabilityFlags flags; @@ -473,7 +454,7 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea if(temp == reachableOnWWAN) { - // Updated for the fact that we have CDMA phones now! + return NSLocalizedString(@"Cellular", @""); } if (temp == ReachableViaWiFi) @@ -508,7 +489,7 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea } } - // this makes sure the change notification happens on the MAIN THREAD + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:kYYReachabilityChangedNotification object:self]; diff --git a/YuMi/Tools/Reachability/YYReachability.m.backup b/YuMi/Tools/Reachability/YYReachability.m.backup new file mode 100644 index 0000000..fcd8ba1 --- /dev/null +++ b/YuMi/Tools/Reachability/YYReachability.m.backup @@ -0,0 +1,527 @@ +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import "YYReachability.h" + + +NSString *const kYYReachabilityChangedNotification = @"kYYReachabilityChangedNotification"; + +@interface YYReachability () + +@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; + + +#if NEEDS_DISPATCH_RETAIN_RELEASE +@property (nonatomic, assign) dispatch_queue_t reachabilitySerialQueue; +#else +@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; +#endif + + +@property (nonatomic, strong) id reachabilityObject; + +-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; +-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; + +@end + +static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) +{ + return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", +#if TARGET_OS_IPHONE + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', +#else + 'X', +#endif + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; +} + +// Start listening for reachability notifications on the current run loop +static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) +{ +#pragma unused (target) +#if __has_feature(objc_arc) + YYReachability *reachability = ((__bridge YYReachability*)info); +#else + YYReachability *reachability = ((YYReachability*)info); +#endif + + // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, + // but what the heck eh? + @autoreleasepool + { + [reachability reachabilityChanged:flags]; + } +} + + +@implementation YYReachability + +@synthesize reachabilityRef; +@synthesize reachabilitySerialQueue; + +@synthesize reachableOnWWAN; + +@synthesize reachableBlock; +@synthesize unreachableBlock; + +@synthesize reachabilityObject; + +#pragma mark - Class Constructor Methods + ++(YYReachability*)reachabilityWithHostName:(NSString*)hostname +{ + return [YYReachability reachabilityWithHostname:hostname]; +} + ++(YYReachability*)reachabilityWithHostname:(NSString*)hostname +{ + SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); + if (ref) + { + id reachability = [[self alloc] initWithReachabilityRef:ref]; + +#if __has_feature(objc_arc) + return reachability; +#else + return [reachability autorelease]; +#endif + + } + + return nil; +} + ++(YYReachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress +{ + SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); + if (ref) + { + id reachability = [[self alloc] initWithReachabilityRef:ref]; + +#if __has_feature(objc_arc) + return reachability; +#else + return [reachability autorelease]; +#endif + } + + return nil; +} + ++(YYReachability *)reachabilityForInternetConnection +{ + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + return [self reachabilityWithAddress:&zeroAddress]; +} + ++(YYReachability*)reachabilityForLocalWiFi +{ + struct sockaddr_in localWifiAddress; + bzero(&localWifiAddress, sizeof(localWifiAddress)); + localWifiAddress.sin_len = sizeof(localWifiAddress); + localWifiAddress.sin_family = AF_INET; + // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); + + return [self reachabilityWithAddress:&localWifiAddress]; +} + + +// Initialization methods + +-(YYReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref +{ + self = [super init]; + if (self != nil) + { + self.reachableOnWWAN = YES; + self.reachabilityRef = ref; + } + + return self; +} + +-(void)dealloc +{ + [self stopNotifier]; + + if(self.reachabilityRef) + { + CFRelease(self.reachabilityRef); + self.reachabilityRef = nil; + } + + self.reachableBlock = nil; + self.unreachableBlock = nil; + +#if !(__has_feature(objc_arc)) + [super dealloc]; +#endif + + +} + +#pragma mark - Notifier Methods + +// Notifier +// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD +// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. +// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) + +-(BOOL)startNotifier +{ + SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; + + // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves + // woah + self.reachabilityObject = self; + + + + // First, we need to create a serial queue. + // We allocate this once for the lifetime of the notifier. + self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); + if(!self.reachabilitySerialQueue) + { + return NO; + } + +#if __has_feature(objc_arc) + context.info = (__bridge void *)self; +#else + context.info = (void *)self; +#endif + + if (!SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) + { +#ifdef DEBUG + NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); +#endif + + // Clear out the dispatch queue + if(self.reachabilitySerialQueue) + { +#if NEEDS_DISPATCH_RETAIN_RELEASE + dispatch_release(self.reachabilitySerialQueue); +#endif + self.reachabilitySerialQueue = nil; + } + + self.reachabilityObject = nil; + + return NO; + } + + // Set it as our reachability queue, which will retain the queue + if(!SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) + { +#ifdef DEBUG + NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); +#endif + + // UH OH - FAILURE! + + // First stop, any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); + + // Then clear out the dispatch queue. + if(self.reachabilitySerialQueue) + { +#if NEEDS_DISPATCH_RETAIN_RELEASE + dispatch_release(self.reachabilitySerialQueue); +#endif + self.reachabilitySerialQueue = nil; + } + + self.reachabilityObject = nil; + + return NO; + } + + return YES; +} + +-(void)stopNotifier +{ + // First stop, any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); + + // Unregister target from the GCD serial dispatch queue. + SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); + + if(self.reachabilitySerialQueue) + { +#if NEEDS_DISPATCH_RETAIN_RELEASE + dispatch_release(self.reachabilitySerialQueue); +#endif + self.reachabilitySerialQueue = nil; + } + + self.reachabilityObject = nil; +} + +#pragma mark - reachability tests + +// This is for the case where you flick the airplane mode; +// you end up getting something like this: +//Reachability: WR ct----- +//Reachability: -- ------- +//Reachability: WR ct----- +//Reachability: -- ------- +// We treat this as 4 UNREACHABLE triggers - really apple should do better than this + +#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) + +-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags +{ + BOOL connectionUP = YES; + + if(!(flags & kSCNetworkReachabilityFlagsReachable)) + connectionUP = NO; + + if( (flags & testcase) == testcase ) + connectionUP = NO; + +#if TARGET_OS_IPHONE + if(flags & kSCNetworkReachabilityFlagsIsWWAN) + { + // We're on 3G. + if(!self.reachableOnWWAN) + { + // We don't want to connect when on 3G. + connectionUP = NO; + } + } +#endif + + return connectionUP; +} + +-(BOOL)isReachable +{ + SCNetworkReachabilityFlags flags; + + if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + return NO; + + return [self isReachableWithFlags:flags]; +} + +-(BOOL)isReachableViaWWAN +{ +#if TARGET_OS_IPHONE + + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + // Check we're REACHABLE + if(flags & kSCNetworkReachabilityFlagsReachable) + { + // Now, check we're on WWAN + if(flags & kSCNetworkReachabilityFlagsIsWWAN) + { + return YES; + } + } + } +#endif + + return NO; +} + +-(BOOL)isReachableViaWiFi +{ + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + // Check we're reachable + if((flags & kSCNetworkReachabilityFlagsReachable)) + { +#if TARGET_OS_IPHONE + // Check we're NOT on WWAN + if((flags & kSCNetworkReachabilityFlagsIsWWAN)) + { + return NO; + } +#endif + return YES; + } + } + + return NO; +} + + +// WWAN may be available, but not active until a connection has been established. +// WiFi may require a connection for VPN on Demand. +-(BOOL)isConnectionRequired +{ + return [self connectionRequired]; +} + +-(BOOL)connectionRequired +{ + SCNetworkReachabilityFlags flags; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); + } + + return NO; +} + +// Dynamic, on demand connection? +-(BOOL)isConnectionOnDemand +{ + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && + (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); + } + + return NO; +} + +// Is user intervention required? +-(BOOL)isInterventionRequired +{ + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && + (flags & kSCNetworkReachabilityFlagsInterventionRequired)); + } + + return NO; +} + + +#pragma mark - reachability status stuff + +-(NetworkStatus)currentReachabilityStatus +{ + if([self isReachable]) + { + if([self isReachableViaWiFi]) + return ReachableViaWiFi; + +#if TARGET_OS_IPHONE + return ReachableViaWWAN; +#endif + } + + return NotReachable; +} + +-(SCNetworkReachabilityFlags)reachabilityFlags +{ + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return flags; + } + + return 0; +} + +-(NSString*)currentReachabilityString +{ + NetworkStatus temp = [self currentReachabilityStatus]; + + if(temp == reachableOnWWAN) + { + // Updated for the fact that we have CDMA phones now! + return NSLocalizedString(@"Cellular", @""); + } + if (temp == ReachableViaWiFi) + { + return NSLocalizedString(@"WiFi", @""); + } + + return NSLocalizedString(@"No Connection", @""); +} + +-(NSString*)currentReachabilityFlags +{ + return reachabilityFlags([self reachabilityFlags]); +} + +#pragma mark - Callback function calls this method + +-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags +{ + if([self isReachableWithFlags:flags]) + { + if(self.reachableBlock) + { + self.reachableBlock(self); + } + } + else + { + if(self.unreachableBlock) + { + self.unreachableBlock(self); + } + } + + // this makes sure the change notification happens on the MAIN THREAD + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:kYYReachabilityChangedNotification + object:self]; + }); +} + +#pragma mark - Debug Description + +- (NSString *) description +{ + NSString *description = [NSString stringWithFormat:@"<%@: %#x>", + NSStringFromClass([self class]), (unsigned int) self]; + return description; +} + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h index ec33cec..93bf93f 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h +++ b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h @@ -1,27 +1,25 @@ -// -// SDBrowserImageView.h -// SDPhotoBrowser -// -// Created by aier on 15-2-6. -// Copyright (c) 2015年 GSD. All rights reserved. -// - -#import -#import "SDWaitingView.h" - - -@interface SDBrowserImageView : UIImageView - -@property (nonatomic, assign) CGFloat progress; -@property (nonatomic, assign, readonly) BOOL isScaled; -@property (nonatomic, assign) BOOL hasLoadedImage; - -- (void)eliminateScale; // 清除缩放 - -- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; - -- (void)doubleTapToZommWithScale:(CGFloat)scale; - -- (void)clear; - -@end + + +// Created by aier on 15-2-6. +// Copyright (c) 2015年 GSD. All rights reserved. + + +#import +#import "SDWaitingView.h" + + +@interface SDBrowserImageView : UIImageView + +@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, assign, readonly) BOOL isScaled; +@property (nonatomic, assign) BOOL hasLoadedImage; + +- (void)eliminateScale; + +- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; + +- (void)doubleTapToZommWithScale:(CGFloat)scale; + +- (void)clear; + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h.backup b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h.backup new file mode 100755 index 0000000..ec33cec --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.h.backup @@ -0,0 +1,27 @@ +// +// SDBrowserImageView.h +// SDPhotoBrowser +// +// Created by aier on 15-2-6. +// Copyright (c) 2015年 GSD. All rights reserved. +// + +#import +#import "SDWaitingView.h" + + +@interface SDBrowserImageView : UIImageView + +@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, assign, readonly) BOOL isScaled; +@property (nonatomic, assign) BOOL hasLoadedImage; + +- (void)eliminateScale; // 清除缩放 + +- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; + +- (void)doubleTapToZommWithScale:(CGFloat)scale; + +- (void)clear; + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m index d1c3fb4..a69c9a0 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m +++ b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m @@ -1,10 +1,8 @@ -// -// SDBrowserImageView.m -// SDPhotoBrowser -// + + // Created by aier on 15-2-6. // Copyright (c) 2015年 GSD. All rights reserved. -// + #import "SDBrowserImageView.h" #import "UIImageView+WebCache.h" @@ -30,13 +28,12 @@ self.contentMode = UIViewContentModeScaleAspectFit; _totalScale = 1.0; - // 捏合手势缩放图片 + UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(zoomImage:)]; pinch.delegate = self; [self addGestureRecognizer:pinch]; - } return self; } @@ -77,13 +74,12 @@ _scroll.contentSize = CGSizeMake(0, _scrollImageView.bounds.size.height); } else { - if (_scroll) [_scroll removeFromSuperview]; // 防止旋转时适配的scrollView的影响 + if (_scroll) [_scroll removeFromSuperview]; } } - - (void)setProgress:(CGFloat)progress { _progress = progress; @@ -141,7 +137,7 @@ - (void)setTotalScale:(CGFloat)totalScale { - if ((_totalScale < 0.5 && totalScale < _totalScale) || (_totalScale > 2.0 && totalScale > _totalScale)) return; // 最大缩放 2倍,最小0.5倍 + if ((_totalScale < 0.5 && totalScale < _totalScale) || (_totalScale > 2.0 && totalScale > _totalScale)) return; [self zoomWithScale:totalScale]; } @@ -162,7 +158,7 @@ CGPoint offset = _zoomingScroolView.contentOffset; offset.x = (contentW - _zoomingScroolView.frame.size.width) * 0.5; -// offset.y = (contentH - _zoomingImageView.frame.size.height) * 0.5; + _zoomingScroolView.contentOffset = offset; } else { @@ -211,7 +207,7 @@ [self setTotalScale:scale]; } -// 清除缩放 + - (void)eliminateScale { [self clear]; @@ -232,6 +228,4 @@ } - - @end diff --git a/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m.backup b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m.backup new file mode 100755 index 0000000..d1c3fb4 --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDBrowserImageView.m.backup @@ -0,0 +1,237 @@ +// +// SDBrowserImageView.m +// SDPhotoBrowser +// +// Created by aier on 15-2-6. +// Copyright (c) 2015年 GSD. All rights reserved. +// + +#import "SDBrowserImageView.h" +#import "UIImageView+WebCache.h" +#import "SDPhotoBrowserConfig.h" + +@implementation SDBrowserImageView +{ + __weak SDWaitingView *_waitingView; + BOOL _didCheckSize; + UIScrollView *_scroll; + UIImageView *_scrollImageView; + UIScrollView *_zoomingScroolView; + UIImageView *_zoomingImageView; + CGFloat _totalScale; +} + + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.userInteractionEnabled = YES; + self.contentMode = UIViewContentModeScaleAspectFit; + _totalScale = 1.0; + + // 捏合手势缩放图片 + UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(zoomImage:)]; + pinch.delegate = self; + [self addGestureRecognizer:pinch]; + + + + } + return self; +} + +- (BOOL)isScaled +{ + return 1.0 != _totalScale; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + _waitingView.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5); + + CGSize imageSize = self.image.size; + + if (self.bounds.size.width * (imageSize.height / imageSize.width) > self.bounds.size.height) { + if (!_scroll) { + UIScrollView *scroll = [[UIScrollView alloc] init]; + scroll.backgroundColor = [UIColor whiteColor]; + UIImageView *imageView = [[UIImageView alloc] init]; + imageView.image = self.image; + _scrollImageView = imageView; + [scroll addSubview:imageView]; + scroll.backgroundColor = SDPhotoBrowserBackgroundColor; + _scroll = scroll; + [self addSubview:scroll]; + if (_waitingView) { + [self bringSubviewToFront:_waitingView]; + } + } + _scroll.frame = self.bounds; + + CGFloat imageViewH = self.bounds.size.width * (imageSize.height / imageSize.width); + + _scrollImageView.bounds = CGRectMake(0, 0, _scroll.frame.size.width, imageViewH); + _scrollImageView.center = CGPointMake(_scroll.frame.size.width * 0.5, _scrollImageView.frame.size.height * 0.5); + _scroll.contentSize = CGSizeMake(0, _scrollImageView.bounds.size.height); + + } else { + if (_scroll) [_scroll removeFromSuperview]; // 防止旋转时适配的scrollView的影响 + } + +} + + + +- (void)setProgress:(CGFloat)progress +{ + _progress = progress; + _waitingView.progress = progress; + +} + +- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder +{ + SDWaitingView *waiting = [[SDWaitingView alloc] init]; + waiting.bounds = CGRectMake(0, 0, 100, 100); + waiting.mode = SDWaitingViewProgressMode; + _waitingView = waiting; + [self addSubview:waiting]; + + + __weak SDBrowserImageView *imageViewWeak = self; + + + [self sd_setImageWithURL:url placeholderImage:placeholder options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) { + imageViewWeak.progress = (CGFloat)receivedSize / expectedSize; + } completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + [imageViewWeak removeWaitingView]; + + + if (error) { + UILabel *label = [[UILabel alloc] init]; + label.bounds = CGRectMake(0, 0, 160, 30); + label.center = CGPointMake(imageViewWeak.bounds.size.width * 0.5, imageViewWeak.bounds.size.height * 0.5); + label.text = YMLocalizedString(@"SDBrowserImageView0"); + label.font = [UIFont systemFontOfSize:16]; + label.textColor = [UIColor whiteColor]; + label.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8]; + label.layer.cornerRadius = 5; + label.clipsToBounds = YES; + label.textAlignment = NSTextAlignmentCenter; + [imageViewWeak addSubview:label]; + } else { + _scrollImageView.image = image; + [_scrollImageView setNeedsDisplay]; + } + + }]; + +} + +- (void)zoomImage:(UIPinchGestureRecognizer *)recognizer +{ + [self prepareForImageViewScaling]; + CGFloat scale = recognizer.scale; + CGFloat temp = _totalScale + (scale - 1); + [self setTotalScale:temp]; + recognizer.scale = 1.0; +} + +- (void)setTotalScale:(CGFloat)totalScale +{ + if ((_totalScale < 0.5 && totalScale < _totalScale) || (_totalScale > 2.0 && totalScale > _totalScale)) return; // 最大缩放 2倍,最小0.5倍 + + [self zoomWithScale:totalScale]; +} + +- (void)zoomWithScale:(CGFloat)scale +{ + _totalScale = scale; + + _zoomingImageView.transform = CGAffineTransformMakeScale(scale, scale); + + if (scale > 1) { + CGFloat contentW = _zoomingImageView.frame.size.width; + CGFloat contentH = MAX(_zoomingImageView.frame.size.height, self.frame.size.height); + + _zoomingImageView.center = CGPointMake(contentW * 0.5, contentH * 0.5); + _zoomingScroolView.contentSize = CGSizeMake(contentW, contentH); + + + CGPoint offset = _zoomingScroolView.contentOffset; + offset.x = (contentW - _zoomingScroolView.frame.size.width) * 0.5; +// offset.y = (contentH - _zoomingImageView.frame.size.height) * 0.5; + _zoomingScroolView.contentOffset = offset; + + } else { + _zoomingScroolView.contentSize = _zoomingScroolView.frame.size; + _zoomingScroolView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); + _zoomingImageView.center = _zoomingScroolView.center; + } +} + +- (void)doubleTapToZommWithScale:(CGFloat)scale +{ + [self prepareForImageViewScaling]; + [UIView animateWithDuration:0.5 animations:^{ + [self zoomWithScale:scale]; + } completion:^(BOOL finished) { + if (scale == 1) { + [self clear]; + } + }]; +} + +- (void)prepareForImageViewScaling +{ + if (!_zoomingScroolView) { + _zoomingScroolView = [[UIScrollView alloc] initWithFrame:self.bounds]; + _zoomingScroolView.backgroundColor = SDPhotoBrowserBackgroundColor; + _zoomingScroolView.contentSize = self.bounds.size; + UIImageView *zoomingImageView = [[UIImageView alloc] initWithImage:self.image]; + CGSize imageSize = zoomingImageView.image.size; + CGFloat imageViewH = self.bounds.size.height; + if (imageSize.width > 0) { + imageViewH = self.bounds.size.width * (imageSize.height / imageSize.width); + } + zoomingImageView.bounds = CGRectMake(0, 0, self.bounds.size.width, imageViewH); + zoomingImageView.center = _zoomingScroolView.center; + zoomingImageView.contentMode = UIViewContentModeScaleAspectFit; + _zoomingImageView = zoomingImageView; + [_zoomingScroolView addSubview:zoomingImageView]; + [self addSubview:_zoomingScroolView]; + } +} + +- (void)scaleImage:(CGFloat)scale +{ + [self prepareForImageViewScaling]; + [self setTotalScale:scale]; +} + +// 清除缩放 +- (void)eliminateScale +{ + [self clear]; + _totalScale = 1.0; +} + +- (void)clear +{ + [_zoomingScroolView removeFromSuperview]; + _zoomingScroolView = nil; + _zoomingImageView = nil; + +} + +- (void)removeWaitingView +{ + [_waitingView removeFromSuperview]; +} + + + + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h index 301ecce..dd2fd03 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h +++ b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h @@ -1,39 +1,37 @@ -// -// SDPhotoBrowser.h -// photobrowser -// -// Created by aier on 15-2-3. -// Copyright (c) 2015年 aier. All rights reserved. -// - -#import - - -@class SDButton, SDPhotoBrowser; - -@protocol SDPhotoBrowserDelegate - -@required - -- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index; - -@optional - -- (NSURL *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index; -- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageForIndex:(NSInteger)index; -@end - - -@interface SDPhotoBrowser : UIView - -@property (nonatomic, weak) UIView *sourceImagesContainerView; -@property (nonatomic, assign) NSInteger currentImageIndex; -@property (nonatomic, assign) NSInteger imageCount; -@property (nonatomic, assign) BOOL isMe; -@property (nonatomic, assign) BOOL isAvatar; -@property (nonatomic, assign) CGRect sourceImagesFrame; -@property (nonatomic, strong) id delegate; -@property (nonatomic, assign) BOOL isHaveUserAdd; // 为了区分当前页面的cell是否第一个是添加图片的Icon -- (void)show; - -@end + + +// Created by aier on 15-2-3. +// Copyright (c) 2015年 aier. All rights reserved. + + +#import + + +@class SDButton, SDPhotoBrowser; + +@protocol SDPhotoBrowserDelegate + +@required + +- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index; + +@optional + +- (NSURL *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index; +- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageForIndex:(NSInteger)index; +@end + + +@interface SDPhotoBrowser : UIView + +@property (nonatomic, weak) UIView *sourceImagesContainerView; +@property (nonatomic, assign) NSInteger currentImageIndex; +@property (nonatomic, assign) NSInteger imageCount; +@property (nonatomic, assign) BOOL isMe; +@property (nonatomic, assign) BOOL isAvatar; +@property (nonatomic, assign) CGRect sourceImagesFrame; +@property (nonatomic, strong) id delegate; +@property (nonatomic, assign) BOOL isHaveUserAdd; +- (void)show; + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h.backup b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h.backup new file mode 100755 index 0000000..301ecce --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.h.backup @@ -0,0 +1,39 @@ +// +// SDPhotoBrowser.h +// photobrowser +// +// Created by aier on 15-2-3. +// Copyright (c) 2015年 aier. All rights reserved. +// + +#import + + +@class SDButton, SDPhotoBrowser; + +@protocol SDPhotoBrowserDelegate + +@required + +- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index; + +@optional + +- (NSURL *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index; +- (UIImage *)photoBrowser:(SDPhotoBrowser *)browser highQualityImageForIndex:(NSInteger)index; +@end + + +@interface SDPhotoBrowser : UIView + +@property (nonatomic, weak) UIView *sourceImagesContainerView; +@property (nonatomic, assign) NSInteger currentImageIndex; +@property (nonatomic, assign) NSInteger imageCount; +@property (nonatomic, assign) BOOL isMe; +@property (nonatomic, assign) BOOL isAvatar; +@property (nonatomic, assign) CGRect sourceImagesFrame; +@property (nonatomic, strong) id delegate; +@property (nonatomic, assign) BOOL isHaveUserAdd; // 为了区分当前页面的cell是否第一个是添加图片的Icon +- (void)show; + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m index e5002ad..4169198 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m +++ b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m @@ -1,30 +1,20 @@ -// -// SDPhotoBrowser.m -// photobrowser -// + + // Created by aier on 15-2-3. // Copyright (c) 2015年 aier. All rights reserved. -// + #import "SDPhotoBrowser.h" #import "UIImageView+WebCache.h" #import "SDBrowserImageView.h" -#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) //判断是否iPhoneX +#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhoneX_NavSafeArea ([[UIScreen mainScreen] bounds].size.height >= 812.0 ? 24 : 0) // 如果是iphoneX 顶部安全区域 24 +#define iPhoneX_NavSafeArea ([[UIScreen mainScreen] bounds].size.height >= 812.0 ? 24 : 0) -// ============在这里方便配置样式相关设置=========== - -// || -// || -// || -// \\// -// \/ #import "SDPhotoBrowserConfig.h" -// ============================================= @implementation SDPhotoBrowser { @@ -64,7 +54,7 @@ - (void)setupToolbars { - // 1. 序标 + UILabel *indexLabel = [[UILabel alloc] init]; indexLabel.bounds = CGRectMake(0, 0, 80, 30); indexLabel.textAlignment = NSTextAlignmentCenter; @@ -79,7 +69,7 @@ _indexLabel = indexLabel; [self addSubview:indexLabel]; - // 2.保存按钮 + UIButton *saveButton = [[UIButton alloc] init]; [saveButton setTitle:YMLocalizedString(@"SDPhotoBrowser0") forState:UIControlStateNormal]; [saveButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; @@ -144,10 +134,10 @@ SDBrowserImageView *imageView = [[SDBrowserImageView alloc] init]; imageView.tag = i; - // 单击图片 + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoClick:)]; - // 双击放大图片 + UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDoubleTaped:)]; doubleTap.numberOfTapsRequired = 2; @@ -162,7 +152,7 @@ } -// 加载图片 + - (void)setupImageOfImageViewForIndex:(NSInteger)index { if(index < _scrollView.subviews.count){ @@ -213,7 +203,7 @@ tempView.image = currentImageView.image; CGFloat h = (self.bounds.size.width / currentImageView.image.size.width) * currentImageView.image.size.height; - if (!currentImageView.image) { // 防止 因imageview的image加载失败 导致 崩溃 + if (!currentImageView.image) { h = self.bounds.size.height; } @@ -263,7 +253,6 @@ CGFloat h = _scrollView.frame.size.height; - [_scrollView.subviews enumerateObjectsUsingBlock:^(SDBrowserImageView *obj, NSUInteger idx, BOOL *stop) { CGFloat x = SDPhotoBrowserImageViewMargin + idx * (SDPhotoBrowserImageViewMargin * 2 + w); obj.frame = CGRectMake(x, y, w, h); @@ -370,7 +359,7 @@ { int index = (scrollView.contentOffset.x + _scrollView.bounds.size.width * 0.5) / _scrollView.bounds.size.width; - // 有过缩放的图片在拖动一定距离后清除缩放 + CGFloat margin = 150; CGFloat x = scrollView.contentOffset.x; if ((x - index * self.bounds.size.width) > margin || (x - index * self.bounds.size.width) < - margin) { @@ -403,5 +392,4 @@ } - @end diff --git a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m.backup b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m.backup new file mode 100755 index 0000000..e5002ad --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m.backup @@ -0,0 +1,407 @@ +// +// SDPhotoBrowser.m +// photobrowser +// +// Created by aier on 15-2-3. +// Copyright (c) 2015年 aier. All rights reserved. +// + +#import "SDPhotoBrowser.h" +#import "UIImageView+WebCache.h" +#import "SDBrowserImageView.h" + +#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) //判断是否iPhoneX + +#define iPhoneX_NavSafeArea ([[UIScreen mainScreen] bounds].size.height >= 812.0 ? 24 : 0) // 如果是iphoneX 顶部安全区域 24 + +// ============在这里方便配置样式相关设置=========== + +// || +// || +// || +// \\// +// \/ + +#import "SDPhotoBrowserConfig.h" + +// ============================================= + +@implementation SDPhotoBrowser +{ + UIScrollView *_scrollView; + BOOL _hasShowedFistView; + UILabel *_indexLabel; + UIButton *_saveButton; + UIActivityIndicatorView *_indicatorView; + BOOL _willDisappear; + UIWindow *currentWindows; +} + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + + if (self) { + self.backgroundColor = SDPhotoBrowserBackgroundColor; + _isMe = NO; + } + return self; +} + + +- (void)didMoveToSuperview +{ + [self setupScrollView]; + [self setupToolbars]; +} + +- (void)dealloc +{ + [currentWindows removeObserver:self forKeyPath:@"frame"]; + self.delegate = nil; +} + + +- (void)setupToolbars +{ + // 1. 序标 + UILabel *indexLabel = [[UILabel alloc] init]; + indexLabel.bounds = CGRectMake(0, 0, 80, 30); + indexLabel.textAlignment = NSTextAlignmentCenter; + indexLabel.textColor = [UIColor whiteColor]; + indexLabel.font = [UIFont boldSystemFontOfSize:20]; + indexLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; + indexLabel.layer.cornerRadius = indexLabel.bounds.size.height * 0.5; + indexLabel.clipsToBounds = YES; + if (self.imageCount >= 1) { + indexLabel.text = [NSString stringWithFormat:@"1/%ld", (long)self.imageCount]; + } + _indexLabel = indexLabel; + [self addSubview:indexLabel]; + + // 2.保存按钮 + UIButton *saveButton = [[UIButton alloc] init]; + [saveButton setTitle:YMLocalizedString(@"SDPhotoBrowser0") forState:UIControlStateNormal]; + [saveButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + saveButton.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.90f]; + saveButton.layer.cornerRadius = 5; + saveButton.clipsToBounds = YES; + [saveButton addTarget:self action:@selector(saveImage) forControlEvents:UIControlEventTouchUpInside]; + _saveButton = saveButton; + [self addSubview:saveButton]; +} + +- (void)saveImage +{ + int index = _scrollView.contentOffset.x / _scrollView.bounds.size.width; + UIImageView *currentImageView = _scrollView.subviews[index]; + + UIImageWriteToSavedPhotosAlbum(currentImageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL); + + if (_indicatorView == nil) { + _indicatorView = [[UIActivityIndicatorView alloc] init]; + _indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge; + _indicatorView.center = self.center; + [[UIApplication sharedApplication].keyWindow addSubview:_indicatorView]; + } + + [_indicatorView startAnimating]; +} + +- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo; +{ + [_indicatorView stopAnimating]; + + UILabel *label = [[UILabel alloc] init]; + label.textColor = [UIColor whiteColor]; + label.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.90f]; + label.layer.cornerRadius = 5; + label.clipsToBounds = YES; + label.bounds = CGRectMake(0, 0, 150, 30); + label.center = self.center; + label.textAlignment = NSTextAlignmentCenter; + label.font = [UIFont boldSystemFontOfSize:17]; + [[UIApplication sharedApplication].keyWindow addSubview:label]; + [[UIApplication sharedApplication].keyWindow bringSubviewToFront:label]; + if (error) { + label.text = SDPhotoBrowserSaveImageFailText; + } else { + label.text = SDPhotoBrowserSaveImageSuccessText; + } + [label performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1.0]; +} + +- (void)setupScrollView +{ + _scrollView = [[UIScrollView alloc] init]; + _scrollView.delegate = self; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.pagingEnabled = YES; + [self addSubview:_scrollView]; + + for (int i = 0; i < self.imageCount; i++) { + SDBrowserImageView *imageView = [[SDBrowserImageView alloc] init]; + imageView.tag = i; + + // 单击图片 + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoClick:)]; + + // 双击放大图片 + UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDoubleTaped:)]; + doubleTap.numberOfTapsRequired = 2; + + [singleTap requireGestureRecognizerToFail:doubleTap]; + + [imageView addGestureRecognizer:singleTap]; + [imageView addGestureRecognizer:doubleTap]; + [_scrollView addSubview:imageView]; + } + + [self setupImageOfImageViewForIndex:self.currentImageIndex]; + +} + +// 加载图片 +- (void)setupImageOfImageViewForIndex:(NSInteger)index +{ + if(index < _scrollView.subviews.count){ + SDBrowserImageView *imageView = _scrollView.subviews[index]; + self.currentImageIndex = index; + if (imageView.hasLoadedImage) return; + if ([self highQualityImageURLForIndex:index]) { + [imageView setImageWithURL:[self highQualityImageURLForIndex:index] placeholderImage:[self placeholderImageForIndex:index]]; + } else { + if([self highQualityImageForIndex: index]){ + imageView.image = [self highQualityImageForIndex: index]; + }else{ + imageView.image = [self placeholderImageForIndex:index]; + } + + } + imageView.hasLoadedImage = YES; + } + +} + +- (void)photoClick:(UITapGestureRecognizer *)recognizer +{ + _scrollView.hidden = YES; + _willDisappear = YES; + + SDBrowserImageView *currentImageView = (SDBrowserImageView *)recognizer.view; + NSInteger currentIndex = currentImageView.tag; + if (self.isHaveUserAdd) { + currentIndex = currentImageView.tag + 1; + } + + UIView *sourceView = nil; + if ([self.sourceImagesContainerView isKindOfClass:UICollectionView.class]) { + UICollectionView *view = (UICollectionView *)self.sourceImagesContainerView; + NSIndexPath *path = [NSIndexPath indexPathForItem:currentIndex inSection:0]; + sourceView = [view cellForItemAtIndexPath:path]; + }else { + if (self.currentImageIndex margin || (x - index * self.bounds.size.width) < - margin) { + if(index < _scrollView.subviews.count){ + SDBrowserImageView *imageView = _scrollView.subviews[index]; + if (imageView.isScaled) { + [UIView animateWithDuration:0.5 animations:^{ + imageView.transform = CGAffineTransformIdentity; + } completion:^(BOOL finished) { + [imageView eliminateScale]; + }]; + } + } + } + + + if (!_willDisappear) { + if (self.isMe) { + if (self.isHaveUserAdd) { + _indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index + 1, (long)self.imageCount]; + } else { + _indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index, (long)self.imageCount]; + } + }else{ + _indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index + 1, (long)self.imageCount]; + } + + } + [self setupImageOfImageViewForIndex:index]; +} + + + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h index 6c0dceb..3a7f607 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h +++ b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h @@ -1,42 +1,38 @@ -// -// SDPhotoBrowserConfig.h -// SDPhotoBrowser -// -// Created by aier on 15-2-9. -// Copyright (c) 2015年 GSD. All rights reserved. -// - - -typedef enum { - SDWaitingViewModeLoopDiagram, // 环形 - SDWaitingViewModePieDiagram // 饼型 -} SDWaitingViewMode; - -// 图片保存成功提示文字 -#define SDPhotoBrowserSaveImageSuccessText @" ^_^ 保存成功 "; - -// 图片保存失败提示文字 -#define SDPhotoBrowserSaveImageFailText @" >_< 保存失敗 "; - -// browser背景颜色 -#define SDPhotoBrowserBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.95] - -// browser中图片间的margin -#define SDPhotoBrowserImageViewMargin 10 - -// browser中显示图片动画时长 -#define SDPhotoBrowserShowImageAnimationDuration 0.4f - -// browser中显示图片动画时长 -#define SDPhotoBrowserHideImageAnimationDuration 0.4f - -// 图片下载进度指示进度显示样式(SDWaitingViewModeLoopDiagram 环形,SDWaitingViewModePieDiagram 饼型) -#define SDWaitingViewProgressMode SDWaitingViewModeLoopDiagram - -// 图片下载进度指示器背景色 -#define SDWaitingViewBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7] - -// 图片下载进度指示器内部控件间的间距 -#define SDWaitingViewItemMargin 10 - - + + +// Created by aier on 15-2-9. +// Copyright (c) 2015年 GSD. All rights reserved. + + +typedef enum { + SDWaitingViewModeLoopDiagram, + SDWaitingViewModePieDiagram +} SDWaitingViewMode; + + +#define SDPhotoBrowserSaveImageSuccessText @" ^_^ 保存成功 "; + + +#define SDPhotoBrowserSaveImageFailText @" >_< 保存失敗 "; + + +#define SDPhotoBrowserBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.95] + + +#define SDPhotoBrowserImageViewMargin 10 + + +#define SDPhotoBrowserShowImageAnimationDuration 0.4f + + +#define SDPhotoBrowserHideImageAnimationDuration 0.4f + + +#define SDWaitingViewProgressMode SDWaitingViewModeLoopDiagram + + +#define SDWaitingViewBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7] + + +#define SDWaitingViewItemMargin 10 + diff --git a/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h.backup b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h.backup new file mode 100755 index 0000000..6c0dceb --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowserConfig.h.backup @@ -0,0 +1,42 @@ +// +// SDPhotoBrowserConfig.h +// SDPhotoBrowser +// +// Created by aier on 15-2-9. +// Copyright (c) 2015年 GSD. All rights reserved. +// + + +typedef enum { + SDWaitingViewModeLoopDiagram, // 环形 + SDWaitingViewModePieDiagram // 饼型 +} SDWaitingViewMode; + +// 图片保存成功提示文字 +#define SDPhotoBrowserSaveImageSuccessText @" ^_^ 保存成功 "; + +// 图片保存失败提示文字 +#define SDPhotoBrowserSaveImageFailText @" >_< 保存失敗 "; + +// browser背景颜色 +#define SDPhotoBrowserBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.95] + +// browser中图片间的margin +#define SDPhotoBrowserImageViewMargin 10 + +// browser中显示图片动画时长 +#define SDPhotoBrowserShowImageAnimationDuration 0.4f + +// browser中显示图片动画时长 +#define SDPhotoBrowserHideImageAnimationDuration 0.4f + +// 图片下载进度指示进度显示样式(SDWaitingViewModeLoopDiagram 环形,SDWaitingViewModePieDiagram 饼型) +#define SDWaitingViewProgressMode SDWaitingViewModeLoopDiagram + +// 图片下载进度指示器背景色 +#define SDWaitingViewBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7] + +// 图片下载进度指示器内部控件间的间距 +#define SDWaitingViewItemMargin 10 + + diff --git a/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h index fa60171..9c67d47 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h +++ b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h @@ -1,17 +1,15 @@ -// -// SDWaitingView.h -// SDPhotoBrowser -// -// Created by aier on 15-2-6. -// Copyright (c) 2015年 GSD. All rights reserved. -// - -#import -#import "SDPhotoBrowserConfig.h" - -@interface SDWaitingView : UIView - -@property (nonatomic, assign) CGFloat progress; -@property (nonatomic, assign) int mode; - -@end + + +// Created by aier on 15-2-6. +// Copyright (c) 2015年 GSD. All rights reserved. + + +#import +#import "SDPhotoBrowserConfig.h" + +@interface SDWaitingView : UIView + +@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, assign) int mode; + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h.backup b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h.backup new file mode 100755 index 0000000..fa60171 --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.h.backup @@ -0,0 +1,17 @@ +// +// SDWaitingView.h +// SDPhotoBrowser +// +// Created by aier on 15-2-6. +// Copyright (c) 2015年 GSD. All rights reserved. +// + +#import +#import "SDPhotoBrowserConfig.h" + +@interface SDWaitingView : UIView + +@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, assign) int mode; + +@end diff --git a/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m index ca8ae36..177a742 100755 --- a/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m +++ b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m @@ -1,20 +1,11 @@ -// -// SDWaitingView.m -// SDPhotoBrowser -// + + // Created by aier on 15-2-6. // Copyright (c) 2015年 GSD. All rights reserved. -// + #import "SDWaitingView.h" -//// 图片下载进度指示器背景色 -//#define SDWaitingViewBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7] -// -//// 图片下载进度指示器内部控件间的间距 -// -//#define SDWaitingViewItemMargin 10 - @implementation SDWaitingView @@ -34,8 +25,8 @@ - (void)setProgress:(CGFloat)progress { _progress = progress; -// NSLog(@"%@",[NSThread currentThread]); - //将重绘操作放在主线程,解决自动布局控制台报错的问题 + + dispatch_async(dispatch_get_main_queue(), ^{ [self setNeedsDisplay]; @@ -69,7 +60,7 @@ [SDWaitingViewBackgroundColor set]; CGContextMoveToPoint(ctx, xCenter, yCenter); CGContextAddLineToPoint(ctx, xCenter, 0); - CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.001; // 初始值 + CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.001; CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 1); CGContextClosePath(ctx); @@ -81,7 +72,7 @@ { CGContextSetLineWidth(ctx, 15); CGContextSetLineCap(ctx, kCGLineCapRound); - CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.05; // 初始值0.05 + CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.05; CGFloat radius = MIN(rect.size.width, rect.size.height) * 0.5 - SDWaitingViewItemMargin; CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 0); CGContextStrokePath(ctx); diff --git a/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m.backup b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m.backup new file mode 100755 index 0000000..ca8ae36 --- /dev/null +++ b/YuMi/Tools/SDPhotoBrowser/SDWaitingView.m.backup @@ -0,0 +1,93 @@ +// +// SDWaitingView.m +// SDPhotoBrowser +// +// Created by aier on 15-2-6. +// Copyright (c) 2015年 GSD. All rights reserved. +// + +#import "SDWaitingView.h" + +//// 图片下载进度指示器背景色 +//#define SDWaitingViewBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7] +// +//// 图片下载进度指示器内部控件间的间距 +// +//#define SDWaitingViewItemMargin 10 + + +@implementation SDWaitingView + + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = SDWaitingViewBackgroundColor; + self.layer.cornerRadius = 5; + self.clipsToBounds = YES; + self.mode = SDWaitingViewModeLoopDiagram; + } + return self; +} + +- (void)setProgress:(CGFloat)progress +{ + _progress = progress; +// NSLog(@"%@",[NSThread currentThread]); + //将重绘操作放在主线程,解决自动布局控制台报错的问题 + dispatch_async(dispatch_get_main_queue(), ^{ + + [self setNeedsDisplay]; + if (progress >= 1) { + [self removeFromSuperview]; + } + }); +} + +- (void)drawRect:(CGRect)rect +{ + CGContextRef ctx = UIGraphicsGetCurrentContext(); + + CGFloat xCenter = rect.size.width * 0.5; + CGFloat yCenter = rect.size.height * 0.5; + [[UIColor whiteColor] set]; + + switch (self.mode) { + case SDWaitingViewModePieDiagram: + { + CGFloat radius = MIN(rect.size.width * 0.5, rect.size.height * 0.5) - SDWaitingViewItemMargin; + + + CGFloat w = radius * 2 + SDWaitingViewItemMargin; + CGFloat h = w; + CGFloat x = (rect.size.width - w) * 0.5; + CGFloat y = (rect.size.height - h) * 0.5; + CGContextAddEllipseInRect(ctx, CGRectMake(x, y, w, h)); + CGContextFillPath(ctx); + + [SDWaitingViewBackgroundColor set]; + CGContextMoveToPoint(ctx, xCenter, yCenter); + CGContextAddLineToPoint(ctx, xCenter, 0); + CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.001; // 初始值 + CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 1); + CGContextClosePath(ctx); + + CGContextFillPath(ctx); + } + break; + + default: + { + CGContextSetLineWidth(ctx, 15); + CGContextSetLineCap(ctx, kCGLineCapRound); + CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.05; // 初始值0.05 + CGFloat radius = MIN(rect.size.width, rect.size.height) * 0.5 - SDWaitingViewItemMargin; + CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 0); + CGContextStrokePath(ctx); + } + break; + } +} + +@end diff --git a/YuMi/Tools/Safe/NSArray+Safe.h b/YuMi/Tools/Safe/NSArray+Safe.h index 4e4b098..48c9ed6 100644 --- a/YuMi/Tools/Safe/NSArray+Safe.h +++ b/YuMi/Tools/Safe/NSArray+Safe.h @@ -1,9 +1,7 @@ -// -// NSArray+Safe.h -// YUMI -// + + // Created by YUMI on 2022/11/11. -// + #import diff --git a/YuMi/Tools/Safe/NSArray+Safe.h.backup b/YuMi/Tools/Safe/NSArray+Safe.h.backup new file mode 100644 index 0000000..4e4b098 --- /dev/null +++ b/YuMi/Tools/Safe/NSArray+Safe.h.backup @@ -0,0 +1,16 @@ +// +// NSArray+Safe.h +// YUMI +// +// Created by YUMI on 2022/11/11. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSArray (Safe) +-(id)xpSafeObjectAtIndex:(NSUInteger)index; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Safe/NSArray+Safe.m b/YuMi/Tools/Safe/NSArray+Safe.m index 13729c7..199bfac 100644 --- a/YuMi/Tools/Safe/NSArray+Safe.m +++ b/YuMi/Tools/Safe/NSArray+Safe.m @@ -1,9 +1,7 @@ -// -// NSArray+Safe.m -// YUMI -// + + // Created by YUMI on 2022/11/11. -// + #import "NSArray+Safe.h" diff --git a/YuMi/Tools/Safe/NSArray+Safe.m.backup b/YuMi/Tools/Safe/NSArray+Safe.m.backup new file mode 100644 index 0000000..13729c7 --- /dev/null +++ b/YuMi/Tools/Safe/NSArray+Safe.m.backup @@ -0,0 +1,23 @@ +// +// NSArray+Safe.m +// YUMI +// +// Created by YUMI on 2022/11/11. +// + +#import "NSArray+Safe.h" + +@implementation NSArray (Safe) + +-(id)xpSafeObjectAtIndex:(NSUInteger)index{ + if ([self isKindOfClass:[NSArray class]]){ + if (self.count){ + if (self.count>index){ + return self[index]; + } + } + } + return nil; +} + +@end diff --git a/YuMi/Tools/Safe/NSMutableArray+Safe.h b/YuMi/Tools/Safe/NSMutableArray+Safe.h index 1894935..a8bdb0a 100644 --- a/YuMi/Tools/Safe/NSMutableArray+Safe.h +++ b/YuMi/Tools/Safe/NSMutableArray+Safe.h @@ -1,9 +1,7 @@ -// -// NSMutableArray+Safe.h -// YUMI -// + + // Created by YUMI on 2023/11/15. -// + #import @@ -11,52 +9,22 @@ NS_ASSUME_NONNULL_BEGIN @interface NSMutableArray (Safe) -/** - 安全地从数组中移除指定索引的对象 - 如果索引超出范围,则不执行任何操作 - - @param index 要移除的对象的索引 - */ + - (void)xpSafeRemoveObjectAtIndex:(NSUInteger)index; -/** - 安全地从数组中移除指定的对象 - 如果对象不存在,则不执行任何操作 - - @param anObject 要移除的对象 - */ + - (void)xpSafeRemoveObject:(id)anObject; -/** - 安全地从数组中移除指定索引集合中的对象 - 如果索引集合中的任何索引超出范围,则跳过该索引 - - @param indexes 要移除的对象的索引集合 - */ + - (void)xpSafeRemoveObjectsAtIndexes:(NSIndexSet *)indexes; -/** - 安全地在指定索引处插入对象 - 如果索引超出范围,则不执行任何操作或在末尾添加(取决于索引) - - @param anObject 要插入的对象 - @param index 要插入的位置 - */ + - (void)xpSafeInsertObject:(id)anObject atIndex:(NSUInteger)index; -/** - 安全地替换指定索引处的对象 - 如果索引超出范围,则不执行任何操作 - - @param index 要替换的对象的索引 - @param anObject 替换的对象 - */ + - (void)xpSafeReplaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; -/** - 安全地移除数组中的所有对象 - 如果数组为空,则不执行任何操作 - */ + - (void)xpSafeRemoveAllObjects; @end diff --git a/YuMi/Tools/Safe/NSMutableArray+Safe.h.backup b/YuMi/Tools/Safe/NSMutableArray+Safe.h.backup new file mode 100644 index 0000000..1894935 --- /dev/null +++ b/YuMi/Tools/Safe/NSMutableArray+Safe.h.backup @@ -0,0 +1,64 @@ +// +// NSMutableArray+Safe.h +// YUMI +// +// Created by YUMI on 2023/11/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSMutableArray (Safe) + +/** + 安全地从数组中移除指定索引的对象 + 如果索引超出范围,则不执行任何操作 + + @param index 要移除的对象的索引 + */ +- (void)xpSafeRemoveObjectAtIndex:(NSUInteger)index; + +/** + 安全地从数组中移除指定的对象 + 如果对象不存在,则不执行任何操作 + + @param anObject 要移除的对象 + */ +- (void)xpSafeRemoveObject:(id)anObject; + +/** + 安全地从数组中移除指定索引集合中的对象 + 如果索引集合中的任何索引超出范围,则跳过该索引 + + @param indexes 要移除的对象的索引集合 + */ +- (void)xpSafeRemoveObjectsAtIndexes:(NSIndexSet *)indexes; + +/** + 安全地在指定索引处插入对象 + 如果索引超出范围,则不执行任何操作或在末尾添加(取决于索引) + + @param anObject 要插入的对象 + @param index 要插入的位置 + */ +- (void)xpSafeInsertObject:(id)anObject atIndex:(NSUInteger)index; + +/** + 安全地替换指定索引处的对象 + 如果索引超出范围,则不执行任何操作 + + @param index 要替换的对象的索引 + @param anObject 替换的对象 + */ +- (void)xpSafeReplaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; + +/** + 安全地移除数组中的所有对象 + 如果数组为空,则不执行任何操作 + */ +- (void)xpSafeRemoveAllObjects; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/YuMi/Tools/Safe/NSMutableArray+Safe.m b/YuMi/Tools/Safe/NSMutableArray+Safe.m index e024538..d3ecb7b 100644 --- a/YuMi/Tools/Safe/NSMutableArray+Safe.m +++ b/YuMi/Tools/Safe/NSMutableArray+Safe.m @@ -1,9 +1,7 @@ -// -// NSMutableArray+Safe.m -// YUMI -// + + // Created by YUMI on 2023/11/15. -// + #import "NSMutableArray+Safe.h" @@ -27,7 +25,7 @@ - (void)xpSafeRemoveObjectsAtIndexes:(NSIndexSet *)indexes { if ([self isKindOfClass:[NSMutableArray class]] && indexes) { - // 创建一个有效索引的集合 + NSMutableIndexSet *validIndexes = [NSMutableIndexSet indexSet]; [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { if (idx < self.count) { @@ -46,7 +44,7 @@ if (index <= self.count) { [self insertObject:anObject atIndex:index]; } else if (index > self.count) { - // 如果索引超出范围,则添加到末尾 + [self addObject:anObject]; } } diff --git a/YuMi/Tools/Safe/NSMutableArray+Safe.m.backup b/YuMi/Tools/Safe/NSMutableArray+Safe.m.backup new file mode 100644 index 0000000..e024538 --- /dev/null +++ b/YuMi/Tools/Safe/NSMutableArray+Safe.m.backup @@ -0,0 +1,69 @@ +// +// NSMutableArray+Safe.m +// YUMI +// +// Created by YUMI on 2023/11/15. +// + +#import "NSMutableArray+Safe.h" + +@implementation NSMutableArray (Safe) + +- (void)xpSafeRemoveObjectAtIndex:(NSUInteger)index { + if ([self isKindOfClass:[NSMutableArray class]]) { + if (self.count > 0 && index < self.count) { + [self removeObjectAtIndex:index]; + } + } +} + +- (void)xpSafeRemoveObject:(id)anObject { + if ([self isKindOfClass:[NSMutableArray class]]) { + if (anObject && [self containsObject:anObject]) { + [self removeObject:anObject]; + } + } +} + +- (void)xpSafeRemoveObjectsAtIndexes:(NSIndexSet *)indexes { + if ([self isKindOfClass:[NSMutableArray class]] && indexes) { + // 创建一个有效索引的集合 + NSMutableIndexSet *validIndexes = [NSMutableIndexSet indexSet]; + [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + if (idx < self.count) { + [validIndexes addIndex:idx]; + } + }]; + + if (validIndexes.count > 0) { + [self removeObjectsAtIndexes:validIndexes]; + } + } +} + +- (void)xpSafeInsertObject:(id)anObject atIndex:(NSUInteger)index { + if ([self isKindOfClass:[NSMutableArray class]] && anObject) { + if (index <= self.count) { + [self insertObject:anObject atIndex:index]; + } else if (index > self.count) { + // 如果索引超出范围,则添加到末尾 + [self addObject:anObject]; + } + } +} + +- (void)xpSafeReplaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { + if ([self isKindOfClass:[NSMutableArray class]] && anObject) { + if (index < self.count) { + [self replaceObjectAtIndex:index withObject:anObject]; + } + } +} + +- (void)xpSafeRemoveAllObjects { + if ([self isKindOfClass:[NSMutableArray class]] && self.count > 0) { + [self removeAllObjects]; + } +} + +@end \ No newline at end of file diff --git a/YuMi/Tools/Safe/NSMutableDictionary+Saft.h b/YuMi/Tools/Safe/NSMutableDictionary+Saft.h index 86118dd..8628d0a 100644 --- a/YuMi/Tools/Safe/NSMutableDictionary+Saft.h +++ b/YuMi/Tools/Safe/NSMutableDictionary+Saft.h @@ -1,9 +1,7 @@ -// -// NSMutableDictionary+Saft.h -// YUMI -// + + // Created by YUMI on 2022/11/11. -// + #import diff --git a/YuMi/Tools/Safe/NSMutableDictionary+Saft.h.backup b/YuMi/Tools/Safe/NSMutableDictionary+Saft.h.backup new file mode 100644 index 0000000..86118dd --- /dev/null +++ b/YuMi/Tools/Safe/NSMutableDictionary+Saft.h.backup @@ -0,0 +1,16 @@ +// +// NSMutableDictionary+Saft.h +// YUMI +// +// Created by YUMI on 2022/11/11. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSMutableDictionary (Saft) +- (void)safeSetObject:(id)anObject forKey:(id )aKey; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Safe/NSMutableDictionary+Saft.m b/YuMi/Tools/Safe/NSMutableDictionary+Saft.m index 4c9b450..9932fb7 100644 --- a/YuMi/Tools/Safe/NSMutableDictionary+Saft.m +++ b/YuMi/Tools/Safe/NSMutableDictionary+Saft.m @@ -1,9 +1,7 @@ -// -// NSMutableDictionary+Saft.m -// YUMI -// + + // Created by YUMI on 2022/11/11. -// + #import "NSMutableDictionary+Saft.h" diff --git a/YuMi/Tools/Safe/NSMutableDictionary+Saft.m.backup b/YuMi/Tools/Safe/NSMutableDictionary+Saft.m.backup new file mode 100644 index 0000000..4c9b450 --- /dev/null +++ b/YuMi/Tools/Safe/NSMutableDictionary+Saft.m.backup @@ -0,0 +1,17 @@ +// +// NSMutableDictionary+Saft.m +// YUMI +// +// Created by YUMI on 2022/11/11. +// + +#import "NSMutableDictionary+Saft.h" + +@implementation NSMutableDictionary (Saft) + +- (void)safeSetObject:(id)anObject forKey:(id )aKey{ + if (anObject == nil || aKey == nil)return; + [self setObject:anObject forKey:aKey]; +} + +@end diff --git a/YuMi/Tools/Security/AESUtils.h b/YuMi/Tools/Security/AESUtils.h index 1bf73dc..86b1cd4 100644 --- a/YuMi/Tools/Security/AESUtils.h +++ b/YuMi/Tools/Security/AESUtils.h @@ -1,9 +1,7 @@ -// -// AESUtils.h -// YUMI -// + + // Created by YUMI on 2023/2/13. -// + #import diff --git a/YuMi/Tools/Security/AESUtils.h.backup b/YuMi/Tools/Security/AESUtils.h.backup new file mode 100644 index 0000000..1bf73dc --- /dev/null +++ b/YuMi/Tools/Security/AESUtils.h.backup @@ -0,0 +1,19 @@ +// +// AESUtils.h +// YUMI +// +// Created by YUMI on 2023/2/13. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AESUtils : NSObject +//MARK: AES加解密 ++ (NSString *)aesEncrypt:(NSString *)sourceStr; + ++ (NSString *)aesDecrypt:(NSString *)secretStr; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Security/AESUtils.m b/YuMi/Tools/Security/AESUtils.m index af7ba8b..313f608 100644 --- a/YuMi/Tools/Security/AESUtils.m +++ b/YuMi/Tools/Security/AESUtils.m @@ -1,9 +1,7 @@ -// -// AESUtils.m -// YUMI -// + + // Created by YUMI on 2023/2/13. -// + #import "AESUtils.h" #import @@ -17,12 +15,12 @@ return nil; } - //秘钥 + char keyPtr[kCCKeySizeAES256 + 1]; bzero(keyPtr, sizeof(keyPtr)); [GL_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; - //向量 + char ivPtr[kCCBlockSizeAES128 + 1]; bzero(ivPtr, sizeof(ivPtr)); [GL_AES_IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; @@ -32,18 +30,14 @@ size_t buffersize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(buffersize); size_t numBytesEncrypted = 0; - /* - //CBC模式 - kCCOptionPKCS7Padding - //ECB模式 - kCCOptionPKCS7Padding | kCCOptionECBMode - */ + + CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCBlockSizeAES128, - ivPtr,//ECB模式下可以为NULL + ivPtr, [sourceData bytes], dataLength, buffer, @@ -52,10 +46,8 @@ if (cryptStatus == kCCSuccess) { NSData *encryptData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; - //对加密后的二进制数据进行base64转码 - //return [encryptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; - - //转换为16进制字符串 + + NSMutableString *output = [NSMutableString stringWithCapacity:encryptData.length * 2]; if (encryptData && encryptData.length > 0) { Byte *datas = (Byte*)[encryptData bytes]; @@ -75,17 +67,15 @@ if (!secretStr) { return nil; } -// //先对加密的字符串进行base64解码 - NSData *decodeData = [[NSData alloc] initWithBase64EncodedString:secretStr options:NSDataBase64DecodingIgnoreUnknownCharacters]; - //先对加密的字符串进行16进制解码 -// NSData *decodeData = [self convertHexStrToData:secretStr]; - //秘钥 + NSData *decodeData = [[NSData alloc] initWithBase64EncodedString:secretStr options:NSDataBase64DecodingIgnoreUnknownCharacters]; + + char keyPtr[kCCKeySizeAES256 + 1]; bzero(keyPtr, sizeof(keyPtr)); [GL_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; - //向量 + char ivPtr[kCCBlockSizeAES128 + 1]; bzero(ivPtr, sizeof(ivPtr)); [GL_AES_IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; @@ -94,18 +84,14 @@ size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; - /* - //CBC模式 - kCCOptionPKCS7Padding - //ECB模式 - kCCOptionPKCS7Padding | kCCOptionECBMode - */ + + CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCBlockSizeAES128, - ivPtr,//ECB模式下可以为NULL + ivPtr, [decodeData bytes], dataLength, buffer, @@ -121,7 +107,7 @@ } } -// 16进制转NSData + + (NSData *)convertHexStrToData:(NSString *)str { if (!str || [str length] == 0) { return nil; diff --git a/YuMi/Tools/Security/AESUtils.m.backup b/YuMi/Tools/Security/AESUtils.m.backup new file mode 100644 index 0000000..af7ba8b --- /dev/null +++ b/YuMi/Tools/Security/AESUtils.m.backup @@ -0,0 +1,151 @@ +// +// AESUtils.m +// YUMI +// +// Created by YUMI on 2023/2/13. +// + +#import "AESUtils.h" +#import + +#define GL_AES_KEY @"aef01238765abcdeaaageggbeggsded" +#define GL_AES_IV @"edgcdgrtc" +@implementation AESUtils +//MARK: AES加解密相关 start ++ (NSString *)aesEncrypt:(NSString *)sourceStr { + if (!sourceStr) { + return nil; + } + + //秘钥 + char keyPtr[kCCKeySizeAES256 + 1]; + bzero(keyPtr, sizeof(keyPtr)); + [GL_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; + + //向量 + char ivPtr[kCCBlockSizeAES128 + 1]; + bzero(ivPtr, sizeof(ivPtr)); + [GL_AES_IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; + + NSData *sourceData = [sourceStr dataUsingEncoding:NSUTF8StringEncoding]; + NSUInteger dataLength = [sourceData length]; + size_t buffersize = dataLength + kCCBlockSizeAES128; + void *buffer = malloc(buffersize); + size_t numBytesEncrypted = 0; + /* + //CBC模式 + kCCOptionPKCS7Padding + //ECB模式 + kCCOptionPKCS7Padding | kCCOptionECBMode + */ + CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, + kCCAlgorithmAES128, + kCCOptionPKCS7Padding, + keyPtr, + kCCBlockSizeAES128, + ivPtr,//ECB模式下可以为NULL + [sourceData bytes], + dataLength, + buffer, + buffersize, + &numBytesEncrypted); + + if (cryptStatus == kCCSuccess) { + NSData *encryptData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; + //对加密后的二进制数据进行base64转码 + //return [encryptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; + + //转换为16进制字符串 + NSMutableString *output = [NSMutableString stringWithCapacity:encryptData.length * 2]; + if (encryptData && encryptData.length > 0) { + Byte *datas = (Byte*)[encryptData bytes]; + for(int i = 0; i < encryptData.length; i++){ + [output appendFormat:@"%02x", datas[i]]; + } + } + return output; + + } else { + free(buffer); + return nil; + } +} + ++ (NSString *)aesDecrypt:(NSString *)secretStr { + if (!secretStr) { + return nil; + } +// //先对加密的字符串进行base64解码 + NSData *decodeData = [[NSData alloc] initWithBase64EncodedString:secretStr options:NSDataBase64DecodingIgnoreUnknownCharacters]; + //先对加密的字符串进行16进制解码 +// NSData *decodeData = [self convertHexStrToData:secretStr]; + + //秘钥 + char keyPtr[kCCKeySizeAES256 + 1]; + bzero(keyPtr, sizeof(keyPtr)); + [GL_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; + + //向量 + char ivPtr[kCCBlockSizeAES128 + 1]; + bzero(ivPtr, sizeof(ivPtr)); + [GL_AES_IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; + + NSUInteger dataLength = [decodeData length]; + size_t bufferSize = dataLength + kCCBlockSizeAES128; + void *buffer = malloc(bufferSize); + size_t numBytesDecrypted = 0; + /* + //CBC模式 + kCCOptionPKCS7Padding + //ECB模式 + kCCOptionPKCS7Padding | kCCOptionECBMode + */ + CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, + kCCAlgorithmAES128, + kCCOptionPKCS7Padding, + keyPtr, + kCCBlockSizeAES128, + ivPtr,//ECB模式下可以为NULL + [decodeData bytes], + dataLength, + buffer, + bufferSize, + &numBytesDecrypted); + if (cryptStatus == kCCSuccess) { + NSData *data = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; + NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + return result; + } else { + free(buffer); + return nil; + } +} + +// 16进制转NSData ++ (NSData *)convertHexStrToData:(NSString *)str { + if (!str || [str length] == 0) { + return nil; + } + + NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:20]; + NSRange range; + if ([str length] % 2 == 0) { + range = NSMakeRange(0, 2); + } else { + range = NSMakeRange(0, 1); + } + for (NSInteger i = range.location; i < [str length]; i += 2) { + unsigned int anInt; + NSString *hexCharStr = [str substringWithRange:range]; + NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr]; + + [scanner scanHexInt:&anInt]; + NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1]; + [hexData appendData:entity]; + + range.location += range.length; + range.length = 2; + } + return hexData; +} +@end diff --git a/YuMi/Tools/Security/Base64.h b/YuMi/Tools/Security/Base64.h index f0c90df..8ca3a74 100644 --- a/YuMi/Tools/Security/Base64.h +++ b/YuMi/Tools/Security/Base64.h @@ -1,16 +1,14 @@ -// -// Base64.h -// YMhatFramework -// -// Created by chenran on 2017/5/4. -// Copyright © 2017年 chenran. All rights reserved. -// - -#import - -@interface Base64 : NSObject - -+(NSString *)encode:(NSData *)data; -+(NSData *)decode:(NSString *)dataString; - -@end + + +// Created by chenran on 2017/5/4. +// Copyright © 2017年 chenran. All rights reserved. + + +#import + +@interface Base64 : NSObject + ++(NSString *)encode:(NSData *)data; ++(NSData *)decode:(NSString *)dataString; + +@end diff --git a/YuMi/Tools/Security/Base64.h.backup b/YuMi/Tools/Security/Base64.h.backup new file mode 100644 index 0000000..f0c90df --- /dev/null +++ b/YuMi/Tools/Security/Base64.h.backup @@ -0,0 +1,16 @@ +// +// Base64.h +// YMhatFramework +// +// Created by chenran on 2017/5/4. +// Copyright © 2017年 chenran. All rights reserved. +// + +#import + +@interface Base64 : NSObject + ++(NSString *)encode:(NSData *)data; ++(NSData *)decode:(NSString *)dataString; + +@end diff --git a/YuMi/Tools/Security/Base64.m b/YuMi/Tools/Security/Base64.m index 1f74c46..aaf18dd 100644 --- a/YuMi/Tools/Security/Base64.m +++ b/YuMi/Tools/Security/Base64.m @@ -1,10 +1,8 @@ -// -// Base64.m -// YMhatFramework -// + + // Created by chenran on 2017/5/4. // Copyright © 2017年 chenran. All rights reserved. -// + #import "Base64.h" diff --git a/YuMi/Tools/Security/Base64.m.backup b/YuMi/Tools/Security/Base64.m.backup new file mode 100644 index 0000000..1f74c46 --- /dev/null +++ b/YuMi/Tools/Security/Base64.m.backup @@ -0,0 +1,133 @@ +// +// Base64.m +// YMhatFramework +// +// Created by chenran on 2017/5/4. +// Copyright © 2017年 chenran. All rights reserved. +// + +#import "Base64.h" + +@interface Base64() ++(int)char2Int:(char)c; +@end + +@implementation Base64 + +static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + ++(NSString *)encode:(NSData *)data +{ + if (data.length == 0) + return nil; + + char *characters = malloc(data.length * 3 / 2); + + if (characters == NULL) + return nil; + + int end = data.length - 3; + int index = 0; + int charCount = 0; + int n = 0; + + while (index <= end) { + int d = (((int)(((char *)[data bytes])[index]) & 0x0ff) << 16) + | (((int)(((char *)[data bytes])[index + 1]) & 0x0ff) << 8) + | ((int)(((char *)[data bytes])[index + 2]) & 0x0ff); + + characters[charCount++] = encodingTable[(d >> 18) & 63]; + characters[charCount++] = encodingTable[(d >> 12) & 63]; + characters[charCount++] = encodingTable[(d >> 6) & 63]; + characters[charCount++] = encodingTable[d & 63]; + + index += 3; + + if(n++ >= 14) + { + n = 0; + characters[charCount++] = ' '; + } + } + + if(index == data.length - 2) + { + int d = (((int)(((char *)[data bytes])[index]) & 0x0ff) << 16) + | (((int)(((char *)[data bytes])[index + 1]) & 255) << 8); + characters[charCount++] = encodingTable[(d >> 18) & 63]; + characters[charCount++] = encodingTable[(d >> 12) & 63]; + characters[charCount++] = encodingTable[(d >> 6) & 63]; + characters[charCount++] = '='; + } + else if(index == data.length - 1) + { + int d = ((int)(((char *)[data bytes])[index]) & 0x0ff) << 16; + characters[charCount++] = encodingTable[(d >> 18) & 63]; + characters[charCount++] = encodingTable[(d >> 12) & 63]; + characters[charCount++] = '='; + characters[charCount++] = '='; + } + NSString * rtnStr = [[NSString alloc] initWithBytesNoCopy:characters length:charCount encoding:NSUTF8StringEncoding freeWhenDone:YES]; + return rtnStr; + +} + ++(NSData *)decode:(NSString *)data +{ + if(data == nil || data.length <= 0) { + return nil; + } + NSMutableData *rtnData = [[NSMutableData alloc]init]; + int slen = data.length; + int index = 0; + while (true) { + while (index < slen && [data characterAtIndex:index] <= ' ') { + index++; + } + if (index >= slen || index + 3 >= slen) { + break; + } + + int byte = ([self char2Int:[data characterAtIndex:index]] << 18) + ([self char2Int:[data characterAtIndex:index + 1]] << 12) + ([self char2Int:[data characterAtIndex:index + 2]] << 6) + [self char2Int:[data characterAtIndex:index + 3]]; + Byte temp1 = (byte >> 16) & 255; + [rtnData appendBytes:&temp1 length:1]; + if([data characterAtIndex:index + 2] == '=') { + break; + } + Byte temp2 = (byte >> 8) & 255; + [rtnData appendBytes:&temp2 length:1]; + if([data characterAtIndex:index + 3] == '=') { + break; + } + Byte temp3 = byte & 255; + [rtnData appendBytes:&temp3 length:1]; + index += 4; + + } + return rtnData; +} + ++(int)char2Int:(char)c +{ + if (c >= 'A' && c <= 'Z') { + return c - 65; + } else if (c >= 'a' && c <= 'z') { + return c - 97 + 26; + } else if (c >= '0' && c <= '9') { + return c - 48 + 26 + 26; + } else { + switch(c) { + case '+': + return 62; + case '/': + return 63; + case '=': + return 0; + default: + return -1; + } + } +} + + +@end diff --git a/YuMi/Tools/Security/DESEncrypt.h b/YuMi/Tools/Security/DESEncrypt.h index 9056a7e..0f04fc2 100644 --- a/YuMi/Tools/Security/DESEncrypt.h +++ b/YuMi/Tools/Security/DESEncrypt.h @@ -1,16 +1,14 @@ -// -// DESEncrypt.h -// YMhatFramework -// -// Created by chenran on 2017/5/4. -// Copyright © 2017年 chenran. All rights reserved. -// - -#import - -@interface DESEncrypt : NSObject -//加密方法 -+(NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key; -//解密方法 -+(NSString *) decryptUseDES:(NSString *)cipherText key:(NSString *)key; -@end + + +// Created by chenran on 2017/5/4. +// Copyright © 2017年 chenran. All rights reserved. + + +#import + +@interface DESEncrypt : NSObject + ++(NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key; + ++(NSString *) decryptUseDES:(NSString *)cipherText key:(NSString *)key; +@end diff --git a/YuMi/Tools/Security/DESEncrypt.h.backup b/YuMi/Tools/Security/DESEncrypt.h.backup new file mode 100644 index 0000000..9056a7e --- /dev/null +++ b/YuMi/Tools/Security/DESEncrypt.h.backup @@ -0,0 +1,16 @@ +// +// DESEncrypt.h +// YMhatFramework +// +// Created by chenran on 2017/5/4. +// Copyright © 2017年 chenran. All rights reserved. +// + +#import + +@interface DESEncrypt : NSObject +//加密方法 ++(NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key; +//解密方法 ++(NSString *) decryptUseDES:(NSString *)cipherText key:(NSString *)key; +@end diff --git a/YuMi/Tools/Security/DESEncrypt.m b/YuMi/Tools/Security/DESEncrypt.m index 18a3a3b..d454a42 100644 --- a/YuMi/Tools/Security/DESEncrypt.m +++ b/YuMi/Tools/Security/DESEncrypt.m @@ -1,10 +1,8 @@ -// -// DESEncrypt.m -// YMhatFramework -// + + // Created by chenran on 2017/5/4. // Copyright © 2017年 chenran. All rights reserved. -// + #import "DESEncrypt.h" #import @@ -45,7 +43,7 @@ const Byte iv[] = {1,2,3,4,5,6,7,8}; unsigned char buffer[200000]; memset(buffer, 0, sizeof(char)); size_t numBytesDecrypted = 0; - // kCCOptionPKCS7Padding|kCCOptionECBMode 最主要在这步 + CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding|kCCOptionECBMode, [key UTF8String], kCCKeySizeDES, diff --git a/YuMi/Tools/Security/DESEncrypt.m.backup b/YuMi/Tools/Security/DESEncrypt.m.backup new file mode 100644 index 0000000..18a3a3b --- /dev/null +++ b/YuMi/Tools/Security/DESEncrypt.m.backup @@ -0,0 +1,63 @@ +// +// DESEncrypt.m +// YMhatFramework +// +// Created by chenran on 2017/5/4. +// Copyright © 2017年 chenran. All rights reserved. +// + +#import "DESEncrypt.h" +#import +#import "Base64.h" + +@implementation DESEncrypt : NSObject + +const Byte iv[] = {1,2,3,4,5,6,7,8}; + +#pragma mark- 加密算法 ++(NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key +{ + NSString *ciphertext = nil; + NSData *textData = [plainText dataUsingEncoding:NSUTF8StringEncoding]; + NSUInteger dataLength = [textData length]; + unsigned char buffer[200000]; + memset(buffer, 0, sizeof(char)); + size_t numBytesEncrypted = 0; + CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES, + kCCOptionPKCS7Padding|kCCOptionECBMode, + [key UTF8String], kCCKeySizeDES, + iv, + [textData bytes], dataLength, + buffer, 200000, + &numBytesEncrypted); + if (cryptStatus == kCCSuccess) { + NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted]; + ciphertext = [Base64 encode:data]; + } + return ciphertext; +} + +#pragma mark- 解密算法 ++(NSString *)decryptUseDES:(NSString *)cipherText key:(NSString *)key +{ + NSString *plaintext = nil; + NSData *cipherdata = [Base64 decode:cipherText]; + unsigned char buffer[200000]; + memset(buffer, 0, sizeof(char)); + size_t numBytesDecrypted = 0; + // kCCOptionPKCS7Padding|kCCOptionECBMode 最主要在这步 + CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, + kCCOptionPKCS7Padding|kCCOptionECBMode, + [key UTF8String], kCCKeySizeDES, + iv, + [cipherdata bytes], [cipherdata length], + buffer, 200000, + &numBytesDecrypted); + if(cryptStatus == kCCSuccess) { + NSData *plaindata = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted]; + plaintext = [[NSString alloc]initWithData:plaindata encoding:NSUTF8StringEncoding]; + } + return plaintext; +} +@end + diff --git a/YuMi/Tools/Timer/XPWeakTimer.h b/YuMi/Tools/Timer/XPWeakTimer.h.backup similarity index 100% rename from YuMi/Tools/Timer/XPWeakTimer.h rename to YuMi/Tools/Timer/XPWeakTimer.h.backup diff --git a/YuMi/Tools/Timer/XPWeakTimer.m b/YuMi/Tools/Timer/XPWeakTimer.m.backup similarity index 100% rename from YuMi/Tools/Timer/XPWeakTimer.m rename to YuMi/Tools/Timer/XPWeakTimer.m.backup diff --git a/YuMi/Tools/Timestamp/Timestamp.h b/YuMi/Tools/Timestamp/Timestamp.h index e44400e..aec034d 100644 --- a/YuMi/Tools/Timestamp/Timestamp.h +++ b/YuMi/Tools/Timestamp/Timestamp.h @@ -1,18 +1,15 @@ -// -// Timestamp.h -// YUMI -// + + // Created by YUMI on 2022/1/12. -// + #import NS_ASSUME_NONNULL_BEGIN @interface Timestamp : NSObject -/// 获取当前的时间戳 -/// @param succes 成功 -/// @param failure 失败 + + + (void)getInternetDateWithSuccess:(void(^)(NSTimeInterval timeInterval))succes failure:(void(^)(NSError *error))failure; @end diff --git a/YuMi/Tools/Timestamp/Timestamp.h.backup b/YuMi/Tools/Timestamp/Timestamp.h.backup new file mode 100644 index 0000000..e44400e --- /dev/null +++ b/YuMi/Tools/Timestamp/Timestamp.h.backup @@ -0,0 +1,20 @@ +// +// Timestamp.h +// YUMI +// +// Created by YUMI on 2022/1/12. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface Timestamp : NSObject +/// 获取当前的时间戳 +/// @param succes 成功 +/// @param failure 失败 ++ (void)getInternetDateWithSuccess:(void(^)(NSTimeInterval timeInterval))succes + failure:(void(^)(NSError *error))failure; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/Timestamp/Timestamp.m b/YuMi/Tools/Timestamp/Timestamp.m index 860fd4b..49d5419 100644 --- a/YuMi/Tools/Timestamp/Timestamp.m +++ b/YuMi/Tools/Timestamp/Timestamp.m @@ -1,35 +1,32 @@ -// -// Timestamp.m -// YUMI -// + + // Created by YUMI on 2022/1/12. -// + #import "Timestamp.h" #import "YUMIMacroUitls.h" @implementation Timestamp -/// 获取当前的时间戳 -/// @param succes 成功 -/// @param failure 失败 + + + (void)getInternetDateWithSuccess:(void(^)(NSTimeInterval timeInterval))succes failure:(void(^)(NSError *error))failure{ - //1.创建URL + NSString *urlString = [HttpRequestHelper getHostUrl]; urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; - //2.创建request请求对象 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString: urlString]]; [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; [request setTimeoutInterval:5]; [request setHTTPShouldHandleCookies:FALSE]; [request setHTTPMethod:@"GET"]; - //3.创建URLSession对象 + NSURLSession *session = [NSURLSession sharedSession]; - //4.设置数据返回回调的block + NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error == nil && response != nil) { - //这么做的原因是简体中文下的手机不能识别“MMM”,只能识别“MM” + NSArray *monthEnglishArray = @[@"Jan",@"Feb",@"Mar",@"Apr",@"May",@"Jun",@"Jul",@"Aug",@"Sept",@"Sep",@"Oct",@"Nov",@"Dec"]; NSArray *monthNumArray = @[@"01",@"02",@"03",@"04",@"05",@"06",@"07",@"08",@"09",@"09",@"10",@"11",@"12"]; NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; @@ -38,7 +35,7 @@ dateStr = [dateStr substringFromIndex:5]; dateStr = [dateStr substringToIndex:[dateStr length]-4]; dateStr = [dateStr stringByAppendingString:@" +0000"]; - //当前语言是中文的话,识别不了英文缩写 + for (NSInteger i = 0 ; i < monthEnglishArray.count ; i++) { NSString *monthEngStr = monthEnglishArray[i]; NSString *monthNumStr = monthNumArray[i]; @@ -61,7 +58,7 @@ } }]; - //5、执行网络请求 + [task resume]; } diff --git a/YuMi/Tools/Timestamp/Timestamp.m.backup b/YuMi/Tools/Timestamp/Timestamp.m.backup new file mode 100644 index 0000000..860fd4b --- /dev/null +++ b/YuMi/Tools/Timestamp/Timestamp.m.backup @@ -0,0 +1,68 @@ +// +// Timestamp.m +// YUMI +// +// Created by YUMI on 2022/1/12. +// + +#import "Timestamp.h" +#import "YUMIMacroUitls.h" + +@implementation Timestamp +/// 获取当前的时间戳 +/// @param succes 成功 +/// @param failure 失败 ++ (void)getInternetDateWithSuccess:(void(^)(NSTimeInterval timeInterval))succes + failure:(void(^)(NSError *error))failure{ + //1.创建URL + NSString *urlString = [HttpRequestHelper getHostUrl]; + urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + //2.创建request请求对象 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + [request setURL:[NSURL URLWithString: urlString]]; + [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; + [request setTimeoutInterval:5]; + [request setHTTPShouldHandleCookies:FALSE]; + [request setHTTPMethod:@"GET"]; + //3.创建URLSession对象 + NSURLSession *session = [NSURLSession sharedSession]; + //4.设置数据返回回调的block + NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if (error == nil && response != nil) { + //这么做的原因是简体中文下的手机不能识别“MMM”,只能识别“MM” + NSArray *monthEnglishArray = @[@"Jan",@"Feb",@"Mar",@"Apr",@"May",@"Jun",@"Jul",@"Aug",@"Sept",@"Sep",@"Oct",@"Nov",@"Dec"]; + NSArray *monthNumArray = @[@"01",@"02",@"03",@"04",@"05",@"06",@"07",@"08",@"09",@"09",@"10",@"11",@"12"]; + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + NSDictionary *allHeaderFields = [httpResponse allHeaderFields]; + NSString *dateStr = [allHeaderFields objectForKey:@"Date"]; + dateStr = [dateStr substringFromIndex:5]; + dateStr = [dateStr substringToIndex:[dateStr length]-4]; + dateStr = [dateStr stringByAppendingString:@" +0000"]; + //当前语言是中文的话,识别不了英文缩写 + for (NSInteger i = 0 ; i < monthEnglishArray.count ; i++) { + NSString *monthEngStr = monthEnglishArray[i]; + NSString *monthNumStr = monthNumArray[i]; + dateStr = [dateStr stringByReplacingOccurrencesOfString:monthEngStr withString:monthNumStr]; + + } + NSDateFormatter *dMatter = [[NSDateFormatter alloc] init]; + [dMatter setDateFormat:@"dd MM yyyy HH:mm:ss Z"]; + NSDate *netDate = [dMatter dateFromString:dateStr]; + NSTimeInterval timeInterval = [netDate timeIntervalSince1970]; + dispatch_async(dispatch_get_main_queue(), ^{ + succes(timeInterval); + }); + + }else{ + dispatch_async(dispatch_get_main_queue(), ^{ + failure(error); + }); + + } + + }]; + //5、执行网络请求 + [task resume]; + +} +@end diff --git a/YuMi/Tools/UILabel/UILabel+Utils.h b/YuMi/Tools/UILabel/UILabel+Utils.h.backup similarity index 100% rename from YuMi/Tools/UILabel/UILabel+Utils.h rename to YuMi/Tools/UILabel/UILabel+Utils.h.backup diff --git a/YuMi/Tools/UILabel/UILabel+Utils.m b/YuMi/Tools/UILabel/UILabel+Utils.m.backup similarity index 100% rename from YuMi/Tools/UILabel/UILabel+Utils.m rename to YuMi/Tools/UILabel/UILabel+Utils.m.backup diff --git a/YuMi/Tools/YYUtility/CarrierIdentifier.h b/YuMi/Tools/YYUtility/CarrierIdentifier.h index 94c5bdb..ae6be61 100644 --- a/YuMi/Tools/YYUtility/CarrierIdentifier.h +++ b/YuMi/Tools/YYUtility/CarrierIdentifier.h @@ -1,21 +1,19 @@ -// -// CarrierIdentifier.h -// YYMobileFramework -// -// Created by wuwei on 14-5-30. -// Copyright (c) 2014年 YY Inc. All rights reserved. -// - -#import - -// 运营商类型 -typedef NS_ENUM(NSUInteger, CarrierIdentifier) -{ - CarrierIdentifier_Unknown = 0, // 未知, 网络不可用(未插SIM卡/无信号/飞行模式) - - CarrierIdentifier_ChinaMobile = 1, // 中国移动 - CarrierIdentifier_ChinaUnicom = 2, // 中国联通 - CarrierIdentifier_ChinaTelecom = 3, // 中国电信 - - CarrierIdentifier_Otherwise = 0x0000FFFF, // 其他运营商 + + +// Created by wuwei on 14-5-30. +// Copyright (c) 2014年 YY Inc. All rights reserved. + + +#import + + +typedef NS_ENUM(NSUInteger, CarrierIdentifier) +{ + CarrierIdentifier_Unknown = 0, + + CarrierIdentifier_ChinaMobile = 1, + CarrierIdentifier_ChinaUnicom = 2, + CarrierIdentifier_ChinaTelecom = 3, + + CarrierIdentifier_Otherwise = 0x0000FFFF, }; \ No newline at end of file diff --git a/YuMi/Tools/YYUtility/YYUtility+App.m b/YuMi/Tools/YYUtility/YYUtility+App.m index db81600..dccbc15 100644 --- a/YuMi/Tools/YYUtility/YYUtility+App.m +++ b/YuMi/Tools/YYUtility/YYUtility+App.m @@ -1,160 +1,45 @@ -// -// YYUtility+App.m -// YYMobileFramework -// + + // Created by wuwei on 14-5-30. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import "YYUtility.h" -#import //为判断网络制式的主要文件 -#import //添加获取客户端运营商 支持 - +#import +#import @implementation YYUtility (App) -+ (id)valueInPlistForKey:(NSString *)key{ - NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; - return [infoDictionary objectForKey:key]; -} - + (NSString *)appVersion{ static NSString *appVersion = nil; if (!appVersion) { - appVersion = [self valueInPlistForKey:@"CFBundleShortVersionString"]; + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; + appVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"]; } return appVersion; } + +(NSString *)getLanguage{ NSString *language = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] firstObject]; return language; - } + + (NSString *)appName { -#ifdef DEBUG - NSString *isProduction = [[NSUserDefaults standardUserDefaults]valueForKey:@"kIsProductionEnvironment"]; - if([isProduction isEqualToString:@"YES"]){ - return @"youmi"; - } - return @"eparti"; - -#else - return @"youmi"; -#endif - - - - - -} - -+ (NSString *)appBuild{ - static NSString *appBuild = nil; - if (!appBuild) { - appBuild = [self valueInPlistForKey:(NSString *)kCFBundleVersionKey]; - } - return appBuild; -} - -+ (NSString *)appBundleId{ - static NSString *appBundleId = nil; - if (!appBundleId) { - appBundleId = [self valueInPlistForKey:(NSString *)kCFBundleIdentifierKey]; - } - return appBundleId; -} - - -+ (NSString *)svnVersion{ - static NSString *svnVersion = nil; - if (!svnVersion) { - svnVersion = [self valueInPlistForKey:@"SvnBuildVersion"]; - } - return svnVersion; -} - -static NSString * const kMobileFrameworkResourceBundleName = @"YYMobileFrameworkRes"; - -+ (NSURL *)URLForMobileFrameworkResourceBundle{ - return [[NSBundle mainBundle] URLForResource:kMobileFrameworkResourceBundleName - withExtension:@"bundle"]; -} - -+ (NSString *)pathForMobileFrameworkResourceBundle{ - return [[NSBundle mainBundle] pathForResource:kMobileFrameworkResourceBundleName - ofType:@"bundle"]; -} - -+ (NSString *)buildType{ #ifdef DEBUG NSString *isProduction = [[NSUserDefaults standardUserDefaults]valueForKey:@"kIsProductionEnvironment"]; if([isProduction isEqualToString:@"YES"]){ - return @"RELEASE"; + return @"youmi"; } - return @"DEBUG"; + return @"eparti"; #else - return @"RELEASE"; + return @"youmi"; #endif } -+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)fileURL{ - if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { - NSLog(@"File %@ dosen't exist!", fileURL); - return NO; - } - - NSError *error = nil; - BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] - forKey:NSURLIsExcludedFromBackupKey - error:&error]; - if (!result) { - NSLog(@"Error excluding '%@' from backup, error: %@.", fileURL, error); - } - - return result; -} - -static NSString *_from = nil; - + (NSString *)getAppSource{ + static NSString *_from = nil; return _from; } -+ (BOOL)isFromAppStore{ - return YES; -} - - -+ (NSString *)removeSpaceAndNewline:(NSString *)str{ - NSString *temp = [str stringByReplacingOccurrencesOfString:@" " withString:@""]; - temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""]; - temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""]; - return temp; -} -/// 获取运营商信息 -+ (YYUtilityTelephonType)getOperatorInfomation { - CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init]; - //NSLog(@"info = %@", info); - CTCarrier *carrier = [info serviceSubscriberCellularProviders]; - //NSLog(@"carrier = %@", carrier); - if (carrier == nil) { - return YYUtilityTelephonType_Link_Unknown; - } - NSString *code = [carrier mobileNetworkCode]; - if (code == nil) { - return YYUtilityTelephonType_Link_Unknown; - } - if ([code isEqualToString:@"00"] || [code isEqualToString:@"02"] || [code isEqualToString:@"07"]) { - return YYUtilityTelephonType_Move; - } else if ([code isEqualToString:@"01"] || [code isEqualToString:@"06"]) { - return YYUtilityTelephonType_Link_Together; - } else if ([code isEqualToString:@"03"] || [code isEqualToString:@"05"]) { - return YYUtilityTelephonType_Link_Telegraphy; - } else if ([code isEqualToString:@"20"]) { - return YYUtilityTelephonType_Link_Tietong; - } - return YYUtilityTelephonType_Link_Unknown; -} - @end diff --git a/YuMi/Tools/YYUtility/YYUtility+Carrier.m b/YuMi/Tools/YYUtility/YYUtility+Carrier.m index 6b8c110..d29b775 100644 --- a/YuMi/Tools/YYUtility/YYUtility+Carrier.m +++ b/YuMi/Tools/YYUtility/YYUtility+Carrier.m @@ -1,10 +1,8 @@ -// -// YYUtility+Carrier.m -// YYFoundation -// + + // Created by wuwei on 14-5-30. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import "YYUtility.h" #import @@ -12,86 +10,53 @@ #import "CarrierIdentifier.h" @import CoreTelephony; -/* - * The most update-to-date list of MNC&MCC is fetched - * from the website below: http://www.mcc-mnc.com - */ -// MCCs -static NSString * const kMobileCountryCode_China = @"460"; // 中国 -// MNCs -static NSSet * kMobileNetworkCodes_ChinaMobile; // 移动 -static NSSet * kMobileNetworkCodes_ChinaUnicom; // 联通 -static NSSet * kMobileNetworkCodes_ChinaTelecom; // 电信 +static NSString * const kMobileCountryCode_China = @"460"; + + +static NSSet * kMobileNetworkCodes_ChinaMobile; +static NSSet * kMobileNetworkCodes_ChinaUnicom; +static NSSet * kMobileNetworkCodes_ChinaTelecom; @implementation YYUtility (Carrier) + (void)load { if (self == [YYUtility self]) { - kMobileNetworkCodes_ChinaMobile = [NSSet setWithObjects:@"00", @"02", @"07", nil]; // 中国移动 - kMobileNetworkCodes_ChinaUnicom = [NSSet setWithObjects:@"01", @"06", nil]; // 中国联通 - kMobileNetworkCodes_ChinaTelecom = [NSSet setWithObjects:@"03", @"05", nil]; // 中国电信 + kMobileNetworkCodes_ChinaMobile = [NSSet setWithObjects:@"00", @"02", @"07", nil]; + kMobileNetworkCodes_ChinaUnicom = [NSSet setWithObjects:@"01", @"06", nil]; + kMobileNetworkCodes_ChinaTelecom = [NSSet setWithObjects:@"03", @"05", nil]; } } -+ (NSString *)carrierName -{ - return [self carrier].carrierName; -} - -+ (NSInteger)carrierIdentifier -{ - return [self identifierOfCarrier:[self carrier]]; -} - -+ (CTCarrier *)carrier -{ - return [[CTTelephonyNetworkInfo alloc] init].subscriberCellularProvider; -} -+(NSString *)getMobileCountryCode{ ++ (NSString *)getMobileCountryCode{ CTCarrier *carrier = [[CTTelephonyNetworkInfo alloc] init].subscriberCellularProvider; NSString *code = carrier.mobileCountryCode; return code; } -+ (NSInteger)identifierOfCarrier:(CTCarrier *)carrier + ++ (NSInteger)carrierIdentifier { -// CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init]; -// if (@available(iOS 16, *)) { -// carrier = networkInfo.serviceSubscriberCellularProviders; -// } - + CTCarrier *carrier = [[CTTelephonyNetworkInfo alloc] init].subscriberCellularProvider; CarrierIdentifier identifier = CarrierIdentifier_Unknown; - do { - if (carrier.mobileCountryCode == nil || carrier.mobileNetworkCode == nil) - { - identifier = CarrierIdentifier_Unknown; - break; + + if (carrier.mobileCountryCode == nil || carrier.mobileNetworkCode == nil) { + return identifier; + } + + if ([carrier.mobileCountryCode isEqualToString:kMobileCountryCode_China]) { + if ([kMobileNetworkCodes_ChinaMobile containsObject:carrier.mobileNetworkCode]) { + identifier = CarrierIdentifier_ChinaMobile; + } else if ([kMobileNetworkCodes_ChinaUnicom containsObject:carrier.mobileNetworkCode]) { + identifier = CarrierIdentifier_ChinaUnicom; + } else if ([kMobileNetworkCodes_ChinaTelecom containsObject:carrier.mobileNetworkCode]) { + identifier = CarrierIdentifier_ChinaTelecom; } - - if ([carrier.mobileCountryCode isEqualToString:kMobileCountryCode_China]) - { - if ([kMobileNetworkCodes_ChinaMobile containsObject:carrier.mobileNetworkCode]) - { - identifier = CarrierIdentifier_ChinaMobile; - break; - } - else if ([kMobileNetworkCodes_ChinaUnicom containsObject:carrier.mobileNetworkCode]) - { - identifier = CarrierIdentifier_ChinaUnicom; - break; - } - else if ([kMobileNetworkCodes_ChinaTelecom containsObject:carrier.mobileNetworkCode]) - { - identifier = CarrierIdentifier_ChinaTelecom; - break; - } - } - + } else { identifier = CarrierIdentifier_Otherwise; - - } while (0); + } return identifier; } + @end diff --git a/YuMi/Tools/YYUtility/YYUtility+Device.m b/YuMi/Tools/YYUtility/YYUtility+Device.m index 3d2e744..858c1d6 100644 --- a/YuMi/Tools/YYUtility/YYUtility+Device.m +++ b/YuMi/Tools/YYUtility/YYUtility+Device.m @@ -1,60 +1,27 @@ -// -// YYUtility+Device.m -// YYMobileFramework -// + + // Created by wuwei on 14-5-30. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import #import #import +#import #import "YYUtility.h" -#import -#import -#import -#import #import "YYReachability.h" -#import - -#import -#import -#import #import "SSKeychain.h" #import "GCDHelper.h" - -#if !defined(IFT_ETHER) -#define IFT_ETHER 0x6 -#endif - -#define kIOSCellular @"pdp_ip0" -#define kIOSWifi @"en0" -#define kIPAddrV4 @"ipv4" -#define kIPAddrV6 @"ipv6" -#define kAppName @"yym51ip" - @implementation YYUtility (Device) -+ (NSString *)modelName -{ - static NSString *modelName = nil; - if (!modelName) { - struct utsname systemInfo; - uname(&systemInfo); - modelName = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; - } - return modelName; -} - + (NSString *)systemVersion { - // 调用非常频繁,主要在cleanSpecialText中 static NSString* _systemVersion = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - _systemVersion = [UIDevice currentDevice].systemVersion;; + _systemVersion = [UIDevice currentDevice].systemVersion; }); if (_systemVersion) { @@ -73,18 +40,16 @@ return idfv; } -+ (NSString *)deviceID -{ - NSString *deviceID = @""; - if (!deviceID || deviceID.length == 0) { - deviceID = [YYUtility identifierForVendor]; ++ (NSString *)deviceUniqueIdentification { + NSString * currentDeviceUUIDStr = [SSKeychain passwordForService:@" " account:@"uuid"]; + if (currentDeviceUUIDStr == nil || [currentDeviceUUIDStr isEqualToString:@""]) { + NSUUID * currentDeviceUUID = [UIDevice currentDevice].identifierForVendor; + currentDeviceUUIDStr = currentDeviceUUID.UUIDString; + currentDeviceUUIDStr = [currentDeviceUUIDStr stringByReplacingOccurrencesOfString:@"-" withString:@""]; + currentDeviceUUIDStr = [currentDeviceUUIDStr lowercaseString]; + [SSKeychain setPassword: currentDeviceUUIDStr forService:@" "account:@"uuid"]; } - - if (!deviceID) { - deviceID = @""; - } - - return deviceID; + return currentDeviceUUIDStr; } + (NSInteger)networkStatus @@ -111,7 +76,7 @@ if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { - // iOS7下,需要检查iPhone的隐私和访问限制项 + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; switch (authStatus) { case AVAuthorizationStatusAuthorized: @@ -121,7 +86,7 @@ } case AVAuthorizationStatusDenied: { - // [设置->隐私->相机]中禁止了YY访问相机 + denied(); break; } @@ -192,148 +157,6 @@ } } -+ (NSString *)deviceUniqueIdentification { - // SSKeychain - NSString * currentDeviceUUIDStr = [SSKeychain passwordForService:@" " account:@"uuid"]; - if (currentDeviceUUIDStr == nil || [currentDeviceUUIDStr isEqualToString:@""]) - { - NSUUID * currentDeviceUUID = [UIDevice currentDevice].identifierForVendor; - currentDeviceUUIDStr = currentDeviceUUID.UUIDString; - currentDeviceUUIDStr = [currentDeviceUUIDStr stringByReplacingOccurrencesOfString:@"-" withString:@""]; - currentDeviceUUIDStr = [currentDeviceUUIDStr lowercaseString]; - [SSKeychain setPassword: currentDeviceUUIDStr forService:@" "account:@"uuid"]; - } - return currentDeviceUUIDStr; -} - -+ (NSString *)ipAddress -{ - return [self ipAddress:YES]; -} - -+ (NSString *)ipAddress:(BOOL)preferIPv4 -{ - NSArray *searchArray = preferIPv4 ? - @[ kIOSWifi @"/" kIPAddrV4, kIOSWifi @"/" kIPAddrV6, kIOSCellular @"/" kIPAddrV4, kIOSCellular @"/" kIPAddrV6 ] : - @[ kIOSWifi @"/" kIPAddrV6, kIOSWifi @"/" kIPAddrV4, kIOSCellular @"/" kIPAddrV6, kIOSCellular @"/" kIPAddrV4 ] ; - - NSDictionary *addresses = [self getIpAddresses]; - - __block NSString *addr; - [searchArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - addr = addresses[obj]; - if (addr) { - *stop = YES; - } - }]; - return addr ? : @"0.0.0.0"; -} - -+ (NSDictionary *)getIpAddresses -{ - NSMutableDictionary *addresses = [NSMutableDictionary dictionary]; - - // retrieve the current interfaces - return 0 on success - struct ifaddrs *interfaces; - if (!getifaddrs(&interfaces)) { - // Loop through linked list of interfaces - struct ifaddrs *interface; - for (interface = interfaces; interface; interface = interface->ifa_next) { - if (!(interface -> ifa_flags & IFF_UP)) { - continue; - } - const struct sockaddr_in *addr = (const struct sockaddr_in *)interface->ifa_addr; - char addrBuf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 2]; - if (addr && (addr->sin_family == AF_INET || addr->sin_family == AF_INET6)) { - NSString *ifaName = [NSString stringWithUTF8String:interface->ifa_name]; - NSString *ifaType; - if (addr->sin_family == AF_INET) { - if (inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) { - ifaType = kIPAddrV4; - } - } else { - const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)interface->ifa_addr; - if (inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) { - ifaType = kIPAddrV6; - } - } - if (ifaType) { - NSString *key = [NSString stringWithFormat:@"%@/%@", ifaName, ifaType]; - addresses[key] = [NSString stringWithUTF8String:addrBuf]; - } - } - } - } - // free memory - freeifaddrs(interfaces); - return addresses; -} - -+ (NSString *)macAddresss -{ - static NSMutableString *macAddress = nil; - - if ([macAddress length] > 0) { - return macAddress; - } - - do - { - struct ifaddrs* addrs; - if ( getifaddrs( &addrs ) ) - break; - - const struct ifaddrs *cursor = addrs; - while ( cursor ) - { - if ( ( cursor->ifa_addr->sa_family == AF_LINK ) - && strcmp( "en0", cursor->ifa_name ) == 0 - && ( ( ( const struct sockaddr_dl * )cursor->ifa_addr)->sdl_type == IFT_ETHER ) ) - { - const struct sockaddr_dl *dlAddr = ( const struct sockaddr_dl * )cursor->ifa_addr; - const uint8_t *base = ( const uint8_t * )&dlAddr->sdl_data[dlAddr->sdl_nlen]; - - macAddress = [[NSMutableString alloc] initWithCapacity:64]; - - for ( int i = 0; i < dlAddr->sdl_alen; i++ ) - { - if (i > 0) { - [macAddress appendFormat:@"])%02X", base[i]]; - } - else - { - [macAddress appendFormat:@"%02X", base[i]]; - } - } - - break; - } - cursor = cursor->ifa_next; - } - freeifaddrs(addrs); - } while (NO); - - if (macAddress == nil) { - macAddress = [NSMutableString stringWithString:@""]; - } - - return macAddress; -} - -+ (NSString *)idfa -{ - static NSString *idfa = nil; - if (!idfa) { - if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0) { - idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]; - } else { - idfa = @""; - } - } - return idfa; -} - - + (NSString*)modelType { struct utsname systemInfo; @@ -421,57 +244,6 @@ if ([platform isEqualToString:@"i386"]) return @"iPhone Simulator"; if ([platform isEqualToString:@"x86_64"]) return @"iPhone Simulator"; return platform; - -} - -// 当前设备是否低于, 等于 iPhone6 -+ (BOOL)isIphone6AndLow { - struct utsname systemInfo; - - uname(&systemInfo); - - NSString*platform = [NSString stringWithCString: systemInfo.machine encoding:NSASCIIStringEncoding]; - if([platform isEqualToString:@"iPhone1,1"])return YES; - - if([platform isEqualToString:@"iPhone1,2"])return YES; - - if([platform isEqualToString:@"iPhone2,1"])return YES; - - if([platform isEqualToString:@"iPhone3,1"])return YES; - - if([platform isEqualToString:@"iPhone3,2"])return YES; - - if([platform isEqualToString:@"iPhone3,3"])return YES; - - if([platform isEqualToString:@"iPhone4,1"])return YES; - - if([platform isEqualToString:@"iPhone5,1"])return YES; - - if([platform isEqualToString:@"iPhone5,2"])return YES; - - if([platform isEqualToString:@"iPhone5,3"])return YES; - - if([platform isEqualToString:@"iPhone5,4"])return YES; - - if([platform isEqualToString:@"iPhone6,1"])return YES; - - if([platform isEqualToString:@"iPhone6,2"])return YES; - - if([platform isEqualToString:@"iPhone7,1"])return YES; - - if([platform isEqualToString:@"iPhone7,2"])return YES; - - if ([platform isEqualToString:@"iPhone8,1"]) return YES; - - if ([platform isEqualToString:@"iPhone8,3"]) return YES; - - if ([platform isEqualToString:@"iPhone8,4"]) return YES; - - if ([platform isEqualToString:@"iPhone9,1"]) return YES; - - if ([platform isEqualToString:@"iPhone9,3"]) return YES; - - return NO; } @end diff --git a/YuMi/Tools/YYUtility/YYUtility.h b/YuMi/Tools/YYUtility/YYUtility.h index 5f70580..8d806a1 100644 --- a/YuMi/Tools/YYUtility/YYUtility.h +++ b/YuMi/Tools/YYUtility/YYUtility.h @@ -1,225 +1,42 @@ -// -// YYUtility.h -// YYMobileFramework -// -// Created by wuwei on 14/6/11. -// Copyright (c) 2014年 YY.inc. All rights reserved. -// - -#import -typedef enum : NSUInteger { - YYUtilityTelephonType_Move = 0,///移动 - YYUtilityTelephonType_Link_Together,///联通 - YYUtilityTelephonType_Link_Telegraphy,///电信 - YYUtilityTelephonType_Link_Tietong,///铁通 - YYUtilityTelephonType_Link_Unknown,///不知道的运营商 -} YYUtilityTelephonType; -@class CTCarrier; - -@interface YYUtility : NSObject - -@end - -/*==============================*/ -/* App Utilities */ -/*==============================*/ -@interface YYUtility (App) - -/** - * 从YYMobile-Info.plist中读取字段 - * - * @param key 键 - * - * @return 值 - */ -+ (id)valueInPlistForKey:(NSString *)key; - -/** - * 获取App版本号, 从plist从读取CFBundleShortVersion - */ -+ (NSString *)appVersion; -+(NSString *)getLanguage; -/** - * 获取AppBuild号, 从plist中读取CFBundleVersion - */ -+ (NSString *)appBuild; - -/** - * 当前构建出的版本在svn中的版本号 - */ -+ (NSString *)svnVersion; - -/** - 获取appName - - @return app的名称 - */ -+ (NSString *)appName; - -/** - * 获取bundle id - * - * @return bundle id - */ -+ (NSString *)appBundleId; - -/** - * 获取YYMobileFrameworkRes.bundle的URL - */ -+ (NSURL *)URLForMobileFrameworkResourceBundle; - -/** - * 获取YYMobileFrameworkRes.bundle的路径 - */ -+ (NSString *)pathForMobileFrameworkResourceBundle; - -+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)fileURL; - -/** - * 获取当前的构建类型(DEBUG/RELEASE) - * - * @return 构建类型 - */ -+ (NSString *)buildType; - -/** - * 获取平台渠道 - */ -+ (NSString *)getAppSource; - -/** - * 是否来自appstore - */ -+ (BOOL)isFromAppStore; -/// 获取运营商信息 -+ (YYUtilityTelephonType)getOperatorInfomation; -@end - -/*==============================*/ -/* Carrier Utilities */ -/*==============================*/ -@interface YYUtility (Carrier) -+(NSString *)getMobileCountryCode; - -/** - 获取设备唯一标识 - - @return 唯一标识 - */ -+ (NSString *)deviceUniqueIdentification; - -/** - * 获取运营商 - */ -+ (CTCarrier *)carrier; - -/** - * 获取运营商类型 - */ -+ (NSInteger)carrierIdentifier; - -/** - * 获取运营商名称 - */ -+ (NSString *)carrierName; - -/** - * 从CTCarrier对象获取网络类型 - * @param carrier - CTCarrier对象 - * @return CarrierType - */ -+ (NSInteger)identifierOfCarrier:(CTCarrier *)carrier; - -@end - -/*==============================*/ -/* Device Utilities */ -/*==============================*/ -@interface YYUtility (Device) - -/** - * 获取modelName, 如iPhone5,2 - */ -+ (NSString *)modelName; - - -/** - 获取设备类型 - - @return 设备类型 - */ -+ (NSString*)modelType; - -/** - * 获取系统版本 - */ -+ (NSString *)systemVersion; - -/** - * 获取当前设备的 IDFV,IDFV 在某些情况下会变,不建议将其作为设备标识 - */ -+ (NSString *)identifierForVendor NS_AVAILABLE_IOS(6_0); - -/** - * 获取当前的设备标识,会使用海度 SDK 中的 OpenUDID - * - * @return 海度 SDK 缓存的 OpenUDID - */ -+ (NSString *)deviceID; - -/** - * 获取当前网络状态 - */ -+ (NSInteger)networkStatus; - -/** - * 获取当前IP地址 - */ -+ (NSString *)ipAddress; - -/** - * 获取当前IP地址 - * - * @param preferIPv4 优先取IPv4的地址 - */ -+ (NSString *)ipAddress:(BOOL)preferIPv4; - -/** - * 检查Camera是否可用, 可用则调用available; 若隐私设置中禁用了本app对相机 - * 的访问, 则调用denied; 否则视为被限制, 调用restriction - * - * @param available 可用 - * @param denied 不可用 - * @param restriction 受限制 - */ -+ (void)checkCameraAvailable:(void (^)(void))available denied:(void(^)(void))denied restriction:(void(^)(void))restriction; - -/** - * 检查相册是否可用, 可用则调用available; 若隐私设置中禁用了本app对相册 - * 的访问, 则调用denied; 否则视为被限制, 调用restriction - * - * @param available 可用 - * @param denied 不可用 - * @param restriction 受限制 - */ -+ (void)checkAssetsLibrayAvailable:(void (^)(void))available denied:(void(^)(void))denied restriction:(void(^)(void))restriction; - -+ (NSString *)macAddresss; -+ (NSString *)idfa; - -/** - * 初始化信令sdk,imsdk所用到的appName - * - * @return app name - */ -+ (NSString *)appName; - - -/** - 当前设备是否低于, 等于 iPhone6 - - @return 当前设备是否低于, 等于 iPhone6 - */ -+ (BOOL)isIphone6AndLow; - -@end + + +// Created by wuwei on 14/6/11. +// Copyright (c) 2014年 YY.inc. All rights reserved. + + +#import + +@interface YYUtility : NSObject + +@end + + +@interface YYUtility (App) + ++ (NSString *)appVersion; ++ (NSString *)getLanguage; ++ (NSString *)appName; ++ (NSString *)getAppSource; + +@end + + +@interface YYUtility (Carrier) + ++ (NSString *)getMobileCountryCode; ++ (NSInteger)carrierIdentifier; + +@end + + +@interface YYUtility (Device) + ++ (NSString *)deviceUniqueIdentification; ++ (NSString *)modelType; ++ (NSString *)systemVersion; ++ (NSString *)identifierForVendor NS_AVAILABLE_IOS(6_0); ++ (NSInteger)networkStatus; ++ (void)checkCameraAvailable:(void (^)(void))available denied:(void(^)(void))denied restriction:(void(^)(void))restriction; ++ (void)checkAssetsLibrayAvailable:(void (^)(void))available denied:(void(^)(void))denied restriction:(void(^)(void))restriction; + +@end diff --git a/YuMi/Tools/YYUtility/YYUtility.m b/YuMi/Tools/YYUtility/YYUtility.m index 2f91c12..1babf14 100644 --- a/YuMi/Tools/YYUtility/YYUtility.m +++ b/YuMi/Tools/YYUtility/YYUtility.m @@ -1,10 +1,8 @@ -// -// YYUtility.m -// YYMobileFramework -// + + // Created by wuwei on 14-5-30. // Copyright (c) 2014年 YY Inc. All rights reserved. -// + #import "YYUtility.h" diff --git a/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h index 2e795b2..1df2e82 100644 --- a/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h +++ b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h @@ -1,29 +1,25 @@ -// -// GWSDLayoutUtil.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/31. // Copyright © 2016年 xw.com. All rights reserved. -// + #import #import "Masonry.h" -//位置固定宽度跟高度 -#define SDLAYOUT_wh1(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.leading.equalTo(B).offset(C);make.top.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//左上 -#define SDLAYOUT_wh2(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.trailing.equalTo(B).offset(C);make.top.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//右上 +#define SDLAYOUT_wh1(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.leading.equalTo(B).offset(C);make.top.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}]; -#define SDLAYOUT_wh3(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.leading.equalTo(B).offset(C);make.bottom.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//左下 +#define SDLAYOUT_wh2(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.trailing.equalTo(B).offset(C);make.top.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}]; -#define SDLAYOUT_wh4(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.trailing.equalTo(B).offset(C);make.bottom.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//右下 +#define SDLAYOUT_wh3(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.leading.equalTo(B).offset(C);make.bottom.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}]; + +#define SDLAYOUT_wh4(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.trailing.equalTo(B).offset(C);make.bottom.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}]; -//固定高度 #define SDLAYOUT_h(A,B,C,D,E,F,G,H) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(B).offset(C);make.leading.equalTo(D).offset(E);make.trailing.equalTo(F).offset(G);make.height.mas_equalTo(H);}]; -//原始的 #define SDLAYOUT(A,B,C,D,E,F,G,H,I) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(B).offset(C);make.leading.equalTo(D).offset(E);make.trailing.equalTo(F).offset(G);make.bottom.equalTo(H).offset(I);}]; @interface BSSDLayoutUtil : PIBaseModel diff --git a/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h.backup b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h.backup new file mode 100644 index 0000000..2e795b2 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.h.backup @@ -0,0 +1,31 @@ +// +// GWSDLayoutUtil.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/31. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import "Masonry.h" + +//位置固定宽度跟高度 +#define SDLAYOUT_wh1(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.leading.equalTo(B).offset(C);make.top.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//左上 + +#define SDLAYOUT_wh2(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.trailing.equalTo(B).offset(C);make.top.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//右上 + +#define SDLAYOUT_wh3(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.leading.equalTo(B).offset(C);make.bottom.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//左下 + +#define SDLAYOUT_wh4(A,B,C,D,E,F,G) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.trailing.equalTo(B).offset(C);make.bottom.equalTo(D).offset(E);make.width.mas_equalTo(F);make.height.mas_equalTo(G);}];//右下 + + +//固定高度 +#define SDLAYOUT_h(A,B,C,D,E,F,G,H) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(B).offset(C);make.leading.equalTo(D).offset(E);make.trailing.equalTo(F).offset(G);make.height.mas_equalTo(H);}]; + + +//原始的 +#define SDLAYOUT(A,B,C,D,E,F,G,H,I) [A mas_makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(B).offset(C);make.leading.equalTo(D).offset(E);make.trailing.equalTo(F).offset(G);make.bottom.equalTo(H).offset(I);}]; + +@interface BSSDLayoutUtil : PIBaseModel + +@end diff --git a/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m index e60ba2c..756bef6 100644 --- a/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m +++ b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m @@ -1,17 +1,12 @@ -// -// GWSDLayoutUtil.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/31. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSSDLayoutUtil.h" @implementation BSSDLayoutUtil -// - - @end diff --git a/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m.backup b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m.backup new file mode 100644 index 0000000..e60ba2c --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/3Party/fmdb/BSSDLayoutUtil.m.backup @@ -0,0 +1,17 @@ +// +// GWSDLayoutUtil.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/31. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSSDLayoutUtil.h" + +@implementation BSSDLayoutUtil + + +// + + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h index e57db98..7a5e652 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h @@ -1,39 +1,18 @@ -// -// GWNSDictionary.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/11/8. // Copyright © 2016年 xw.com. All rights reserved. -// + #import @interface BSNSDictionary : NSObject -/*! - - * @brief 把格式化的JSON格式的字符串转换成字典 - - * @param jsonString JSON格式的字符串 - - * @return 返回字典 - - */ + (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString; -/*! - - * @brief 把字典转json字符串 - - * @param dic 字典 - - * @return 字符串 - - */ + (NSString*)dictionaryToJson:(NSDictionary *)dic; - @end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h.backup b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h.backup new file mode 100644 index 0000000..e57db98 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.h.backup @@ -0,0 +1,39 @@ +// +// GWNSDictionary.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/11/8. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + +@interface BSNSDictionary : NSObject + +/*! + + * @brief 把格式化的JSON格式的字符串转换成字典 + + * @param jsonString JSON格式的字符串 + + * @return 返回字典 + + */ + ++ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString; + + +/*! + + * @brief 把字典转json字符串 + + * @param dic 字典 + + * @return 字符串 + + */ ++ (NSString*)dictionaryToJson:(NSDictionary *)dic; + + + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m index 5ca96f5..b369ebe 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m @@ -1,10 +1,8 @@ -// -// GWNSDictionary.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/11/8. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSNSDictionary.h" @@ -24,7 +22,7 @@ options:NSJSONReadingMutableContainers error:&err]; if(err) { -// NSLog(@"json解析失败:%@",err); + return nil; } return dic; diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m.backup b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m.backup new file mode 100644 index 0000000..5ca96f5 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSDictionary.m.backup @@ -0,0 +1,47 @@ +// +// GWNSDictionary.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/11/8. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSNSDictionary.h" + +@implementation BSNSDictionary + + +#pragma mark - 把格式化的JSON格式的字符串转换成字典 ++ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString { + + if (jsonString == nil) { + return nil; + } + + NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSError *err; + NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData + options:NSJSONReadingMutableContainers + error:&err]; + if(err) { +// NSLog(@"json解析失败:%@",err); + return nil; + } + return dic; +} + + +#pragma mark - 把字典转json字符串 ++ (NSString*)dictionaryToJson:(NSDictionary *)dic + +{ + + NSError *parseError = nil; + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError]; + + return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + +} + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h index 428e453..c427355 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h @@ -1,10 +1,8 @@ -// -// NSStringUtil.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/30. // Copyright © 2016年 xw.com. All rights reserved. -// + #import #import @@ -12,60 +10,23 @@ @interface BSNSStringUtil : PIBaseModel -/** - 格式换字典,数组,转字符串(格式化) - - @param object 数据对象 - @return 格式化的字符串 - */ +(NSString *)getStringFromObj:(id)object; -/** - 去掉所有的空格和回车,\t - - @param str 原始的字符串 - @return 去掉所有的空格和回车后的字符串 - */ +(NSString *)clearStr:(NSString *)str; -/** - URLEncode url编码 - - @param unencodedString 原始字符串 - @return 编码后的字符串 - */ +(NSString*)encodeString:(NSString*)unencodedString; -/** - URLDEcode url解码 - - @param encodedString 原始字符串 - @return 解码后的字符串 - */ +(NSString *)decodeString:(NSString*)encodedString; -/** - 判断字符串是否是纯数字 - @param BOOL 字符串 - @return 是否纯数字 - */ + (BOOL)isPureInt:(NSString *)string; #pragma mark - 富文本相关 -/** - 根据字体,颜色,返回富文本,行距 - @param str 字符串 - @param color 颜色 - @param font 字体 - @param lineSpac 行距 - @return 富文本 - */ +(NSAttributedString *)getAttributedString:(NSString *)str color:(UIColor *)color font:(CGFloat)font lineSpa:(CGFloat)lineSpac; @end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h.backup b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h.backup new file mode 100644 index 0000000..428e453 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.h.backup @@ -0,0 +1,71 @@ +// +// NSStringUtil.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/30. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import + +@interface BSNSStringUtil : PIBaseModel + + +/** + 格式换字典,数组,转字符串(格式化) + + @param object 数据对象 + @return 格式化的字符串 + */ ++(NSString *)getStringFromObj:(id)object; + + +/** + 去掉所有的空格和回车,\t + + @param str 原始的字符串 + @return 去掉所有的空格和回车后的字符串 + */ ++(NSString *)clearStr:(NSString *)str; + + +/** + URLEncode url编码 + + @param unencodedString 原始字符串 + @return 编码后的字符串 + */ ++(NSString*)encodeString:(NSString*)unencodedString; + + +/** + URLDEcode url解码 + + @param encodedString 原始字符串 + @return 解码后的字符串 + */ ++(NSString *)decodeString:(NSString*)encodedString; + +/** + 判断字符串是否是纯数字 + + @param BOOL 字符串 + @return 是否纯数字 + */ ++ (BOOL)isPureInt:(NSString *)string; + +#pragma mark - 富文本相关 + +/** + 根据字体,颜色,返回富文本,行距 + + @param str 字符串 + @param color 颜色 + @param font 字体 + @param lineSpac 行距 + @return 富文本 + */ ++(NSAttributedString *)getAttributedString:(NSString *)str color:(UIColor *)color font:(CGFloat)font lineSpa:(CGFloat)lineSpac; + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m index 4f73c15..1f4a8d6 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m @@ -1,10 +1,8 @@ -// -// NSStringUtil.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/30. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSNSStringUtil.h" @@ -16,7 +14,6 @@ } - +(NSString *)getStringFromObj:(id)object withTimes:(int)times{ if (!object) { @@ -33,7 +30,7 @@ NSMutableString *string = [NSMutableString string]; [string appendString:@"{\n"]; - // 遍历所有的键值对 + [object enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { [string appendFormat:@"\t%@%@",intervalStr,key]; @@ -41,10 +38,10 @@ [string appendFormat:@"%@,\n", [self getStringFromObj:obj withTimes:times]]; }]; - // 结尾有个} + [string appendFormat:@"%@}",intervalStr]; - // 查找最后一个逗号 + NSRange range = [string rangeOfString:@"," options:NSBackwardsSearch]; if (range.location != NSNotFound){ [string deleteCharactersInRange:range]; @@ -55,20 +52,19 @@ NSMutableString *string = [NSMutableString string]; - // 开头有个[ + [string appendString:@"[\n"]; - // 遍历所有的元素 + [object enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - // [string appendFormat:@"\t%@,\n", [self getStringFromObj:obj withTimes:times]]; + [string appendFormat:@"\t%@%@,\n",intervalStr, [self getStringFromObj:obj withTimes:times]]; }]; - // 结尾有个] - // [string appendString:@"]"]; + [string appendFormat:@"%@]",intervalStr]; - // 查找最后一个逗号 + NSRange range = [string rangeOfString:@"," options:NSBackwardsSearch]; if (range.location != NSNotFound){ [string deleteCharactersInRange:range]; @@ -150,7 +146,7 @@ } NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineSpacing = lineSpac;// 字体的行间距 + paragraphStyle.lineSpacing = lineSpac; NSDictionary *attributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:font], NSParagraphStyleAttributeName:paragraphStyle, @@ -161,8 +157,4 @@ } -//返回拼接的富文本 - - - @end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m.backup b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m.backup new file mode 100644 index 0000000..4f73c15 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSNSStringUtil.m.backup @@ -0,0 +1,168 @@ +// +// NSStringUtil.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/30. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSNSStringUtil.h" + +@implementation BSNSStringUtil + +#pragma mark - 格式换字典,数组,转字符串(格式化) ++(NSString *)getStringFromObj:(id)object{ + return [self getStringFromObj:object withTimes:0]; +} + + + ++(NSString *)getStringFromObj:(id)object withTimes:(int)times{ + + if (!object) { + return @""; + } + + times++; + NSMutableString *intervalStr = [NSMutableString string]; + for (int i = 1; i < times; i++) { + [intervalStr appendString:@"\t"]; + } + + if ([object isKindOfClass:[NSDictionary class]]) { + NSMutableString *string = [NSMutableString string]; + [string appendString:@"{\n"]; + + // 遍历所有的键值对 + [object enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + [string appendFormat:@"\t%@%@",intervalStr,key]; + [string appendString:@" : "]; + [string appendFormat:@"%@,\n", [self getStringFromObj:obj withTimes:times]]; + }]; + + // 结尾有个} + [string appendFormat:@"%@}",intervalStr]; + + // 查找最后一个逗号 + NSRange range = [string rangeOfString:@"," options:NSBackwardsSearch]; + if (range.location != NSNotFound){ + [string deleteCharactersInRange:range]; + } + return string; + + }else if([object isKindOfClass:[NSArray class]]){ + + NSMutableString *string = [NSMutableString string]; + + // 开头有个[ + [string appendString:@"[\n"]; + + // 遍历所有的元素 + [object enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + // [string appendFormat:@"\t%@,\n", [self getStringFromObj:obj withTimes:times]]; + [string appendFormat:@"\t%@%@,\n",intervalStr, [self getStringFromObj:obj withTimes:times]]; + }]; + + // 结尾有个] + // [string appendString:@"]"]; + [string appendFormat:@"%@]",intervalStr]; + + // 查找最后一个逗号 + NSRange range = [string rangeOfString:@"," options:NSBackwardsSearch]; + if (range.location != NSNotFound){ + [string deleteCharactersInRange:range]; + } + return string; + + + }else if([object isKindOfClass:[NSString class]]){ + return (NSString *)object; + } + return [object description]; +} + + +#pragma mark - 去掉所有的空格和回车,\t ++(NSString *)clearStr:(NSString *)str{ + str = [str stringByReplacingOccurrencesOfString: @" " withString: @""]; + str = [str stringByReplacingOccurrencesOfString: @"\n" withString: @""]; + str = [str stringByReplacingOccurrencesOfString: @"\t" withString: @""]; + return str; +} + +#pragma mark - URLEncode ++(NSString*)encodeString:(NSString*)unencodedString{ + + #pragma clang diagnostic push + #pragma clang diagnostic ignored"-Wdeprecated-declarations" + NSString *encodedString = (NSString *) + CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, + (CFStringRef)unencodedString, + NULL, + (CFStringRef)@"!*'();:@&=+$,/?%#[]", + kCFStringEncodingUTF8)); + + #pragma clang diagnostic pop + return encodedString; +} + +#pragma mark - URLDEcode ++(NSString *)decodeString:(NSString*)encodedString + +{ + #pragma clang diagnostic push + #pragma clang diagnostic ignored"-Wdeprecated-declarations" + NSString *decodedString = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, + (__bridge CFStringRef)encodedString, + CFSTR(""), + CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); + #pragma clang diagnostic pop + return decodedString; +} + +#pragma mark -- 判断字符串是否是纯数字 ++ (BOOL)isPureInt:(NSString *)string{ + + NSScanner* scan = [NSScanner scannerWithString:string]; + + int val; + + return [scan scanInt:&val] && [scan isAtEnd]; + +} + +#pragma mark - 富文本相关 +#pragma mark - 根据字体,颜色,返回富文本,行距 ++(NSAttributedString *)getAttributedString:(NSString *)str color:(UIColor *)color font:(CGFloat)font lineSpa:(CGFloat)lineSpac{ + + if (lineSpac == 0) { + lineSpac = 5; + } + if (str == nil){ + str = @""; + } + if (font <= 0) { + font = 15; + } + if (color == nil) { + color = [UIColor blackColor]; + } + + NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; + paragraphStyle.lineSpacing = lineSpac;// 字体的行间距 + NSDictionary *attributes = @{ + NSFontAttributeName:[UIFont systemFontOfSize:font], + NSParagraphStyleAttributeName:paragraphStyle, + NSForegroundColorAttributeName:color + }; + + return [[NSAttributedString alloc] initWithString:str attributes:attributes]; +} + + +//返回拼接的富文本 + + + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h index bac555a..c7eac94 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h +++ b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h @@ -1,17 +1,15 @@ -// -// GWUIDemoUtil.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/10/28. // Copyright © 2016年 xw.com. All rights reserved. -// + #import #import @interface BSUIDemoUtil : PIBaseModel -//测试的button + +(UIButton *)addBtn:(NSString *)btnName withView:(UIView *)subViewn frame:(CGRect)frame andtarget:(id)target action:(SEL)action; @end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h.backup b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h.backup new file mode 100644 index 0000000..bac555a --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.h.backup @@ -0,0 +1,17 @@ +// +// GWUIDemoUtil.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/10/28. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import + +@interface BSUIDemoUtil : PIBaseModel + +//测试的button ++(UIButton *)addBtn:(NSString *)btnName withView:(UIView *)subViewn frame:(CGRect)frame andtarget:(id)target action:(SEL)action; + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m index 199af9c..604ee70 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m +++ b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m @@ -1,17 +1,14 @@ -// -// GWUIDemoUtil.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/10/28. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSUIDemoUtil.h" @implementation BSUIDemoUtil -//测试的button +(UIButton *)addBtn:(NSString *)btnName withView:(UIView *)subViewn frame:(CGRect)frame andtarget:(id)target action:(SEL)action{ UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -24,10 +21,5 @@ return btn; } -//测试的textFILE - - -//测试的lable - @end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m.backup b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m.backup new file mode 100644 index 0000000..199af9c --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSUIDemoUtil.m.backup @@ -0,0 +1,33 @@ +// +// GWUIDemoUtil.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/10/28. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSUIDemoUtil.h" + +@implementation BSUIDemoUtil + + +//测试的button ++(UIButton *)addBtn:(NSString *)btnName withView:(UIView *)subViewn frame:(CGRect)frame andtarget:(id)target action:(SEL)action{ + + UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; + [btn setTitle:btnName forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + btn.backgroundColor = [UIColor grayColor]; + btn.frame = frame; + [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; + + return btn; +} + +//测试的textFILE + + +//测试的lable + + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h index aa49437..48e4dbf 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h +++ b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h @@ -1,106 +1,38 @@ -// -// XWDateUtil.h -// FrameObject -// + + // Created by shenba on 16/4/12. // Copyright © 2016年 xiaowen. All rights reserved. -// + #import @interface BSXWDateUtil : PIBaseModel -/** - 获取多少天,多少小时,多少分钟,多少秒之后的时间 - - @param day 天 - @param hours 小时 - @param min 分数 - @param ss 秒数 - @param date 当前时间 - @param forMet 格式化 - @return 结果字符串 - */ +(NSString *)getTimeAfterDay:(int)day hours:(int)hours min:(int)min ss:(int)ss fromDate:(NSDate *)date withForMet:(NSString *)forMet; - -/** - 时间转字符串 - - @param date 时间 - @param forMet 格式 - @return 结果字符串 - */ +(NSString *)strWithDate:(NSDate *)date withForMet:(NSString *)forMet; - -/** - 字符串转时间 - - @param dateStr 时间格式的字符串 - @param dateFormatterStr 格式 - @return 时间 - */ +(NSDate *)DateInitWithString:(NSString *)dateStr dateFormatterStr:(NSString *)dateFormatterStr; - -/** - 判断是否超过某个时间段 timeInterval:单位秒,记录到硬盘 - - @param timeInterval 时间(秒) - @param tag 标记 - @return 结果是否超过某个时间 - */ +(Boolean)isTimeOver:(int)timeInterval withTag:(NSString *)tag; -/** - 清除记录标记的时间 - @param tag 标记 - */ +(void)removeTimeOverTag:(NSString *)tag; - -/** - 判断是否超过某个时间段 timeInterval:单位秒 分组处理 - - @param timeInterval 时间(秒) - @param tag 标记 - @param group 分组 - @return 结果是否超过某个时间 - */ +(Boolean)isTimeOver:(int)timeInterval withTag:(NSString *)tag withGroup:(NSString *)group; -/** - 按照分组清除记录标记的时间 - @param group 分组 - */ +(void)removeTimeOverGroup:(NSString *)group; -/** - 计算事件差,需要同格式的字符串 - - @param time1 时间1 - @param time2 时间2 - @param formet 时间格式 - @return 时间差 - */ +(NSTimeInterval)TimeDifferenceWithTime1:(NSString *)time1 AndTime2:(NSString *)time2 formet:(NSString *)formet; -/** - 根据日期返回是否今天,明天,昨天 - - @param date 日期 - @return 今天,昨天,明天,... - */ +(NSString *)compareDate:(NSDate *)date; @end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h.backup b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h.backup new file mode 100644 index 0000000..aa49437 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.h.backup @@ -0,0 +1,106 @@ +// +// XWDateUtil.h +// FrameObject +// +// Created by shenba on 16/4/12. +// Copyright © 2016年 xiaowen. All rights reserved. +// + +#import + +@interface BSXWDateUtil : PIBaseModel + + +/** + 获取多少天,多少小时,多少分钟,多少秒之后的时间 + + @param day 天 + @param hours 小时 + @param min 分数 + @param ss 秒数 + @param date 当前时间 + @param forMet 格式化 + @return 结果字符串 + */ ++(NSString *)getTimeAfterDay:(int)day hours:(int)hours min:(int)min ss:(int)ss fromDate:(NSDate *)date withForMet:(NSString *)forMet; + + + +/** + 时间转字符串 + + @param date 时间 + @param forMet 格式 + @return 结果字符串 + */ ++(NSString *)strWithDate:(NSDate *)date withForMet:(NSString *)forMet; + + + +/** + 字符串转时间 + + @param dateStr 时间格式的字符串 + @param dateFormatterStr 格式 + @return 时间 + */ ++(NSDate *)DateInitWithString:(NSString *)dateStr dateFormatterStr:(NSString *)dateFormatterStr; + + + +/** + 判断是否超过某个时间段 timeInterval:单位秒,记录到硬盘 + + @param timeInterval 时间(秒) + @param tag 标记 + @return 结果是否超过某个时间 + */ ++(Boolean)isTimeOver:(int)timeInterval withTag:(NSString *)tag; + +/** + 清除记录标记的时间 + + @param tag 标记 + */ ++(void)removeTimeOverTag:(NSString *)tag; + + + +/** + 判断是否超过某个时间段 timeInterval:单位秒 分组处理 + + @param timeInterval 时间(秒) + @param tag 标记 + @param group 分组 + @return 结果是否超过某个时间 + */ ++(Boolean)isTimeOver:(int)timeInterval withTag:(NSString *)tag withGroup:(NSString *)group; + +/** + 按照分组清除记录标记的时间 + + @param group 分组 + */ ++(void)removeTimeOverGroup:(NSString *)group; + + +/** + 计算事件差,需要同格式的字符串 + + @param time1 时间1 + @param time2 时间2 + @param formet 时间格式 + @return 时间差 + */ ++(NSTimeInterval)TimeDifferenceWithTime1:(NSString *)time1 AndTime2:(NSString *)time2 formet:(NSString *)formet; + + +/** + 根据日期返回是否今天,明天,昨天 + + @param date 日期 + @return 今天,昨天,明天,... + */ ++(NSString *)compareDate:(NSDate *)date; + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m index 8d8fd38..0dd0adc 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m +++ b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m @@ -1,10 +1,8 @@ -// -// XWDateUtil.m -// FrameObject -// + + // Created by shenba on 16/4/12. // Copyright © 2016年 xiaowen. All rights reserved. -// + #import "BSXWDateUtil.h" @@ -34,13 +32,13 @@ static NSDateFormatter *simgle_df; } if (forMet==nil) { if (!simgle_df) { - simgle_df = [[NSDateFormatter alloc]init];//格式化 - [simgle_df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//simgle_df保持这个格式,避免多线程调用的时候变化dateFormat造成其他的影响 + simgle_df = [[NSDateFormatter alloc]init]; + [simgle_df setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; } return [simgle_df stringFromDate:date]; } - NSDateFormatter*df = [[NSDateFormatter alloc]init];//格式化 + NSDateFormatter*df = [[NSDateFormatter alloc]init]; [df setDateFormat:forMet]; return [df stringFromDate:date]; @@ -55,8 +53,8 @@ static NSDateFormatter *simgle_df; if (dateFormatterStr == nil) { if (!simgle_df) { - simgle_df = [[NSDateFormatter alloc]init];//格式化 - [simgle_df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//simgle_df保持这个格式,避免多线程调用的时候变化dateFormat造成其他的影响 + simgle_df = [[NSDateFormatter alloc]init]; + [simgle_df setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; } return [simgle_df dateFromString:dateStr]; } @@ -65,7 +63,7 @@ static NSDateFormatter *simgle_df; NSDate *reslutDate = nil; NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; [formatter setDateFormat:dateFormatterStr]; - reslutDate = [formatter dateFromString:dateStr];//得到时间 + reslutDate = [formatter dateFromString:dateStr]; return reslutDate; } @@ -78,19 +76,19 @@ static NSDateFormatter *simgle_df; NSString *tempStrTag = [NSString stringWithFormat:@"bs_timesover_%@",tag]; NSString *str = [defaults valueForKey:tempStrTag]; NSDate *nowDate = [NSDate date]; -// NSLog(@"比较之前存放的时间:%@",tempStrTag); + if (timeInterval == 0) { [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:tempStrTag]; - return YES;//时间设置为0,表示刷新标志时间,返回成功 + return YES; } if (!str) { [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:tempStrTag]; - return YES;//第一次调用 + return YES; } NSTimeInterval time = [nowDate timeIntervalSinceDate:[self DateInitWithString:str dateFormatterStr:nil]]; -// NSLog(@"比较相差的时间:%f",time); + if (time > timeInterval) { [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:tempStrTag]; return YES; @@ -109,7 +107,6 @@ static NSDateFormatter *simgle_df; NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults]; - //记录分组 NSArray *temp = [defaults valueForKey:@"bs_timesGroup"]; NSMutableArray *resultArr = [NSMutableArray arrayWithArray:temp]; NSString *keyStr = [NSString stringWithFormat:@"bs_timeGroup_%@_%@",group,tag]; @@ -119,22 +116,21 @@ static NSDateFormatter *simgle_df; } - NSString *str = [defaults valueForKey:keyStr]; NSDate *nowDate = [NSDate date]; - // NSLog(@"比较之前存放的时间:%@",tempStrTag); + if (timeInterval == 0) { [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:keyStr]; - return YES;//时间设置为0,表示刷新标志时间,返回成功 + return YES; } if (!str) { [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:keyStr]; - return YES;//第一次调用 + return YES; } NSTimeInterval time = [nowDate timeIntervalSinceDate:[self DateInitWithString:str dateFormatterStr:nil]]; - // NSLog(@"比较相差的时间:%f",time); + if (time > timeInterval) { [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:keyStr]; return YES; @@ -179,7 +175,6 @@ static NSDateFormatter *simgle_df; } - #pragma mark - 计算事件差,需要同格式的字符串 +(NSTimeInterval)TimeDifferenceWithTime1:(NSString *)time1 AndTime2:(NSString *)time2 formet:(NSString *)formet{ @@ -196,7 +191,7 @@ static NSDateFormatter *simgle_df; tomorrow = [today dateByAddingTimeInterval: secondsPerDay]; yesterday = [today dateByAddingTimeInterval: -secondsPerDay]; - // 10 first characters of description is the calendar date: + NSString * todayString = [[today description] substringToIndex:10]; NSString * yesterdayString = [[yesterday description] substringToIndex:10]; NSString * tomorrowString = [[tomorrow description] substringToIndex:10]; diff --git a/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m.backup b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m.backup new file mode 100644 index 0000000..8d8fd38 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BSXWDateUtil.m.backup @@ -0,0 +1,222 @@ +// +// XWDateUtil.m +// FrameObject +// +// Created by shenba on 16/4/12. +// Copyright © 2016年 xiaowen. All rights reserved. +// + +#import "BSXWDateUtil.h" + +@implementation BSXWDateUtil + +static NSDateFormatter *simgle_df; + +#pragma mark - 获取多少天,多少小时,多少分钟,多少秒之后的时间 ++(NSString *)getTimeAfterDay:(int)day hours:(int)hours min:(int)min ss:(int)ss fromDate:(NSDate *)date withForMet:(NSString *)forMet{ + + if (date==nil) { + date = [NSDate date]; + } + + NSDate *resultDate = [[NSDate alloc]initWithTimeInterval:(24 * 60 * 60)*day+(60*60)*hours+min*60+ss sinceDate:date]; + + return [self strWithDate:resultDate withForMet:forMet]; + +} + + +#pragma mark - 时间转字符串 ++(NSString *)strWithDate:(NSDate *)date withForMet:(NSString *)forMet{ + + if (date == nil) { + date = [NSDate date]; + } + if (forMet==nil) { + if (!simgle_df) { + simgle_df = [[NSDateFormatter alloc]init];//格式化 + [simgle_df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//simgle_df保持这个格式,避免多线程调用的时候变化dateFormat造成其他的影响 + } + return [simgle_df stringFromDate:date]; + } + + NSDateFormatter*df = [[NSDateFormatter alloc]init];//格式化 + [df setDateFormat:forMet]; + return [df stringFromDate:date]; + +} + +#pragma mark - 字符串转时间 ++(NSDate *)DateInitWithString:(NSString *)dateStr dateFormatterStr:(NSString *)dateFormatterStr +{ + if (!dateStr) { + return [NSDate date]; + } + + if (dateFormatterStr == nil) { + if (!simgle_df) { + simgle_df = [[NSDateFormatter alloc]init];//格式化 + [simgle_df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//simgle_df保持这个格式,避免多线程调用的时候变化dateFormat造成其他的影响 + } + return [simgle_df dateFromString:dateStr]; + } + + + NSDate *reslutDate = nil; + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; + [formatter setDateFormat:dateFormatterStr]; + reslutDate = [formatter dateFromString:dateStr];//得到时间 + return reslutDate; +} + + +#pragma mark - 判断是否超过某个时间段 timeInterval:单位秒 ++(Boolean)isTimeOver:(int)timeInterval withTag:(NSString *)tag{ + + + NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults]; + NSString *tempStrTag = [NSString stringWithFormat:@"bs_timesover_%@",tag]; + NSString *str = [defaults valueForKey:tempStrTag]; + NSDate *nowDate = [NSDate date]; +// NSLog(@"比较之前存放的时间:%@",tempStrTag); + if (timeInterval == 0) { + [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:tempStrTag]; + return YES;//时间设置为0,表示刷新标志时间,返回成功 + } + if (!str) { + [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:tempStrTag]; + return YES;//第一次调用 + } + + + NSTimeInterval time = [nowDate timeIntervalSinceDate:[self DateInitWithString:str dateFormatterStr:nil]]; +// NSLog(@"比较相差的时间:%f",time); + if (time > timeInterval) { + [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:tempStrTag]; + return YES; + } + return NO; +} + + +#pragma mark - 判断是否超过某个时间段 timeInterval:单位秒 分组处理 ++(Boolean)isTimeOver:(int)timeInterval withTag:(NSString *)tag withGroup:(NSString *)group{ + + if (group == nil || tag == nil) { + return YES; + } + + NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults]; + + + //记录分组 + NSArray *temp = [defaults valueForKey:@"bs_timesGroup"]; + NSMutableArray *resultArr = [NSMutableArray arrayWithArray:temp]; + NSString *keyStr = [NSString stringWithFormat:@"bs_timeGroup_%@_%@",group,tag]; + if (![resultArr containsObject:keyStr]) { + [resultArr addObject:keyStr]; + [defaults setValue:resultArr forKey:@"bs_timesGroup"]; + } + + + + NSString *str = [defaults valueForKey:keyStr]; + NSDate *nowDate = [NSDate date]; + // NSLog(@"比较之前存放的时间:%@",tempStrTag); + if (timeInterval == 0) { + [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:keyStr]; + return YES;//时间设置为0,表示刷新标志时间,返回成功 + } + if (!str) { + [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:keyStr]; + return YES;//第一次调用 + } + + + NSTimeInterval time = [nowDate timeIntervalSinceDate:[self DateInitWithString:str dateFormatterStr:nil]]; + // NSLog(@"比较相差的时间:%f",time); + if (time > timeInterval) { + [defaults setValue:[self strWithDate:nowDate withForMet:nil] forKey:keyStr]; + return YES; + } + return NO; +} + +#pragma mark - 清除记录标记的时间 ++(void)removeTimeOverTag:(NSString *)tag{ + + if (tag == nil) { + return; + } + + NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults]; + NSString *tempStrTag = [NSString stringWithFormat:@"bs_timesover_%@",tag]; + [defaults removeObjectForKey:tempStrTag]; +} +#pragma mark - 按照分组清除记录标记的时间 ++(void)removeTimeOverGroup:(NSString *)group{ + + if (group == nil) { + return; + } + + NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults]; + + NSMutableArray *resultArr = [NSMutableArray array]; + NSArray *temp = [defaults valueForKey:@"bs_timesGroup"]; + Boolean isChange = NO; + for (NSString *str in temp) { + if ([str hasPrefix:[NSString stringWithFormat:@"bs_timeGroup_%@_",group]]) { + [defaults removeObjectForKey:str]; + isChange = YES; + }else{ + [resultArr addObject:str]; + } + } + if (isChange) { + [defaults setValue:resultArr forKey:@"bs_timesGroup"]; + } +} + + + +#pragma mark - 计算事件差,需要同格式的字符串 ++(NSTimeInterval)TimeDifferenceWithTime1:(NSString *)time1 AndTime2:(NSString *)time2 formet:(NSString *)formet{ + + return [[self DateInitWithString:time1 dateFormatterStr:formet] timeIntervalSinceDate:[self DateInitWithString:time2 dateFormatterStr:formet]]; +} + + +#pragma mark - ios判断是昨天,今天,还是明天 ++(NSString *)compareDate:(NSDate *)date{ + + NSTimeInterval secondsPerDay = 24 * 60 * 60; + NSDate *today = [[NSDate alloc] init]; + NSDate *tomorrow, *yesterday; + + tomorrow = [today dateByAddingTimeInterval: secondsPerDay]; + yesterday = [today dateByAddingTimeInterval: -secondsPerDay]; + // 10 first characters of description is the calendar date: + NSString * todayString = [[today description] substringToIndex:10]; + NSString * yesterdayString = [[yesterday description] substringToIndex:10]; + NSString * tomorrowString = [[tomorrow description] substringToIndex:10]; + + NSString * dateString = [[date description] substringToIndex:10]; + + if ([dateString isEqualToString:todayString]) + { + return @"今天"; + } else if ([dateString isEqualToString:yesterdayString]) + { + return @"昨天"; + }else if ([dateString isEqualToString:tomorrowString]) + { + return @"明天"; + } + else + { + return dateString; + } +} + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h index 5f2d3ce..6a79db9 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h +++ b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h @@ -1,10 +1,8 @@ -// -// BS_UIColor.h -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import #import diff --git a/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h.backup b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h.backup new file mode 100644 index 0000000..5f2d3ce --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.h.backup @@ -0,0 +1,16 @@ +// +// BS_UIColor.h +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import +#import + +@interface BS_UIColor : NSObject + ++ (UIColor *) stringTOColor:(NSString *)str; + +@end diff --git a/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m index a24c749..8c56de7 100644 --- a/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m +++ b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m @@ -1,10 +1,8 @@ -// -// BS_UIColor.m -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import "BS_UIColor.h" diff --git a/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m.backup b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m.backup new file mode 100644 index 0000000..a24c749 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/Util/BS_UIColor.m.backup @@ -0,0 +1,31 @@ +// +// BS_UIColor.m +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import "BS_UIColor.h" + +@implementation BS_UIColor + ++ (UIColor *) stringTOColor:(NSString *)str +{ + if (!str || [str isEqualToString:@""]) { + return nil; + } + unsigned red,green,blue; + NSRange range; + range.length = 2; + range.location = 1; + [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&red]; + range.location = 3; + [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&green]; + range.location = 5; + [[NSScanner scannerWithString:[str substringWithRange:range]] scanHexInt:&blue]; + UIColor *color= [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1]; + return color; +} + +@end diff --git a/YuMi/Tools/sdkContent/catagory/system/BS_Define.h b/YuMi/Tools/sdkContent/catagory/system/BS_Define.h index f3e2b78..e58fc55 100644 --- a/YuMi/Tools/sdkContent/catagory/system/BS_Define.h +++ b/YuMi/Tools/sdkContent/catagory/system/BS_Define.h @@ -1,10 +1,8 @@ -// -// BS_Define.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/16. // Copyright © 2016年 xw.com. All rights reserved. -// + #define GET_X(view) view.frame.origin.x #define GET_Y(view) view.frame.origin.y @@ -19,13 +17,9 @@ #define Set_frame2(tempView,a,b,c,d) CGRect bs_tempRect = tempView.frame;bs_tempRect.origin.x = a;bs_tempRect.origin.y = b;bs_tempRect.size.width = c;bs_tempRect.size.height = d;tempView.frame = bs_tempRect; - #define USER_LANGUAGE @"user_language" - - -//判断ios系统版本 #define IOS7 ([[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 ? YES:NO) #define IOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ? YES:NO) #define IOS9 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0 ? YES:NO) diff --git a/YuMi/Tools/sdkContent/catagory/system/BS_Define.h.backup b/YuMi/Tools/sdkContent/catagory/system/BS_Define.h.backup new file mode 100644 index 0000000..f3e2b78 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/system/BS_Define.h.backup @@ -0,0 +1,32 @@ +// +// BS_Define.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/16. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#define GET_X(view) view.frame.origin.x +#define GET_Y(view) view.frame.origin.y +#define GET_W(view) view.frame.size.width +#define GET_H(view) view.frame.size.height + +#define GET_X_Max(view) view.frame.origin.x + view.frame.size.width +#define GET_Y_Max(view) view.frame.origin.y + view.frame.size.height + +#define Set_frame(tempView,a,b) CGRect bs_tempRect = tempView.frame;bs_tempRect.origin.x = a;bs_tempRect.origin.y = b;tempView.frame = bs_tempRect; + +#define Set_frame2(tempView,a,b,c,d) CGRect bs_tempRect = tempView.frame;bs_tempRect.origin.x = a;bs_tempRect.origin.y = b;bs_tempRect.size.width = c;bs_tempRect.size.height = d;tempView.frame = bs_tempRect; + + + +#define USER_LANGUAGE @"user_language" + + + + +//判断ios系统版本 +#define IOS7 ([[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 ? YES:NO) +#define IOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ? YES:NO) +#define IOS9 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0 ? YES:NO) +#define IOS10 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0 ? YES:NO) diff --git a/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h index a389567..d95e24e 100644 --- a/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h +++ b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h @@ -1,18 +1,14 @@ -// -// SystemUtil.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/11/10. // Copyright © 2016年 xw.com. All rights reserved. -// + #import @interface SystemUtil : PIBaseModel -/* - * 获取项目名 - */ + +(NSString *)getProjectName; @end diff --git a/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h.backup b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h.backup new file mode 100644 index 0000000..a389567 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.h.backup @@ -0,0 +1,18 @@ +// +// SystemUtil.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/11/10. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + +@interface SystemUtil : PIBaseModel + +/* + * 获取项目名 + */ ++(NSString *)getProjectName; + +@end diff --git a/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m index 6672fee..91aeba5 100644 --- a/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m +++ b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m @@ -1,10 +1,8 @@ -// -// SystemUtil.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/11/10. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "SystemUtil.h" @@ -15,21 +13,9 @@ NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; - return [infoDictionary objectForKey:(NSString *)kCFBundleExecutableKey]; //获取项目名称 + return [infoDictionary objectForKey:(NSString *)kCFBundleExecutableKey]; } @end - - -// -// -// -// -// -// -// -// - -// diff --git a/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m.backup b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m.backup new file mode 100644 index 0000000..6672fee --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/system/SystemUtil.m.backup @@ -0,0 +1,35 @@ +// +// SystemUtil.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/11/10. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "SystemUtil.h" + +@implementation SystemUtil + + ++(NSString *)getProjectName{ + + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; + + return [infoDictionary objectForKey:(NSString *)kCFBundleExecutableKey]; //获取项目名称 + +} + +@end + + + +// +// +// +// +// +// +// +// + +// diff --git a/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h index d1e9c18..6443c53 100755 --- a/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h +++ b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h @@ -1,21 +1,15 @@ -// -// UILabel+YBAttributeTextTapAction.h -// + + // Created by LYB on 16/7/1. // Copyright © 2016年 LYB. All rights reserved. -// + #import @protocol YBAttributeTapActionDelegate @optional -/** - * YBAttributeTapActionDelegate - * - * @param string 点击的字符串 - * @param range 点击的字符串range - * @param index 点击的字符在数组中的index - */ + + - (void)yb_attributeTapReturnString:(NSString *)string range:(NSRange)range index:(NSInteger)index; @@ -30,31 +24,16 @@ @end - - - @interface UILabel (YBAttributeTextTapAction) -/** - * 是否打开点击效果,默认是打开 - */ + @property (nonatomic, assign) BOOL enabledTapEffect; -/** - * 给文本添加点击事件Block回调 - * - * @param strings 需要添加的字符串数组 - * @param tapClick 点击事件回调 - */ + - (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings tapClicked:(void (^) (NSString *string , NSRange range , NSInteger index))tapClick; -/** - * 给文本添加点击事件delegate回调 - * - * @param strings 需要添加的字符串数组 - * @param delegate delegate - */ + - (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings delegate:(id )delegate; diff --git a/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h.backup b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h.backup new file mode 100755 index 0000000..d1e9c18 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.h.backup @@ -0,0 +1,62 @@ +// +// UILabel+YBAttributeTextTapAction.h +// +// Created by LYB on 16/7/1. +// Copyright © 2016年 LYB. All rights reserved. +// + +#import + +@protocol YBAttributeTapActionDelegate +@optional +/** + * YBAttributeTapActionDelegate + * + * @param string 点击的字符串 + * @param range 点击的字符串range + * @param index 点击的字符在数组中的index + */ +- (void)yb_attributeTapReturnString:(NSString *)string + range:(NSRange)range + index:(NSInteger)index; +@end + +@interface YBAttributeModel : PIBaseModel + +@property (nonatomic, copy) NSString *str; + +@property (nonatomic, assign) NSRange range; + +@end + + + + + +@interface UILabel (YBAttributeTextTapAction) + +/** + * 是否打开点击效果,默认是打开 + */ +@property (nonatomic, assign) BOOL enabledTapEffect; + +/** + * 给文本添加点击事件Block回调 + * + * @param strings 需要添加的字符串数组 + * @param tapClick 点击事件回调 + */ +- (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings + tapClicked:(void (^) (NSString *string , NSRange range , NSInteger index))tapClick; + +/** + * 给文本添加点击事件delegate回调 + * + * @param strings 需要添加的字符串数组 + * @param delegate delegate + */ +- (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings + delegate:(id )delegate; + +@end + diff --git a/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m index fa502e6..058f7e1 100755 --- a/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m +++ b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m @@ -1,9 +1,8 @@ -// -// UILabel+YBAttributeTextTapAction.m -// + + // Created by LYB on 16/7/1. // Copyright © 2016年 LYB. All rights reserved. -// + #import "UILabel+YBAttributeTextTapAction.h" #import diff --git a/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m.backup b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m.backup new file mode 100755 index 0000000..fa502e6 --- /dev/null +++ b/YuMi/Tools/sdkContent/catagory/system/UILabel+YBAttributeTextTapAction.m.backup @@ -0,0 +1,396 @@ +// +// UILabel+YBAttributeTextTapAction.m +// +// Created by LYB on 16/7/1. +// Copyright © 2016年 LYB. All rights reserved. +// + +#import "UILabel+YBAttributeTextTapAction.h" +#import +#import +#import + +@implementation YBAttributeModel + +@end + +@implementation UILabel (YBAttributeTextTapAction) + +#pragma mark - AssociatedObjects + +- (NSMutableArray *)siefnsufwhf +{ + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setSiefnsufwhf:(NSMutableArray *)siefnsufwhf +{ + objc_setAssociatedObject(self, @selector(siefnsufwhf), siefnsufwhf, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSMutableDictionary *)siefidshfiwhi +{ + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setSiefidshfiwhi:(NSMutableDictionary *)siefidshfiwhi +{ + objc_setAssociatedObject(self, @selector(siefidshfiwhi), siefidshfiwhi, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (BOOL)isTapAction +{ + return [objc_getAssociatedObject(self, _cmd) boolValue]; +} + +- (void)setIsTapAction:(BOOL)isTapAction +{ + objc_setAssociatedObject(self, @selector(isTapAction), @(isTapAction), OBJC_ASSOCIATION_ASSIGN); +} + +- (void (^)(NSString *, NSRange, NSInteger))tapBlock +{ + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setTapBlock:(void (^)(NSString *, NSRange, NSInteger))tapBlock +{ + objc_setAssociatedObject(self, @selector(tapBlock), tapBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (id)delegate +{ + return objc_getAssociatedObject(self, _cmd); +} + +- (BOOL)enabledTapEffect +{ + return [objc_getAssociatedObject(self, _cmd) boolValue]; +} + +- (void)setEnabledTapEffect:(BOOL)enabledTapEffect +{ + objc_setAssociatedObject(self, @selector(enabledTapEffect), @(enabledTapEffect), OBJC_ASSOCIATION_ASSIGN); + self.isTapEffect = enabledTapEffect; +} + +- (BOOL)isTapEffect +{ + return [objc_getAssociatedObject(self, _cmd) boolValue]; +} + +- (void)setIsTapEffect:(BOOL)isTapEffect +{ + objc_setAssociatedObject(self, @selector(isTapEffect), @(isTapEffect), OBJC_ASSOCIATION_ASSIGN); +} + +- (void)setDelegate:(id)delegate +{ + objc_setAssociatedObject(self, @selector(delegate), delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +#pragma mark - mainFunction +- (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings tapClicked:(void (^) (NSString *string , NSRange range , NSInteger index))tapClick +{ + [self yb_getRangesWithStrings:strings]; + + if (self.tapBlock != tapClick) { + self.tapBlock = tapClick; + } +} + +- (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings + delegate:(id )delegate +{ + [self yb_getRangesWithStrings:strings]; + + if (self.delegate != delegate) { + self.delegate = delegate; + } +} + +#pragma mark - touchAction +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (!self.isTapAction) { + return; + } + + if (objc_getAssociatedObject(self, @selector(enabledTapEffect))) { + self.isTapEffect = self.enabledTapEffect; + } + + UITouch *touch = [touches anyObject]; + + CGPoint point = [touch locationInView:self]; + + __weak typeof(self) weakSelf = self; + + [self yb_getTapFrameWithTouchPoint:point result:^(NSString *string, NSRange range, NSInteger index) { + + if (weakSelf.tapBlock) { + weakSelf.tapBlock (string , range , index); + } + + if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(yb_attributeTapReturnString:range:index:)]) { + [weakSelf.delegate yb_attributeTapReturnString:string range:range index:index]; + } + + if (self.isTapEffect) { + + [self yb_saveEffectDicWithRange:range]; + + [self yb_tapEffectWithStatus:NO]; + } + + }]; +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + + if (self.isTapAction) { + if ([self yb_getTapFrameWithTouchPoint:point result:nil]) { + return self; + } + } + return [super hitTest:point withEvent:event]; +} + +#pragma mark - getTapFrame +- (BOOL)yb_getTapFrameWithTouchPoint:(CGPoint)point result:(void (^) (NSString *string , NSRange range , NSInteger index))resultBlock +{ + CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attributedText); + + CGMutablePathRef Path = CGPathCreateMutable(); + + CGPathAddRect(Path, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)); + + CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL); + + CFRange range = CTFrameGetVisibleStringRange(frame); + + if (self.attributedText.length > range.length) { + + UIFont *font ; + + if ([self.attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:nil]) { + + font = [self.attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:nil]; + + }else if (self.font){ + font = self.font; + + }else { + font = [UIFont systemFontOfSize:17]; + } + + CGPathRelease(Path); + + Path = CGPathCreateMutable(); + + CGPathAddRect(Path, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height + font.lineHeight)); + + frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL); + } + + CFArrayRef lines = CTFrameGetLines(frame); + + if (!lines) { + CFRelease(frame); + CFRelease(framesetter); + CGPathRelease(Path); + return NO; + } + + CFIndex count = CFArrayGetCount(lines); + + CGPoint origins[count]; + + CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins); + + CGAffineTransform transform = [self yb_transformForCoreText]; + + CGFloat verticalOffset = 0; + + for (CFIndex i = 0; i < count; i++) { + CGPoint linePoint = origins[i]; + + CTLineRef line = CFArrayGetValueAtIndex(lines, i); + + CGRect flippedRect = [self yb_getLineBounds:line point:linePoint]; + + CGRect rect = CGRectApplyAffineTransform(flippedRect, transform); + + rect = CGRectInset(rect, 0, 0); + + rect = CGRectOffset(rect, 0, verticalOffset); + + NSParagraphStyle *style = [self.attributedText attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:nil]; + + CGFloat lineSpace; + + if (style) { + lineSpace = style.lineSpacing; + }else { + lineSpace = 0; + } + + CGFloat lineOutSpace = (self.bounds.size.height - lineSpace * (count - 1) -rect.size.height * count) / 2; + + rect.origin.y = lineOutSpace + rect.size.height * i + lineSpace * i; + + if (CGRectContainsPoint(rect, point)) { + + CGPoint relativePoint = CGPointMake(point.x - CGRectGetMinX(rect), point.y - CGRectGetMinY(rect)); + + CFIndex index = CTLineGetStringIndexForPosition(line, relativePoint); + + CGFloat offset; + + CTLineGetOffsetForStringIndex(line, index, &offset); + + if (offset > relativePoint.x) { + index = index - 1; + } + + NSInteger link_count = self.siefnsufwhf.count; + + for (int j = 0; j < link_count; j++) { + + YBAttributeModel *model = self.siefnsufwhf[j]; + + NSRange link_range = model.range; + if (NSLocationInRange(index, link_range)) { + if (resultBlock) { + resultBlock (model.str , model.range , (NSInteger)j); + } + CFRelease(frame); + CFRelease(framesetter); + CGPathRelease(Path); + return YES; + } + } + } + } + CFRelease(frame); + CFRelease(framesetter); + CGPathRelease(Path); + return NO; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.isTapEffect) { + + [self performSelectorOnMainThread:@selector(yb_tapEffectWithStatus:) withObject:nil waitUntilDone:NO]; + + } +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.isTapEffect) { + + [self performSelectorOnMainThread:@selector(yb_tapEffectWithStatus:) withObject:nil waitUntilDone:NO]; + + } +} + +- (CGAffineTransform)yb_transformForCoreText +{ + return CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f); +} + +- (CGRect)yb_getLineBounds:(CTLineRef)line point:(CGPoint)point +{ + CGFloat ascent = 0.0f; + CGFloat descent = 0.0f; + CGFloat leading = 0.0f; + CGFloat width = (CGFloat)CTLineGetTypographicBounds(line, &ascent, &descent, &leading); + CGFloat height = ascent + fabs(descent) + leading; + + return CGRectMake(point.x, point.y , width, height); +} + +#pragma mark - tapEffect +- (void)yb_tapEffectWithStatus:(BOOL)status +{ + if (self.isTapEffect) { + NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText]; + + NSMutableAttributedString *subAtt = [[NSMutableAttributedString alloc] initWithAttributedString:[[self.siefidshfiwhi allValues] firstObject]]; + + NSRange range = NSRangeFromString([[self.siefidshfiwhi allKeys] firstObject]); + + if (status) { + [subAtt addAttribute:NSBackgroundColorAttributeName value:[UIColor lightGrayColor] range:NSMakeRange(0, subAtt.string.length)]; + + [attStr replaceCharactersInRange:range withAttributedString:subAtt]; + }else { + + [attStr replaceCharactersInRange:range withAttributedString:subAtt]; + } + self.attributedText = attStr; + } +} + +- (void)yb_saveEffectDicWithRange:(NSRange)range +{ + self.siefidshfiwhi = [NSMutableDictionary dictionary]; + + NSAttributedString *subAttribute = [self.attributedText attributedSubstringFromRange:range]; + + [self.siefidshfiwhi setObject:subAttribute forKey:NSStringFromRange(range)]; +} + +#pragma mark - getRange +- (void)yb_getRangesWithStrings:(NSArray *)strings +{ + if (self.attributedText == nil) { + self.isTapAction = NO; + return; + } + + self.isTapAction = YES; + + self.isTapEffect = YES; + + __block NSString *totalStr = self.attributedText.string; + + self.siefnsufwhf = [NSMutableArray array]; + + __weak typeof(self) weakSelf = self; + + [strings enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + + NSRange range = [totalStr rangeOfString:obj]; + + if (range.length != 0) { + + totalStr = [totalStr stringByReplacingCharactersInRange:range withString:[weakSelf yb_getStringWithRange:range]]; + + YBAttributeModel *model = [YBAttributeModel new]; + + model.range = range; + + model.str = obj; + + [weakSelf.siefnsufwhf addObject:model]; + + } + + }]; +} + +- (NSString *)yb_getStringWithRange:(NSRange)range +{ + NSMutableString *string = [NSMutableString string]; + + for (int i = 0; i < range.length ; i++) { + + [string appendString:@" "]; + } + return string; +} + +@end diff --git a/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h index b77c4c3..9b9d72a 100644 --- a/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h +++ b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h @@ -1,32 +1,20 @@ -// -// GWFileOptionModel.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/29. // Copyright © 2016年 xw.com. All rights reserved. -// + #import @interface BSFileOptionModel : PIBaseModel - -//写入数据 +(void)writeToFile_RecordModel:(NSArray *)logArray stringForMatBlock:( NSString*(^)( NSString *forMatString) )forMatblock withCompletion:( NSString*(^)( NSString *logString) )block class:(Class)class1; -/* - * 压缩当天产生的日志文件zip文件: - * 1:如果当天没有日志文件,返回空; - * 2:如果没有实现压缩zip的方法,返回日志的位置路径; - * 3:如果实现了压缩文件的方法,返回日志压缩后的位置路径. - * - */ + +(NSString *)compression:(void(^)( NSString *logPath))block; - -//删除所有日志数据 +(void)deleteFilePathLog; @end diff --git a/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h.backup b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h.backup new file mode 100644 index 0000000..b77c4c3 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.h.backup @@ -0,0 +1,32 @@ +// +// GWFileOptionModel.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/29. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + +@interface BSFileOptionModel : PIBaseModel + + + +//写入数据 ++(void)writeToFile_RecordModel:(NSArray *)logArray stringForMatBlock:( NSString*(^)( NSString *forMatString) )forMatblock withCompletion:( NSString*(^)( NSString *logString) )block class:(Class)class1; + +/* + * 压缩当天产生的日志文件zip文件: + * 1:如果当天没有日志文件,返回空; + * 2:如果没有实现压缩zip的方法,返回日志的位置路径; + * 3:如果实现了压缩文件的方法,返回日志压缩后的位置路径. + * + */ ++(NSString *)compression:(void(^)( NSString *logPath))block; + + + +//删除所有日志数据 ++(void)deleteFilePathLog; + +@end diff --git a/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m index 800b94a..fc7d299 100644 --- a/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m +++ b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m @@ -1,14 +1,12 @@ -// -// FileOptionModel.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/29. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSFileOptionModel.h" #import "BSRecordModel.h" -#import // 导入运行时文件 +#import #define BS_DocumentPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] @@ -19,11 +17,8 @@ @implementation BSFileOptionModel - - - +(void)writeToFile_RecordModel:(NSArray *)logArray stringForMatBlock:( NSString*(^)( NSString *forMatString) )forMatblock withCompletion:( NSString*(^)( NSString *logString) )block class:(Class)class1{ - //日志文件夹 + NSString *logFile = BS_LogFilePath; if (![[NSFileManager defaultManager] fileExistsAtPath:logFile]) { [[NSFileManager defaultManager] createDirectoryAtPath:logFile withIntermediateDirectories:YES attributes:nil error:nil]; @@ -33,16 +28,15 @@ } - //日志txt文件 NSString *logTxtPath = [NSString stringWithFormat:@"%@/%@.txt", logFile,[self currentTime]]; if (![[NSFileManager defaultManager] fileExistsAtPath:logTxtPath]) { [[NSFileManager defaultManager] createFileAtPath:logTxtPath contents:nil attributes:nil]; } -// NSLog(@"logTxtPath = %@",logTxtPath); - //写入日志头 + + NSError *error; NSString *logHead = [NSString stringWithFormat:@"日志协议类型:1,写入时间:%@\n",[self currentTime2]]; - BOOL flag = [logHead writeToFile:logTxtPath atomically:YES encoding:NSUTF8StringEncoding error:&error];//一般error都设置为nil,保证写入成功 + BOOL flag = [logHead writeToFile:logTxtPath atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (flag) { NSLog(@"写入文件头成功"); } @@ -51,7 +45,6 @@ } - @autoreleasepool { NSString *str = @"类型编码:[coding] 类型:ddd 描述:[describe] 关键字:[keyword] 结果:[result] 操作编码:[optionCoding]\n"; if (forMatblock) { @@ -91,23 +84,14 @@ } - - } -/* - * 压缩当天产生的日志文件zip文件: - * 1:如果当天没有日志文件,返回空; - * 2:如果没有实现压缩zip的方法,返回日志的位置路径; - * 3:如果实现了压缩文件的方法,返回日志压缩后的位置路径. - * - */ +(NSString *)compression:(void(^)( NSString *logPath))block{ - //压缩 + NSString *logTextPath = [NSString stringWithFormat:@"%@/%@.txt", BS_LogFilePath,[self currentTime]]; if (![[NSFileManager defaultManager] fileExistsAtPath:logTextPath]) { - //文件不存在 + return nil; } @@ -126,17 +110,17 @@ + (instancetype)getProperties:(Class)cls{ - // 获取当前类的所有属性 - unsigned int count;// 记录属性个数 + + unsigned int count; objc_property_t *properties = class_copyPropertyList(cls, &count); - // 遍历 + NSMutableArray *mArray = [NSMutableArray array]; for (int i = 0; i < count; i++) { - // objc_property_t 属性类型 + objc_property_t property = properties[i]; - // 获取属性的名称 C语言字符串 + const char *cName = property_getName(property); - // 转换为Objective C 字符串 + NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding]; [mArray addObject:name]; } @@ -144,12 +128,12 @@ return mArray.copy; } -//获取当前时间 + +(NSString *)currentTime{ return [self getTimeStr:@"YYYY-MM-dd"]; } -//获取当前时间 + +(NSString *)currentTime2{ return [self getTimeStr:@"YYYY-MM-dd HH:mm:ss:SSS"]; } @@ -158,18 +142,17 @@ +(NSString *)getTimeStr:(NSString *)forMet{ NSDate * currentTime=[NSDate date]; NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init]; - [dateformatter setDateFormat:forMet];// + [dateformatter setDateFormat:forMet]; NSString *currentTimeStr=[dateformatter stringFromDate:currentTime]; return currentTimeStr; } - #pragma mark - 删除的方法 +(void)deleteFilePathLog{ NSFileManager *fileManager = [NSFileManager defaultManager]; - [self deleteFilePath:BS_LogFilePath fileManager:fileManager];//删除普通文件 - [self deleteFilePath:BS_LogZipFilePath fileManager:fileManager];//删除压缩文件 + [self deleteFilePath:BS_LogFilePath fileManager:fileManager]; + [self deleteFilePath:BS_LogZipFilePath fileManager:fileManager]; } +(void)deleteFilePath:(NSString *)path fileManager:(NSFileManager *)fileManager{ diff --git a/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m.backup b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m.backup new file mode 100644 index 0000000..800b94a --- /dev/null +++ b/YuMi/Tools/sdkContent/content/FileOption(文件操作)/BSFileOptionModel.m.backup @@ -0,0 +1,206 @@ +// +// FileOptionModel.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/29. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSFileOptionModel.h" +#import "BSRecordModel.h" +#import // 导入运行时文件 + +#define BS_DocumentPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] + +#define BS_LogFilePath [NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0],@"GWLogFile"] + +#define BS_LogZipFilePath [NSString stringWithFormat:@"%@/%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0],@"GWLogFileZip"] + +@implementation BSFileOptionModel + + + + + ++(void)writeToFile_RecordModel:(NSArray *)logArray stringForMatBlock:( NSString*(^)( NSString *forMatString) )forMatblock withCompletion:( NSString*(^)( NSString *logString) )block class:(Class)class1{ + //日志文件夹 + NSString *logFile = BS_LogFilePath; + if (![[NSFileManager defaultManager] fileExistsAtPath:logFile]) { + [[NSFileManager defaultManager] createDirectoryAtPath:logFile withIntermediateDirectories:YES attributes:nil error:nil]; + } else { + + NSLog(@"FileDir is exists."); + } + + + //日志txt文件 + NSString *logTxtPath = [NSString stringWithFormat:@"%@/%@.txt", logFile,[self currentTime]]; + if (![[NSFileManager defaultManager] fileExistsAtPath:logTxtPath]) { + [[NSFileManager defaultManager] createFileAtPath:logTxtPath contents:nil attributes:nil]; + } +// NSLog(@"logTxtPath = %@",logTxtPath); + //写入日志头 + NSError *error; + NSString *logHead = [NSString stringWithFormat:@"日志协议类型:1,写入时间:%@\n",[self currentTime2]]; + BOOL flag = [logHead writeToFile:logTxtPath atomically:YES encoding:NSUTF8StringEncoding error:&error];//一般error都设置为nil,保证写入成功 + if (flag) { + NSLog(@"写入文件头成功"); + } + else{ + NSLog(@"写入文件头失败"); + } + + + + @autoreleasepool { + NSString *str = @"类型编码:[coding] 类型:ddd 描述:[describe] 关键字:[keyword] 结果:[result] 操作编码:[optionCoding]\n"; + if (forMatblock) { + str = forMatblock(str); + } + id log; + NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:logTxtPath]; + for (int i = 0 ; i #import @@ -12,79 +10,32 @@ @interface BSDrawLine : NSObject -/* - * 设置坐标系数据 - */ -(void)initSettingXuint:(CGFloat)xunit xBegin:(CGFloat)xBegin yUint:(CGFloat)yUint yBegain:(CGFloat)yBegain; -/* - * 设置坐标原点 - */ + + -(void)initPoint:(CGPoint)point; -/** - 设置阴线阳线的颜色,是否实心 - @param color 阳线颜色 - @param color2 阴线颜色 - @param isYangLineSolid 阳线是否实心 - @param isYinLineSolid 阴线是否实心 - . - */ -(void)initYangLineColor:(UIColor *)color YinLineColor:(UIColor *)color2 isYangLineSolid:(Boolean)isYangLineSolid isYinLineSolid:(Boolean)isYinLineSolid; - -/** - 画k图 - - @param arr arr数组长度要>=5 [最大值,最小值,开盘值,收盘值,x坐标,...] - @param ctx CGContextRef画笔对象 - @param scan 放大比例 - */ -(void)drawKline:(NSArray *)arr withContext:(CGContextRef)contex scan:(CGFloat)scan; #pragma mark - 类方法 -/** - 画直线 - [self.myDraw drawLinePoint:@[@[lineWidthStr,@"185",@"185",@"15",@"1"],@[temp5,temp6]] withContext:UIGraphicsGetCurrentContext()]; - @param arr2 [[粗细,颜色r,颜色g,颜色b,透明度],[第一条线[第一个点],[第二个点]...],[第二条线]......] - @param ctx CGContextRef画笔对象 - @param scan 放大比例 - */ +(void)drawLinePoint:(NSArray *)arr2 withContext:(CGContextRef)context scan:(CGFloat)scan; -/** - 画曲线 - @param lineArr [[线宽,点size,颜色],[第一条线[第一个点],[第二个点]...],[第二条线]...] - @param ctx CGContextRef画笔对象 - @param scan 放大比例 - */ + +(void)drawCurves:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan; -/** - 画多个多边形 - @param lineArr [[线宽,线颜色,填充颜色],[第一个多边形[第一个点],[第二个点]...],[第二个多边形]...] - @param ctx CGContextRef画笔对象 - @param scan 放大比例 - */ +(void)drawMoreRects:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan; #pragma mark - 字体类相关 -/** - 富文本字体 - @param str 字符串 - @param size 字体范围 - @param point 中心点位置 - @param font 字体大小 - @param color 字体颜色 - */ +(void)drawWord:(NSString *)str size:(CGSize)size centerPoint:(CGPoint)point font:(CGFloat)font color:(UIColor *)color; - @end diff --git a/YuMi/Tools/sdkContent/content/K/BSDrawLine.h.backup b/YuMi/Tools/sdkContent/content/K/BSDrawLine.h.backup new file mode 100644 index 0000000..468e208 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/K/BSDrawLine.h.backup @@ -0,0 +1,90 @@ +// +// GWDrawLine.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/9/26. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import + +@interface BSDrawLine : NSObject + + +/* + * 设置坐标系数据 + */ +-(void)initSettingXuint:(CGFloat)xunit xBegin:(CGFloat)xBegin yUint:(CGFloat)yUint yBegain:(CGFloat)yBegain; +/* + * 设置坐标原点 + */ +-(void)initPoint:(CGPoint)point; + +/** + 设置阴线阳线的颜色,是否实心 + + @param color 阳线颜色 + @param color2 阴线颜色 + @param isYangLineSolid 阳线是否实心 + @param isYinLineSolid 阴线是否实心 + . + */ +-(void)initYangLineColor:(UIColor *)color YinLineColor:(UIColor *)color2 isYangLineSolid:(Boolean)isYangLineSolid isYinLineSolid:(Boolean)isYinLineSolid; + + + +/** + 画k图 + + @param arr arr数组长度要>=5 [最大值,最小值,开盘值,收盘值,x坐标,...] + @param ctx CGContextRef画笔对象 + @param scan 放大比例 + */ +-(void)drawKline:(NSArray *)arr withContext:(CGContextRef)contex scan:(CGFloat)scan; + +#pragma mark - 类方法 + +/** + 画直线 + [self.myDraw drawLinePoint:@[@[lineWidthStr,@"185",@"185",@"15",@"1"],@[temp5,temp6]] withContext:UIGraphicsGetCurrentContext()]; + + @param arr2 [[粗细,颜色r,颜色g,颜色b,透明度],[第一条线[第一个点],[第二个点]...],[第二条线]......] + @param ctx CGContextRef画笔对象 + @param scan 放大比例 + */ ++(void)drawLinePoint:(NSArray *)arr2 withContext:(CGContextRef)context scan:(CGFloat)scan; + +/** + 画曲线 + @param lineArr [[线宽,点size,颜色],[第一条线[第一个点],[第二个点]...],[第二条线]...] + @param ctx CGContextRef画笔对象 + @param scan 放大比例 + */ ++(void)drawCurves:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan; + +/** + 画多个多边形 + + @param lineArr [[线宽,线颜色,填充颜色],[第一个多边形[第一个点],[第二个点]...],[第二个多边形]...] + @param ctx CGContextRef画笔对象 + @param scan 放大比例 + */ ++(void)drawMoreRects:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan; + +#pragma mark - 字体类相关 + +/** + 富文本字体 + + @param str 字符串 + @param size 字体范围 + @param point 中心点位置 + @param font 字体大小 + @param color 字体颜色 + */ ++(void)drawWord:(NSString *)str size:(CGSize)size centerPoint:(CGPoint)point font:(CGFloat)font color:(UIColor *)color; + + + +@end diff --git a/YuMi/Tools/sdkContent/content/K/BSDrawLine.m b/YuMi/Tools/sdkContent/content/K/BSDrawLine.m index c094322..3eeb656 100644 --- a/YuMi/Tools/sdkContent/content/K/BSDrawLine.m +++ b/YuMi/Tools/sdkContent/content/K/BSDrawLine.m @@ -1,37 +1,35 @@ -// -// GWDrawLine.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/9/26. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSDrawLine.h" @interface BSDrawLine() -@property(nonatomic,assign)CGPoint point; //原点坐标 +@property(nonatomic,assign)CGPoint point; -@property(nonatomic,assign)CGFloat xUint; //x轴比例 -@property(nonatomic,assign)CGFloat xbegin; //x轴初始值 -@property(nonatomic,assign)CGFloat yUint; //y轴比例 -@property(nonatomic,assign)CGFloat ybegin; //y轴初始值 +@property(nonatomic,assign)CGFloat xUint; +@property(nonatomic,assign)CGFloat xbegin; +@property(nonatomic,assign)CGFloat yUint; +@property(nonatomic,assign)CGFloat ybegin; -@property(nonatomic,assign)NSString *isSolidYangLine; //阳线是否实心 0(空心),1 -@property(nonatomic,assign)NSString *isSolidYinLine; //阴线是否实心 0(实心),1 +@property(nonatomic,assign)NSString *isSolidYangLine; +@property(nonatomic,assign)NSString *isSolidYinLine; -@property(nonatomic,strong)UIColor *YangLineColor; //阳线颜色 -@property(nonatomic,strong)UIColor *YinLineColor; //阴线颜色 +@property(nonatomic,strong)UIColor *YangLineColor; +@property(nonatomic,strong)UIColor *YinLineColor; @end @implementation BSDrawLine -//设置坐标系数据 + -(void)initSettingXuint:(CGFloat)xunit xBegin:(CGFloat)xBegin yUint:(CGFloat)yUint yBegain:(CGFloat)yBegain{ - //检查配置参数 + if (xunit <= 0 || yBegain < 0 || yUint <= 0 || xBegin < 0) { NSLog(@"参数配置有误...,%.2f,%.2f,%.2f,%.2f",xunit,xBegin,yUint,yBegain); return; @@ -43,12 +41,12 @@ _yUint = yUint; } -//设置坐标原点 + -(void)initPoint:(CGPoint)point{ _point = point; } -//设置阴线阳线的颜色,是否实心 + -(void)initYangLineColor:(UIColor *)color YinLineColor:(UIColor *)color2 isYangLineSolid:(Boolean)isYangLineSolid isYinLineSolid:(Boolean)isYinLineSolid{ _YangLineColor = color; _YinLineColor = color2; @@ -68,7 +66,7 @@ -(void)drawKline:(NSArray *)arr withContext:(CGContextRef)context scan:(CGFloat)scan{ - //检查配置参数 + if (_xUint <= 0 ) { NSLog(@"参数配置未设置..."); return; @@ -102,15 +100,12 @@ } - //画坐标系 - - } -(void)drawKLine:(CGFloat)max min:(CGFloat)min open:(CGFloat)open close:(CGFloat)close x:(CGFloat)x lineWidth:(CGFloat)lineWidth lineWidth2:(CGFloat)lineWidth2 context:(CGContextRef)context{ - //检查格式是否规范 + if (max < min || max < open || max < close) { NSLog(@"最大值不正确"); NSLog(@"最大值:%.2f,最小值:%.2f,开盘:%.2f,收盘:%.2f",max,min,open,close); @@ -124,13 +119,9 @@ } -/** - * 画k线 - */ -(void)drawKLine:(CGFloat)max min:(CGFloat)min open:(CGFloat)open close:(CGFloat)close x:(CGFloat)x lineWidth:(CGFloat)lineWidth lineWidth2:(CGFloat)lineWidth2 withPoint:(CGPoint)point xUnit:(CGFloat)xUnit yUnit:(CGFloat)yUnit xbegin:(CGFloat)xbegin ybegin:(CGFloat)ybegin context:(CGContextRef)context{ - //阳线or阴线 Boolean isYangLine; CGFloat top = 0; CGFloat bottom = 0; @@ -144,52 +135,51 @@ bottom = close; } - //根据point计算目标点在view中的位置 + max = point.y - (max - ybegin)*yUnit; min = point.y - (min - ybegin)*yUnit; top = point.y - (top - ybegin)*yUnit; bottom = point.y - (bottom - ybegin)*yUnit; x = (x - xbegin)*xUnit + point.x; - // NSLog(@"\nmax:%.2f\ntop:%.2f\nbottom:%.2f\nmin:%.2f",max,top,bottom,min); UIColor *lineColor = [self getLineColor:isYangLine]; [lineColor setStroke]; - //画上面的线 - CGContextSetLineCap(context,kCGLineCapSquare); //指定直线样式 - CGContextSetLineWidth(context,lineWidth); //线宽 - CGContextBeginPath(context); //开始绘制 - CGContextMoveToPoint(context,x, max); //画笔移动到点 - CGContextAddLineToPoint(context,x, top); //下一点 - CGContextStrokePath(context); //绘制完成 - //画中间的柱体 + CGContextSetLineCap(context,kCGLineCapSquare); + CGContextSetLineWidth(context,lineWidth); + CGContextBeginPath(context); + CGContextMoveToPoint(context,x, max); + CGContextAddLineToPoint(context,x, top); + CGContextStrokePath(context); + + CGFloat height = top - bottom == 0 ? 1 : top - bottom; if (height < 0) { height = - height; } UIColor *solidColor = lineColor; if (![self getSolid:isYangLine]) { - solidColor = [UIColor clearColor]; //实心的颜色 + solidColor = [UIColor clearColor]; } - CGContextBeginPath(context); //开始绘制 - CGContextMoveToPoint(context,x, top); //画笔移动到点 + CGContextBeginPath(context); + CGContextMoveToPoint(context,x, top); [self draw4Rect:CGRectMake(x - lineWidth2/2 , top, lineWidth2,height) withColor:lineColor color2:solidColor withContex:context]; - //画下面的线 + [lineColor setStroke]; - CGContextSetLineCap(context,kCGLineCapSquare); //指定直线样式 - CGContextSetLineWidth(context,lineWidth); //线宽 - CGContextBeginPath(context); //开始绘制 - CGContextMoveToPoint(context,x, bottom); //画笔移动到点 - CGContextAddLineToPoint(context,x, min); //下一点 - CGContextStrokePath(context); //绘制完成 + CGContextSetLineCap(context,kCGLineCapSquare); + CGContextSetLineWidth(context,lineWidth); + CGContextBeginPath(context); + CGContextMoveToPoint(context,x, bottom); + CGContextAddLineToPoint(context,x, min); + CGContextStrokePath(context); } -//获取k线的颜色 + -(UIColor *)getLineColor:(Boolean)isYangLine{ if (isYangLine) { @@ -203,7 +193,7 @@ } return _YinLineColor; } -//获取柱体是否实心 + -(Boolean)getSolid:(Boolean)isYangLine{ if (isYangLine) { if ([_isSolidYangLine isEqualToString:@"0"]) { @@ -217,7 +207,7 @@ return true; } -//[[粗细,颜色r,颜色g,颜色b,透明度],[第一个点],[第二个点]......] + +(void)drawLinePoint:(NSArray *)arr2 withContext:(CGContextRef)context scan:(CGFloat)scan{ if (arr2.count < 2) { @@ -235,25 +225,19 @@ return; } - //kCGLineCapButt, - //kCGLineCapRound, - //kCGLineCapSquare - //设置线段头尾部的样式 + CGContextSetLineCap(context,kCGLineCapSquare); - // kCGLineJoinMiter, - // kCGLineJoinRound, - // kCGLineJoinBevel - //设置线段转折点的样式 + CGContextSetLineJoin(context, kCGLineJoinRound); - //直线宽度 + CGContextSetLineWidth(context,[arr[0] floatValue]/scan); - //设置颜色 + CGContextSetRGBStrokeColor(context,[arr[1] floatValue]/255.0, [arr[2] floatValue]/255.0, [arr[3] floatValue]/255.0, [arr[4] floatValue]); - //开始绘制 + CGContextBeginPath(context); - //画笔移动到点(31,170) + for (int i = 1; i < arr2.count; i++) { NSArray *temp = arr2[i]; @@ -264,15 +248,15 @@ if (j == 0) { if (tempArr.count != 2) { NSLog(@"初始点异常"); - //绘制完成 + CGContextStrokePath(context); return; } CGContextMoveToPoint(context, [tempArr[0] floatValue], [tempArr[1] floatValue]); }else{ - // NSLog(@"画下一个点(%.2f,%.2f);",[tempArr[0] floatValue],[tempArr[1] floatValue]); - //下一点 + + CGContextAddLineToPoint(context, [tempArr[0] floatValue], [tempArr[1] floatValue]); } @@ -282,12 +266,12 @@ NSLog(@"抛弃不规范的数据..."); } } - //绘制完成 + CGContextStrokePath(context); } } -//[[线宽,点size,颜色],[第一条线[第一个点],[第二个点]...],[第二条线]...] + +(void)drawCurves:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan{ if (lineArr.count < 2) { @@ -305,19 +289,19 @@ UIColor *lineColor; if ([peizhiArr isKindOfClass:[NSArray class]]) { - //线宽 + if (peizhiArr.count > 0) { lineWidth = [peizhiArr[0] floatValue]; }else{ lineWidth = 1; } - //点大小 + if (peizhiArr.count > 1) { pointSize1 = [peizhiArr[1] CGSizeValue]; }else{ pointSize1 = CGSizeMake(1, 1); } - //线颜色 + if (peizhiArr.count > 2) { lineColor = peizhiArr[2]; }else{ @@ -346,12 +330,10 @@ } - -//画曲线 +(void)drawCurve:(NSArray *)lineArr2_1 context:(CGContextRef)ctx color:(UIColor *)color pointSize:(CGSize)pointSize lineWidth:(CGFloat)lineWidth{ - //bezier 贝赛尔曲线 + if([lineArr2_1 count]){ - //画线 + UIBezierPath* path = [UIBezierPath bezierPath]; [path setLineWidth:lineWidth]; for(int i=0; i<[lineArr2_1 count]-1; i++){ @@ -360,7 +342,7 @@ CGPoint secondPoint = [[lineArr2_1 xpSafeObjectAtIndex:i+1] CGPointValue]; [path moveToPoint:firstPoint]; - // 核心方法ios 如何根据坐标点画曲线 + [path addCurveToPoint:secondPoint controlPoint1:CGPointMake((secondPoint.x-firstPoint.x)/2+firstPoint.x, firstPoint.y) controlPoint2:CGPointMake((secondPoint.x-firstPoint.x)/2+firstPoint.x, secondPoint.y)]; [color set]; } @@ -368,22 +350,11 @@ path.lineCapStyle = kCGLineCapRound; [path strokeWithBlendMode:kCGBlendModeNormal alpha:1]; - //画点 - // for(int i=0; i<[lineArr2_1 count]; i++){ - // CGPoint point = [[lineArr2_1 safeObjectAtIndex1:i] CGPointValue]; - // CGContextFillEllipseInRect(ctx, CGRectMake(point.x-(pointSize.width/2.0), point.y-(pointSize.height/2.0), pointSize.width, pointSize.height)); - // CGContextSetFillColorWithColor(ctx, color.CGColor); - // CGContextFillPath(ctx); - // } - } } -/** - * 画折线 - */ -(void)drawlineWithPointsArray:(CGPoint *)points count:(int)count lineWeight:(CGFloat)lineWeight lineColor:(UIColor *)lineColor withPointWeight1:(CGFloat)width pointWeight2:(CGFloat)width2 pointColor1:(UIColor *)color1 pointColor2:(UIColor *)color2{ CGContextRef context = UIGraphicsGetCurrentContext(); @@ -406,23 +377,18 @@ } -/** - * 画四边形 - */ -(void)draw4Rect:(CGRect)rect withColor:(UIColor *)color1 color2:(UIColor *)color2 withContex:(CGContextRef)ctx{ - // 2.画矩形 + CGContextAddRect(ctx,rect); - CGContextSetLineWidth(ctx,0.5f);//边框宽度 - CGContextSetFillColorWithColor(ctx, color2.CGColor);//填充颜色 - CGContextSetStrokeColorWithColor(ctx, color1.CGColor);//线框颜色 - CGContextAddRect(ctx,rect);//画方框 - CGContextDrawPath(ctx, kCGPathFillStroke);//绘画路径 - CGContextFillPath(ctx);// + CGContextSetLineWidth(ctx,0.5f); + CGContextSetFillColorWithColor(ctx, color2.CGColor); + CGContextSetStrokeColorWithColor(ctx, color1.CGColor); + CGContextAddRect(ctx,rect); + CGContextDrawPath(ctx, kCGPathFillStroke); + CGContextFillPath(ctx); } - -//[[线宽,线颜色,填充颜色],[第一个多边形[第一个点],[第二个点]...],[第二个多边形]...] +(void)drawMoreRects:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan{ if (lineArr.count < 2) { @@ -440,20 +406,20 @@ UIColor *fileColor; if ([peizhiArr isKindOfClass:[NSArray class]]) { - //线宽 + if (peizhiArr.count > 0) { lineWidth = [peizhiArr[0] floatValue]; }else{ lineWidth = 1; } - //线颜色 + if (peizhiArr.count > 1) { lineColor = peizhiArr[1]; }else{ lineColor = [UIColor blackColor]; } - //填充颜色 + if (peizhiArr.count > 2) { fileColor = peizhiArr[2]; }else{ @@ -480,9 +446,6 @@ } -/** - * 画多边形 color1线框颜色 color2填充颜色 width线框宽度 pointArr点数组,里面的格式是cgpoint - */ +(void)drawMoreRect:(NSArray *)pointArr withColor:(UIColor *)color1 color2:(UIColor *)color2 width:(CGFloat)width withContex:(CGContextRef)context{ if (pointArr.count < 3) { @@ -490,10 +453,10 @@ return; } - //画一个菱形 + CGContextSetLineWidth(context, width); - CGContextSetFillColorWithColor(context, color2.CGColor);//填充颜色 - CGContextSetStrokeColorWithColor(context, color1.CGColor);//线框颜色 + CGContextSetFillColorWithColor(context, color2.CGColor); + CGContextSetStrokeColorWithColor(context, color1.CGColor); CGPoint begainPoint = [pointArr[0] CGPointValue]; CGContextMoveToPoint(context, begainPoint.x, begainPoint.y); @@ -522,7 +485,7 @@ NSMutableDictionary *attr = [NSMutableDictionary dictionaryWithObject:style forKey:NSParagraphStyleAttributeName]; [attr setValue:color forKey:NSForegroundColorAttributeName]; - [attr setValue:[UIFont systemFontOfSize:font] forKey:NSFontAttributeName];//[UIFont fontWithName:@"Zapfino"size:5.0] + [attr setValue:[UIFont systemFontOfSize:font] forKey:NSFontAttributeName]; [str drawInRect:CGRectMake(point.x - size.width/2.0, point.y - size.height/2.0, size.width, size.height) withAttributes:attr]; } diff --git a/YuMi/Tools/sdkContent/content/K/BSDrawLine.m.backup b/YuMi/Tools/sdkContent/content/K/BSDrawLine.m.backup new file mode 100644 index 0000000..c094322 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/K/BSDrawLine.m.backup @@ -0,0 +1,530 @@ +// +// GWDrawLine.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/9/26. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSDrawLine.h" + +@interface BSDrawLine() + +@property(nonatomic,assign)CGPoint point; //原点坐标 + +@property(nonatomic,assign)CGFloat xUint; //x轴比例 +@property(nonatomic,assign)CGFloat xbegin; //x轴初始值 +@property(nonatomic,assign)CGFloat yUint; //y轴比例 +@property(nonatomic,assign)CGFloat ybegin; //y轴初始值 + +@property(nonatomic,assign)NSString *isSolidYangLine; //阳线是否实心 0(空心),1 +@property(nonatomic,assign)NSString *isSolidYinLine; //阴线是否实心 0(实心),1 + +@property(nonatomic,strong)UIColor *YangLineColor; //阳线颜色 +@property(nonatomic,strong)UIColor *YinLineColor; //阴线颜色 + +@end + + +@implementation BSDrawLine + +//设置坐标系数据 +-(void)initSettingXuint:(CGFloat)xunit xBegin:(CGFloat)xBegin yUint:(CGFloat)yUint yBegain:(CGFloat)yBegain{ + + //检查配置参数 + if (xunit <= 0 || yBegain < 0 || yUint <= 0 || xBegin < 0) { + NSLog(@"参数配置有误...,%.2f,%.2f,%.2f,%.2f",xunit,xBegin,yUint,yBegain); + return; + } + + _xbegin = xBegin; + _ybegin = yBegain; + _xUint = xunit; + _yUint = yUint; + +} +//设置坐标原点 +-(void)initPoint:(CGPoint)point{ + _point = point; +} + +//设置阴线阳线的颜色,是否实心 +-(void)initYangLineColor:(UIColor *)color YinLineColor:(UIColor *)color2 isYangLineSolid:(Boolean)isYangLineSolid isYinLineSolid:(Boolean)isYinLineSolid{ + _YangLineColor = color; + _YinLineColor = color2; + if (isYangLineSolid) { + _isSolidYangLine = @"1"; + }else{ + _isSolidYangLine = @"0"; + } + + if (isYinLineSolid) { + _isSolidYinLine = @"0"; + }else{ + _isSolidYinLine = @"1"; + } +} + + +-(void)drawKline:(NSArray *)arr withContext:(CGContextRef)context scan:(CGFloat)scan{ + + //检查配置参数 + if (_xUint <= 0 ) { + NSLog(@"参数配置未设置..."); + return; + } + if (scan == 0) { + scan = 1; + } + + if ([arr isKindOfClass:[NSArray class]]) { + for (NSArray *tempArr in arr) { + if ([tempArr isKindOfClass:[NSArray class]]) { + if ([tempArr count] >= 5) { + + CGFloat maxTemp = [tempArr[0] floatValue]; + CGFloat minTemp = [tempArr[1] floatValue]; + CGFloat openTemp = [tempArr[2] floatValue]; + CGFloat closeTemp = [tempArr[3] floatValue]; + CGFloat xTemp = [tempArr[4] floatValue]; + + [self drawKLine:maxTemp min:minTemp open:openTemp close:closeTemp x:xTemp lineWidth:1/scan lineWidth2:5/scan context:context]; + + }else{ + NSLog(@"单条数组长度<4"); + } + }else{ + NSLog(@"单条数组数据异常"); + } + } + }else{ + NSLog(@"数组有误"); + } + + + //画坐标系 + + +} + + +-(void)drawKLine:(CGFloat)max min:(CGFloat)min open:(CGFloat)open close:(CGFloat)close x:(CGFloat)x lineWidth:(CGFloat)lineWidth lineWidth2:(CGFloat)lineWidth2 context:(CGContextRef)context{ + + //检查格式是否规范 + if (max < min || max < open || max < close) { + NSLog(@"最大值不正确"); + NSLog(@"最大值:%.2f,最小值:%.2f,开盘:%.2f,收盘:%.2f",max,min,open,close); + } + if (min > max || min > open || min > close) { + NSLog(@"最小值不正确"); + NSLog(@"最大值:%.2f,最小值:%.2f,开盘:%.2f,收盘:%.2f",max,min,open,close); + } + + [self drawKLine:max min:min open:open close:close x:x lineWidth:lineWidth lineWidth2:lineWidth2 withPoint:_point xUnit:_xUint yUnit:_yUint xbegin:_xbegin ybegin:_ybegin context:context]; +} + + +/** + * 画k线 + */ +-(void)drawKLine:(CGFloat)max min:(CGFloat)min open:(CGFloat)open close:(CGFloat)close x:(CGFloat)x lineWidth:(CGFloat)lineWidth lineWidth2:(CGFloat)lineWidth2 withPoint:(CGPoint)point xUnit:(CGFloat)xUnit yUnit:(CGFloat)yUnit xbegin:(CGFloat)xbegin ybegin:(CGFloat)ybegin context:(CGContextRef)context{ + + + //阳线or阴线 + Boolean isYangLine; + CGFloat top = 0; + CGFloat bottom = 0; + if (close > open) { + isYangLine = true; + top = close; + bottom = open; + }else{ + isYangLine = false; + top = open; + bottom = close; + } + + //根据point计算目标点在view中的位置 + max = point.y - (max - ybegin)*yUnit; + min = point.y - (min - ybegin)*yUnit; + top = point.y - (top - ybegin)*yUnit; + bottom = point.y - (bottom - ybegin)*yUnit; + x = (x - xbegin)*xUnit + point.x; + + // NSLog(@"\nmax:%.2f\ntop:%.2f\nbottom:%.2f\nmin:%.2f",max,top,bottom,min); + + UIColor *lineColor = [self getLineColor:isYangLine]; + [lineColor setStroke]; + //画上面的线 + + CGContextSetLineCap(context,kCGLineCapSquare); //指定直线样式 + CGContextSetLineWidth(context,lineWidth); //线宽 + CGContextBeginPath(context); //开始绘制 + CGContextMoveToPoint(context,x, max); //画笔移动到点 + CGContextAddLineToPoint(context,x, top); //下一点 + CGContextStrokePath(context); //绘制完成 + + //画中间的柱体 + CGFloat height = top - bottom == 0 ? 1 : top - bottom; + if (height < 0) { + height = - height; + } + UIColor *solidColor = lineColor; + if (![self getSolid:isYangLine]) { + solidColor = [UIColor clearColor]; //实心的颜色 + } + + CGContextBeginPath(context); //开始绘制 + CGContextMoveToPoint(context,x, top); //画笔移动到点 + [self draw4Rect:CGRectMake(x - lineWidth2/2 , top, lineWidth2,height) withColor:lineColor color2:solidColor withContex:context]; + + //画下面的线 + [lineColor setStroke]; + CGContextSetLineCap(context,kCGLineCapSquare); //指定直线样式 + CGContextSetLineWidth(context,lineWidth); //线宽 + CGContextBeginPath(context); //开始绘制 + CGContextMoveToPoint(context,x, bottom); //画笔移动到点 + CGContextAddLineToPoint(context,x, min); //下一点 + CGContextStrokePath(context); //绘制完成 + + +} +//获取k线的颜色 +-(UIColor *)getLineColor:(Boolean)isYangLine{ + + if (isYangLine) { + if (_YangLineColor == nil) { + return [UIColor redColor]; + } + return _YangLineColor; + } + if (_YinLineColor == nil) { + return [UIColor greenColor]; + } + return _YinLineColor; +} +//获取柱体是否实心 +-(Boolean)getSolid:(Boolean)isYangLine{ + if (isYangLine) { + if ([_isSolidYangLine isEqualToString:@"0"]) { + return false; + } + }else{ + if (![_isSolidYinLine isEqualToString:@"0"]) { + return false; + } + } + return true; +} + +//[[粗细,颜色r,颜色g,颜色b,透明度],[第一个点],[第二个点]......] ++(void)drawLinePoint:(NSArray *)arr2 withContext:(CGContextRef)context scan:(CGFloat)scan{ + + if (arr2.count < 2) { + NSLog(@"数据不全..."); + return; + } + if (scan == 0) { + scan = 1; + } + + @autoreleasepool { + NSArray *arr = arr2[0]; + if (![arr isKindOfClass:[NSArray class]] || arr.count < 5) { + NSLog(@"设置参数不正确..."); + return; + } + + //kCGLineCapButt, + //kCGLineCapRound, + //kCGLineCapSquare + //设置线段头尾部的样式 + CGContextSetLineCap(context,kCGLineCapSquare); + + // kCGLineJoinMiter, + // kCGLineJoinRound, + // kCGLineJoinBevel + //设置线段转折点的样式 + CGContextSetLineJoin(context, kCGLineJoinRound); + + //直线宽度 + CGContextSetLineWidth(context,[arr[0] floatValue]/scan); + //设置颜色 + CGContextSetRGBStrokeColor(context,[arr[1] floatValue]/255.0, [arr[2] floatValue]/255.0, [arr[3] floatValue]/255.0, [arr[4] floatValue]); + //开始绘制 + CGContextBeginPath(context); + //画笔移动到点(31,170) + + for (int i = 1; i < arr2.count; i++) { + NSArray *temp = arr2[i]; + if ([temp isKindOfClass:[NSArray class]]) { + for (int j = 0; j < temp.count; ++j) { + NSString *tempStr = temp[j]; + NSArray *tempArr = [tempStr componentsSeparatedByString:@","]; + if (j == 0) { + if (tempArr.count != 2) { + NSLog(@"初始点异常"); + //绘制完成 + CGContextStrokePath(context); + return; + } + CGContextMoveToPoint(context, + [tempArr[0] floatValue], [tempArr[1] floatValue]); + }else{ + // NSLog(@"画下一个点(%.2f,%.2f);",[tempArr[0] floatValue],[tempArr[1] floatValue]); + //下一点 + CGContextAddLineToPoint(context, + [tempArr[0] floatValue], [tempArr[1] floatValue]); + } + } + + }else{ + NSLog(@"抛弃不规范的数据..."); + } + } + //绘制完成 + CGContextStrokePath(context); + } +} + +//[[线宽,点size,颜色],[第一条线[第一个点],[第二个点]...],[第二条线]...] ++(void)drawCurves:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan{ + + if (lineArr.count < 2) { + return; + } + + if (scan == 0) { + scan = 1; + } + + + NSArray *peizhiArr = lineArr[0]; + CGFloat lineWidth = 0.0; + CGSize pointSize1; + UIColor *lineColor; + + if ([peizhiArr isKindOfClass:[NSArray class]]) { + //线宽 + if (peizhiArr.count > 0) { + lineWidth = [peizhiArr[0] floatValue]; + }else{ + lineWidth = 1; + } + //点大小 + if (peizhiArr.count > 1) { + pointSize1 = [peizhiArr[1] CGSizeValue]; + }else{ + pointSize1 = CGSizeMake(1, 1); + } + //线颜色 + if (peizhiArr.count > 2) { + lineColor = peizhiArr[2]; + }else{ + lineColor = [UIColor blackColor]; + } + + + }else{ + lineWidth = 1; + pointSize1 = CGSizeMake(1, 1); + lineColor = [UIColor blackColor]; + } + + lineWidth = lineWidth/scan; + pointSize1 = CGSizeMake(pointSize1.width/scan, pointSize1.height/scan); + + for (int i = 1; i < lineArr.count; ++i) { + NSArray *tempLineArr = lineArr[i]; + if ([tempLineArr isKindOfClass:[NSArray class]]) { + + [self drawCurve:tempLineArr context:ctx color:lineColor pointSize:pointSize1 lineWidth:lineWidth]; + + } + } + +} + + + +//画曲线 ++(void)drawCurve:(NSArray *)lineArr2_1 context:(CGContextRef)ctx color:(UIColor *)color pointSize:(CGSize)pointSize lineWidth:(CGFloat)lineWidth{ + //bezier 贝赛尔曲线 + if([lineArr2_1 count]){ + //画线 + UIBezierPath* path = [UIBezierPath bezierPath]; + [path setLineWidth:lineWidth]; + for(int i=0; i<[lineArr2_1 count]-1; i++){ + if([lineArr2_1 xpSafeObjectAtIndex:i] != nil && [lineArr2_1 xpSafeObjectAtIndex:i+1] != nil){ + CGPoint firstPoint = [[lineArr2_1 xpSafeObjectAtIndex:i] CGPointValue]; + CGPoint secondPoint = [[lineArr2_1 xpSafeObjectAtIndex:i+1] CGPointValue]; + [path moveToPoint:firstPoint]; + + // 核心方法ios 如何根据坐标点画曲线 + [path addCurveToPoint:secondPoint controlPoint1:CGPointMake((secondPoint.x-firstPoint.x)/2+firstPoint.x, firstPoint.y) controlPoint2:CGPointMake((secondPoint.x-firstPoint.x)/2+firstPoint.x, secondPoint.y)]; + [color set]; + } + } + path.lineCapStyle = kCGLineCapRound; + [path strokeWithBlendMode:kCGBlendModeNormal alpha:1]; + + //画点 + // for(int i=0; i<[lineArr2_1 count]; i++){ + // CGPoint point = [[lineArr2_1 safeObjectAtIndex1:i] CGPointValue]; + // CGContextFillEllipseInRect(ctx, CGRectMake(point.x-(pointSize.width/2.0), point.y-(pointSize.height/2.0), pointSize.width, pointSize.height)); + // CGContextSetFillColorWithColor(ctx, color.CGColor); + // CGContextFillPath(ctx); + // } + + + } +} + + +/** + * 画折线 + */ +-(void)drawlineWithPointsArray:(CGPoint *)points count:(int)count lineWeight:(CGFloat)lineWeight lineColor:(UIColor *)lineColor withPointWeight1:(CGFloat)width pointWeight2:(CGFloat)width2 pointColor1:(UIColor *)color1 pointColor2:(UIColor *)color2{ + + CGContextRef context = UIGraphicsGetCurrentContext(); + [lineColor setStroke]; + CGContextSetLineWidth(context, lineWeight); + + + CGContextAddLines(context, points, count); + CGContextStrokePath(context); + + for (int i = 0; i < count; i ++) { + CGRect ellipseRect = CGRectMake(points[i].x - (width+width2), points[i].y - (width+width2), (width+width2)*2, (width+width2)*2); + CGContextAddEllipseInRect(context, ellipseRect); + CGContextSetLineWidth(context, width); + [color1 setStroke]; + [color2 setFill]; + CGContextFillEllipseInRect(context, ellipseRect); + CGContextStrokeEllipseInRect(context, ellipseRect); + } +} + + +/** + * 画四边形 + */ +-(void)draw4Rect:(CGRect)rect withColor:(UIColor *)color1 color2:(UIColor *)color2 withContex:(CGContextRef)ctx{ + // 2.画矩形 + CGContextAddRect(ctx,rect); + CGContextSetLineWidth(ctx,0.5f);//边框宽度 + CGContextSetFillColorWithColor(ctx, color2.CGColor);//填充颜色 + CGContextSetStrokeColorWithColor(ctx, color1.CGColor);//线框颜色 + CGContextAddRect(ctx,rect);//画方框 + CGContextDrawPath(ctx, kCGPathFillStroke);//绘画路径 + CGContextFillPath(ctx);// +} + + + +//[[线宽,线颜色,填充颜色],[第一个多边形[第一个点],[第二个点]...],[第二个多边形]...] ++(void)drawMoreRects:(NSArray *)lineArr withContext:(CGContextRef)ctx scan:(CGFloat)scan{ + + if (lineArr.count < 2) { + return; + } + + if (scan == 0) { + scan = 1; + } + + + NSArray *peizhiArr = lineArr[0]; + CGFloat lineWidth = 0.0; + UIColor *lineColor; + UIColor *fileColor; + + if ([peizhiArr isKindOfClass:[NSArray class]]) { + //线宽 + if (peizhiArr.count > 0) { + lineWidth = [peizhiArr[0] floatValue]; + }else{ + lineWidth = 1; + } + //线颜色 + if (peizhiArr.count > 1) { + lineColor = peizhiArr[1]; + }else{ + lineColor = [UIColor blackColor]; + } + + //填充颜色 + if (peizhiArr.count > 2) { + fileColor = peizhiArr[2]; + }else{ + fileColor = [UIColor redColor]; + } + + + }else{ + lineWidth = 1; + lineColor = [UIColor blackColor]; + fileColor = [UIColor redColor]; + } + + lineWidth = lineWidth/scan; + + for (int i = 1; i < lineArr.count; ++i) { + NSArray *tempLineArr = lineArr[i]; + if ([tempLineArr isKindOfClass:[NSArray class]]) { + [self drawMoreRect:tempLineArr withColor:lineColor color2:fileColor width:lineWidth withContex:ctx]; + + } + } + +} + + +/** + * 画多边形 color1线框颜色 color2填充颜色 width线框宽度 pointArr点数组,里面的格式是cgpoint + */ ++(void)drawMoreRect:(NSArray *)pointArr withColor:(UIColor *)color1 color2:(UIColor *)color2 width:(CGFloat)width withContex:(CGContextRef)context{ + + if (pointArr.count < 3) { + NSLog(@"不规范的多边形图"); + return; + } + + //画一个菱形 + CGContextSetLineWidth(context, width); + CGContextSetFillColorWithColor(context, color2.CGColor);//填充颜色 + CGContextSetStrokeColorWithColor(context, color1.CGColor);//线框颜色 + + CGPoint begainPoint = [pointArr[0] CGPointValue]; + CGContextMoveToPoint(context, begainPoint.x, begainPoint.y); + + for (int i = 1; i < pointArr.count; ++i) { + CGPoint tempPoint = [pointArr[i] CGPointValue]; + CGContextAddLineToPoint(context, tempPoint.x, tempPoint.y); + + } + + CGContextFillPath(context); + +} + + +#pragma mark - 字体类相关 ++(void)drawWord:(NSString *)str size:(CGSize)size centerPoint:(CGPoint)point font:(CGFloat)font color:(UIColor *)color{ + + if (color == nil) { + color = [UIColor blueColor]; + } + + NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + style.alignment=NSTextAlignmentCenter; + style.lineSpacing=0.1; + + NSMutableDictionary *attr = [NSMutableDictionary dictionaryWithObject:style forKey:NSParagraphStyleAttributeName]; + [attr setValue:color forKey:NSForegroundColorAttributeName]; + [attr setValue:[UIFont systemFontOfSize:font] forKey:NSFontAttributeName];//[UIFont fontWithName:@"Zapfino"size:5.0] + + [str drawInRect:CGRectMake(point.x - size.width/2.0, point.y - size.height/2.0, size.width, size.height) withAttributes:attr]; +} + +@end diff --git a/YuMi/Tools/sdkContent/content/K/BSkObject.h b/YuMi/Tools/sdkContent/content/K/BSkObject.h index 75d2a32..613aa75 100644 --- a/YuMi/Tools/sdkContent/content/K/BSkObject.h +++ b/YuMi/Tools/sdkContent/content/K/BSkObject.h @@ -1,45 +1,32 @@ -// -// GWkObject.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/9/26. // Copyright © 2016年 xw.com. All rights reserved. -// + #import #import -/* - * 阳线:收盘价高于开盘价(红色/空心),阴线:收盘价低于开盘价(黑色/实心) - */ + + @interface BSkObject : NSObject -//开盘价 + @property(nonatomic,assign)CGFloat opening; -//收盘价 + @property(nonatomic,assign)CGFloat closing; -//最高价 + @property(nonatomic,assign)CGFloat highest; -//最低价 + @property(nonatomic,assign)CGFloat lowest; - #pragma mark - 时间类 -@property(nonatomic,assign)NSDate *openingTime; //开盘时间 -@property(nonatomic,assign)NSDate *closingTime; //收盘时间 -@property(nonatomic,assign)NSDate *kTime; //k线时间差 +@property(nonatomic,assign)NSDate *openingTime; +@property(nonatomic,assign)NSDate *closingTime; +@property(nonatomic,assign)NSDate *kTime; #pragma mark - 获取方法 -/** - 获取当前是否为阳线 - - @return 是否为阳线 - */ -//-(Boolean)isYangLine; - -// - @end diff --git a/YuMi/Tools/sdkContent/content/K/BSkObject.h.backup b/YuMi/Tools/sdkContent/content/K/BSkObject.h.backup new file mode 100644 index 0000000..75d2a32 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/K/BSkObject.h.backup @@ -0,0 +1,45 @@ +// +// GWkObject.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/9/26. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import +/* + * 阳线:收盘价高于开盘价(红色/空心),阴线:收盘价低于开盘价(黑色/实心) + */ +@interface BSkObject : NSObject + +//开盘价 +@property(nonatomic,assign)CGFloat opening; +//收盘价 +@property(nonatomic,assign)CGFloat closing; +//最高价 +@property(nonatomic,assign)CGFloat highest; +//最低价 +@property(nonatomic,assign)CGFloat lowest; + + + +#pragma mark - 时间类 +@property(nonatomic,assign)NSDate *openingTime; //开盘时间 +@property(nonatomic,assign)NSDate *closingTime; //收盘时间 +@property(nonatomic,assign)NSDate *kTime; //k线时间差 + + +#pragma mark - 获取方法 + +/** + 获取当前是否为阳线 + + @return 是否为阳线 + */ +//-(Boolean)isYangLine; + +// + + +@end diff --git a/YuMi/Tools/sdkContent/content/K/BSkObject.m b/YuMi/Tools/sdkContent/content/K/BSkObject.m index d6ec8f7..154ec65 100644 --- a/YuMi/Tools/sdkContent/content/K/BSkObject.m +++ b/YuMi/Tools/sdkContent/content/K/BSkObject.m @@ -1,10 +1,8 @@ -// -// GWkObject.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/9/26. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSkObject.h" diff --git a/YuMi/Tools/sdkContent/content/K/BSkObject.m.backup b/YuMi/Tools/sdkContent/content/K/BSkObject.m.backup new file mode 100644 index 0000000..d6ec8f7 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/K/BSkObject.m.backup @@ -0,0 +1,14 @@ +// +// GWkObject.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/9/26. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSkObject.h" + + +@implementation BSkObject + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h index 1fd9b62..b7c3ff0 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h @@ -1,10 +1,8 @@ -// -// NetListenModel.h -// BaseProject -// + + // Created by xiaowen.chen on 16/8/12. // Copyright © 2016年 xw.com. All rights reserved. -// + #import #import @@ -14,14 +12,13 @@ + (instancetype)sharedInstance:(UIWindow *)window; -//初始化实时监听的view + +(void)initRealTimeView:(UIView *)view; +(void)initRealTimeView; -//隐藏view + +(void)hideView; -//实时打印事件 +(void)GWPrint:(id)object; +(void)GWPrint:(id)object color:(UIColor *)color; @@ -29,13 +26,9 @@ +(void)GWPrint:(id)object color:(UIColor *)color font:(CGFloat)font; - #pragma mark - 网络类的监听处理 -/* - * url:请求的链接 - * headDic:请求的头文件 - * param:请求的参数 - */ + + +(void)addHttpReq:(NSString *)url param:(NSDictionary *)param time:(NSString *)time; +(void)addHttpReq:(NSString *)url header:(NSDictionary *)headDic param:(NSDictionary *)param time:(NSString *)time; @@ -44,12 +37,8 @@ #pragma mark - 操作记录存储 -/* - * coding:类型编码 - * keyword:关键字,(比如:按钮名) - * describe:描述语,(比如:打开) - * option:操作编码 - */ + + +(void)addOptionRecord:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option; diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h.backup new file mode 100644 index 0000000..1fd9b62 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.h.backup @@ -0,0 +1,60 @@ +// +// NetListenModel.h +// BaseProject +// +// Created by xiaowen.chen on 16/8/12. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import + +@interface BSNetListenModel : NSObject +@property(nonatomic,assign)BOOL isShow; + ++ (instancetype)sharedInstance:(UIWindow *)window; + +//初始化实时监听的view ++(void)initRealTimeView:(UIView *)view; ++(void)initRealTimeView; +//隐藏view ++(void)hideView; + + +//实时打印事件 ++(void)GWPrint:(id)object; + ++(void)GWPrint:(id)object color:(UIColor *)color; + ++(void)GWPrint:(id)object color:(UIColor *)color font:(CGFloat)font; + + + +#pragma mark - 网络类的监听处理 +/* + * url:请求的链接 + * headDic:请求的头文件 + * param:请求的参数 + */ ++(void)addHttpReq:(NSString *)url param:(NSDictionary *)param time:(NSString *)time; ++(void)addHttpReq:(NSString *)url header:(NSDictionary *)headDic param:(NSDictionary *)param time:(NSString *)time; + ++(void)addHttpRsp:(NSString *)url result:(id)result isSuccess:(Boolean)isSuccess time:(NSString *)time; ++(void)addHttpRsp:(NSString *)url header:(NSDictionary *)headDic result:(id)result isSuccess:(Boolean)isSuccess time:(NSString *)time; + + +#pragma mark - 操作记录存储 +/* + * coding:类型编码 + * keyword:关键字,(比如:按钮名) + * describe:描述语,(比如:打开) + * option:操作编码 + */ ++(void)addOptionRecord:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option; + + +#pragma mark - 页面分析 ++(void)pushToLogViewWithNavigationController:(UINavigationController *)na; + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m index 63a7a21..f30ce2f 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m @@ -1,10 +1,8 @@ -// -// NetListenModel.m -// BaseProject -// + + // Created by xiaowen.chen on 16/8/12. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSNetListenModel.h" #import "BSRealTimeView.h" @@ -18,14 +16,10 @@ static NSString * const gwTeskSdk_version = @"gwTeskSdk_version"; - @interface BSNetListenModel() @property (nonatomic, strong) UIWindow *window; -@property (nonatomic, strong) BSRealTimeView *timeView;//监听的view - - - +@property (nonatomic, strong) BSRealTimeView *timeView; @end @@ -33,7 +27,6 @@ static NSString * const gwTeskSdk_version = @"gwTeskSdk_version"; @implementation BSNetListenModel - + (instancetype)sharedInstance:(UIWindow *)window { static BSNetListenModel *instance; static dispatch_once_t onceToken; @@ -44,7 +37,7 @@ static NSString * const gwTeskSdk_version = @"gwTeskSdk_version"; [self instance]; - //关闭监听的view; + [BSNotification addHandler:^(NFMessageType type,NSString *key,NSObject *value) { [instance.timeView setHidden:YES]; instance.isShow = NO; @@ -63,10 +56,9 @@ static NSString * const gwTeskSdk_version = @"gwTeskSdk_version"; NSString *result = [userDefaults valueForKey:@"bs_isFirstRunDataBase_gwtestsdk"]; - } -static NSMutableDictionary *dataDic;//数据 +static NSMutableDictionary *dataDic; +(void)initRealTimeView:(UIView *)view{ @@ -77,7 +69,7 @@ static NSMutableDictionary *dataDic;//数据 netModel.timeView = timeView; }else{ if (netModel.timeView.subviews) { - [netModel.timeView removeFromSuperview];//父类移除 + [netModel.timeView removeFromSuperview]; } } [view addSubview:netModel.timeView]; @@ -93,7 +85,7 @@ static NSMutableDictionary *dataDic;//数据 netModel.timeView = timeView; }else{ if (netModel.timeView.subviews) { - [netModel.timeView removeFromSuperview];//父类移除 + [netModel.timeView removeFromSuperview]; } } [netModel.window addSubview:netModel.timeView]; @@ -116,7 +108,7 @@ static NSMutableDictionary *dataDic;//数据 } +(void)addHttpReq:(NSString *)url header:(NSDictionary *)headDic param:(NSDictionary *)param time:(NSString *)time{ - if (time == nil) {//要求有唯一产生规则 + if (time == nil) { return; } @@ -140,7 +132,7 @@ static NSMutableDictionary *dataDic;//数据 } +(void)addHttpRsp:(NSString *)url header:(NSDictionary *)headDic result:(id)result isSuccess:(Boolean)isSuccess time:(NSString *)time{ - if (time == nil) {//要求有唯一产生规则 + if (time == nil) { return; } @@ -164,8 +156,6 @@ static NSMutableDictionary *dataDic;//数据 } - -//实时打印事件 +(void)GWPrint:(id)object{ return [self GWPrint:object color:nil font:0]; } @@ -177,7 +167,7 @@ static NSMutableDictionary *dataDic;//数据 +(void)GWPrint:(id)object color:(UIColor *)color font:(CGFloat)font{ NSMutableDictionary *dic; - //字符串 + if ([object isKindOfClass:[NSDictionary class]]||[object isKindOfClass:[NSArray class]]) { dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"yes",@"isChangeLine",object,@"printData", nil]; @@ -201,19 +191,17 @@ static NSMutableDictionary *dataDic;//数据 } -static NSMutableArray *recordArr;//内存 +static NSMutableArray *recordArr; #pragma mark - 操作记录存储 +(void)addOptionRecord:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option{ - - BSRecordModel *tempModel = [BSRecordModel recordModelWith:coding keyword:keyword describe:describe option:option]; [self GWPrint:[tempModel description] color:[UIColor orangeColor] font:7]; if (tempModel) { - //记录到内存 + [self writeRecordToCache:tempModel]; } @@ -221,8 +209,6 @@ static NSMutableArray *recordArr;//内存 } - -//写入内存 +(void)writeRecordToCache:(BSRecordModel *)record{ if (!recordArr) { recordArr = [NSMutableArray array]; @@ -232,8 +218,6 @@ static NSMutableArray *recordArr;//内存 } - -//内存中获取 +(NSMutableArray *)getRecordFromCache{ if (!recordArr) { @@ -243,21 +227,17 @@ static NSMutableArray *recordArr;//内存 } - - #pragma mark - 页面分析 +(void)pushToLogViewWithNavigationController:(UINavigationController *)na{ UIWindow * window = [[UIApplication sharedApplication].windows lastObject]; BSNetListenModel *netModel = [BSNetListenModel sharedInstance:window]; if (netModel.timeView != nil) { - [netModel.timeView cancleINtime];//暂停实时监听 + [netModel.timeView cancleINtime]; } BSLogTableViewController *gw = [[BSLogTableViewController alloc] init]; [na pushViewController:gw animated:YES]; } - - @end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m.backup new file mode 100644 index 0000000..63a7a21 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/BSNetListenModel.m.backup @@ -0,0 +1,263 @@ +// +// NetListenModel.m +// BaseProject +// +// Created by xiaowen.chen on 16/8/12. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSNetListenModel.h" +#import "BSRealTimeView.h" +#import "BSRecordModel.h" + + +#import "BSLogTableViewController.h" + +#import "BSNotification.h" + +static NSString * const gwTeskSdk_version = @"gwTeskSdk_version"; + + + +@interface BSNetListenModel() + +@property (nonatomic, strong) UIWindow *window; +@property (nonatomic, strong) BSRealTimeView *timeView;//监听的view + + + + + +@end + +@implementation BSNetListenModel + + + ++ (instancetype)sharedInstance:(UIWindow *)window { + static BSNetListenModel *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + + instance.window = window; + + [self instance]; + + //关闭监听的view; + [BSNotification addHandler:^(NFMessageType type,NSString *key,NSObject *value) { + [instance.timeView setHidden:YES]; + instance.isShow = NO; + } withName:@"netlisten_viewhide"]; + }); + + return instance; +} + +#pragma mark - 初始化相关的数据 + ++(void)instance{ + + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + NSString *result = [userDefaults valueForKey:@"bs_isFirstRunDataBase_gwtestsdk"]; + + + +} + +static NSMutableDictionary *dataDic;//数据 + ++(void)initRealTimeView:(UIView *)view{ + + UIWindow * window = [UIApplication sharedApplication].keyWindow; + BSNetListenModel *netModel = [BSNetListenModel sharedInstance:window]; + if (!netModel.timeView) { + BSRealTimeView *timeView = [[BSRealTimeView alloc] initWithFrame:CGRectMake(20, 300, 200, 160)]; + netModel.timeView = timeView; + }else{ + if (netModel.timeView.subviews) { + [netModel.timeView removeFromSuperview];//父类移除 + } + } + [view addSubview:netModel.timeView]; + [netModel.timeView setHidden:NO]; + +} ++(void)initRealTimeView{ + + UIWindow * window = [UIApplication sharedApplication].keyWindow; + BSNetListenModel *netModel = [BSNetListenModel sharedInstance:window]; + if (!netModel.timeView) { + BSRealTimeView *timeView = [[BSRealTimeView alloc] initWithFrame:CGRectMake(20, 300, 200, 160)]; + netModel.timeView = timeView; + }else{ + if (netModel.timeView.subviews) { + [netModel.timeView removeFromSuperview];//父类移除 + } + } + [netModel.window addSubview:netModel.timeView]; + [netModel.timeView setHidden:NO]; + +} + + ++(void)hideView{ + [BSNotification pushHandle:nil withName:@"netlisten_viewhide"]; + UIWindow * window = [UIApplication sharedApplication].keyWindow; + BSNetListenModel *netModel = [BSNetListenModel sharedInstance:window]; + netModel.isShow = NO; + +} + +#pragma mark - 网络类监听处理 ++(void)addHttpReq:(NSString *)url param:(NSDictionary *)param time:(NSString *)time{ + return [self addHttpReq:url header:nil param:param time:time]; +} ++(void)addHttpReq:(NSString *)url header:(NSDictionary *)headDic param:(NSDictionary *)param time:(NSString *)time{ + + if (time == nil) {//要求有唯一产生规则 + return; + } + + NSMutableDictionary *dic; + if (url == nil) { + url = @"---"; + } + dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:url,@"url",@"netReq",@"handle",time,@"time", nil]; + if (headDic != nil) { + [dic setValue:headDic forKey:@"header"]; + } + if (param != nil) { + [dic setValue:param forKey:@"param"]; + } + + + [BSNotification pushHandle:dic withName:@"gwsdk_print"]; +} ++(void)addHttpRsp:(NSString *)url result:(id)result isSuccess:(Boolean)isSuccess time:(NSString *)time{ + return [self addHttpRsp:url header:nil result:result isSuccess:isSuccess time:time]; +} ++(void)addHttpRsp:(NSString *)url header:(NSDictionary *)headDic result:(id)result isSuccess:(Boolean)isSuccess time:(NSString *)time{ + + if (time == nil) {//要求有唯一产生规则 + return; + } + + NSMutableDictionary *dic; + if (url == nil) { + url = @"---"; + } + dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:url,@"url",@"netRsp",@"handle",time,@"time", nil]; + if (headDic != nil) { + [dic setValue:headDic forKey:@"header"]; + } + if (result != nil) { + [dic setValue:result forKey:@"result"]; + } + if (isSuccess) { + [dic setValue:@"1" forKey:@"isSuccess"]; + }else{ + [dic setValue:@"0" forKey:@"isSuccess"]; + } + [BSNotification pushHandle:dic withName:@"gwsdk_print"]; +} + + + +//实时打印事件 ++(void)GWPrint:(id)object{ + return [self GWPrint:object color:nil font:0]; +} + ++(void)GWPrint:(id)object color:(UIColor *)color{ + return [self GWPrint:object color:color font:0]; +} + ++(void)GWPrint:(id)object color:(UIColor *)color font:(CGFloat)font{ + + NSMutableDictionary *dic; + //字符串 + if ([object isKindOfClass:[NSDictionary class]]||[object isKindOfClass:[NSArray class]]) { + dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"yes",@"isChangeLine",object,@"printData", nil]; + + + }else if([object isKindOfClass:[NSString class]]){ + dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"no",@"isChangeLine",object,@"printData", nil]; + + }else{ + dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"yes",@"isChangeLine",@"不支持该打印模式...",@"printData",@"15",@"font",[UIColor redColor],@"color", nil]; + + } + + if (!dic[@"color"] && color != nil) { + [dic setValue:color forKey:@"color"]; + } + if (!dic[@"font"] && font != 0) { + [dic setValue:[NSString stringWithFormat:@"%.2f",font] forKey:@"font"]; + } + + [BSNotification pushHandle:dic withName:@"gwsdk_print"]; +} + + +static NSMutableArray *recordArr;//内存 +#pragma mark - 操作记录存储 + ++(void)addOptionRecord:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option{ + + + + + BSRecordModel *tempModel = [BSRecordModel recordModelWith:coding keyword:keyword describe:describe option:option]; + [self GWPrint:[tempModel description] color:[UIColor orangeColor] font:7]; + + if (tempModel) { + //记录到内存 + [self writeRecordToCache:tempModel]; + + } + +} + + + +//写入内存 ++(void)writeRecordToCache:(BSRecordModel *)record{ + if (!recordArr) { + recordArr = [NSMutableArray array]; + } + + [recordArr addObject:record]; +} + + + +//内存中获取 ++(NSMutableArray *)getRecordFromCache{ + + if (!recordArr) { + recordArr = [NSMutableArray array]; + } + return recordArr; +} + + + + +#pragma mark - 页面分析 ++(void)pushToLogViewWithNavigationController:(UINavigationController *)na{ + + UIWindow * window = [[UIApplication sharedApplication].windows lastObject]; + BSNetListenModel *netModel = [BSNetListenModel sharedInstance:window]; + if (netModel.timeView != nil) { + [netModel.timeView cancleINtime];//暂停实时监听 + } + BSLogTableViewController *gw = [[BSLogTableViewController alloc] init]; + [na pushViewController:gw animated:YES]; +} + + + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h index b5f3e45..cefb12a 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h @@ -1,15 +1,12 @@ -// -// GWLogNetDetailViewController.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/31. // Copyright © 2016年 xw.com. All rights reserved. -// + #import #import "BSRecordModel.h" -//网络详情 @interface BSLogNetDetailViewController : UIViewController diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h.backup new file mode 100644 index 0000000..b5f3e45 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.h.backup @@ -0,0 +1,18 @@ +// +// GWLogNetDetailViewController.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/31. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import +#import "BSRecordModel.h" + +//网络详情 + +@interface BSLogNetDetailViewController : UIViewController + +@property (nonatomic, strong) BSRecordModel *model; + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m index 8f54248..f88eef5 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m @@ -1,10 +1,8 @@ -// -// GWLogNetDetailViewController.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/31. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSLogNetDetailViewController.h" #import "BSSDLayoutUtil.h" @@ -26,24 +24,23 @@ - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - //url + _urlLabel = [[UILabel alloc] init]; _urlLabel.numberOfLines = 2; [self.view addSubview:_urlLabel]; SDLAYOUT_h(_urlLabel, self.view, 20, self.view, -5, self.view, -5, 40); - //请求时间 + _reqTimeLable = [[UILabel alloc] init]; [self.view addSubview:_reqTimeLable]; SDLAYOUT_h(_reqTimeLable, _urlLabel, 42, self.view, -5, self.view, -5, 22); - //返回时间 + _rspTimeLable = [[UILabel alloc] init]; [self.view addSubview:_rspTimeLable]; SDLAYOUT_h(_rspTimeLable, _reqTimeLable, 25, self.view, -5, self.view, -5, 22); - //请求 _reqLabel = [[UITextView alloc] init]; _reqLabel.editable = NO; _reqLabel.textColor = [UIColor grayColor]; @@ -51,15 +48,12 @@ SDLAYOUT_h(_reqLabel, _rspTimeLable, 25, self.view, -5, self.view, -5, 150); - //返回 _rspLabel = [[UITextView alloc] init]; _rspLabel.editable = NO; [self.view addSubview:_rspLabel]; SDLAYOUT(_rspLabel, _reqLabel, 152, self.view, 5, self.view, -5, self.view,-5); - - [self initData]; } @@ -74,7 +68,7 @@ - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. + } /* diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m.backup new file mode 100644 index 0000000..8f54248 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogNetDetailViewController.m.backup @@ -0,0 +1,90 @@ +// +// GWLogNetDetailViewController.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/31. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSLogNetDetailViewController.h" +#import "BSSDLayoutUtil.h" + +@interface BSLogNetDetailViewController () + +@property (nonatomic, strong) UILabel *urlLabel; + +@property (nonatomic, strong) UILabel *reqTimeLable; +@property (nonatomic, strong) UILabel *rspTimeLable; + +@property (nonatomic, strong) UITextView *reqLabel; +@property (nonatomic, strong) UITextView *rspLabel; + +@end + +@implementation BSLogNetDetailViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + //url + _urlLabel = [[UILabel alloc] init]; + _urlLabel.numberOfLines = 2; + [self.view addSubview:_urlLabel]; + SDLAYOUT_h(_urlLabel, self.view, 20, self.view, -5, self.view, -5, 40); + + //请求时间 + _reqTimeLable = [[UILabel alloc] init]; + [self.view addSubview:_reqTimeLable]; + SDLAYOUT_h(_reqTimeLable, _urlLabel, 42, self.view, -5, self.view, -5, 22); + + //返回时间 + _rspTimeLable = [[UILabel alloc] init]; + [self.view addSubview:_rspTimeLable]; + SDLAYOUT_h(_rspTimeLable, _reqTimeLable, 25, self.view, -5, self.view, -5, 22); + + + //请求 + _reqLabel = [[UITextView alloc] init]; + _reqLabel.editable = NO; + _reqLabel.textColor = [UIColor grayColor]; + [self.view addSubview:_reqLabel]; + SDLAYOUT_h(_reqLabel, _rspTimeLable, 25, self.view, -5, self.view, -5, 150); + + + //返回 + _rspLabel = [[UITextView alloc] init]; + _rspLabel.editable = NO; + [self.view addSubview:_rspLabel]; + SDLAYOUT(_rspLabel, _reqLabel, 152, self.view, 5, self.view, -5, self.view,-5); + + + + + [self initData]; +} + +-(void)initData{ + + _urlLabel.text = _model.keyword; + _reqTimeLable.text = [NSString stringWithFormat:@"请求时间:%@",_model.time]; + _rspTimeLable.text = [NSString stringWithFormat:@"响应时间:%@",_model.time2]; + _reqLabel.text = [NSString stringWithFormat:@"请求头:%@\n请求参数:%@",_model.describe,_model.result]; + _rspLabel.text = [NSString stringWithFormat:@"结果头:%@\n结果:%@",_model.describe2,_model.result2]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h index b8de915..74d0476 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h @@ -1,10 +1,8 @@ -// -// LogTableViewController.h -// BaseProject -// + + // Created by xiaowen.chen on 16/8/24. // Copyright © 2016年 xw.com. All rights reserved. -// + #import diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h.backup new file mode 100644 index 0000000..b8de915 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.h.backup @@ -0,0 +1,13 @@ +// +// LogTableViewController.h +// BaseProject +// +// Created by xiaowen.chen on 16/8/24. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + +@interface BSLogTableViewController : UIViewController + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m index f9eb8bb..d5728b0 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m @@ -1,10 +1,8 @@ -// -// LogTableViewController.m -// BaseProject -// + + // Created by xiaowen.chen on 16/8/24. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSLogTableViewController.h" #import "BSRecordModel.h" @@ -47,15 +45,9 @@ }]; - -// NSLog(@"获取数据1"); - //模拟数据 _arr = [NSMutableArray array]; - - - //右上角菜单 UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithTitle:@"清空" style:UIBarButtonItemStylePlain target:self action:@selector(rightBarButtonItem:) ] ; [rightBarButton setTintColor:[UIColor blueColor]]; self.navigationItem.rightBarButtonItem = rightBarButton; @@ -63,18 +55,13 @@ } -//保存txt + -(void)rightBarButtonItem:(UIBarButtonItem *)btnItem{ - //保存 -// btnItem.enabled = NO; -// [GWFileOptionModel writeToFile_RecordModel:_arr stringForMatBlock:^NSString *(NSString *forMatString) { -// return @"类型编码:[coding] 链接:[keyword] 请求时间:[time] 返回时间:[time2] 关键字:[keyword] 请求:[result] 结果:[result2] 操作编码:[optionCoding]\n\n "; -// } withCompletion:nil class:[BSRecordModel class]]; #pragma clang diagnostic push #pragma clang diagnostic ignored"-Wdeprecated-declarations" - //写在这个中间的代码,都不会被编译器提示-Wdeprecated-declarations类型的警告 + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"是否清空历史记录?" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; [alert show]; @@ -87,7 +74,7 @@ #pragma clang diagnostic ignored"-Wdeprecated-declarations" -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if (buttonIndex == 1) { - //删除所有 + self.navigationItem.rightBarButtonItem.enabled = NO; BSRecordModel *tempModel = [[BSRecordModel alloc] init]; @@ -120,7 +107,7 @@ cell.textLabel.numberOfLines = 2; } - // 设置 Cell... + BSRecordModel *model = _arr[indexPath.section]; if (model.coding == 200) { if (indexPath.row == 0) { @@ -151,15 +138,13 @@ } - - #pragma mark - tableView分区设定 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ - //分区数 + return _arr.count; } -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ - //分区高度 + return 30; } @@ -225,7 +210,6 @@ [detailBtn addTarget:self action:@selector(onclicBtn:) forControlEvents:UIControlEventTouchUpInside]; - [hf addSubview:view]; } return hf; @@ -244,7 +228,7 @@ - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. + } /* diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m.backup new file mode 100644 index 0000000..f9eb8bb --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSLogTableViewController.m.backup @@ -0,0 +1,260 @@ +// +// LogTableViewController.m +// BaseProject +// +// Created by xiaowen.chen on 16/8/24. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSLogTableViewController.h" +#import "BSRecordModel.h" +#import "BSLogNetDetailViewController.h" + +#import "Masonry.h" +#import "BSNSStringUtil.h" +#import "BS_UIColor.h" +#import "BSXWDateUtil.h" + +@interface BSLogTableViewController () + +@property (nonatomic, strong) UITableView *tableView; + +@property (nonatomic, strong) NSMutableArray *arr; + +@end + +@implementation BSLogTableViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + [self createMyView]; +} + +-(void)createMyView{ + self.title = @"历史记录30条"; + self.view.backgroundColor = [UIColor whiteColor]; + _tableView = [[UITableView alloc] init]; + [self.view addSubview:_tableView]; + _tableView.dataSource = self; + _tableView.delegate = self; + + + [_tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view); + make.leading.equalTo(self.view); + make.trailing.equalTo(self.view); + make.bottom.equalTo(self.view); + }]; + + + +// NSLog(@"获取数据1"); + //模拟数据 + _arr = [NSMutableArray array]; + + + + + //右上角菜单 + UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithTitle:@"清空" style:UIBarButtonItemStylePlain target:self action:@selector(rightBarButtonItem:) ] ; + [rightBarButton setTintColor:[UIColor blueColor]]; + self.navigationItem.rightBarButtonItem = rightBarButton; + + +} + +//保存txt +-(void)rightBarButtonItem:(UIBarButtonItem *)btnItem{ + + //保存 +// btnItem.enabled = NO; +// [GWFileOptionModel writeToFile_RecordModel:_arr stringForMatBlock:^NSString *(NSString *forMatString) { +// return @"类型编码:[coding] 链接:[keyword] 请求时间:[time] 返回时间:[time2] 关键字:[keyword] 请求:[result] 结果:[result2] 操作编码:[optionCoding]\n\n "; +// } withCompletion:nil class:[BSRecordModel class]]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored"-Wdeprecated-declarations" + //写在这个中间的代码,都不会被编译器提示-Wdeprecated-declarations类型的警告 + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"是否清空历史记录?" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + [alert show]; + +#pragma clang diagnostic pop + +} + +#pragma mark - alertView的代理方法 +#pragma clang diagnostic push +#pragma clang diagnostic ignored"-Wdeprecated-declarations" +-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ + if (buttonIndex == 1) { + //删除所有 + self.navigationItem.rightBarButtonItem.enabled = NO; + BSRecordModel *tempModel = [[BSRecordModel alloc] init]; + + + [_arr removeAllObjects]; + [_tableView reloadData]; + } +} +#pragma clang diagnostic pop + +#pragma mark - 数据源方法 +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + BSRecordModel *model = _arr[section]; + if (model.coding == 200) { + return 1; + }else{ + return 1; + } + +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *indentifiner = @"gwlog_table_cell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:indentifiner]; + if(cell == nil) + { + NSLog(@"创建cell1~~"); + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:indentifiner] ; + cell.textLabel.numberOfLines = 2; + } + + // 设置 Cell... + BSRecordModel *model = _arr[indexPath.section]; + if (model.coding == 200) { + if (indexPath.row == 0) { + cell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; + cell.textLabel.text = model.keyword; + + }else if (indexPath.row == 1){ + cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; + cell.textLabel.text = [BSNSStringUtil clearStr:model.result]; + }else{ + cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; + cell.textLabel.text = [BSNSStringUtil clearStr:model.result2]; + } + + }else{ + cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; + cell.textLabel.text = model.result; + } + + return cell; +} +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ + if (indexPath == 0) { + return 45; + }else{ + return 40; + } +} + + + + +#pragma mark - tableView分区设定 +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ + //分区数 + return _arr.count; +} +-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ + //分区高度 + return 30; +} + + +-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ + + BSRecordModel *model = _arr[section]; + + static NSString *identy = @"headhead"; + UITableViewHeaderFooterView * hf = [tableView dequeueReusableHeaderFooterViewWithIdentifier:identy]; + if (!hf) { + + NSLog(@"创建分区头~~"); + hf = [[UITableViewHeaderFooterView alloc]initWithReuseIdentifier:identy]; + UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 40)]; + view.backgroundColor = [BS_UIColor stringTOColor:@"#ecffff"]; + + UILabel *la = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, view.frame.size.width-40, 40)]; + [view addSubview:la]; + + + NSString *option = @"未知"; + if (model.optionCoding == -1) { + option = @"正在请求"; + }else if (model.optionCoding == 0) { + option = @"请求失败"; + }else if (model.optionCoding == 1) { + option = @"请求成功"; + } + NSMutableAttributedString *att = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"[%@],S:%d,R:%@",model.onlySign,model.coding,option]]; + + if (model.time2.length > 8 && model.time.length > 8) { + NSTimeInterval time = [BSXWDateUtil TimeDifferenceWithTime1:model.time2 AndTime2:model.time formet:nil]; + + UIColor *color = [UIColor blackColor]; + if (time > 30) { + color = [UIColor redColor]; + }else if(time > 15){ + color = [UIColor yellowColor]; + } + + [att appendAttributedString:[BSNSStringUtil getAttributedString:[NSString stringWithFormat:@",T:%.1fS",time] color:color font:14 lineSpa:5]]; + } + la.attributedText = att; + + la.font = [UIFont systemFontOfSize:10]; + + + UIButton *detailBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + detailBtn.tag = section; + [view addSubview:detailBtn]; + + [detailBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(40); + make.height.mas_equalTo(30); + make.bottom.equalTo(view).offset(-2); + make.trailing.equalTo(view).offset(-8); + }]; + + + [detailBtn setTitle:@"详细" forState:UIControlStateNormal]; + [detailBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; + [detailBtn addTarget:self action:@selector(onclicBtn:) forControlEvents:UIControlEventTouchUpInside]; + + + + [hf addSubview:view]; + } + return hf; + +} + + +-(void)onclicBtn:(UIButton *)btn{ + BSRecordModel *model = _arr[btn.tag]; + BSLogNetDetailViewController *tempView = [[BSLogNetDetailViewController alloc] init]; + tempView.model = model; + [self.navigationController pushViewController:tempView animated:YES]; + +} + + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h index 003ec0d..99f60e9 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h @@ -1,10 +1,8 @@ -// -// BSRealTextView.h -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import #import "RealViewCellModel.h" @@ -14,6 +12,6 @@ @property(nonatomic,strong)NSString *guid; @property(nonatomic,strong)NSString *number; -//初始化数据 + -(void)initData; @end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h.backup new file mode 100644 index 0000000..003ec0d --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.h.backup @@ -0,0 +1,19 @@ +// +// BSRealTextView.h +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import +#import "RealViewCellModel.h" + +@interface BSRealTextView : UIView +@property (nonatomic,strong)RealViewCellModel *tempModel; +@property(nonatomic,strong)NSString *guid; +@property(nonatomic,strong)NSString *number; + +//初始化数据 +-(void)initData; +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m index 1e91c11..f7b973e 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m @@ -1,10 +1,8 @@ -// -// BSRealTextView.m -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import "BSRealTextView.h" #import "BSRecordModel.h" @@ -14,11 +12,11 @@ @interface BSRealTextView() -@property (nonatomic, strong) UITextView *dataLabel;//显示的内容 +@property (nonatomic, strong) UITextView *dataLabel; @property (nonatomic, strong) NSMutableAttributedString *resultAttiText; -@property (nonatomic, strong) UIButton *option_close;//关闭 -@property (nonatomic, strong) UIButton *option_copy;//拷贝 -@property (nonatomic, strong) UILabel *numbLable;//数字 +@property (nonatomic, strong) UIButton *option_close; +@property (nonatomic, strong) UIButton *option_copy; +@property (nonatomic, strong) UILabel *numbLable; @end @implementation BSRealTextView @@ -79,7 +77,6 @@ _dataLabel.backgroundColor = [UIColor whiteColor]; - } #pragma mark - 关闭的方法 @@ -138,17 +135,10 @@ return [self getAttributedString:str color:color font:0 lineSpa:0]; } -//根据字体,颜色,返回富文本 + -(NSAttributedString *)getAttributedString:(NSString *)str color:(UIColor *)color font:(CGFloat)font lineSpa:(CGFloat)lineSpac{ return [BSNSStringUtil getAttributedString:str color:color font:font lineSpa:lineSpac]; } -/* -// Only override drawRect: if you perform custom drawing. -// An empty implementation adversely affects performance during animation. -- (void)drawRect:(CGRect)rect { - // Drawing code -} -*/ @end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m.backup new file mode 100644 index 0000000..1e91c11 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTextView.m.backup @@ -0,0 +1,154 @@ +// +// BSRealTextView.m +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import "BSRealTextView.h" +#import "BSRecordModel.h" +#import "Masonry.h" +#import "BSSDLayoutUtil.h" +#import "BSNSStringUtil.h" + +@interface BSRealTextView() + +@property (nonatomic, strong) UITextView *dataLabel;//显示的内容 +@property (nonatomic, strong) NSMutableAttributedString *resultAttiText; +@property (nonatomic, strong) UIButton *option_close;//关闭 +@property (nonatomic, strong) UIButton *option_copy;//拷贝 +@property (nonatomic, strong) UILabel *numbLable;//数字 +@end + +@implementation BSRealTextView + + +-(instancetype)init{ + + self = [super init]; + if (self) { + [self initView]; + } + + return self; +} + +-(void)initView{ + + + _option_close = [UIButton buttonWithType:UIButtonTypeCustom]; + [_option_close setTitle:@" x " forState:UIControlStateNormal]; + [_option_close addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_option_close]; + _option_close.backgroundColor = [UIColor greenColor]; + SDLAYOUT_wh2(_option_close, self, 0, self, 0, 40, 30) + + _option_copy = [UIButton buttonWithType:UIButtonTypeCustom]; + [_option_copy setTitle:@"copy" forState:UIControlStateNormal]; + [_option_copy addTarget:self action:@selector(onclickCopy:) forControlEvents:UIControlEventTouchUpInside]; + [_option_copy setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [self addSubview:_option_copy]; + [_option_copy mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_offset(0); + make.width.mas_offset(40); + make.height.mas_offset(30); + make.trailing.mas_offset(-55); + }]; + + _numbLable = [[UILabel alloc] init]; + [self addSubview:_numbLable]; + [_numbLable mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_offset(0); + make.width.mas_offset(50); + make.height.mas_offset(30); + make.leading.mas_offset(10); + }]; + _numbLable.textColor = [UIColor blackColor]; + _numbLable.textAlignment = NSTextAlignmentCenter; + + _dataLabel = [[UITextView alloc] init]; + _dataLabel.editable = NO; + [self addSubview:_dataLabel]; + [_dataLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_offset(30); + make.leading.mas_offset(4); + make.bottom.mas_offset(-4); + make.trailing.mas_offset(-4); + }]; + _dataLabel.backgroundColor = [UIColor whiteColor]; + + + +} + +#pragma mark - 关闭的方法 +-(void)onclick:(UIButton *)btn{ + if (self.subviews) { + [self removeFromSuperview]; + } +} + +#pragma mark - 拷贝的方法 +-(void)onclickCopy:(UIButton *)btn{ + + UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; + pasteboard.string = _dataLabel.attributedText.string; + [_option_copy setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; + +} + + +-(void)initData{ + + _resultAttiText = [[NSMutableAttributedString alloc] init]; + _resultAttiText = [[NSMutableAttributedString alloc] init]; + + [_resultAttiText appendAttributedString:[self getAttributedString:[NSString stringWithFormat:@"请求时间:%@",self.tempModel.time1]]]; + [_resultAttiText appendAttributedString:[self getAttributedString:[NSString stringWithFormat:@"\n响应时间:%@",self.tempModel.time2]]]; + [_resultAttiText appendAttributedString:[self getAttributedString:@"\n请求链接:"]]; + [_resultAttiText appendAttributedString:[self getAttributedString:self.tempModel.url color:[UIColor blueColor]]]; + + [_resultAttiText appendAttributedString:[self getAttributedString:@"\n请求header:\n"]]; + NSString *headStr = [NSString stringWithFormat:@"%@\n",[BSNSStringUtil getStringFromObj:self.tempModel.header]]; + [_resultAttiText appendAttributedString:[self getAttributedString:headStr color:[UIColor grayColor] font:12 lineSpa:3]]; + + [_resultAttiText appendAttributedString:[self getAttributedString:@"请求参数:\n"]]; + NSString *paramStr = [NSString stringWithFormat:@"%@\n",[BSNSStringUtil getStringFromObj:self.tempModel.param]]; + [_resultAttiText appendAttributedString:[self getAttributedString:paramStr color:[UIColor redColor] font:12 lineSpa:3]]; + + + [_resultAttiText appendAttributedString:[self getAttributedString:@"返回header:\n"]]; + NSString *headStr2 = [NSString stringWithFormat:@"%@\n",[BSNSStringUtil getStringFromObj:self.tempModel.backHeader]]; + [_resultAttiText appendAttributedString:[self getAttributedString:headStr2 color:[UIColor grayColor] font:12 lineSpa:3]]; + [_resultAttiText appendAttributedString:[self getAttributedString:@"结果:\n"]]; + UIColor *color = [UIColor redColor]; + NSString *resultStr = [NSString stringWithFormat:@"%@\n",[BSNSStringUtil getStringFromObj:self.tempModel.result]]; + [_resultAttiText appendAttributedString:[self getAttributedString:resultStr color:color font:12 lineSpa:3]]; + + _dataLabel.attributedText = _resultAttiText; + _numbLable.text = _number; +} + +-(NSAttributedString *)getAttributedString:(NSString *)str{ + return [self getAttributedString:str color:nil font:0 lineSpa:0]; +} + +-(NSAttributedString *)getAttributedString:(NSString *)str color:(UIColor *)color{ + return [self getAttributedString:str color:color font:0 lineSpa:0]; +} + +//根据字体,颜色,返回富文本 +-(NSAttributedString *)getAttributedString:(NSString *)str color:(UIColor *)color font:(CGFloat)font lineSpa:(CGFloat)lineSpac{ + return [BSNSStringUtil getAttributedString:str color:color font:font lineSpa:lineSpac]; +} + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h index 4eddabf..2e87621 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h @@ -1,10 +1,8 @@ -// -// RealTimeView.h -// BaseProject -// + + // Created by xiaowen.chen on 16/8/12. // Copyright © 2016年 xw.com. All rights reserved. -// + #import @@ -12,9 +10,7 @@ @interface BSRealTimeView : UIView -//取消实时监听 -(void)cancleINtime; - @end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h.backup new file mode 100644 index 0000000..4eddabf --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.h.backup @@ -0,0 +1,20 @@ +// +// RealTimeView.h +// BaseProject +// +// Created by xiaowen.chen on 16/8/12. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + + +@interface BSRealTimeView : UIView + + +//取消实时监听 +-(void)cancleINtime; + + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m index 6099bac..3d4d608 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m @@ -1,10 +1,8 @@ -// -// RealTimeView.m -// BaseProject -// + + // Created by xiaowen.chen on 16/8/12. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSRealTimeView.h" #import "BSSelectView.h" @@ -30,11 +28,6 @@ @property (nonatomic, assign) CGRect self_rect; -//@property (nonatomic, strong) UITextView *dataLabel; -//@property (nonatomic, strong) NSMutableAttributedString *resultAttiText; - - -//窗口操作按钮' @property (nonatomic, strong) UIButton *option; @property (nonatomic, strong) UIButton *option_clear; @property (nonatomic, strong) BSSelectView *option_intime; @@ -52,7 +45,7 @@ [self createMyView]; - //添加监听 todo + [BSNotification addHandler:^(NFMessageType type,NSString *key,NSObject *value) { NSDictionary *handleDic = (NSDictionary *)value; @@ -61,11 +54,11 @@ NSString *stateStr = handleDic[@"handle"]; if (stateStr) { if ([stateStr isEqualToString:@"netReq"]) { - //网络请求类的监听-请求 - [self printReq:handleDic[@"url"] header:handleDic[@"header"] param:handleDic[@"param"] time:handleDic[@"time"]];//发出网络请求 + + [self printReq:handleDic[@"url"] header:handleDic[@"header"] param:handleDic[@"param"] time:handleDic[@"time"]]; }else if([stateStr isEqualToString:@"netRsp"]){ - //网络请求类的监听-返回 + [self printRsp:handleDic[@"url"] header:handleDic[@"header"] result:handleDic[@"result"] isSuccess:handleDic[@"isSuccess"] time:handleDic[@"time"]]; }else{ @@ -87,16 +80,14 @@ -(void)createMyView{ _isMin = NO; - _model = 0;//移动模式 + _model = 0; _sc_width = [[UIScreen mainScreen] bounds].size.width; _sc_height = [[UIScreen mainScreen] bounds].size.height; -// _resultAttiText = [[NSMutableAttributedString alloc] init]; + self.clipsToBounds = YES; self.backgroundColor = [UIColor grayColor]; - - _option = [UIButton buttonWithType:UIButtonTypeCustom]; [_option setTitle:@" x " forState:UIControlStateNormal]; [_option addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchUpInside]; @@ -104,28 +95,17 @@ _option.backgroundColor = [UIColor greenColor]; SDLAYOUT_wh1(_option, self, 0, self, 0, 40, 30) - //双击事件 + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickClose:)]; - //设置点击次数 - tap.numberOfTapsRequired = 2;//主要 - //将这个手势添加到图片上 + + tap.numberOfTapsRequired = 2; + [_option addGestureRecognizer:tap]; - - - _dataArr = [NSMutableArray array]; -// for (int i = 0; i < 5; i++) { -// RealViewCellModel *modle = [[RealViewCellModel alloc] init]; -// [_dataArr addObject:modle]; -// } - -// _dataLabel = [[UITextView alloc] init]; -// _dataLabel.editable = NO; -// [self addSubview:_dataLabel]; -// SDLAYOUT(_dataLabel, self, 30, self, 2, self, -2, self, -30) - + + _tableView = [[UITableView alloc] init]; [self addSubview:_tableView]; _tableView.dataSource = self; @@ -140,16 +120,12 @@ self.tableView.backgroundColor = [BS_UIColor stringTOColor:@"#f4f4f4"]; - - - _opLable = [[UILabel alloc] init]; _opLable.text = @""; [self addSubview:_opLable]; SDLAYOUT_wh1(_opLable, _option, 5, self, 5, 50, 20) - _option_intime = [[BSSelectView alloc]init]; _option_intime.button.tag = 1001; _option_intime.label.textColor = [UIColor whiteColor]; @@ -160,7 +136,6 @@ SDLAYOUT_wh1(_option_intime, _option, 55, self, 10, 50, 20) - _option_clear = [UIButton buttonWithType:UIButtonTypeCustom]; [_option_clear setTitle:@"清空" forState:UIControlStateNormal]; [_option_clear addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchUpInside]; @@ -169,7 +144,6 @@ SDLAYOUT_wh3(_option_clear, self, 5, self, -5, 50, 20) - //把view放在最上面 [self bringSubviewToFront:_option]; } @@ -194,14 +168,10 @@ NSLog(@"暂无实现"); -// [_resultAttiText appendAttributedString:[self getAttributedString:str color:color font:font lineSpa:8]]; -// [self printToLable:[_resultAttiText copy]]; - } - #pragma mark - 特定格式的数据 -(void)printReq:(NSString *)url header:(NSDictionary *)headDic param:(NSDictionary *)param time:(NSString *)time{ @@ -228,10 +198,7 @@ -(void)printRsp:(NSString *)url header:(NSDictionary *)headDic result:(id)result isSuccess:(NSString *)isSuccess time:(NSString *)time{ -// if (![self isNeedToPrintWithType:@"rsp"]) { -// return; -// } - + for (RealViewCellModel *tempModel in _dataArr) { if ([tempModel.UI_rightStr isEqualToString:url]) { tempModel.result = result; @@ -249,15 +216,13 @@ } -//判断是否需要打印 -(Boolean)isNeedToPrintWithType:(NSString *)type{ if (!_option_intime.button.isSelected) { return NO; } - //print,req,rsp//根据配置决定是否打印 - + return YES; } @@ -268,7 +233,6 @@ } - #pragma mark - 富文本处理 +(void)printRsp:(NSString *)url header:(NSDictionary *)headDic result:(NSDictionary *)result{ @@ -276,7 +240,6 @@ } - -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ if (!_isCanMove) { return; @@ -287,7 +250,6 @@ } - #pragma mark - 外部启用事件 -(void)printDictionary:(NSDictionary *)dic{ if ([dic isKindOfClass:[NSDictionary class]]) { @@ -332,13 +294,11 @@ } -//点击事件 -(void)onclick:(UIButton *)btn{ if (btn == _option_clear) { -// _resultAttiText = [[NSMutableAttributedString alloc] init]; -// _dataLabel.attributedText = [_resultAttiText copy]; + [_dataArr removeAllObjects]; [_tableView reloadData]; @@ -356,22 +316,20 @@ } -//关闭事件 + -(void)clickClose:(UITapGestureRecognizer *)tap{ [BSNotification pushHandle:nil withName:@"netlisten_viewhide"]; [[NSNotificationCenter defaultCenter]postNotificationName:@"netlisten_viewhide1" object:nil userInfo:nil]; - //退出实时模式 + [_option_intime.button setSelected:NO]; } - - -(void)onclick_min:(UIButton *)btn{ - _self_rect = self.frame;//记录最小化前的坐标 + _self_rect = self.frame; [_option_clear setHidden:YES]; CGRect endRect = CGRectMake(_self_rect.origin.x, _self_rect.origin.y, _option.frame.size.width, _option.frame.size.height); @@ -401,9 +359,6 @@ } - - - #pragma clang diagnostic push #pragma clang diagnostic ignored"-Wdeprecated-declarations" @@ -412,7 +367,7 @@ if (buttonIndex == 1) { [BSNotification pushHandle:nil withName:@"netlisten_viewhide"]; [[NSNotificationCenter defaultCenter]postNotificationName:@"netlisten_viewhide1" object:nil userInfo:nil]; - //退出实时模式 + [_option_intime.button setSelected:NO]; } @@ -424,42 +379,39 @@ UITouch *touch = [touches anyObject]; CGPoint currentP = [touch locationInView:self]; -// NSLog(@"当前点击的位置:(%.2f,%.2f)",currentP.x,currentP.y); + if (currentP.x > self.frame.size.width - 40 && currentP.y > self.frame.size.height - 40) { _model = 1; -// NSLog(@"进入缩放状态"); + }else{ _model = 0; -// NSLog(@"进入移动状态"); + } } -//(2)触摸移动 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { -// if (!_isCanMove) { -// return; -// } - + + if (_model == 0) { -// NSLog(@"改变位置"); - //获取终点 + + self.userInteractionEnabled = NO; UITouch *touch = [touches anyObject]; - //当前的point + CGPoint currentP = [touch locationInView:self]; - //以前的point + CGPoint preP = [touch previousLocationInView:self]; - //x轴偏移的量 + CGFloat offsetX = currentP.x - preP.x; - //Y轴偏移的量 + CGFloat offsetY = currentP.y - preP.y; self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY); @@ -468,29 +420,24 @@ }else if(_model == 1){ - //最大的情况下不给缩放 -// if ([_option_max.titleLabel.text isEqualToString:@"还原"]) { -// return; -// } - //获取终点 self.userInteractionEnabled = NO; UITouch *touch = [touches anyObject]; - //当前的point + CGPoint currentP = [touch locationInView:self]; - //以前的point + CGPoint preP = [touch previousLocationInView:self]; - //x轴偏移的量 + CGFloat offsetX = currentP.x - preP.x; - //Y轴偏移的量 + CGFloat offsetY = currentP.y - preP.y; - //限制条件 + CGFloat tempWidth = self.frame.size.width + offsetX; CGFloat tempHeight = self.frame.size.height +offsetY; if (tempWidth < 165 || tempWidth > KScreenWidth || tempHeight < 150 || tempHeight > _sc_height) { @@ -500,7 +447,6 @@ } - self.frame = CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width + offsetX, self.frame.size.height +offsetY); @@ -589,10 +535,6 @@ } - - - - #pragma mark - 画图部分 -(void)drawRect:(CGRect)rect{ [super drawRect:rect]; @@ -604,7 +546,7 @@ NSString *point4 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width ,self.frame.size.height - 10]; NSString *point5 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width - 5,self.frame.size.height]; NSString *point6 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width ,self.frame.size.height - 5]; - //放大缩小的线 + [BSDrawLine drawLinePoint:@[@[@"1",@"255",@"255",@"255",@"1"],@[point1,point2],@[point3,point4],@[point5,point6]] withContext:UIGraphicsGetCurrentContext() scan:1]; } diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m.backup new file mode 100644 index 0000000..6099bac --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/BSRealTimeView.m.backup @@ -0,0 +1,613 @@ +// +// RealTimeView.m +// BaseProject +// +// Created by xiaowen.chen on 16/8/12. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSRealTimeView.h" +#import "BSSelectView.h" +#import "BSRecordModel.h" +#import "BSDrawLine.h" +#import +#import "RealViewNetWorkCell_0.h" +#import "BSRealTextView.h" +#import "BSNotification.h" +#import "BS_UIColor.h" +#import "BSSDLayoutUtil.h" + +@interface BSRealTimeView() + +@property (nonatomic, assign) Boolean isCanMove; +@property (nonatomic, strong) UIView *topView; +@property (nonatomic, strong) UITableView *tableView; +@property(nonatomic,strong)NSMutableArray *dataArr; + +@property (nonatomic, assign) int model; +@property (nonatomic, assign) CGFloat sc_width; +@property (nonatomic, assign) CGFloat sc_height; +@property (nonatomic, assign) CGRect self_rect; + + +//@property (nonatomic, strong) UITextView *dataLabel; +//@property (nonatomic, strong) NSMutableAttributedString *resultAttiText; + + +//窗口操作按钮' +@property (nonatomic, strong) UIButton *option; +@property (nonatomic, strong) UIButton *option_clear; +@property (nonatomic, strong) BSSelectView *option_intime; + + +@property (nonatomic, strong) UILabel *opLable; +@property (nonatomic, assign) Boolean isMin; + +@end + +@implementation BSRealTimeView + +-(instancetype)initWithFrame:(CGRect)frame{ + self = [super initWithFrame:frame]; + + [self createMyView]; + + //添加监听 todo + [BSNotification addHandler:^(NFMessageType type,NSString *key,NSObject *value) { + + NSDictionary *handleDic = (NSDictionary *)value; + dispatch_async(dispatch_get_main_queue(), ^{ + + NSString *stateStr = handleDic[@"handle"]; + if (stateStr) { + if ([stateStr isEqualToString:@"netReq"]) { + //网络请求类的监听-请求 + [self printReq:handleDic[@"url"] header:handleDic[@"header"] param:handleDic[@"param"] time:handleDic[@"time"]];//发出网络请求 + + }else if([stateStr isEqualToString:@"netRsp"]){ + //网络请求类的监听-返回 + [self printRsp:handleDic[@"url"] header:handleDic[@"header"] result:handleDic[@"result"] isSuccess:handleDic[@"isSuccess"] time:handleDic[@"time"]]; + + }else{ + [self print:@"不支持该打印模式..." isChangeLine:YES colors:[UIColor yellowColor] font:0]; + } + return; + } + [self printDictionary:handleDic]; + + }); + + + } withName:@"gwsdk_print"]; + + + return self; +} + +-(void)createMyView{ + + _isMin = NO; + _model = 0;//移动模式 + _sc_width = [[UIScreen mainScreen] bounds].size.width; + _sc_height = [[UIScreen mainScreen] bounds].size.height; +// _resultAttiText = [[NSMutableAttributedString alloc] init]; + self.clipsToBounds = YES; + self.backgroundColor = [UIColor grayColor]; + + + + + _option = [UIButton buttonWithType:UIButtonTypeCustom]; + [_option setTitle:@" x " forState:UIControlStateNormal]; + [_option addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_option]; + _option.backgroundColor = [UIColor greenColor]; + SDLAYOUT_wh1(_option, self, 0, self, 0, 40, 30) + + //双击事件 + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickClose:)]; + //设置点击次数 + tap.numberOfTapsRequired = 2;//主要 + //将这个手势添加到图片上 + [_option addGestureRecognizer:tap]; + + + + + + _dataArr = [NSMutableArray array]; +// for (int i = 0; i < 5; i++) { +// RealViewCellModel *modle = [[RealViewCellModel alloc] init]; +// [_dataArr addObject:modle]; +// } + +// _dataLabel = [[UITextView alloc] init]; +// _dataLabel.editable = NO; +// [self addSubview:_dataLabel]; +// SDLAYOUT(_dataLabel, self, 30, self, 2, self, -2, self, -30) + + _tableView = [[UITableView alloc] init]; + [self addSubview:_tableView]; + _tableView.dataSource = self; + _tableView.delegate = self; + [_tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_offset(30); + make.leading.mas_offset(1); + make.bottom.mas_offset(-30); + make.trailing.mas_offset(-1); + }]; + self.tableView.separatorStyle = NO; + self.tableView.backgroundColor = [BS_UIColor stringTOColor:@"#f4f4f4"]; + + + + + + _opLable = [[UILabel alloc] init]; + _opLable.text = @""; + [self addSubview:_opLable]; + SDLAYOUT_wh1(_opLable, _option, 5, self, 5, 50, 20) + + + + _option_intime = [[BSSelectView alloc]init]; + _option_intime.button.tag = 1001; + _option_intime.label.textColor = [UIColor whiteColor]; + [self addSubview:_option_intime]; + [_option_intime setTitle:@"实时" detail:@"" sender:self selector:@selector(buttonDidSelect:)]; + [_option_intime.button setSelected:YES]; + + SDLAYOUT_wh1(_option_intime, _option, 55, self, 10, 50, 20) + + + + _option_clear = [UIButton buttonWithType:UIButtonTypeCustom]; + [_option_clear setTitle:@"清空" forState:UIControlStateNormal]; + [_option_clear addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_option_clear]; + + SDLAYOUT_wh3(_option_clear, self, 5, self, -5, 50, 20) + + + //把view放在最上面 + [self bringSubviewToFront:_option]; +} + + +#pragma mark - 输出数据 +-(void)print:(NSString *)str isChangeLine:(Boolean)isChange colors:(UIColor*)color font:(CGFloat)font{ + + + if (![self isNeedToPrintWithType:@"print"]) { + return; + } + + if (isChange) { + str = [NSString stringWithFormat:@"%@\n",str]; + } + if (font == 0) { + font = 15; + } + if (color == nil) { + color = [UIColor blackColor]; + } + + NSLog(@"暂无实现"); + +// [_resultAttiText appendAttributedString:[self getAttributedString:str color:color font:font lineSpa:8]]; +// [self printToLable:[_resultAttiText copy]]; + + +} + + + +#pragma mark - 特定格式的数据 + +-(void)printReq:(NSString *)url header:(NSDictionary *)headDic param:(NSDictionary *)param time:(NSString *)time{ + + if (![self isNeedToPrintWithType:@"req"]) { + return; + } + + if (!url) { + url = @"---"; + } + + RealViewCellModel *modle = [[RealViewCellModel alloc] init]; + modle.UI_centerStr = @"请求..."; + modle.guid = time; + modle.header = headDic; + modle.time1 = time; + modle.param = param; + modle.UI_rightStr = url; + [_dataArr addObject:modle]; + [_tableView reloadData]; + +} + +-(void)printRsp:(NSString *)url header:(NSDictionary *)headDic result:(id)result isSuccess:(NSString *)isSuccess time:(NSString *)time{ + +// if (![self isNeedToPrintWithType:@"rsp"]) { +// return; +// } + + for (RealViewCellModel *tempModel in _dataArr) { + if ([tempModel.UI_rightStr isEqualToString:url]) { + tempModel.result = result; + tempModel.url = url; + tempModel.backHeader = headDic; + tempModel.time2 = time; + tempModel.isSuccess = [isSuccess isEqualToString:@"1"]; + tempModel.UI_centerStr = isSuccess; + [_tableView reloadData]; + break; + } + } + + +} + + +//判断是否需要打印 +-(Boolean)isNeedToPrintWithType:(NSString *)type{ + + if (!_option_intime.button.isSelected) { + return NO; + } + + //print,req,rsp//根据配置决定是否打印 + + return YES; +} + +#pragma mark - 外部调用的方法 + +-(void)cancleINtime{ + [_option_intime.button setSelected:NO]; +} + + + +#pragma mark - 富文本处理 + ++(void)printRsp:(NSString *)url header:(NSDictionary *)headDic result:(NSDictionary *)result{ + +} + + + +-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ + if (!_isCanMove) { + return; + } + + if (_model == 0 || _model == 1) { + } +} + + + +#pragma mark - 外部启用事件 +-(void)printDictionary:(NSDictionary *)dic{ + if ([dic isKindOfClass:[NSDictionary class]]) { + + id object = dic[@"printData"]; + Boolean isChange = [dic[@"isChangeLine"] isEqualToString:@"yes"] ? YES : NO; + CGFloat font = 0; + UIColor *color = nil; + if (!dic[@"font"]) { + font = [dic[@"font"] floatValue]; + } + + if ([dic[@"color"] isKindOfClass:[UIColor class]]) { + color = dic[@"color"]; + } + + if (object) { + if ([object isKindOfClass:[NSDictionary class]]) { + NSString *tempStr = [NSString stringWithFormat:@"%@",object]; + [self print:tempStr isChangeLine:isChange colors:color font:font]; + }else if([object isKindOfClass:[NSString class]]){ + [self print:object isChangeLine:isChange colors:color font:font]; + }else if([object isKindOfClass:[NSArray class]]){ + NSString *tempStr = [NSString stringWithFormat:@"%@",object]; + [self print:tempStr isChangeLine:isChange colors:color font:font]; + } + + } + } +} + + +#pragma mark - 点击事件 +-(void)buttonDidSelect:(UIButton *)btn{ + if(btn.tag == 1001){ + if (_option_intime.button.selected) { + [_option_intime.button setSelected:NO]; + }else{ + [_option_intime.button setSelected:YES]; + } + } +} + + +//点击事件 +-(void)onclick:(UIButton *)btn{ + + if (btn == _option_clear) { + +// _resultAttiText = [[NSMutableAttributedString alloc] init]; +// _dataLabel.attributedText = [_resultAttiText copy]; + [_dataArr removeAllObjects]; + [_tableView reloadData]; + + return; + } + + + if (_isMin) { + _isMin = NO; + [self onclick_min_end:btn]; + }else{ + _isMin = YES; + [self onclick_min:btn]; + } + +} + +//关闭事件 +-(void)clickClose:(UITapGestureRecognizer *)tap{ + [BSNotification pushHandle:nil withName:@"netlisten_viewhide"]; + [[NSNotificationCenter defaultCenter]postNotificationName:@"netlisten_viewhide1" object:nil userInfo:nil]; + + //退出实时模式 + [_option_intime.button setSelected:NO]; +} + + + + +-(void)onclick_min:(UIButton *)btn{ + + + _self_rect = self.frame;//记录最小化前的坐标 + [_option_clear setHidden:YES]; + + CGRect endRect = CGRectMake(_self_rect.origin.x, _self_rect.origin.y, _option.frame.size.width, _option.frame.size.height); + + [UIView animateWithDuration:0.2 animations:^{ + self.frame = endRect; + } completion:^(BOOL finished) { + self.frame = endRect; + + [_option_clear setHidden:NO]; + + + }]; + + +} + +-(void)onclick_min_end:(UIButton *)btn{ + + [UIView animateWithDuration:0.2 animations:^{ + self.frame = _self_rect; + } completion:^(BOOL finished) { + self.frame = _self_rect; + + }]; + +} + + + + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored"-Wdeprecated-declarations" + +-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ + + if (buttonIndex == 1) { + [BSNotification pushHandle:nil withName:@"netlisten_viewhide"]; + [[NSNotificationCenter defaultCenter]postNotificationName:@"netlisten_viewhide1" object:nil userInfo:nil]; + //退出实时模式 + [_option_intime.button setSelected:NO]; + + } + +} +#pragma clang diagnostic pop + +-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + + UITouch *touch = [touches anyObject]; + CGPoint currentP = [touch locationInView:self]; +// NSLog(@"当前点击的位置:(%.2f,%.2f)",currentP.x,currentP.y); + + if (currentP.x > self.frame.size.width - 40 && currentP.y > self.frame.size.height - 40) { + _model = 1; +// NSLog(@"进入缩放状态"); + }else{ + _model = 0; +// NSLog(@"进入移动状态"); + } + +} + + +//(2)触摸移动 +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { +// if (!_isCanMove) { +// return; +// } + + if (_model == 0) { +// NSLog(@"改变位置"); + //获取终点 + self.userInteractionEnabled = NO; + + UITouch *touch = [touches anyObject]; + + //当前的point + CGPoint currentP = [touch locationInView:self]; + + //以前的point + CGPoint preP = [touch previousLocationInView:self]; + + //x轴偏移的量 + CGFloat offsetX = currentP.x - preP.x; + + //Y轴偏移的量 + CGFloat offsetY = currentP.y - preP.y; + + self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY); + + self.userInteractionEnabled = YES; + + }else if(_model == 1){ + + //最大的情况下不给缩放 +// if ([_option_max.titleLabel.text isEqualToString:@"还原"]) { +// return; +// } + + //获取终点 + self.userInteractionEnabled = NO; + + UITouch *touch = [touches anyObject]; + + //当前的point + CGPoint currentP = [touch locationInView:self]; + + //以前的point + CGPoint preP = [touch previousLocationInView:self]; + + //x轴偏移的量 + CGFloat offsetX = currentP.x - preP.x; + + //Y轴偏移的量 + CGFloat offsetY = currentP.y - preP.y; + + //限制条件 + CGFloat tempWidth = self.frame.size.width + offsetX; + CGFloat tempHeight = self.frame.size.height +offsetY; + if (tempWidth < 165 || tempWidth > KScreenWidth || tempHeight < 150 || tempHeight > _sc_height) { + + self.userInteractionEnabled = YES; + return; + } + + + + self.frame = CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width + offsetX, self.frame.size.height +offsetY); + + + self.userInteractionEnabled = YES; + + } + + +} + +-(void)dealloc{ + + [BSNotification removeHandler:@"gwsdk_print"]; + +} + +#pragma mark - tableView代理方法 +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return _dataArr.count; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ + + RealViewCellModel *tempModel = _dataArr[indexPath.row]; + if (tempModel.type == 0) { + return tempModel.rightCellHeight; + } + return 190; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + + RealViewCellModel *tempModel = _dataArr[indexPath.row]; + tempModel.UI_leftStr = [NSString stringWithFormat:@"%d",(int)indexPath.row]; + if (tempModel.type == 0) { + static NSString *identifier = @"RealViewNetWorkCell_0"; + RealViewNetWorkCell_0 *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + if (!cell) + { + cell = [[RealViewNetWorkCell_0 alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; + } + cell.model = tempModel; + return cell; + } + + return nil; + +} + +-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{ + return YES; +} +- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { + @kWeakify(self) + UITableViewRowAction * deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"置頂" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { + @kStrongify(self) + if (indexPath.row < self.dataArr.count) { + [self.dataArr xpSafeRemoveObjectAtIndex:indexPath.row]; + [self.tableView reloadData]; + } + }]; + deleteAction.title = @"刪除"; + deleteAction.backgroundColor = [UIColor redColor]; + return @[deleteAction]; +} +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ + + + RealViewCellModel *tempModel = _dataArr[indexPath.row]; + if (tempModel.type == 0) { + BSRealTextView *textView = [[BSRealTextView alloc] init]; + textView.tempModel = tempModel; + textView.guid = tempModel.guid; + textView.number = tempModel.UI_leftStr; + [textView initData]; + [self addSubview:textView]; + [textView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_offset(30); + make.leading.mas_offset(0); + make.bottom.mas_offset(-30); + make.trailing.mas_offset(0); + }]; + textView.backgroundColor = [BS_UIColor stringTOColor:@"#f4f4f4"]; + } + +} + + + + + + +#pragma mark - 画图部分 +-(void)drawRect:(CGRect)rect{ + [super drawRect:rect]; + + if (_isCanMove) { + NSString *point1 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width - 15,self.frame.size.height]; + NSString *point2 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width ,self.frame.size.height - 15]; + NSString *point3 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width - 10,self.frame.size.height]; + NSString *point4 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width ,self.frame.size.height - 10]; + NSString *point5 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width - 5,self.frame.size.height]; + NSString *point6 = [NSString stringWithFormat:@"%.2f,%.2f",self.frame.size.width ,self.frame.size.height - 5]; + //放大缩小的线 + [BSDrawLine drawLinePoint:@[@[@"1",@"255",@"255",@"255",@"1"],@[point1,point2],@[point3,point4],@[point5,point6]] withContext:UIGraphicsGetCurrentContext() scan:1]; + } + +} + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h index 861d22e..1685d05 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h @@ -1,10 +1,8 @@ -// -// RealViewCellModel.h -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import #import @@ -21,10 +19,7 @@ @property (nonatomic,copy) NSString *time2; - - - -@property(nonatomic,assign)int type;//0 +@property(nonatomic,assign)int type; @property(nonatomic,strong)NSString *guid; @property(nonatomic,strong)NSString *UI_leftStr; @@ -39,7 +34,7 @@ @property(nonatomic,strong)NSString *UI_rightStr; @property(nonatomic,assign)CGFloat rightFont; @property(nonatomic,strong)UIColor *rightColor; -@property(nonatomic,assign)CGFloat rightCellHeight;//实际的高度 +@property(nonatomic,assign)CGFloat rightCellHeight; @end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h.backup new file mode 100644 index 0000000..861d22e --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.h.backup @@ -0,0 +1,45 @@ +// +// RealViewCellModel.h +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import +#import + +@interface RealViewCellModel : PIBaseModel +@property (nonatomic,assign) BOOL isSuccess; +@property (nonatomic,copy) id result; +@property (nonatomic,copy) NSString *url; +@property (nonatomic,copy) NSDictionary * header; +@property (nonatomic,copy) NSDictionary * backHeader; +@property (nonatomic,copy) NSDictionary * param; + +@property (nonatomic,copy) NSString *time1; +@property (nonatomic,copy) NSString *time2; + + + + + +@property(nonatomic,assign)int type;//0 +@property(nonatomic,strong)NSString *guid; + +@property(nonatomic,strong)NSString *UI_leftStr; +@property(nonatomic,assign)CGFloat leftFont; +@property(nonatomic,strong)UIColor *leftColor; + +@property(nonatomic,strong)NSString *UI_centerStr; +@property(nonatomic,assign)CGFloat centerFont; +@property(nonatomic,strong)UIColor *centerColor; + + +@property(nonatomic,strong)NSString *UI_rightStr; +@property(nonatomic,assign)CGFloat rightFont; +@property(nonatomic,strong)UIColor *rightColor; +@property(nonatomic,assign)CGFloat rightCellHeight;//实际的高度 + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m index eb19e5f..1ff506c 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m @@ -1,10 +1,8 @@ -// -// RealViewCellModel.m -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import "RealViewCellModel.h" diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m.backup new file mode 100644 index 0000000..eb19e5f --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/model/RealViewCellModel.m.backup @@ -0,0 +1,13 @@ +// +// RealViewCellModel.m +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import "RealViewCellModel.h" + +@implementation RealViewCellModel + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h index 668f24d..48f658b 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h @@ -1,10 +1,8 @@ -// -// RealViewNetWorkCell_0.h -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import #import "RealViewCellModel.h" diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h.backup new file mode 100644 index 0000000..668f24d --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.h.backup @@ -0,0 +1,21 @@ +// +// RealViewNetWorkCell_0.h +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import +#import "RealViewCellModel.h" + +@interface RealViewNetWorkCell_0 : UITableViewCell + +@property(nonatomic,strong)RealViewCellModel *model; + +@property(nonatomic,strong)UILabel *leftLable; +@property(nonatomic,strong)UILabel *centerLable; +@property(nonatomic,strong)UILabel *rightLable; + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m index 93bb088..deffad5 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m @@ -1,10 +1,8 @@ -// -// RealViewNetWorkCell_0.m -// TextSdk -// + + // Created by xiaowen on 2017/9/22. // Copyright © 2017年 gatawang.com. All rights reserved. -// + #import "RealViewNetWorkCell_0.h" #import "Masonry.h" @@ -25,8 +23,6 @@ -(void)initUI{ - - _rightLable = [[UILabel alloc] init]; [self addSubview:_rightLable]; [_rightLable mas_makeConstraints:^(MASConstraintMaker *make) { @@ -52,8 +48,7 @@ _leftLable.layer.masksToBounds = YES; _leftLable.layer.borderWidth = 0.5; _leftLable.backgroundColor = [UIColor redColor]; -// _leftLable.text = @"100"; - + _centerLable = [[UILabel alloc] init]; [self addSubview:_centerLable]; @@ -64,9 +59,7 @@ make.height.mas_offset(35); }]; _centerLable.textAlignment = NSTextAlignmentCenter; -// _centerLable.text = @"请求..."; - - + } @@ -87,20 +80,7 @@ _leftLable.layer.borderColor = [BS_UIColor stringTOColor:@"#181818"].CGColor; } -// _centerLable.text = model.UI_centerStr; -// //中间的描述 -// if (model.centerFont != 0) { -// _centerLable.font = AUTOADAPFont(model.centerFont]; -// }else{ -// _centerLable.font = AUTOADAPFont(12]; -// } -// if (model.centerColor != nil) { -// _centerLable.textColor = model.centerColor; -// }else{ -// _centerLable.textColor = [BS_UIColor stringTOColor:@"#181818"]; -// } - - //右边的描述 + if ([model.UI_rightStr isKindOfClass:[NSNull class]]) { model.UI_rightStr = @""; } @@ -139,16 +119,15 @@ } - - (void)awakeFromNib { [super awakeFromNib]; - // Initialization code + } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; - // Configure the view for the selected state + } @end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m.backup new file mode 100644 index 0000000..93bb088 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/RealTime(实时)/view/RealViewNetWorkCell_0.m.backup @@ -0,0 +1,154 @@ +// +// RealViewNetWorkCell_0.m +// TextSdk +// +// Created by xiaowen on 2017/9/22. +// Copyright © 2017年 gatawang.com. All rights reserved. +// + +#import "RealViewNetWorkCell_0.h" +#import "Masonry.h" +#import "BS_UIColor.h" + +@implementation RealViewNetWorkCell_0 + + +-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.contentView.userInteractionEnabled = YES; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self initUI]; + } + return self; +} + +-(void)initUI{ + + + + + _rightLable = [[UILabel alloc] init]; + [self addSubview:_rightLable]; + [_rightLable mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self); + make.leading.mas_offset(35); + make.trailing.mas_offset(-10); + make.height.mas_offset(35); + }]; + _rightLable.textAlignment = NSTextAlignmentRight; + _rightLable.text = @"openapi/jfidnfdinfdnfd/fdinfidfndf/nfidjfidjfdijf"; + _rightLable.lineBreakMode = NSLineBreakByTruncatingHead; + + _leftLable = [[UILabel alloc] init]; + [self addSubview:_leftLable]; + [_leftLable mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contentView); + make.leading.mas_offset(5); + make.width.mas_offset(20); + make.height.mas_offset(20); + }]; + _leftLable.textAlignment = NSTextAlignmentCenter; + _leftLable.layer.cornerRadius = 10; + _leftLable.layer.masksToBounds = YES; + _leftLable.layer.borderWidth = 0.5; + _leftLable.backgroundColor = [UIColor redColor]; +// _leftLable.text = @"100"; + + + _centerLable = [[UILabel alloc] init]; + [self addSubview:_centerLable]; + [_centerLable mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(_rightLable); + make.leading.equalTo(_leftLable.mas_trailing).mas_offset(5); + make.width.mas_offset(0); + make.height.mas_offset(35); + }]; + _centerLable.textAlignment = NSTextAlignmentCenter; +// _centerLable.text = @"请求..."; + + + +} + +-(void)setModel:(RealViewCellModel *)model{ + + _model = model; + _leftLable.text = model.UI_leftStr; + if (model.leftFont != 0) { + _leftLable.font = [UIFont systemFontOfSize:model.leftFont] ; + }else{ + _leftLable.font = [UIFont systemFontOfSize:12]; + } + if (model.leftColor != nil) { + _leftLable.textColor = model.leftColor; + _leftLable.layer.borderColor = model.leftColor.CGColor; + }else{ + _leftLable.textColor = [BS_UIColor stringTOColor:@"#181818"]; + _leftLable.layer.borderColor = [BS_UIColor stringTOColor:@"#181818"].CGColor; + } + +// _centerLable.text = model.UI_centerStr; +// //中间的描述 +// if (model.centerFont != 0) { +// _centerLable.font = AUTOADAPFont(model.centerFont]; +// }else{ +// _centerLable.font = AUTOADAPFont(12]; +// } +// if (model.centerColor != nil) { +// _centerLable.textColor = model.centerColor; +// }else{ +// _centerLable.textColor = [BS_UIColor stringTOColor:@"#181818"]; +// } + + //右边的描述 + if ([model.UI_rightStr isKindOfClass:[NSNull class]]) { + model.UI_rightStr = @""; + } + _rightLable.text = model.UI_rightStr; + if (model.rightFont != 0) { + _rightLable.font = [UIFont systemFontOfSize:model.rightFont] ; + }else{ + _rightLable.font = [UIFont systemFontOfSize:12]; + } + if (model.leftColor != nil) { + _rightLable.textColor = model.rightColor; + }else{ + _rightLable.textColor = [BS_UIColor stringTOColor:@"#676767"]; + } + + if ([model.UI_centerStr isEqualToString:@"0"]) { + + UIColor *redCor = [BS_UIColor stringTOColor:@"#ff2d2d"];; + _rightLable.textColor = redCor; + _leftLable.textColor = redCor; + _leftLable.layer.borderColor = redCor.CGColor; + } + + model.rightCellHeight = 40; + + UIView *view = [[UIView alloc] init]; + [self.contentView addSubview:view]; + [view mas_makeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_offset(-1); + make.leading.mas_offset(5); + make.trailing.mas_offset(-5); + make.height.mas_offset(0.5); + }]; + view.backgroundColor = [BS_UIColor stringTOColor:@"#f0f0f0"]; + +} + + + +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h index 6d47d3c..30d5e86 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h @@ -1,28 +1,20 @@ -// -// SelectView.h -// lianxi -// + + // Created by 陈奕智 on 16/7/7. // Copyright © 2016年 chenyizhi. All rights reserved. -// + #import @interface BSSelectView : UIView -/** - * 按钮 - */ + + @property (nonatomic, strong) UIButton *button; -/** - * 标签 - */ + + @property (nonatomic, strong) UILabel *label; -/** - * title,detail 显示文字 - * sender,selector 按钮添加点击方法参数 - */ -(void)setTitle:(NSString*)title detail:(NSString*)detail sender:(id)sender selector:(SEL)selector; diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h.backup new file mode 100644 index 0000000..6d47d3c --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.h.backup @@ -0,0 +1,29 @@ +// +// SelectView.h +// lianxi +// +// Created by 陈奕智 on 16/7/7. +// Copyright © 2016年 chenyizhi. All rights reserved. +// + +#import + +@interface BSSelectView : UIView +/** + * 按钮 + */ +@property (nonatomic, strong) UIButton *button; +/** + * 标签 + */ +@property (nonatomic, strong) UILabel *label; + + +/** + * title,detail 显示文字 + * sender,selector 按钮添加点击方法参数 + */ +-(void)setTitle:(NSString*)title detail:(NSString*)detail sender:(id)sender selector:(SEL)selector; + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m index 1695044..23dc28a 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m @@ -1,10 +1,8 @@ -// -// SelectView.m -// lianxi -// + + // Created by 陈奕智 on 16/7/7. // Copyright © 2016年 chenyizhi. All rights reserved. -// + #import "BSSelectView.h" #import "Masonry.h" @@ -42,7 +40,6 @@ static int const FONTSIZE = 14; }]; - } return self; } diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m.backup new file mode 100644 index 0000000..1695044 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/component(组件)/BSSelectView.m.backup @@ -0,0 +1,71 @@ +// +// SelectView.m +// lianxi +// +// Created by 陈奕智 on 16/7/7. +// Copyright © 2016年 chenyizhi. All rights reserved. +// + +#import "BSSelectView.h" +#import "Masonry.h" + +static int const FONTSIZE = 14; + + +@implementation BSSelectView + + +-(instancetype)init{ + self = [super init]; + if (self) { + + self.button = [[UIButton alloc]init]; + [self addSubview:self.button]; + [self.button setImage:[UIImage imageNamed:@"pay_off"] forState:UIControlStateNormal]; + [self.button setImage:[UIImage imageNamed:@"pay_on"] forState:UIControlStateSelected]; + + + [self.button mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self).offset(0); + make.top.equalTo(self).offset(0); + make.width.mas_equalTo(12); + make.height.mas_equalTo(12); + }]; + + self.label = [[UILabel alloc]init]; + [self addSubview:self.label]; + + [self.label mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.equalTo(self).offset(12); + make.bottom.equalTo(self).offset(-4); + make.width.mas_equalTo(40); + }]; + + + + } + return self; +} + + +-(void)setTitle:(NSString *)title detail:(NSString *)detail sender:(id)sender selector:(SEL)selector { + NSInteger len1 = title.length; + NSInteger len2 = detail.length; + NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"%@%@", title, detail]]; + [attStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:FONTSIZE weight:UIFontWeightBold] range:NSMakeRange(0, len1)]; + [attStr addAttribute:NSFontAttributeName value:[UIFont italicSystemFontOfSize:FONTSIZE-2] range:NSMakeRange(len1, len2)]; + [attStr addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, len1)]; + [attStr addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(len1, len2)]; + self.label.attributedText = attStr; + + + [self.button addTarget:sender action:selector forControlEvents:UIControlEventTouchUpInside]; +} + + +-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + [self.button sendActionsForControlEvents:UIControlEventTouchUpInside]; +} + + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h index 9117a11..bda1819 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h @@ -1,46 +1,42 @@ -// -// BSRecordModel.h -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/18. // Copyright © 2016年 xw.com. All rights reserved. -// + #import @interface BSRecordModel : PIBaseModel -//类型编码 + @property (nonatomic, assign) int coding; -//关键字 + @property (nonatomic, strong) NSString *keyword; -//描述 + @property (nonatomic, strong) NSString *describe; -//描述2 + @property (nonatomic, strong) NSString *describe2; -//操作编码 + @property (nonatomic, assign) int optionCoding; -//唯一标示 + @property (nonatomic, strong) NSString *onlySign; -//时间 @property (nonatomic, strong) NSString *time; -//详细时间 + @property (nonatomic, strong) NSString *time2; -//结果 -@property (nonatomic, strong) NSString *result; -//结果2 -@property (nonatomic, strong) NSString *result2; +@property (nonatomic, strong) NSString *result; + +@property (nonatomic, strong) NSString *result2; +(BSRecordModel *)recordModelWith:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option; diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h.backup new file mode 100644 index 0000000..9117a11 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.h.backup @@ -0,0 +1,50 @@ +// +// BSRecordModel.h +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/18. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + + +@interface BSRecordModel : PIBaseModel + +//类型编码 +@property (nonatomic, assign) int coding; + +//关键字 +@property (nonatomic, strong) NSString *keyword; + +//描述 +@property (nonatomic, strong) NSString *describe; + +//描述2 +@property (nonatomic, strong) NSString *describe2; + +//操作编码 +@property (nonatomic, assign) int optionCoding; + +//唯一标示 +@property (nonatomic, strong) NSString *onlySign; + + +//时间 +@property (nonatomic, strong) NSString *time; + +//详细时间 +@property (nonatomic, strong) NSString *time2; + +//结果 +@property (nonatomic, strong) NSString *result; +//结果2 +@property (nonatomic, strong) NSString *result2; + + + ++(BSRecordModel *)recordModelWith:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option; + ++(NSString *)getStringWithDate:(NSDate *)date format:(NSString *)format; + +@end diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m index 3193918..fd18d0d 100644 --- a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m @@ -1,15 +1,13 @@ -// -// RecordModel.m -// GWTestSDK -// + + // Created by xiaowen.chen on 16/8/18. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSRecordModel.h" @implementation BSRecordModel -// + -(NSDictionary *)getAttribute{ return @{ diff --git a/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m.backup b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m.backup new file mode 100644 index 0000000..3193918 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/NetListen(网络监听)/model/BSRecordModel.m.backup @@ -0,0 +1,89 @@ +// +// RecordModel.m +// GWTestSDK +// +// Created by xiaowen.chen on 16/8/18. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSRecordModel.h" + +@implementation BSRecordModel +// +-(NSDictionary *)getAttribute{ + + return @{ + @"coding":@"INTEGER", + @"keyword":@"TEXT", + @"describe":@"TEXT", + @"describe2":@"TEXT", + @"optionCoding":@"INTEGER", + @"time":@"DATETIME", + @"time2":@"DATETIME", + @"onlySign":@"TEXT", + @"result":@"TEXT", + @"result2":@"TEXT" + }; + +} + + ++(BSRecordModel *)recordModelWith:(int)coding keyword:(NSString *)keyword describe:(NSString *)describe option:(int)option{ + if([keyword rangeOfString:@","].location !=NSNotFound) + { + keyword = @"不合法的keyword"; + } + if([describe rangeOfString:@","].location !=NSNotFound) + { + describe = @"不合法的describe"; + } + + BSRecordModel *recordModel = [[BSRecordModel alloc] init]; + recordModel.coding = coding; + recordModel.keyword = keyword; + recordModel.describe = describe; + recordModel.optionCoding = option; + recordModel.time = [self getStringWithDate:nil format:nil]; + + return recordModel; +} + ++(NSString *)getStringWithDate:(NSDate *)date format:(NSString *)format +{ + if (date == nil) { + date = [NSDate date]; + } + if (format == nil) { + format = @"yyyyMMdd HH:mm:ss.SSS"; + } + NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; + [formatter setDateFormat:format]; + return [formatter stringFromDate:date]; +} + +-(NSString *)description{ + return [NSString stringWithFormat:@"%d,[%@],%@,%@,%d\n",_coding,[_time substringWithRange:NSMakeRange(9, 8)],_keyword,_describe,_optionCoding]; +} + + +-(id)copy{ + BSRecordModel *resultId = [[BSRecordModel alloc] init]; + resultId.coding = _coding; + resultId.keyword = _keyword; + resultId.describe = _describe; + resultId.describe2 = _describe2; + resultId.optionCoding = _optionCoding; + resultId.onlySign = _onlySign; + resultId.time = _time; + resultId.time2 = _time2; + resultId.result = _result; + resultId.result2 = _result2; + + return resultId; +} + +-(void)setValue:(id)value forUndefinedKey:(NSString *)key{ + +} + +@end diff --git a/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h index e5830ed..67872ed 100644 --- a/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h +++ b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h @@ -1,22 +1,20 @@ -// -// XWNotification.h -// BaseProject -// + + // Created by xiaowen.chen on 16/7/19. // Copyright © 2016年 xw.com. All rights reserved. -// + #import enum{ - //简单的消息 + NFMessageType_Simple, - //api消息 + NFMessageType_API, - //主题消息 + NFMessageType_Theme, - //自定义消息 + NFMessageType_Custom }typedef NFMessageType; @@ -28,105 +26,45 @@ typedef NSDictionary *(^GWSingleHandleOption)(NSDictionary *handleDic); @interface BSNotification : NSObject -/** - 添加处理方法,在viewdeload或者viewwillAppear里面添加,object对象的地址h加key确定唯一性 - - @param block 回调方法块 - @param handleName 处理标识名 - @param object 对象实例 - */ +(void)addHandler:(GWHandleOption)block withName:(NSString *)handleName andObject:(NSObject *)object; -/** - 移除处理方法,在dealloc或者viewwillDisAppear里面移除,object对象的地址加key确定唯一性 - - @param handleName 处理标识名 - @param object 对象实例 - */ + +(void)removeHandler:(NSString *)handleName andObject:(NSObject *)object; -/** - 添加处理方法,在viewdeload或者viewwillAppear里面添加,添加重复的name无效 - @param block 回调方法块 - @param handleName 处理标识名 - */ +(void)addHandler:(GWHandleOption)block withName:(NSString *)handleName; -/** - 移除处理方法,在dealloc或者viewwillDisAppear里面移除 - - @param name 处理标识名 - */ +(void)removeHandler:(NSString *)name; -/** - 推送消息-简化版本 - - @param handleDic 参数字典 - @param handleName 处理标识名 - */ +(void)pushHandle:(NSDictionary *)handleDic withName:(NSString *)handleName; -/** - 推送消息-简化版本 - - @param type 消息类型 - @param key key - @param value 结果对象 - @param handleName 处理标识名 - */ + +(void)pushHandle:(NFMessageType)type withKey:(NSString *)key value:(NSObject *)value withName:(NSString *)handleName; -/** - 获取所有的注册信息,调试的时候用 - @return 处理标识名数组 - */ +(NSMutableDictionary *)getHandleDic; #pragma mark - 有返回值的做法,可以用在一个页面向另外一个页面取值,要求是1对1,不然会出异常 -/** - 添加一个唯一的处理方法 - @param block 回调方法块 - @param handleName 处理标识名 - */ + +(void)addSingleHandler:(GWSingleHandleOption)block withName:(NSString *)handleName; -/** - 触发唯一的处理方法,并且从唯一的处理方法中获取结果 - @param handleDic 参数字典 - @param handleName 处理标识名 - @return 结果字典 - */ +(NSDictionary *)getResultFromSingleHandle:(NSDictionary *)handleDic withName:(NSString *)handleName; #pragma mark - 批量移除的方法 -/** - 移除所有 - */ +(void)removeAllHandle; -/** - 移除所有不是指定字符串开头的 - @param str 指定字符串 - */ +(void)removeHandleNotInclude:(NSString *)str; -/** - 移除所有指定字符串开头的 - @param str 指定字符串 - */ +(void)removeHandleInclude:(NSString *)str; @end diff --git a/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h.backup b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h.backup new file mode 100644 index 0000000..e5830ed --- /dev/null +++ b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.h.backup @@ -0,0 +1,132 @@ +// +// XWNotification.h +// BaseProject +// +// Created by xiaowen.chen on 16/7/19. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import + + +enum{ + //简单的消息 + NFMessageType_Simple, + //api消息 + NFMessageType_API, + //主题消息 + NFMessageType_Theme, + //自定义消息 + NFMessageType_Custom + +}typedef NFMessageType; + + +typedef void(^GWHandleOption)(NFMessageType type,NSString *key,NSObject *value); +typedef NSDictionary *(^GWSingleHandleOption)(NSDictionary *handleDic); + +@interface BSNotification : NSObject + + +/** + 添加处理方法,在viewdeload或者viewwillAppear里面添加,object对象的地址h加key确定唯一性 + + @param block 回调方法块 + @param handleName 处理标识名 + @param object 对象实例 + */ ++(void)addHandler:(GWHandleOption)block withName:(NSString *)handleName andObject:(NSObject *)object; + +/** + 移除处理方法,在dealloc或者viewwillDisAppear里面移除,object对象的地址加key确定唯一性 + + @param handleName 处理标识名 + @param object 对象实例 + */ ++(void)removeHandler:(NSString *)handleName andObject:(NSObject *)object; + +/** + 添加处理方法,在viewdeload或者viewwillAppear里面添加,添加重复的name无效 + + @param block 回调方法块 + @param handleName 处理标识名 + */ ++(void)addHandler:(GWHandleOption)block withName:(NSString *)handleName; + + +/** + 移除处理方法,在dealloc或者viewwillDisAppear里面移除 + + @param name 处理标识名 + */ ++(void)removeHandler:(NSString *)name; + + +/** + 推送消息-简化版本 + + @param handleDic 参数字典 + @param handleName 处理标识名 + */ ++(void)pushHandle:(NSDictionary *)handleDic withName:(NSString *)handleName; + +/** + 推送消息-简化版本 + + @param type 消息类型 + @param key key + @param value 结果对象 + @param handleName 处理标识名 + */ ++(void)pushHandle:(NFMessageType)type withKey:(NSString *)key value:(NSObject *)value withName:(NSString *)handleName; + +/** + 获取所有的注册信息,调试的时候用 + + @return 处理标识名数组 + */ ++(NSMutableDictionary *)getHandleDic; + + +#pragma mark - 有返回值的做法,可以用在一个页面向另外一个页面取值,要求是1对1,不然会出异常 +/** + 添加一个唯一的处理方法 + + @param block 回调方法块 + @param handleName 处理标识名 + */ ++(void)addSingleHandler:(GWSingleHandleOption)block withName:(NSString *)handleName; + +/** + 触发唯一的处理方法,并且从唯一的处理方法中获取结果 + + @param handleDic 参数字典 + @param handleName 处理标识名 + @return 结果字典 + */ ++(NSDictionary *)getResultFromSingleHandle:(NSDictionary *)handleDic withName:(NSString *)handleName; + + +#pragma mark - 批量移除的方法 + + +/** + 移除所有 + */ ++(void)removeAllHandle; + +/** + 移除所有不是指定字符串开头的 + + @param str 指定字符串 + */ ++(void)removeHandleNotInclude:(NSString *)str; + +/** + 移除所有指定字符串开头的 + + @param str 指定字符串 + */ ++(void)removeHandleInclude:(NSString *)str; + +@end diff --git a/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m index 0e138f9..b5afdab 100644 --- a/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m +++ b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m @@ -1,10 +1,8 @@ - // -// XWNotification.m -// BaseProject -// + + // Created by xiaowen.chen on 16/7/19. // Copyright © 2016年 xw.com. All rights reserved. -// + #import "BSNotification.h" @@ -47,7 +45,6 @@ static NSString *objectSplit = @"_obj_"; } - #pragma mark - 移除处理方法 +(void)removeHandler:(NSString *)name{ @@ -62,7 +59,6 @@ static NSString *objectSplit = @"_obj_"; } - #pragma mark - 推送处理-简化版本 +(void)pushHandle:(NSDictionary *)handleDic withName:(NSString *)handleName{ @@ -91,9 +87,7 @@ static NSString *objectSplit = @"_obj_"; #pragma mark - 有返回值的做法,可以用在一个页面向另外一个页面取值,要求是1对1,不然会出异常 -/* - * 添加一个唯一的处理方法 - */ + +(void)addSingleHandler:(GWSingleHandleOption)block withName:(NSString *)handleName{ [self checkClass]; @@ -113,9 +107,8 @@ static NSString *objectSplit = @"_obj_"; [bs_handlerDic setObject:block forKey:handleName]; } } -/* - * 触发唯一的处理方法,并且从唯一的处理方法中获取结果 - */ + + +(NSDictionary *)getResultFromSingleHandle:(NSDictionary *)handleDic withName:(NSString *)handleName{ [self checkClass]; @@ -134,9 +127,8 @@ static NSString *objectSplit = @"_obj_"; } #pragma mark - 批量移除的方法 -/* - * 移除所有 - */ + + +(void)removeAllHandle{ [self checkClass]; @synchronized (bs_lock_obj) { @@ -144,9 +136,8 @@ static NSString *objectSplit = @"_obj_"; [bs_handlerDic removeAllObjects]; } } -/* - * 移除所有不是指定字符串开头的 - */ + + +(void)removeHandleNotInclude:(NSString *)str{ [self checkClass]; @synchronized (bs_lock_obj) { @@ -161,9 +152,8 @@ static NSString *objectSplit = @"_obj_"; } } } -/* - * 移除所有指定字符串开头的 - */ + + +(void)removeHandleInclude:(NSString *)str{ [self checkClass]; @synchronized (bs_lock_obj) { diff --git a/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m.backup b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m.backup new file mode 100644 index 0000000..0e138f9 --- /dev/null +++ b/YuMi/Tools/sdkContent/content/XWNotification(通知)/BSNotification.m.backup @@ -0,0 +1,193 @@ + // +// XWNotification.m +// BaseProject +// +// Created by xiaowen.chen on 16/7/19. +// Copyright © 2016年 xw.com. All rights reserved. +// + +#import "BSNotification.h" + +@implementation BSNotification + + +static NSMutableDictionary *bs_handlerDic = nil; +static NSObject *bs_lock_obj = nil; + +static NSString *objectSplit = @"_obj_"; +#pragma mark - 添加处理方法(根据key进行分组,object地址区分不同的实例) ++(void)addHandler:(GWHandleOption)block withName:(NSString *)handleName andObject:(NSObject *)object{ + handleName = [NSString stringWithFormat:@"%@%@%p",handleName,objectSplit,object]; + [self addHandler:block withName:handleName]; +} +#pragma mark - 移除处理方法(根据key进行分组,object地址区分不同的实例) ++(void)removeHandler:(NSString *)handleName andObject:(NSObject *)object{ + handleName = [NSString stringWithFormat:@"%@%@%p",handleName,objectSplit,object]; + [self removeHandler: handleName]; +} + + +#pragma mark - 添加处理方法 ++(void)addHandler:(GWHandleOption)block withName:(NSString *)handleName{ + + [self checkClass]; + @synchronized (bs_lock_obj) { + Boolean ishave = NO; + for (NSString *tempStr in [bs_handlerDic allKeys]) { + if ([tempStr isEqualToString:handleName]) { + ishave = YES; + break; + } + } + if (ishave) { + [bs_handlerDic removeObjectForKey:handleName]; + } + [bs_handlerDic setObject:block forKey:handleName]; + } +} + + + +#pragma mark - 移除处理方法 ++(void)removeHandler:(NSString *)name{ + + [self checkClass]; + @synchronized (bs_lock_obj) { + for (NSString *key in [bs_handlerDic allKeys]) { + if ([key isEqualToString:name]) { + [bs_handlerDic removeObjectForKey:key]; + } + } + } +} + + + +#pragma mark - 推送处理-简化版本 ++(void)pushHandle:(NSDictionary *)handleDic withName:(NSString *)handleName{ + + return [self pushHandle:NFMessageType_Simple withKey:@"BSdefaultKey" value:handleDic withName:handleName]; +} + +#pragma mark - 推送处理 ++(void)pushHandle:(NFMessageType)type withKey:(NSString *)key value:(NSObject *)value withName:(NSString *)handleName{ + [self checkClass]; + + @synchronized (bs_lock_obj) { + for (NSString *temp in [bs_handlerDic allKeys]) { + if ([temp hasPrefix:handleName]) { + GWHandleOption option = (GWHandleOption)[bs_handlerDic objectForKey:temp]; + if (option) { + option(type,key,value); + } + } + } + } +} + ++(NSMutableDictionary *)getHandleDic{ + return bs_handlerDic; +} + +#pragma mark - 有返回值的做法,可以用在一个页面向另外一个页面取值,要求是1对1,不然会出异常 + +/* + * 添加一个唯一的处理方法 + */ ++(void)addSingleHandler:(GWSingleHandleOption)block withName:(NSString *)handleName{ + + [self checkClass]; + + @synchronized (bs_lock_obj) { + Boolean ishave = NO; + for (NSString *tempStr in [bs_handlerDic allKeys]) { + if ([tempStr isEqualToString:handleName]) { + ishave = YES; + break; + } + } + if (ishave) { + [bs_handlerDic removeObjectForKey:handleName]; + } + + [bs_handlerDic setObject:block forKey:handleName]; + } +} +/* + * 触发唯一的处理方法,并且从唯一的处理方法中获取结果 + */ ++(NSDictionary *)getResultFromSingleHandle:(NSDictionary *)handleDic withName:(NSString *)handleName{ + + [self checkClass]; + + @synchronized (bs_lock_obj) { + for (NSString *temp in [bs_handlerDic allKeys]) { + if ([temp isEqualToString:handleName]) { + GWSingleHandleOption option = (GWSingleHandleOption)[bs_handlerDic objectForKey:temp]; + if (option) { + return option(handleDic); + } + } + } + } + return nil; +} + +#pragma mark - 批量移除的方法 +/* + * 移除所有 + */ ++(void)removeAllHandle{ + [self checkClass]; + @synchronized (bs_lock_obj) { + + [bs_handlerDic removeAllObjects]; + } +} +/* + * 移除所有不是指定字符串开头的 + */ ++(void)removeHandleNotInclude:(NSString *)str{ + [self checkClass]; + @synchronized (bs_lock_obj) { + NSMutableArray *resultArr = [NSMutableArray array]; + for (NSString *temp in [bs_handlerDic allKeys]) { + if ([temp hasPrefix:str]) { + [resultArr addObject:temp]; + } + } + for(NSString *temp in resultArr){ + [bs_handlerDic removeObjectForKey:temp]; + } + } +} +/* + * 移除所有指定字符串开头的 + */ ++(void)removeHandleInclude:(NSString *)str{ + [self checkClass]; + @synchronized (bs_lock_obj) { + + NSMutableArray *resultArr = [NSMutableArray array]; + for (NSString *temp in [bs_handlerDic allKeys]) { + if (![temp hasPrefix:str]) { + [resultArr addObject:temp]; + } + } + for(NSString *temp in resultArr){ + [bs_handlerDic removeObjectForKey:temp]; + } + } +} + ++(void)checkClass{ + if (bs_lock_obj == nil) { + bs_lock_obj = [[NSObject alloc] init]; + } + if (bs_handlerDic == nil) { + bs_handlerDic = [NSMutableDictionary dictionary]; + } +} + + +@end diff --git a/YuMi/YuMi-Bridging-Header.h b/YuMi/YuMi-Bridging-Header.h index c3f114d..81d30b3 100644 --- a/YuMi/YuMi-Bridging-Header.h +++ b/YuMi/YuMi-Bridging-Header.h @@ -1,23 +1,19 @@ -// -// YuMi-Bridging-Header.h -// YuMi -// + + // Created by AI on 2025-10-09. // Copyright © 2025 YuMi. All rights reserved. -// -// Swift/OC 混编桥接头文件 + #ifndef YuMi_Bridging_Header_h #define YuMi_Bridging_Header_h // MARK: - Minimal Bridging Header -// 只引入 Swift 中真正需要用到的 OC 类 + // MARK: - Foundation #import - // MARK: - New Modules (White Label) #import "EPMomentViewController.h" @@ -47,7 +43,6 @@ #import "MomentsInfoModel.h" #import "MomentsListInfoModel.h" #import "UserInfoModel.h" -#import "UploadFile.h" #import "YYUtility.h" #import "SDWebImage.h" @@ -65,11 +60,11 @@ #import "BaseViewController.h" // MARK: - Login - Utilities -#import "YUMIMacroUitls.h" // YMLocalizedString -#import "YUMIHtmlUrl.h" // URLWithType -#import "YUMIConstant.h" // KeyWithType, KeyType_Sign -#import "DESEncrypt.h" // DES加密工具 -#import "HttpRequestHelper.h" // getHostUrl +#import "YUMIMacroUitls.h" +#import "YUMIHtmlUrl.h" +#import "YUMIConstant.h" +#import "DESEncrypt.h" +#import "HttpRequestHelper.h" // MARK: - Login - Models (Phase 2 使用,先添加) #import "AccountInfoStorage.h" @@ -82,9 +77,5 @@ // MARK: - Login - Captcha & Config #import "TTPopup.h" -// 注意: -// 1. EPMomentViewController 和 EPMineViewController 直接继承 UIViewController -// 2. 不继承 BaseViewController(避免 ClientConfig → PIBaseModel 依赖链) -// 3. 其他依赖在各自的 .m 文件中 import -#endif /* YuMi_Bridging_Header_h */ +#endif diff --git a/YuMi/YuMi-Bridging-Header.h.backup b/YuMi/YuMi-Bridging-Header.h.backup new file mode 100644 index 0000000..c3f114d --- /dev/null +++ b/YuMi/YuMi-Bridging-Header.h.backup @@ -0,0 +1,90 @@ +// +// YuMi-Bridging-Header.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// +// Swift/OC 混编桥接头文件 + +#ifndef YuMi_Bridging_Header_h +#define YuMi_Bridging_Header_h + +// MARK: - Minimal Bridging Header +// 只引入 Swift 中真正需要用到的 OC 类 + +// MARK: - Foundation +#import + + + +// MARK: - New Modules (White Label) + +#import "EPMomentViewController.h" +#import "EPMineViewController.h" +#import "EPMomentCell.h" +#import "EPMineHeaderView.h" + + +// MARK: - Emotion Color System +#import "EPEmotionColorStorage.h" +#import "EPSignatureColorGuideView.h" + +// MARK: - QCloud SDK +#import + +// MARK: - Image Upload & Progress HUD +#import "MBProgressHUD.h" + +// MARK: - Base Model & Types +#import "PIBaseModel.h" +#import "YUMINNNN.h" + +// MARK: - API & Models +#import "Api+Moments.h" +#import "Api+Mine.h" +#import "AccountInfoStorage.h" +#import "MomentsInfoModel.h" +#import "MomentsListInfoModel.h" +#import "UserInfoModel.h" +#import "UploadFile.h" +#import "YYUtility.h" +#import "SDWebImage.h" + +// MARK: - API Helpers +#import "EPMineAPIHelper.h" + +// MARK: - Utilities +#import "UIImage+Utils.h" +#import "NSString+Utils.h" +#import "UIView+GradientLayer.h" +#import + +// MARK: - Login - Navigation & Web +#import "BaseNavigationController.h" +#import "BaseViewController.h" + +// MARK: - Login - Utilities +#import "YUMIMacroUitls.h" // YMLocalizedString +#import "YUMIHtmlUrl.h" // URLWithType +#import "YUMIConstant.h" // KeyWithType, KeyType_Sign +#import "DESEncrypt.h" // DES加密工具 +#import "HttpRequestHelper.h" // getHostUrl + +// MARK: - Login - Models (Phase 2 使用,先添加) +#import "AccountInfoStorage.h" +#import "AccountModel.h" + +// MARK: - Login - APIs (Phase 2) +#import "Api+Login.h" +#import "Api+Main.h" + +// MARK: - Login - Captcha & Config +#import "TTPopup.h" + +// 注意: +// 1. EPMomentViewController 和 EPMineViewController 直接继承 UIViewController +// 2. 不继承 BaseViewController(避免 ClientConfig → PIBaseModel 依赖链) +// 3. 其他依赖在各自的 .m 文件中 import + +#endif /* YuMi_Bridging_Header_h */ diff --git a/YuMi/en.lproj/InfoPlist.strings b/YuMi/en.lproj/InfoPlist.strings index 8801e44..1f4b85a 100644 --- a/YuMi/en.lproj/InfoPlist.strings +++ b/YuMi/en.lproj/InfoPlist.strings @@ -2,7 +2,6 @@ NSCameraUsageDescription ="\"E-Party\" needs your consent before you can visit, take photos and upload your pictures, and then display them on your personal homepage for others to view"; NSLocalNetworkUsageDescription ="The app will discover and connect to devices on your network"; -NSLocationWhenInUseUsageDescription = "Your consent is required before you can use location services and recommend nearby friends"; NSPhotoLibraryAddUsageDescription = "\"E-Party\" needs your consent before it can store photos in the album"; NSPhotoLibraryUsageDescription = "\"E-Party\" needs your consent before you can access the album and select the pictures you need to upload, and then display them on your personal homepage for others to view"; NSUserTrackingUsageDescription = "Please allow us to obtain your idfa permission to provide you with personalized activities and services. your information will not be used for other purposes without your permission"; diff --git a/YuMi/main.m b/YuMi/main.m index dc98f87..cc6b6ee 100644 --- a/YuMi/main.m +++ b/YuMi/main.m @@ -4,7 +4,7 @@ int main(int argc, char * argv[]) { NSString * appDelegateClassName; @autoreleasepool { - // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); } diff --git a/YuMi/main.m.backup b/YuMi/main.m.backup new file mode 100644 index 0000000..dc98f87 --- /dev/null +++ b/YuMi/main.m.backup @@ -0,0 +1,13 @@ +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + NSString * appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} + diff --git a/analyze_macro_usage.py b/analyze_macro_usage.py new file mode 100755 index 0000000..0cf584c --- /dev/null +++ b/analyze_macro_usage.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +宏使用情况依赖链分析工具 +分析宏定义文件中哪些宏实际被外部使用,哪些仅在文件内部被引用 +""" + +import re +import os +from pathlib import Path +from typing import Dict, Set, List, Tuple + +class MacroAnalyzer: + """宏依赖分析器""" + + def __init__(self, header_file: str, source_dir: str): + self.header_file = Path(header_file) + self.source_dir = Path(source_dir) + self.macros: Dict[str, dict] = {} # 宏定义信息 + self.dependencies: Dict[str, Set[str]] = {} # 宏依赖关系 + self.external_usage: Dict[str, Set[str]] = {} # 外部使用情况 + + def parse_header(self): + """解析头文件,提取所有宏定义""" + with open(self.header_file, 'r', encoding='utf-8') as f: + content = f.read() + + # 匹配 #define 宏定义 + # 支持多行宏定义(使用 \ 续行) + pattern = r'#define\s+(\w+)(?:\([^)]*\))?\s+((?:[^\n\\]|\\[\s\S])*)' + + for match in re.finditer(pattern, content): + macro_name = match.group(1) + macro_body = match.group(2).strip() + + # 移除续行符和多余空白 + macro_body = re.sub(r'\\\s*\n\s*', ' ', macro_body) + + self.macros[macro_name] = { + 'name': macro_name, + 'body': macro_body, + 'line': content[:match.start()].count('\n') + 1 + } + + # 分析这个宏依赖了哪些其他宏 + self.dependencies[macro_name] = self._find_dependencies(macro_body) + + def _find_dependencies(self, macro_body: str) -> Set[str]: + """从宏定义体中找出依赖的其他宏""" + deps = set() + # 查找所有可能的宏引用(大写字母开头的标识符) + for word in re.findall(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b', macro_body): + if word in self.macros or word.startswith('k') or word.startswith('K') or word.startswith('is'): + deps.add(word) + return deps + + def scan_external_usage(self): + """扫描外部文件中宏的使用情况""" + # 排除头文件本身和备份文件 + exclude_files = { + self.header_file.name, + f"{self.header_file.name}.backup" + } + + # 支持的文件扩展名 + extensions = {'.m', '.mm', '.swift', '.h', '.c', '.cpp'} + + # 遍历所有源文件 + for file_path in self.source_dir.rglob('*'): + if file_path.is_file() and file_path.suffix in extensions: + if file_path.name in exclude_files: + continue + + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # 检查每个宏是否在文件中使用 + for macro_name in self.macros: + # 使用单词边界匹配,避免部分匹配 + pattern = r'\b' + re.escape(macro_name) + r'\b' + if re.search(pattern, content): + if macro_name not in self.external_usage: + self.external_usage[macro_name] = set() + # 存储相对路径 + rel_path = file_path.relative_to(self.source_dir) + self.external_usage[macro_name].add(str(rel_path)) + + except Exception as e: + # 忽略无法读取的文件 + pass + + def calculate_effective_usage(self) -> Dict[str, int]: + """ + 计算有效使用次数(依赖链分析) + 如果一个宏只被文件内其他宏使用,但这些宏没有外部使用,则计为0 + """ + effective_usage = {} + + def is_effectively_used(macro_name: str, visited: Set[str] = None) -> bool: + """递归检查宏是否被有效使用""" + if visited is None: + visited = set() + + # 防止循环依赖 + if macro_name in visited: + return False + visited.add(macro_name) + + # 如果有外部使用,直接返回True + if macro_name in self.external_usage: + return True + + # 检查是否有其他宏依赖这个宏,且这些宏被有效使用 + for other_macro, deps in self.dependencies.items(): + if macro_name in deps: + if is_effectively_used(other_macro, visited.copy()): + return True + + return False + + # 计算每个宏的有效使用次数 + for macro_name in self.macros: + if is_effectively_used(macro_name): + # 有效使用,统计外部使用次数 + effective_usage[macro_name] = len(self.external_usage.get(macro_name, set())) + else: + # 无效使用 + effective_usage[macro_name] = 0 + + return effective_usage + + def generate_report(self): + """生成分析报告""" + print("\n" + "=" * 80) + print("宏使用情况依赖链分析报告") + print("=" * 80) + print(f"头文件: {self.header_file}") + print(f"源码目录: {self.source_dir}") + print(f"总宏定义数: {len(self.macros)}") + print("=" * 80 + "\n") + + # 计算有效使用 + effective_usage = self.calculate_effective_usage() + + # 分类统计 + unused_macros = [] + internal_only = [] + external_used = [] + + for macro_name, count in sorted(effective_usage.items()): + if count == 0: + unused_macros.append(macro_name) + elif macro_name in self.external_usage: + external_used.append((macro_name, count)) + else: + internal_only.append(macro_name) + + # 输出未使用的宏 + print("❌ 完全未使用的宏(包括依赖链分析)") + print("-" * 80) + if unused_macros: + for macro_name in unused_macros: + macro_info = self.macros[macro_name] + # 检查是否被内部引用 + referenced_by = [] + for other, deps in self.dependencies.items(): + if macro_name in deps and other != macro_name: + referenced_by.append(other) + + status = "" + if referenced_by: + status = f" (被内部宏引用: {', '.join(referenced_by)},但这些宏未被外部使用)" + + print(f" • {macro_name}{status}") + print(f" 行号: {macro_info['line']}") + print(f" 定义: {macro_info['body'][:60]}...") + print() + else: + print(" 无\n") + + # 输出仅内部使用的宏(有效) + print("✅ 仅被内部其他宏使用(但这些宏有外部使用)") + print("-" * 80) + if internal_only: + for macro_name in internal_only: + macro_info = self.macros[macro_name] + # 找出哪些外部使用的宏依赖它 + used_by_external = [] + + def find_external_users(macro: str, visited: Set[str] = None) -> List[str]: + if visited is None: + visited = set() + if macro in visited: + return [] + visited.add(macro) + + users = [] + for other, deps in self.dependencies.items(): + if macro in deps: + if other in self.external_usage: + users.append(other) + else: + users.extend(find_external_users(other, visited)) + return users + + used_by_external = find_external_users(macro_name) + + print(f" • {macro_name}") + print(f" 被以下外部使用的宏依赖: {', '.join(set(used_by_external)) if used_by_external else '(间接)'}") + print() + else: + print(" 无\n") + + # 输出有外部使用的宏 + print("✅ 有外部使用的宏") + print("-" * 80) + if external_used: + for macro_name, count in sorted(external_used, key=lambda x: x[1], reverse=True): + files = self.external_usage[macro_name] + print(f" • {macro_name}") + print(f" 外部使用次数: {count} 个文件") + if count <= 3: + for f in list(files)[:3]: + print(f" - {f}") + print() + else: + print(" 无\n") + + # 统计汇总 + print("\n" + "=" * 80) + print("📊 统计汇总") + print("=" * 80) + print(f"❌ 未使用宏: {len(unused_macros)} 个 ({len(unused_macros)/len(self.macros)*100:.1f}%)") + print(f"⚙️ 内部使用宏: {len(internal_only)} 个 ({len(internal_only)/len(self.macros)*100:.1f}%)") + print(f"✅ 外部使用宏: {len(external_used)} 个 ({len(external_used)/len(self.macros)*100:.1f}%)") + print("=" * 80 + "\n") + + # 建议清理 + if unused_macros: + print("💡 建议清理以下宏定义:") + print("-" * 80) + for macro_name in unused_macros: + macro_info = self.macros[macro_name] + print(f" 第 {macro_info['line']} 行: #define {macro_name} ...") + print() + + +def main(): + import sys + + if len(sys.argv) < 3: + print("用法: python3 analyze_macro_usage.py <头文件路径> <源码目录>") + print("示例: python3 analyze_macro_usage.py YuMi/Global/YUMIMacroUitls.h YuMi/") + sys.exit(1) + + header_file = sys.argv[1] + source_dir = sys.argv[2] + + if not os.path.exists(header_file): + print(f"错误: 头文件不存在: {header_file}") + sys.exit(1) + + if not os.path.exists(source_dir): + print(f"错误: 源码目录不存在: {source_dir}") + sys.exit(1) + + analyzer = MacroAnalyzer(header_file, source_dir) + + print("正在解析头文件...") + analyzer.parse_header() + + print(f"正在扫描外部文件使用情况...") + analyzer.scan_external_usage() + + print("正在分析依赖链...") + analyzer.generate_report() + + +if __name__ == '__main__': + main() + diff --git a/clean_comments.sh b/clean_comments.sh new file mode 100755 index 0000000..c04c3d4 --- /dev/null +++ b/clean_comments.sh @@ -0,0 +1,187 @@ +#!/bin/bash +# 代码注释清理快捷脚本 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PYTHON_SCRIPT="$SCRIPT_DIR/remove_comments.py" + +# 颜色定义 +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# 打印带颜色的消息 +print_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 显示使用说明 +show_usage() { + cat << EOF +代码注释清理工具 - 快捷脚本 + +用法: + $0 [选项] <路径> + +选项: + preview 预览模式(不实际修改) + clean 清理注释(保留版权和重要注释) + clean-all 清理所有注释(包括版权) + test 在测试文件上运行 + +示例: + $0 preview YuMi/Global/ # 预览Global目录 + $0 clean YuMi/Global/ # 清理Global目录 + $0 clean-all YuMi/Global/YUMIConstant.m # 清理单个文件的所有注释 + $0 test # 测试模式 + +EOF +} + +# 预览模式 +preview_mode() { + local path=$1 + print_info "预览模式:查看将要删除的注释" + python3 "$PYTHON_SCRIPT" "$path" -r --dry-run +} + +# 清理模式(保留重要注释) +clean_mode() { + local path=$1 + + print_warning "即将清理注释,但会保留:" + echo " ✓ 版权声明 (Copyright, Created by)" + echo " ✓ 重要注释 (TODO, FIXME, NOTE)" + echo " ✓ 编译指令 (#pragma mark)" + echo "" + + read -p "是否继续? (y/N): " -n 1 -r + echo + + if [[ $REPLY =~ ^[Yy]$ ]]; then + python3 "$PYTHON_SCRIPT" "$path" -r + else + print_info "已取消" + fi +} + +# 清理所有注释 +clean_all_mode() { + local path=$1 + + print_warning "⚠️ 警告:将删除所有注释(包括版权声明)" + echo "" + + read -p "是否确认? (y/N): " -n 1 -r + echo + + if [[ $REPLY =~ ^[Yy]$ ]]; then + python3 "$PYTHON_SCRIPT" "$path" -r --no-copyright --no-important --no-pragma + else + print_info "已取消" + fi +} + +# 测试模式 +test_mode() { + local test_file="$SCRIPT_DIR/test_comment_removal.m" + + if [ ! -f "$test_file" ]; then + print_error "测试文件不存在: $test_file" + exit 1 + fi + + print_info "在测试文件上运行..." + echo "" + + # 预览 + print_info "步骤 1/3: 预览删除效果" + python3 "$PYTHON_SCRIPT" "$test_file" --dry-run + echo "" + + # 实际清理 + print_info "步骤 2/3: 执行清理" + python3 "$PYTHON_SCRIPT" "$test_file" + echo "" + + # 显示结果 + print_info "步骤 3/3: 查看清理后的文件" + echo "----------------------------------------" + cat "$test_file" + echo "----------------------------------------" + echo "" + + # 恢复测试文件 + if [ -f "${test_file}.backup" ]; then + mv "${test_file}.backup" "$test_file" + print_info "已恢复测试文件" + fi +} + +# 主函数 +main() { + # 检查Python脚本是否存在 + if [ ! -f "$PYTHON_SCRIPT" ]; then + print_error "找不到Python脚本: $PYTHON_SCRIPT" + exit 1 + fi + + # 检查参数 + if [ $# -eq 0 ]; then + show_usage + exit 1 + fi + + local command=$1 + + case $command in + preview) + if [ $# -lt 2 ]; then + print_error "缺少路径参数" + show_usage + exit 1 + fi + preview_mode "$2" + ;; + clean) + if [ $# -lt 2 ]; then + print_error "缺少路径参数" + show_usage + exit 1 + fi + clean_mode "$2" + ;; + clean-all) + if [ $# -lt 2 ]; then + print_error "缺少路径参数" + show_usage + exit 1 + fi + clean_all_mode "$2" + ;; + test) + test_mode + ;; + help|--help|-h) + show_usage + ;; + *) + print_error "未知命令: $command" + show_usage + exit 1 + ;; + esac +} + +main "$@" + diff --git a/remove_comments.py b/remove_comments.py new file mode 100755 index 0000000..7240bae --- /dev/null +++ b/remove_comments.py @@ -0,0 +1,451 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +安全移除代码注释工具 +支持 Objective-C, Swift, C/C++ 等语言 +""" + +import re +import os +import sys +import argparse +from pathlib import Path +from typing import List, Tuple, Optional +import shutil + +class CommentRemover: + """代码注释移除器""" + + def __init__(self, keep_copyright=True, keep_important=True, keep_pragma=True): + """ + 初始化注释移除器 + + Args: + keep_copyright: 保留版权声明 + keep_important: 保留重要注释(TODO, FIXME, NOTE等) + keep_pragma: 保留编译指令(#pragma mark等) + """ + self.keep_copyright = keep_copyright + self.keep_important = keep_important + self.keep_pragma = keep_pragma + + # 重要关键词 + self.important_keywords = [ + 'TODO', 'FIXME', 'HACK', 'NOTE', 'WARNING', + 'IMPORTANT', 'BUG', 'CRITICAL', 'MARK' + ] + + # 版权相关关键词 + self.copyright_keywords = [ + 'Copyright', 'copyright', '©', 'LICENSE', + 'All rights reserved', 'Created by' + ] + + def is_copyright_comment(self, comment: str) -> bool: + """判断是否是版权声明注释""" + if not self.keep_copyright: + return False + return any(keyword in comment for keyword in self.copyright_keywords) + + def is_important_comment(self, comment: str) -> bool: + """判断是否是重要注释""" + if not self.keep_important: + return False + return any(keyword in comment for keyword in self.important_keywords) + + def is_pragma_comment(self, comment: str) -> bool: + """判断是否是编译指令注释""" + if not self.keep_pragma: + return False + return '#pragma' in comment or 'MARK:' in comment or 'MARK -' in comment + + def should_keep_comment(self, comment: str) -> bool: + """判断是否应该保留注释""" + return (self.is_copyright_comment(comment) or + self.is_important_comment(comment) or + self.is_pragma_comment(comment)) + + def remove_comments(self, code: str, file_extension: str) -> str: + """ + 移除代码中的注释 + + Args: + code: 源代码字符串 + file_extension: 文件扩展名 + + Returns: + 移除注释后的代码 + """ + result = [] + i = 0 + in_string = False + in_char = False + string_char = None + + while i < len(code): + # 处理字符串 + if not in_string and not in_char: + # 检查字符串开始 + if code[i] in ('"', "'"): + string_char = code[i] + in_string = True + result.append(code[i]) + i += 1 + continue + + # Swift 的多行字符串 + if file_extension == '.swift' and i + 2 < len(code) and code[i:i+3] == '"""': + result.append('"""') + i += 3 + # 跳过多行字符串内容 + while i < len(code): + if i + 2 < len(code) and code[i:i+3] == '"""': + result.append('"""') + i += 3 + break + result.append(code[i]) + i += 1 + continue + + # 检查单行注释 // + if i + 1 < len(code) and code[i:i+2] == '//': + # 检查是否是 URL (http://, https://) + if i >= 5 and code[i-5:i+2] == 'http://': + result.append(code[i]) + i += 1 + continue + if i >= 6 and code[i-6:i+2] == 'https://': + result.append(code[i]) + i += 1 + continue + + # 检查是否是行尾注释(前面有非空白字符) + line_start = len(result) + for j in range(len(result) - 1, -1, -1): + if result[j] == '\n': + line_start = j + 1 + break + + # 获取当前行已有的内容 + current_line = ''.join(result[line_start:]) + has_code_before = current_line.strip() != '' + + # 提取注释内容 + comment_start = i + i += 2 + while i < len(code) and code[i] != '\n': + i += 1 + + comment = code[comment_start:i] + + # 判断是否保留注释 + if self.should_keep_comment(comment): + result.append(comment) + elif has_code_before: + # 行尾注释:移除注释但保留前面的空格 + # 移除注释前的多余空格,只保留一个空格的位置 + while len(result) > 0 and result[-1] in (' ', '\t'): + result.pop() + + # 保留换行符 + if i < len(code) and code[i] == '\n': + result.append('\n') + i += 1 + continue + + # 检查多行注释 /* */ 或文档注释 /** */ + if i + 1 < len(code) and code[i:i+2] == '/*': + comment_start = i + i += 2 + + # 检查是否是文档注释 /** + is_doc_comment = (i < len(code) and code[i] == '*') + + # 查找注释结束 + while i < len(code): + if i + 1 < len(code) and code[i:i+2] == '*/': + i += 2 + break + i += 1 + + comment = code[comment_start:i] + + # 判断是否保留注释 + if self.should_keep_comment(comment): + result.append(comment) + else: + # 检查注释前是否有代码(行尾注释) + line_start = len(result) + for j in range(len(result) - 1, -1, -1): + if result[j] == '\n': + line_start = j + 1 + break + + current_line = ''.join(result[line_start:]) + has_code_before = current_line.strip() != '' + + if has_code_before: + # 行尾多行注释:移除注释前的多余空格 + while len(result) > 0 and result[-1] in (' ', '\t'): + result.pop() + else: + # 独立的多行注释:保留最多1个换行符维持代码分段 + newline_count = comment.count('\n') + if newline_count > 0: + result.append('\n') + + continue + + # 在字符串内部 + elif in_string: + # 检查转义字符 + if code[i] == '\\' and i + 1 < len(code): + result.append(code[i]) + result.append(code[i + 1]) + i += 2 + continue + + # 检查字符串结束 + if code[i] == string_char: + in_string = False + string_char = None + + result.append(code[i]) + i += 1 + continue + + # 普通字符 + result.append(code[i]) + i += 1 + + return ''.join(result) + + def clean_empty_lines(self, code: str) -> str: + """清理多余的空行(超过2行的空行压缩为2行)""" + lines = code.split('\n') + result = [] + empty_count = 0 + + for line in lines: + if line.strip() == '': + empty_count += 1 + if empty_count <= 2: + result.append(line) + else: + empty_count = 0 + result.append(line) + + return '\n'.join(result) + + +class FileProcessor: + """文件处理器""" + + # 支持的文件扩展名 + SUPPORTED_EXTENSIONS = {'.m', '.h', '.mm', '.swift', '.c', '.cpp', '.cc', '.hpp'} + + def __init__(self, remover: CommentRemover, backup: bool = True, dry_run: bool = False): + """ + 初始化文件处理器 + + Args: + remover: 注释移除器实例 + backup: 是否备份原文件 + dry_run: 是否仅预览(不实际修改文件) + """ + self.remover = remover + self.backup = backup + self.dry_run = dry_run + self.stats = { + 'processed': 0, + 'skipped': 0, + 'errors': 0 + } + + def is_supported_file(self, filepath: Path) -> bool: + """检查文件是否支持""" + return filepath.suffix in self.SUPPORTED_EXTENSIONS + + def process_file(self, filepath: Path) -> bool: + """ + 处理单个文件 + + Args: + filepath: 文件路径 + + Returns: + 处理是否成功 + """ + try: + if not self.is_supported_file(filepath): + print(f"⚠️ 跳过不支持的文件: {filepath}") + self.stats['skipped'] += 1 + return False + + # 读取文件 + with open(filepath, 'r', encoding='utf-8') as f: + original_code = f.read() + + # 移除注释 + cleaned_code = self.remover.remove_comments( + original_code, + filepath.suffix + ) + + # 清理空行 + cleaned_code = self.remover.clean_empty_lines(cleaned_code) + + # 计算变化 + original_lines = len(original_code.splitlines()) + cleaned_lines = len(cleaned_code.splitlines()) + removed_lines = original_lines - cleaned_lines + + if original_code == cleaned_code: + print(f"✓ 无需修改: {filepath}") + self.stats['skipped'] += 1 + return True + + print(f"📝 {'[预览]' if self.dry_run else '处理'} {filepath}") + print(f" 删除 {removed_lines} 行注释 ({original_lines} → {cleaned_lines} 行)") + + if self.dry_run: + print(f" [预览模式] 不会实际修改文件") + return True + + # 备份原文件 + if self.backup: + backup_path = filepath.with_suffix(filepath.suffix + '.backup') + shutil.copy2(filepath, backup_path) + print(f" 备份: {backup_path}") + + # 写入清理后的代码 + with open(filepath, 'w', encoding='utf-8') as f: + f.write(cleaned_code) + + print(f"✅ 完成: {filepath}") + self.stats['processed'] += 1 + return True + + except Exception as e: + print(f"❌ 错误: {filepath}") + print(f" {str(e)}") + self.stats['errors'] += 1 + return False + + def process_directory(self, directory: Path, recursive: bool = True) -> None: + """ + 处理目录中的所有文件 + + Args: + directory: 目录路径 + recursive: 是否递归处理子目录 + """ + if recursive: + pattern = '**/*' + else: + pattern = '*' + + files = [f for f in directory.glob(pattern) if f.is_file()] + supported_files = [f for f in files if self.is_supported_file(f)] + + print(f"\n🔍 找到 {len(supported_files)} 个支持的文件\n") + + for filepath in supported_files: + self.process_file(filepath) + + self.print_summary() + + def print_summary(self) -> None: + """打印处理摘要""" + print("\n" + "=" * 60) + print("📊 处理摘要") + print("=" * 60) + print(f"✅ 已处理: {self.stats['processed']} 个文件") + print(f"⚠️ 已跳过: {self.stats['skipped']} 个文件") + print(f"❌ 错误: {self.stats['errors']} 个文件") + print("=" * 60 + "\n") + + +def main(): + """主函数""" + parser = argparse.ArgumentParser( + description='安全移除代码注释工具', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +示例: + # 处理单个文件 + python remove_comments.py path/to/file.m + + # 处理整个目录 + python remove_comments.py YuMi/Global/ -r + + # 预览模式(不实际修改) + python remove_comments.py YuMi/Global/ -r --dry-run + + # 不保留版权信息和重要注释 + python remove_comments.py file.m --no-copyright --no-important + + # 不创建备份文件 + python remove_comments.py file.m --no-backup + """ + ) + + parser.add_argument('path', type=str, help='文件或目录路径') + parser.add_argument('-r', '--recursive', action='store_true', + help='递归处理子目录') + parser.add_argument('--dry-run', action='store_true', + help='预览模式(不实际修改文件)') + parser.add_argument('--no-backup', action='store_true', + help='不创建备份文件') + parser.add_argument('--no-copyright', action='store_true', + help='不保留版权声明') + parser.add_argument('--no-important', action='store_true', + help='不保留重要注释(TODO, FIXME等)') + parser.add_argument('--no-pragma', action='store_true', + help='不保留编译指令(#pragma mark等)') + + args = parser.parse_args() + + # 检查路径 + path = Path(args.path) + if not path.exists(): + print(f"❌ 路径不存在: {path}") + sys.exit(1) + + # 创建注释移除器 + remover = CommentRemover( + keep_copyright=not args.no_copyright, + keep_important=not args.no_important, + keep_pragma=not args.no_pragma + ) + + # 创建文件处理器 + processor = FileProcessor( + remover=remover, + backup=not args.no_backup, + dry_run=args.dry_run + ) + + # 打印配置 + print("\n" + "=" * 60) + print("⚙️ 配置") + print("=" * 60) + print(f"路径: {path}") + print(f"模式: {'预览' if args.dry_run else '实际修改'}") + print(f"备份: {'是' if not args.no_backup else '否'}") + print(f"保留版权: {'是' if not args.no_copyright else '否'}") + print(f"保留重要注释: {'是' if not args.no_important else '否'}") + print(f"保留编译指令: {'是' if not args.no_pragma else '否'}") + print("=" * 60) + + # 处理文件或目录 + if path.is_file(): + processor.process_file(path) + processor.print_summary() + else: + processor.process_directory(path, recursive=args.recursive) + + +if __name__ == '__main__': + main() + diff --git a/test_comment_removal.m b/test_comment_removal.m new file mode 100644 index 0000000..ccf040f --- /dev/null +++ b/test_comment_removal.m @@ -0,0 +1,64 @@ +// +// TestFile.m +// YuMi +// +// Created by Test on 2025/01/27. +// Copyright © 2025 Company. All rights reserved. +// + +#import "TestFile.h" + +// 这是一个普通注释,应该被删除 +@implementation TestFile + +// MARK: - Initialization + +/// 这是一个文档注释 +- (instancetype)init { + self = [super init]; + if (self) { + // TODO: 实现初始化逻辑 - 这个应该保留 + NSString *url = @"https://example.com"; // URL中的//会被保护 + + /* + 这是一个多行注释 + 应该被删除 + 除非包含重要关键字 + */ + + /* FIXME: 这个多行注释包含FIXME,应该保留 */ + + NSLog(@"// 字符串中的注释符号会被保护"); + } + return self; +} + +#pragma mark - Public Methods + +// 普通方法注释 - 会被删除 +- (void)doSomething { + // 实现细节注释 - 会被删除 + NSString *test = @"test"; // 行尾注释 - 会被删除 + int count = 0; // 计数器 + + // NOTE: 重要说明 - 会被保留 + [self helper]; +} + +// Helper method +- (void)helper { + // 简单注释 + return; +} + +/* + 多行注释测试 + 这个会被删除 +*/ +- (void)anotherMethod { + // Nothing +} + +@end + +// 文件末尾的注释 - 会被删除 diff --git a/test_doc_comment.m b/test_doc_comment.m new file mode 100644 index 0000000..9736465 --- /dev/null +++ b/test_doc_comment.m @@ -0,0 +1,42 @@ + + +// Created by Test on 2025/01/27. + + +#import "TestDocComment.h" + + +- (void)showSuccessToast { + +} + + +- (void)methodWithDocComment { + NSString *test = @"test"; + + + [self process]; +} + + +- (void)singleLineDocComment { + return; +} + + +- (void)swiftStyleComment { + +} + + +- (NSString *)formalDocComment:(NSString *)name { + return name; +} + +/** FIXME: 这个文档注释包含重要关键字,应该保留 */ +- (void)importantDocComment { + return; +} + +@end +