xplan ios start

This commit is contained in:
zu
2021-09-06 18:47:38 +08:00
commit cbc85a02d2
103 changed files with 5818 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
Flutter filter=lfs diff=lfs merge=lfs -text

68
.gitignore vendored Normal file
View 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
View 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
View 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

View 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 */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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
View 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
View 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

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View 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
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View 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
View 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 */

View 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 */

View 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

View 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

View 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);

View 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);
}
}

View 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

View 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

View 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

View 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

View 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, // 其他运营商
};

View 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

View 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

View 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])
{
// iOS7iPhone访
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

View 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;
/**
* 获取当前设备的 IDFVIDFV 在某些情况下会变,不建议将其作为设备标识
*/
+ (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;
/**
* 初始化信令sdkimsdk所用到的appName
*
* @return app name
*/
+ (NSString *)appName;
/**
当前设备是否低于, 等于 iPhone6
@return 当前设备是否低于, 等于 iPhone6
*/
+ (BOOL)isIphone6AndLow;
@end

View 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

View 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

View 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

View 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

View 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

View 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

View 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, viewnil, 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];
}
/**
viewGIFLoading, 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];
}
/**
viewGIFLoading
@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
View 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>

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

Some files were not shown because too many files have changed in this diff Show More