xplan ios start
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Flutter filter=lfs diff=lfs merge=lfs -text
|
68
.gitignore
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## User settings
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
|
||||||
|
*.xcscmblueprint
|
||||||
|
*.xccheckout
|
||||||
|
|
||||||
|
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
*.moved-aside
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
|
||||||
|
## Obj-C/Swift specific
|
||||||
|
*.hmap
|
||||||
|
|
||||||
|
## App packaging
|
||||||
|
*.ipa
|
||||||
|
*.dSYM.zip
|
||||||
|
*.dSYM
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
#
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
#
|
||||||
|
Pods/
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||||
|
# *.xcworkspace
|
||||||
|
|
||||||
|
# Carthage
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
|
# Carthage/Checkouts
|
||||||
|
|
||||||
|
Carthage/Build/
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
#
|
||||||
|
# It is recommended to not store the screenshots in the git repo.
|
||||||
|
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
||||||
|
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots/**/*.png
|
||||||
|
fastlane/test_output
|
||||||
|
|
||||||
|
# Code Injection
|
||||||
|
#
|
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||||
|
# https://github.com/johnno1962/injectionforxcode
|
||||||
|
|
||||||
|
iOSInjectionProject/
|
17
Podfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Uncomment the next line to define a global platform for your project
|
||||||
|
# platform :ios, '9.0'
|
||||||
|
|
||||||
|
target 'xplan-ios' do
|
||||||
|
# Comment the next line if you don't want to use dynamic frameworks
|
||||||
|
use_frameworks!
|
||||||
|
|
||||||
|
# Pods for xplan-ios
|
||||||
|
pod 'AFNetworking'
|
||||||
|
pod 'YYText'
|
||||||
|
pod 'Masonry'
|
||||||
|
pod 'ReactiveObjC'
|
||||||
|
pod 'MBProgressHUD'
|
||||||
|
#易盾 本机一键登录
|
||||||
|
pod 'NTESQuickPass', '~> 2.1.6'
|
||||||
|
|
||||||
|
end
|
50
Podfile.lock
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
PODS:
|
||||||
|
- AFNetworking (4.0.1):
|
||||||
|
- AFNetworking/NSURLSession (= 4.0.1)
|
||||||
|
- AFNetworking/Reachability (= 4.0.1)
|
||||||
|
- AFNetworking/Security (= 4.0.1)
|
||||||
|
- AFNetworking/Serialization (= 4.0.1)
|
||||||
|
- AFNetworking/UIKit (= 4.0.1)
|
||||||
|
- AFNetworking/NSURLSession (4.0.1):
|
||||||
|
- AFNetworking/Reachability
|
||||||
|
- AFNetworking/Security
|
||||||
|
- AFNetworking/Serialization
|
||||||
|
- AFNetworking/Reachability (4.0.1)
|
||||||
|
- AFNetworking/Security (4.0.1)
|
||||||
|
- AFNetworking/Serialization (4.0.1)
|
||||||
|
- AFNetworking/UIKit (4.0.1):
|
||||||
|
- AFNetworking/NSURLSession
|
||||||
|
- Masonry (1.1.0)
|
||||||
|
- MBProgressHUD (1.2.0)
|
||||||
|
- NTESQuickPass (2.1.9)
|
||||||
|
- ReactiveObjC (3.1.1)
|
||||||
|
- YYText (1.0.7)
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- AFNetworking
|
||||||
|
- Masonry
|
||||||
|
- MBProgressHUD
|
||||||
|
- NTESQuickPass (~> 2.1.6)
|
||||||
|
- ReactiveObjC
|
||||||
|
- YYText
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- AFNetworking
|
||||||
|
- Masonry
|
||||||
|
- MBProgressHUD
|
||||||
|
- NTESQuickPass
|
||||||
|
- ReactiveObjC
|
||||||
|
- YYText
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
|
||||||
|
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||||
|
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
|
||||||
|
NTESQuickPass: 8431dc52737c95883cd382c2ee75664d58f39377
|
||||||
|
ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040
|
||||||
|
YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: f8d8c44df1ae85a1571fe37ee767fc992db1ff6b
|
||||||
|
|
||||||
|
COCOAPODS: 1.10.1
|
699
xplan-ios.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,699 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 51;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
189DD52E26DE255300AB55B1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD52D26DE255300AB55B1 /* AppDelegate.m */; };
|
||||||
|
189DD53426DE255300AB55B1 /* TabbarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD53326DE255300AB55B1 /* TabbarViewController.m */; };
|
||||||
|
189DD53926DE255600AB55B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 189DD53826DE255600AB55B1 /* Assets.xcassets */; };
|
||||||
|
189DD53C26DE255600AB55B1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 189DD53A26DE255600AB55B1 /* LaunchScreen.storyboard */; };
|
||||||
|
189DD53F26DE255600AB55B1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD53E26DE255600AB55B1 /* main.m */; };
|
||||||
|
189DD54B26DE338800AB55B1 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD54A26DE338800AB55B1 /* BaseViewController.m */; };
|
||||||
|
189DD55026DE37F900AB55B1 /* MvpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD54F26DE37F900AB55B1 /* MvpViewController.m */; };
|
||||||
|
189DD55A26DE39D200AB55B1 /* BaseMvpPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD55926DE39D200AB55B1 /* BaseMvpPresenter.m */; };
|
||||||
|
189DD56526DE465A00AB55B1 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD56426DE465A00AB55B1 /* LoginViewController.m */; };
|
||||||
|
189DD58F26DF97E700AB55B1 /* LoginPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD58E26DF97E700AB55B1 /* LoginPresenter.m */; };
|
||||||
|
189DD67E26E1FD8900AB55B1 /* UIImage+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD67D26E1FD8900AB55B1 /* UIImage+Utils.m */; };
|
||||||
|
189DD68426E1FDBB00AB55B1 /* XCHUDTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD68226E1FDBB00AB55B1 /* XCHUDTool.m */; };
|
||||||
|
189DD6FF26E20E5900AB55B1 /* HttpRequestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD6FE26E20E5900AB55B1 /* HttpRequestHelper.m */; };
|
||||||
|
189DD73D26E21C3F00AB55B1 /* YYUtility+Device.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD73826E21C3F00AB55B1 /* YYUtility+Device.m */; };
|
||||||
|
189DD73E26E21C3F00AB55B1 /* YYUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD73926E21C3F00AB55B1 /* YYUtility.m */; };
|
||||||
|
189DD73F26E21C3F00AB55B1 /* YYUtility+Carrier.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD73A26E21C3F00AB55B1 /* YYUtility+Carrier.m */; };
|
||||||
|
189DD74026E21C3F00AB55B1 /* YYUtility+App.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD73B26E21C3F00AB55B1 /* YYUtility+App.m */; };
|
||||||
|
189DD74526E21CCC00AB55B1 /* YYReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD74426E21CCC00AB55B1 /* YYReachability.m */; };
|
||||||
|
189DD74A26E21D8400AB55B1 /* SSKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD74926E21D8400AB55B1 /* SSKeychain.m */; };
|
||||||
|
189DD75026E21D9000AB55B1 /* GCDHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD74E26E21D9000AB55B1 /* GCDHelper.m */; };
|
||||||
|
189DD75926E6003C00AB55B1 /* Api.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD75826E6003C00AB55B1 /* Api.m */; };
|
||||||
|
189DD76226E60DDC00AB55B1 /* Api+Login.m in Sources */ = {isa = PBXBuildFile; fileRef = 189DD76126E60DDC00AB55B1 /* Api+Login.m */; };
|
||||||
|
73FFADDC93E195344047A2EC /* Pods_xplan_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CACF623970097D653132D69A /* Pods_xplan_ios.framework */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
189DD52926DE255300AB55B1 /* xplan-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "xplan-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
189DD52C26DE255300AB55B1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||||
|
189DD52D26DE255300AB55B1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||||
|
189DD53226DE255300AB55B1 /* TabbarViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TabbarViewController.h; sourceTree = "<group>"; };
|
||||||
|
189DD53326DE255300AB55B1 /* TabbarViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TabbarViewController.m; sourceTree = "<group>"; };
|
||||||
|
189DD53826DE255600AB55B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
189DD53B26DE255600AB55B1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
189DD53D26DE255600AB55B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
189DD53E26DE255600AB55B1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
|
189DD54926DE338800AB55B1 /* BaseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseViewController.h; sourceTree = "<group>"; };
|
||||||
|
189DD54A26DE338800AB55B1 /* BaseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseViewController.m; sourceTree = "<group>"; };
|
||||||
|
189DD54E26DE37F900AB55B1 /* MvpViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MvpViewController.h; sourceTree = "<group>"; };
|
||||||
|
189DD54F26DE37F900AB55B1 /* MvpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MvpViewController.m; sourceTree = "<group>"; };
|
||||||
|
189DD55826DE39D200AB55B1 /* BaseMvpPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseMvpPresenter.h; sourceTree = "<group>"; };
|
||||||
|
189DD55926DE39D200AB55B1 /* BaseMvpPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseMvpPresenter.m; sourceTree = "<group>"; };
|
||||||
|
189DD55E26DE3BBE00AB55B1 /* BaseMvpProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseMvpProtocol.h; sourceTree = "<group>"; };
|
||||||
|
189DD56326DE465A00AB55B1 /* LoginViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = "<group>"; };
|
||||||
|
189DD56426DE465A00AB55B1 /* LoginViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = "<group>"; };
|
||||||
|
189DD57226DF5F0C00AB55B1 /* Base.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Base.pch; sourceTree = "<group>"; };
|
||||||
|
189DD58D26DF97E700AB55B1 /* LoginPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoginPresenter.h; sourceTree = "<group>"; };
|
||||||
|
189DD58E26DF97E700AB55B1 /* LoginPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LoginPresenter.m; sourceTree = "<group>"; };
|
||||||
|
189DD59426DF986300AB55B1 /* LoginProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoginProtocol.h; sourceTree = "<group>"; };
|
||||||
|
189DD67C26E1FD8900AB55B1 /* UIImage+Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Utils.h"; sourceTree = "<group>"; };
|
||||||
|
189DD67D26E1FD8900AB55B1 /* UIImage+Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Utils.m"; sourceTree = "<group>"; };
|
||||||
|
189DD68226E1FDBB00AB55B1 /* XCHUDTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCHUDTool.m; sourceTree = "<group>"; };
|
||||||
|
189DD68326E1FDBB00AB55B1 /* XCHUDTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCHUDTool.h; sourceTree = "<group>"; };
|
||||||
|
189DD6FD26E20E5900AB55B1 /* HttpRequestHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HttpRequestHelper.h; sourceTree = "<group>"; };
|
||||||
|
189DD6FE26E20E5900AB55B1 /* HttpRequestHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HttpRequestHelper.m; sourceTree = "<group>"; };
|
||||||
|
189DD73726E21C3F00AB55B1 /* CarrierIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CarrierIdentifier.h; sourceTree = "<group>"; };
|
||||||
|
189DD73826E21C3F00AB55B1 /* YYUtility+Device.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "YYUtility+Device.m"; sourceTree = "<group>"; };
|
||||||
|
189DD73926E21C3F00AB55B1 /* YYUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYUtility.m; sourceTree = "<group>"; };
|
||||||
|
189DD73A26E21C3F00AB55B1 /* YYUtility+Carrier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "YYUtility+Carrier.m"; sourceTree = "<group>"; };
|
||||||
|
189DD73B26E21C3F00AB55B1 /* YYUtility+App.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "YYUtility+App.m"; sourceTree = "<group>"; };
|
||||||
|
189DD73C26E21C3F00AB55B1 /* YYUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYUtility.h; sourceTree = "<group>"; };
|
||||||
|
189DD74326E21CCC00AB55B1 /* YYReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYReachability.h; sourceTree = "<group>"; };
|
||||||
|
189DD74426E21CCC00AB55B1 /* YYReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYReachability.m; sourceTree = "<group>"; };
|
||||||
|
189DD74826E21D8400AB55B1 /* SSKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychain.h; sourceTree = "<group>"; };
|
||||||
|
189DD74926E21D8400AB55B1 /* SSKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychain.m; sourceTree = "<group>"; };
|
||||||
|
189DD74E26E21D9000AB55B1 /* GCDHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDHelper.m; sourceTree = "<group>"; };
|
||||||
|
189DD74F26E21D9000AB55B1 /* GCDHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDHelper.h; sourceTree = "<group>"; };
|
||||||
|
189DD75726E6003C00AB55B1 /* Api.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Api.h; sourceTree = "<group>"; };
|
||||||
|
189DD75826E6003C00AB55B1 /* Api.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Api.m; sourceTree = "<group>"; };
|
||||||
|
189DD76026E60DDC00AB55B1 /* Api+Login.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Api+Login.h"; sourceTree = "<group>"; };
|
||||||
|
189DD76126E60DDC00AB55B1 /* Api+Login.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "Api+Login.m"; sourceTree = "<group>"; };
|
||||||
|
189DD78026E620FE00AB55B1 /* ApiHost.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApiHost.h; sourceTree = "<group>"; };
|
||||||
|
7DB00EC07F1D0ADFF900B38D /* Pods-xplan-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-xplan-ios.debug.xcconfig"; path = "Target Support Files/Pods-xplan-ios/Pods-xplan-ios.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
B66633E061B1B34177CD011C /* Pods-xplan-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-xplan-ios.release.xcconfig"; path = "Target Support Files/Pods-xplan-ios/Pods-xplan-ios.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
CACF623970097D653132D69A /* Pods_xplan_ios.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_xplan_ios.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
189DD52626DE255300AB55B1 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
73FFADDC93E195344047A2EC /* Pods_xplan_ios.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
187EEEA926E62679002833B2 /* Api */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD75726E6003C00AB55B1 /* Api.h */,
|
||||||
|
189DD75826E6003C00AB55B1 /* Api.m */,
|
||||||
|
);
|
||||||
|
path = Api;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD52026DE255300AB55B1 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD52B26DE255300AB55B1 /* xplan-ios */,
|
||||||
|
189DD52A26DE255300AB55B1 /* Products */,
|
||||||
|
D09C770DC30B9BAAEAFC7945 /* Pods */,
|
||||||
|
BFB922F5D81845AC32D1E1ED /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD52A26DE255300AB55B1 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD52926DE255300AB55B1 /* xplan-ios.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD52B26DE255300AB55B1 /* xplan-ios */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD56B26DF5B0900AB55B1 /* Base */,
|
||||||
|
189DD56126DE45F800AB55B1 /* Main */,
|
||||||
|
189DD52C26DE255300AB55B1 /* AppDelegate.h */,
|
||||||
|
189DD52D26DE255300AB55B1 /* AppDelegate.m */,
|
||||||
|
189DD53826DE255600AB55B1 /* Assets.xcassets */,
|
||||||
|
189DD53A26DE255600AB55B1 /* LaunchScreen.storyboard */,
|
||||||
|
189DD53D26DE255600AB55B1 /* Info.plist */,
|
||||||
|
189DD53E26DE255600AB55B1 /* main.m */,
|
||||||
|
);
|
||||||
|
path = "xplan-ios";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD54826DE327B00AB55B1 /* MVP */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
187EEEA926E62679002833B2 /* Api */,
|
||||||
|
189DD56026DE456100AB55B1 /* Model */,
|
||||||
|
189DD55326DE382E00AB55B1 /* View */,
|
||||||
|
189DD55726DE398A00AB55B1 /* Presenter */,
|
||||||
|
189DD55D26DE3BA300AB55B1 /* Protocol */,
|
||||||
|
);
|
||||||
|
path = MVP;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD55326DE382E00AB55B1 /* View */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD54E26DE37F900AB55B1 /* MvpViewController.h */,
|
||||||
|
189DD54F26DE37F900AB55B1 /* MvpViewController.m */,
|
||||||
|
);
|
||||||
|
path = View;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD55726DE398A00AB55B1 /* Presenter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD55826DE39D200AB55B1 /* BaseMvpPresenter.h */,
|
||||||
|
189DD55926DE39D200AB55B1 /* BaseMvpPresenter.m */,
|
||||||
|
);
|
||||||
|
path = Presenter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD55D26DE3BA300AB55B1 /* Protocol */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD55E26DE3BBE00AB55B1 /* BaseMvpProtocol.h */,
|
||||||
|
);
|
||||||
|
path = Protocol;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD56026DE456100AB55B1 /* Model */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
path = Model;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD56126DE45F800AB55B1 /* Main */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD54826DE327B00AB55B1 /* MVP */,
|
||||||
|
189DD56226DE460400AB55B1 /* Login */,
|
||||||
|
189DD53226DE255300AB55B1 /* TabbarViewController.h */,
|
||||||
|
189DD53326DE255300AB55B1 /* TabbarViewController.m */,
|
||||||
|
);
|
||||||
|
path = Main;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD56226DE460400AB55B1 /* Login */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD75326E2211000AB55B1 /* Api */,
|
||||||
|
189DD58926DF977D00AB55B1 /* Model */,
|
||||||
|
189DD58A26DF978700AB55B1 /* View */,
|
||||||
|
189DD58B26DF978F00AB55B1 /* Presenter */,
|
||||||
|
189DD59126DF97F600AB55B1 /* Protocol */,
|
||||||
|
);
|
||||||
|
path = Login;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD56B26DF5B0900AB55B1 /* Base */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD61E26E0ED0100AB55B1 /* Net */,
|
||||||
|
189DD5A726DFA09700AB55B1 /* Tool */,
|
||||||
|
189DD56C26DF5B5400AB55B1 /* UI */,
|
||||||
|
189DD57226DF5F0C00AB55B1 /* Base.pch */,
|
||||||
|
);
|
||||||
|
path = Base;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD56C26DF5B5400AB55B1 /* UI */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD54926DE338800AB55B1 /* BaseViewController.h */,
|
||||||
|
189DD54A26DE338800AB55B1 /* BaseViewController.m */,
|
||||||
|
189DD67C26E1FD8900AB55B1 /* UIImage+Utils.h */,
|
||||||
|
189DD67D26E1FD8900AB55B1 /* UIImage+Utils.m */,
|
||||||
|
189DD68326E1FDBB00AB55B1 /* XCHUDTool.h */,
|
||||||
|
189DD68226E1FDBB00AB55B1 /* XCHUDTool.m */,
|
||||||
|
);
|
||||||
|
path = UI;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD58926DF977D00AB55B1 /* Model */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
path = Model;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD58A26DF978700AB55B1 /* View */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD56326DE465A00AB55B1 /* LoginViewController.h */,
|
||||||
|
189DD56426DE465A00AB55B1 /* LoginViewController.m */,
|
||||||
|
);
|
||||||
|
path = View;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD58B26DF978F00AB55B1 /* Presenter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD58D26DF97E700AB55B1 /* LoginPresenter.h */,
|
||||||
|
189DD58E26DF97E700AB55B1 /* LoginPresenter.m */,
|
||||||
|
);
|
||||||
|
path = Presenter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD59126DF97F600AB55B1 /* Protocol */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD59426DF986300AB55B1 /* LoginProtocol.h */,
|
||||||
|
);
|
||||||
|
path = Protocol;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD5A726DFA09700AB55B1 /* Tool */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD74D26E21D9000AB55B1 /* GCDHelper */,
|
||||||
|
189DD74726E21D8400AB55B1 /* KeyChain */,
|
||||||
|
189DD74226E21CCC00AB55B1 /* Reachability */,
|
||||||
|
189DD73626E21C3F00AB55B1 /* YYUtility */,
|
||||||
|
);
|
||||||
|
path = Tool;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD61E26E0ED0100AB55B1 /* Net */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD78026E620FE00AB55B1 /* ApiHost.h */,
|
||||||
|
189DD6FD26E20E5900AB55B1 /* HttpRequestHelper.h */,
|
||||||
|
189DD6FE26E20E5900AB55B1 /* HttpRequestHelper.m */,
|
||||||
|
);
|
||||||
|
path = Net;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD73626E21C3F00AB55B1 /* YYUtility */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD73726E21C3F00AB55B1 /* CarrierIdentifier.h */,
|
||||||
|
189DD73C26E21C3F00AB55B1 /* YYUtility.h */,
|
||||||
|
189DD73926E21C3F00AB55B1 /* YYUtility.m */,
|
||||||
|
189DD73B26E21C3F00AB55B1 /* YYUtility+App.m */,
|
||||||
|
189DD73A26E21C3F00AB55B1 /* YYUtility+Carrier.m */,
|
||||||
|
189DD73826E21C3F00AB55B1 /* YYUtility+Device.m */,
|
||||||
|
);
|
||||||
|
path = YYUtility;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD74226E21CCC00AB55B1 /* Reachability */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD74326E21CCC00AB55B1 /* YYReachability.h */,
|
||||||
|
189DD74426E21CCC00AB55B1 /* YYReachability.m */,
|
||||||
|
);
|
||||||
|
path = Reachability;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD74726E21D8400AB55B1 /* KeyChain */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD74826E21D8400AB55B1 /* SSKeychain.h */,
|
||||||
|
189DD74926E21D8400AB55B1 /* SSKeychain.m */,
|
||||||
|
);
|
||||||
|
path = KeyChain;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD74D26E21D9000AB55B1 /* GCDHelper */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD74E26E21D9000AB55B1 /* GCDHelper.m */,
|
||||||
|
189DD74F26E21D9000AB55B1 /* GCDHelper.h */,
|
||||||
|
);
|
||||||
|
path = GCDHelper;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
189DD75326E2211000AB55B1 /* Api */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
189DD76026E60DDC00AB55B1 /* Api+Login.h */,
|
||||||
|
189DD76126E60DDC00AB55B1 /* Api+Login.m */,
|
||||||
|
);
|
||||||
|
path = Api;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
BFB922F5D81845AC32D1E1ED /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
CACF623970097D653132D69A /* Pods_xplan_ios.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D09C770DC30B9BAAEAFC7945 /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7DB00EC07F1D0ADFF900B38D /* Pods-xplan-ios.debug.xcconfig */,
|
||||||
|
B66633E061B1B34177CD011C /* Pods-xplan-ios.release.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
189DD52826DE255300AB55B1 /* xplan-ios */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 189DD54226DE255600AB55B1 /* Build configuration list for PBXNativeTarget "xplan-ios" */;
|
||||||
|
buildPhases = (
|
||||||
|
1865B406E358C680125F108D /* [CP] Check Pods Manifest.lock */,
|
||||||
|
189DD52526DE255300AB55B1 /* Sources */,
|
||||||
|
189DD52626DE255300AB55B1 /* Frameworks */,
|
||||||
|
189DD52726DE255300AB55B1 /* Resources */,
|
||||||
|
8311720C3643AC2030B96510 /* [CP] Embed Pods Frameworks */,
|
||||||
|
4C25F8F9E2D1F501119C383D /* [CP] Copy Pods Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = "xplan-ios";
|
||||||
|
productName = "xplan-ios";
|
||||||
|
productReference = 189DD52926DE255300AB55B1 /* xplan-ios.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
189DD52126DE255300AB55B1 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 1240;
|
||||||
|
TargetAttributes = {
|
||||||
|
189DD52826DE255300AB55B1 = {
|
||||||
|
CreatedOnToolsVersion = 12.4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 189DD52426DE255300AB55B1 /* Build configuration list for PBXProject "xplan-ios" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 189DD52026DE255300AB55B1;
|
||||||
|
productRefGroup = 189DD52A26DE255300AB55B1 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
189DD52826DE255300AB55B1 /* xplan-ios */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
189DD52726DE255300AB55B1 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
189DD53C26DE255600AB55B1 /* LaunchScreen.storyboard in Resources */,
|
||||||
|
189DD53926DE255600AB55B1 /* Assets.xcassets in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
1865B406E358C680125F108D /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-xplan-ios-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
4C25F8F9E2D1F501119C383D /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-xplan-ios/Pods-xplan-ios-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-xplan-ios/Pods-xplan-ios-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-xplan-ios/Pods-xplan-ios-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
8311720C3643AC2030B96510 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-xplan-ios/Pods-xplan-ios-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-xplan-ios/Pods-xplan-ios-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-xplan-ios/Pods-xplan-ios-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
189DD52526DE255300AB55B1 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
189DD76226E60DDC00AB55B1 /* Api+Login.m in Sources */,
|
||||||
|
189DD73E26E21C3F00AB55B1 /* YYUtility.m in Sources */,
|
||||||
|
189DD53426DE255300AB55B1 /* TabbarViewController.m in Sources */,
|
||||||
|
189DD55A26DE39D200AB55B1 /* BaseMvpPresenter.m in Sources */,
|
||||||
|
189DD6FF26E20E5900AB55B1 /* HttpRequestHelper.m in Sources */,
|
||||||
|
189DD74A26E21D8400AB55B1 /* SSKeychain.m in Sources */,
|
||||||
|
189DD68426E1FDBB00AB55B1 /* XCHUDTool.m in Sources */,
|
||||||
|
189DD73F26E21C3F00AB55B1 /* YYUtility+Carrier.m in Sources */,
|
||||||
|
189DD54B26DE338800AB55B1 /* BaseViewController.m in Sources */,
|
||||||
|
189DD67E26E1FD8900AB55B1 /* UIImage+Utils.m in Sources */,
|
||||||
|
189DD52E26DE255300AB55B1 /* AppDelegate.m in Sources */,
|
||||||
|
189DD56526DE465A00AB55B1 /* LoginViewController.m in Sources */,
|
||||||
|
189DD73D26E21C3F00AB55B1 /* YYUtility+Device.m in Sources */,
|
||||||
|
189DD74026E21C3F00AB55B1 /* YYUtility+App.m in Sources */,
|
||||||
|
189DD74526E21CCC00AB55B1 /* YYReachability.m in Sources */,
|
||||||
|
189DD75026E21D9000AB55B1 /* GCDHelper.m in Sources */,
|
||||||
|
189DD75926E6003C00AB55B1 /* Api.m in Sources */,
|
||||||
|
189DD53F26DE255600AB55B1 /* main.m in Sources */,
|
||||||
|
189DD58F26DF97E700AB55B1 /* LoginPresenter.m in Sources */,
|
||||||
|
189DD55026DE37F900AB55B1 /* MvpViewController.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
189DD53A26DE255600AB55B1 /* LaunchScreen.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
189DD53B26DE255600AB55B1 /* Base */,
|
||||||
|
);
|
||||||
|
name = LaunchScreen.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
189DD54026DE255600AB55B1 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
189DD54126DE255600AB55B1 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
189DD54326DE255600AB55B1 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7DB00EC07F1D0ADFF900B38D /* Pods-xplan-ios.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 48UCG35Q9W;
|
||||||
|
GCC_PREFIX_HEADER = "xplan-ios/Base/Base.pch";
|
||||||
|
INFOPLIST_FILE = "xplan-ios/Info.plist";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 3.1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.yinyou.enterprise.ios;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
189DD54426DE255600AB55B1 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = B66633E061B1B34177CD011C /* Pods-xplan-ios.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 48UCG35Q9W;
|
||||||
|
GCC_PREFIX_HEADER = "xplan-ios/Base/Base.pch";
|
||||||
|
INFOPLIST_FILE = "xplan-ios/Info.plist";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 3.1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.yinyou.enterprise.ios;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
189DD52426DE255300AB55B1 /* Build configuration list for PBXProject "xplan-ios" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
189DD54026DE255600AB55B1 /* Debug */,
|
||||||
|
189DD54126DE255600AB55B1 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
189DD54226DE255600AB55B1 /* Build configuration list for PBXNativeTarget "xplan-ios" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
189DD54326DE255600AB55B1 /* Debug */,
|
||||||
|
189DD54426DE255600AB55B1 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 189DD52126DE255300AB55B1 /* Project object */;
|
||||||
|
}
|
7
xplan-ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
xplan-ios.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:xplan-ios.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
15
xplan-ios/AppDelegate.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||||
|
|
||||||
|
@property (strong, nonatomic) UIWindow *window;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
26
xplan-ios/AppDelegate.m
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
#import "TabbarViewController.h"
|
||||||
|
|
||||||
|
@interface AppDelegate ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
|
TabbarViewController *vc = [[TabbarViewController alloc] init];
|
||||||
|
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
|
||||||
|
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||||
|
self.window.rootViewController = nav;
|
||||||
|
[self.window makeKeyAndVisible];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
11
xplan-ios/Assets.xcassets/AccentColor.colorset/Contents.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 392 KiB |
62
xplan-ios/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Icon-Spotlight-40.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-60.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-Small@2x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-Small@3x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-Spotlight-40@2x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-60@2x-1.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-60@2x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-60@3x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "APP Store 1024_1024 (2).png",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/AppIcon.appiconset/Icon-60.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
xplan-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x-1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
xplan-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
xplan-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
xplan-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
xplan-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 6.4 KiB |
6
xplan-ios/Assets.xcassets/Common/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
22
xplan-ios/Assets.xcassets/Common/common_checkbox_checked.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "common_checkbox_checked@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "common_checkbox_checked@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Common/common_checkbox_checked.imageset/common_checkbox_checked@2x.png
vendored
Normal file
After Width: | Height: | Size: 696 B |
BIN
xplan-ios/Assets.xcassets/Common/common_checkbox_checked.imageset/common_checkbox_checked@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
22
xplan-ios/Assets.xcassets/Common/common_checkbox_uncheck.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "common_checkbox_uncheck@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "common_checkbox_uncheck@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Common/common_checkbox_uncheck.imageset/common_checkbox_uncheck@2x.png
vendored
Normal file
After Width: | Height: | Size: 690 B |
BIN
xplan-ios/Assets.xcassets/Common/common_checkbox_uncheck.imageset/common_checkbox_uncheck@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
22
xplan-ios/Assets.xcassets/Common/common_loading.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "loading@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "loading@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Common/common_loading.imageset/loading@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
xplan-ios/Assets.xcassets/Common/common_loading.imageset/loading@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.2 KiB |
22
xplan-ios/Assets.xcassets/Common/common_nav_back.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "common_nav_back@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "common_nav_back@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Common/common_nav_back.imageset/common_nav_back@2x.png
vendored
Normal file
After Width: | Height: | Size: 313 B |
BIN
xplan-ios/Assets.xcassets/Common/common_nav_back.imageset/common_nav_back@3x.png
vendored
Normal file
After Width: | Height: | Size: 558 B |
6
xplan-ios/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
6
xplan-ios/Assets.xcassets/Login/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
22
xplan-ios/Assets.xcassets/Login/login_appIcon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_appIcon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_appIcon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_appIcon.imageset/login_appIcon@2x.png
vendored
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_appIcon.imageset/login_appIcon@3x.png
vendored
Normal file
After Width: | Height: | Size: 10 KiB |
22
xplan-ios/Assets.xcassets/Login/login_auth_bubble.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_auth_bubble@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_auth_bubble@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_auth_bubble.imageset/login_auth_bubble@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_auth_bubble.imageset/login_auth_bubble@3x.png
vendored
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_china_mobile.imageset/ChinaMobile_icon@2x.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_china_mobile.imageset/ChinaMobile_icon@3x.png
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
22
xplan-ios/Assets.xcassets/Login/login_china_mobile.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "ChinaMobile_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "ChinaMobile_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
22
xplan-ios/Assets.xcassets/Login/login_ct_mobile.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "ctmobile_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "ctmobile_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_ct_mobile.imageset/ctmobile_icon@2x.png
vendored
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_ct_mobile.imageset/ctmobile_icon@3x.png
vendored
Normal file
After Width: | Height: | Size: 55 KiB |
22
xplan-ios/Assets.xcassets/Login/login_phone.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "phone@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "phone@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_phone.imageset/phone@2x.png
vendored
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_phone.imageset/phone@3x.png
vendored
Normal file
After Width: | Height: | Size: 9.5 KiB |
22
xplan-ios/Assets.xcassets/Login/login_qq.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "qq@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "qq@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_qq.imageset/qq@2x.png
vendored
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_qq.imageset/qq@3x.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
22
xplan-ios/Assets.xcassets/Login/login_unicom_mobile.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "unicomMobile_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "unicomMobile_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_unicom_mobile.imageset/unicomMobile_icon@2x.png
vendored
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_unicom_mobile.imageset/unicomMobile_icon@3x.png
vendored
Normal file
After Width: | Height: | Size: 6.5 KiB |
22
xplan-ios/Assets.xcassets/Login/login_wechat.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "wechat@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "wechat@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
xplan-ios/Assets.xcassets/Login/login_wechat.imageset/wechat@2x.png
vendored
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
xplan-ios/Assets.xcassets/Login/login_wechat.imageset/wechat@3x.png
vendored
Normal file
After Width: | Height: | Size: 10 KiB |
25
xplan-ios/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
63
xplan-ios/Base/Base.pch
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// Base.pch
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Base_pch
|
||||||
|
#define Base_pch
|
||||||
|
|
||||||
|
// Include any system framework and library headers here that should be included in all compilation units.
|
||||||
|
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#define AppName ([[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"])
|
||||||
|
|
||||||
|
//iPhoneX系列设备(刘海屏设备)
|
||||||
|
#define iPhoneXSeries \
|
||||||
|
({BOOL isPhoneXSeries = NO;\
|
||||||
|
if (@available(iOS 11.0, *)) {\
|
||||||
|
isPhoneXSeries = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0;\
|
||||||
|
}\
|
||||||
|
(isPhoneXSeries);})
|
||||||
|
|
||||||
|
#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 ThemeDefaultColor UIColorFromRGB(0x248CFE)
|
||||||
|
/// 页面背景色
|
||||||
|
#define ThemeBackgroundColor UIColorFromRGB(0x1C1B22)
|
||||||
|
/// 字体默认颜色
|
||||||
|
#define ThemeTextColor UIColorFromRGB(0xC6C6E9)
|
||||||
|
/// 字体默认颜色
|
||||||
|
#define ThemeTextSecondColor UIColorFromRGB(0x4F516A)
|
||||||
|
/// 按钮渐变色 start
|
||||||
|
#define ThemeButtonGradientStartColor UIColorFromRGB(0x218EFF)
|
||||||
|
/// 按钮渐变色 end
|
||||||
|
#define ThemeButtonGradientEndColor UIColorFromRGB(0x7727E4)
|
||||||
|
|
||||||
|
#define KScreenWidth [[UIScreen mainScreen] bounds].size.width
|
||||||
|
#define KScreenHeight [[UIScreen mainScreen] bounds].size.height
|
||||||
|
#define statusbarHeight [[UIApplication sharedApplication] statusBarFrame].size.height
|
||||||
|
#define kStatusBarHeight statusbarHeight
|
||||||
|
#define kSafeAreaBottomHeight (iPhoneXSeries ? 34 : 0)
|
||||||
|
#define kSafeAreaTopHeight (iPhoneXSeries ? 24 : 0)
|
||||||
|
#define kNavigationHeight (kStatusBarHeight + 44)
|
||||||
|
#define kTabBarHeight (iPhoneXSeries ? 49.0+34.0 : 49.0)
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define NSLog(fmt,...) NSLog((@"%s [Line %d]" fmt),__PRETTY_FUNCTION__,__LINE__,##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define NSLog(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define isEnterprise \
|
||||||
|
({BOOL isEnterprise = NO;\
|
||||||
|
if (@available(iOS 11.0, *)) {\
|
||||||
|
NSString *bundleID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];\
|
||||||
|
isEnterprise = [bundleID isEqualToString:@"com.yinyou.enterprise.ios"];\
|
||||||
|
}\
|
||||||
|
(isEnterprise);})
|
||||||
|
|
||||||
|
#endif /* Base_pch */
|
17
xplan-ios/Base/Net/ApiHost.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// ApiHost.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ApiHost_h
|
||||||
|
#define ApiHost_h
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define API_HOST_URL @"http://api.uat.lecheng163.com"
|
||||||
|
#else
|
||||||
|
#define API_HOST_URL @"https://api.lecheng163.com"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ApiHost_h */
|
59
xplan-ios/Base/Net/HttpRequestHelper.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// HttpRequestHelper.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, HttpRequestHelperMethod) {
|
||||||
|
HttpRequestHelperMethodPOST,
|
||||||
|
HttpRequestHelperMethodGET
|
||||||
|
};
|
||||||
|
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
|
||||||
|
typedef void(^HttpRequestHelperCompletion)(id _Nullable data, NSNumber * _Nullable code, NSString * _Nullable msg);
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface HttpRequestHelper : NSObject
|
||||||
|
|
||||||
|
+ (void)GET:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure;
|
||||||
|
|
||||||
|
+ (void)GET:(NSString *)interfaceUrl
|
||||||
|
method:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure;
|
||||||
|
|
||||||
|
|
||||||
|
+ (void)POST:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure;
|
||||||
|
|
||||||
|
+ (void)POST:(NSString *)interfaceUrl
|
||||||
|
method:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure;
|
||||||
|
|
||||||
|
+ (void)request:(NSString *)url
|
||||||
|
method:(HttpRequestHelperMethod)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure;
|
||||||
|
|
||||||
|
+ (void)request:(NSString *)path
|
||||||
|
method:(HttpRequestHelperMethod)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
completion:(HttpRequestHelperCompletion)completion;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
170
xplan-ios/Base/Net/HttpRequestHelper.m
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
//
|
||||||
|
// HttpRequestHelper.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "HttpRequestHelper.h"
|
||||||
|
#import "ApiHost.h"
|
||||||
|
#import "YYUtility.h"
|
||||||
|
#import "YYReachability.h"
|
||||||
|
#import <AFNetworking.h>
|
||||||
|
|
||||||
|
@implementation HttpRequestHelper
|
||||||
|
|
||||||
|
+(AFHTTPSessionManager *)requestManager
|
||||||
|
{
|
||||||
|
static AFHTTPSessionManager *manager = nil;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||||
|
manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:config];
|
||||||
|
manager.requestSerializer.timeoutInterval = 15;
|
||||||
|
manager.responseSerializer = [AFJSONResponseSerializer serializer];
|
||||||
|
manager.requestSerializer.HTTPShouldHandleCookies = YES;
|
||||||
|
// 客户端是否信任非法证书
|
||||||
|
manager.securityPolicy.allowInvalidCertificates = YES;
|
||||||
|
AFSecurityPolicy *securityPolicy= [AFSecurityPolicy defaultPolicy];
|
||||||
|
manager.securityPolicy = securityPolicy;
|
||||||
|
// 是否在证书域字段中验证域名
|
||||||
|
[manager.securityPolicy setValidatesDomainName:NO];
|
||||||
|
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"image/jpeg",@"image/png", nil];
|
||||||
|
});
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)GET:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure
|
||||||
|
{
|
||||||
|
[self GET:API_HOST_URL method:method params:params success:success failure:failure];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)GET:(NSString *)interfaceUrl method:(NSString *)method params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSNumber *, NSString *))failure
|
||||||
|
{
|
||||||
|
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) {
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AFHTTPSessionManager *manager = [HttpRequestHelper requestManager];
|
||||||
|
|
||||||
|
NSString *url = [NSString stringWithFormat:@"%@/%@", interfaceUrl, method];
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"url:%@, parameter:%@", url, params);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[manager GET:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||||
|
|
||||||
|
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||||
|
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)POST:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *resCode, NSString *message))failure
|
||||||
|
{
|
||||||
|
[self POST:API_HOST_URL method:method params:params success:success failure:failure];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)POST:(NSString *)interfaceUrl
|
||||||
|
method:(NSString *)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *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(), ^{
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AFHTTPSessionManager *manager = [HttpRequestHelper requestManager];
|
||||||
|
|
||||||
|
NSString *url = [NSString stringWithFormat:@"%@/%@", interfaceUrl, method];
|
||||||
|
params = [self configBaseParmars:params];
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"\nurl:\n%@\nparameter:\n%@", url, params);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[manager POST:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"\n%@", responseObject);
|
||||||
|
#endif
|
||||||
|
success(responseObject);
|
||||||
|
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"\n%@", error);
|
||||||
|
#endif
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)request:(NSString *)url
|
||||||
|
method:(HttpRequestHelperMethod)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
success:(void (^)(id data))success
|
||||||
|
failure:(void (^)(NSNumber *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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)request:(NSString *)path
|
||||||
|
method:(HttpRequestHelperMethod)method
|
||||||
|
params:(NSDictionary *)params
|
||||||
|
completion:(HttpRequestHelperCompletion)completion
|
||||||
|
{
|
||||||
|
if ([path hasPrefix:@"/"]) {
|
||||||
|
path = [path substringFromIndex:1];
|
||||||
|
}
|
||||||
|
[self request:path method:method params:params success:^(id data) {
|
||||||
|
if (completion) {
|
||||||
|
completion(data, nil, nil);
|
||||||
|
}
|
||||||
|
} failure:^(NSNumber *resCode, NSString *message) {
|
||||||
|
if (completion) {
|
||||||
|
completion(nil, resCode, message);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary*)configBaseParmars:(NSDictionary *)parmars {
|
||||||
|
NSDictionary *defaultBasciParame = @{
|
||||||
|
@"os" : @"iOS",
|
||||||
|
@"osVersion" : [YYUtility systemVersion],
|
||||||
|
@"netType" : ([YYUtility networkStatus] == ReachableViaWiFi) ? @2 : @1,
|
||||||
|
@"ispType" : @([YYUtility carrierIdentifier]),
|
||||||
|
@"channel" : [YYUtility getAppSource] ? : @"",
|
||||||
|
@"model" : [YYUtility modelName],
|
||||||
|
@"deviceId" : [YYUtility deviceUniqueIdentification],
|
||||||
|
@"appVersion" : [YYUtility appVersion],
|
||||||
|
@"app" : [YYUtility appName]
|
||||||
|
};
|
||||||
|
if (!parmars||![parmars isKindOfClass:[NSDictionary class]]){
|
||||||
|
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:defaultBasciParame];
|
||||||
|
return dic;
|
||||||
|
}
|
||||||
|
NSMutableDictionary * dic = [NSMutableDictionary dictionaryWithDictionary:parmars];
|
||||||
|
for (NSString *parameKey in defaultBasciParame.allKeys) {
|
||||||
|
[dic setObject:defaultBasciParame[parameKey] forKey:parameKey];
|
||||||
|
}
|
||||||
|
return dic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
11
xplan-ios/Base/Tool/GCDHelper/GCDHelper.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// GCDHelper.h
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14/7/18.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
void dispatch_main_sync_safe(dispatch_block_t block);
|
16
xplan-ios/Base/Tool/GCDHelper/GCDHelper.m
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
357
xplan-ios/Base/Tool/KeyChain/SSKeychain.h
Executable file
@@ -0,0 +1,357 @@
|
|||||||
|
//
|
||||||
|
// SSKeychain.h
|
||||||
|
// SSToolkit
|
||||||
|
//
|
||||||
|
// Created by Sam Soffes on 5/19/10.
|
||||||
|
// Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Security/Security.h>
|
||||||
|
|
||||||
|
/** Error codes that can be returned in NSError objects. */
|
||||||
|
typedef enum {
|
||||||
|
/** No error. */
|
||||||
|
SSKeychainErrorNone = noErr,
|
||||||
|
|
||||||
|
/** Some of the arguments were invalid. */
|
||||||
|
SSKeychainErrorBadArguments = -1001,
|
||||||
|
|
||||||
|
/** There was no password. */
|
||||||
|
SSKeychainErrorNoPassword = -1002,
|
||||||
|
|
||||||
|
/** One or more parameters passed internally were not valid. */
|
||||||
|
SSKeychainErrorInvalidParameter = errSecParam,
|
||||||
|
|
||||||
|
/** Failed to allocate memory. */
|
||||||
|
SSKeychainErrorFailedToAllocated = errSecAllocate,
|
||||||
|
|
||||||
|
/** No trust results are available. */
|
||||||
|
SSKeychainErrorNotAvailable = errSecNotAvailable,
|
||||||
|
|
||||||
|
/** Authorization/Authentication failed. */
|
||||||
|
SSKeychainErrorAuthorizationFailed = errSecAuthFailed,
|
||||||
|
|
||||||
|
/** The item already exists. */
|
||||||
|
SSKeychainErrorDuplicatedItem = errSecDuplicateItem,
|
||||||
|
|
||||||
|
/** The item cannot be found.*/
|
||||||
|
SSKeychainErrorNotFound = errSecItemNotFound,
|
||||||
|
|
||||||
|
/** Interaction with the Security Server is not allowed. */
|
||||||
|
SSKeychainErrorInteractionNotAllowed = errSecInteractionNotAllowed,
|
||||||
|
|
||||||
|
/** Unable to decode the provided data. */
|
||||||
|
SSKeychainErrorFailedToDecode = errSecDecode
|
||||||
|
} SSKeychainErrorCode;
|
||||||
|
|
||||||
|
extern NSString *const kSSKeychainErrorDomain;
|
||||||
|
|
||||||
|
/** Account name. */
|
||||||
|
extern NSString *const kSSKeychainAccountKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Time the item was created.
|
||||||
|
|
||||||
|
The value will be a string.
|
||||||
|
*/
|
||||||
|
extern NSString *const kSSKeychainCreatedAtKey;
|
||||||
|
|
||||||
|
/** Item class. */
|
||||||
|
extern NSString *const kSSKeychainClassKey;
|
||||||
|
|
||||||
|
/** Item description. */
|
||||||
|
extern NSString *const kSSKeychainDescriptionKey;
|
||||||
|
|
||||||
|
/** Item label. */
|
||||||
|
extern NSString *const kSSKeychainLabelKey;
|
||||||
|
|
||||||
|
/** Time the item was last modified.
|
||||||
|
|
||||||
|
The value will be a string.
|
||||||
|
*/
|
||||||
|
extern NSString *const kSSKeychainLastModifiedKey;
|
||||||
|
|
||||||
|
/** Where the item was created. */
|
||||||
|
extern NSString *const kSSKeychainWhereKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system
|
||||||
|
Keychain on Mac OS X and iOS.
|
||||||
|
|
||||||
|
This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors.
|
||||||
|
SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it).
|
||||||
|
*/
|
||||||
|
@interface SSKeychain : NSObject
|
||||||
|
|
||||||
|
///-----------------------
|
||||||
|
/// @name Getting Accounts
|
||||||
|
///-----------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts.
|
||||||
|
|
||||||
|
See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
|
||||||
|
dictionaries returned by this method.
|
||||||
|
|
||||||
|
@return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
|
||||||
|
accounts. The order of the objects in the array isn't defined.
|
||||||
|
|
||||||
|
@see allAccounts:
|
||||||
|
*/
|
||||||
|
+ (NSArray *)allAccounts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an array containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
|
||||||
|
accounts.
|
||||||
|
|
||||||
|
See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
|
||||||
|
dictionaries returned by this method.
|
||||||
|
|
||||||
|
@param error If accessing the accounts fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
|
||||||
|
accounts. The order of the objects in the array isn't defined.
|
||||||
|
|
||||||
|
@see allAccounts
|
||||||
|
*/
|
||||||
|
+ (NSArray *)allAccounts:(NSError **)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
|
||||||
|
accounts for the given service.
|
||||||
|
|
||||||
|
See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
|
||||||
|
dictionaries returned by this method.
|
||||||
|
|
||||||
|
@param serviceName The service for which to return the corresponding accounts.
|
||||||
|
|
||||||
|
@return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain
|
||||||
|
doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
|
||||||
|
|
||||||
|
@see accountsForService:error:
|
||||||
|
*/
|
||||||
|
+ (NSArray *)accountsForService:(NSString *)serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
|
||||||
|
accounts for the given service.
|
||||||
|
|
||||||
|
@param serviceName The service for which to return the corresponding accounts.
|
||||||
|
|
||||||
|
@param error If accessing the accounts fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain
|
||||||
|
doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
|
||||||
|
|
||||||
|
@see accountsForService:
|
||||||
|
*/
|
||||||
|
+ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError **)error;
|
||||||
|
|
||||||
|
|
||||||
|
///------------------------
|
||||||
|
/// @name Getting Passwords
|
||||||
|
///------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
|
||||||
|
password for the given parameters.
|
||||||
|
|
||||||
|
@param serviceName The service for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to return the corresponding password.
|
||||||
|
|
||||||
|
@return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
|
||||||
|
have a password for the given parameters.
|
||||||
|
|
||||||
|
@see passwordForService:account:error:
|
||||||
|
*/
|
||||||
|
+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
|
||||||
|
password for the given parameters.
|
||||||
|
|
||||||
|
@param serviceName The service for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param error If accessing the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
|
||||||
|
have a password for the given parameters.
|
||||||
|
|
||||||
|
@see passwordForService:account:
|
||||||
|
*/
|
||||||
|
+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data
|
||||||
|
for the given parameters.
|
||||||
|
|
||||||
|
@param serviceName The service for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param error If accessing the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't
|
||||||
|
have data for the given parameters.
|
||||||
|
|
||||||
|
@see passwordDataForService:account:error:
|
||||||
|
*/
|
||||||
|
+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data
|
||||||
|
for the given parameters.
|
||||||
|
|
||||||
|
@param serviceName The service for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to return the corresponding password.
|
||||||
|
|
||||||
|
@param error If accessing the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't
|
||||||
|
have a password for the given parameters.
|
||||||
|
|
||||||
|
@see passwordDataForService:account:
|
||||||
|
*/
|
||||||
|
+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
|
||||||
|
|
||||||
|
|
||||||
|
///-------------------------
|
||||||
|
/// @name Deleting Passwords
|
||||||
|
///-------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes a password from the Keychain.
|
||||||
|
|
||||||
|
@param serviceName The service for which to delete the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to delete the corresponding password.
|
||||||
|
|
||||||
|
@return Returns `YES` on success, or `NO` on failure.
|
||||||
|
|
||||||
|
@see deletePasswordForService:account:error:
|
||||||
|
*/
|
||||||
|
+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes a password from the Keychain.
|
||||||
|
|
||||||
|
@param serviceName The service for which to delete the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to delete the corresponding password.
|
||||||
|
|
||||||
|
@param error If deleting the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns `YES` on success, or `NO` on failure.
|
||||||
|
|
||||||
|
@see deletePasswordForService:account:
|
||||||
|
*/
|
||||||
|
+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
|
||||||
|
|
||||||
|
|
||||||
|
///------------------------
|
||||||
|
/// @name Setting Passwords
|
||||||
|
///------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets a password in the Keychain.
|
||||||
|
|
||||||
|
@param password The password to store in the Keychain.
|
||||||
|
|
||||||
|
@param serviceName The service for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to set the corresponding password.
|
||||||
|
|
||||||
|
@return Returns `YES` on success, or `NO` on failure.
|
||||||
|
|
||||||
|
@see setPassword:forService:account:error:
|
||||||
|
*/
|
||||||
|
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets a password in the Keychain.
|
||||||
|
|
||||||
|
@param password The password to store in the Keychain.
|
||||||
|
|
||||||
|
@param serviceName The service for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param error If setting the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns `YES` on success, or `NO` on failure.
|
||||||
|
|
||||||
|
@see setPassword:forService:account:
|
||||||
|
*/
|
||||||
|
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets arbirary data in the Keychain.
|
||||||
|
|
||||||
|
@param password The data to store in the Keychain.
|
||||||
|
|
||||||
|
@param serviceName The service for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param error If setting the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns `YES` on success, or `NO` on failure.
|
||||||
|
|
||||||
|
@see setPasswordData:forService:account:error:
|
||||||
|
*/
|
||||||
|
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets arbirary data in the Keychain.
|
||||||
|
|
||||||
|
@param password The data to store in the Keychain.
|
||||||
|
|
||||||
|
@param serviceName The service for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param account The account for which to set the corresponding password.
|
||||||
|
|
||||||
|
@param error If setting the password fails, upon return contains an error that describes the problem.
|
||||||
|
|
||||||
|
@return Returns `YES` on success, or `NO` on failure.
|
||||||
|
|
||||||
|
@see setPasswordData:forService:account:
|
||||||
|
*/
|
||||||
|
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
|
||||||
|
|
||||||
|
|
||||||
|
///--------------------
|
||||||
|
/// @name Configuration
|
||||||
|
///--------------------
|
||||||
|
|
||||||
|
#if __IPHONE_4_0 && TARGET_OS_IPHONE
|
||||||
|
/**
|
||||||
|
Returns the accessibility type for all future passwords saved to the Keychain.
|
||||||
|
|
||||||
|
@return Returns the accessibility type.
|
||||||
|
|
||||||
|
The return value will be `NULL` or one of the "Keychain Item Accessibility Constants" used for determining when a
|
||||||
|
keychain item should be readable.
|
||||||
|
|
||||||
|
@see accessibilityType
|
||||||
|
*/
|
||||||
|
+ (CFTypeRef)accessibilityType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the accessibility type for all future passwords saved to the Keychain.
|
||||||
|
|
||||||
|
@param accessibilityType One of the "Keychain Item Accessibility Constants" used for determining when a keychain item
|
||||||
|
should be readable.
|
||||||
|
|
||||||
|
If the value is `NULL` (the default), the Keychain default will be used.
|
||||||
|
|
||||||
|
@see accessibilityType
|
||||||
|
*/
|
||||||
|
+ (void)setAccessibilityType:(CFTypeRef)accessibilityType;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@end
|
262
xplan-ios/Base/Tool/KeyChain/SSKeychain.m
Executable file
@@ -0,0 +1,262 @@
|
|||||||
|
//
|
||||||
|
// SSKeychain.m
|
||||||
|
// SSToolkit
|
||||||
|
//
|
||||||
|
// Created by Sam Soffes on 5/19/10.
|
||||||
|
// Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SSKeychain.h"
|
||||||
|
|
||||||
|
NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain";
|
||||||
|
|
||||||
|
NSString *const kSSKeychainAccountKey = @"acct";
|
||||||
|
NSString *const kSSKeychainCreatedAtKey = @"cdat";
|
||||||
|
NSString *const kSSKeychainClassKey = @"labl";
|
||||||
|
NSString *const kSSKeychainDescriptionKey = @"desc";
|
||||||
|
NSString *const kSSKeychainLabelKey = @"labl";
|
||||||
|
NSString *const kSSKeychainLastModifiedKey = @"mdat";
|
||||||
|
NSString *const kSSKeychainWhereKey = @"svce";
|
||||||
|
|
||||||
|
#if __IPHONE_4_0 && TARGET_OS_IPHONE
|
||||||
|
CFTypeRef SSKeychainAccessibilityType = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface SSKeychain ()
|
||||||
|
+ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SSKeychain
|
||||||
|
|
||||||
|
#pragma mark - Getting Accounts
|
||||||
|
|
||||||
|
+ (NSArray *)allAccounts {
|
||||||
|
return [self accountsForService:nil error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSArray *)allAccounts:(NSError **)error {
|
||||||
|
return [self accountsForService:nil error:error];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSArray *)accountsForService:(NSString *)service {
|
||||||
|
return [self accountsForService:service error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSArray *)accountsForService:(NSString *)service error:(NSError **)error {
|
||||||
|
OSStatus status = SSKeychainErrorBadArguments;
|
||||||
|
NSMutableDictionary *query = [self _queryForService:service account:nil];
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
|
||||||
|
[query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
|
||||||
|
#else
|
||||||
|
[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
|
||||||
|
[query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CFTypeRef result = NULL;
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
|
||||||
|
#else
|
||||||
|
status = SecItemCopyMatching((CFDictionaryRef)query, &result);
|
||||||
|
#endif
|
||||||
|
if (status != noErr && error != NULL) {
|
||||||
|
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
return (__bridge_transfer NSArray *)result;
|
||||||
|
#else
|
||||||
|
return [(NSArray *)result autorelease];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Getting Passwords
|
||||||
|
|
||||||
|
+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account {
|
||||||
|
return [self passwordForService:service account:account error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
|
||||||
|
NSData *data = [self passwordDataForService:service account:account error:error];
|
||||||
|
if (data.length > 0) {
|
||||||
|
NSString *string = [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding];
|
||||||
|
#if !__has_feature(objc_arc)
|
||||||
|
[string autorelease];
|
||||||
|
#endif
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account {
|
||||||
|
return [self passwordDataForService:service account:account error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
|
||||||
|
OSStatus status = SSKeychainErrorBadArguments;
|
||||||
|
if (!service || !account) {
|
||||||
|
if (error) {
|
||||||
|
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFTypeRef result = NULL;
|
||||||
|
NSMutableDictionary *query = [self _queryForService:service account:account];
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
|
||||||
|
[query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
|
||||||
|
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
|
||||||
|
#else
|
||||||
|
[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
|
||||||
|
[query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
|
||||||
|
status = SecItemCopyMatching((CFDictionaryRef)query, &result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (status != noErr && error != NULL) {
|
||||||
|
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
return (__bridge_transfer NSData *)result;
|
||||||
|
#else
|
||||||
|
return [(NSData *)result autorelease];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Deleting Passwords
|
||||||
|
|
||||||
|
+ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account {
|
||||||
|
return [self deletePasswordForService:service account:account error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
|
||||||
|
OSStatus status = SSKeychainErrorBadArguments;
|
||||||
|
if (service && account) {
|
||||||
|
NSMutableDictionary *query = [self _queryForService:service account:account];
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
status = SecItemDelete((__bridge CFDictionaryRef)query);
|
||||||
|
#else
|
||||||
|
status = SecItemDelete((CFDictionaryRef)query);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (status != noErr && error != NULL) {
|
||||||
|
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
|
||||||
|
}
|
||||||
|
return (status == noErr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Setting Passwords
|
||||||
|
|
||||||
|
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account {
|
||||||
|
return [self setPassword:password forService:service account:account error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
|
||||||
|
NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
return [self setPasswordData:data forService:service account:account error:error];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account {
|
||||||
|
return [self setPasswordData:password forService:service account:account error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
|
||||||
|
OSStatus status = SSKeychainErrorBadArguments;
|
||||||
|
if (password && service && account) {
|
||||||
|
[self deletePasswordForService:service account:account];
|
||||||
|
NSMutableDictionary *query = [self _queryForService:service account:account];
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[query setObject:password forKey:(__bridge id)kSecValueData];
|
||||||
|
#else
|
||||||
|
[query setObject:password forKey:(id)kSecValueData];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __IPHONE_4_0 && TARGET_OS_IPHONE
|
||||||
|
if (SSKeychainAccessibilityType) {
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[query setObject:(id)[self accessibilityType] forKey:(__bridge id)kSecAttrAccessible];
|
||||||
|
#else
|
||||||
|
[query setObject:(id)[self accessibilityType] forKey:(id)kSecAttrAccessible];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
|
||||||
|
#else
|
||||||
|
status = SecItemAdd((CFDictionaryRef)query, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (status != noErr && error != NULL) {
|
||||||
|
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
|
||||||
|
}
|
||||||
|
return (status == noErr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Configuration
|
||||||
|
|
||||||
|
#if __IPHONE_4_0 && TARGET_OS_IPHONE
|
||||||
|
+ (CFTypeRef)accessibilityType {
|
||||||
|
return SSKeychainAccessibilityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (void)setAccessibilityType:(CFTypeRef)accessibilityType {
|
||||||
|
CFRetain(accessibilityType);
|
||||||
|
if (SSKeychainAccessibilityType) {
|
||||||
|
CFRelease(SSKeychainAccessibilityType);
|
||||||
|
}
|
||||||
|
SSKeychainAccessibilityType = accessibilityType;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
|
+ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account {
|
||||||
|
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3];
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
|
||||||
|
#else
|
||||||
|
[dictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (service) {
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[dictionary setObject:service forKey:(__bridge id)kSecAttrService];
|
||||||
|
#else
|
||||||
|
[dictionary setObject:service forKey:(id)kSecAttrService];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account) {
|
||||||
|
#if __has_feature(objc_arc)
|
||||||
|
[dictionary setObject:account forKey:(__bridge id)kSecAttrAccount];
|
||||||
|
#else
|
||||||
|
[dictionary setObject:account forKey:(id)kSecAttrAccount];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
109
xplan-ios/Base/Tool/Reachability/YYReachability.h
Normal file
@@ -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 <Foundation/Foundation.h>
|
||||||
|
#import <SystemConfiguration/SystemConfiguration.h>
|
||||||
|
|
||||||
|
#import <sys/socket.h>
|
||||||
|
#import <netinet/in.h>
|
||||||
|
#import <netinet6/in6.h>
|
||||||
|
#import <arpa/inet.h>
|
||||||
|
#import <ifaddrs.h>
|
||||||
|
#import <netdb.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
527
xplan-ios/Base/Tool/Reachability/YYReachability.m
Normal file
@@ -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 <netinet/in.h> 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
|
21
xplan-ios/Base/Tool/YYUtility/CarrierIdentifier.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// CarrierIdentifier.h
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14-5-30.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
// 运营商类型
|
||||||
|
typedef NS_ENUM(NSUInteger, CarrierIdentifier)
|
||||||
|
{
|
||||||
|
CarrierIdentifier_Unknown = 0, // 未知, 网络不可用(未插SIM卡/无信号/飞行模式)
|
||||||
|
|
||||||
|
CarrierIdentifier_ChinaMobile = 1, // 中国移动
|
||||||
|
CarrierIdentifier_ChinaUnicom = 2, // 中国联通
|
||||||
|
CarrierIdentifier_ChinaTelecom = 3, // 中国电信
|
||||||
|
|
||||||
|
CarrierIdentifier_Otherwise = 0x0000FFFF, // 其他运营商
|
||||||
|
};
|
141
xplan-ios/Base/Tool/YYUtility/YYUtility+App.m
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
//
|
||||||
|
// YYUtility+App.m
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14-5-30.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "YYUtility.h"
|
||||||
|
|
||||||
|
@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"];
|
||||||
|
}
|
||||||
|
return appVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)appName {
|
||||||
|
if (isEnterprise) {
|
||||||
|
return @"yinyouEnterprise"; // 企业包名字 区分一键登录使用
|
||||||
|
}else {
|
||||||
|
return @"yinyou";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (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
|
||||||
|
return @"DEBUG";
|
||||||
|
#else
|
||||||
|
return @"RELEASE";
|
||||||
|
#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{
|
||||||
|
if (_from == nil) {
|
||||||
|
NSString *path = [[NSBundle mainBundle] pathForResource:@"sourceid.dat" ofType:nil];
|
||||||
|
|
||||||
|
NSError *error;
|
||||||
|
NSString *from = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
|
||||||
|
|
||||||
|
// 去除换行及空格
|
||||||
|
if (from) {
|
||||||
|
from = [self removeSpaceAndNewline:from];
|
||||||
|
}
|
||||||
|
// 如果读到有值且不为0
|
||||||
|
if (!error
|
||||||
|
&& ![from isEqualToString:@"0"]
|
||||||
|
&& ![from isEqualToString:@""]) {
|
||||||
|
_from = from;
|
||||||
|
} else {
|
||||||
|
if (isEnterprise) {
|
||||||
|
_from = @"yinyou_Enterprise"; // 企业包
|
||||||
|
}else {
|
||||||
|
_from = @"yinyou_appstore"; // App Store包
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _from;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isFromAppStore{
|
||||||
|
if([[[YYUtility getAppSource] lowercaseString] isEqualToString:@"appstore"]){
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSString *)removeSpaceAndNewline:(NSString *)str{
|
||||||
|
NSString *temp = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||||
|
temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""];
|
||||||
|
temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
88
xplan-ios/Base/Tool/YYUtility/YYUtility+Carrier.m
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// YYUtility+Carrier.m
|
||||||
|
// YYFoundation
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14-5-30.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "YYUtility.h"
|
||||||
|
#import <CoreTelephony/CTCarrier.h>
|
||||||
|
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||||
|
#import "CarrierIdentifier.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; // 电信
|
||||||
|
|
||||||
|
@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]; // 中国电信
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)carrierName
|
||||||
|
{
|
||||||
|
return [self carrier].carrierName;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSInteger)carrierIdentifier
|
||||||
|
{
|
||||||
|
return [self identifierOfCarrier:[self carrier]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CTCarrier *)carrier
|
||||||
|
{
|
||||||
|
return [[CTTelephonyNetworkInfo alloc] init].subscriberCellularProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSInteger)identifierOfCarrier:(CTCarrier *)carrier
|
||||||
|
{
|
||||||
|
CarrierIdentifier identifier = CarrierIdentifier_Unknown;
|
||||||
|
do {
|
||||||
|
if (carrier.mobileCountryCode == nil || carrier.mobileNetworkCode == nil)
|
||||||
|
{
|
||||||
|
identifier = CarrierIdentifier_Unknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
identifier = CarrierIdentifier_Otherwise;
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
538
xplan-ios/Base/Tool/YYUtility/YYUtility+Device.m
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
//
|
||||||
|
// YYUtility+Device.m
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14-5-30.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
#import <AssetsLibrary/AssetsLibrary.h>
|
||||||
|
|
||||||
|
#import "YYUtility.h"
|
||||||
|
#import <sys/utsname.h>
|
||||||
|
#import <arpa/inet.h>
|
||||||
|
#import <net/if.h>
|
||||||
|
#import <ifaddrs.h>
|
||||||
|
#import "YYReachability.h"
|
||||||
|
#import <AdSupport/ASIdentifierManager.h>
|
||||||
|
|
||||||
|
#import <ifaddrs.h>
|
||||||
|
#import <net/if_dl.h>
|
||||||
|
#import <sys/socket.h>
|
||||||
|
#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;;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_systemVersion) {
|
||||||
|
return _systemVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [UIDevice currentDevice].systemVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)identifierForVendor
|
||||||
|
{
|
||||||
|
static NSString *idfv = nil;
|
||||||
|
if (!idfv) {
|
||||||
|
idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
|
||||||
|
}
|
||||||
|
return idfv;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)deviceID
|
||||||
|
{
|
||||||
|
NSString *deviceID = @"";
|
||||||
|
if (!deviceID || deviceID.length == 0) {
|
||||||
|
deviceID = [YYUtility identifierForVendor];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deviceID) {
|
||||||
|
deviceID = @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
return deviceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSInteger)networkStatus
|
||||||
|
{
|
||||||
|
return (self.reachability.currentReachabilityStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (YYReachability *)reachability
|
||||||
|
{
|
||||||
|
static YYReachability *reachability = nil;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
reachability = [YYReachability reachabilityForInternetConnection];
|
||||||
|
});
|
||||||
|
return reachability;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (void)checkCameraAvailable:(void (^)(void))available denied:(void(^)(void))denied restriction:(void(^)(void))restriction
|
||||||
|
{
|
||||||
|
available = available ? : ^{};
|
||||||
|
denied = denied ? : ^{};
|
||||||
|
restriction = restriction ? : ^{};
|
||||||
|
|
||||||
|
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
|
||||||
|
{
|
||||||
|
// iOS7下,需要检查iPhone的隐私和访问限制项
|
||||||
|
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||||
|
switch (authStatus) {
|
||||||
|
case AVAuthorizationStatusAuthorized:
|
||||||
|
{
|
||||||
|
available();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AVAuthorizationStatusDenied:
|
||||||
|
{
|
||||||
|
// [设置->隐私->相机]中禁止了YY访问相机
|
||||||
|
denied();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AVAuthorizationStatusRestricted:
|
||||||
|
{
|
||||||
|
// NOTE: 这个跟[设置-通用-访问限制]似乎没有关系
|
||||||
|
restriction();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AVAuthorizationStatusNotDetermined:
|
||||||
|
{
|
||||||
|
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
|
||||||
|
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
if (granted)
|
||||||
|
{
|
||||||
|
available();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
denied();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
restriction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)checkAssetsLibrayAvailable:(void (^)(void))available denied:(void(^)(void))denied restriction:(void(^)(void))restriction
|
||||||
|
{
|
||||||
|
available = available ? : ^{};
|
||||||
|
denied = denied ? : ^{};
|
||||||
|
restriction = restriction ? : ^{};
|
||||||
|
|
||||||
|
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary] ||
|
||||||
|
[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
|
||||||
|
ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];
|
||||||
|
if (author == ALAuthorizationStatusNotDetermined) {
|
||||||
|
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
|
||||||
|
[assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
|
||||||
|
if (*stop) {
|
||||||
|
available();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*stop = TRUE;
|
||||||
|
} failureBlock:^(NSError *error) {
|
||||||
|
denied();
|
||||||
|
}];
|
||||||
|
}else if (author == ALAuthorizationStatusDenied) {
|
||||||
|
denied();
|
||||||
|
}else if(author == ALAuthorizationStatusRestricted) {
|
||||||
|
restriction();
|
||||||
|
}else if(author == ALAuthorizationStatusAuthorized) {
|
||||||
|
available();
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
restriction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)checkMicPrivacy:(void(^)(BOOL succeed))resultBlock
|
||||||
|
{
|
||||||
|
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
|
||||||
|
if (resultBlock) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
resultBlock(granted);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (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;
|
||||||
|
|
||||||
|
uname(&systemInfo);
|
||||||
|
|
||||||
|
NSString*platform = [NSString stringWithCString: systemInfo.machine encoding:NSASCIIStringEncoding];
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone1,1"])return@"iPhone 2G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone1,2"])return@"iPhone 3G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone2,1"])return@"iPhone 3GS";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone3,1"])return@"iPhone 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone3,2"])return@"iPhone 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone3,3"])return@"iPhone 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone4,1"])return@"iPhone 4S";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone5,1"])return@"iPhone 5";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone5,2"])return@"iPhone 5";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone5,3"])return@"iPhone 5c";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone5,4"])return@"iPhone 5c";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone6,1"])return@"iPhone 5s";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone6,2"])return@"iPhone 5s";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone7,1"])return@"iPhone 6 Plus";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone7,2"])return@"iPhone 6";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone8,1"])return@"iPhone 6s";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone8,2"])return@"iPhone 6s Plus";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone8,4"])return@"iPhone SE";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone9,1"])return@"iPhone 7";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone9,2"])return@"iPhone 7 Plus";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone10,1"])return@"iPhone 8";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone10,4"])return@"iPhone 8";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone10,2"])return@"iPhone 8 Plus";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone10,5"])return@"iPhone 8 Plus";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone10,3"])return@"iPhone X";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPhone10,6"])return@"iPhone X";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPod1,1"])return@"iPod Touch 1G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPod2,1"])return@"iPod Touch 2G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPod3,1"])return@"iPod Touch 3G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPod4,1"])return@"iPod Touch 4G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPod5,1"])return@"iPod Touch 5G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad1,1"])return@"iPad 1G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,1"])return@"iPad 2";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,2"])return@"iPad 2";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,3"])return@"iPad 2";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,4"])return@"iPad 2";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,5"])return@"iPad Mini 1G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,6"])return@"iPad Mini 1G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad2,7"])return@"iPad Mini 1G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad3,1"])return@"iPad 3";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad3,2"])return@"iPad 3";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad3,3"])return@"iPad 3";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad3,4"])return@"iPad 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad3,5"])return@"iPad 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad3,6"])return@"iPad 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,1"])return@"iPad Air";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,2"])return@"iPad Air";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,3"])return@"iPad Air";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,4"])return@"iPad Mini 2G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,5"])return@"iPad Mini 2G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,6"])return@"iPad Mini 2G";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,7"])return@"iPad Mini 3";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,8"])return@"iPad Mini 3";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad4,9"])return@"iPad Mini 3";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad5,1"])return@"iPad Mini 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad5,2"])return@"iPad Mini 4";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad5,3"])return@"iPad Air 2";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad5,4"])return@"iPad Air 2";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad6,3"])return@"iPad Pro 9.7";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad6,4"])return@"iPad Pro 9.7";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad6,7"])return@"iPad Pro 12.9";
|
||||||
|
|
||||||
|
if([platform isEqualToString:@"iPad6,8"])return@"iPad Pro 12.9";
|
||||||
|
|
||||||
|
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
|
225
xplan-ios/Base/Tool/YYUtility/YYUtility.h
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
//
|
||||||
|
// YYUtility.h
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14/6/11.
|
||||||
|
// Copyright (c) 2014年 YY.inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取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;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/*==============================*/
|
||||||
|
/* Carrier Utilities */
|
||||||
|
/*==============================*/
|
||||||
|
@interface YYUtility (Carrier)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
获取设备唯一标识
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
检查麦克风权限
|
||||||
|
|
||||||
|
@param resultBlock 结果处理block
|
||||||
|
*/
|
||||||
|
+ (void)checkMicPrivacy:(void(^)(BOOL succeed))resultBlock;
|
||||||
|
|
||||||
|
+ (NSString *)macAddresss;
|
||||||
|
+ (NSString *)idfa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化信令sdk,imsdk所用到的appName
|
||||||
|
*
|
||||||
|
* @return app name
|
||||||
|
*/
|
||||||
|
+ (NSString *)appName;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
当前设备是否低于, 等于 iPhone6
|
||||||
|
|
||||||
|
@return 当前设备是否低于, 等于 iPhone6
|
||||||
|
*/
|
||||||
|
+ (BOOL)isIphone6AndLow;
|
||||||
|
|
||||||
|
@end
|
13
xplan-ios/Base/Tool/YYUtility/YYUtility.m
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// YYUtility.m
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14-5-30.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "YYUtility.h"
|
||||||
|
|
||||||
|
@implementation YYUtility
|
||||||
|
|
||||||
|
@end
|
38
xplan-ios/Base/UI/BaseViewController.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// BaseViewController.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface BaseViewController : UIViewController
|
||||||
|
|
||||||
|
/**
|
||||||
|
显示/隐藏导航
|
||||||
|
*/
|
||||||
|
- (void)hideNavigationBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
隐藏导航栏
|
||||||
|
*/
|
||||||
|
- (void)showNavigationBar;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
显示/隐藏状态栏
|
||||||
|
*/
|
||||||
|
- (void)showStatusBar;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
隐藏状态栏
|
||||||
|
*/
|
||||||
|
- (void)hideStatusBar;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
70
xplan-ios/Base/UI/BaseViewController.m
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// BaseViewController.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "BaseViewController.h"
|
||||||
|
|
||||||
|
@interface BaseViewController ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation BaseViewController
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
[self themeConfig];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)themeConfig {
|
||||||
|
self.view.backgroundColor = ThemeBackgroundColor;
|
||||||
|
|
||||||
|
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
|
||||||
|
self.navigationController.navigationBar.shadowImage = [[UIImage alloc] init];
|
||||||
|
self.navigationController.navigationBar.barTintColor = ThemeBackgroundColor;
|
||||||
|
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
|
||||||
|
self.navigationController.navigationBar.translucent = NO;
|
||||||
|
|
||||||
|
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
|
||||||
|
self.navigationItem.backBarButtonItem = item;
|
||||||
|
|
||||||
|
[self.navigationController.navigationBar setTitleTextAttributes:@{
|
||||||
|
NSFontAttributeName:[UIFont systemFontOfSize:18],
|
||||||
|
NSForegroundColorAttributeName:UIColor.whiteColor
|
||||||
|
}];
|
||||||
|
self.navigationItem.title = @"音游";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
隐藏导航条
|
||||||
|
*/
|
||||||
|
- (void)hideNavigationBar {
|
||||||
|
[self.navigationController setNavigationBarHidden:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
显示导航条
|
||||||
|
*/
|
||||||
|
- (void)showNavigationBar {
|
||||||
|
[self.navigationController setNavigationBarHidden:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
显示状态栏
|
||||||
|
*/
|
||||||
|
- (void)showStatusBar {
|
||||||
|
[UIApplication sharedApplication].statusBarHidden = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
隐藏状态栏
|
||||||
|
*/
|
||||||
|
- (void)hideStatusBar {
|
||||||
|
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
43
xplan-ios/Base/UI/UIImage+Utils.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// UIImage+Utils.h
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14/6/20.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
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<UIColor *>*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize;
|
||||||
|
@end
|
301
xplan-ios/Base/UI/UIImage+Utils.m
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
//
|
||||||
|
// UIImage+Utils.m
|
||||||
|
// YYMobileFramework
|
||||||
|
//
|
||||||
|
// Created by wuwei on 14/6/20.
|
||||||
|
// Copyright (c) 2014年 YY Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "UIImage+Utils.h"
|
||||||
|
#import <ImageIO/ImageIO.h>
|
||||||
|
|
||||||
|
@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,
|
||||||
|
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
|
||||||
|
CGColorSpaceRelease(colorSpace);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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<UIColor *> *)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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
134
xplan-ios/Base/UI/XCHUDTool.h
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// XCHUDTool.h
|
||||||
|
// TTPlay
|
||||||
|
//
|
||||||
|
// Created by Macx on 2019/5/15.
|
||||||
|
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
showGIFLoading使用注意:
|
||||||
|
1.谁负责showLoading, 谁负责hideHUD
|
||||||
|
2.showLoading是指定了加载在那个View, hideHUD时请指定hide那个view的hud
|
||||||
|
*/
|
||||||
|
|
||||||
|
@interface XCHUDTool : NSObject
|
||||||
|
/**
|
||||||
|
隐藏HUD
|
||||||
|
*/
|
||||||
|
+ (void)hideHUD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
隐藏HUD, 如果view为nil, 则默认隐藏主窗口的HUD
|
||||||
|
|
||||||
|
@param view view
|
||||||
|
*/
|
||||||
|
+ (void)hideHUDInView:(nullable 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)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;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
284
xplan-ios/Base/UI/XCHUDTool.m
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
//
|
||||||
|
// XCHUDTool.m
|
||||||
|
// TTPlay
|
||||||
|
//
|
||||||
|
// Created by Macx on 2019/5/15.
|
||||||
|
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "XCHUDTool.h"
|
||||||
|
#import "GCDHelper.h"
|
||||||
|
#import <MBProgressHUD/MBProgressHUD.h>
|
||||||
|
|
||||||
|
#define kDelayTime 2.5
|
||||||
|
|
||||||
|
@implementation XCHUDTool
|
||||||
|
/**
|
||||||
|
隐藏HUD, 如果view为nil, 则默认隐藏主窗口的HUD
|
||||||
|
|
||||||
|
@param view view
|
||||||
|
*/
|
||||||
|
+ (void)hideHUDInView:(nullable UIView *)view {
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
if (view) {
|
||||||
|
[MBProgressHUD hideHUDForView:view animated:NO];
|
||||||
|
[MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:NO];
|
||||||
|
} else {
|
||||||
|
[MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:NO];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
隐藏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 showLoadingInView:[UIApplication sharedApplication].keyWindow];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在view上显示菊花
|
||||||
|
*/
|
||||||
|
+ (void)showLoadingInView:(nullable UIView *)view {
|
||||||
|
[self showLoadingInView:view enabled:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在view上显示菊花
|
||||||
|
*/
|
||||||
|
+ (void)showLoadingInView:(nullable UIView *)view enabled:(BOOL)enabled {
|
||||||
|
[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(168, 133);
|
||||||
|
hud.userInteractionEnabled = enabled;
|
||||||
|
hud.mode = MBProgressHUDModeCustomView;
|
||||||
|
hud.minSize = CGSizeMake(150, 150);
|
||||||
|
[hud.bezelView addSubview:[self loadingView]];
|
||||||
|
hud.backgroundColor = bgColor;
|
||||||
|
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 *loadingBGView = [[UIView alloc] init];
|
||||||
|
loadingBGView.layer.cornerRadius = 20;
|
||||||
|
loadingBGView.backgroundColor = [UIColor whiteColor];
|
||||||
|
UIImageView *loadingImageView = [[UIImageView alloc] init];
|
||||||
|
|
||||||
|
UILabel *loadingTitleLabel = [[UILabel alloc] init];
|
||||||
|
loadingTitleLabel = [[UILabel alloc] init];
|
||||||
|
loadingTitleLabel.textColor = [UIColor colorWithRed:(153.0)/255.0f green:(153.0)/255.0f blue:(153.0)/255.0f alpha:1];
|
||||||
|
loadingTitleLabel.font = [UIFont systemFontOfSize:14];
|
||||||
|
loadingTitleLabel.text = @"加载中…";
|
||||||
|
loadingTitleLabel.textAlignment = NSTextAlignmentCenter;
|
||||||
|
|
||||||
|
[loadingBGView addSubview:loadingImageView];
|
||||||
|
[loadingBGView addSubview:loadingTitleLabel];
|
||||||
|
|
||||||
|
loadingBGView.frame = CGRectMake(0,0,130,130);
|
||||||
|
loadingImageView.frame = CGRectMake((CGRectGetWidth(loadingBGView.frame)-40)/ 2, (CGRectGetHeight(loadingBGView.frame) - 40 -15-15) / 2, 40, 40);
|
||||||
|
loadingTitleLabel.frame = CGRectMake(0, CGRectGetMaxY(loadingImageView.frame) + 15, loadingBGView.frame.size.width, 15);
|
||||||
|
|
||||||
|
loadingImageView.image = [UIImage imageNamed:@"common_loading"];
|
||||||
|
|
||||||
|
CABasicAnimation * animage = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||||
|
animage.fromValue = 0;
|
||||||
|
animage.toValue = @(2 * M_PI);
|
||||||
|
animage.duration = 1;
|
||||||
|
animage.repeatCount = CGFLOAT_MAX;
|
||||||
|
animage.autoreverses = NO;
|
||||||
|
animage.removedOnCompletion = NO;
|
||||||
|
[loadingImageView.layer addAnimation:animage forKey:@"animation"];
|
||||||
|
return loadingBGView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
54
xplan-ios/Info.plist
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>音游</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(MARKETING_VERSION)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSAppTransportSecurity</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>armv7</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
18
xplan-ios/Main/Login/Api/Api+Login.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Api+Login.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
18
xplan-ios/Main/Login/Api/Api+Login.m
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Api+Login.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "Api+Login.h"
|
||||||
|
|
||||||
|
@implementation Api (Login)
|
||||||
|
|
||||||
|
+ (void)phoneQuickLogin:(HttpRequestHelperCompletion)completion accessToken:(NSString *)accessToken token:(NSString *)token {
|
||||||
|
[self makeRequest:@"acc/oneclick/login" method:HttpRequestHelperMethodPOST completion:^(id _Nullable data, NSNumber * _Nonnull code, NSString * _Nullable msg) {
|
||||||
|
completion(data, code, msg);
|
||||||
|
}, __FUNCTION__, accessToken, token, nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
18
xplan-ios/Main/Login/Presenter/LoginPresenter.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// LoginPresenter.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "BaseMvpPresenter.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface LoginPresenter : BaseMvpPresenter
|
||||||
|
|
||||||
|
- (void)phoneQuickLogin:(NSString *)accessToken token:(NSString*) token;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
26
xplan-ios/Main/Login/Presenter/LoginPresenter.m
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// LoginPresenter.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "LoginPresenter.h"
|
||||||
|
#import "LoginProtocol.h"
|
||||||
|
#import "Api+Login.h"
|
||||||
|
|
||||||
|
@implementation LoginPresenter
|
||||||
|
|
||||||
|
- (id<LoginProtocol>)getView {
|
||||||
|
return ((id<LoginProtocol>) [super getView]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)phoneQuickLogin:(NSString *)accessToken token:(NSString *)token {
|
||||||
|
[Api phoneQuickLogin:[self createHttpCompletion:^(id _Nonnull data) {
|
||||||
|
[[self getView] phoneQuickLoginSuccess];
|
||||||
|
} fail:^(NSNumber * _Nonnull code, NSString * _Nullable msg) {
|
||||||
|
// todo fail
|
||||||
|
} showLoading:YES errorToast:YES] accessToken:accessToken token:token];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
18
xplan-ios/Main/Login/Protocol/LoginProtocol.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// LoginProtocol.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol LoginProtocol <NSObject>
|
||||||
|
|
||||||
|
- (void)phoneQuickLoginSuccess;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
16
xplan-ios/Main/Login/View/LoginViewController.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// LoginViewController.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MvpViewController.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface LoginViewController : MvpViewController
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
578
xplan-ios/Main/Login/View/LoginViewController.m
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
//
|
||||||
|
// LoginViewController.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "LoginViewController.h"
|
||||||
|
#import "LoginPresenter.h"
|
||||||
|
#import "LoginProtocol.h"
|
||||||
|
#import "UIImage+Utils.h"
|
||||||
|
#import "GCDHelper.h"
|
||||||
|
#import "XCHUDTool.h"
|
||||||
|
#import <Masonry/Masonry.h>
|
||||||
|
#import <ReactiveObjC.h>
|
||||||
|
#import <YYText.h>
|
||||||
|
#import <NTESQuickPass/NTESQuickPass.h>
|
||||||
|
|
||||||
|
// 易盾 本机一键登录
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSString *businessID = @"09c1214706c34f4798d3f05d86148608";
|
||||||
|
#else
|
||||||
|
NSString *businessID = @"09c1214706c34f4798d3f05d86148608";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, XYLoginType) {
|
||||||
|
XYLoginTypeUnknow = 0, //未知
|
||||||
|
XYLoginTypeTelecom = 1, //电信
|
||||||
|
XYLoginTypeChinaMobile = 2, //移动
|
||||||
|
XYLoginTypeUnicom = 3 //联通
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger,XYThirdLoginType) {
|
||||||
|
XYThirdLoginWechat = 1, // 微信登录
|
||||||
|
XYThirdLoginQQ = 2, // QQ登录
|
||||||
|
XYThirdLoginPhoneNum = 3, // 手机号登录
|
||||||
|
XYThirdLoginApple = 5, // 苹果id登录
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface LLButtonView : UIView
|
||||||
|
|
||||||
|
//icon
|
||||||
|
@property (nonatomic,strong) UIImageView *logoImageView;
|
||||||
|
//title
|
||||||
|
@property (nonatomic,strong) UILabel *titleLabel;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation LLButtonView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame {
|
||||||
|
if (self = [super initWithFrame:frame]) {
|
||||||
|
[self initView];
|
||||||
|
[self initContrations];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)initView {
|
||||||
|
[self addSubview:self.logoImageView];
|
||||||
|
[self addSubview:self.titleLabel];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initContrations {
|
||||||
|
[self.logoImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.size.mas_equalTo(CGSizeMake(36, 36));
|
||||||
|
make.centerX.left.mas_equalTo(self);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.right.mas_equalTo(self);
|
||||||
|
make.top.mas_equalTo(self.logoImageView.mas_bottom).offset(15);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImageView *)logoImageView {
|
||||||
|
if (!_logoImageView) {
|
||||||
|
_logoImageView = [[UIImageView alloc] init];
|
||||||
|
_logoImageView.userInteractionEnabled = YES;
|
||||||
|
}
|
||||||
|
return _logoImageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)titleLabel {
|
||||||
|
if (!_titleLabel) {
|
||||||
|
_titleLabel = [[UILabel alloc] init];
|
||||||
|
_titleLabel.font = [UIFont systemFontOfSize:11];
|
||||||
|
_titleLabel.textColor = ThemeTextColor;
|
||||||
|
_titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||||
|
}
|
||||||
|
return _titleLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface LoginViewController () <LoginProtocol>
|
||||||
|
|
||||||
|
@property (nonatomic, strong) UIImageView *appIcon;
|
||||||
|
/** 标题 */
|
||||||
|
@property (nonatomic, strong) UILabel *titleLabel;
|
||||||
|
/** 副标题 */
|
||||||
|
@property (nonatomic, strong) UILabel *subTitleLabel;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) UIView *contentView;
|
||||||
|
/** 登录按钮*/
|
||||||
|
@property (nonatomic, strong) UIButton *loginButton;
|
||||||
|
|
||||||
|
@property (nonatomic,strong) UIStackView *stackView;
|
||||||
|
///手机
|
||||||
|
@property (nonatomic,strong) LLButtonView *qqButtonView;
|
||||||
|
///wx
|
||||||
|
@property (nonatomic,strong) LLButtonView *wxButtonView;
|
||||||
|
///qq
|
||||||
|
@property (nonatomic,strong) LLButtonView *phoneButtonView;
|
||||||
|
|
||||||
|
/** 同意勾选按钮*/
|
||||||
|
@property (nonatomic, strong) UIButton *agreeButton;
|
||||||
|
/** 同意即可登录 */
|
||||||
|
@property (nonatomic, strong) YYLabel *agreeLabel;
|
||||||
|
/** 勾选隐私政策提示泡泡 */
|
||||||
|
@property (nonatomic, strong) UIImageView *authBubbleView;
|
||||||
|
/** 泡泡提示内容 */
|
||||||
|
@property (nonatomic, strong) UILabel *authBubbleLabel;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation LoginViewController
|
||||||
|
|
||||||
|
- (LoginPresenter *)createPresenter {
|
||||||
|
return [[LoginPresenter alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)phoneQuickLoginSuccess {
|
||||||
|
[XCHUDTool showSuccessWithMessage:@"一键登录成功。"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
[self initView];
|
||||||
|
[self setUpConstraints];
|
||||||
|
[self setEvents];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
[super viewWillAppear:animated];
|
||||||
|
[self hideNavigationBar];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
[self showNavigationBar];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initView {
|
||||||
|
[self.view addSubview:self.appIcon];
|
||||||
|
[self.view addSubview:self.titleLabel];
|
||||||
|
[self.view addSubview:self.subTitleLabel];
|
||||||
|
|
||||||
|
[self.view addSubview:self.contentView];
|
||||||
|
[self.contentView addSubview:self.loginButton];
|
||||||
|
[self.contentView addSubview:self.stackView];
|
||||||
|
[self.view addSubview:self.agreeButton];
|
||||||
|
[self.view addSubview:self.agreeLabel];
|
||||||
|
[self.view addSubview:self.authBubbleView];
|
||||||
|
[self.authBubbleView addSubview:self.authBubbleLabel];
|
||||||
|
|
||||||
|
[self.stackView addArrangedSubview:self.qqButtonView];
|
||||||
|
[self.stackView addArrangedSubview:self.phoneButtonView];
|
||||||
|
[self.stackView addArrangedSubview:self.wxButtonView];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)setUpConstraints {
|
||||||
|
[self.appIcon mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.mas_equalTo(110 + kSafeAreaTopHeight);
|
||||||
|
make.left.mas_equalTo(52);
|
||||||
|
make.width.mas_equalTo(100);
|
||||||
|
make.height.mas_equalTo(100);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.mas_equalTo(self.appIcon.mas_top).offset(28.5);
|
||||||
|
make.left.mas_equalTo(self.appIcon.mas_right).offset(7.5);
|
||||||
|
make.height.mas_equalTo(20);
|
||||||
|
make.right.mas_equalTo(-20);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.subTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(13);
|
||||||
|
make.left.mas_equalTo(self.titleLabel.mas_left);
|
||||||
|
make.height.mas_equalTo(13);
|
||||||
|
make.right.mas_equalTo(-20);
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.mas_equalTo(self.view).offset(iPhoneXSeries ? 300 : 228);
|
||||||
|
make.left.right.bottom.mas_equalTo(0);
|
||||||
|
}];
|
||||||
|
[self.loginButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.right.mas_equalTo(self.view).inset(52);
|
||||||
|
make.top.mas_equalTo(70);
|
||||||
|
make.height.mas_equalTo(45);
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
[self.stackView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.bottom.mas_equalTo(self.view).offset(-kSafeAreaBottomHeight - 60);
|
||||||
|
make.centerX.mas_equalTo(self.view);
|
||||||
|
make.height.mas_equalTo(65);
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
[self.agreeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.mas_equalTo(self.loginButton.mas_bottom).offset(20);
|
||||||
|
make.height.mas_equalTo(40);
|
||||||
|
make.width.mas_equalTo(270);
|
||||||
|
make.centerX.mas_equalTo(self.view).mas_offset(15 - 6);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.agreeButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.right.mas_equalTo(self.agreeLabel.mas_left).mas_offset(6);
|
||||||
|
make.centerY.mas_equalTo(self.agreeLabel.mas_centerY);
|
||||||
|
make.width.height.mas_equalTo(30);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.authBubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.mas_equalTo(self.agreeButton).mas_offset((-16));
|
||||||
|
make.top.mas_equalTo(self.agreeButton.mas_bottom);
|
||||||
|
make.width.mas_equalTo(235);
|
||||||
|
make.height.mas_equalTo(29);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.authBubbleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.mas_equalTo(8);
|
||||||
|
make.bottom.mas_equalTo(self.authBubbleView).mas_offset(-6);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setEvents {
|
||||||
|
// 手机登陆按钮点击
|
||||||
|
@weakify(self)
|
||||||
|
UITapGestureRecognizer *phoneTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didClickRecognizer:)];
|
||||||
|
[self.phoneButtonView addGestureRecognizer:phoneTap];
|
||||||
|
UITapGestureRecognizer * qqTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didClickRecognizer:)];
|
||||||
|
[self.qqButtonView addGestureRecognizer:qqTap];
|
||||||
|
UITapGestureRecognizer * wxTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didClickRecognizer:)];
|
||||||
|
[self.wxButtonView addGestureRecognizer:wxTap];
|
||||||
|
|
||||||
|
[[self.agreeButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
|
||||||
|
self.agreeButton.selected = !self.agreeButton.selected;
|
||||||
|
if (self.agreeButton.isSelected) {
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
[defaults setObject:@"hadAgree" forKey:@"kHadAgreePrivacy"];
|
||||||
|
[defaults synchronize];
|
||||||
|
[UIView animateWithDuration:0.5 animations:^{
|
||||||
|
self.authBubbleView.alpha = 0.0;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 一键登录
|
||||||
|
[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
|
||||||
|
@strongify(self)
|
||||||
|
if (self.agreeButton.isSelected) {
|
||||||
|
[self phoneQuickLogin];
|
||||||
|
} else {
|
||||||
|
[UIView animateWithDuration:0.5 animations:^{
|
||||||
|
self.authBubbleView.alpha = 1.0;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)didClickRecognizer:(UITapGestureRecognizer *)tap {
|
||||||
|
UIView * view = tap.view;
|
||||||
|
if (self.agreeButton.isSelected) {
|
||||||
|
if ([view isEqual:self.phoneButtonView]) {
|
||||||
|
// InputPhoneLoginViewController *inputPhoneVC = [[InputPhoneLoginViewController alloc] init];
|
||||||
|
// [self.navigationController pushViewController:inputPhoneVC animated:YES];
|
||||||
|
} else if([view isEqual:self.qqButtonView]) {
|
||||||
|
[XCHUDTool showLoading];
|
||||||
|
// [GetCore(AuthCore) thirdLoginPlatform:SSDKPlatformTypeQQ];
|
||||||
|
} else if([view isEqual:self.wxButtonView]) {
|
||||||
|
[XCHUDTool showLoading];
|
||||||
|
// [GetCore(AuthCore) thirdLoginPlatform:SSDKPlatformTypeWechat];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[UIView animateWithDuration:0.5 animations:^{
|
||||||
|
self.authBubbleView.alpha = 1.0;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)phoneQuickLogin {
|
||||||
|
[XCHUDTool showLoading];
|
||||||
|
// 在使用一键登录之前,请先调用shouldQuickLogin方法,判断当前上网卡的网络环境和运营商是否可以一键登录
|
||||||
|
@weakify(self)
|
||||||
|
NTESQuickLoginManager *qlManager = [NTESQuickLoginManager sharedInstance];
|
||||||
|
BOOL shouldQL = [qlManager shouldQuickLogin];
|
||||||
|
if (!shouldQL) {
|
||||||
|
[self phoneQuickLoginFail];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[qlManager registerWithBusinessID:businessID timeout:3*1000 configURL:nil extData:nil completion:^(NSDictionary * _Nullable params, BOOL regSuccess) {
|
||||||
|
@strongify(self)
|
||||||
|
if (!regSuccess) {
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
[self phoneQuickLoginFail];
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *token = [params objectForKey:@"token"];
|
||||||
|
[qlManager getPhoneNumberCompletion:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
@strongify(self)
|
||||||
|
NSNumber *boolNum = [resultDic objectForKey:@"success"];
|
||||||
|
BOOL getPhoneNumberSuccess = [boolNum boolValue];
|
||||||
|
if (!getPhoneNumberSuccess) {
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
[self phoneQuickLoginFail];
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self configQuickLogin];
|
||||||
|
[qlManager CUCMCTAuthorizeLoginCompletion:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
@strongify(self)
|
||||||
|
NSNumber *boolNum = [resultDic objectForKey:@"success"];
|
||||||
|
BOOL authSuccess = [boolNum boolValue];
|
||||||
|
if (!authSuccess) {
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
NSString *resultCode = [resultDic objectForKey:@"resultCode"];
|
||||||
|
//取消一键登录
|
||||||
|
if ([resultCode isEqualToString:@"200020"] ||
|
||||||
|
[resultCode isEqualToString:@"10104"]) {
|
||||||
|
[XCHUDTool hideHUD];
|
||||||
|
} else {
|
||||||
|
[self phoneQuickLoginFail];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
@strongify(self)
|
||||||
|
// [TTStatisticsService trackEvent:@"one_click_login_succeed" eventDescribe:@"一键登录成功"];
|
||||||
|
// // 取号成功,获取acessToken
|
||||||
|
[XCHUDTool hideHUD];
|
||||||
|
[self dismissViewControllerAnimated:YES completion:nil];
|
||||||
|
[self.presenter phoneQuickLogin:resultDic[@"accessToken"] token:token];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)phoneQuickLoginFail {
|
||||||
|
[XCHUDTool showErrorWithMessage:@"一键登录失败,请检查手机网络状态。"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configQuickLogin {
|
||||||
|
// 获取当前上网卡的运营商,0:未知 1:电信 2.移动 3.联通
|
||||||
|
NSInteger currentCarrier = [[NTESQuickLoginManager sharedInstance] getCarrier];
|
||||||
|
NTESQuickLoginModel *CMModel = [[NTESQuickLoginModel alloc] init];
|
||||||
|
CMModel.currentVC = self;
|
||||||
|
CMModel.presentDirectionType = NTESPresentDirectionPresent;
|
||||||
|
if (currentCarrier == XYLoginTypeUnicom) { // 联通
|
||||||
|
CMModel.logoImg = [UIImage imageNamed:@"login_unicom_mobile"];
|
||||||
|
}else if (currentCarrier == XYLoginTypeChinaMobile) { //移动
|
||||||
|
CMModel.logoImg = [UIImage imageNamed:@"login_china_mobile"];
|
||||||
|
}else { //电信
|
||||||
|
CMModel.logoImg = [UIImage imageNamed:@"login_ct_mobile"];
|
||||||
|
}
|
||||||
|
CMModel.backgroundColor = ThemeBackgroundColor;
|
||||||
|
|
||||||
|
CMModel.logoWidth = 95;
|
||||||
|
CMModel.logoHeight = 95;
|
||||||
|
CMModel.logoOffsetTopY = 30;
|
||||||
|
CMModel.navText = @"一键登录";
|
||||||
|
CMModel.navTextColor = UIColor.whiteColor;
|
||||||
|
CMModel.navTextFont = [UIFont boldSystemFontOfSize:18];
|
||||||
|
|
||||||
|
CMModel.navReturnImg = [UIImage imageNamed:@"common_nav_back"];
|
||||||
|
CMModel.navBgColor = ThemeBackgroundColor;
|
||||||
|
|
||||||
|
CMModel.logBtnHeight = 45;
|
||||||
|
CMModel.logBtnRadius = 45.f / 2;
|
||||||
|
CMModel.logBtnOffsetTopY= 260;
|
||||||
|
CMModel.logBtnOriginLeft = 52;
|
||||||
|
CMModel.logBtnOriginRight = 52;
|
||||||
|
CMModel.logBtnUsableBGColor = ThemeDefaultColor;
|
||||||
|
CMModel.logBtnText = @"本机号码一键登录";
|
||||||
|
CMModel.logBtnTextColor = UIColor.whiteColor;
|
||||||
|
CMModel.logBtnTextFont = [UIFont systemFontOfSize:18 weight:UIFontWeightMedium];
|
||||||
|
|
||||||
|
CMModel.numberOffsetTopY = 170;
|
||||||
|
CMModel.numberColor = UIColor.whiteColor;
|
||||||
|
CMModel.numberFont = [UIFont boldSystemFontOfSize:20];
|
||||||
|
CMModel.brandColor = UIColor.whiteColor;
|
||||||
|
|
||||||
|
CMModel.uncheckedImg = [UIImage imageNamed:@"common_checkbox_uncheck"];
|
||||||
|
CMModel.checkedImg = [UIImage imageNamed:@"common_checkbox_checked"];
|
||||||
|
CMModel.checkboxWH = 20;
|
||||||
|
|
||||||
|
CMModel.privacyColor = ThemeTextColor;
|
||||||
|
CMModel.appPrivacyText = @"登录即代表同意《默认》,并授权音游获取本机号码。";
|
||||||
|
CMModel.privacyState = YES;
|
||||||
|
CMModel.privacyFont = [UIFont systemFontOfSize:12];
|
||||||
|
CMModel.protocolColor = ThemeDefaultColor;
|
||||||
|
|
||||||
|
CMModel.backActionBlock = ^{ //点击了返回按钮
|
||||||
|
[XCHUDTool hideHUD];
|
||||||
|
};
|
||||||
|
dispatch_main_sync_safe(^{
|
||||||
|
[[NTESQuickLoginManager sharedInstance] setupModel:CMModel];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImageView *)appIcon {
|
||||||
|
if (!_appIcon) {
|
||||||
|
_appIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_appIcon"]];
|
||||||
|
}
|
||||||
|
return _appIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)titleLabel{
|
||||||
|
if (!_titleLabel) {
|
||||||
|
_titleLabel = [[UILabel alloc] init];
|
||||||
|
_titleLabel.font = [UIFont fontWithName:@"PingFang-SC-Medium" size:18];
|
||||||
|
_titleLabel.text = AppName;
|
||||||
|
_titleLabel.textColor = ThemeTextColor;
|
||||||
|
}
|
||||||
|
return _titleLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)subTitleLabel {
|
||||||
|
if (!_subTitleLabel) {
|
||||||
|
_subTitleLabel = [[UILabel alloc] init];
|
||||||
|
_subTitleLabel.font = [UIFont systemFontOfSize:13];
|
||||||
|
_subTitleLabel.text = @"来音游打游戏,争夺更多赏金!";
|
||||||
|
_subTitleLabel.textColor = ThemeTextColor;
|
||||||
|
_subTitleLabel.textAlignment = NSTextAlignmentLeft;
|
||||||
|
}
|
||||||
|
return _subTitleLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIButton *)loginButton{
|
||||||
|
if (!_loginButton) {
|
||||||
|
_loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
_loginButton.layer.masksToBounds = YES;
|
||||||
|
_loginButton.layer.cornerRadius = 45/2.f;
|
||||||
|
[_loginButton setTitle:@"本机号码一键登录" forState:UIControlStateNormal];
|
||||||
|
[_loginButton setTitle:@"本机号码一键登录" forState:UIControlStateSelected];
|
||||||
|
_loginButton.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightMedium];
|
||||||
|
[_loginButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
|
||||||
|
UIImage *image = [UIImage gradientColorImageFromColors:@[ThemeButtonGradientStartColor,ThemeButtonGradientEndColor] gradientType:GradientTypeLeftToRight imgSize:CGSizeMake(KScreenWidth - 52 * 2, 45)];
|
||||||
|
[_loginButton setBackgroundImage:image forState:UIControlStateNormal];
|
||||||
|
}
|
||||||
|
return _loginButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIButton *)agreeButton {
|
||||||
|
if (!_agreeButton) {
|
||||||
|
_agreeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
[_agreeButton setImage:[UIImage imageNamed:@"common_checkbox_uncheck"] forState:UIControlStateNormal];
|
||||||
|
[_agreeButton setImage:[UIImage imageNamed:@"common_checkbox_checked"] forState:UIControlStateSelected];
|
||||||
|
}
|
||||||
|
return _agreeButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (YYLabel *)agreeLabel {
|
||||||
|
if (!_agreeLabel) {
|
||||||
|
_agreeLabel = [[YYLabel alloc] init];
|
||||||
|
_agreeLabel.font = [UIFont systemFontOfSize:12];
|
||||||
|
_agreeLabel.numberOfLines = 0;
|
||||||
|
_agreeLabel.attributedText = [self privacyAttributedStr];
|
||||||
|
_agreeLabel.textAlignment = NSTextAlignmentCenter;
|
||||||
|
[_agreeLabel sizeToFit];
|
||||||
|
}
|
||||||
|
return _agreeLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableAttributedString *)privacyAttributedStr{
|
||||||
|
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"登录即代表同意"];
|
||||||
|
attString.yy_color = ThemeTextColor;
|
||||||
|
NSString *userString = @"《用户服务协议》";
|
||||||
|
NSMutableAttributedString *userAttString = [[NSMutableAttributedString alloc] initWithString:userString attributes:@{NSForegroundColorAttributeName:ThemeDefaultColor}];
|
||||||
|
@weakify(self)
|
||||||
|
[userAttString yy_setTextHighlightRange:NSMakeRange(0, userAttString.length) color:nil backgroundColor:nil userInfo:nil tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
|
||||||
|
@strongify(self);
|
||||||
|
// 跳转用户协议
|
||||||
|
// [self goToWebview:HtmlUrlKey(kUserProtocalURL)];
|
||||||
|
} longPressAction:nil];
|
||||||
|
|
||||||
|
NSMutableAttributedString *andString = [[NSMutableAttributedString alloc] initWithString:@"和"];
|
||||||
|
andString.yy_color = ThemeTextColor;
|
||||||
|
NSString *protocolString = @"《隐私政策》";
|
||||||
|
NSMutableAttributedString *privateString = [[NSMutableAttributedString alloc] initWithString:protocolString attributes:@{NSForegroundColorAttributeName:ThemeDefaultColor}];
|
||||||
|
[privateString yy_setTextHighlightRange:NSMakeRange(0, privateString.length) color:nil backgroundColor:nil userInfo:nil tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
|
||||||
|
@strongify(self);
|
||||||
|
// 跳转隐私政策
|
||||||
|
// [self goToWebview:HtmlUrlKey(kPrivacyURL)];
|
||||||
|
} longPressAction:nil];
|
||||||
|
[attString appendAttributedString:userAttString];
|
||||||
|
[attString appendAttributedString:andString];
|
||||||
|
[attString appendAttributedString:privateString];
|
||||||
|
return attString;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImageView *)authBubbleView {
|
||||||
|
if (!_authBubbleView) {
|
||||||
|
_authBubbleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_auth_bubble"]];
|
||||||
|
_authBubbleView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
_authBubbleView.alpha = 0;
|
||||||
|
}
|
||||||
|
return _authBubbleView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)authBubbleLabel {
|
||||||
|
if (!_authBubbleLabel) {
|
||||||
|
_authBubbleLabel = [[UILabel alloc] init];
|
||||||
|
_authBubbleLabel.text = @"同意隐私政策和用户协议后,才可以注册登录哦~";
|
||||||
|
_authBubbleLabel.font = [UIFont systemFontOfSize:10];
|
||||||
|
_authBubbleLabel.textColor = UIColor.whiteColor;
|
||||||
|
}
|
||||||
|
return _authBubbleLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)contentView {
|
||||||
|
if (!_contentView) {
|
||||||
|
_contentView = [[UIView alloc] init];
|
||||||
|
}
|
||||||
|
return _contentView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIStackView *)stackView {
|
||||||
|
if (!_stackView) {
|
||||||
|
_stackView = [[UIStackView alloc] init];
|
||||||
|
_stackView.distribution = UIStackViewDistributionEqualSpacing;
|
||||||
|
_stackView.spacing = 43;
|
||||||
|
_stackView.axis = UILayoutConstraintAxisHorizontal;
|
||||||
|
_stackView.alignment = UIStackViewAlignmentFill;
|
||||||
|
}
|
||||||
|
return _stackView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (LLButtonView *)phoneButtonView {
|
||||||
|
if (!_phoneButtonView) {
|
||||||
|
_phoneButtonView = [[LLButtonView alloc] init];
|
||||||
|
_phoneButtonView.logoImageView.image = [UIImage imageNamed:@"login_phone"];
|
||||||
|
_phoneButtonView.titleLabel.text = @"手机";
|
||||||
|
}
|
||||||
|
return _phoneButtonView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (LLButtonView *)qqButtonView {
|
||||||
|
if (!_qqButtonView) {
|
||||||
|
_qqButtonView = [[LLButtonView alloc] init];
|
||||||
|
_qqButtonView.logoImageView.image = [UIImage imageNamed:@"login_qq"];
|
||||||
|
_qqButtonView.titleLabel.text = @"QQ";
|
||||||
|
}
|
||||||
|
return _qqButtonView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (LLButtonView *)wxButtonView {
|
||||||
|
if (!_wxButtonView) {
|
||||||
|
_wxButtonView = [[LLButtonView alloc] init];
|
||||||
|
_wxButtonView.logoImageView.image = [UIImage imageNamed:@"login_wechat"];
|
||||||
|
_wxButtonView.titleLabel.text = @"微信";
|
||||||
|
}
|
||||||
|
return _wxButtonView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
25
xplan-ios/Main/MVP/Api/Api.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Api.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#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, ...;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
39
xplan-ios/Main/MVP/Api/Api.m
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// Api.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/9/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "Api.h"
|
||||||
|
|
||||||
|
@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 = fn.length - start - 2;
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
26
xplan-ios/Main/MVP/Presenter/BaseMvpPresenter.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// BaseMvpPresenter.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "BaseMvpProtocol.h"
|
||||||
|
#import "HttpRequestHelper.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef void(^HttpSuccess)(id _Nonnull data);
|
||||||
|
typedef void(^HttpFail)(NSNumber * _Nonnull code, NSString * _Nullable msg);
|
||||||
|
|
||||||
|
@interface BaseMvpPresenter : NSObject
|
||||||
|
|
||||||
|
- (void)attatchView:(id)view;
|
||||||
|
- (id)getView;
|
||||||
|
- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success fail:(HttpFail)fail showLoading:(BOOL)loading errorToast:(BOOL)toast;
|
||||||
|
- (void)detatchView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
60
xplan-ios/Main/MVP/Presenter/BaseMvpPresenter.m
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// BaseMvpPresenter.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "BaseMvpPresenter.h"
|
||||||
|
#import "XCHUDTool.h"
|
||||||
|
|
||||||
|
@interface BaseMvpPresenter()
|
||||||
|
|
||||||
|
@property (nonatomic, weak) id view;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation BaseMvpPresenter
|
||||||
|
|
||||||
|
- (void)attatchView:(id)view {
|
||||||
|
self.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)getView {
|
||||||
|
return self.view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (HttpRequestHelperCompletion)createHttpCompletion:(HttpSuccess)success fail:(HttpFail)fail showLoading:(BOOL)loading errorToast:(BOOL)toast {
|
||||||
|
if (loading) {
|
||||||
|
[XCHUDTool showLoading];
|
||||||
|
}
|
||||||
|
return ^(id _Nullable data, NSNumber * _Nonnull code, NSString * _Nullable msg) {
|
||||||
|
if (data != nil) {
|
||||||
|
NSString *message = [data valueForKey:@"message"];
|
||||||
|
NSNumber *resCode = [data valueForKey:@"code"];
|
||||||
|
switch (resCode.intValue) {
|
||||||
|
case 200:
|
||||||
|
success(data);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (toast) {
|
||||||
|
[XCHUDTool showErrorWithMessage:msg];
|
||||||
|
}
|
||||||
|
fail(resCode, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toast) {
|
||||||
|
[XCHUDTool showErrorWithMessage:msg];
|
||||||
|
}
|
||||||
|
fail(code, msg);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)detatchView {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
19
xplan-ios/Main/MVP/Protocol/BaseMvpProtocol.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// BaseMvpProtocol.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol BaseMvpProtocol <NSObject>
|
||||||
|
|
||||||
|
- (void)tokenInvalid;
|
||||||
|
- (void)completeUserInfo;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
21
xplan-ios/Main/MVP/View/MvpViewController.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// MvpViewController.h
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "BaseViewController.h"
|
||||||
|
#import "BaseMvpPresenter.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface MvpViewController<T> : BaseViewController<BaseMvpProtocol>
|
||||||
|
|
||||||
|
@property (nonatomic,strong) __kindof T presenter;
|
||||||
|
|
||||||
|
- (__kindof T)createPresenter;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
45
xplan-ios/Main/MVP/View/MvpViewController.m
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// MvpViewController.m
|
||||||
|
// xplan-ios
|
||||||
|
//
|
||||||
|
// Created by zu on 2021/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MvpViewController.h"
|
||||||
|
#import "BaseMvpProtocol.h"
|
||||||
|
#import "BaseMvpPresenter.h"
|
||||||
|
#import "LoginViewController.h"
|
||||||
|
|
||||||
|
@interface MvpViewController ()
|
||||||
|
|
||||||
|
@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)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tokenInvalid {
|
||||||
|
LoginViewController *loginVC = [[LoginViewController alloc] init];
|
||||||
|
[self.navigationController pushViewController:loginVC animated:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)completeUserInfo {
|
||||||
|
// TODO:完善用户信息
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|