瀏覽代碼

网络请求封装;
用户信息请求;

iOS-Abel 1 年之前
父節點
當前提交
1d7627830d
共有 71 個文件被更改,包括 32643 次插入27351 次删除
  1. 58 0
      Asteria.xcodeproj/project.pbxproj
  2. 1 1
      Asteria/ASUI/CustomView/ASSignDayView.h
  3. 3 3
      Asteria/ASUI/CustomView/ASSignDayView.m
  4. 2 0
      Asteria/ASUI/CustomView/UserInfoV/ASUserBaseInfoView.h
  5. 9 8
      Asteria/ASUI/CustomView/UserInfoV/ASUserBaseInfoView.m
  6. 4 1
      Asteria/AppDelegate.m
  7. 2 1
      Asteria/Fuction/Home/ASHomeViewController.m
  8. 4 0
      Asteria/Fuction/UserCenter/Target_userCenter.m
  9. 19 0
      Asteria/Fuction/UserCenter/UserCenterHome/ASSginViewModel.h
  10. 32 0
      Asteria/Fuction/UserCenter/UserCenterHome/ASSginViewModel.m
  11. 15 3
      Asteria/Fuction/UserCenter/UserCenterHome/ASUserCenterViewController.m
  12. 2 1
      Asteria/Fuction/UserCenter/UserCenterHome/views/ASSginView.h
  13. 79 29
      Asteria/Fuction/UserCenter/UserCenterHome/views/ASSginView.m
  14. 2 0
      Asteria/Fuction/UserCenter/UserCenterHome/views/ASUserCenterTopView.h
  15. 18 4
      Asteria/Fuction/UserCenter/UserCenterHome/views/ASUserCenterTopView.m
  16. 35 0
      Asteria/Fuction/UserManager/ASUserInfoManager.h
  17. 119 0
      Asteria/Fuction/UserManager/ASUserInfoManager.m
  18. 69 0
      Asteria/Fuction/UserManager/ASUserModel.h
  19. 55 0
      Asteria/Fuction/UserManager/ASUserModel.m
  20. 33 0
      Asteria/Fuction/UserManager/ASVipModel.h
  21. 30 0
      Asteria/Fuction/UserManager/ASVipModel.m
  22. 21 0
      Asteria/Fuction/UserManager/ASVipUrlTempModel.h
  23. 13 0
      Asteria/Fuction/UserManager/ASVipUrlTempModel.m
  24. 37 0
      Asteria/NetTools/ASNetApis.h
  25. 41 0
      Asteria/NetTools/ASNetTools.h
  26. 338 0
      Asteria/NetTools/ASNetTools.m
  27. 14 0
      Asteria/NetTools/ASUserNotifyStatic.h
  28. 5 0
      Asteria/PreFixHeader.h
  29. 2 0
      Asteria/Product/CTMediatoaTargets/CTMediator+UserCenter.h
  30. 4 0
      Asteria/Product/CTMediatoaTargets/CTMediator+UserCenter.m
  31. 6 0
      Asteria/Tabber/AS_TabBarViewController.m
  32. 2 0
      Podfile
  33. 6 1
      Podfile.lock
  34. 42 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSData+Base64.h
  35. 312 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSData+Base64.m
  36. 25 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSDate+RFC1123.h
  37. 79 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSDate+RFC1123.m
  38. 31 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSDictionary+RequestEncoding.h
  39. 79 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSDictionary+RequestEncoding.m
  40. 32 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSString+MKNetworkKitAdditions.h
  41. 81 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/NSString+MKNetworkKitAdditions.m
  42. 31 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/UIAlertView+MKNetworkKitAdditions.h
  43. 41 0
      Pods/MKNetworkKit/MKNetworkKit/Categories/UIAlertView+MKNetworkKitAdditions.m
  44. 324 0
      Pods/MKNetworkKit/MKNetworkKit/MKNetworkEngine.h
  45. 652 0
      Pods/MKNetworkKit/MKNetworkKit/MKNetworkEngine.m
  46. 102 0
      Pods/MKNetworkKit/MKNetworkKit/MKNetworkKit.h
  47. 547 0
      Pods/MKNetworkKit/MKNetworkKit/MKNetworkOperation.h
  48. 1300 0
      Pods/MKNetworkKit/MKNetworkKit/MKNetworkOperation.m
  49. 103 0
      Pods/MKNetworkKit/README.mdown
  50. 6 1
      Pods/Manifest.lock
  51. 27557 27286
      Pods/Pods.xcodeproj/project.pbxproj
  52. 26 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit-Info.plist
  53. 5 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit-dummy.m
  54. 12 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit-prefix.pch
  55. 24 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit-umbrella.h
  56. 16 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit.debug.xcconfig
  57. 6 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit.modulemap
  58. 16 0
      Pods/Target Support Files/MKNetworkKit/MKNetworkKit.release.xcconfig
  59. 21 0
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.markdown
  60. 27 0
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.plist
  61. 3 3
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.debug.xcconfig
  62. 3 3
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.release.xcconfig
  63. 21 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.markdown
  64. 27 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.plist
  65. 1 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-input-files.xcfilelist
  66. 1 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-output-files.xcfilelist
  67. 1 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-input-files.xcfilelist
  68. 1 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-output-files.xcfilelist
  69. 2 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks.sh
  70. 3 3
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria.debug.xcconfig
  71. 3 3
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria.release.xcconfig

+ 58 - 0
Asteria.xcodeproj/project.pbxproj

@@ -10,6 +10,12 @@
 		2B3E96D298A3E04003DA2AD3 /* Pods_Asteria_NotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51AF3B78609F55449DF09609 /* Pods_Asteria_NotificationServiceExtension.framework */; };
 		811F42462A40533C00DA68F1 /* ASPointsHomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 811F42452A40533C00DA68F1 /* ASPointsHomeViewController.m */; };
 		811F42492A40536C00DA68F1 /* ASPointHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 811F42482A40536C00DA68F1 /* ASPointHeadView.m */; };
+		812021152B14659A0026B8B5 /* ASUserInfoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 812021142B14659A0026B8B5 /* ASUserInfoManager.m */; };
+		812021182B1467410026B8B5 /* ASUserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 812021172B1467410026B8B5 /* ASUserModel.m */; };
+		8120211B2B15F03B0026B8B5 /* ASVipModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8120211A2B15F03B0026B8B5 /* ASVipModel.m */; };
+		8120211E2B15F2B30026B8B5 /* ASVipUrlTempModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8120211D2B15F2B30026B8B5 /* ASVipUrlTempModel.m */; };
+		812021212B16CD630026B8B5 /* ASSginViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 812021202B16CD630026B8B5 /* ASSginViewModel.m */; };
+		8127ADDB2B1193A300464D27 /* ASNetTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 8127ADDA2B1193A300464D27 /* ASNetTools.m */; };
 		8134C1AD2A13094F006EB0EC /* Target_userCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8134C1AC2A13094F006EB0EC /* Target_userCenter.m */; };
 		8134C1B42A1358F3006EB0EC /* ASSginView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8134C1B32A1358F3006EB0EC /* ASSginView.m */; };
 		8134C1B72A1359E6006EB0EC /* ASSignDayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8134C1B62A1359E6006EB0EC /* ASSignDayView.m */; };
@@ -258,6 +264,20 @@
 		811F42452A40533C00DA68F1 /* ASPointsHomeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASPointsHomeViewController.m; sourceTree = "<group>"; };
 		811F42472A40536C00DA68F1 /* ASPointHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASPointHeadView.h; sourceTree = "<group>"; };
 		811F42482A40536C00DA68F1 /* ASPointHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASPointHeadView.m; sourceTree = "<group>"; };
+		812021132B14659A0026B8B5 /* ASUserInfoManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASUserInfoManager.h; sourceTree = "<group>"; };
+		812021142B14659A0026B8B5 /* ASUserInfoManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASUserInfoManager.m; sourceTree = "<group>"; };
+		812021162B1467410026B8B5 /* ASUserModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASUserModel.h; sourceTree = "<group>"; };
+		812021172B1467410026B8B5 /* ASUserModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASUserModel.m; sourceTree = "<group>"; };
+		812021192B15F03B0026B8B5 /* ASVipModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASVipModel.h; sourceTree = "<group>"; };
+		8120211A2B15F03B0026B8B5 /* ASVipModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASVipModel.m; sourceTree = "<group>"; };
+		8120211C2B15F2B30026B8B5 /* ASVipUrlTempModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASVipUrlTempModel.h; sourceTree = "<group>"; };
+		8120211D2B15F2B30026B8B5 /* ASVipUrlTempModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASVipUrlTempModel.m; sourceTree = "<group>"; };
+		8120211F2B16CD630026B8B5 /* ASSginViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASSginViewModel.h; sourceTree = "<group>"; };
+		812021202B16CD630026B8B5 /* ASSginViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASSginViewModel.m; sourceTree = "<group>"; };
+		812021222B16D2D40026B8B5 /* ASUserNotifyStatic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASUserNotifyStatic.h; sourceTree = "<group>"; };
+		8127ADD92B1193A300464D27 /* ASNetTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASNetTools.h; sourceTree = "<group>"; };
+		8127ADDA2B1193A300464D27 /* ASNetTools.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASNetTools.m; sourceTree = "<group>"; };
+		8127ADDC2B11973400464D27 /* ASNetApis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASNetApis.h; sourceTree = "<group>"; };
 		8134C1AB2A13094F006EB0EC /* Target_userCenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Target_userCenter.h; sourceTree = "<group>"; };
 		8134C1AC2A13094F006EB0EC /* Target_userCenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Target_userCenter.m; sourceTree = "<group>"; };
 		8134C1B22A1358F3006EB0EC /* ASSginView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASSginView.h; sourceTree = "<group>"; };
@@ -704,6 +724,8 @@
 			children = (
 				814F5CED2A11B1F2003847A9 /* ASUserCenterViewController.h */,
 				814F5CEE2A11B1F2003847A9 /* ASUserCenterViewController.m */,
+				8120211F2B16CD630026B8B5 /* ASSginViewModel.h */,
+				812021202B16CD630026B8B5 /* ASSginViewModel.m */,
 				81354BEF2A287B040082C93A /* models */,
 				81354BE82A2879EE0082C93A /* views */,
 			);
@@ -723,6 +745,32 @@
 			path = Points;
 			sourceTree = "<group>";
 		};
+		812021122B14657D0026B8B5 /* UserManager */ = {
+			isa = PBXGroup;
+			children = (
+				812021132B14659A0026B8B5 /* ASUserInfoManager.h */,
+				812021142B14659A0026B8B5 /* ASUserInfoManager.m */,
+				812021162B1467410026B8B5 /* ASUserModel.h */,
+				812021172B1467410026B8B5 /* ASUserModel.m */,
+				812021192B15F03B0026B8B5 /* ASVipModel.h */,
+				8120211A2B15F03B0026B8B5 /* ASVipModel.m */,
+				8120211C2B15F2B30026B8B5 /* ASVipUrlTempModel.h */,
+				8120211D2B15F2B30026B8B5 /* ASVipUrlTempModel.m */,
+			);
+			path = UserManager;
+			sourceTree = "<group>";
+		};
+		8127ADD82B11930300464D27 /* NetTools */ = {
+			isa = PBXGroup;
+			children = (
+				8127ADD92B1193A300464D27 /* ASNetTools.h */,
+				8127ADDA2B1193A300464D27 /* ASNetTools.m */,
+				8127ADDC2B11973400464D27 /* ASNetApis.h */,
+				812021222B16D2D40026B8B5 /* ASUserNotifyStatic.h */,
+			);
+			path = NetTools;
+			sourceTree = "<group>";
+		};
 		81354BE82A2879EE0082C93A /* views */ = {
 			isa = PBXGroup;
 			children = (
@@ -1085,6 +1133,7 @@
 				9A2646BA2A187B6100CBFBDC /* Product */,
 				9A2027F32A137B6A00FF4DAF /* Asteria.entitlements */,
 				81C3B44F29F6699900D79294 /* PreFixHeader.h */,
+				8127ADD82B11930300464D27 /* NetTools */,
 				9A8DD8CC2A0B9E0C00573324 /* Assets */,
 				9AD364CE2A05EC4500452C7A /* Tabber */,
 				9AD364CC2A05EBE800452C7A /* Fuction */,
@@ -1699,6 +1748,7 @@
 		9AD364CC2A05EBE800452C7A /* Fuction */ = {
 			isa = PBXGroup;
 			children = (
+				812021122B14657D0026B8B5 /* UserManager */,
 				81DFA55A2A46C44800DA708B /* WebView */,
 				81717CAC2A3C453900648139 /* Category */,
 				81601FE32A2D938B00E4A8F1 /* Home */,
@@ -2086,6 +2136,7 @@
 				81E5EE942A4A760D0075695F /* ASVipCenterLineItemView.m in Sources */,
 				81601FFF2A2DC8E700E4A8F1 /* ASHomeBannerCell.m in Sources */,
 				81717D132A3C4AE000648139 /* KWSearchViewController.m in Sources */,
+				812021212B16CD630026B8B5 /* ASSginViewModel.m in Sources */,
 				81CE28972AF4953C0012AA45 /* ASGiftCardModel.m in Sources */,
 				9AD6A5442A1218E8001DE3D9 /* PassWordSecureBtnV.m in Sources */,
 				811F42462A40533C00DA68F1 /* ASPointsHomeViewController.m in Sources */,
@@ -2115,6 +2166,7 @@
 				81717D212A3C4AE000648139 /* KWSearchSubTypeTableView.m in Sources */,
 				9AD3461D2A08D6F0005CA070 /* GoodsInformationM.m in Sources */,
 				9A1247972A1B0A2800126226 /* AS_ForgotC.m in Sources */,
+				812021182B1467410026B8B5 /* ASUserModel.m in Sources */,
 				81EC476C2A33131100516573 /* ASHomeNewInSubCollectCell.m in Sources */,
 				81DFA5632A46CD6000DA708B /* Target_WebView.m in Sources */,
 				81354BF52A287BED0082C93A /* KWMineHomeOrderSubView.m in Sources */,
@@ -2124,6 +2176,8 @@
 				81354C002A2899CB0082C93A /* KWMineMoreProductModel.m in Sources */,
 				81717D362A3D322700648139 /* KWLenovoWordListView.m in Sources */,
 				8134C1BA2A1372A7006EB0EC /* ASUserCenterEnterItemV.m in Sources */,
+				8127ADDB2B1193A300464D27 /* ASNetTools.m in Sources */,
+				812021152B14659A0026B8B5 /* ASUserInfoManager.m in Sources */,
 				9AD3460A2A08D60F005CA070 /* ZFUtilities.m in Sources */,
 				81354BFC2A28998B0082C93A /* KWMineMoreProductTypeCell.m in Sources */,
 				9AD6A5492A1237D0001DE3D9 /* Target_Login.m in Sources */,
@@ -2149,6 +2203,7 @@
 				81717D102A3C4AE000648139 /* KWHisAndHotWordsViewModel.m in Sources */,
 				9AD3460D2A08D60F005CA070 /* ZFLandScapeControlView.m in Sources */,
 				9AD364C62A05E73E00452C7A /* AS_GoodsDetailsC.m in Sources */,
+				8120211E2B15F2B30026B8B5 /* ASVipUrlTempModel.m in Sources */,
 				816020102A2EE55F00E4A8F1 /* ASCategaryListCell.m in Sources */,
 				9AD3460B2A08D60F005CA070 /* UIView+ZFFrame.m in Sources */,
 				81E257FD2A12340E004EEF71 /* ASEnterItemV.m in Sources */,
@@ -2161,6 +2216,7 @@
 				81717C9C2A3BF1F100648139 /* ASHomeAlertViewController.m in Sources */,
 				9AD345FC2A08D60F005CA070 /* ZFPlayerLogManager.m in Sources */,
 				816D0C9D2AF3988400395B5B /* ASGiftCardAvailabelCell.m in Sources */,
+				8120211B2B15F03B0026B8B5 /* ASVipModel.m in Sources */,
 				81354C0E2A297D6A0082C93A /* HomeFlashDealSubCollectCell.m in Sources */,
 				81354BFD2A28998B0082C93A /* KWMineMoreProductsCell.m in Sources */,
 				9ACBEC252A14707400A8F97A /* AS_SignUpC.m in Sources */,
@@ -2336,6 +2392,7 @@
 				GCC_PREFIX_HEADER = "$(SRCROOT)/Asteria/PreFixHeader.h";
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = Asteria/Info.plist;
+				INFOPLIST_KEY_CFBundleDisplayName = Asteria;
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
 				INFOPLIST_KEY_UIMainStoryboardFile = "";
@@ -2368,6 +2425,7 @@
 				GCC_PREFIX_HEADER = "$(SRCROOT)/Asteria/PreFixHeader.h";
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = Asteria/Info.plist;
+				INFOPLIST_KEY_CFBundleDisplayName = Asteria;
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
 				INFOPLIST_KEY_UIMainStoryboardFile = "";

+ 1 - 1
Asteria/ASUI/CustomView/ASSignDayView.h

@@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, strong) UILabel *dayLb;
 @property (nonatomic, strong) UIImageView *statusImgV;
 
-- (void)setDay:(NSInteger)day st:(BOOL)isSgin isToday:(BOOL)isToday;
+- (void)setDay:(NSInteger)day st:(NSInteger)isSgin;
 
 @end
 

+ 3 - 3
Asteria/ASUI/CustomView/ASSignDayView.m

@@ -9,13 +9,13 @@
 
 @implementation ASSignDayView
 
-- (void)setDay:(NSInteger)day st:(BOOL)isSgin isToday:(BOOL)isToday {
+- (void)setDay:(NSInteger)day st:(NSInteger)isSgin {
     self.dayLb.text = [NSString stringWithFormat:@"D%ld", day];
-    if (isSgin) {
+    if (isSgin == 2) {
         self.dayLb.textColor = Col_000;
         self.statusImgV.image = [UIImage imageNamed:@"sd_signed"];
     } else {
-        if (isToday) {
+        if (isSgin == 1) {
             self.dayLb.textColor = Col_666;
             self.statusImgV.image = [UIImage imageNamed:@"sd_waitSign"];
         } else {

+ 2 - 0
Asteria/ASUI/CustomView/UserInfoV/ASUserBaseInfoView.h

@@ -15,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, strong) ASUserAvaterView *avaterV;
 @property (nonatomic, strong) UILabel *usefualLb;
 
+- (void)setData;
+
 // vip页面展示用户信息调整
 - (void)reSetSubVMas;
 

+ 9 - 8
Asteria/ASUI/CustomView/UserInfoV/ASUserBaseInfoView.m

@@ -22,13 +22,15 @@
 @implementation ASUserBaseInfoView
 
 
-- (void)setDemoData {
-    [self.avaterV setUserHeadV:@"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F5b342386-43ce-4ab5-bf30-c1bb7e2d85d8%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1690257640&t=8bdb74b6b68e2eeb05e1ab74bf6647ab" uName:@"new"];//@"https://www.shijuepi.com/uploads/allimg/201103/1-201103104255.jpg"
-    self.uNameLb.text = @"new";
-    self.vipLevelV.image = [UIImage imageNamed:@"uc_vip_level_1"];
-    self.uNameLb.text = @"new";
-    self.emailLb.text = @"653462314@qq.com";
-    self.usefualLb.text = @"300 points";
+- (void)setData {
+    ASUserModel *user = ASUserInfoManager.shared.userInfo;
+    NSString *userName = [NSString stringWithFormat:@"%@ %@", user.lastname, user.firstname];
+    [self.avaterV setUserHeadV:@"" uName:userName];
+    self.uNameLb.text = userName;
+    NSInteger level = ASUserInfoManager.shared.curVipInfo.level.integerValue;
+    self.vipLevelV.image = [UIImage imageNamed:[NSString stringWithFormat:@"uc_vip_level_%ld", level]];
+    self.emailLb.text = user.email;
+    self.usefualLb.text = [NSString stringWithFormat: @"%@ points", ASUserInfoManager.shared.userPoints];
 }
 
 - (instancetype)initWithFrame:(CGRect)frame {
@@ -36,7 +38,6 @@
     if (self) {
         self.backgroundColor = UIColor.clearColor;
         [self loadSubV];
-        [self setDemoData];
     }
     return self;
 }

+ 4 - 1
Asteria/AppDelegate.m

@@ -32,8 +32,11 @@
     AS_TabBarViewController *tab = [[AS_TabBarViewController alloc] init];
     tab.selectedIndex = 0;
     self.window.rootViewController = tab;
+    if (ASUserInfoManager.shared.isLogin ) {
+        [ASUserInfoManager.shared getInfo];
+    }
     [self.window makeKeyAndVisible];
-    
+    [UIApplication.sharedApplication setNetworkActivityIndicatorVisible:true];
     
     return YES;
 }

+ 2 - 1
Asteria/Fuction/Home/ASHomeViewController.m

@@ -31,6 +31,7 @@
 
 - (void)viewDidLoad {
     [super viewDidLoad];
+    
     __block typeof(self) wSelf = self;
     [self ucHomeStyle:^{
         // TODO: 跳转搜索模块
@@ -157,7 +158,7 @@
         case 3: {// bestSell
             ASHomeBestSellCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ASHomeBestSellCell" forIndexPath:indexPath];
             cell.productClick = ^(NSInteger i, ASProductBaseModel * _Nonnull m) {
-                
+                [ASNetTools login];
             };
             cell.model = m;
             return cell;

+ 4 - 0
Asteria/Fuction/UserCenter/Target_userCenter.m

@@ -15,4 +15,8 @@
     return  vc;
 }
 
+- (Class)Action_userCenterVcClass:(NSDictionary *)params {
+    return ASUserCenterViewController.class;
+}
+
 @end

+ 19 - 0
Asteria/Fuction/UserCenter/UserCenterHome/ASSginViewModel.h

@@ -0,0 +1,19 @@
+//
+//  ASSginViewModel.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/29.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ASSginViewModel : NSObject
+
+- (void)getSignData:(void(^)(NSArray *arr))compBlock;
+- (void)signToday:(void(^)(void))compBlock;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 32 - 0
Asteria/Fuction/UserCenter/UserCenterHome/ASSginViewModel.m

@@ -0,0 +1,32 @@
+//
+//  ASSginViewModel.m
+//  Asteria
+//
+//  Created by iOS on 2023/11/29.
+//
+
+#import "ASSginViewModel.h"
+
+@implementation ASSginViewModel
+
+- (void)getSignData:(void(^)(NSArray *arr))compBlock {
+    [ASNetTools.shared getWithPath:getSignStateUrl param:@{} success:^(id _Nonnull json) {
+        NSArray *arr = json;
+        compBlock(arr);
+    } faild:^(NSString * _Nonnull code, NSString * _Nonnull msg) {
+        NSArray *arr= [NSArray array];
+        compBlock(arr);
+        [Current_normalTool.currentNav.topViewController.view makeToast:msg];
+    }];
+}
+
+- (void)signToday:(void(^)(void))compBlock {
+    [ASNetTools.shared postWithPath:postSignUrl param:@{} success:^(id _Nonnull json) {
+        compBlock();
+    } faild:^(NSString * _Nonnull code, NSString * _Nonnull msg) {
+        compBlock();
+        [Current_normalTool.currentNav.topViewController.view makeToast:msg];
+    }];
+}
+
+@end

+ 15 - 3
Asteria/Fuction/UserCenter/UserCenterHome/ASUserCenterViewController.m

@@ -31,14 +31,27 @@
 - (void)viewDidLoad {
     [super viewDidLoad];
     [self configSubVs];
+    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(setData) name:UserInfoUpdate object:nil];
     
-    
 }
 
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    [self setData];
+}
+
+// MARK: - setData
+- (void)setData {
+    [self.tableHeadV.topV setData];
+    [self.tableHeadV.signV refreshData];
+}
+
+
+// MARK: - subVs
 - (void)configSubVs {
     __block typeof(self) wSelf = self;
     [self ucHomeStyle:^{
-        // TODO: 跳转搜索模块
+        
     }];
     
     [self.view addSubview:self.tableV];
@@ -48,7 +61,6 @@
         make.bottom.equalTo(self.view);
     }];
     
-    [self.tableHeadV.signV configDayArr:4 currentDay:7 status:false];
     
     
     __weak typeof(self) weakSelf = self;

+ 2 - 1
Asteria/Fuction/UserCenter/UserCenterHome/views/ASSginView.h

@@ -11,7 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface ASSginView : UIView
 
-- (void)configDayArr:(NSInteger)from currentDay:(NSInteger)current status:(BOOL)isSign;
+- (void)refreshData;
+
 
 @end
 

+ 79 - 29
Asteria/Fuction/UserCenter/UserCenterHome/views/ASSginView.m

@@ -7,6 +7,7 @@
 
 #import "ASSginView.h"
 #import "ASSignDayView.h"
+#import "ASSginViewModel.h"
 
 @interface ASSginView ()
 
@@ -19,15 +20,30 @@
 @property (nonatomic, strong) UILabel *titleLb;
 @property (nonatomic, strong) UIButton *signBt;
 
+@property (nonatomic, strong) ASSginViewModel *vm;
+
 @end
 
 @implementation ASSginView
 
-- (void)configDayArr:(NSInteger)from currentDay:(NSInteger)current status:(BOOL)isSign {
+- (void)signBtAction {
+    [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:true];
+    [self.vm signToday:^{
+        [ASUserInfoManager.shared getInfo];
+        [MBProgressHUD hideHUDForView:UIApplication.sharedApplication.keyWindow animated:true];
+    }];
+}
+
+- (void)refreshData {
+    __weak typeof(self) weakSelf = self;
+    [self.vm getSignData:^(NSArray * _Nonnull arr) {
+        [weakSelf setData:arr];
+    }];
+}
+
+- (void)setData:(NSArray<NSDictionary<NSString *, NSString*> *> *)data {
     self.unSignLineV.hidden = true;
     self.waitSignLineV.hidden = true;
-    self.signBt.backgroundColor = isSign ? Col_999 : Col_000;
-    
     for (ASSignDayView *v in self.dayArr) {
         if (v.superview) {
             [v removeFromSuperview];
@@ -35,58 +51,91 @@
     }
     self.dayArr = @[];
     NSMutableArray *arr = [NSMutableArray array];
-    for (NSInteger i = from; i < from + 7; i++) {
+    CGFloat space = (KScreenWidth-60-11*7)/6;
+    int todayindex = 0;
+    BOOL todayIsSign = true;
+    ASSignDayView *todayV = nil;
+    for (int i = 0; i<data.count; i++) {
+        NSDictionary<NSString *, NSString*> *dayData = data[i];
+        
         ASSignDayView *v = [[ASSignDayView alloc] initWithFrame:CGRectZero];
         v.tag = 10000+i;
         [arr addObject:v];
         [self.bgV addSubview:v];
-        CGFloat space = (KScreenWidth-60-11*7)/6;
-        if (current > i) {
-            [v setDay:i st:true  isToday:false];
-        } else if (current == i) {
-            [v setDay:i st:isSign  isToday:true];
-            if (!isSign) {
-                self.waitSignLineV.hidden = false;
-                [self.waitSignLineV mas_remakeConstraints:^(MASConstraintMaker *make) {
-                    make.trailing.equalTo(v.statusImgV.mas_centerX);
-                    make.width.equalTo([NSNumber numberWithFloat:space+11]);
-                    make.height.equalTo(@1);
-                    make.centerY.equalTo(self.baseLineV);
-                }];
+        
+        NSInteger signState = dayData[@"isSign"].integerValue;
+        [v setDay:dayData[@"day"].integerValue st:signState];
+        if (signState == 1) {
+            todayIsSign = false;
+            todayindex = i;
+            todayV = v;
+        } else if (signState == 2) {
+            if (i+1 < data.count) {
+                NSDictionary<NSString *, NSString*> *nextData = data[i+1];
+                NSInteger nextSignState = nextData[@"isSign"].integerValue;
+                if (signState == 2 && nextSignState == -1) {
+                    todayIsSign = true;
+                    todayindex = i;
+                    todayV = v;
+                }
+            } else {
+                todayIsSign = signState == 2;
+                todayindex = i;
+                todayV = v;
             }
-            self.unSignLineV.hidden = false;
-            [self.unSignLineV mas_remakeConstraints:^(MASConstraintMaker *make) {
-                make.trailing.equalTo(self.baseLineV.mas_trailing);
-                make.leading.equalTo(v.statusImgV.mas_centerX);
-                make.height.equalTo(@1);
-                make.centerY.equalTo(self.baseLineV);
-            }];
-            
         } else {
-            [v setDay:i st:false  isToday:false];
+            if (i == 0) {
+                todayIsSign = false;
+                todayindex = i;
+                todayV = v;
+            }
         }
         
         
         
+        
+        
         [v mas_makeConstraints:^(MASConstraintMaker *make) {
-            make.centerX.equalTo(self.baseLineV.mas_left).offset((i-from)*(space + 11)+5.5);
+            make.centerX.equalTo(self.baseLineV.mas_left).offset((i)*(space + 11)+5.5);
             make.bottom.equalTo(self.baseLineV.mas_centerY).offset(5.5);
         }];
-        
     }
+    self.dayArr = arr;
+    if (todayV == nil) {
+        return;
+    }
+    if (!todayIsSign && todayindex != 0) {
+        self.waitSignLineV.hidden = false;
+        [self.waitSignLineV mas_remakeConstraints:^(MASConstraintMaker *make) {
+            make.trailing.equalTo(todayV.statusImgV.mas_centerX);
+            make.width.equalTo([NSNumber numberWithFloat:space+11]);
+            make.height.equalTo(@1);
+            make.centerY.equalTo(self.baseLineV);
+        }];
+    }
+    self.unSignLineV.hidden = false;
+    [self.unSignLineV mas_remakeConstraints:^(MASConstraintMaker *make) {
+        make.trailing.equalTo(self.baseLineV.mas_trailing);
+        make.leading.equalTo(todayV.statusImgV.mas_centerX);
+        make.height.equalTo(@1);
+        make.centerY.equalTo(self.baseLineV);
+    }];
     
-    
+    self.signBt.backgroundColor = todayIsSign ? Col_999 : Col_000;
+    self.signBt.userInteractionEnabled = !todayIsSign;
     
 }
 
 
 
+
     
 - (instancetype)initWithFrame:(CGRect)frame {
     self = [super initWithFrame:frame];
     if (self) {
         self.bgV.frame = CGRectMake(10, 10, frame.size.width-20, frame.size.height-20);
         self.colorBgV.frame = self.bgV.bounds;
+        self.vm = [ASSginViewModel new];
         [self loadSubV];
     }
     return self;
@@ -213,6 +262,7 @@
         [bt setTitleColor:Col_FFF forState:UIControlStateNormal];
         bt.titleLabel.font = [UIFont fontWithName:Rob_Bold size:16];
         bt.backgroundColor = Col_000;
+        [bt addTarget:self action:@selector(signBtAction) forControlEvents:UIControlEventTouchUpInside];
         _signBt = bt;
     }
     return _signBt;

+ 2 - 0
Asteria/Fuction/UserCenter/UserCenterHome/views/ASUserCenterTopView.h

@@ -13,6 +13,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, copy) btnClickBlock settingBlock;
 
+- (void)setData;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 18 - 4
Asteria/Fuction/UserCenter/UserCenterHome/views/ASUserCenterTopView.m

@@ -36,10 +36,25 @@
 
 @implementation ASUserCenterTopView
 
-- (void)setDemoData {
-    
-    [self.bgAvaterV setUserHeadV:@"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F5b342386-43ce-4ab5-bf30-c1bb7e2d85d8%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1690257640&t=8bdb74b6b68e2eeb05e1ab74bf6647ab" uName:@"new"];
+- (void)setData {
+    ASUserModel *user = ASUserInfoManager.shared.userInfo;
+    NSString *userName = [NSString stringWithFormat:@"%@ %@", user.lastname, user.firstname];
+    [self.bgAvaterV setUserHeadV:@"" uName:userName];
     [self.bgAvaterV setBorderColor:[UIColor clearColor] width:0];
+    
+    [self.userInfoV setData];
+    
+    ASVipModel *curVipM = ASUserInfoManager.shared.curVipInfo;
+    ASVipModel *nexVipM = ASUserInfoManager.shared.nextVipInfo;
+    self.vipLevel1.image = [UIImage imageNamed:[NSString stringWithFormat:@"uc_vip_level_%ld", curVipM.level.integerValue]];
+    self.vipDesLb.text = [NSString stringWithFormat:@"Growth Value %ld/%ld", ASUserInfoManager.shared.pointAmount.integerValue, nexVipM.exppoints.integerValue];
+    
+    self.vipLevel2.image = [UIImage imageNamed:[NSString stringWithFormat:@"uc_vip_level_%ld", nexVipM.level.integerValue]];
+    
+    
+    
+    
+    
 }
 
 - (void)settingAction {
@@ -56,7 +71,6 @@
     if (self) {
         self.backgroundColor = UIColor.clearColor;
         [self loadSubV];
-        [self setDemoData];
     }
     return self;
 }

+ 35 - 0
Asteria/Fuction/UserManager/ASUserInfoManager.h

@@ -0,0 +1,35 @@
+//
+//  ASUserInfoManager.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/27.
+//
+
+#import <Foundation/Foundation.h>
+#import "ASUserModel.h"
+#import "ASVipModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ASUserInfoManager : NSObject
+
++ (instancetype)shared;
+
+@property (nonatomic, assign) BOOL isLogin;
+
+@property (nonatomic, strong) ASUserModel *userInfo;
+@property (nonatomic, strong) ASVipModel *curVipInfo;
+@property (nonatomic, strong) ASVipModel *nextVipInfo;
+
+/// 以获取总积分
+@property (nonatomic, copy) NSString *pointAmount;
+/// 用户当前可用积分
+@property (nonatomic, copy) NSString *userPoints;
+
+@property (nonatomic, strong) NSArray<ASVipModel *> *vipInfoArr;
+
+- (void)getInfo;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 119 - 0
Asteria/Fuction/UserManager/ASUserInfoManager.m

@@ -0,0 +1,119 @@
+//
+//  ASUserInfoManager.m
+//  Asteria
+//
+//  Created by iOS on 2023/11/27.
+//
+
+#import "ASUserInfoManager.h"
+#import "ASVipUrlTempModel.h"
+
+@interface ASUserInfoManager ()
+
+
+
+@end
+
+@implementation ASUserInfoManager
+
++ (instancetype)shared {
+    static id sharedInstance = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        sharedInstance = [[self alloc] init];
+    });
+    return sharedInstance;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        
+    }
+    return self;
+}
+
+- (void)getInfo {
+    [self baseInfoNet];
+    [self vipInfoNet];
+}
+
+- (void)baseInfoNet {
+    [ASNetTools.shared getWithPath:userinfoUrl param:@{} success:^(id _Nonnull json) {
+        self.userInfo = [ASUserModel mj_objectWithKeyValues:json];
+        [NSNotificationCenter.defaultCenter postNotificationName:UserInfoUpdate object:nil];
+        NSLog(@"----userInfo:%@-----id:%@----issub:%u----address:%@----", self.userInfo, self.userInfo.Id, self.userInfo.is_subscribed, self.userInfo.addresses);
+    } faild:^(NSString * _Nonnull code, NSString * _Nonnull msg) {
+        [Current_normalTool.currentNav.topViewController.view makeToast:msg];
+    }];
+}
+
+- (void)vipInfoNet {
+    [ASNetTools.shared getWithPath:vipInfoUrl param:@{} success:^(id _Nonnull json) {
+        
+        ASVipUrlTempModel *tempModel = [ASVipUrlTempModel mj_objectWithKeyValues:json];
+        self.pointAmount = tempModel.amount;
+        self.userPoints = tempModel.balanceAmount;
+        NSMutableArray<ASVipModel *> *arr = [NSMutableArray array];
+        ASVipModel *cur = [ASVipModel new];
+        ASVipModel *next = [ASVipModel new];
+        if (tempModel != nil && tempModel.membergrade.count != 0) {
+            NSArray *keys = tempModel.membergrade.allKeys;
+            NSMutableArray *sortedArr = [NSMutableArray array];
+            for (NSString *key in keys) {
+                if (sortedArr.count == 0) {
+                    [sortedArr addObject:key];
+                    continue;
+                }
+                for (int i=0; i<sortedArr.count; i++) {
+                    NSString *this = sortedArr[i];
+                    if (sortedArr.count > i+1) {
+                        NSString *nx = sortedArr[i+1];
+                        if (key.intValue >= this.intValue && key.intValue < nx.intValue) {
+                            [sortedArr insertObject:key atIndex:i+1];
+                            break;
+                        }
+                    } else {
+                        if (sortedArr.count == 1 && key.intValue <= this.intValue) {
+                            [sortedArr insertObject:key atIndex:i];
+                        } else {
+                            [sortedArr addObject:key];
+                        }
+                        break;
+                    }
+                }
+                
+            }
+            for (int i=0; i<sortedArr.count; i++) {
+                ASVipModel *vipM = [ASVipModel mj_objectWithKeyValues: tempModel.membergrade[sortedArr[i]]];
+                if (cur.level.intValue > 0 && next.level.intValue <= 0) {
+                    next = vipM;
+                }
+                if (vipM.is_cur) {
+                    cur = vipM;
+                }
+                if (cur.level.intValue > 0 && next.level.intValue <= 0 && i == sortedArr.count-1) {
+                    next = vipM;
+                }
+                [arr addObject:vipM];
+            }
+        }
+        self.curVipInfo = cur;
+        self.nextVipInfo = next;
+        self.vipInfoArr = arr;
+        [NSNotificationCenter.defaultCenter postNotificationName:UserInfoUpdate object:nil];
+        
+    } faild:^(NSString * _Nonnull code, NSString * _Nonnull msg) {
+        [Current_normalTool.currentNav.topViewController.view makeToast:msg];
+    }];
+}
+
+- (BOOL)isLogin {
+    NSString *token = [NSUserDefaults.standardUserDefaults stringForKey:TokenKey];
+    return !(token == nil || [token isEqualToString:@""]);
+}
+
+
+
+@end

+ 69 - 0
Asteria/Fuction/UserManager/ASUserModel.h

@@ -0,0 +1,69 @@
+//
+//  ASUserModel.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/27.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface ASAddressReginModel : NSObject
+
+@property (nonatomic, copy) NSString *region_code;
+@property (nonatomic, copy) NSString *region;
+@property (nonatomic, copy) NSString *region_id;
+
+
+@end
+
+@interface ASAddressModel : NSObject
+
+@property (nonatomic, copy) NSString *Id;
+@property (nonatomic, copy) NSString *customer_id;
+@property (nonatomic, strong) ASAddressReginModel *region;
+@property (nonatomic, copy) NSString *region_id;
+@property (nonatomic, copy) NSString *country_id;
+@property (nonatomic, copy) NSString *street;
+@property (nonatomic, copy) NSString *company;
+@property (nonatomic, copy) NSString *telephone;
+@property (nonatomic, copy) NSString *postcode;
+@property (nonatomic, copy) NSString *city;
+@property (nonatomic, copy) NSString *firstname;
+@property (nonatomic, copy) NSString *lastname;
+@property (nonatomic, copy) NSString *default_shipping;
+@property (nonatomic, copy) NSString *default_billing;
+
+
+@end
+
+@interface ASUserModel : NSObject
+
+@property (nonatomic, copy, ) NSString *Id;
+@property (nonatomic, copy) NSString *group_id;
+@property (nonatomic, copy) NSString *default_billing;
+@property (nonatomic, copy) NSString *default_shipping;
+@property (nonatomic, copy) NSString *created_at;
+@property (nonatomic, copy) NSString *updated_at;
+@property (nonatomic, copy) NSString *created_in;
+@property (nonatomic, copy) NSString *email;
+@property (nonatomic, copy) NSString *firstname;
+@property (nonatomic, copy) NSString *lastname;
+@property (nonatomic, copy) NSString *gender;
+@property (nonatomic, copy) NSString *store_id;
+@property (nonatomic, copy) NSString *website_id;
+@property (nonatomic, strong) NSArray<ASAddressModel *> *addresses;
+@property (nonatomic, assign) BOOL is_subscribed;
+
+
+
+@end
+
+
+
+
+
+NS_ASSUME_NONNULL_END

+ 55 - 0
Asteria/Fuction/UserManager/ASUserModel.m

@@ -0,0 +1,55 @@
+//
+//  ASUserModel.m
+//  Asteria
+//
+//  Created by iOS on 2023/11/27.
+//
+
+#import "ASUserModel.h"
+
+
+@implementation ASUserModel
+
++ (NSDictionary *)mj_replacedKeyFromPropertyName {
+    return @{
+        @"Id": @"id",
+        @"is_subscribed": @"extension_attributes.is_subscribed",
+    };
+}
+
+
+
+
++ (NSDictionary *)mj_objectClassInArray{
+    
+    return @{
+        
+        @"addresses" : [ASAddressModel class]
+        
+    };
+    
+    
+    
+}
+
+
+
+
+@end
+
+
+@implementation ASAddressModel
+
++ (NSDictionary *)mj_replacedKeyFromPropertyName {
+    return @{
+        @"Id": @"id",
+    };
+}
+
+@end
+
+@implementation ASAddressReginModel
+
+
+
+@end

+ 33 - 0
Asteria/Fuction/UserManager/ASVipModel.h

@@ -0,0 +1,33 @@
+//
+//  ASVipModel.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/28.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@interface ASVipPriSubModel : NSObject
+
+@property (nonatomic, copy) NSString *title;
+@property (nonatomic, copy) NSString *desc;
+/// web使用    暂时无用
+@property (nonatomic, copy) NSString *url;
+
+@end
+
+
+@interface ASVipModel : NSObject
+
+@property (nonatomic, copy) NSString *level;
+@property (nonatomic, copy) NSString *level_name;
+@property (nonatomic, copy) NSString *exppoints;
+@property (nonatomic, copy) NSArray<ASVipPriSubModel *> *privilege;
+@property (nonatomic, assign) BOOL is_cur;
+
+@end
+
+
+
+NS_ASSUME_NONNULL_END

+ 30 - 0
Asteria/Fuction/UserManager/ASVipModel.m

@@ -0,0 +1,30 @@
+//
+//  ASVipModel.m
+//  Asteria
+//
+//  Created by iOS on 2023/11/28.
+//
+
+#import "ASVipModel.h"
+
+@implementation ASVipPriSubModel
+
+
+
+@end
+
+@implementation ASVipModel
+
++ (NSDictionary *)mj_objectClassInArray{
+    
+    return @{
+        
+        @"privilege" : [ASVipPriSubModel class]
+        
+    };
+    
+    
+    
+}
+
+@end

+ 21 - 0
Asteria/Fuction/UserManager/ASVipUrlTempModel.h

@@ -0,0 +1,21 @@
+//
+//  ASVipUrlTempModel.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/28.
+//
+
+#import <Foundation/Foundation.h>
+#import "ASVipModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ASVipUrlTempModel : NSObject
+
+@property (nonatomic, copy) NSString *amount;
+@property (nonatomic, copy) NSString *balanceAmount;
+@property (nonatomic, strong) NSDictionary<NSString*, NSDictionary*> *membergrade;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 13 - 0
Asteria/Fuction/UserManager/ASVipUrlTempModel.m

@@ -0,0 +1,13 @@
+//
+//  ASVipUrlTempModel.m
+//  Asteria
+//
+//  Created by iOS on 2023/11/28.
+//
+
+#import "ASVipUrlTempModel.h"
+
+@implementation ASVipUrlTempModel
+
+
+@end

+ 37 - 0
Asteria/NetTools/ASNetApis.h

@@ -0,0 +1,37 @@
+//
+//  ASNetApis.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/25.
+//
+
+#ifndef ASNetApis_h
+#define ASNetApis_h
+
+#define TokenKey @"ASUserToken"
+
+#define BaseRequestrUrl(url) ([NSString stringWithFormat:@"%@%@",@"rest/V1/",url])
+
+// MARK: - host
+#if (DEBUG)
+#define HostPath @"pc.bilisar.com"//@"www.bilisar.com"//@"https://www.bilisar.com/"  //测试
+#else
+#define HostPath @"pc.bilisar.com"//@"https://pc.bilisar.com/"  //正式
+#endif
+
+// MARK: - path
+
+// MARK: - userinfo
+#define registerUrl BaseRequestrUrl(@"customers")
+#define loginUrl BaseRequestrUrl(@"integration/customer/token")
+#define userinfoUrl BaseRequestrUrl(@"customers/me")
+#define vipInfoUrl BaseRequestrUrl(@"vip/index")
+#define userBirthUrl BaseRequestrUrl(@"vip/birthday")
+
+
+//MARK: - 个人中心
+#define getSignStateUrl BaseRequestrUrl(@"sign/index")
+#define postSignUrl BaseRequestrUrl(@"sign/add")
+
+
+#endif /* ASNetApis_h */

+ 41 - 0
Asteria/NetTools/ASNetTools.h

@@ -0,0 +1,41 @@
+//
+//  ASNetTools.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/25.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ASNetTools : NSObject
+
++ (instancetype)shared;
+- (void)setDefualtParam:(NSDictionary *)defualt;
+- (void)updateDefualtParam:(NSDictionary *)newData;
+
+// 登录或者退出登录时调用;
+- (void)updateEngine;
+
+
+/// post请求
+- (void)postWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild;
+
+/// get请求
+- (void)getWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild;
+
+/// put请求
+- (void)putWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild;
+
+/// delete请求
+- (void)delWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild;
+
+
++ (void)login;
++ (void)debugRegist;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 338 - 0
Asteria/NetTools/ASNetTools.m

@@ -0,0 +1,338 @@
+//
+//  ASNetTools.m
+//  Asteria
+//
+//  Created by iOS on 2023/11/25.
+//
+
+#import "ASNetTools.h"
+#import <MKNetworkKit/MKNetworkKit.h>
+
+@interface ASNetTools ()
+
+@property (nonatomic, strong) MKNetworkEngine *engine;
+@property (nonatomic, strong) NSMutableDictionary *defuatParam;
+
+@end
+
+@implementation ASNetTools
+
++ (instancetype)shared {
+    static id sharedInstance = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        sharedInstance = [[self alloc] init];
+    });
+    return sharedInstance;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self updateEngine];
+        self.defuatParam = [NSMutableDictionary dictionary];
+    }
+    return self;
+}
+
+- (void)setDefualtParam:(NSDictionary *)defualt {
+    self.defuatParam = [[NSMutableDictionary alloc] initWithDictionary:defualt];
+}
+
+- (void)updateDefualtParam:(NSDictionary *)newData {
+    for (NSString *key in newData.allKeys) {
+        self.defuatParam[key] = newData[key];
+    }
+}
+
+- (void)updateEngine {
+    NSString *token = [NSUserDefaults.standardUserDefaults stringForKey:TokenKey];
+    if (!token) {
+        token = @"";
+    }
+    self.engine = [[MKNetworkEngine alloc] initWithHostName:HostPath customHeaderFields:@{
+        @"Authorization":token,
+        @"powerby": @"longyitec",
+        @"Content-Type": @"application/json;charset=utf-8"
+    }];
+    
+}
+
+// post请求
+- (void)postWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild {
+    BOOL isSSL = true;
+//#if (DEBUG)
+//    isSSL = false;
+//#endif
+    NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithDictionary:self.defuatParam];
+    [tempDic addEntriesFromDictionary:param];
+    MKNetworkOperation *op = [self.engine operationWithPath:path params:tempDic httpMethod:@"POST" ssl:isSSL];
+    [op setPostDataEncoding:MKNKPostDataEncodingTypeJSON];
+    __weak typeof(self) weakSelf = self;
+    [op onCompletion:^(MKNetworkOperation *completedOperation) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = [NSString stringWithFormat:@"%@", result[@"status"]];
+                id data = result[@"data"];
+                if ([status isEqualToString:@"1"]) {
+                    success(data);
+                } else {
+                    NSString *msg = result[@"msg"];
+                    faild(status, msg);
+                }
+            }
+            
+        });
+    } onError:^(NSError *error) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = result[@"status"];
+                NSString *msg = result[@"msg"];
+                if (error.code == 401) {
+                    [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                    [weakSelf updateEngine];
+                    faild(status, msg);
+                    return;
+                }
+                faild(status, msg);
+                return;
+            }
+            if (error.code == 401) {
+                [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                [weakSelf updateEngine];
+                faild(@"-1", @"Plase Login");
+                return;
+            }
+            faild([NSString stringWithFormat:@"%ld", error.code], error.localizedDescription);
+        });
+    }];
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
+        [self.engine enqueueOperation:op];
+    });
+}
+
+// get 请求
+- (void)getWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild {
+    BOOL isSSL = true;
+//#if (DEBUG)
+//    isSSL = false;
+//#endif
+    NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithDictionary:self.defuatParam];
+    [tempDic addEntriesFromDictionary:param];
+    MKNetworkOperation *op = [self.engine operationWithPath:path params:tempDic httpMethod:@"GET" ssl:isSSL];
+    __weak typeof(self) weakSelf = self;
+    [op onCompletion:^(MKNetworkOperation *completedOperation) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = [NSString stringWithFormat:@"%@", result[@"status"]];
+                id data = result[@"data"];
+                if ([status isEqualToString:@"1"]) {
+                    success(data);
+                } else {
+                    NSString *msg = result[@"msg"];
+                    faild(status, msg);
+                }
+            }
+            
+        });
+    } onError:^(NSError *error) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = result[@"status"];
+                NSString *msg = result[@"msg"];
+                if (error.code == 401) {
+                    [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                    [weakSelf updateEngine];
+                    faild(status, msg);
+                    return;
+                }
+                faild(status, msg);
+                return;
+            }
+            if (error.code == 401) {
+                [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                [weakSelf updateEngine];
+                faild(@"-1", @"Plase Login");
+                return;
+            }
+            faild([NSString stringWithFormat:@"%ld", error.code], error.localizedDescription);
+        });
+    }];
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
+        [self.engine enqueueOperation:op];
+    });
+
+}
+
+// put 请求
+- (void)putWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild {
+    BOOL isSSL = true;
+//#if (DEBUG)
+//    isSSL = false;
+//#endif
+    NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithDictionary:self.defuatParam];
+    [tempDic addEntriesFromDictionary:param];
+    MKNetworkOperation *op = [self.engine operationWithPath:path params:tempDic httpMethod:@"PUT" ssl:isSSL];
+    [op setPostDataEncoding:MKNKPostDataEncodingTypeJSON];
+    __weak typeof(self) weakSelf = self;
+    [op onCompletion:^(MKNetworkOperation *completedOperation) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = [NSString stringWithFormat:@"%@", result[@"status"]];
+                id data = result[@"data"];
+                if ([status isEqualToString:@"1"]) {
+                    success(data);
+                } else {
+                    NSString *msg = result[@"msg"];
+                    faild(status, msg);
+                }
+            }
+            
+        });
+    } onError:^(NSError *error) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = result[@"status"];
+                NSString *msg = result[@"msg"];
+                if (error.code == 401) {
+                    [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                    [weakSelf updateEngine];
+                    faild(status, msg);
+                    return;
+                }
+                faild(status, msg);
+                return;
+            }
+            if (error.code == 401) {
+                [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                [weakSelf updateEngine];
+                faild(@"-1", @"Plase Login");
+                return;
+            }
+            faild([NSString stringWithFormat:@"%ld", error.code], error.localizedDescription);
+        });
+    }];
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
+        [self.engine enqueueOperation:op];
+    });
+
+}
+
+// del 请求
+- (void)delWithPath:(NSString *)path param:(NSDictionary *)param success:(void(^)(id))success faild:(void(^)(NSString *code, NSString *msg))faild {
+    BOOL isSSL = true;
+//#if (DEBUG)
+//    isSSL = false;
+//#endif
+    NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithDictionary:self.defuatParam];
+    [tempDic addEntriesFromDictionary:param];
+    MKNetworkOperation *op = [self.engine operationWithPath:path params:tempDic httpMethod:@"DELETE" ssl:isSSL];
+    [op setPostDataEncoding:MKNKPostDataEncodingTypeJSON];
+    __weak typeof(self) weakSelf = self;
+    [op onCompletion:^(MKNetworkOperation *completedOperation) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = [NSString stringWithFormat:@"%@", result[@"status"]];
+                id data = result[@"data"];
+                if ([status isEqualToString:@"1"]) {
+                    success(data);
+                } else {
+                    NSString *msg = result[@"msg"];
+                    faild(status, msg);
+                }
+            }
+            
+        });
+    } onError:^(NSError *error) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *json = [op responseJSON];
+            id temp = [json mj_JSONObject];
+            if ([temp isKindOfClass:[NSDictionary class]]) {
+                NSDictionary *result = (NSDictionary *)temp;
+                NSString *status = result[@"status"];
+                NSString *msg = result[@"msg"];
+                if (error.code == 401) {
+                    [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                    [weakSelf updateEngine];
+                    faild(status, msg);
+                    return;
+                }
+                faild(status, msg);
+                return;
+            }
+            if (error.code == 401) {
+                [NSUserDefaults.standardUserDefaults setValue:@"" forKey:TokenKey];
+                [weakSelf updateEngine];
+                faild(@"-1", @"Plase Login");
+                return;
+            }
+            faild([NSString stringWithFormat:@"%ld", error.code], error.localizedDescription);
+        });
+    }];
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
+        [self.engine enqueueOperation:op];
+    });
+
+}
+
+
+
++ (void)debugRegist {
+    NSDictionary *param = @{
+        @"customer": @{
+            @"email": @"abc123456@qq.com",
+            @"firstname": @"ujrbcf",
+            @"lastname": @"serwt",
+            @"dob": @"2023/10/20"
+        },
+        @"password": @"a123456A",
+        @"extension_attributes" : @{
+            @"is_subscribed": @(true)
+        }
+    };
+    [ASNetTools.shared postWithPath:registerUrl param:param success:^(id _Nonnull result) {
+        NSLog(@"----url:%@-----result:%@------", registerUrl, result);
+    } faild:^(NSString * _Nonnull code, NSString * _Nonnull msg) {
+        NSLog(@"----url:%@-----code:%@----msg:%@--", registerUrl, code, msg);
+    }];
+}
+
++ (void)login {
+    NSDictionary *param = @{
+        @"username" :@"abc123456@qq.com",
+        @"password":@"a123456A"
+    };
+    [ASNetTools.shared postWithPath:loginUrl param:param success:^(id _Nonnull result) {
+        NSString *token = [NSString stringWithFormat:@"Bearer %@", result];
+        [NSUserDefaults.standardUserDefaults setValue:token forKey:TokenKey];
+        [ASNetTools.shared updateEngine];
+        [ASUserInfoManager.shared getInfo];
+        NSLog(@"----url:%@-----result:%@------", loginUrl, result);
+    } faild:^(NSString * _Nonnull code, NSString * _Nonnull msg) {
+        NSLog(@"----url:%@-----code:%@----msg:%@--", loginUrl, code, msg);
+    }];
+}
+
+@end

+ 14 - 0
Asteria/NetTools/ASUserNotifyStatic.h

@@ -0,0 +1,14 @@
+//
+//  ASUserNotifyStatic.h
+//  Asteria
+//
+//  Created by iOS on 2023/11/29.
+//
+
+#ifndef ASUserNotifyStatic_h
+#define ASUserNotifyStatic_h
+
+#define UserInfoUpdate @"ASUserInfoUpdate"
+
+
+#endif /* ASUserNotifyStatic_h */

+ 5 - 0
Asteria/PreFixHeader.h

@@ -8,6 +8,11 @@
 #ifndef PreFixHeader_h
 #define PreFixHeader_h
 
+#import "ASNetTools.h"
+#import "ASNetApis.h"
+#import "ASUserInfoManager.h"
+#import "ASUserNotifyStatic.h"
+
 #import "CTMediator+Categorys.h"
 #import "CTMediator+Home.h"
 #import "CTMediator+ASWebView.h"

+ 2 - 0
Asteria/Product/CTMediatoaTargets/CTMediator+UserCenter.h

@@ -14,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN
 /// 个人中心首页
 -(UIViewController *)getUserCenterVc:(NSDictionary *)params;
 
+-(Class)userCenterVcClass;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 4 - 0
Asteria/Product/CTMediatoaTargets/CTMediator+UserCenter.m

@@ -13,4 +13,8 @@
     return [self performTarget:@"userCenter" action:@"getUserCenterVc" params:params shouldCacheTarget:NO];
 }
 
+
+-(Class)userCenterVcClass {
+    return [self performTarget:@"userCenter" action:@"userCenterVcClass" params:@{} shouldCacheTarget:NO];
+}
 @end

+ 6 - 0
Asteria/Tabber/AS_TabBarViewController.m

@@ -75,6 +75,12 @@
             
             return false;
         }
+        if ([vc isKindOfClass:[CTMediator.sharedInstance userCenterVcClass]] && !([ASUserInfoManager.shared isLogin])) {
+            UIViewController *vc1 = [[CTMediator sharedInstance] getUserCenterVc:@{}];
+            
+            [self.selectedViewController pushViewController:vc1 animated:true];
+            return false;
+        }
 //        NSString *name = [NSString stringWithFormat:@"%s", object_getClassName(vc)];
 //        if ([name isEqualToString:@"APCategoryViewController"]) {
 //            return <#expression#>;

+ 2 - 0
Podfile

@@ -53,6 +53,8 @@ target 'Asteria' do
 
   pod 'GKPhotoBrowser'
   pod 'WMBase', :path =>"../WMBase"
+  
+  pod 'MKNetworkKit'
 
 
 pod 'OneSignalXCFramework', '>= 3.0.0', '< 4.0'

+ 6 - 1
Podfile.lock

@@ -812,6 +812,8 @@ PODS:
   - MBProgressHUD (1.2.0)
   - MJExtension (3.4.1)
   - MJRefresh (3.7.5)
+  - MKNetworkKit (0.85):
+    - Reachability (~> 3.0)
   - nanopb (2.30909.0):
     - nanopb/decode (= 2.30909.0)
     - nanopb/encode (= 2.30909.0)
@@ -1167,6 +1169,7 @@ DEPENDENCIES:
   - MBProgressHUD
   - MJExtension
   - MJRefresh
+  - MKNetworkKit
   - OneSignalXCFramework (< 4.0, >= 3.0.0)
   - PPBadgeView
   - Reachability
@@ -1210,6 +1213,7 @@ SPEC REPOS:
     - MBProgressHUD
     - MJExtension
     - MJRefresh
+    - MKNetworkKit
     - nanopb
     - OneSignalXCFramework
     - PPBadgeView
@@ -1261,6 +1265,7 @@ SPEC CHECKSUMS:
   MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
   MJExtension: 21c5f6f8c4d5d8844b7ae8fbae08fed0b501f961
   MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
+  MKNetworkKit: 1171bfac5c3a1cd7fea9a027f29359e1b4cab705
   nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
   OneSignalXCFramework: 4afdd14f6fa769eadf141209037e3eac5890beb9
   PPBadgeView: b50a223638970fd0781e8753250385864b6dd2fe
@@ -1274,6 +1279,6 @@ SPEC CHECKSUMS:
   YYCache: 8105b6638f5e849296c71f331ff83891a4942952
   YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
 
-PODFILE CHECKSUM: 6cbb741d4132b550ccfdc6abbfe06c4b24911517
+PODFILE CHECKSUM: 5d955d5ce86f96810ca16fd7acd16a89ff2750e0
 
 COCOAPODS: 1.13.0

+ 42 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSData+Base64.h

@@ -0,0 +1,42 @@
+//
+//  NSData+Base64.h
+//  base64
+//
+//  Created by Matt Gallagher on 2009/06/03.
+//  Copyright 2009 Matt Gallagher. All rights reserved.
+//
+//  This software is provided 'as-is', without any express or implied
+//  warranty. In no event will the authors be held liable for any damages
+//  arising from the use of this software. Permission is granted to anyone to
+//  use this software for any purpose, including commercial applications, and to
+//  alter it and redistribute it freely, subject to the following restrictions:
+//
+//  1. The origin of this software must not be misrepresented; you must not
+//     claim that you wrote the original software. If you use this software
+//     in a product, an acknowledgment in the product documentation would be
+//     appreciated but is not required.
+//  2. Altered source versions must be plainly marked as such, and must not be
+//     misrepresented as being the original software.
+//  3. This notice may not be removed or altered from any source
+//     distribution.
+//
+
+#import <Foundation/Foundation.h>
+
+void *NewBase64Decode(
+	const char *inputBuffer,
+	size_t length,
+	size_t *outputLength);
+
+char *NewBase64Encode(
+	const void *inputBuffer,
+	size_t length,
+	bool separateLines,
+	size_t *outputLength);
+
+@interface NSData (Base64)
+
++ (NSData *)dataFromBase64String:(NSString *)aString;
+- (NSString *)base64EncodedString;
+
+@end

+ 312 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSData+Base64.m

@@ -0,0 +1,312 @@
+//
+//  NSData+Base64.m
+//  base64
+//
+//  Created by Matt Gallagher on 2009/06/03.
+//  Copyright 2009 Matt Gallagher. All rights reserved.
+//
+//  This software is provided 'as-is', without any express or implied
+//  warranty. In no event will the authors be held liable for any damages
+//  arising from the use of this software. Permission is granted to anyone to
+//  use this software for any purpose, including commercial applications, and to
+//  alter it and redistribute it freely, subject to the following restrictions:
+//
+//  1. The origin of this software must not be misrepresented; you must not
+//     claim that you wrote the original software. If you use this software
+//     in a product, an acknowledgment in the product documentation would be
+//     appreciated but is not required.
+//  2. Altered source versions must be plainly marked as such, and must not be
+//     misrepresented as being the original software.
+//  3. This notice may not be removed or altered from any source
+//     distribution.
+//
+
+#import "NSData+Base64.h"
+
+//
+// Mapping from 6 bit pattern to ASCII character.
+//
+static unsigned char base64EncodeLookup[65] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+//
+// Definition for "masked-out" areas of the base64DecodeLookup mapping
+//
+#define xx 65
+
+//
+// Mapping from ASCII character to 6 bit pattern.
+//
+static unsigned char base64DecodeLookup[256] =
+{
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, 
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, 
+    xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, 
+    xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
+};
+
+//
+// Fundamental sizes of the binary and base64 encode/decode units in bytes
+//
+#define BINARY_UNIT_SIZE 3
+#define BASE64_UNIT_SIZE 4
+
+//
+// NewBase64Decode
+//
+// Decodes the base64 ASCII string in the inputBuffer to a newly malloced
+// output buffer.
+//
+//  inputBuffer - the source ASCII string for the decode
+//	length - the length of the string or -1 (to specify strlen should be used)
+//	outputLength - if not-NULL, on output will contain the decoded length
+//
+// returns the decoded buffer. Must be free'd by caller. Length is given by
+//	outputLength.
+//
+void *NewBase64Decode(
+	const char *inputBuffer,
+	size_t length,
+	size_t *outputLength)
+{
+	if (length == -1)
+	{
+		length = strlen(inputBuffer);
+	}
+	
+	size_t outputBufferSize =
+		((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;
+	unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);
+	
+	size_t i = 0;
+	size_t j = 0;
+	while (i < length)
+	{
+		//
+		// Accumulate 4 valid characters (ignore everything else)
+		//
+		unsigned char accumulated[BASE64_UNIT_SIZE];
+		size_t accumulateIndex = 0;
+		while (i < length)
+		{
+			unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
+			if (decode != xx)
+			{
+				accumulated[accumulateIndex] = decode;
+				accumulateIndex++;
+				
+				if (accumulateIndex == BASE64_UNIT_SIZE)
+				{
+					break;
+				}
+			}
+		}
+		
+		//
+		// Store the 6 bits from each of the 4 characters as 3 bytes
+		//
+		// (Uses improved bounds checking suggested by Alexandre Colucci)
+		//
+		if(accumulateIndex >= 2)  
+			outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);  
+		if(accumulateIndex >= 3)  
+			outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);  
+		if(accumulateIndex >= 4)  
+			outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
+		j += accumulateIndex - 1;
+	}
+	
+	if (outputLength)
+	{
+		*outputLength = j;
+	}
+	return outputBuffer;
+}
+
+//
+// NewBase64Encode
+//
+// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
+// output buffer.
+//
+//  inputBuffer - the source data for the encode
+//	length - the length of the input in bytes
+//  separateLines - if zero, no CR/LF characters will be added. Otherwise
+//		a CR/LF pair will be added every 64 encoded chars.
+//	outputLength - if not-NULL, on output will contain the encoded length
+//		(not including terminating 0 char)
+//
+// returns the encoded buffer. Must be free'd by caller. Length is given by
+//	outputLength.
+//
+char *NewBase64Encode(
+	const void *buffer,
+	size_t length,
+	bool separateLines,
+	size_t *outputLength)
+{
+	const unsigned char *inputBuffer = (const unsigned char *)buffer;
+	
+	#define MAX_NUM_PADDING_CHARS 2
+	#define OUTPUT_LINE_LENGTH 64
+	#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)
+	#define CR_LF_SIZE 2
+	
+	//
+	// Byte accurate calculation of final buffer size
+	//
+	size_t outputBufferSize =
+			((length / BINARY_UNIT_SIZE)
+				+ ((length % BINARY_UNIT_SIZE) ? 1 : 0))
+					* BASE64_UNIT_SIZE;
+	if (separateLines)
+	{
+		outputBufferSize +=
+			(outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
+	}
+	
+	//
+	// Include space for a terminating zero
+	//
+	outputBufferSize += 1;
+
+	//
+	// Allocate the output buffer
+	//
+	char *outputBuffer = (char *)malloc(outputBufferSize);
+	if (!outputBuffer)
+	{
+		return NULL;
+	}
+
+	size_t i = 0;
+	size_t j = 0;
+	const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
+	size_t lineEnd = lineLength;
+	
+	while (true)
+	{
+		if (lineEnd > length)
+		{
+			lineEnd = length;
+		}
+
+		for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE)
+		{
+			//
+			// Inner loop: turn 48 bytes into 64 base64 characters
+			//
+			outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
+			outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
+				| ((inputBuffer[i + 1] & 0xF0) >> 4)];
+			outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
+				| ((inputBuffer[i + 2] & 0xC0) >> 6)];
+			outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];
+		}
+		
+		if (lineEnd == length)
+		{
+			break;
+		}
+		
+		//
+		// Add the newline
+		//
+		outputBuffer[j++] = '\r';
+		outputBuffer[j++] = '\n';
+		lineEnd += lineLength;
+	}
+	
+	if (i + 1 < length)
+	{
+		//
+		// Handle the single '=' case
+		//
+		outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
+		outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
+			| ((inputBuffer[i + 1] & 0xF0) >> 4)];
+		outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
+		outputBuffer[j++] =	'=';
+	}
+	else if (i < length)
+	{
+		//
+		// Handle the double '=' case
+		//
+		outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
+		outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
+		outputBuffer[j++] = '=';
+		outputBuffer[j++] = '=';
+	}
+	outputBuffer[j] = 0;
+	
+	//
+	// Set the output length and return the buffer
+	//
+	if (outputLength)
+	{
+		*outputLength = j;
+	}
+	return outputBuffer;
+}
+
+@implementation NSData (Base64)
+
+//
+// dataFromBase64String:
+//
+// Creates an NSData object containing the base64 decoded representation of
+// the base64 string 'aString'
+//
+// Parameters:
+//    aString - the base64 string to decode
+//
+// returns the autoreleased NSData representation of the base64 string
+//
++ (NSData *)dataFromBase64String:(NSString *)aString
+{
+	NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];
+	size_t outputLength;
+	void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);
+	NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];
+	free(outputBuffer);
+	return result;
+}
+
+//
+// base64EncodedString
+//
+// Creates an NSString object that contains the base 64 encoding of the
+// receiver's data. Lines are broken at 64 characters long.
+//
+// returns an autoreleased NSString being the base 64 representation of the
+//	receiver.
+//
+- (NSString *)base64EncodedString
+{
+	size_t outputLength;
+	char *outputBuffer =
+		NewBase64Encode([self bytes], [self length], false, &outputLength);
+	
+	NSString *result =
+		[[NSString alloc]
+			initWithBytes:outputBuffer
+			length:outputLength
+			encoding:NSASCIIStringEncoding];
+	free(outputBuffer);
+	return result;
+}
+
+@end

+ 25 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSDate+RFC1123.h

@@ -0,0 +1,25 @@
+//
+//  NSDate+RFC1123.h
+//  MKNetworkKit
+//
+//  Created by Marcus Rohrmoser
+//  http://blog.mro.name/2009/08/nsdateformatter-http-header/
+//  http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
+
+//  No obvious license attached
+
+@interface NSDate (RFC1123)
+/**
+ Convert a RFC1123 'Full-Date' string
+ (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1)
+ into NSDate.
+ */
++(NSDate*)dateFromRFC1123:(NSString*)value_;
+
+/**
+ Convert NSDate into a RFC1123 'Full-Date' string
+ (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1).
+ */
+-(NSString*)rfc1123String;
+
+@end

+ 79 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSDate+RFC1123.m

@@ -0,0 +1,79 @@
+//
+//  NSDate+RFC1123.m
+//  MKNetworkKit
+//
+//  Created by Marcus Rohrmoser
+//  http://blog.mro.name/2009/08/nsdateformatter-http-header/
+//
+//  No obvious license attached
+
+#import "NSDate+RFC1123.h"
+
+@implementation NSDate (RFC1123)
+
++(NSDate*)dateFromRFC1123:(NSString*)value_
+{
+    if(value_ == nil)
+        return nil;    
+    
+    __strong static NSDateFormatter *rfc1123 = nil;
+    if (!rfc1123) {
+        static dispatch_once_t oncePredicate;
+        dispatch_once(&oncePredicate, ^{
+            rfc1123 = [[NSDateFormatter alloc] init];
+            rfc1123.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
+            rfc1123.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
+            rfc1123.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss z";
+        });
+    }
+    NSDate *ret = [rfc1123 dateFromString:value_];
+    if(ret != nil)
+        return ret;
+    
+    static NSDateFormatter *rfc850 = nil;
+    if(!rfc850)
+    {
+        static dispatch_once_t oncePredicate;
+        dispatch_once(&oncePredicate, ^{
+            rfc850 = [[NSDateFormatter alloc] init];
+            rfc850.locale = rfc1123.locale;
+            rfc850.timeZone = rfc1123.timeZone;
+            rfc850.dateFormat = @"EEEE',' dd'-'MMM'-'yy HH':'mm':'ss z";
+        });
+    }
+    ret = [rfc850 dateFromString:value_];
+    if(ret != nil)
+        return ret;
+    
+    static NSDateFormatter *asctime = nil;
+    if(!asctime)
+    {
+        static dispatch_once_t oncePredicate;
+        dispatch_once(&oncePredicate, ^{
+            
+            asctime = [[NSDateFormatter alloc] init];
+            asctime.locale = rfc1123.locale;
+            asctime.timeZone = rfc1123.timeZone;
+            asctime.dateFormat = @"EEE MMM d HH':'mm':'ss yyyy";
+        });
+    }
+    return [asctime dateFromString:value_];
+}
+
+-(NSString*)rfc1123String
+{
+    static NSDateFormatter *df = nil;
+    if(!df)
+    {
+        static dispatch_once_t oncePredicate;
+        dispatch_once(&oncePredicate, ^{
+            df = [[NSDateFormatter alloc] init];
+            df.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
+            df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
+            df.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
+        });
+    }
+    return [df stringFromDate:self];
+}
+
+@end

+ 31 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSDictionary+RequestEncoding.h

@@ -0,0 +1,31 @@
+//
+//  NSDictionary+RequestEncoding.h
+//  MKNetworkKitDemo
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+@interface NSDictionary (RequestEncoding)
+
+-(NSString*) urlEncodedKeyValueString;
+-(NSString*) jsonEncodedKeyValueString;
+-(NSString*) plistEncodedKeyValueString;
+@end

+ 79 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSDictionary+RequestEncoding.m

@@ -0,0 +1,79 @@
+//
+//  NSDictionary+RequestEncoding.m
+//  MKNetworkKitDemo
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#import "MKNetworkKit.h"
+
+@implementation NSDictionary (RequestEncoding)
+
+-(NSString*) urlEncodedKeyValueString {
+  
+  NSMutableString *string = [NSMutableString string];
+  for (NSString *key in self) {
+    
+    NSObject *value = [self valueForKey:key];
+    if([value isKindOfClass:[NSString class]])
+      [string appendFormat:@"%@=%@&", [key urlEncodedString], [((NSString*)value) urlEncodedString]];
+    else
+      [string appendFormat:@"%@=%@&", [key urlEncodedString], value];
+  }
+  
+  if([string length] > 0)
+    [string deleteCharactersInRange:NSMakeRange([string length] - 1, 1)];
+  
+  return string;    
+}
+
+
+-(NSString*) jsonEncodedKeyValueString {
+  
+  if(NSClassFromString(@"NSJSONSerialization")) {
+    NSError *error = nil;
+    NSData *data = [NSClassFromString(@"NSJSONSerialization") dataWithJSONObject:self
+                                                                         options:0 // non-pretty printing
+                                                                           error:&error];
+    if(error)
+      DLog(@"JSON Parsing Error: %@", error);
+    
+    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+  } else {
+    DLog(@"JSON encoder missing, falling back to URL encoding");
+    return [self urlEncodedKeyValueString];
+  }
+}
+
+
+-(NSString*) plistEncodedKeyValueString {
+  
+  NSError *error = nil;    
+  NSData *data = [NSPropertyListSerialization dataWithPropertyList:self 
+                                                            format:NSPropertyListXMLFormat_v1_0 
+                                                           options:0 error:&error];
+  if(error)
+    DLog(@"JSON Parsing Error: %@", error);
+  
+  return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];    
+}
+
+@end

+ 32 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSString+MKNetworkKitAdditions.h

@@ -0,0 +1,32 @@
+//
+//  NSString+MKNetworkKitAdditions.h
+//  MKNetworkKitDemo
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+@interface NSString (MKNetworkKitAdditions)
+
+- (NSString *) md5;
++ (NSString*) uniqueString;
+- (NSString*) urlEncodedString;
+- (NSString*) urlDecodedString;
+@end

+ 81 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/NSString+MKNetworkKitAdditions.m

@@ -0,0 +1,81 @@
+//
+//  NSString+MKNetworkKitAdditions.m
+//  MKNetworkKitDemo
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#import "NSString+MKNetworkKitAdditions.h"
+#import <CommonCrypto/CommonDigest.h>
+
+@implementation NSString (MKNetworkKitAdditions)
+
+- (NSString *) md5
+{
+    const char *cStr = [self UTF8String];
+    unsigned char result[16];
+    CC_MD5( cStr, (unsigned int) strlen(cStr), result);
+    return [NSString stringWithFormat:
+			@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+			result[0], result[1], result[2], result[3], 
+			result[4], result[5], result[6], result[7],
+			result[8], result[9], result[10], result[11],
+			result[12], result[13], result[14], result[15]
+			];      
+}
+
++ (NSString*) uniqueString
+{
+	CFUUIDRef	uuidObj = CFUUIDCreate(nil);
+	NSString	*uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(nil, uuidObj);
+	CFRelease(uuidObj);
+	return uuidString;
+}
+
+- (NSString*) urlEncodedString {
+    
+    CFStringRef encodedCFString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
+                                                                        (__bridge CFStringRef) self, 
+                                                                        nil,
+                                                                        CFSTR("?!@#$^&%*+,:;='\"`<>()[]{}/\\| "), 
+                                                                        kCFStringEncodingUTF8);
+    
+    NSString *encodedString = [[NSString alloc] initWithString:(__bridge_transfer NSString*) encodedCFString];    
+
+    if(!encodedString)
+        encodedString = @"";    
+    
+    return encodedString;
+}
+
+- (NSString*) urlDecodedString {
+
+    CFStringRef decodedCFString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, 
+                                                                                          (__bridge CFStringRef) self, 
+                                                                                          CFSTR(""),
+                                                                                          kCFStringEncodingUTF8);
+    
+    // We need to replace "+" with " " because the CF method above doesn't do it
+    NSString *decodedString = [[NSString alloc] initWithString:(__bridge_transfer NSString*) decodedCFString];    
+    return (!decodedString) ? @"" : [decodedString stringByReplacingOccurrencesOfString:@"+" withString:@" "];
+}
+
+@end

+ 31 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/UIAlertView+MKNetworkKitAdditions.h

@@ -0,0 +1,31 @@
+//
+//  UIAlertView+MKNetworkKitAdditions.h
+//  MKNetworkKitDemo
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+#if TARGET_OS_IPHONE
+#import <UIKit/UIKit.h>
+
+@interface UIAlertView (MKNetworkKitAdditions)
++(UIAlertView*) showWithError:(NSError*) networkError;
+@end
+#endif

+ 41 - 0
Pods/MKNetworkKit/MKNetworkKit/Categories/UIAlertView+MKNetworkKitAdditions.m

@@ -0,0 +1,41 @@
+//
+//  UIAlertView+MKNetworkKitAdditions.m
+//  MKNetworkKitDemo
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+#if TARGET_OS_IPHONE
+#import "UIAlertView+MKNetworkKitAdditions.h"
+
+@implementation UIAlertView (MKNetworkKitAdditions)
+
++(UIAlertView*) showWithError:(NSError*) networkError {
+
+    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[networkError localizedDescription]
+                                                    message:[networkError localizedRecoverySuggestion]
+                                                   delegate:nil
+                                          cancelButtonTitle:NSLocalizedString(@"Dismiss", @"")
+                                          otherButtonTitles:nil];
+    [alert show];
+    return alert;
+}
+@end
+#endif

+ 324 - 0
Pods/MKNetworkKit/MKNetworkKit/MKNetworkEngine.h

@@ -0,0 +1,324 @@
+//
+//  MKNetworkEngine.h
+//  MKNetworkKit
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#import "MKNetworkKit.h"
+/*!
+ @header MKNetworkEngine.h
+ @abstract   Represents a subclassable Network Engine for your app
+ */
+
+/*!
+ *  @class MKNetworkEngine
+ *  @abstract Represents a subclassable Network Engine for your app
+ *  
+ *  @discussion
+ *	This class is the heart of MKNetworkEngine
+ *  You create network operations and enqueue them here
+ *  MKNetworkEngine encapsulates a Reachability object that relieves you of managing network connectivity losses
+ *  MKNetworkEngine also allows you to provide custom header fields that gets appended automatically to every request
+ */
+@interface MKNetworkEngine : NSObject
+
+/*!
+ *  @abstract Initializes your network engine with a hostname
+ *  
+ *  @discussion
+ *	Creates an engine for a given host name
+ *  The hostname parameter is optional
+ *  The hostname, if not null, initializes a Reachability notifier.
+ *  Network reachability notifications are automatically taken care of by MKNetworkEngine
+ *  
+ */
+- (id) initWithHostName:(NSString*) hostName;
+/*!
+ *  @abstract Initializes your network engine with a hostname and custom header fields
+ *  
+ *  @discussion
+ *	Creates an engine for a given host name
+ *  The default headers you specify here will be appened to every operation created in this engine
+ *  The hostname, if not null, initializes a Reachability notifier.
+ *  Network reachability notifications are automatically taken care of by MKNetworkEngine
+ *  Both parameters are optional
+ *  
+ */
+- (id) initWithHostName:(NSString*) hostName customHeaderFields:(NSDictionary*) headers;
+
+/*!
+ *  @abstract Initializes your network engine with a hostname
+ *  
+ *  @discussion
+ *	Creates an engine for a given host name
+ *  The hostname parameter is optional
+ *  The apiPath paramter is optional
+ *  The apiPath is prefixed to every call to operationWithPath: You can use this method if your server's API location is not at the root (/)
+ *  The hostname, if not null, initializes a Reachability notifier.
+ *  Network reachability notifications are automatically taken care of by MKNetworkEngine
+ *  
+ */
+- (id) initWithHostName:(NSString*) hostName apiPath:(NSString*) apiPath customHeaderFields:(NSDictionary*) headers;
+/*!
+ *  @abstract Creates a simple GET Operation with a request URL
+ *  
+ *  @discussion
+ *	Creates an operation with the given URL path.
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The HTTP Method is implicitly assumed to be GET
+ *  
+ */
+
+-(MKNetworkOperation*) operationWithPath:(NSString*) path;
+
+/*!
+ *  @abstract Creates a simple GET Operation with a request URL and parameters
+ *  
+ *  @discussion
+ *	Creates an operation with the given URL path.
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The body dictionary in this method gets attached to the URL as query parameters
+ *  The HTTP Method is implicitly assumed to be GET
+ *  
+ */
+-(MKNetworkOperation*) operationWithPath:(NSString*) path
+                         params:(NSMutableDictionary*) body;
+
+/*!
+ *  @abstract Creates a simple GET Operation with a request URL, parameters and HTTP Method
+ *  
+ *  @discussion
+ *	Creates an operation with the given URL path.
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The params dictionary in this method gets attached to the URL as query parameters if the HTTP Method is GET/DELETE
+ *  The params dictionary is attached to the body if the HTTP Method is POST/PUT
+ *  The HTTP Method is implicitly assumed to be GET
+ */
+-(MKNetworkOperation*) operationWithPath:(NSString*) path
+                         params:(NSMutableDictionary*) body
+                   httpMethod:(NSString*)method;
+
+/*!
+ *  @abstract Creates a simple GET Operation with a request URL, parameters, HTTP Method and the SSL switch
+ *  
+ *  @discussion
+ *	Creates an operation with the given URL path.
+ *  The ssl option when true changes the URL to https.
+ *  The ssl option when false changes the URL to http.
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The params dictionary in this method gets attached to the URL as query parameters if the HTTP Method is GET/DELETE
+ *  The params dictionary is attached to the body if the HTTP Method is POST/PUT
+ *  The previously mentioned methods operationWithPath: and operationWithPath:params: call this internally
+ */
+-(MKNetworkOperation*) operationWithPath:(NSString*) path
+                         params:(NSMutableDictionary*) body
+                   httpMethod:(NSString*)method 
+                          ssl:(BOOL) useSSL;
+
+
+/*!
+ *  @abstract Creates a simple GET Operation with a request URL
+ *  
+ *  @discussion
+ *	Creates an operation with the given absolute URL.
+ *  The hostname of the engine is *NOT* prefixed
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The HTTP method is implicitly assumed to be GET.
+ */
+-(MKNetworkOperation*) operationWithURLString:(NSString*) urlString;
+
+/*!
+ *  @abstract Creates a simple GET Operation with a request URL and parameters
+ *  
+ *  @discussion
+ *	Creates an operation with the given absolute URL.
+ *  The hostname of the engine is *NOT* prefixed
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The body dictionary in this method gets attached to the URL as query parameters
+ *  The HTTP method is implicitly assumed to be GET.
+ */
+-(MKNetworkOperation*) operationWithURLString:(NSString*) urlString
+                                       params:(NSMutableDictionary*) body;
+
+/*!
+ *  @abstract Creates a simple Operation with a request URL, parameters and HTTP Method
+ *  
+ *  @discussion
+ *	Creates an operation with the given absolute URL.
+ *  The hostname of the engine is *NOT* prefixed
+ *  The default headers you specified in your MKNetworkEngine subclass gets added to the headers
+ *  The params dictionary in this method gets attached to the URL as query parameters if the HTTP Method is GET/DELETE
+ *  The params dictionary is attached to the body if the HTTP Method is POST/PUT
+ *	This method can be over-ridden by subclasses to tweak the operation creation mechanism.
+ *  You would typically over-ride this method to create a subclass of MKNetworkOperation (if you have one). After you create it, you should call [super prepareHeaders:operation] to attach any custom headers from super class.
+ *  @seealso
+ *  prepareHeaders:
+ */
+-(MKNetworkOperation*) operationWithURLString:(NSString*) urlString
+                              params:(NSMutableDictionary*) body
+                        httpMethod:(NSString*) method;
+
+/*!
+ *  @abstract adds the custom default headers
+ *  
+ *  @discussion
+ *	This method adds custom default headers to the factory created MKNetworkOperation.
+ *	This method can be over-ridden by subclasses to add more default headers if necessary.
+ *  You would typically over-ride this method if you have over-ridden operationWithURLString:params:httpMethod:.
+ *  @seealso
+ *  operationWithURLString:params:httpMethod:
+ */
+
+-(void) prepareHeaders:(MKNetworkOperation*) operation;
+/*!
+ *  @abstract Handy helper method for fetching images
+ *  
+ *  @discussion
+ *	Creates an operation with the given image URL.
+ *  The hostname of the engine is *NOT* prefixed.
+ *  The image is returned to the caller via MKNKImageBlock callback block. 
+ */
+- (MKNetworkOperation*)imageAtURL:(NSURL *)url onCompletion:(MKNKImageBlock) imageFetchedBlock;
+/*!
+ *  @abstract Enqueues your operation into the shared queue
+ *  
+ *  @discussion
+ *	The operation you created is enqueued to the shared queue. If the response for this operation was previously cached, the cached data will be returned.
+ *  @seealso
+ *  enqueueOperation:forceReload:
+ */
+-(void) enqueueOperation:(MKNetworkOperation*) request;
+
+/*!
+ *  @abstract Enqueues your operation into the shared queue.
+ *  
+ *  @discussion
+ *	The operation you created is enqueued to the shared queue. 
+ *  When forceReload is NO, this method behaves like enqueueOperation:
+ *  When forceReload is YES, No cached data will be returned even if cached data is available.
+ *  @seealso
+ *  enqueueOperation:
+ */
+-(void) enqueueOperation:(MKNetworkOperation*) operation forceReload:(BOOL) forceReload;
+
+/*!
+ *  @abstract HostName of the engine
+ *  @property readonlyHostName
+ *  
+ *  @discussion
+ *	Returns the host name of the engine
+ *  This property is readonly cannot be updated. 
+ *  You normally initialize an engine with its hostname using the initWithHostName:customHeaders: method
+ */
+@property (readonly, strong, nonatomic) NSString *readonlyHostName;
+
+/*!
+ *  @abstract Port Number that should be used by URL creating factory methods
+ *  @property portNumber
+ *  
+ *  @discussion
+ *	Set a port number for your engine if your remote URL mandates it.
+ *  This property is optional and you DON'T have to specify the default HTTP port 80
+ */
+@property (assign, nonatomic) int portNumber;
+
+/*!
+ *  @abstract Sets an api path if it is different from root URL
+ *  @property apiPath
+ *  
+ *  @discussion
+ *	You can use this method to set a custom path to the API location if your server's API path is different from root (/) 
+ *  This property is optional
+ */
+@property (strong, nonatomic) NSString* apiPath;
+
+/*!
+ *  @abstract Handler that you implement to monitor reachability changes
+ *  @property reachabilityChangedHandler
+ *  
+ *  @discussion
+ *	The framework calls this handler whenever the reachability of the host changes.
+ *  The default implementation freezes the queued operations and stops network activity
+ *  You normally don't have to implement this unless you need to show a HUD notifying the user of connectivity loss
+ */
+@property (copy, nonatomic) void (^reachabilityChangedHandler)(NetworkStatus ns);
+
+/*!
+ *  @abstract Registers an associated operation subclass
+ *  
+ *  @discussion
+ *	When you override both MKNetworkEngine and MKNetworkOperation, you might want the engine's factory method
+ *  to prepare operations of your MKNetworkOperation subclass. To create your own MKNetworkOperation subclasses from the factory method, you can register your MKNetworkOperation subclass using this method.
+ *  This method is optional. If you don't use, factory methods in MKNetworkEngine creates MKNetworkOperation objects.
+ */
+-(void) registerOperationSubclass:(Class) aClass;
+/*!
+ *  @abstract Cache Directory Name
+ *  
+ *  @discussion
+ *	This method can be over-ridden by subclasses to provide an alternative cache directory
+ *  The default directory (MKNetworkKitCache) within the NSCaches directory will be used otherwise
+ *  Overriding this method is optional
+ */
+-(NSString*) cacheDirectoryName;
+
+/*!
+ *  @abstract Cache Directory In Memory Cost
+ *  
+ *  @discussion
+ *	This method can be over-ridden by subclasses to provide an alternative in memory cache size.
+ *  By default, MKNetworkKit caches 10 recent requests in memory
+ *  The default size is 10
+ *  Overriding this method is optional
+ */
+-(int) cacheMemoryCost;
+
+/*!
+ *  @abstract Enable Caching
+ *  
+ *  @discussion
+ *	This method should be called explicitly to enable caching for this engine.
+ *  By default, MKNetworkKit doens't cache your requests.
+ *  The cacheMemoryCost and cacheDirectoryName will be used when you turn caching on using this method.
+ */
+-(void) useCache;
+
+/*!
+ *  @abstract Empties previously cached data
+ *  
+ *  @discussion
+ *	This method is a handy helper that you can use to clear cached data.
+ *  By default, MKNetworkKit doens't cache your requests. Use this only when you enabled caching
+ *  @seealso
+ *  useCache
+ */
+-(void) emptyCache;
+
+/*!
+ *  @abstract Checks current reachable status
+ *  
+ *  @discussion
+ *	This method is a handy helper that you can use to check for network reachability.
+ */
+-(BOOL) isReachable;
+
+@end

+ 652 - 0
Pods/MKNetworkKit/MKNetworkKit/MKNetworkEngine.m

@@ -0,0 +1,652 @@
+//
+//  MKNetworkEngine.m
+//  MKNetworkKit
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#import "MKNetworkKit.h"
+#define kFreezableOperationExtension @"mknetworkkitfrozenoperation"
+
+#ifdef __OBJC_GC__
+#error MKNetworkKit does not support Objective-C Garbage Collection
+#endif
+
+#if ! __has_feature(objc_arc)
+#error MKNetworkKit is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
+#endif
+
+@interface MKNetworkEngine (/*Private Methods*/)
+
+@property (strong, nonatomic) NSString *hostName;
+@property (strong, nonatomic) Reachability *reachability;
+@property (strong, nonatomic) NSDictionary *customHeaders;
+@property (assign, nonatomic) Class customOperationSubclass;
+
+@property (nonatomic, strong) NSMutableDictionary *memoryCache;
+@property (nonatomic, strong) NSMutableArray *memoryCacheKeys;
+@property (nonatomic, strong) NSMutableDictionary *cacheInvalidationParams;
+
+-(void) saveCache;
+-(void) saveCacheData:(NSData*) data forKey:(NSString*) cacheDataKey;
+
+-(void) freezeOperations;
+-(void) checkAndRestoreFrozenOperations;
+
+-(BOOL) isCacheEnabled;
+@end
+
+static NSOperationQueue *_sharedNetworkQueue;
+
+@implementation MKNetworkEngine
+@synthesize hostName = _hostName;
+@synthesize reachability = _reachability;
+@synthesize customHeaders = _customHeaders;
+@synthesize customOperationSubclass = _customOperationSubclass;
+
+@synthesize memoryCache = _memoryCache;
+@synthesize memoryCacheKeys = _memoryCacheKeys;
+@synthesize cacheInvalidationParams = _cacheInvalidationParams;
+
+@synthesize reachabilityChangedHandler = _reachabilityChangedHandler;
+@synthesize portNumber = _portNumber;
+@synthesize apiPath = _apiPath;
+
+// Network Queue is a shared singleton object.
+// no matter how many instances of MKNetworkEngine is created, there is one and only one network queue
+// In theory an app should contain as many network engines as the number of domains it talks to
+
+#pragma mark -
+#pragma mark Initialization
+
++(void) initialize {
+  
+  if(!_sharedNetworkQueue) {
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+      _sharedNetworkQueue = [[NSOperationQueue alloc] init];
+      [_sharedNetworkQueue addObserver:[self self] forKeyPath:@"operationCount" options:0 context:NULL];
+      [_sharedNetworkQueue setMaxConcurrentOperationCount:6];
+      
+    });
+  }            
+}
+
+- (id) init {
+  
+  return [self initWithHostName:nil];
+}
+
+- (id) initWithHostName:(NSString*) hostName {
+  
+  return [self initWithHostName:hostName apiPath:nil customHeaderFields:nil];
+}
+
+- (id) initWithHostName:(NSString*) hostName apiPath:(NSString*) apiPath customHeaderFields:(NSDictionary*) headers {
+  
+  if((self = [super init])) {        
+    
+    self.apiPath = apiPath;
+
+    if(hostName) {
+      [[NSNotificationCenter defaultCenter] addObserver:self 
+                                               selector:@selector(reachabilityChanged:) 
+                                                   name:kReachabilityChangedNotification 
+                                                 object:nil];
+      
+      self.hostName = hostName;  
+      self.reachability = [Reachability reachabilityWithHostname:self.hostName];
+      [self.reachability startNotifier];            
+    }
+    
+    if([headers objectForKey:@"User-Agent"] == nil) {
+      
+      NSMutableDictionary *newHeadersDict = [headers mutableCopy];
+      NSString *userAgentString = [NSString stringWithFormat:@"%@/%@", 
+                                   [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleNameKey], 
+                                   [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey]];
+      [newHeadersDict setObject:userAgentString forKey:@"User-Agent"];
+      self.customHeaders = newHeadersDict;
+    } else {
+      self.customHeaders = headers;
+    }    
+    
+    self.customOperationSubclass = [MKNetworkOperation class];
+  }
+  
+  return self;  
+}
+
+- (id) initWithHostName:(NSString*) hostName customHeaderFields:(NSDictionary*) headers {
+  
+  return [self initWithHostName:hostName apiPath:nil customHeaderFields:headers];
+}
+
+#pragma mark -
+#pragma mark Memory Mangement
+
+-(void) dealloc {
+  
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
+#if TARGET_OS_IPHONE    
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
+#elif TARGET_OS_MAC
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillHideNotification object:nil];
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillResignActiveNotification object:nil];
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:nil];
+#endif
+
+}
+
++(void) dealloc {
+  
+  [_sharedNetworkQueue removeObserver:[self self] forKeyPath:@"operationCount"];
+}
+
+#pragma mark -
+#pragma mark KVO for network Queue
+
++ (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
+                         change:(NSDictionary *)change context:(void *)context
+{
+  if (object == _sharedNetworkQueue && [keyPath isEqualToString:@"operationCount"]) {
+    
+    [[NSNotificationCenter defaultCenter] postNotificationName:kMKNetworkEngineOperationCountChanged 
+                                                        object:[NSNumber numberWithInteger:[_sharedNetworkQueue operationCount]]];
+#if TARGET_OS_IPHONE
+    [UIApplication sharedApplication].networkActivityIndicatorVisible = 
+    ([_sharedNetworkQueue.operations count] > 0);        
+#endif
+  }
+  else {
+    [super observeValueForKeyPath:keyPath ofObject:object 
+                           change:change context:context];
+  }
+}
+
+#pragma mark -
+#pragma mark Reachability related
+
+-(void) reachabilityChanged:(NSNotification*) notification
+{
+  if([self.reachability currentReachabilityStatus] == ReachableViaWiFi)
+  {
+    DLog(@"Server [%@] is reachable via Wifi", self.hostName);
+    [_sharedNetworkQueue setMaxConcurrentOperationCount:6];
+    
+    [self checkAndRestoreFrozenOperations];
+  }
+  else if([self.reachability currentReachabilityStatus] == ReachableViaWWAN)
+  {
+    DLog(@"Server [%@] is reachable only via cellular data", self.hostName);
+    [_sharedNetworkQueue setMaxConcurrentOperationCount:2];
+    [self checkAndRestoreFrozenOperations];
+  }
+  else if([self.reachability currentReachabilityStatus] == NotReachable)
+  {
+    DLog(@"Server [%@] is not reachable", self.hostName);        
+    [self freezeOperations];
+  }   
+  
+  if(self.reachabilityChangedHandler) {
+    self.reachabilityChangedHandler([self.reachability currentReachabilityStatus]);
+  }
+}
+
+#pragma mark Freezing operations (Called when network connectivity fails)
+-(void) freezeOperations {
+  
+  if(![self isCacheEnabled]) return;
+  
+  for(MKNetworkOperation *operation in _sharedNetworkQueue.operations) {
+    
+    // freeze only freeable operations.
+    if(![operation freezable]) continue;
+    
+    if(!self.hostName) return;
+    
+    // freeze only operations that belong to this server
+    if([[operation url] rangeOfString:self.hostName].location == NSNotFound) continue;
+    
+    NSString *archivePath = [[[self cacheDirectoryName] stringByAppendingPathComponent:[operation uniqueIdentifier]] 
+                             stringByAppendingPathExtension:kFreezableOperationExtension];
+    [NSKeyedArchiver archiveRootObject:operation toFile:archivePath];
+    [operation cancel];
+  }
+  
+}
+
+-(void) checkAndRestoreFrozenOperations {
+  
+  if(![self isCacheEnabled]) return;
+  
+  NSError *error = nil;
+  NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self cacheDirectoryName] error:&error];
+  if(error)
+    DLog(@"%@", error);
+  
+  NSArray *pendingOperations = [files filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
+    
+    NSString *thisFile = (NSString*) evaluatedObject;
+    return ([thisFile rangeOfString:kFreezableOperationExtension].location != NSNotFound);             
+  }]];
+  
+  for(NSString *pendingOperationFile in pendingOperations) {
+    
+    NSString *archivePath = [[self cacheDirectoryName] stringByAppendingPathComponent:pendingOperationFile];
+    MKNetworkOperation *pendingOperation = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
+    [self enqueueOperation:pendingOperation];
+    NSError *error = nil;
+    [[NSFileManager defaultManager] removeItemAtPath:archivePath error:&error];
+    if(error)
+      DLog(@"%@", error);
+  }
+}
+
+-(NSString*) readonlyHostName {
+  
+  return [_hostName copy];
+}
+
+-(BOOL) isReachable {
+  
+  return ([self.reachability currentReachabilityStatus] != NotReachable);
+}
+
+#pragma mark -
+#pragma mark Create methods
+
+-(void) registerOperationSubclass:(Class) aClass {
+  
+  self.customOperationSubclass = aClass;
+}
+
+-(MKNetworkOperation*) operationWithPath:(NSString*) path {
+  
+  return [self operationWithPath:path params:nil];
+}
+
+-(MKNetworkOperation*) operationWithPath:(NSString*) path
+                                  params:(NSMutableDictionary*) body {
+  
+  return [self operationWithPath:path 
+                          params:body 
+                      httpMethod:@"GET"];
+}
+
+-(MKNetworkOperation*) operationWithPath:(NSString*) path
+                                  params:(NSMutableDictionary*) body
+                              httpMethod:(NSString*)method  {
+  
+  return [self operationWithPath:path params:body httpMethod:method ssl:NO];
+}
+
+-(MKNetworkOperation*) operationWithPath:(NSString*) path
+                                  params:(NSMutableDictionary*) body
+                              httpMethod:(NSString*)method 
+                                     ssl:(BOOL) useSSL {
+  
+  if(self.hostName == nil) {
+   
+    DLog(@"Hostname is nil, use operationWithURLString: method to create absolute URL operations");
+    return nil;
+  }
+  
+  NSMutableString *urlString = [NSMutableString stringWithFormat:@"%@://%@", useSSL ? @"https" : @"http", self.hostName];
+
+  if(self.portNumber != 0)
+    [urlString appendFormat:@":%d", self.portNumber];
+  
+  if(self.apiPath) 
+    [urlString appendFormat:@"/%@", self.apiPath];
+  
+  [urlString appendFormat:@"/%@", path];
+  
+  return [self operationWithURLString:urlString params:body httpMethod:method];
+}
+
+-(MKNetworkOperation*) operationWithURLString:(NSString*) urlString {
+  
+  return [self operationWithURLString:urlString params:nil httpMethod:@"GET"];
+}
+
+-(MKNetworkOperation*) operationWithURLString:(NSString*) urlString
+                                       params:(NSMutableDictionary*) body {
+  
+  return [self operationWithURLString:urlString params:body httpMethod:@"GET"];
+}
+
+
+-(MKNetworkOperation*) operationWithURLString:(NSString*) urlString
+                                       params:(NSMutableDictionary*) body
+                                   httpMethod:(NSString*)method {
+  
+  MKNetworkOperation *operation = [[self.customOperationSubclass alloc] initWithURLString:urlString params:body httpMethod:method];
+  
+  [self prepareHeaders:operation];
+  return operation;
+}
+
+-(void) prepareHeaders:(MKNetworkOperation*) operation {
+  
+  [operation addHeaders:self.customHeaders];
+}
+
+-(NSData*) cachedDataForOperation:(MKNetworkOperation*) operation {
+  
+  NSData *cachedData = [self.memoryCache objectForKey:[operation uniqueIdentifier]];
+  if(cachedData) return cachedData;
+  
+  NSString *filePath = [[self cacheDirectoryName] stringByAppendingPathComponent:[operation uniqueIdentifier]];    
+  
+  if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
+    
+    cachedData = [NSData dataWithContentsOfFile:filePath];
+    [self saveCacheData:cachedData forKey:[operation uniqueIdentifier]]; // bring it back to the in-memory cache
+    return cachedData;
+  }
+  
+  return nil;
+}
+
+-(void) enqueueOperation:(MKNetworkOperation*) operation {
+  
+  [self enqueueOperation:operation forceReload:NO];
+}
+
+-(void) enqueueOperation:(MKNetworkOperation*) operation forceReload:(BOOL) forceReload {
+  
+  NSParameterAssert(operation != nil);
+  // Grab on to the current queue (We need it later)
+  dispatch_queue_t originalQueue = dispatch_get_current_queue();
+#if DO_GCD_RETAIN_RELEASE
+  dispatch_retain(originalQueue);
+#endif
+  // Jump off the main thread, mainly for disk cache reading purposes
+  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+    [operation setCacheHandler:^(MKNetworkOperation* completedCacheableOperation) {
+      
+      // if this is not called, the request would have been a non cacheable request
+      //completedCacheableOperation.cacheHeaders;
+      NSString *uniqueId = [completedCacheableOperation uniqueIdentifier];
+      [self saveCacheData:[completedCacheableOperation responseData] 
+                   forKey:uniqueId];
+      
+      [self.cacheInvalidationParams setObject:completedCacheableOperation.cacheHeaders forKey:uniqueId];
+    }];
+    
+    __block double expiryTimeInSeconds = 0.0f;    
+
+    if([operation isCacheable]) {
+
+    if(!forceReload) {
+      NSData *cachedData = [self cachedDataForOperation:operation];
+      if(cachedData) {
+        dispatch_async(originalQueue, ^{
+          // Jump back to the original thread here since setCachedData updates the main thread
+          [operation setCachedData:cachedData];                    
+        });
+        
+        
+        NSString *uniqueId = [operation uniqueIdentifier];
+        NSMutableDictionary *savedCacheHeaders = [self.cacheInvalidationParams objectForKey:uniqueId];
+        // there is a cached version.
+        // this means, the current operation is a "GET"
+        if(savedCacheHeaders) {
+          NSString *expiresOn = [savedCacheHeaders objectForKey:@"Expires"];
+          
+          dispatch_sync(originalQueue, ^{
+            NSDate *expiresOnDate = [NSDate dateFromRFC1123:expiresOn];
+            expiryTimeInSeconds = [expiresOnDate timeIntervalSinceNow];
+          });
+          
+          [operation updateOperationBasedOnPreviousHeaders:savedCacheHeaders];
+        }
+      }
+    }
+    
+    dispatch_async(originalQueue, ^{
+      
+      NSUInteger index = [_sharedNetworkQueue.operations indexOfObject:operation];
+      if(index == NSNotFound) {
+        
+        if(expiryTimeInSeconds <= 0)
+          [_sharedNetworkQueue addOperation:operation];
+        else if(forceReload)
+          [_sharedNetworkQueue addOperation:operation];
+        // else don't do anything
+      }
+      else {
+        // This operation is already being processed
+        MKNetworkOperation *queuedOperation = (MKNetworkOperation*) [_sharedNetworkQueue.operations objectAtIndex:index];
+        [queuedOperation updateHandlersFromOperation:operation];
+      }
+      
+      
+    });
+    } else {
+      
+      [_sharedNetworkQueue addOperation:operation];
+    }
+
+    if([self.reachability currentReachabilityStatus] == NotReachable)
+      [self freezeOperations];
+#if DO_GCD_RETAIN_RELEASE
+    dispatch_release(originalQueue);
+#endif
+  });
+}
+
+- (MKNetworkOperation*)imageAtURL:(NSURL *)url onCompletion:(MKNKImageBlock) imageFetchedBlock
+{
+#ifdef DEBUG
+  // I could enable caching here, but that hits performance and inturn affects table view scrolling
+  // if imageAtURL is called for loading thumbnails.
+  if(![self isCacheEnabled]) DLog(@"imageAtURL:onCompletion: requires caching to be enabled.")
+#endif
+    
+    if (url == nil) {
+      return nil;
+    }
+  
+  MKNetworkOperation *op = [self operationWithURLString:[url absoluteString]];
+  
+  [op 
+   onCompletion:^(MKNetworkOperation *completedOperation)
+   {
+     imageFetchedBlock([completedOperation responseImage], 
+                       url,
+                       [completedOperation isCachedResponse]);
+     
+   }
+   onError:^(NSError* error) {
+     
+     DLog(@"%@", error);
+   }];    
+  
+  [self enqueueOperation:op];
+  
+  return op;
+}
+
+#pragma mark -
+#pragma mark Cache related
+
+-(NSString*) cacheDirectoryName {
+  
+  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+  NSString *documentsDirectory = [paths objectAtIndex:0];
+  NSString *cacheDirectoryName = [documentsDirectory stringByAppendingPathComponent:MKNETWORKCACHE_DEFAULT_DIRECTORY];
+  return cacheDirectoryName;
+}
+
+-(int) cacheMemoryCost {
+  
+  return MKNETWORKCACHE_DEFAULT_COST;
+}
+
+-(void) saveCache {
+  
+  for(NSString *cacheKey in [self.memoryCache allKeys])
+  {
+    NSString *filePath = [[self cacheDirectoryName] stringByAppendingPathComponent:cacheKey];
+    if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
+      
+      NSError *error = nil;
+      [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; 
+      ELog(error);
+    }
+    
+    [[self.memoryCache objectForKey:cacheKey] writeToFile:filePath atomically:YES];        
+  }
+  
+  [self.memoryCache removeAllObjects];
+  [self.memoryCacheKeys removeAllObjects];
+  
+  NSString *cacheInvalidationPlistFilePath = [[self cacheDirectoryName] stringByAppendingPathExtension:@"plist"];
+  [self.cacheInvalidationParams writeToFile:cacheInvalidationPlistFilePath atomically:YES];
+}
+
+-(void) saveCacheData:(NSData*) data forKey:(NSString*) cacheDataKey
+{    
+  @synchronized(self) {
+    [self.memoryCache setObject:data forKey:cacheDataKey];
+    
+    NSUInteger index = [self.memoryCacheKeys indexOfObject:cacheDataKey];
+    if(index != NSNotFound)
+      [self.memoryCacheKeys removeObjectAtIndex:index];    
+    
+    [self.memoryCacheKeys insertObject:cacheDataKey atIndex:0]; // remove it and insert it at start
+    
+    if([self.memoryCacheKeys count] >= [self cacheMemoryCost])
+    {
+      NSString *lastKey = [self.memoryCacheKeys lastObject];        
+      NSData *data = [self.memoryCache objectForKey:lastKey];        
+      NSString *filePath = [[self cacheDirectoryName] stringByAppendingPathComponent:lastKey];
+      
+      if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
+        
+        NSError *error = nil;
+        [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; 
+        ELog(error);
+      }
+      [data writeToFile:filePath atomically:YES];
+      
+      [self.memoryCacheKeys removeLastObject];
+      [self.memoryCache removeObjectForKey:lastKey];        
+    }
+  }
+}
+
+/*
+ - (BOOL) dataOldness:(NSString*) imagePath
+ {
+ NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:imagePath error:nil];
+ NSDate *creationDate = [attributes valueForKey:NSFileCreationDate];
+ 
+ return abs([creationDate timeIntervalSinceNow]);
+ }*/
+
+-(BOOL) isCacheEnabled {
+  
+  BOOL isDir = NO;
+  BOOL isCachingEnabled = [[NSFileManager defaultManager] fileExistsAtPath:[self cacheDirectoryName] isDirectory:&isDir];
+  return isCachingEnabled;
+}
+
+-(void) useCache {
+  
+  self.memoryCache = [NSMutableDictionary dictionaryWithCapacity:[self cacheMemoryCost]];
+  self.memoryCacheKeys = [NSMutableArray arrayWithCapacity:[self cacheMemoryCost]];
+  self.cacheInvalidationParams = [NSMutableDictionary dictionary];
+  
+  NSString *cacheDirectory = [self cacheDirectoryName];
+  BOOL isDirectory = YES;
+  BOOL folderExists = [[NSFileManager defaultManager] fileExistsAtPath:cacheDirectory isDirectory:&isDirectory] && isDirectory;
+  
+  if (!folderExists)
+  {
+    NSError *error = nil;
+    [[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:YES attributes:nil error:&error];
+  }
+  
+  NSString *cacheInvalidationPlistFilePath = [cacheDirectory stringByAppendingPathExtension:@"plist"];
+  
+  BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:cacheInvalidationPlistFilePath];
+  
+  if (fileExists)
+  {
+    self.cacheInvalidationParams = [NSMutableDictionary dictionaryWithContentsOfFile:cacheInvalidationPlistFilePath];
+  }
+  
+#if TARGET_OS_IPHONE        
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCache)
+                                               name:UIApplicationDidReceiveMemoryWarningNotification
+                                             object:nil];
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCache)
+                                               name:UIApplicationDidEnterBackgroundNotification
+                                             object:nil];
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCache)
+                                               name:UIApplicationWillTerminateNotification
+                                             object:nil];
+  
+#elif TARGET_OS_MAC
+  
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCache)
+                                               name:NSApplicationWillHideNotification
+                                             object:nil];
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCache)
+                                               name:NSApplicationWillResignActiveNotification
+                                             object:nil];
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCache)
+                                               name:NSApplicationWillTerminateNotification
+                                             object:nil];
+  
+#endif
+  
+  
+}
+
+-(void) emptyCache {
+  
+  [self saveCache]; // ensures that invalidation params are written to disk properly
+  NSError *error = nil;
+  NSArray *directoryContents = [[NSFileManager defaultManager] 
+                                contentsOfDirectoryAtPath:[self cacheDirectoryName] error:&error];
+  if(error) DLog(@"%@", error);
+  
+  error = nil;
+  for(NSString *fileName in directoryContents) {
+    
+    NSString *path = [[self cacheDirectoryName] stringByAppendingPathComponent:fileName];
+    [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
+    if(error) DLog(@"%@", error);
+  }    
+  
+  error = nil;
+  NSString *cacheInvalidationPlistFilePath = [[self cacheDirectoryName] stringByAppendingPathExtension:@"plist"];
+  [[NSFileManager defaultManager] removeItemAtPath:cacheInvalidationPlistFilePath error:&error];
+  if(error) DLog(@"%@", error);
+}
+
+@end

+ 102 - 0
Pods/MKNetworkKit/MKNetworkKit/MKNetworkKit.h

@@ -0,0 +1,102 @@
+//
+//  MKNetworkKit.h
+//  MKNetworkKit
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#ifndef MKNetworkKit_MKNetworkKit_h
+#define MKNetworkKit_MKNetworkKit_h
+
+#ifndef __IPHONE_4_0
+#error "MKNetworkKit uses features only available in iOS SDK 4.0 and later."
+#endif
+
+#if TARGET_OS_IPHONE
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
+#define DO_GCD_RETAIN_RELEASE 0
+#else
+#define DO_GCD_RETAIN_RELEASE 1
+#endif
+#elif TARGET_OS_MAC
+#import <Cocoa/Cocoa.h>
+#import <AppKit/AppKit.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
+#define DO_GCD_RETAIN_RELEASE 0
+#else
+#define DO_GCD_RETAIN_RELEASE 1
+#endif
+#endif
+
+#ifdef DEBUG
+#   define DLog(fmt, ...) {NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);}
+#   define ELog(err) {if(err) DLog(@"%@", err)}
+#else
+#   define DLog(...)
+#   define ELog(err)
+#endif
+
+// ALog always displays output regardless of the DEBUG setting
+#define ALog(fmt, ...) {NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);};
+
+#import "NSString+MKNetworkKitAdditions.h"
+#import "NSDictionary+RequestEncoding.h"
+#import "NSDate+RFC1123.h"
+#import "NSData+Base64.h"
+
+//#import "Categories/NSString+MKNetworkKitAdditions.h"
+//#import "Categories/NSDictionary+RequestEncoding.h"
+//#import "Categories/NSDate+RFC1123.h"
+//#import "Categories/NSData+Base64.h"
+
+#if TARGET_OS_IPHONE
+#import "UIAlertView+MKNetworkKitAdditions.h"
+#elif TARGET_OS_MAC
+#import "NSAlert+MKNetworkKitAdditions.h"
+
+//#import "Categories/UIAlertView+MKNetworkKitAdditions.h"
+//#elif TARGET_OS_MAC
+//#import "Categories/NSAlert+MKNetworkKitAdditions.h"
+
+#endif
+
+#import "Reachability/Reachability.h"
+
+#import "MKNetworkOperation.h"
+#import "MKNetworkEngine.h"
+
+#define kMKNetworkEngineOperationCountChanged @"kMKNetworkEngineOperationCountChanged"
+#define MKNETWORKCACHE_DEFAULT_COST 10
+#define MKNETWORKCACHE_DEFAULT_DIRECTORY @"MKNetworkKitCache"
+#define kMKNetworkKitDefaultCacheDuration 60 // 1 minute
+#define kMKNetworkKitDefaultImageHeadRequestDuration 3600*24*1 // 1 day (HEAD requests with eTag are sent only after expiry of this. Not that these are not RFC compliant, but needed for performance tuning)
+#define kMKNetworkKitDefaultImageCacheDuration 3600*24*7 // 1 day
+
+// if your server takes longer than 30 seconds to provide real data,
+// you should hire a better server developer.
+// on iOS (or any mobile device), 30 seconds is already considered high.
+
+#define kMKNetworkKitRequestTimeOutInSeconds 30
+#endif
+
+

+ 547 - 0
Pods/MKNetworkKit/MKNetworkKit/MKNetworkOperation.h

@@ -0,0 +1,547 @@
+//
+//  MKNetwork.h
+//  MKNetworkKit
+//
+//  Created by Mugunth Kumar (@mugunthkumar) on 11/11/11.
+//  Copyright (C) 2011-2020 by Steinlogic Consulting and Training Pte Ltd
+
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+@class MKNetworkOperation;
+
+typedef enum {
+  MKNetworkOperationStateReady = 1,
+  MKNetworkOperationStateExecuting = 2,
+  MKNetworkOperationStateFinished = 3
+} MKNetworkOperationState;
+
+typedef void (^MKNKProgressBlock)(double progress);
+typedef void (^MKNKResponseBlock)(MKNetworkOperation* completedOperation);
+#if TARGET_OS_IPHONE
+typedef void (^MKNKImageBlock) (UIImage* fetchedImage, NSURL* url, BOOL isInCache);
+#elif TARGET_OS_MAC
+typedef void (^MKNKImageBlock) (NSImage* fetchedImage, NSURL* url, BOOL isInCache);
+#endif
+typedef void (^MKNKErrorBlock)(NSError* error);
+
+typedef void (^MKNKAuthBlock)(NSURLAuthenticationChallenge* challenge);
+
+typedef NSString* (^MKNKEncodingBlock) (NSDictionary* postDataDict);
+
+typedef enum {
+  
+  MKNKPostDataEncodingTypeURL = 0, // default
+  MKNKPostDataEncodingTypeJSON,
+  MKNKPostDataEncodingTypePlist,
+  MKNKPostDataEncodingTypeCustom
+} MKNKPostDataEncodingType;
+/*!
+ @header MKNetworkOperation.h
+ @abstract   Represents a single unique network operation.
+ */
+
+/*!
+ *  @class MKNetworkOperation
+ *  @abstract Represents a single unique network operation.
+ *  
+ *  @discussion
+ *	You normally create an instance of this class using the methods exposed by MKNetworkEngine
+ *  Created operations are enqueued into the shared queue on MKNetworkEngine
+ *  MKNetworkOperation encapsulates both request and response
+ *  Printing a MKNetworkOperation prints out a cURL command that can be copied and pasted directly on terminal
+ *  Freezable operations are serialized when network connectivity is lost and performed when connection is restored
+ */
+@interface MKNetworkOperation : NSOperation {
+  
+@private
+  int _state;
+  BOOL _freezable;
+  MKNKPostDataEncodingType _postDataEncoding;
+}
+
+/*!
+ *  @abstract Request URL Property
+ *  @property url
+ *  
+ *  @discussion
+ *	Returns the operation's URL
+ *  This property is readonly cannot be updated. 
+ *  To create an operation with a specific URL, use the operationWithURLString:params:httpMethod: 
+ */
+@property (nonatomic, readonly) NSString *url;
+
+/*!
+ *  @abstract The internal request object
+ *  @property readonlyRequest
+ *  
+ *  @discussion
+ *	Returns the operation's actual request object
+ *  This property is readonly cannot be modified. 
+ *  To create an operation with a new request, use the operationWithURLString:params:httpMethod: 
+ */
+@property (nonatomic, strong, readonly) NSURLRequest *readonlyRequest;
+
+/*!
+ *  @abstract The internal HTTP Response Object
+ *  @property readonlyResponse
+ *  
+ *  @discussion
+ *	Returns the operation's actual response object
+ *  This property is readonly cannot be updated. 
+ */
+@property (nonatomic, strong, readonly) NSHTTPURLResponse *readonlyResponse;
+
+/*!
+ *  @abstract The internal HTTP Post data values
+ *  @property readonlyPostDictionary
+ *  
+ *  @discussion
+ *	Returns the operation's post data dictionary
+ *  This property is readonly cannot be updated.
+ *  Rather, updating this post dictionary doesn't have any effect on the MKNetworkOperation.
+ *  Use the addHeaders method to add post data parameters to the operation.
+ *
+ *  @seealso
+ *   addHeaders:
+ */
+@property (nonatomic, strong, readonly) NSDictionary *readonlyPostDictionary;
+
+/*!
+ *  @abstract The internal request object's method type
+ *  @property HTTPMethod
+ *  
+ *  @discussion
+ *	Returns the operation's method type
+ *  This property is readonly cannot be modified. 
+ *  To create an operation with a new method type, use the operationWithURLString:params:httpMethod: 
+ */
+@property (nonatomic, strong, readonly) NSString *HTTPMethod;
+
+/*!
+ *  @abstract The internal response object's status code
+ *  @property HTTPStatusCode
+ *  
+ *  @discussion
+ *	Returns the operation's response's status code.
+ *  Returns 0 when the operation has not yet started and the response is not available.
+ *  This property is readonly cannot be modified. 
+ */
+@property (nonatomic, assign, readonly) NSInteger HTTPStatusCode;
+
+/*!
+ *  @abstract Post Data Encoding Type Property
+ *  @property postDataEncoding
+ *  
+ *  @discussion
+ *  Specifies which type of encoding should be used to encode post data.
+ *  MKNKPostDataEncodingTypeURL is the default which defaults to application/x-www-form-urlencoded
+ *  MKNKPostDataEncodingTypeJSON uses JSON encoding. 
+ *  JSON Encoding is supported only in iOS 5 or Mac OS X 10.7 and above.
+ *  On older operating systems, JSON Encoding reverts back to URL Encoding
+ *  You can use the postDataEncodingHandler to provide a custom postDataEncoding 
+ *  For example, JSON encoding using a third party library.
+ *
+ *  @seealso
+ *  setCustomPostDataEncodingHandler:forType:
+ *
+ */
+@property (nonatomic, assign) MKNKPostDataEncodingType postDataEncoding;
+
+/*!
+ *  @abstract Set a customized Post Data Encoding Handler for a given HTTP Content Type
+ *  
+ *  @discussion
+ *  If you need customized post data encoding support, provide a block method here.
+ *  This block method will be invoked only when your HTTP Method is POST or PUT
+ *  For default URL encoding or JSON encoding, use the property postDataEncoding
+ *  If you change the postData format, it's your responsiblity to provide a correct Content-Type.
+ *
+ *  @seealso
+ *  postDataEncoding
+ */
+
+-(void) setCustomPostDataEncodingHandler:(MKNKEncodingBlock) postDataEncodingHandler forType:(NSString*) contentType;
+
+/*!
+ *  @abstract String Encoding Property
+ *  @property stringEncoding
+ *  
+ *  @discussion
+ *  Specifies which type of encoding should be used to encode URL strings
+ */
+@property (nonatomic, assign) NSStringEncoding stringEncoding;
+
+/*!
+ *  @abstract Freezable request
+ *  @property freezable
+ *  
+ *  @discussion
+ *	Freezable operations are serialized when the network goes down and restored when the connectivity is up again.
+ *  Only POST, PUT and DELETE operations are freezable.
+ *  In short, any operation that changes the state of the server are freezable, creating a tweet, checking into a new location etc., Operations like fetching a list of tweets (think readonly GET operations) are not freezable.
+ *  MKNetworkKit doesn't freeze (readonly) GET operations even if they are marked as freezable
+ */
+@property (nonatomic, assign) BOOL freezable;
+
+/*!
+ *  @abstract Error object
+ *  @property error
+ *  
+ *  @discussion
+ *	If the network operation results in an error, this will hold the response error, otherwise it will be nil
+ */
+@property (nonatomic, readonly, strong) NSError *error;
+
+/*!
+ *  @abstract Cache headers of the response
+ *  @property cacheHeaders
+ *  
+ *  @discussion
+ *	If the network operation is a GET, this dictionary will be populated with relevant cache related headers
+ *	MKNetworkKit assumes a 7 day cache for images and 1 minute cache for all requests with no-cache set
+ *	This property is internal to MKNetworkKit. Modifying this is not recommended and will result in unexpected behaviour
+ */
+@property (strong, nonatomic) NSMutableDictionary *cacheHeaders;
+
+/*!
+ *  @abstract Authentication methods
+ *  
+ *  @discussion
+ *	If your request needs to be authenticated, set your username and password using this method.
+ */
+-(void) setUsername:(NSString*) name password:(NSString*) password;
+
+/*!
+ *  @abstract Authentication methods
+ *  
+ *  @discussion
+ *	If your request needs to be authenticated using HTTP Basic, use this method to set your username and password.
+ *  Calling this method with basicAuth:NO is same as calling setUserName:password:
+ *  @seealso
+ *  setUserName:password:
+ */
+-(void) setUsername:(NSString*) username password:(NSString*) password basicAuth:(BOOL) bYesOrNo;
+
+/*!
+ *  @abstract Authentication methods (Client Certificate)
+ *  @property clientCertificate
+ *  
+ *  @discussion
+ *	If your request needs to be authenticated using a client certificate, set the certificate path here
+ */
+@property (strong, nonatomic) NSString *clientCertificate;
+
+/*!
+ *  @abstract Custom authentication handler
+ *  @property authHandler
+ *  
+ *  @discussion
+ *	If your request needs to be authenticated using a custom method (like a Web page/HTML Form), add a block method here
+ *  and process the NSURLAuthenticationChallenge
+ */
+@property (nonatomic, copy) MKNKAuthBlock authHandler;
+
+/*!
+ *  @abstract Handler that you implement to monitor reachability changes
+ *  @property operationStateChangedHandler
+ *  
+ *  @discussion
+ *	The framework calls this handler whenever the operation state changes
+ */
+@property (copy, nonatomic) void (^operationStateChangedHandler)(MKNetworkOperationState newState);
+
+/*!
+ *  @abstract controls persistence of authentication credentials
+ *  @property credentialPersistence
+ *  
+ *  @discussion
+ *  The default value is set to NSURLCredentialPersistenceForSession, change it to NSURLCredentialPersistenceNone to avoid caching issues (isse #35)
+ */
+@property (nonatomic, assign) NSURLCredentialPersistence credentialPersistence;
+#if TARGET_OS_IPHONE
+
+/*!
+ *  @abstract notification that has to be shown when an error occurs and the app is in background
+ *  @property localNotification
+ *  
+ *  @discussion
+ *  The default value nil. No notification is shown when an error occurs.
+ *  To show a notification when the app is in background and the network operation running in background fails,
+ *  set this parameter to a UILocalNotification object
+ */
+@property (nonatomic, strong) UILocalNotification *localNotification;
+/*!
+ *  @abstract Shows a local notification when an error occurs
+ *  @property shouldShowLocalNotificationOnError
+ *  
+ *  @discussion
+ *  The default value NO. No notification is shown when an error occurs.
+ *  When set to YES, MKNetworkKit shows the NSError localizedDescription text as a notification when the app is in background and the network operation ended in error.
+ *  To customize the local notification text, use the property localNotification
+ 
+ *  @seealso
+ *  localNotification
+ */
+@property (nonatomic, assign) BOOL shouldShowLocalNotificationOnError;
+#endif
+
+/*!
+ *  @abstract Add additional header parameters
+ *  
+ *  @discussion
+ *	If you ever need to set additional headers after creating your operation, you this method.
+ *  You normally set default headers to the engine and they get added to every request you create.
+ *  On specific cases where you need to set a new header parameter for just a single API call, you can use this
+ */
+-(void) addHeaders:(NSDictionary*) headersDictionary;
+
+/*!
+ *  @abstract Sets the authorization header after prefixing it with a given auth type
+ *  
+ *  @discussion
+ *	If you need to set the HTTP Authorization header, you can use this convinience method.
+ *  This method internally calls addHeaders:
+ *  The authType parameter is a string that you can prefix to your auth token to tell your server what kind of authentication scheme you want to use. HTTP Basic Authentication uses the string "Basic" for authType
+ *  To use HTTP Basic Authentication, consider using the method setUsername:password:basicAuth: instead.
+ *
+ *  Example
+ *  [op setToken:@"abracadabra" forAuthType:@"Token"] will set the header value to 
+ *  "Authorization: Token abracadabra"
+ 
+ *  @seealso
+ *  setUsername:password:basicAuth:
+ *  addHeaders:
+ */
+-(void) setAuthorizationHeaderValue:(NSString*) token forAuthType:(NSString*) authType;
+
+/*!
+ *  @abstract Attaches a file to the request
+ *  
+ *  @discussion
+ *	This method lets you attach a file to the request
+ *  The method has a side effect. It changes the HTTPMethod to "POST" regardless of what it was before.
+ *  It also changes the post format to multipart/form-data
+ *  The mime-type is assumed to be application/octet-stream
+ */
+-(void) addFile:(NSString*) filePath forKey:(NSString*) key;
+
+/*!
+ *  @abstract Attaches a file to the request and allows you to specify a mime-type
+ *  
+ *  @discussion
+ *	This method lets you attach a file to the request
+ *  The method has a side effect. It changes the HTTPMethod to "POST" regardless of what it was before.
+ *  It also changes the post format to multipart/form-data
+ */
+-(void) addFile:(NSString*) filePath forKey:(NSString*) key mimeType:(NSString*) mimeType;
+
+/*!
+ *  @abstract Attaches a resource to the request from a NSData pointer
+ *  
+ *  @discussion
+ *	This method lets you attach a NSData object to the request. The behaviour is exactly similar to addFile:forKey:
+ *  The method has a side effect. It changes the HTTPMethod to "POST" regardless of what it was before.
+ *  It also changes the post format to multipart/form-data
+ *  The mime-type is assumed to be application/octet-stream
+ */
+-(void) addData:(NSData*) data forKey:(NSString*) key;
+
+/*!
+ *  @abstract Attaches a resource to the request from a NSData pointer and allows you to specify a mime-type
+ *  
+ *  @discussion
+ *	This method lets you attach a NSData object to the request. The behaviour is exactly similar to addFile:forKey:mimeType:
+ *  The method has a side effect. It changes the HTTPMethod to "POST" regardless of what it was before.
+ *  It also changes the post format to multipart/form-data
+ */
+-(void) addData:(NSData*) data forKey:(NSString*) key mimeType:(NSString*) mimeType fileName:(NSString*) fileName;
+
+/*!
+ *  @abstract Block Handler for completion and error
+ *  
+ *  @discussion
+ *	This method sets your completion and error blocks. If your operation's response data was previously called,
+ *  the completion block will be called almost immediately with the cached response. You can check if the completion 
+ *  handler was invoked with a cached data or with real data by calling the isCachedResponse method.
+ *
+ *  @seealso
+ *  isCachedResponse
+ */
+-(void) onCompletion:(MKNKResponseBlock) response onError:(MKNKErrorBlock) error;
+
+/*!
+ *  @abstract Block Handler for tracking upload progress
+ *  
+ *  @discussion
+ *	This method can be used to update your progress bars when an upload is in progress. 
+ *  The value range of the progress is 0 to 1.
+ *
+ */
+-(void) onUploadProgressChanged:(MKNKProgressBlock) uploadProgressBlock;
+
+/*!
+ *  @abstract Block Handler for tracking download progress
+ *  
+ *  @discussion
+ *	This method can be used to update your progress bars when a download is in progress. 
+ *  The value range of the progress is 0 to 1.
+ *
+ */
+-(void) onDownloadProgressChanged:(MKNKProgressBlock) downloadProgressBlock;
+
+/*!
+ *  @abstract Uploads a resource from a stream
+ *  
+ *  @discussion
+ *	This method can be used to upload a resource for a post body directly from a stream.
+ *
+ */
+-(void) setUploadStream:(NSInputStream*) inputStream;
+
+/*!
+ *  @abstract Downloads a resource directly to a file or any output stream
+ *  
+ *  @discussion
+ *	This method can be used to download a resource directly to a stream (It's normally a file in most cases).
+ *  Calling this method multiple times adds new streams to the same operation.
+ *  A stream cannot be removed after it is added.
+ *
+ */
+-(void) addDownloadStream:(NSOutputStream*) outputStream;
+
+/*!
+ *  @abstract Helper method to check if the response is from cache
+ *  
+ *  @discussion
+ *	This method should be used to check if your response is cached.
+ *  When you enable caching on MKNetworkEngine, your completionHandler will be called with cached data first and then
+ *  with real data, later after fetching. In your handler, you can call this method to check if it is from cache or not
+ *
+ */
+-(BOOL) isCachedResponse;
+
+/*!
+ *  @abstract Helper method to retrieve the contents
+ *  
+ *  @discussion
+ *	This method is used for accessing the downloaded data. If the operation is still in progress, the method returns nil instead of partial data. To access partial data, use a downloadStream.
+ *
+ *  @seealso
+ *  addDownloadStream:
+ */
+-(NSData*) responseData;
+
+/*!
+ *  @abstract Helper method to retrieve the contents as a NSString
+ *  
+ *  @discussion
+ *	This method is used for accessing the downloaded data. If the operation is still in progress, the method returns nil instead of partial data. To access partial data, use a downloadStream. The method also converts the responseData to a NSString using the stringEncoding specified in the operation
+ *
+ *  @seealso
+ *  addDownloadStream:
+ *  stringEncoding
+ */
+-(NSString*)responseString;
+
+/*!
+ *  @abstract Helper method to print the request as a cURL command
+ *  
+ *  @discussion
+ *	This method is used for displaying the request you created as a cURL command
+ *
+ */
+-(NSString*) curlCommandLineString;
+
+/*!
+ *  @abstract Helper method to retrieve the contents as a NSString encoded using a specific string encoding
+ *  
+ *  @discussion
+ *	This method is used for accessing the downloaded data. If the operation is still in progress, the method returns nil instead of partial data. To access partial data, use a downloadStream. The method also converts the responseData to a NSString using the stringEncoding specified in the parameter
+ *
+ *  @seealso
+ *  addDownloadStream:
+ *  stringEncoding
+ */
+-(NSString*) responseStringWithEncoding:(NSStringEncoding) encoding;
+
+/*!
+ *  @abstract Helper method to retrieve the contents as a UIImage
+ *  
+ *  @discussion
+ *	This method is used for accessing the downloaded data as a UIImage. If the operation is still in progress, the method returns nil instead of a partial image. To access partial data, use a downloadStream. If the response is not a valid image, this method returns nil. This method doesn't obey the response mime type property. If the server response with a proper image data but set the mime type incorrectly, this method will still be able access the response as an image.
+ *
+ *  @seealso
+ *  addDownloadStream:
+ */
+#if TARGET_OS_IPHONE
+-(UIImage*) responseImage;
+#elif TARGET_OS_MAC
+-(NSImage*) responseImage;
+-(NSXMLDocument*) responseXML;
+#endif
+
+/*!
+ *  @abstract Helper method to retrieve the contents as a NSDictionary or NSArray depending on the JSON contents
+ *  
+ *  @discussion
+ *	This method is used for accessing the downloaded data as a NSDictionary or an NSArray. If the operation is still in progress, the method returns nil. If the response is not a valid JSON, this method returns nil.
+ *
+ *  @availability
+ *  iOS 5 and above or Mac OS 10.7 and above
+ */
+-(id) responseJSON;
+
+/*!
+ *  @abstract Overridable custom method where you can add your custom business logic error handling
+ *  
+ *  @discussion
+ *	This optional method can be overridden to do custom error handling. Be sure to call [super operationSucceeded] at the last.
+ *  For example, a valid HTTP response (200) like "Item not found in database" might have a custom business error code
+ *  You can override this method and called [super failWithError:customError]; to notify that HTTP call was successful but the method
+ *  ended as a failed call
+ *
+ */
+-(void) operationSucceeded;
+
+/*!
+ *  @abstract Overridable custom method where you can add your custom business logic error handling
+ *  
+ *  @discussion
+ *	This optional method can be overridden to do custom error handling. Be sure to call [super operationSucceeded] at the last.
+ *  For example, a invalid HTTP response (401) like "Unauthorized" might be a valid case in your app.
+ *  You can override this method and called [super operationSucceeded]; to notify that HTTP call failed but the method
+ *  ended as a success call. For example, Facebook login failed, but to your business implementation, it's not a problem as you
+ *  are going to try alternative login mechanisms.
+ *
+ */
+-(void) operationFailedWithError:(NSError*) error;
+
+// internal methods called by MKNetworkEngine only.
+// Don't touch
+-(BOOL) isCacheable;
+-(void) setCachedData:(NSData*) cachedData;
+-(void) setCacheHandler:(MKNKResponseBlock) cacheHandler;
+-(void) updateHandlersFromOperation:(MKNetworkOperation*) operation;
+-(void) updateOperationBasedOnPreviousHeaders:(NSMutableDictionary*) headers;
+-(NSString*) uniqueIdentifier;
+
+- (id)initWithURLString:(NSString *)aURLString
+                 params:(NSMutableDictionary *)params
+             httpMethod:(NSString *)method;
+@end

文件差異過大導致無法顯示
+ 1300 - 0
Pods/MKNetworkKit/MKNetworkKit/MKNetworkOperation.m


文件差異過大導致無法顯示
+ 103 - 0
Pods/MKNetworkKit/README.mdown


+ 6 - 1
Pods/Manifest.lock

@@ -812,6 +812,8 @@ PODS:
   - MBProgressHUD (1.2.0)
   - MJExtension (3.4.1)
   - MJRefresh (3.7.5)
+  - MKNetworkKit (0.85):
+    - Reachability (~> 3.0)
   - nanopb (2.30909.0):
     - nanopb/decode (= 2.30909.0)
     - nanopb/encode (= 2.30909.0)
@@ -1167,6 +1169,7 @@ DEPENDENCIES:
   - MBProgressHUD
   - MJExtension
   - MJRefresh
+  - MKNetworkKit
   - OneSignalXCFramework (< 4.0, >= 3.0.0)
   - PPBadgeView
   - Reachability
@@ -1210,6 +1213,7 @@ SPEC REPOS:
     - MBProgressHUD
     - MJExtension
     - MJRefresh
+    - MKNetworkKit
     - nanopb
     - OneSignalXCFramework
     - PPBadgeView
@@ -1261,6 +1265,7 @@ SPEC CHECKSUMS:
   MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
   MJExtension: 21c5f6f8c4d5d8844b7ae8fbae08fed0b501f961
   MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
+  MKNetworkKit: 1171bfac5c3a1cd7fea9a027f29359e1b4cab705
   nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
   OneSignalXCFramework: 4afdd14f6fa769eadf141209037e3eac5890beb9
   PPBadgeView: b50a223638970fd0781e8753250385864b6dd2fe
@@ -1274,6 +1279,6 @@ SPEC CHECKSUMS:
   YYCache: 8105b6638f5e849296c71f331ff83891a4942952
   YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
 
-PODFILE CHECKSUM: 6cbb741d4132b550ccfdc6abbfe06c4b24911517
+PODFILE CHECKSUM: 5d955d5ce86f96810ca16fd7acd16a89ff2750e0
 
 COCOAPODS: 1.13.0

文件差異過大導致無法顯示
+ 27557 - 27286
Pods/Pods.xcodeproj/project.pbxproj


+ 26 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit-Info.plist

@@ -0,0 +1,26 @@
+<?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>${PODS_DEVELOPMENT_LANGUAGE}</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>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>0.85.0</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>${CURRENT_PROJECT_VERSION}</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>

+ 5 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit-dummy.m

@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_MKNetworkKit : NSObject
+@end
+@implementation PodsDummy_MKNetworkKit
+@end

+ 12 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit-prefix.pch

@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+

+ 24 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit-umbrella.h

@@ -0,0 +1,24 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
+#import "MKNetworkEngine.h"
+#import "MKNetworkKit.h"
+#import "MKNetworkOperation.h"
+#import "NSData+Base64.h"
+#import "NSDate+RFC1123.h"
+#import "NSDictionary+RequestEncoding.h"
+#import "NSString+MKNetworkKitAdditions.h"
+#import "UIAlertView+MKNetworkKitAdditions.h"
+
+FOUNDATION_EXPORT double MKNetworkKitVersionNumber;
+FOUNDATION_EXPORT const unsigned char MKNetworkKitVersionString[];
+

+ 16 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit.debug.xcconfig

@@ -0,0 +1,16 @@
+APPLICATION_EXTENSION_API_ONLY = YES
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MKNetworkKit
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reachability"
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/MKNetworkKit/MKNetworkKit/"
+OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Reachability" -framework "Security" -framework "SystemConfiguration"
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/MKNetworkKit
+PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit.modulemap

@@ -0,0 +1,6 @@
+framework module MKNetworkKit {
+  umbrella header "MKNetworkKit-umbrella.h"
+
+  export *
+  module * { export * }
+}

+ 16 - 0
Pods/Target Support Files/MKNetworkKit/MKNetworkKit.release.xcconfig

@@ -0,0 +1,16 @@
+APPLICATION_EXTENSION_API_ONLY = YES
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MKNetworkKit
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Reachability"
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/MKNetworkKit/MKNetworkKit/"
+OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Reachability" -framework "Security" -framework "SystemConfiguration"
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/MKNetworkKit
+PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 21 - 0
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.markdown

@@ -2790,6 +2790,27 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 
+## MKNetworkKit
+
+MKNetworkKit is licensed under MIT License
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
 ## Masonry
 
 Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry

+ 27 - 0
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.plist

@@ -2975,6 +2975,33 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>MKNetworkKit is licensed under MIT License
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>MKNetworkKit</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry

文件差異過大導致無法顯示
+ 3 - 3
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.debug.xcconfig


文件差異過大導致無法顯示
+ 3 - 3
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.release.xcconfig


+ 21 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.markdown

@@ -2790,6 +2790,27 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 
+## MKNetworkKit
+
+MKNetworkKit is licensed under MIT License
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
 ## Masonry
 
 Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry

+ 27 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.plist

@@ -2975,6 +2975,33 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>MKNetworkKit is licensed under MIT License
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>MKNetworkKit</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry

+ 1 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-input-files.xcfilelist

@@ -20,6 +20,7 @@ ${BUILT_PRODUCTS_DIR}/Libuv-gRPC/uv.framework
 ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
 ${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework
 ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
+${BUILT_PRODUCTS_DIR}/MKNetworkKit/MKNetworkKit.framework
 ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
 ${BUILT_PRODUCTS_DIR}/PPBadgeView/PPBadgeView.framework
 ${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework

+ 1 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-output-files.xcfilelist

@@ -19,6 +19,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uv.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MKNetworkKit.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PPBadgeView.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework

+ 1 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-input-files.xcfilelist

@@ -20,6 +20,7 @@ ${BUILT_PRODUCTS_DIR}/Libuv-gRPC/uv.framework
 ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
 ${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework
 ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
+${BUILT_PRODUCTS_DIR}/MKNetworkKit/MKNetworkKit.framework
 ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
 ${BUILT_PRODUCTS_DIR}/PPBadgeView/PPBadgeView.framework
 ${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework

+ 1 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-output-files.xcfilelist

@@ -19,6 +19,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uv.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MKNetworkKit.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PPBadgeView.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework

+ 2 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks.sh

@@ -197,6 +197,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
+  install_framework "${BUILT_PRODUCTS_DIR}/MKNetworkKit/MKNetworkKit.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/PPBadgeView/PPBadgeView.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework"
@@ -244,6 +245,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
+  install_framework "${BUILT_PRODUCTS_DIR}/MKNetworkKit/MKNetworkKit.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/PPBadgeView/PPBadgeView.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework"

文件差異過大導致無法顯示
+ 3 - 3
Pods/Target Support Files/Pods-Asteria/Pods-Asteria.debug.xcconfig


文件差異過大導致無法顯示
+ 3 - 3
Pods/Target Support Files/Pods-Asteria/Pods-Asteria.release.xcconfig