Browse Source

Update Cartfile

marinofaggiana 6 years ago
parent
commit
0671e8e1cf
100 changed files with 2065 additions and 1776 deletions
  1. 4 4
      Cartfile
  2. 7 7
      Cartfile.resolved
  3. 12 0
      Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md
  4. 1 1
      Carthage/Checkouts/KTVHTTPCache/Framework/Info.plist
  5. 11 3
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache.podspec
  6. 1 2
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCError.h
  7. 17 17
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCError.m
  8. 11 18
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCLog.h
  9. 48 47
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCLog.m
  10. 6 5
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCRange.h
  11. 38 45
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCRange.m
  12. 6 5
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItem.h
  13. 8 22
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItem.m
  14. 2 2
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItemZone.h
  15. 4 10
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItemZone.m
  16. 7 17
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataFileSource.h
  17. 42 58
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataFileSource.m
  18. 10 12
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataLoader.h
  19. 31 43
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataLoader.m
  20. 9 19
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataNetworkSource.h
  21. 87 131
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataNetworkSource.m
  22. 11 13
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.h
  23. 68 100
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.m
  24. 4 7
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataRequest.h
  25. 11 19
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataRequest.m
  26. 7 12
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataResponse.h
  27. 11 41
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataResponse.m
  28. 9 20
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceManager.h
  29. 121 91
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceManager.m
  30. 3 3
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.h
  31. 11 13
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.m
  32. 16 21
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnit.h
  33. 127 175
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnit.m
  34. 8 10
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitItem.h
  35. 25 31
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitItem.m
  36. 1 1
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitPool.h
  37. 71 91
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitPool.m
  38. 2 2
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitQueue.h
  39. 20 35
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitQueue.m
  40. 10 10
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDownload/KTVHCDownload.h
  41. 118 135
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDownload/KTVHCDownload.m
  42. 0 2
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPConnection.h
  43. 8 30
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPConnection.m
  44. 2 2
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPResponse.h
  45. 28 31
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPResponse.m
  46. 2 2
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPServer.h
  47. 108 100
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPServer.m
  48. 335 8
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/KTVHTTPCache.h
  49. 1 1
      Carthage/Checkouts/KTVHTTPCache/LICENSE
  50. 2 2
      Carthage/Checkouts/PDFGenerator/PDFGenerator.podspec
  51. 1 1
      Carthage/Checkouts/SVGKit/Source/DOM classes/Core DOM/DOMGlobalSettings.h
  52. 1 1
      Carthage/Checkouts/SVGKit/Source/DOM classes/SVG-DOM/SVGNumber.h
  53. 1 1
      Carthage/Checkouts/SVGKit/Source/DOM classes/Unported or Partial DOM/SVGElement.h
  54. 1 1
      Carthage/Checkouts/SVGKit/Source/Foundation additions/NSData+NSInputStream.h
  55. 1 1
      Carthage/Checkouts/SVGKit/Source/Foundation additions/NSData+NSInputStream.m
  56. 6 1
      Carthage/Checkouts/SVGKit/Source/UIKit additions/SVGKFastImageView.m
  57. 5 1
      Carthage/Checkouts/SVGKit/Source/UIKit additions/SVGKLayeredImageView.m
  58. 1 1
      Carthage/Checkouts/TLPhotoPicker/.swift-version
  59. 3 3
      Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker.podspec
  60. 5 2
      Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker/Classes/TLAssetsCollection.swift
  61. 10 10
      Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker/Classes/TLPhotoLibrary.swift
  62. 44 38
      Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker/Classes/TLPhotosPickerViewController.swift
  63. 87 39
      Carthage/Checkouts/realm-cocoa/.jenkins.yml
  64. 4 0
      Carthage/Checkouts/realm-cocoa/.swiftlint.yml
  65. 49 0
      Carthage/Checkouts/realm-cocoa/CHANGELOG.md
  66. 1 1
      Carthage/Checkouts/realm-cocoa/Configuration/Base.xcconfig
  67. 12 14
      Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability
  68. 1 46
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm
  69. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.mm
  70. 5 14
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift
  71. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/CMake/RealmCore.cmake
  72. 5 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/CMakeLists.txt
  73. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list
  74. 16 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/CMakeLists.txt
  75. 38 24
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp
  76. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/apple/external_commit_helper.hpp
  77. 30 32
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/epoll/external_commit_helper.cpp
  78. 27 9
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.cpp
  79. 4 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.hpp
  80. 3 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.cpp
  81. 31 11
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.cpp
  82. 18 8
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.hpp
  83. 2 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/CMakeLists.txt
  84. 52 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp
  85. 40 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/results.cpp
  86. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/workflow/build.sh
  87. 2 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMCollection.h
  88. 10 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMConstants.h
  89. 10 15
      Carthage/Checkouts/realm-cocoa/Realm/RLMNetworkClient.mm
  90. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.mm
  91. 3 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration_Private.h
  92. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h
  93. 2 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncPermission.h
  94. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSession.h
  95. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.h
  96. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist
  97. 9 1
      Carthage/Checkouts/realm-cocoa/Realm/Tests/AsyncTests.mm
  98. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m
  99. 6 0
      Carthage/Checkouts/realm-cocoa/Realm/Tests/RealmTests.mm
  100. 1 1
      Carthage/Checkouts/realm-cocoa/RealmSwift/Object.swift

+ 4 - 4
Cartfile

@@ -1,4 +1,4 @@
-github "tilltue/TLPhotoPicker" == 1.8.3
+github "tilltue/TLPhotoPicker" == 1.8.5
 github "kishikawakatsumi/UICKeyChainStore" == 2.1.2
 github "kishikawakatsumi/UICKeyChainStore" == 2.1.2
 github "danielsaidi/Sheeeeeeeeet" == 1.2.2
 github "danielsaidi/Sheeeeeeeeet" == 1.2.2
 github "sgr-ksmt/PDFGenerator" == 2.1
 github "sgr-ksmt/PDFGenerator" == 2.1
@@ -8,10 +8,10 @@ github "ealeksandrov/EAIntroView" == 2.12.0
 github "calimarkus/JDStatusBarNotification" == 1.6.0
 github "calimarkus/JDStatusBarNotification" == 1.6.0
 github "ChangbaDevs/KTVHTTPCache" == 2.0.0
 github "ChangbaDevs/KTVHTTPCache" == 2.0.0
 github "jdg/MBProgressHUD" == 1.1.0
 github "jdg/MBProgressHUD" == 1.1.0
-github "realm/realm-cocoa" == 3.13.1
+github "realm/realm-cocoa" == 3.14.1
 github "SVGKit/SVGKit" == 2.1.0
 github "SVGKit/SVGKit" == 2.1.0
-github "WeTransfer/WeScan" == 0.9.1
-github "malcommac/SwiftRichString" == 2.0.1
+github "WeTransfer/WeScan" == 1.1.0
+github "malcommac/SwiftRichString" == 3.0.0
 github "https://github.com/marinofaggiana/FastScroll" "master"
 github "https://github.com/marinofaggiana/FastScroll" "master"
 github "yannickl/QRCodeReader.swift" >= 10.0.0
 github "yannickl/QRCodeReader.swift" >= 10.0.0
 github "marmelroy/Zip"
 github "marmelroy/Zip"

+ 7 - 7
Cartfile.resolved

@@ -1,8 +1,8 @@
-github "ChangbaDevs/KTVHTTPCache" "1.1.7"
+github "ChangbaDevs/KTVHTTPCache" "2.0.0"
 github "CocoaLumberjack/CocoaLumberjack" "3.5.2"
 github "CocoaLumberjack/CocoaLumberjack" "3.5.2"
 github "MortimerGoro/MGSwipeTableCell" "1.6.8"
 github "MortimerGoro/MGSwipeTableCell" "1.6.8"
-github "SVGKit/SVGKit" "4b507e48da30711e25d1bcdd19580f25887a2267"
-github "WeTransfer/WeScan" "v0.9.1"
+github "SVGKit/SVGKit" "2.1.0"
+github "WeTransfer/WeScan" "v1.1.0"
 github "calimarkus/JDStatusBarNotification" "1.6.0"
 github "calimarkus/JDStatusBarNotification" "1.6.0"
 github "danielsaidi/Sheeeeeeeeet" "1.2.2"
 github "danielsaidi/Sheeeeeeeeet" "1.2.2"
 github "dzenbot/DZNEmptyDataSet" "v1.8.1"
 github "dzenbot/DZNEmptyDataSet" "v1.8.1"
@@ -10,10 +10,10 @@ github "ealeksandrov/EAIntroView" "2.12.0"
 github "ealeksandrov/EARestrictedScrollView" "1.1.0"
 github "ealeksandrov/EARestrictedScrollView" "1.1.0"
 github "jdg/MBProgressHUD" "1.1.0"
 github "jdg/MBProgressHUD" "1.1.0"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
-github "malcommac/SwiftRichString" "2.1.0"
+github "malcommac/SwiftRichString" "3.0.0"
 github "marinofaggiana/FastScroll" "81967c2309d29bc2c330d422da612160a30bade8"
 github "marinofaggiana/FastScroll" "81967c2309d29bc2c330d422da612160a30bade8"
 github "marmelroy/Zip" "1.1.0"
 github "marmelroy/Zip" "1.1.0"
-github "realm/realm-cocoa" "v3.13.1"
-github "sgr-ksmt/PDFGenerator" "2.1.1"
-github "tilltue/TLPhotoPicker" "1.8.3"
+github "realm/realm-cocoa" "v3.14.1"
+github "sgr-ksmt/PDFGenerator" "2.1"
+github "tilltue/TLPhotoPicker" "1.8.5"
 github "yannickl/QRCodeReader.swift" "10.0.0"
 github "yannickl/QRCodeReader.swift" "10.0.0"

+ 12 - 0
Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md

@@ -1,3 +1,15 @@
+## [3.5.2 - Xcode 10.1 on 15th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.2)
+
+### Public
+- Fix reusing of log files after rolling (#1042)
+- Fix creation of too many log files (#1049)
+- Preliminary compatibility with Swift 5 (backwards compatible with Swift 4) (#1044)
+- core: loggers os logger variations have been added (#1039)
+
+### Internal
+- Sync internal queues to prevent cleaning up log files too soon in tests (#1053)
+- DDLog checks for NULL values and for global queue dispatching has been added (#1045)
+
 ## [3.5.1 - Xcode 10 on Feb 4th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.1)
 ## [3.5.1 - Xcode 10 on Feb 4th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.1)
 
 
 ### Public
 ### Public

+ 1 - 1
Carthage/Checkouts/KTVHTTPCache/Framework/Info.plist

@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
 	<key>CFBundleShortVersionString</key>
-	<string>1.1.7</string>
+	<string>2.0.0</string>
 	<key>CFBundleVersion</key>
 	<key>CFBundleVersion</key>
 	<string>$(CURRENT_PROJECT_VERSION)</string>
 	<string>$(CURRENT_PROJECT_VERSION)</string>
 	<key>LSApplicationCategoryType</key>
 	<key>LSApplicationCategoryType</key>

+ 11 - 3
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache.podspec

@@ -1,7 +1,7 @@
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name                = "KTVHTTPCache"
   s.name                = "KTVHTTPCache"
-  s.version             = "1.1.7"
-  s.summary             = "A media cache framework from Changba iOS Team."
+  s.version             = "2.0.0"
+  s.summary             = "A powerful media cache framework."
   s.homepage            = "https://github.com/ChangbaDevs/KTVHTTPCache"
   s.homepage            = "https://github.com/ChangbaDevs/KTVHTTPCache"
   s.license             = { :type => "MIT", :file => "LICENSE" }
   s.license             = { :type => "MIT", :file => "LICENSE" }
   s.author              = { "Single" => "libobjc@gmail.com" }
   s.author              = { "Single" => "libobjc@gmail.com" }
@@ -9,7 +9,15 @@ Pod::Spec.new do |s|
   s.platform            = :ios, "8.0"
   s.platform            = :ios, "8.0"
   s.source              = { :git => "https://github.com/ChangbaDevs/KTVHTTPCache.git", :tag => "#{s.version}" }
   s.source              = { :git => "https://github.com/ChangbaDevs/KTVHTTPCache.git", :tag => "#{s.version}" }
   s.source_files        = "KTVHTTPCache", "KTVHTTPCache/**/*.{h,m}"
   s.source_files        = "KTVHTTPCache", "KTVHTTPCache/**/*.{h,m}"
-  s.public_header_files = "KTVHTTPCache/**/*.h"
+  s.public_header_files =
+                          "KTVHTTPCache/KTVHTTPCache.h",
+                          "KTVHTTPCache/Classes/KTVHCCommon/KTVHCRange.h",
+                          "KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.h",
+                          "KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataLoader.h",
+                          "KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataRequest.h",
+                          "KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataResponse.h",
+                          "KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItem.h",
+                          "KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItemZone.h"
   s.frameworks          = "UIKit", "Foundation"
   s.frameworks          = "UIKit", "Foundation"
   s.requires_arc        = true
   s.requires_arc        = true
   s.dependency 'KTVCocoaHTTPServer'
   s.dependency 'KTVCocoaHTTPServer'

+ 1 - 2
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCError.h

@@ -8,8 +8,7 @@
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
 
 
-typedef NS_ENUM(NSInteger, KTVHCErrorCode)
-{
+typedef NS_ENUM(NSInteger, KTVHCErrorCode) {
     KTVHCErrorCodeResponseUnavailable  = -192700,
     KTVHCErrorCodeResponseUnavailable  = -192700,
     KTVHCErrorCodeUnsupportContentType = -192701,
     KTVHCErrorCodeUnsupportContentType = -192701,
     KTVHCErrorCodeNotEnoughDiskSpace   = -192702,
     KTVHCErrorCodeNotEnoughDiskSpace   = -192702,

+ 17 - 17
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCError.m

@@ -18,7 +18,7 @@ NSString * const KTVHCErrorUserInfoKeyResponse = @"KTVHCErrorUserInfoKeyResponse
                                  request:(NSURLRequest *)request
                                  request:(NSURLRequest *)request
                                 response:(NSURLResponse *)response
                                 response:(NSURLResponse *)response
 {
 {
-    NSMutableDictionary * userInfo = [NSMutableDictionary dictionary];
+    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
     if (URL) {
     if (URL) {
         [userInfo setObject:URL forKey:KTVHCErrorUserInfoKeyURL];
         [userInfo setObject:URL forKey:KTVHCErrorUserInfoKeyURL];
     }
     }
@@ -28,9 +28,9 @@ NSString * const KTVHCErrorUserInfoKeyResponse = @"KTVHCErrorUserInfoKeyResponse
     if (response) {
     if (response) {
         [userInfo setObject:response forKey:KTVHCErrorUserInfoKeyResponse];
         [userInfo setObject:response forKey:KTVHCErrorUserInfoKeyResponse];
     }
     }
-    NSError * error = [NSError errorWithDomain:@"KTVHTTPCache error"
-                                          code:KTVHCErrorCodeResponseUnavailable
-                                      userInfo:userInfo];
+    NSError *error = [NSError errorWithDomain:@"KTVHTTPCache error"
+                                         code:KTVHCErrorCodeResponseUnavailable
+                                     userInfo:userInfo];
     return error;
     return error;
 }
 }
 
 
@@ -38,7 +38,7 @@ NSString * const KTVHCErrorUserInfoKeyResponse = @"KTVHCErrorUserInfoKeyResponse
                                   request:(NSURLRequest *)request
                                   request:(NSURLRequest *)request
                                  response:(NSURLResponse *)response
                                  response:(NSURLResponse *)response
 {
 {
-    NSMutableDictionary * userInfo = [NSMutableDictionary dictionary];
+    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
     if (URL) {
     if (URL) {
         [userInfo setObject:URL forKey:KTVHCErrorUserInfoKeyURL];
         [userInfo setObject:URL forKey:KTVHCErrorUserInfoKeyURL];
     }
     }
@@ -48,9 +48,9 @@ NSString * const KTVHCErrorUserInfoKeyResponse = @"KTVHCErrorUserInfoKeyResponse
     if (response) {
     if (response) {
         [userInfo setObject:response forKey:KTVHCErrorUserInfoKeyResponse];
         [userInfo setObject:response forKey:KTVHCErrorUserInfoKeyResponse];
     }
     }
-    NSError * error = [NSError errorWithDomain:@"KTVHTTPCache error"
-                                          code:KTVHCErrorCodeUnsupportContentType
-                                      userInfo:userInfo];
+    NSError *error = [NSError errorWithDomain:@"KTVHTTPCache error"
+                                         code:KTVHCErrorCodeUnsupportContentType
+                                     userInfo:userInfo];
     return error;
     return error;
 }
 }
 
 
@@ -59,20 +59,20 @@ NSString * const KTVHCErrorUserInfoKeyResponse = @"KTVHCErrorUserInfoKeyResponse
                        totalCacheLength:(long long)totalCacheLength
                        totalCacheLength:(long long)totalCacheLength
                          maxCacheLength:(long long)maxCacheLength
                          maxCacheLength:(long long)maxCacheLength
 {
 {
-    NSError * error = [NSError errorWithDomain:@"KTVHTTPCache error"
-                                          code:KTVHCErrorCodeNotEnoughDiskSpace
-                                      userInfo:@{@"totlaContentLength" : @(totlaContentLength),
-                                                 @"currentContentLength" : @(currentContentLength),
-                                                 @"totalCacheLength" : @(totalCacheLength),
-                                                 @"maxCacheLength" : @(maxCacheLength)}];
+    NSError *error = [NSError errorWithDomain:@"KTVHTTPCache error"
+                                         code:KTVHCErrorCodeNotEnoughDiskSpace
+                                     userInfo:@{@"totlaContentLength" : @(totlaContentLength),
+                                                @"currentContentLength" : @(currentContentLength),
+                                                @"totalCacheLength" : @(totalCacheLength),
+                                                @"maxCacheLength" : @(maxCacheLength)}];
     return error;
     return error;
 }
 }
 
 
 + (NSError *)errorForException:(NSException *)exception
 + (NSError *)errorForException:(NSException *)exception
 {
 {
-    NSError * error = [NSError errorWithDomain:@"KTVHTTPCache error"
-                                          code:KTVHCErrorCodeException
-                                      userInfo:exception.userInfo];
+    NSError *error = [NSError errorWithDomain:@"KTVHTTPCache error"
+                                        code:KTVHCErrorCodeException
+                                    userInfo:exception.userInfo];
     return error;
     return error;
 }
 }
 
 

+ 11 - 18
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCLog.h

@@ -28,10 +28,7 @@ KTVHCLogEnable(Common,            YES, YES)
  */
  */
 KTVHCLogEnable(HTTPServer,        YES, YES)
 KTVHCLogEnable(HTTPServer,        YES, YES)
 KTVHCLogEnable(HTTPConnection,    YES, YES)
 KTVHCLogEnable(HTTPConnection,    YES, YES)
-KTVHCLogEnable(HTTPRequest,       YES, YES)
 KTVHCLogEnable(HTTPResponse,      YES, YES)
 KTVHCLogEnable(HTTPResponse,      YES, YES)
-KTVHCLogEnable(HTTPResponsePing,  YES, YES)
-KTVHCLogEnable(HTTPURL,           YES, YES)
 
 
 /**
 /**
  *  Data Storage
  *  Data Storage
@@ -48,7 +45,6 @@ KTVHCLogEnable(DataUnitPool,      YES, YES)
 KTVHCLogEnable(DataUnitQueue,     YES, YES)
 KTVHCLogEnable(DataUnitQueue,     YES, YES)
 
 
 KTVHCLogEnable(DataSourceManager, YES, YES)
 KTVHCLogEnable(DataSourceManager, YES, YES)
-KTVHCLogEnable(DataSourceQueue,   YES, YES)
 KTVHCLogEnable(DataFileSource,    YES, YES)
 KTVHCLogEnable(DataFileSource,    YES, YES)
 KTVHCLogEnable(DataNetworkSource, YES, YES)
 KTVHCLogEnable(DataNetworkSource, YES, YES)
 
 
@@ -69,8 +65,8 @@ KTVHCLogEnable(Dealloc,           YES, YES)
 #define KTVHCLogging(target, console_log_enable, record_log_enable, ...)            \
 #define KTVHCLogging(target, console_log_enable, record_log_enable, ...)            \
 if (([KTVHCLog log].consoleLogEnable && console_log_enable) || ([KTVHCLog log].recordLogEnable && record_log_enable))       \
 if (([KTVHCLog log].consoleLogEnable && console_log_enable) || ([KTVHCLog log].recordLogEnable && record_log_enable))       \
 {                                                                                   \
 {                                                                                   \
-    NSString * va_args = [NSString stringWithFormat:__VA_ARGS__];                   \
-    NSString * log = [NSString stringWithFormat:@"%@  :   %@", target, va_args];    \
+    NSString *va_args = [NSString stringWithFormat:__VA_ARGS__];                    \
+    NSString *log = [NSString stringWithFormat:@"%@  :   %@", target, va_args];     \
     if ([KTVHCLog log].recordLogEnable && record_log_enable) {                      \
     if ([KTVHCLog log].recordLogEnable && record_log_enable) {                      \
         [[KTVHCLog log] addRecordLog:log];                                          \
         [[KTVHCLog log] addRecordLog:log];                                          \
     }                                                                               \
     }                                                                               \
@@ -83,17 +79,14 @@ if (([KTVHCLog log].consoleLogEnable && console_log_enable) || ([KTVHCLog log].r
 /**
 /**
  *  Common
  *  Common
  */
  */
-#define KTVHCLogCommon(...)                 KTVHCLogging(@"KTVHCCommon           ", KTVHCLogEnableValueConsoleLog(Common),            KTVHCLogEnableValueRecordLog(Common),            ##__VA_ARGS__)
+#define KTVHCLogCommon(...)                 KTVHCLogging(@"KTVHCMacro           ", KTVHCLogEnableValueConsoleLog(Common),            KTVHCLogEnableValueRecordLog(Common),            ##__VA_ARGS__)
 
 
 /**
 /**
  *  HTTP Server
  *  HTTP Server
  */
  */
 #define KTVHCLogHTTPServer(...)             KTVHCLogging(@"KTVHCHTTPServer       ", KTVHCLogEnableValueConsoleLog(HTTPServer),        KTVHCLogEnableValueRecordLog(HTTPServer),        ##__VA_ARGS__)
 #define KTVHCLogHTTPServer(...)             KTVHCLogging(@"KTVHCHTTPServer       ", KTVHCLogEnableValueConsoleLog(HTTPServer),        KTVHCLogEnableValueRecordLog(HTTPServer),        ##__VA_ARGS__)
 #define KTVHCLogHTTPConnection(...)         KTVHCLogging(@"KTVHCHTTPConnection   ", KTVHCLogEnableValueConsoleLog(HTTPConnection),    KTVHCLogEnableValueRecordLog(HTTPConnection),    ##__VA_ARGS__)
 #define KTVHCLogHTTPConnection(...)         KTVHCLogging(@"KTVHCHTTPConnection   ", KTVHCLogEnableValueConsoleLog(HTTPConnection),    KTVHCLogEnableValueRecordLog(HTTPConnection),    ##__VA_ARGS__)
-#define KTVHCLogHTTPRequest(...)            KTVHCLogging(@"KTVHCHTTPRequest      ", KTVHCLogEnableValueConsoleLog(HTTPRequest),       KTVHCLogEnableValueRecordLog(HTTPRequest),       ##__VA_ARGS__)
 #define KTVHCLogHTTPResponse(...)           KTVHCLogging(@"KTVHCHTTPResponse     ", KTVHCLogEnableValueConsoleLog(HTTPResponse),      KTVHCLogEnableValueRecordLog(HTTPResponse),      ##__VA_ARGS__)
 #define KTVHCLogHTTPResponse(...)           KTVHCLogging(@"KTVHCHTTPResponse     ", KTVHCLogEnableValueConsoleLog(HTTPResponse),      KTVHCLogEnableValueRecordLog(HTTPResponse),      ##__VA_ARGS__)
-#define KTVHCLogHTTPResponsePing(...)       KTVHCLogging(@"KTVHCHTTPPingResponse ", KTVHCLogEnableValueConsoleLog(HTTPResponsePing),  KTVHCLogEnableValueRecordLog(HTTPResponsePing),  ##__VA_ARGS__)
-#define KTVHCLogHTTPURL(...)                KTVHCLogging(@"KTVHCHTTPURL          ", KTVHCLogEnableValueConsoleLog(HTTPURL),           KTVHCLogEnableValueRecordLog(HTTPURL),           ##__VA_ARGS__)
 
 
 /**
 /**
  *  Data Storage
  *  Data Storage
@@ -110,7 +103,6 @@ if (([KTVHCLog log].consoleLogEnable && console_log_enable) || ([KTVHCLog log].r
 #define KTVHCLogDataUnitQueue(...)          KTVHCLogging(@"KTVHCDataUnitQueue    ", KTVHCLogEnableValueConsoleLog(DataUnitQueue),     KTVHCLogEnableValueRecordLog(DataUnitQueue),     ##__VA_ARGS__)
 #define KTVHCLogDataUnitQueue(...)          KTVHCLogging(@"KTVHCDataUnitQueue    ", KTVHCLogEnableValueConsoleLog(DataUnitQueue),     KTVHCLogEnableValueRecordLog(DataUnitQueue),     ##__VA_ARGS__)
 
 
 #define KTVHCLogDataSourceManager(...)      KTVHCLogging(@"KTVHCDataSourceManager", KTVHCLogEnableValueConsoleLog(DataSourceManager), KTVHCLogEnableValueRecordLog(DataSourceManager), ##__VA_ARGS__)
 #define KTVHCLogDataSourceManager(...)      KTVHCLogging(@"KTVHCDataSourceManager", KTVHCLogEnableValueConsoleLog(DataSourceManager), KTVHCLogEnableValueRecordLog(DataSourceManager), ##__VA_ARGS__)
-#define KTVHCLogDataSourceQueue(...)        KTVHCLogging(@"KTVHCDataSourceQueue  ", KTVHCLogEnableValueConsoleLog(DataSourceQueue),   KTVHCLogEnableValueRecordLog(DataSourceQueue),   ##__VA_ARGS__)
 #define KTVHCLogDataFileSource(...)         KTVHCLogging(@"KTVHCDataFileSource   ", KTVHCLogEnableValueConsoleLog(DataFileSource),    KTVHCLogEnableValueRecordLog(DataFileSource),    ##__VA_ARGS__)
 #define KTVHCLogDataFileSource(...)         KTVHCLogging(@"KTVHCDataFileSource   ", KTVHCLogEnableValueConsoleLog(DataFileSource),    KTVHCLogEnableValueRecordLog(DataFileSource),    ##__VA_ARGS__)
 #define KTVHCLogDataNetworkSource(...)      KTVHCLogging(@"KTVHCDataNetworkSource", KTVHCLogEnableValueConsoleLog(DataNetworkSource), KTVHCLogEnableValueRecordLog(DataNetworkSource), ##__VA_ARGS__)
 #define KTVHCLogDataNetworkSource(...)      KTVHCLogging(@"KTVHCDataNetworkSource", KTVHCLogEnableValueConsoleLog(DataNetworkSource), KTVHCLogEnableValueRecordLog(DataNetworkSource), ##__VA_ARGS__)
 
 
@@ -136,24 +128,25 @@ if (([KTVHCLog log].consoleLogEnable && console_log_enable) || ([KTVHCLog log].r
  *  DEBUG   : default is NO.
  *  DEBUG   : default is NO.
  *  RELEASE : default is NO.
  *  RELEASE : default is NO.
  */
  */
-@property (nonatomic, assign) BOOL consoleLogEnable;
+@property (nonatomic) BOOL consoleLogEnable;
 
 
 /**
 /**
  *  DEBUG   : default is NO.
  *  DEBUG   : default is NO.
  *  RELEASE : default is NO.
  *  RELEASE : default is NO.
  */
  */
-@property (nonatomic, assign) BOOL recordLogEnable;
+@property (nonatomic) BOOL recordLogEnable;
 
 
 - (void)addRecordLog:(NSString *)log;
 - (void)addRecordLog:(NSString *)log;
 
 
-- (NSString *)recordLogFilePath;
-- (void)deleteRecordLog;
+- (NSURL *)recordLogFileURL;
+- (void)deleteRecordLogFile;
 
 
 /**
 /**
  *  Error
  *  Error
  */
  */
-- (NSError *)lastError;
-- (NSArray <NSError *> *)allErrors;
-- (void)addError:(NSError *)error;
+- (void)addError:(NSError *)error forURL:(NSURL *)URL;
+- (NSDictionary<NSURL *, NSError *> *)errors;
+- (NSError *)errorForURL:(NSURL *)URL;
+- (void)cleanErrorForURL:(NSURL *)URL;
 
 
 @end
 @end

+ 48 - 47
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCLog.m

@@ -7,15 +7,15 @@
 //
 //
 
 
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
-#import "KTVHCPathTools.h"
+#import "KTVHCPathTool.h"
 
 
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 
 
 @interface KTVHCLog ()
 @interface KTVHCLog ()
 
 
-@property (nonatomic, strong) NSLock * lock;
-@property (nonatomic, strong) NSFileHandle * writingHandle;
-@property (nonatomic, strong) NSMutableArray <NSError *> * internalErrors;
+@property (nonatomic, strong) NSLock *lock;
+@property (nonatomic, strong) NSFileHandle *writingHandle;
+@property (nonatomic, strong) NSMutableDictionary<NSURL *, NSError *> *internalErrors;
 
 
 @end
 @end
 
 
@@ -23,7 +23,7 @@
 
 
 + (instancetype)log
 + (instancetype)log
 {
 {
-    static KTVHCLog * obj = nil;
+    static KTVHCLog *obj = nil;
     static dispatch_once_t onceToken;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     dispatch_once(&onceToken, ^{
         obj = [[self alloc] init];
         obj = [[self alloc] init];
@@ -33,54 +33,49 @@
 
 
 - (instancetype)init
 - (instancetype)init
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         self.consoleLogEnable = NO;
         self.consoleLogEnable = NO;
         self.recordLogEnable = NO;
         self.recordLogEnable = NO;
         self.lock = [[NSLock alloc] init];
         self.lock = [[NSLock alloc] init];
-        self.internalErrors = [NSMutableArray array];
+        self.internalErrors = [NSMutableDictionary dictionary];
     }
     }
     return self;
     return self;
 }
 }
 
 
 - (void)addRecordLog:(NSString *)log
 - (void)addRecordLog:(NSString *)log
 {
 {
-    if (!self.recordLogEnable)
-    {
+    if (!self.recordLogEnable) {
         return;
         return;
     }
     }
-    if (log.length <= 0)
-    {
+    if (log.length <= 0) {
         return;
         return;
     }
     }
     [self.lock lock];
     [self.lock lock];
-    NSString * string = [NSString stringWithFormat:@"%@  %@\n", [NSDate date], log];
-    NSData * data = [string dataUsingEncoding:NSUTF8StringEncoding];
-    if (!self.writingHandle)
-    {
-        [KTVHCPathTools deleteFileAtPath:[KTVHCPathTools logPath]];
-        [KTVHCPathTools createFileAtPath:[KTVHCPathTools logPath]];
-        self.writingHandle = [NSFileHandle fileHandleForWritingAtPath:[KTVHCPathTools logPath]];
+    NSString *string = [NSString stringWithFormat:@"%@  %@\n", [NSDate date], log];
+    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
+    if (!self.writingHandle) {
+        [KTVHCPathTool deleteFileAtPath:[KTVHCPathTool logPath]];
+        [KTVHCPathTool createFileAtPath:[KTVHCPathTool logPath]];
+        self.writingHandle = [NSFileHandle fileHandleForWritingAtPath:[KTVHCPathTool logPath]];
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
     }
     }
     [self.writingHandle writeData:data];
     [self.writingHandle writeData:data];
     [self.lock unlock];
     [self.lock unlock];
 }
 }
 
 
-- (NSString *)recordLogFilePath
+- (NSURL *)recordLogFileURL
 {
 {
-    NSString * path = nil;
+    NSURL *URL = nil;
     [self.lock lock];
     [self.lock lock];
-    long long size = [KTVHCPathTools sizeOfItemAtPath:[KTVHCPathTools logPath]];
-    if (size > 0)
-    {
-        path = [KTVHCPathTools logPath];
+    long long size = [KTVHCPathTool sizeAtPath:[KTVHCPathTool logPath]];
+    if (size > 0) {
+        URL = [NSURL fileURLWithPath:[KTVHCPathTool logPath]];
     }
     }
     [self.lock unlock];
     [self.lock unlock];
-    return path;
+    return URL;
 }
 }
 
 
-- (void)deleteRecordLog
+- (void)deleteRecordLogFile
 {
 {
     [self.lock lock];
     [self.lock lock];
     [self.writingHandle synchronizeFile];
     [self.writingHandle synchronizeFile];
@@ -90,41 +85,47 @@
     [self.lock unlock];
     [self.lock unlock];
 }
 }
 
 
-- (NSError *)lastError
+- (void)addError:(NSError *)error forURL:(NSURL *)URL
 {
 {
-    if (self.internalErrors.count > 0)
-    {
-        return self.internalErrors.lastObject;
+    if (!URL || ![error isKindOfClass:[NSError class]]) {
+        return;
     }
     }
-    return nil;
+    [self.lock lock];
+    [self.internalErrors setObject:error forKey:URL];
+    [self.lock unlock];
 }
 }
 
 
-- (NSArray<NSError *> *)allErrors
+- (NSDictionary<NSURL *,NSError *> *)errors
 {
 {
-    if (self.internalErrors.count > 0)
-    {
-        return [self.internalErrors copy];
-    }
-    return nil;
+    [self.lock lock];
+    NSDictionary<NSURL *,NSError *> *ret = [self.internalErrors copy];
+    [self.lock unlock];
+    return ret;
 }
 }
 
 
-- (void)addError:(NSError *)error
+- (NSError *)errorForURL:(NSURL *)URL
 {
 {
-    if (error && [error isKindOfClass:[NSError class]])
-    {
-        if (self.internalErrors.count >= 20)
-        {
-            [self.internalErrors removeObjectAtIndex:0];
-        }
-        [self.internalErrors addObject:error];
+    if (!URL) {
+        return nil;
     }
     }
+    [self.lock lock];
+    NSError *ret = [self.internalErrors objectForKey:URL];
+    [self.lock unlock];
+    return ret;
+}
+
+- (void)cleanErrorForURL:(NSURL *)URL
+{
+    [self.lock lock];
+    [self.internalErrors removeObjectForKey:URL];
+    [self.lock unlock];
 }
 }
 
 
 #pragma mark - UIApplicationWillTerminateNotification
 #pragma mark - UIApplicationWillTerminateNotification
 
 
 - (void)applicationWillTerminate:(NSNotification *)notification
 - (void)applicationWillTerminate:(NSNotification *)notification
 {
 {
-    [self deleteRecordLog];
+    [self deleteRecordLogFile];
 }
 }
 
 
 @end
 @end

+ 6 - 5
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCRange.h

@@ -21,14 +21,15 @@ BOOL KTVHCRangeIsInvaild(KTVHCRange range);
 BOOL KTVHCEqualRanges(KTVHCRange range1, KTVHCRange range2);
 BOOL KTVHCEqualRanges(KTVHCRange range1, KTVHCRange range2);
 long long KTVHCRangeGetLength(KTVHCRange range);
 long long KTVHCRangeGetLength(KTVHCRange range);
 NSString * KTVHCStringFromRange(KTVHCRange range);
 NSString * KTVHCStringFromRange(KTVHCRange range);
-NSDictionary * KTVHCRangeFillToRequestHeaders(KTVHCRange range, NSDictionary * headers);
-NSDictionary * KTVHCRangeFillToResponseHeaders(KTVHCRange range, NSDictionary * headers, long long totalLength);
+NSDictionary * KTVHCRangeFillToRequestHeaders(KTVHCRange range, NSDictionary *eaders);
+NSDictionary * KTVHCRangeFillToRequestHeadersIfNeeded(KTVHCRange range, NSDictionary *headers);
+NSDictionary * KTVHCRangeFillToResponseHeaders(KTVHCRange range, NSDictionary *headers, long long totalLength);
 
 
 KTVHCRange KTVHCMakeRange(long long start, long long end);
 KTVHCRange KTVHCMakeRange(long long start, long long end);
 KTVHCRange KTVHCRangeZero(void);
 KTVHCRange KTVHCRangeZero(void);
 KTVHCRange KTVHCRangeFull(void);
 KTVHCRange KTVHCRangeFull(void);
 KTVHCRange KTVHCRangeInvaild(void);
 KTVHCRange KTVHCRangeInvaild(void);
-KTVHCRange KTVHCRangeWithSeparateValue(NSString * value);
-KTVHCRange KTVHCRangeWithRequestHeaderValue(NSString * value);
-KTVHCRange KTVHCRangeWithResponseHeaderValue(NSString * value, long long * totalLength);
+KTVHCRange KTVHCRangeWithSeparateValue(NSString *value);
+KTVHCRange KTVHCRangeWithRequestHeaderValue(NSString *value);
+KTVHCRange KTVHCRangeWithResponseHeaderValue(NSString *value, long long *totalLength);
 KTVHCRange KTVHCRangeWithEnsureLength(KTVHCRange range, long long ensureLength);
 KTVHCRange KTVHCRangeWithEnsureLength(KTVHCRange range, long long ensureLength);

+ 38 - 45
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCRange.m

@@ -30,43 +30,48 @@ BOOL KTVHCEqualRanges(KTVHCRange range1, KTVHCRange range2)
 
 
 long long KTVHCRangeGetLength(KTVHCRange range)
 long long KTVHCRangeGetLength(KTVHCRange range)
 {
 {
-    if (range.start == KTVHCNotFound || range.end == KTVHCNotFound)
-    {
+    if (range.start == KTVHCNotFound || range.end == KTVHCNotFound) {
         return KTVHCNotFound;
         return KTVHCNotFound;
     }
     }
     return range.end - range.start + 1;
     return range.end - range.start + 1;
 }
 }
 
 
-NSString * KTVHCStringFromRange(KTVHCRange range)
+NSString *KTVHCStringFromRange(KTVHCRange range)
 {
 {
     return [NSString stringWithFormat:@"Range : {%lld, %lld}", range.start, range.end];
     return [NSString stringWithFormat:@"Range : {%lld, %lld}", range.start, range.end];
 }
 }
 
 
-NSString * KTVHCRangeGetHeaderString(KTVHCRange range)
+NSString *KTVHCRangeGetHeaderString(KTVHCRange range)
 {
 {
-    NSMutableString * string = [NSMutableString stringWithFormat:@"bytes="];
-    if (range.start != KTVHCNotFound)
-    {
+    NSMutableString *string = [NSMutableString stringWithFormat:@"bytes="];
+    if (range.start != KTVHCNotFound) {
         [string appendFormat:@"%lld", range.start];
         [string appendFormat:@"%lld", range.start];
     }
     }
     [string appendFormat:@"-"];
     [string appendFormat:@"-"];
-    if (range.end != KTVHCNotFound)
-    {
+    if (range.end != KTVHCNotFound) {
         [string appendFormat:@"%lld", range.end];
         [string appendFormat:@"%lld", range.end];
     }
     }
     return [string copy];
     return [string copy];
 }
 }
 
 
-NSDictionary * KTVHCRangeFillToRequestHeaders(KTVHCRange range, NSDictionary * headers)
+NSDictionary *KTVHCRangeFillToRequestHeaders(KTVHCRange range, NSDictionary *headers)
 {
 {
-    NSMutableDictionary * ret = [NSMutableDictionary dictionaryWithDictionary:headers];
+    NSMutableDictionary *ret = [NSMutableDictionary dictionaryWithDictionary:headers];
     [ret setObject:KTVHCRangeGetHeaderString(range) forKey:@"Range"];
     [ret setObject:KTVHCRangeGetHeaderString(range) forKey:@"Range"];
     return ret;
     return ret;
 }
 }
 
 
-NSDictionary * KTVHCRangeFillToResponseHeaders(KTVHCRange range, NSDictionary * headers, long long totalLength)
+NSDictionary *KTVHCRangeFillToRequestHeadersIfNeeded(KTVHCRange range, NSDictionary *headers)
 {
 {
-    NSMutableDictionary * ret = [NSMutableDictionary dictionaryWithDictionary:headers];
+    if ([headers objectForKey:@"Range"]) {
+        return headers;
+    }
+    return KTVHCRangeFillToRequestHeaders(range, headers);
+}
+
+NSDictionary *KTVHCRangeFillToResponseHeaders(KTVHCRange range, NSDictionary *headers, long long totalLength)
+{
+    NSMutableDictionary *ret = [NSMutableDictionary dictionaryWithDictionary:headers];
     long long currentLength = KTVHCRangeGetLength(range);
     long long currentLength = KTVHCRangeGetLength(range);
     [ret setObject:[NSString stringWithFormat:@"%lld", currentLength] forKey:@"Content-Length"];
     [ret setObject:[NSString stringWithFormat:@"%lld", currentLength] forKey:@"Content-Length"];
     [ret setObject:[NSString stringWithFormat:@"bytes %lld-%lld/%lld", range.start, range.end, totalLength] forKey:@"Content-Range"];
     [ret setObject:[NSString stringWithFormat:@"bytes %lld-%lld/%lld", range.start, range.end, totalLength] forKey:@"Content-Range"];
@@ -94,35 +99,27 @@ KTVHCRange KTVHCRangeInvaild()
     return KTVHCMakeRange(KTVHCNotFound, KTVHCNotFound);
     return KTVHCMakeRange(KTVHCNotFound, KTVHCNotFound);
 }
 }
 
 
-KTVHCRange KTVHCRangeWithSeparateValue(NSString * value)
+KTVHCRange KTVHCRangeWithSeparateValue(NSString *value)
 {
 {
     KTVHCRange range = KTVHCRangeInvaild();
     KTVHCRange range = KTVHCRangeInvaild();
-    if (value.length > 0)
-    {
-        NSArray * components = [value componentsSeparatedByString:@","];
-        if (components.count == 1)
-        {
+    if (value.length > 0) {
+        NSArray *components = [value componentsSeparatedByString:@","];
+        if (components.count == 1) {
             components = [components.firstObject componentsSeparatedByString:@"-"];
             components = [components.firstObject componentsSeparatedByString:@"-"];
-            if (components.count == 2)
-            {
-                NSString * startString = [components objectAtIndex:0];
+            if (components.count == 2) {
+                NSString *startString = [components objectAtIndex:0];
                 NSInteger startValue = [startString integerValue];
                 NSInteger startValue = [startString integerValue];
-                NSString * endString = [components objectAtIndex:1];
+                NSString *endString = [components objectAtIndex:1];
                 NSInteger endValue = [endString integerValue];
                 NSInteger endValue = [endString integerValue];
-                if (startString.length && (startValue >= 0) && endString.length && (endValue >= startValue))
-                {
+                if (startString.length && (startValue >= 0) && endString.length && (endValue >= startValue)) {
                     // The second 500 bytes: "500-999"
                     // The second 500 bytes: "500-999"
                     range.start = startValue;
                     range.start = startValue;
                     range.end = endValue;
                     range.end = endValue;
-                }
-                else if (startString.length && (startValue >= 0))
-                {
+                } else if (startString.length && (startValue >= 0)) {
                     // The bytes after 9500 bytes: "9500-"
                     // The bytes after 9500 bytes: "9500-"
                     range.start = startValue;
                     range.start = startValue;
                     range.end = KTVHCNotFound;
                     range.end = KTVHCNotFound;
-                }
-                else if (endString.length && (endValue > 0))
-                {
+                } else if (endString.length && (endValue > 0)) {
                     // The final 500 bytes: "-500"
                     // The final 500 bytes: "-500"
                     range.start = KTVHCNotFound;
                     range.start = KTVHCNotFound;
                     range.end = endValue;
                     range.end = endValue;
@@ -133,27 +130,24 @@ KTVHCRange KTVHCRangeWithSeparateValue(NSString * value)
     return range;
     return range;
 }
 }
 
 
-KTVHCRange KTVHCRangeWithRequestHeaderValue(NSString * value)
+KTVHCRange KTVHCRangeWithRequestHeaderValue(NSString *value)
 {
 {
-    if ([value hasPrefix:@"bytes="])
-    {
-        NSString * rangeString = [value substringFromIndex:6];
+    if ([value hasPrefix:@"bytes="]) {
+        NSString *rangeString = [value substringFromIndex:6];
         return KTVHCRangeWithSeparateValue(rangeString);
         return KTVHCRangeWithSeparateValue(rangeString);
     }
     }
     return KTVHCRangeInvaild();
     return KTVHCRangeInvaild();
 }
 }
 
 
-KTVHCRange KTVHCRangeWithResponseHeaderValue(NSString * value, long long * totalLength)
+KTVHCRange KTVHCRangeWithResponseHeaderValue(NSString *value, long long *totalLength)
 {
 {
-    if ([value hasPrefix:@"bytes "])
-    {
+    if ([value hasPrefix:@"bytes "]) {
         value = [value stringByReplacingOccurrencesOfString:@"bytes " withString:@""];
         value = [value stringByReplacingOccurrencesOfString:@"bytes " withString:@""];
         NSRange range = [value rangeOfString:@"/"];
         NSRange range = [value rangeOfString:@"/"];
-        if (range.location != NSNotFound)
-        {
-            NSString * rangeString = [value substringToIndex:range.location];
-            NSString * totalLengthString = [value substringFromIndex:range.location + range.length];
-            * totalLength = totalLengthString.longLongValue;
+        if (range.location != NSNotFound) {
+            NSString *rangeString = [value substringToIndex:range.location];
+            NSString *totalLengthString = [value substringFromIndex:range.location + range.length];
+            *totalLength = totalLengthString.longLongValue;
             return KTVHCRangeWithSeparateValue(rangeString);
             return KTVHCRangeWithSeparateValue(rangeString);
         }
         }
     }
     }
@@ -162,8 +156,7 @@ KTVHCRange KTVHCRangeWithResponseHeaderValue(NSString * value, long long * total
 
 
 KTVHCRange KTVHCRangeWithEnsureLength(KTVHCRange range, long long ensureLength)
 KTVHCRange KTVHCRangeWithEnsureLength(KTVHCRange range, long long ensureLength)
 {
 {
-    if (range.end == KTVHCNotFound && ensureLength > 0)
-    {
+    if (range.end == KTVHCNotFound && ensureLength > 0) {
         return KTVHCMakeRange(range.start, ensureLength - 1);
         return KTVHCMakeRange(range.start, ensureLength - 1);
     }
     }
     return range;
     return range;

+ 6 - 5
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItem.h

@@ -15,10 +15,11 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-@property (nonatomic, copy, readonly) NSURL * URL;
-@property (nonatomic, assign, readonly) long long totalLength;
-@property (nonatomic, assign, readonly) long long cacheLength;
-@property (nonatomic, assign, readonly) long long vaildLength;
-@property (nonatomic, copy, readonly) NSArray <KTVHCDataCacheItemZone *> * zones;
+@property (nonatomic, copy, readonly) NSURL *URL;
+@property (nonatomic, copy, readonly) NSArray<KTVHCDataCacheItemZone *> *zones;
+
+@property (nonatomic, readonly) long long totalLength;
+@property (nonatomic, readonly) long long cacheLength;
+@property (nonatomic, readonly) long long vaildLength;
 
 
 @end
 @end

+ 8 - 22
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItem.m

@@ -7,36 +7,22 @@
 //
 //
 
 
 #import "KTVHCDataCacheItem.h"
 #import "KTVHCDataCacheItem.h"
-#import "KTVHCDataPrivate.h"
+#import "KTVHCData+Internal.h"
 
 
 @implementation KTVHCDataCacheItem
 @implementation KTVHCDataCacheItem
 
 
-+ (instancetype)itemWithURL:(NSURL *)URL
-                totalLength:(long long)totalLength
-                cacheLength:(long long)cacheLength
-                vaildLength:(long long)vaildLength
-                      zones:(NSArray <KTVHCDataCacheItemZone *> *)zones
-{
-    return [[self alloc] initWithURL:URL
-                         totalLength:totalLength
-                         cacheLength:cacheLength
-                         vaildLength:vaildLength
-                               zones:zones];
-}
-
 - (instancetype)initWithURL:(NSURL *)URL
 - (instancetype)initWithURL:(NSURL *)URL
+                      zones:(NSArray<KTVHCDataCacheItemZone *> *)zones
                 totalLength:(long long)totalLength
                 totalLength:(long long)totalLength
                 cacheLength:(long long)cacheLength
                 cacheLength:(long long)cacheLength
                 vaildLength:(long long)vaildLength
                 vaildLength:(long long)vaildLength
-                      zones:(NSArray <KTVHCDataCacheItemZone *> *)zones
 {
 {
-    if (self = [super init])
-    {
-        _URL = URL;
-        _totalLength = totalLength;
-        _cacheLength = cacheLength;
-        _vaildLength = vaildLength;
-        _zones = zones;
+    if (self = [super init]) {
+        self->_URL = [URL copy];
+        self->_zones = [zones copy];
+        self->_totalLength = totalLength;
+        self->_cacheLength = cacheLength;
+        self->_vaildLength = vaildLength;
     }
     }
     return self;
     return self;
 }
 }

+ 2 - 2
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItemZone.h

@@ -13,7 +13,7 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-@property (nonatomic, assign, readonly) long long offset;
-@property (nonatomic, assign, readonly) long long length;
+@property (nonatomic, readonly) long long offset;
+@property (nonatomic, readonly) long long length;
 
 
 @end
 @end

+ 4 - 10
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataCacheItemZone.m

@@ -7,21 +7,15 @@
 //
 //
 
 
 #import "KTVHCDataCacheItemZone.h"
 #import "KTVHCDataCacheItemZone.h"
-#import "KTVHCDataPrivate.h"
+#import "KTVHCData+Internal.h"
 
 
 @implementation KTVHCDataCacheItemZone
 @implementation KTVHCDataCacheItemZone
 
 
-+ (instancetype)itemZoneWithOffset:(long long)offset length:(long long)length
-{
-    return [[self alloc] initWithOffset:offset length:length];
-}
-
 - (instancetype)initWithOffset:(long long)offset length:(long long)length
 - (instancetype)initWithOffset:(long long)offset length:(long long)length
 {
 {
-    if (self = [super init])
-    {
-        _offset = offset;
-        _length = length;
+    if (self = [super init]) {
+        self->_offset = offset;
+        self->_length = length;
     }
     }
     return self;
     return self;
 }
 }

+ 7 - 17
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataFileSource.h

@@ -7,36 +7,26 @@
 //
 //
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
-#import "KTVHCDataSourceProtocol.h"
+#import "KTVHCDataSource.h"
 
 
 @class KTVHCDataFileSource;
 @class KTVHCDataFileSource;
 
 
 @protocol KTVHCDataFileSourceDelegate <NSObject>
 @protocol KTVHCDataFileSourceDelegate <NSObject>
 
 
-- (void)fileSourceDidPrepared:(KTVHCDataFileSource *)fileSource;
-- (void)fileSource:(KTVHCDataFileSource *)fileSource didFailed:(NSError *)error;
+- (void)ktv_fileSourceDidPrepare:(KTVHCDataFileSource *)fileSource;
+- (void)ktv_fileSource:(KTVHCDataFileSource *)fileSource didFailWithError:(NSError *)error;
 
 
 @end
 @end
 
 
-@interface KTVHCDataFileSource : NSObject <KTVHCDataSourceProtocol>
+@interface KTVHCDataFileSource : NSObject <KTVHCDataSource>
 
 
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithPath:(NSString *)path range:(KTVHCRange)range readRange:(KTVHCRange)readRange;
+- (instancetype)initWithPath:(NSString *)path range:(KTVHCRange)range readRange:(KTVHCRange)readRange NS_DESIGNATED_INITIALIZER;
 
 
-@property (nonatomic, copy, readonly) NSString * path;
-@property (nonatomic, assign, readonly) KTVHCRange range;
-@property (nonatomic, assign, readonly) KTVHCRange readRange;
-
-@property (nonatomic, assign, readonly) BOOL didPrepared;
-@property (nonatomic, assign, readonly) BOOL didFinished;
-@property (nonatomic, assign, readonly) BOOL didClosed;
-
-- (void)prepare;
-- (void)close;
-
-- (NSData *)readDataOfLength:(NSUInteger)length;
+@property (nonatomic, copy, readonly) NSString *path;
+@property (nonatomic, readonly) KTVHCRange readRange;
 
 
 @property (nonatomic, weak, readonly) id<KTVHCDataFileSourceDelegate> delegate;
 @property (nonatomic, weak, readonly) id<KTVHCDataFileSourceDelegate> delegate;
 @property (nonatomic, strong, readonly) dispatch_queue_t delegateQueue;
 @property (nonatomic, strong, readonly) dispatch_queue_t delegateQueue;

+ 42 - 58
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataFileSource.m

@@ -13,23 +13,28 @@
 
 
 @interface KTVHCDataFileSource () <NSLocking>
 @interface KTVHCDataFileSource () <NSLocking>
 
 
-@property (nonatomic, strong) NSError * error;
-@property (nonatomic, strong) NSLock * coreLock;
-@property (nonatomic, strong) NSFileHandle * readingHandle;
-@property (nonatomic, assign) long long readedLength;
+@property (nonatomic, strong) NSLock *coreLock;
+@property (nonatomic, strong) NSFileHandle *readingHandle;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataFileSource
 @implementation KTVHCDataFileSource
 
 
+@synthesize error = _error;
+@synthesize range = _range;
+@synthesize closed = _closed;
+@synthesize prepared = _prepared;
+@synthesize finished = _finished;
+@synthesize readedLength = _readedLength;
+
 - (instancetype)initWithPath:(NSString *)path range:(KTVHCRange)range readRange:(KTVHCRange)readRange
 - (instancetype)initWithPath:(NSString *)path range:(KTVHCRange)range readRange:(KTVHCRange)readRange
 {
 {
     if (self = [super init])
     if (self = [super init])
     {
     {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
-        _path = path;
-        _range = range;
-        _readRange = readRange;
+        self->_path = path;
+        self->_range = range;
+        self->_readRange = readRange;
         KTVHCLogDataFileSource(@"%p, Create file source\npath : %@\nrange : %@\nreadRange : %@", self, path, KTVHCStringFromRange(range), KTVHCStringFromRange(readRange));
         KTVHCLogDataFileSource(@"%p, Create file source\npath : %@\nrange : %@\nreadRange : %@", self, path, KTVHCStringFromRange(range), KTVHCStringFromRange(readRange));
     }
     }
     return self;
     return self;
@@ -43,30 +48,25 @@
 - (void)prepare
 - (void)prepare
 {
 {
     [self lock];
     [self lock];
-    if (self.didPrepared)
-    {
+    if (self.isPrepared) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
     KTVHCLogDataFileSource(@"%p, Call prepare", self);
     KTVHCLogDataFileSource(@"%p, Call prepare", self);
     self.readingHandle = [NSFileHandle fileHandleForReadingAtPath:self.path];
     self.readingHandle = [NSFileHandle fileHandleForReadingAtPath:self.path];
-    @try
-    {
+    @try {
         [self.readingHandle seekToFileOffset:self.readRange.start];
         [self.readingHandle seekToFileOffset:self.readRange.start];
-        _didPrepared = YES;
-        if ([self.delegate respondsToSelector:@selector(fileSourceDidPrepared:)])
-        {
+        self->_prepared = YES;
+        if ([self.delegate respondsToSelector:@selector(ktv_fileSourceDidPrepare:)]) {
             KTVHCLogDataFileSource(@"%p, Callback for prepared - Begin", self);
             KTVHCLogDataFileSource(@"%p, Callback for prepared - Begin", self);
             [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
                 KTVHCLogDataFileSource(@"%p, Callback for prepared - End", self);
                 KTVHCLogDataFileSource(@"%p, Callback for prepared - End", self);
-                [self.delegate fileSourceDidPrepared:self];
+                [self.delegate ktv_fileSourceDidPrepare:self];
             }];
             }];
         }
         }
-    }
-    @catch (NSException * exception)
-    {
+    } @catch (NSException *exception) {
         KTVHCLogDataFileSource(@"%p, Seek file exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         KTVHCLogDataFileSource(@"%p, Seek file exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
-        NSError * error = [KTVHCError errorForException:exception];
+        NSError *error = [KTVHCError errorForException:exception];
         [self callbackForFailed:error];
         [self callbackForFailed:error];
     }
     }
     [self unlock];
     [self unlock];
@@ -75,12 +75,11 @@
 - (void)close
 - (void)close
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didClosed = YES;
+    self->_closed = YES;
     KTVHCLogDataFileSource(@"%p, Call close", self);
     KTVHCLogDataFileSource(@"%p, Call close", self);
     [self destoryReadingHandle];
     [self destoryReadingHandle];
     [self unlock];
     [self unlock];
@@ -89,38 +88,31 @@
 - (NSData *)readDataOfLength:(NSUInteger)length
 - (NSData *)readDataOfLength:(NSUInteger)length
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    if (self.didFinished)
-    {
+    if (self.isFinished) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    NSData * data = nil;
-    @try
-    {
+    NSData *data = nil;
+    @try {
         long long readLength = KTVHCRangeGetLength(self.readRange);
         long long readLength = KTVHCRangeGetLength(self.readRange);
         length = (NSUInteger)MIN(readLength - self.readedLength, length);
         length = (NSUInteger)MIN(readLength - self.readedLength, length);
         data = [self.readingHandle readDataOfLength:length];
         data = [self.readingHandle readDataOfLength:length];
-        if (data.length > 0)
-        {
-            self.readedLength += data.length;
+        self->_readedLength += data.length;
+        if (data.length > 0) {
             KTVHCLogDataFileSource(@"%p, Read data : %lld, %lld, %lld", self, (long long)data.length, self.readedLength, readLength);
             KTVHCLogDataFileSource(@"%p, Read data : %lld, %lld, %lld", self, (long long)data.length, self.readedLength, readLength);
         }
         }
-        if (self.readedLength >= readLength)
-        {
+        if (self.readedLength >= readLength) {
             KTVHCLogDataFileSource(@"%p, Read data did finished", self);
             KTVHCLogDataFileSource(@"%p, Read data did finished", self);
             [self destoryReadingHandle];
             [self destoryReadingHandle];
-            _didFinished = YES;
+            self->_finished = YES;
         }
         }
-    }
-    @catch (NSException * exception)
-    {
+    } @catch (NSException *exception) {
         KTVHCLogDataFileSource(@"%p, Read exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         KTVHCLogDataFileSource(@"%p, Read exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
-        NSError * error = [KTVHCError errorForException:exception];
+        NSError *error = [KTVHCError errorForException:exception];
         [self callbackForFailed:error];
         [self callbackForFailed:error];
     }
     }
     [self unlock];
     [self unlock];
@@ -129,14 +121,10 @@
 
 
 - (void)destoryReadingHandle
 - (void)destoryReadingHandle
 {
 {
-    if (self.readingHandle)
-    {
-        @try
-        {
+    if (self.readingHandle) {
+        @try {
             [self.readingHandle closeFile];
             [self.readingHandle closeFile];
-        }
-        @catch (NSException * exception)
-        {
+        } @catch (NSException *exception) {
             KTVHCLogDataFileSource(@"%p, Close exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
             KTVHCLogDataFileSource(@"%p, Close exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         }
         }
         self.readingHandle = nil;
         self.readingHandle = nil;
@@ -145,35 +133,31 @@
 
 
 - (void)callbackForFailed:(NSError *)error
 - (void)callbackForFailed:(NSError *)error
 {
 {
-    if (!error)
-    {
+    if (!error) {
         return;
         return;
     }
     }
-    if (self.error)
-    {
+    if (self.error) {
         return;
         return;
     }
     }
-    self.error = error;
-    if ([self.delegate respondsToSelector:@selector(fileSource:didFailed:)])
-    {
+    self->_error = error;
+    if ([self.delegate respondsToSelector:@selector(ktv_fileSource:didFailWithError:)]) {
         KTVHCLogDataFileSource(@"%p, Callback for prepared - Begin", self);
         KTVHCLogDataFileSource(@"%p, Callback for prepared - Begin", self);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataFileSource(@"%p, Callback for prepared - End", self);
             KTVHCLogDataFileSource(@"%p, Callback for prepared - End", self);
-            [self.delegate fileSource:self didFailed:self.error];
+            [self.delegate ktv_fileSource:self didFailWithError:self.error];
         }];
         }];
     }
     }
 }
 }
 
 
 - (void)setDelegate:(id <KTVHCDataFileSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
 - (void)setDelegate:(id <KTVHCDataFileSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
 {
 {
-    _delegate = delegate;
-    _delegateQueue = delegateQueue;
+    self->_delegate = delegate;
+    self->_delegateQueue = delegateQueue;
 }
 }
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSLock alloc] init];
         self.coreLock = [[NSLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];

+ 10 - 12
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataLoader.h

@@ -14,9 +14,9 @@
 
 
 @protocol KTVHCDataLoaderDelegate <NSObject>
 @protocol KTVHCDataLoaderDelegate <NSObject>
 
 
-- (void)loaderDidFinished:(KTVHCDataLoader *)loader;
-- (void)loader:(KTVHCDataLoader *)loader didFailed:(NSError *)error;
-- (void)loader:(KTVHCDataLoader *)loader didChangeProgress:(double)progress;
+- (void)ktv_loaderDidFinish:(KTVHCDataLoader *)loader;
+- (void)ktv_loader:(KTVHCDataLoader *)loader didFailWithError:(NSError *)error;
+- (void)ktv_loader:(KTVHCDataLoader *)loader didChangeProgress:(double)progress;
 
 
 @end
 @end
 
 
@@ -25,21 +25,19 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-+ (instancetype)loaderWithRequest:(KTVHCDataRequest *)request;
-
 @property (nonatomic, weak) id <KTVHCDataLoaderDelegate> delegate;
 @property (nonatomic, weak) id <KTVHCDataLoaderDelegate> delegate;
-
 @property (nonatomic, strong) id object;
 @property (nonatomic, strong) id object;
 
 
-@property (nonatomic, strong, readonly) KTVHCDataRequest * request;
-@property (nonatomic, strong, readonly) KTVHCDataResponse * response;
+@property (nonatomic, strong, readonly) KTVHCDataRequest *request;
+@property (nonatomic, strong, readonly) KTVHCDataResponse *response;
 
 
-@property (nonatomic, strong, readonly) NSError * error;
+@property (nonatomic, copy, readonly) NSError *error;
 
 
-@property (nonatomic, assign, readonly) BOOL didClosed;
-@property (nonatomic, assign, readonly) BOOL didFinished;
+@property (nonatomic, readonly, getter=isFinished) BOOL finished;
+@property (nonatomic, readonly, getter=isClosed) BOOL closed;
 
 
-@property (nonatomic, assign, readonly) double progress;
+@property (nonatomic, readonly) long long loadedLength;
+@property (nonatomic, readonly) double progress;
 
 
 - (void)prepare;
 - (void)prepare;
 - (void)close;
 - (void)close;

+ 31 - 43
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataLoader.m

@@ -7,29 +7,22 @@
 //
 //
 
 
 #import "KTVHCDataLoader.h"
 #import "KTVHCDataLoader.h"
-#import "KTVHCDataReader.h"
-#import "KTVHCDataResponse.h"
+#import "KTVHCData+Internal.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCDataLoader () <KTVHCDataReaderDelegate>
 @interface KTVHCDataLoader () <KTVHCDataReaderDelegate>
 
 
-@property (nonatomic, strong) KTVHCDataReader * reader;
+@property (nonatomic, strong) KTVHCDataReader *reader;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataLoader
 @implementation KTVHCDataLoader
 
 
-+ (instancetype)loaderWithRequest:(KTVHCDataRequest *)request
-{
-    return [[self alloc] initWithRequest:request];
-}
-
 - (instancetype)initWithRequest:(KTVHCDataRequest *)request
 - (instancetype)initWithRequest:(KTVHCDataRequest *)request
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
-        self.reader = [KTVHCDataReader readerWithRequest:request];
+        self.reader = [[KTVHCDataReader alloc] initWithRequest:request];
         self.reader.delegate = self;
         self.reader.delegate = self;
         KTVHCLogDataLoader(@"%p, Create loader\norignalRequest : %@\nreader : %@", self, request, self.reader);
         KTVHCLogDataLoader(@"%p, Create loader\norignalRequest : %@\nreader : %@", self, request, self.reader);
     }
     }
@@ -70,65 +63,60 @@
     return self.reader.error;
     return self.reader.error;
 }
 }
 
 
-- (BOOL)didClosed
+- (BOOL)isFinished
 {
 {
-    return self.reader.didClosed;
+    return self.reader.isFinished;
 }
 }
 
 
-- (BOOL)didFinished
+- (BOOL)isClosed
 {
 {
-    return self.reader.didFinished;
+    return self.reader.isClosed;
 }
 }
 
 
 #pragma mark - KTVHCDataReaderDelegate
 #pragma mark - KTVHCDataReaderDelegate
 
 
-- (void)readerDidPrepared:(KTVHCDataReader *)reader
+- (void)ktv_readerDidPrepare:(KTVHCDataReader *)reader
 {
 {
     [self readData];
     [self readData];
 }
 }
 
 
-- (void)readerHasAvailableData:(KTVHCDataReader *)reader
+- (void)ktv_readerHasAvailableData:(KTVHCDataReader *)reader
 {
 {
     [self readData];
     [self readData];
 }
 }
 
 
-- (void)reader:(KTVHCDataReader *)reader didFailed:(NSError *)error
+- (void)ktv_reader:(KTVHCDataReader *)reader didFailWithError:(NSError *)error
 {
 {
     KTVHCLogDataLoader(@"%p, Callback for failed", self);
     KTVHCLogDataLoader(@"%p, Callback for failed", self);
-    if ([self.delegate respondsToSelector:@selector(loader:didFailed:)])
-    {
-        [self.delegate loader:self didFailed:error];
+    if ([self.delegate respondsToSelector:@selector(ktv_loader:didFailWithError:)]) {
+        [self.delegate ktv_loader:self didFailWithError:error];
     }
     }
 }
 }
 
 
 - (void)readData
 - (void)readData
 {
 {
-    while (YES)
-    {
-        @autoreleasepool
-        {
-            NSData * data = [self.reader readDataOfLength:1024 * 1024 * 1];
-            if (self.reader.didFinished)
-            {
-                _progress = 1.0f;
-                if ([self.delegate respondsToSelector:@selector(loader:didChangeProgress:)])
-                {
-                    [self.delegate loader:self didChangeProgress:_progress];
+    while (YES) {
+        @autoreleasepool {
+            NSData *data = [self.reader readDataOfLength:1024 * 1024 * 1];
+            if (self.reader.isFinished) {
+                self->_loadedLength = self.reader.readedLength;
+                self->_progress = 1.0f;
+                if ([self.delegate respondsToSelector:@selector(ktv_loader:didChangeProgress:)]) {
+                    [self.delegate ktv_loader:self didChangeProgress:self.progress];
                 }
                 }
                 KTVHCLogDataLoader(@"%p, Callback finished", self);
                 KTVHCLogDataLoader(@"%p, Callback finished", self);
-                if ([self.delegate respondsToSelector:@selector(loaderDidFinished:)])
-                {
-                    [self.delegate loaderDidFinished:self];
+                if ([self.delegate respondsToSelector:@selector(ktv_loaderDidFinish:)]) {
+                    [self.delegate ktv_loaderDidFinish:self];
                 }
                 }
-            }
-            else if (data)
-            {
-                _progress = (double)self.reader.readOffset / (double)self.response.currentLength;
-                if ([self.delegate respondsToSelector:@selector(loader:didChangeProgress:)])
-                {
-                    [self.delegate loader:self didChangeProgress:_progress];
+            } else if (data) {
+                self->_loadedLength = self.reader.readedLength;
+                if (self.response.contentLength > 0) {
+                    self->_progress = (double)self.reader.readedLength / (double)self.response.contentLength;
+                }
+                if ([self.delegate respondsToSelector:@selector(ktv_loader:didChangeProgress:)]) {
+                    [self.delegate ktv_loader:self didChangeProgress:self.progress];
                 }
                 }
-                KTVHCLogDataLoader(@"%p, read data progress %f", self, _progress);
+                KTVHCLogDataLoader(@"%p, read data progress %f", self, self.progress);
                 continue;
                 continue;
             }
             }
             KTVHCLogDataLoader(@"%p, read data break", self);
             KTVHCLogDataLoader(@"%p, read data break", self);

+ 9 - 19
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataNetworkSource.h

@@ -7,7 +7,7 @@
 //
 //
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
-#import "KTVHCDataSourceProtocol.h"
+#import "KTVHCDataSource.h"
 #import "KTVHCDataRequest.h"
 #import "KTVHCDataRequest.h"
 #import "KTVHCDataResponse.h"
 #import "KTVHCDataResponse.h"
 
 
@@ -15,32 +15,22 @@
 
 
 @protocol KTVHCDataNetworkSourceDelegate <NSObject>
 @protocol KTVHCDataNetworkSourceDelegate <NSObject>
 
 
-- (void)networkSourceDidPrepared:(KTVHCDataNetworkSource *)networkSource;
-- (void)networkSourceHasAvailableData:(KTVHCDataNetworkSource *)networkSource;
-- (void)networkSourceDidFinishedDownload:(KTVHCDataNetworkSource *)networkSource;
-- (void)networkSource:(KTVHCDataNetworkSource *)networkSource didFailed:(NSError *)error;
+- (void)ktv_networkSourceDidPrepare:(KTVHCDataNetworkSource *)networkSource;
+- (void)ktv_networkSourceHasAvailableData:(KTVHCDataNetworkSource *)networkSource;
+- (void)ktv_networkSourceDidFinisheDownload:(KTVHCDataNetworkSource *)networkSource;
+- (void)ktv_networkSource:(KTVHCDataNetworkSource *)networkSource didFailWithError:(NSError *)error;
 
 
 @end
 @end
 
 
-@interface KTVHCDataNetworkSource : NSObject <KTVHCDataSourceProtocol>
+@interface KTVHCDataNetworkSource : NSObject <KTVHCDataSource>
 
 
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithRequest:(KTVHCDataRequest *)reqeust;
+- (instancetype)initWithRequest:(KTVHCDataRequest *)reqeust NS_DESIGNATED_INITIALIZER;
 
 
-@property (nonatomic, strong, readonly) KTVHCDataRequest * request;
-@property (nonatomic, strong, readonly) KTVHCDataResponse * response;
-@property (nonatomic, assign, readonly) KTVHCRange range;
-
-@property (nonatomic, assign, readonly) BOOL didPrepared;
-@property (nonatomic, assign, readonly) BOOL didFinished;
-@property (nonatomic, assign, readonly) BOOL didClosed;
-
-- (void)prepare;
-- (void)close;
-
-- (NSData *)readDataOfLength:(NSUInteger)length;
+@property (nonatomic, strong, readonly) KTVHCDataRequest *request;
+@property (nonatomic, strong, readonly) KTVHCDataResponse *response;
 
 
 @property (nonatomic, weak, readonly) id<KTVHCDataNetworkSourceDelegate> delegate;
 @property (nonatomic, weak, readonly) id<KTVHCDataNetworkSourceDelegate> delegate;
 @property (nonatomic, strong, readonly) dispatch_queue_t delegateQueue;
 @property (nonatomic, strong, readonly) dispatch_queue_t delegateQueue;

+ 87 - 131
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataNetworkSource.m

@@ -9,37 +9,42 @@
 #import "KTVHCDataNetworkSource.h"
 #import "KTVHCDataNetworkSource.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataCallback.h"
 #import "KTVHCDataCallback.h"
-#import "KTVHCPathTools.h"
+#import "KTVHCPathTool.h"
 #import "KTVHCDownload.h"
 #import "KTVHCDownload.h"
 #import "KTVHCError.h"
 #import "KTVHCError.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCDataNetworkSource () <NSLocking, KTVHCDownloadDelegate>
 @interface KTVHCDataNetworkSource () <NSLocking, KTVHCDownloadDelegate>
 
 
-@property (nonatomic, strong) NSError * error;
-@property (nonatomic, strong) NSLock * coreLock;
-@property (nonatomic, assign) long long downloadLength;
-@property (nonatomic, assign) long long downloadReadedLength;
-@property (nonatomic, assign) BOOL downloadDidCallComplete;
-@property (nonatomic, assign) BOOL needCallHasAvailableData;
-@property (nonatomic, assign) BOOL didCalledPrepare;
+@property (nonatomic, strong) NSLock *coreLock;
+@property (nonatomic, strong) NSFileHandle *readingHandle;
+@property (nonatomic, strong) NSFileHandle *writingHandle;
+@property (nonatomic, strong) KTVHCDataUnitItem *unitItem;
+@property (nonatomic, strong) NSURLSessionTask *downlaodTask;
 
 
-@property (nonatomic, strong) KTVHCDataUnitItem * unitItem;
-@property (nonatomic, strong) NSFileHandle * readingHandle;
-@property (nonatomic, strong) NSFileHandle * writingHandle;
-@property (nonatomic, assign) NSURLSessionTask * downlaodTask;
+@property (nonatomic) long long downloadLength;
+@property (nonatomic) BOOL downloadCalledComplete;
+@property (nonatomic) BOOL callHasAvailableData;
+@property (nonatomic) BOOL calledPrepare;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataNetworkSource
 @implementation KTVHCDataNetworkSource
 
 
+@synthesize error = _error;
+@synthesize range = _range;
+@synthesize closed = _closed;
+@synthesize prepared = _prepared;
+@synthesize finished = _finished;
+@synthesize readedLength = _readedLength;
+
 - (instancetype)initWithRequest:(KTVHCDataRequest *)reqeust
 - (instancetype)initWithRequest:(KTVHCDataRequest *)reqeust
 {
 {
     if (self = [super init])
     if (self = [super init])
     {
     {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
-        _request = reqeust;
-        _range = reqeust.range;
+        self->_request = reqeust;
+        self->_range = reqeust.range;
         KTVHCLogDataNetworkSource(@"%p, Create network source\nrequest : %@\nrange : %@", self, self.request, KTVHCStringFromRange(self.range));
         KTVHCLogDataNetworkSource(@"%p, Create network source\nrequest : %@\nrange : %@", self, self.request, KTVHCStringFromRange(self.range));
     }
     }
     return self;
     return self;
@@ -48,23 +53,21 @@
 - (void)dealloc
 - (void)dealloc
 {
 {
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
-    KTVHCLogDataNetworkSource(@"%p, Destory network source\nError : %@\ndownloadLength : %lld\nreadedLength : %lld", self, self.error, self.downloadLength, self.downloadReadedLength);
+    KTVHCLogDataNetworkSource(@"%p, Destory network source\nError : %@\ndownloadLength : %lld\nreadedLength : %lld", self, self.error, self.downloadLength, self.readedLength);
 }
 }
 
 
 - (void)prepare
 - (void)prepare
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    if (self.didCalledPrepare)
-    {
+    if (self.calledPrepare) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didCalledPrepare = YES;
+    self->_calledPrepare = YES;
     KTVHCLogDataNetworkSource(@"%p, Call prepare", self);
     KTVHCLogDataNetworkSource(@"%p, Call prepare", self);
     self.downlaodTask = [[KTVHCDownload download] downloadWithRequest:self.request delegate:self];
     self.downlaodTask = [[KTVHCDownload download] downloadWithRequest:self.request delegate:self];
     [self unlock];
     [self unlock];
@@ -73,15 +76,13 @@
 - (void)close
 - (void)close
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didClosed = YES;
+    self->_closed = YES;
     KTVHCLogDataNetworkSource(@"%p, Call close", self);
     KTVHCLogDataNetworkSource(@"%p, Call close", self);
-    if (!self.downloadDidCallComplete)
-    {
+    if (!self.downloadCalledComplete) {
         KTVHCLogDataNetworkSource(@"%p, Cancel download task", self);
         KTVHCLogDataNetworkSource(@"%p, Cancel download task", self);
         [self.downlaodTask cancel];
         [self.downlaodTask cancel];
         self.downlaodTask = nil;
         self.downlaodTask = nil;
@@ -94,43 +95,34 @@
 - (NSData *)readDataOfLength:(NSUInteger)length
 - (NSData *)readDataOfLength:(NSUInteger)length
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed || self.didFinished || self.error)
-    {
+    if (self.isClosed || self.isFinished || self.error) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    if (self.downloadReadedLength >= self.downloadLength)
-    {
-        if (self.downloadDidCallComplete)
-        {
-            KTVHCLogDataNetworkSource(@"%p, Read data failed\ndownloadLength : %lld\nreadedLength : %lld", self, self.downloadReadedLength, self.downloadLength);
+    if (self.readedLength >= self.downloadLength) {
+        if (self.downloadCalledComplete) {
+            KTVHCLogDataNetworkSource(@"%p, Read data failed\ndownloadLength : %lld\nreadedLength : %lld", self, self.readedLength, self.downloadLength);
             [self destoryReadingHandle];
             [self destoryReadingHandle];
-        }
-        else
-        {
+        } else {
             KTVHCLogDataNetworkSource(@"%p, Read data wait callback", self);
             KTVHCLogDataNetworkSource(@"%p, Read data wait callback", self);
-            self.needCallHasAvailableData = YES;
+            self.callHasAvailableData = YES;
         }
         }
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    NSData * data = nil;
-    @try
-    {
-        data = [self.readingHandle readDataOfLength:(NSUInteger)MIN(self.downloadLength - self.downloadReadedLength, length)];
-        self.downloadReadedLength += data.length;
-        KTVHCLogDataNetworkSource(@"%p, Read data\nLength : %lld\ndownloadLength : %lld\nreadedLength : %lld", self, (long long)data.length, self.downloadReadedLength, self.downloadLength);
-        if (self.downloadReadedLength >= KTVHCRangeGetLength(self.response.range))
-        {
-            _didFinished = YES;
+    NSData *data = nil;
+    @try {
+        data = [self.readingHandle readDataOfLength:(NSUInteger)MIN(self.downloadLength - self.readedLength, length)];
+        self->_readedLength += data.length;
+        KTVHCLogDataNetworkSource(@"%p, Read data\nLength : %lld\ndownloadLength : %lld\nreadedLength : %lld", self, (long long)data.length, self.readedLength, self.downloadLength);
+        if (self.readedLength >= KTVHCRangeGetLength(self.response.contentRange)) {
+            self->_finished = YES;
             KTVHCLogDataNetworkSource(@"%p, Read data did finished", self);
             KTVHCLogDataNetworkSource(@"%p, Read data did finished", self);
             [self destoryReadingHandle];
             [self destoryReadingHandle];
         }
         }
-    }
-    @catch (NSException * exception)
-    {
+    } @catch (NSException *exception) {
         KTVHCLogDataFileSource(@"%p, Read exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         KTVHCLogDataFileSource(@"%p, Read exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
-        NSError * error = [KTVHCError errorForException:exception];
+        NSError *error = [KTVHCError errorForException:exception];
         [self callbackForFailed:error];
         [self callbackForFailed:error];
     }
     }
     [self unlock];
     [self unlock];
@@ -139,63 +131,49 @@
 
 
 - (void)setDelegate:(id <KTVHCDataNetworkSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
 - (void)setDelegate:(id <KTVHCDataNetworkSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
 {
 {
-    _delegate = delegate;
-    _delegateQueue = delegateQueue;
+    self->_delegate = delegate;
+    self->_delegateQueue = delegateQueue;
 }
 }
 
 
-- (void)download:(KTVHCDownload *)download didCompleteWithError:(NSError *)error
+- (void)ktv_download:(KTVHCDownload *)download didCompleteWithError:(NSError *)error
 {
 {
     [self lock];
     [self lock];
-    self.downloadDidCallComplete = YES;
+    self.downloadCalledComplete = YES;
     [self destoryWritingHandle];
     [self destoryWritingHandle];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         KTVHCLogDataNetworkSource(@"%p, Complete but did closed\nError : %@", self, error);
         KTVHCLogDataNetworkSource(@"%p, Complete but did closed\nError : %@", self, error);
-    }
-    else if (self.error)
-    {
+    } else if (self.error) {
         KTVHCLogDataNetworkSource(@"%p, Complete but did failed\nself.error : %@\nerror : %@", self, self.error, error);
         KTVHCLogDataNetworkSource(@"%p, Complete but did failed\nself.error : %@\nerror : %@", self, self.error, error);
-    }
-    else if (error)
-    {
-        if (error.code != NSURLErrorCancelled)
-        {
+    } else if (error) {
+        if (error.code != NSURLErrorCancelled) {
             [self callbackForFailed:error];
             [self callbackForFailed:error];
-        }
-        else
-        {
+        } else {
             KTVHCLogDataNetworkSource(@"%p, Complete with cancel\nError : %@", self, error);
             KTVHCLogDataNetworkSource(@"%p, Complete with cancel\nError : %@", self, error);
         }
         }
-    }
-    else if (self.downloadLength >= KTVHCRangeGetLength(self.response.range))
-    {
+    } else if (self.downloadLength >= KTVHCRangeGetLength(self.response.contentRange)) {
         KTVHCLogDataNetworkSource(@"%p, Complete and finisehed", self);
         KTVHCLogDataNetworkSource(@"%p, Complete and finisehed", self);
-        if ([self.delegate respondsToSelector:@selector(networkSourceDidFinishedDownload:)])
-        {
+        if ([self.delegate respondsToSelector:@selector(ktv_networkSourceDidFinisheDownload:)]) {
             [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
-                [self.delegate networkSourceDidFinishedDownload:self];
+                [self.delegate ktv_networkSourceDidFinisheDownload:self];
             }];
             }];
         }
         }
-    }
-    else
-    {
+    } else {
         KTVHCLogDataNetworkSource(@"%p, Complete but not finisehed\ndownloadLength : %lld", self, self.downloadLength);
         KTVHCLogDataNetworkSource(@"%p, Complete but not finisehed\ndownloadLength : %lld", self, self.downloadLength);
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)download:(KTVHCDownload *)download didReceiveResponse:(KTVHCDataResponse *)response
+- (void)ktv_download:(KTVHCDownload *)download didReceiveResponse:(KTVHCDataResponse *)response
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed || self.error)
-    {
+    if (self.isClosed || self.error) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _response = response;
-    NSString * path = [KTVHCPathTools unitItemPathWithURL:self.request.URL offset:self.request.range.start];
+    self->_response = response;
+    NSString *path = [KTVHCPathTool filePathWithURL:self.request.URL offset:self.request.range.start];
     self.unitItem = [[KTVHCDataUnitItem alloc] initWithPath:path offset:self.request.range.start];
     self.unitItem = [[KTVHCDataUnitItem alloc] initWithPath:path offset:self.request.range.start];
-    KTVHCDataUnit * unit = [[KTVHCDataUnitPool pool] unitWithURL:self.request.URL];
+    KTVHCDataUnit *unit = [[KTVHCDataUnitPool pool] unitWithURL:self.request.URL];
     [unit insertUnitItem:self.unitItem];
     [unit insertUnitItem:self.unitItem];
     KTVHCLogDataNetworkSource(@"%p, Receive response\nResponse : %@\nUnit : %@\nUnitItem : %@", self, response, unit, self.unitItem);
     KTVHCLogDataNetworkSource(@"%p, Receive response\nResponse : %@\nUnit : %@\nUnitItem : %@", self, response, unit, self.unitItem);
     [unit workingRelease];
     [unit workingRelease];
@@ -205,29 +183,24 @@
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)download:(KTVHCDownload *)download didReceiveData:(NSData *)data
+- (void)ktv_download:(KTVHCDownload *)download didReceiveData:(NSData *)data
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed || self.error)
-    {
+    if (self.isClosed || self.error) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    @try
-    {
+    @try {
         [self.writingHandle writeData:data];
         [self.writingHandle writeData:data];
         self.downloadLength += data.length;
         self.downloadLength += data.length;
-        [self.unitItem setLength:self.downloadLength];
+        [self.unitItem updateLength:self.downloadLength];
         KTVHCLogDataNetworkSource(@"%p, Receive data : %lld, %lld, %lld", self, (long long)data.length, self.downloadLength, self.unitItem.length);
         KTVHCLogDataNetworkSource(@"%p, Receive data : %lld, %lld, %lld", self, (long long)data.length, self.downloadLength, self.unitItem.length);
         [self callbackForHasAvailableData];
         [self callbackForHasAvailableData];
-    }
-    @catch (NSException * exception)
-    {
-        NSError * error = [KTVHCError errorForException:exception];
+    } @catch (NSException *exception) {
+        NSError *error = [KTVHCError errorForException:exception];
         KTVHCLogDataNetworkSource(@"%p, write exception\nError : %@", self, error);
         KTVHCLogDataNetworkSource(@"%p, write exception\nError : %@", self, error);
         [self callbackForFailed:error];
         [self callbackForFailed:error];
-        if (!self.downloadDidCallComplete)
-        {
+        if (!self.downloadCalledComplete) {
             KTVHCLogDataNetworkSource(@"%p, Cancel download task when write exception", self);
             KTVHCLogDataNetworkSource(@"%p, Cancel download task when write exception", self);
             [self.downlaodTask cancel];
             [self.downlaodTask cancel];
             self.downlaodTask = nil;
             self.downlaodTask = nil;
@@ -238,14 +211,10 @@
 
 
 - (void)destoryReadingHandle
 - (void)destoryReadingHandle
 {
 {
-    if (self.readingHandle)
-    {
-        @try
-        {
+    if (self.readingHandle) {
+        @try {
             [self.readingHandle closeFile];
             [self.readingHandle closeFile];
-        }
-        @catch (NSException * exception)
-        {
+        } @catch (NSException *exception) {
             KTVHCLogDataFileSource(@"%p, Close reading handle exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
             KTVHCLogDataFileSource(@"%p, Close reading handle exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         }
         }
         self.readingHandle = nil;
         self.readingHandle = nil;
@@ -254,15 +223,11 @@
 
 
 - (void)destoryWritingHandle
 - (void)destoryWritingHandle
 {
 {
-    if (self.writingHandle)
-    {
-        @try
-        {
+    if (self.writingHandle) {
+        @try {
             [self.writingHandle synchronizeFile];
             [self.writingHandle synchronizeFile];
             [self.writingHandle closeFile];
             [self.writingHandle closeFile];
-        }
-        @catch (NSException * exception)
-        {
+        } @catch (NSException *exception) {
             KTVHCLogDataFileSource(@"%p, Close writing handle exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
             KTVHCLogDataFileSource(@"%p, Close writing handle exception\nname : %@\nreason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         }
         }
         self.writingHandle = nil;
         self.writingHandle = nil;
@@ -271,66 +236,57 @@
 
 
 - (void)callbackForPrepared
 - (void)callbackForPrepared
 {
 {
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         return;
         return;
     }
     }
-    if (self.didPrepared)
-    {
+    if (self.isPrepared) {
         return;
         return;
     }
     }
-    _didPrepared = YES;
-    if ([self.delegate respondsToSelector:@selector(networkSourceDidPrepared:)])
-    {
+    self->_prepared = YES;
+    if ([self.delegate respondsToSelector:@selector(ktv_networkSourceDidPrepare:)]) {
         KTVHCLogDataNetworkSource(@"%p, Callback for prepared - Begin", self);
         KTVHCLogDataNetworkSource(@"%p, Callback for prepared - Begin", self);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataNetworkSource(@"%p, Callback for prepared - End", self);
             KTVHCLogDataNetworkSource(@"%p, Callback for prepared - End", self);
-            [self.delegate networkSourceDidPrepared:self];
+            [self.delegate ktv_networkSourceDidPrepare:self];
         }];
         }];
     }
     }
 }
 }
 
 
 - (void)callbackForHasAvailableData
 - (void)callbackForHasAvailableData
 {
 {
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         return;
         return;
     }
     }
-    if (!self.needCallHasAvailableData)
-    {
+    if (!self.callHasAvailableData) {
         return;
         return;
     }
     }
-    self.needCallHasAvailableData = NO;
-    if ([self.delegate respondsToSelector:@selector(networkSourceHasAvailableData:)])
-    {
+    self.callHasAvailableData = NO;
+    if ([self.delegate respondsToSelector:@selector(ktv_networkSourceHasAvailableData:)]) {
         KTVHCLogDataNetworkSource(@"%p, Callback for has available data - Begin", self);
         KTVHCLogDataNetworkSource(@"%p, Callback for has available data - Begin", self);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataNetworkSource(@"%p, Callback for has available data - End", self);
             KTVHCLogDataNetworkSource(@"%p, Callback for has available data - End", self);
-            [self.delegate networkSourceHasAvailableData:self];
+            [self.delegate ktv_networkSourceHasAvailableData:self];
         }];
         }];
     }
     }
 }
 }
 
 
 - (void)callbackForFailed:(NSError *)error
 - (void)callbackForFailed:(NSError *)error
 {
 {
-    if (self.didClosed || !error || self.error)
-    {
+    if (self.isClosed || !error || self.error) {
         return;
         return;
     }
     }
-    self.error = error;
+    self->_error = error;
     KTVHCLogDataNetworkSource(@"%p, Callback for failed\nError : %@", self, self.error);
     KTVHCLogDataNetworkSource(@"%p, Callback for failed\nError : %@", self, self.error);
-    if ([self.delegate respondsToSelector:@selector(networkSource:didFailed:)])
-    {
+    if ([self.delegate respondsToSelector:@selector(ktv_networkSource:didFailWithError:)]) {
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
-            [self.delegate networkSource:self didFailed:self.error];
+            [self.delegate ktv_networkSource:self didFailWithError:self.error];
         }];
         }];
     }
     }
 }
 }
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSLock alloc] init];
         self.coreLock = [[NSLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];

+ 11 - 13
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.h

@@ -14,9 +14,9 @@
 
 
 @protocol KTVHCDataReaderDelegate <NSObject>
 @protocol KTVHCDataReaderDelegate <NSObject>
 
 
-- (void)readerDidPrepared:(KTVHCDataReader *)reader;
-- (void)readerHasAvailableData:(KTVHCDataReader *)reader;
-- (void)reader:(KTVHCDataReader *)reader didFailed:(NSError *)error;
+- (void)ktv_readerDidPrepare:(KTVHCDataReader *)reader;
+- (void)ktv_readerHasAvailableData:(KTVHCDataReader *)reader;
+- (void)ktv_reader:(KTVHCDataReader *)reader didFailWithError:(NSError *)error;
 
 
 @end
 @end
 
 
@@ -25,22 +25,20 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-+ (instancetype)readerWithRequest:(KTVHCDataRequest *)request;
-
 @property (nonatomic, weak) id <KTVHCDataReaderDelegate> delegate;
 @property (nonatomic, weak) id <KTVHCDataReaderDelegate> delegate;
-
 @property (nonatomic, strong) id object;
 @property (nonatomic, strong) id object;
 
 
-@property (nonatomic, strong, readonly) KTVHCDataRequest * request;
-@property (nonatomic, strong, readonly) KTVHCDataResponse * response;
+@property (nonatomic, strong, readonly) KTVHCDataRequest *request;
+@property (nonatomic, strong, readonly) KTVHCDataResponse *response;
 
 
-@property (nonatomic, strong, readonly) NSError * error;
+@property (nonatomic, copy, readonly) NSError *error;
 
 
-@property (nonatomic, assign, readonly) BOOL didClosed;
-@property (nonatomic, assign, readonly) BOOL didPrepared;
-@property (nonatomic, assign, readonly) BOOL didFinished;
+@property (nonatomic, readonly, getter=isPrepared) BOOL prepared;
+@property (nonatomic, readonly, getter=isFinished) BOOL finished;
+@property (nonatomic, readonly, getter=isClosed) BOOL closed;
 
 
-@property (nonatomic, assign, readonly) long long readOffset;
+@property (nonatomic, readonly) long long readedLength;
+@property (nonatomic, readonly) double progress;
 
 
 - (void)prepare;
 - (void)prepare;
 - (void)close;
 - (void)close;

+ 68 - 100
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.m

@@ -7,6 +7,7 @@
 //
 //
 
 
 #import "KTVHCDataReader.h"
 #import "KTVHCDataReader.h"
+#import "KTVHCData+Internal.h"
 #import "KTVHCDataSourceManager.h"
 #import "KTVHCDataSourceManager.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataCallback.h"
 #import "KTVHCDataCallback.h"
@@ -14,31 +15,23 @@
 
 
 @interface KTVHCDataReader () <KTVHCDataSourceManagerDelegate>
 @interface KTVHCDataReader () <KTVHCDataSourceManagerDelegate>
 
 
-@property (nonatomic, strong) NSRecursiveLock * coreLock;
+@property (nonatomic, strong) KTVHCDataUnit *unit;
+@property (nonatomic, strong) NSRecursiveLock *coreLock;
 @property (nonatomic, strong) dispatch_queue_t delegateQueue;
 @property (nonatomic, strong) dispatch_queue_t delegateQueue;
 @property (nonatomic, strong) dispatch_queue_t internalDelegateQueue;
 @property (nonatomic, strong) dispatch_queue_t internalDelegateQueue;
-@property (nonatomic, assign) BOOL didCalledPrepare;
-
-@property (nonatomic, strong) KTVHCDataUnit * unit;
-@property (nonatomic, strong) KTVHCDataSourceManager * sourceManager;
+@property (nonatomic, strong) KTVHCDataSourceManager *sourceManager;
+@property (nonatomic) BOOL calledPrepare;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataReader
 @implementation KTVHCDataReader
 
 
-+ (instancetype)readerWithRequest:(KTVHCDataRequest *)request
-{
-    return [[self alloc] initWithRequest:request];
-}
-
 - (instancetype)initWithRequest:(KTVHCDataRequest *)request
 - (instancetype)initWithRequest:(KTVHCDataRequest *)request
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
         self.unit = [[KTVHCDataUnitPool pool] unitWithURL:request.URL];
         self.unit = [[KTVHCDataUnitPool pool] unitWithURL:request.URL];
-        _request = [request requestWithTotalLength:self.unit.totalLength];
-        [self.unit updateRequestHeaders:self.request.headers];
+        self->_request = [request newRequestWithTotalLength:self.unit.totalLength];
         self.delegateQueue = dispatch_queue_create("KTVHCDataReader_delegateQueue", DISPATCH_QUEUE_SERIAL);
         self.delegateQueue = dispatch_queue_create("KTVHCDataReader_delegateQueue", DISPATCH_QUEUE_SERIAL);
         self.internalDelegateQueue = dispatch_queue_create("KTVHCDataReader_internalDelegateQueue", DISPATCH_QUEUE_SERIAL);
         self.internalDelegateQueue = dispatch_queue_create("KTVHCDataReader_internalDelegateQueue", DISPATCH_QUEUE_SERIAL);
         KTVHCLogDataReader(@"%p, Create reader\norignalRequest : %@\nfinalRequest : %@\nUnit : %@", self, request, self.request, self.unit);
         KTVHCLogDataReader(@"%p, Create reader\norignalRequest : %@\nfinalRequest : %@\nUnit : %@", self, request, self.request, self.unit);
@@ -50,23 +43,21 @@
 {
 {
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
     [self close];
     [self close];
-    KTVHCLogDataReader(@"%p, Destory reader\nError : %@\nreadOffset : %lld", self, self.error, self.readOffset);
+    KTVHCLogDataReader(@"%p, Destory reader\nError : %@\nreadOffset : %lld", self, self.error, self.readedLength);
 }
 }
 
 
 - (void)prepare
 - (void)prepare
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    if (self.didCalledPrepare)
-    {
+    if (self.calledPrepare) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didCalledPrepare = YES;
+    self->_calledPrepare = YES;
     KTVHCLogDataReader(@"%p, Call prepare", self);
     KTVHCLogDataReader(@"%p, Call prepare", self);
     [self prepareSourceManager];
     [self prepareSourceManager];
     [self unlock];
     [self unlock];
@@ -75,12 +66,11 @@
 - (void)close
 - (void)close
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didClosed = YES;
+    self->_closed = YES;
     KTVHCLogDataReader(@"%p, Call close", self);
     KTVHCLogDataReader(@"%p, Call close", self);
     [self.sourceManager close];
     [self.sourceManager close];
     [self.unit workingRelease];
     [self.unit workingRelease];
@@ -91,28 +81,29 @@
 - (NSData *)readDataOfLength:(NSUInteger)length
 - (NSData *)readDataOfLength:(NSUInteger)length
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    if (self.didFinished)
-    {
+    if (self.isFinished) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    if (self.error)
-    {
+    if (self.error) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    NSData * data = [self.sourceManager readDataOfLength:length];;
-    _readOffset += data.length;
+    NSData *data = [self.sourceManager readDataOfLength:length];
+    if (data.length > 0) {
+        self->_readedLength += data.length;
+        if (self.response.contentLength > 0) {
+            self->_progress = (double)self.readedLength / (double)self.response.contentLength;
+        }
+    }
     KTVHCLogDataReader(@"%p, Read data : %lld", self, (long long)data.length);
     KTVHCLogDataReader(@"%p, Read data : %lld", self, (long long)data.length);
-    if (self.sourceManager.didFinished)
-    {
+    if (self.sourceManager.isFinished) {
         KTVHCLogDataReader(@"%p, Read data did finished", self);
         KTVHCLogDataReader(@"%p, Read data did finished", self);
-        _didFinished = YES;
+        self->_finished = YES;
         [self close];
         [self close];
     }
     }
     [self unlock];
     [self unlock];
@@ -121,35 +112,30 @@
 
 
 - (void)prepareSourceManager
 - (void)prepareSourceManager
 {
 {
-    self.sourceManager = [[KTVHCDataSourceManager alloc] initWithDelegate:self delegateQueue:self.internalDelegateQueue];
-    NSMutableArray <KTVHCDataFileSource *> * fileSources = [NSMutableArray array];
-    NSMutableArray <KTVHCDataNetworkSource *> * networkSources = [NSMutableArray array];
+    NSMutableArray<KTVHCDataFileSource *> *fileSources = [NSMutableArray array];
+    NSMutableArray<KTVHCDataNetworkSource *> *networkSources = [NSMutableArray array];
     long long min = self.request.range.start;
     long long min = self.request.range.start;
     long long max = self.request.range.end;
     long long max = self.request.range.end;
-    NSArray * unitItems = self.unit.unitItems;
-    for (KTVHCDataUnitItem * item in unitItems)
-    {
+    NSArray *unitItems = self.unit.unitItems;
+    for (KTVHCDataUnitItem *item in unitItems) {
         long long itemMin = item.offset;
         long long itemMin = item.offset;
         long long itemMax = item.offset + item.length - 1;
         long long itemMax = item.offset + item.length - 1;
-        if (itemMax < min || itemMin > max)
-        {
+        if (itemMax < min || itemMin > max) {
             continue;
             continue;
         }
         }
-        if (min > itemMin)
-        {
+        if (min > itemMin) {
             itemMin = min;
             itemMin = min;
         }
         }
-        if (max < itemMax)
-        {
+        if (max < itemMax) {
             itemMax = max;
             itemMax = max;
         }
         }
         min = itemMax + 1;
         min = itemMax + 1;
         KTVHCRange range = KTVHCMakeRange(item.offset, item.offset + item.length - 1);
         KTVHCRange range = KTVHCMakeRange(item.offset, item.offset + item.length - 1);
         KTVHCRange readRange = KTVHCMakeRange(itemMin - item.offset, itemMax - item.offset);
         KTVHCRange readRange = KTVHCMakeRange(itemMin - item.offset, itemMax - item.offset);
-        KTVHCDataFileSource * source = [[KTVHCDataFileSource alloc] initWithPath:item.absolutePath range:range readRange:readRange];
+        KTVHCDataFileSource *source = [[KTVHCDataFileSource alloc] initWithPath:item.absolutePath range:range readRange:readRange];
         [fileSources addObject:source];
         [fileSources addObject:source];
     }
     }
-    [fileSources sortUsingComparator:^NSComparisonResult(KTVHCDataFileSource * obj1, KTVHCDataFileSource * obj2) {
+    [fileSources sortUsingComparator:^NSComparisonResult(KTVHCDataFileSource *obj1, KTVHCDataFileSource *obj2) {
         if (obj1.range.start < obj2.range.start) {
         if (obj1.range.start < obj2.range.start) {
             return NSOrderedAscending;
             return NSOrderedAscending;
         }
         }
@@ -157,14 +143,12 @@
     }];
     }];
     long long offset = self.request.range.start;
     long long offset = self.request.range.start;
     long long length = KTVHCRangeIsFull(self.request.range) ? KTVHCRangeGetLength(self.request.range) : (self.request.range.end - offset + 1);
     long long length = KTVHCRangeIsFull(self.request.range) ? KTVHCRangeGetLength(self.request.range) : (self.request.range.end - offset + 1);
-    for (KTVHCDataFileSource * obj in fileSources)
-    {
+    for (KTVHCDataFileSource *obj in fileSources) {
         long long delta = obj.range.start + obj.readRange.start - offset;
         long long delta = obj.range.start + obj.readRange.start - offset;
-        if (delta > 0)
-        {
+        if (delta > 0) {
             KTVHCRange range = KTVHCMakeRange(offset, offset + delta - 1);
             KTVHCRange range = KTVHCMakeRange(offset, offset + delta - 1);
-            KTVHCDataRequest * request = [self.request requestWithRange:range];
-            KTVHCDataNetworkSource * source = [[KTVHCDataNetworkSource alloc] initWithRequest:request];
+            KTVHCDataRequest *request = [self.request newRequestWithRange:range];
+            KTVHCDataNetworkSource *source = [[KTVHCDataNetworkSource alloc] initWithRequest:request];
             [networkSources addObject:source];
             [networkSources addObject:source];
             offset += delta;
             offset += delta;
             length -= delta;
             length -= delta;
@@ -172,32 +156,27 @@
         offset += KTVHCRangeGetLength(obj.readRange);
         offset += KTVHCRangeGetLength(obj.readRange);
         length -= KTVHCRangeGetLength(obj.readRange);
         length -= KTVHCRangeGetLength(obj.readRange);
     }
     }
-    if (length > 0)
-    {
+    if (length > 0) {
         KTVHCRange range = KTVHCMakeRange(offset, self.request.range.end);
         KTVHCRange range = KTVHCMakeRange(offset, self.request.range.end);
-        KTVHCDataRequest * request = [self.request requestWithRange:range];
-        KTVHCDataNetworkSource * source = [[KTVHCDataNetworkSource alloc] initWithRequest:request];
+        KTVHCDataRequest *request = [self.request newRequestWithRange:range];
+        KTVHCDataNetworkSource *source = [[KTVHCDataNetworkSource alloc] initWithRequest:request];
         [networkSources addObject:source];
         [networkSources addObject:source];
     }
     }
-    for (KTVHCDataFileSource * obj in fileSources)
-    {
-        [self.sourceManager putSource:obj];
-    }
-    for (KTVHCDataNetworkSource * obj in networkSources)
-    {
-        [self.sourceManager putSource:obj];
-    }
+    NSMutableArray<id<KTVHCDataSource>> *sources = [NSMutableArray array];
+    [sources addObjectsFromArray:fileSources];
+    [sources addObjectsFromArray:networkSources];
+    self.sourceManager = [[KTVHCDataSourceManager alloc] initWithSources:sources delegate:self delegateQueue:self.internalDelegateQueue];
     [self.sourceManager prepare];
     [self.sourceManager prepare];
 }
 }
 
 
-- (void)sourceManagerDidPrepared:(KTVHCDataSourceManager *)sourceManager
+- (void)ktv_sourceManagerDidPrepare:(KTVHCDataSourceManager *)sourceManager
 {
 {
     [self lock];
     [self lock];
     [self callbackForPrepared];
     [self callbackForPrepared];
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)sourceManager:(KTVHCDataSourceManager *)sourceManager didReceiveResponse:(KTVHCDataResponse *)response
+- (void)ktv_sourceManager:(KTVHCDataSourceManager *)sourceManager didReceiveResponse:(KTVHCDataResponse *)response
 {
 {
     [self lock];
     [self lock];
     [self.unit updateResponseHeaders:response.headers totalLength:response.totalLength];
     [self.unit updateResponseHeaders:response.headers totalLength:response.totalLength];
@@ -205,51 +184,45 @@
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)sourceManagerHasAvailableData:(KTVHCDataSourceManager *)sourceManager
+- (void)ktv_sourceManagerHasAvailableData:(KTVHCDataSourceManager *)sourceManager
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    if ([self.delegate respondsToSelector:@selector(readerHasAvailableData:)])
-    {
+    if ([self.delegate respondsToSelector:@selector(ktv_readerHasAvailableData:)]) {
         KTVHCLogDataReader(@"%p, Callback for has available data - Begin", self);
         KTVHCLogDataReader(@"%p, Callback for has available data - Begin", self);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataReader(@"%p, Callback for has available data - End", self);
             KTVHCLogDataReader(@"%p, Callback for has available data - End", self);
-            [self.delegate readerHasAvailableData:self];
+            [self.delegate ktv_readerHasAvailableData:self];
         }];
         }];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)sourceManager:(KTVHCDataSourceManager *)sourceManager didFailed:(NSError *)error
+- (void)ktv_sourceManager:(KTVHCDataSourceManager *)sourceManager didFailWithError:(NSError *)error
 {
 {
-    if (!error)
-    {
+    if (!error) {
         return;
         return;
     }
     }
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    if (self.error)
-    {
+    if (self.error) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _error = error;
+    self->_error = error;
     [self close];
     [self close];
-    [[KTVHCLog log] addError:self.error];
-    if ([self.delegate respondsToSelector:@selector(reader:didFailed:)])
-    {
+    [[KTVHCLog log] addError:self.error forURL:self.request.URL];
+    if ([self.delegate respondsToSelector:@selector(ktv_reader:didFailWithError:)]) {
         KTVHCLogDataReader(@"%p, Callback for failed - Begin\nError : %@", self, self.error);
         KTVHCLogDataReader(@"%p, Callback for failed - Begin\nError : %@", self, self.error);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataReader(@"%p, Callback for failed - End", self);
             KTVHCLogDataReader(@"%p, Callback for failed - End", self);
-            [self.delegate reader:self didFailed:self.error];
+            [self.delegate ktv_reader:self didFailWithError:self.error];
         }];
         }];
     }
     }
     [self unlock];
     [self unlock];
@@ -257,28 +230,24 @@
 
 
 - (void)callbackForPrepared
 - (void)callbackForPrepared
 {
 {
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         return;
         return;
     }
     }
-    if (self.didPrepared)
-    {
+    if (self.isPrepared) {
         return;
         return;
     }
     }
-    if (self.sourceManager.didPrepared && self.unit.totalLength > 0)
-    {
+    if (self.sourceManager.isPrepared && self.unit.totalLength > 0) {
         long long totalLength = self.unit.totalLength;
         long long totalLength = self.unit.totalLength;
         KTVHCRange range = KTVHCRangeWithEnsureLength(self.request.range, totalLength);
         KTVHCRange range = KTVHCRangeWithEnsureLength(self.request.range, totalLength);
-        NSDictionary * headers = KTVHCRangeFillToResponseHeaders(range, self.unit.responseHeaders, totalLength);
-        _response = [[KTVHCDataResponse alloc] initWithURL:self.request.URL headers:headers];
-        _didPrepared = YES;
+        NSDictionary *headers = KTVHCRangeFillToResponseHeaders(range, self.unit.responseHeaders, totalLength);
+        self->_response = [[KTVHCDataResponse alloc] initWithURL:self.request.URL headers:headers];
+        self->_prepared = YES;
         KTVHCLogDataReader(@"%p, Reader did prepared\nResponse : %@", self, self.response);
         KTVHCLogDataReader(@"%p, Reader did prepared\nResponse : %@", self, self.response);
-        if ([self.delegate respondsToSelector:@selector(readerDidPrepared:)])
-        {
+        if ([self.delegate respondsToSelector:@selector(ktv_readerDidPrepare:)]) {
             KTVHCLogDataReader(@"%p, Callback for prepared - Begin", self);
             KTVHCLogDataReader(@"%p, Callback for prepared - Begin", self);
             [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
                 KTVHCLogDataReader(@"%p, Callback for prepared - End", self);
                 KTVHCLogDataReader(@"%p, Callback for prepared - End", self);
-                [self.delegate readerDidPrepared:self];
+                [self.delegate ktv_readerDidPrepare:self];
             }];
             }];
         }
         }
     }
     }
@@ -286,8 +255,7 @@
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSRecursiveLock alloc] init];
         self.coreLock = [[NSRecursiveLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];

+ 4 - 7
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataRequest.h

@@ -14,13 +14,10 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers;
+- (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers NS_DESIGNATED_INITIALIZER;
 
 
-@property (nonatomic, copy, readonly) NSURL * URL;
-@property (nonatomic, copy, readonly) NSDictionary * headers;
-@property (nonatomic, assign, readonly) KTVHCRange range;
-
-- (KTVHCDataRequest *)requestWithRange:(KTVHCRange)range;
-- (KTVHCDataRequest *)requestWithTotalLength:(long long)totalLength;
+@property (nonatomic, copy, readonly) NSURL *URL;
+@property (nonatomic, copy, readonly) NSDictionary *headers;
+@property (nonatomic, readonly) KTVHCRange range;
 
 
 @end
 @end

+ 11 - 19
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataRequest.m

@@ -7,22 +7,18 @@
 //
 //
 
 
 #import "KTVHCDataRequest.h"
 #import "KTVHCDataRequest.h"
+#import "KTVHCData+Internal.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @implementation KTVHCDataRequest
 @implementation KTVHCDataRequest
 
 
 - (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers
 - (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
-        _URL = URL;
-        if (![headers objectForKey:@"Range"]) {
-            _headers = KTVHCRangeFillToRequestHeaders(KTVHCRangeFull(), headers);
-        } else {
-            _headers = headers;
-        }
-        _range = KTVHCRangeWithRequestHeaderValue([_headers objectForKey:@"Range"]);
+        self->_URL = URL;
+        self->_headers = KTVHCRangeFillToRequestHeadersIfNeeded(KTVHCRangeFull(), headers);
+        self->_range = KTVHCRangeWithRequestHeaderValue([self.headers objectForKey:@"Range"]);
         KTVHCLogDataRequest(@"%p Create data request\nURL : %@\nHeaders : %@\nRange : %@", self, self.URL, self.headers, KTVHCStringFromRange(self.range));
         KTVHCLogDataRequest(@"%p Create data request\nURL : %@\nHeaders : %@\nRange : %@", self, self.URL, self.headers, KTVHCStringFromRange(self.range));
     }
     }
     return self;
     return self;
@@ -33,21 +29,17 @@
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
 }
 }
 
 
-- (KTVHCDataRequest *)requestWithRange:(KTVHCRange)range
+- (KTVHCDataRequest *)newRequestWithRange:(KTVHCRange)range
 {
 {
-    if (!KTVHCEqualRanges(self.range, range))
-    {
-        NSDictionary * headers = KTVHCRangeFillToRequestHeaders(range, self.headers);
-        KTVHCDataRequest * obj = [[KTVHCDataRequest alloc] initWithURL:self.URL headers:headers];
-        return obj;
-    }
-    return self;
+    NSDictionary *headers = KTVHCRangeFillToRequestHeaders(range, self.headers);
+    KTVHCDataRequest *obj = [[KTVHCDataRequest alloc] initWithURL:self.URL headers:headers];
+    return obj;
 }
 }
 
 
-- (KTVHCDataRequest *)requestWithTotalLength:(long long)totalLength
+- (KTVHCDataRequest *)newRequestWithTotalLength:(long long)totalLength
 {
 {
     KTVHCRange range = KTVHCRangeWithEnsureLength(self.range, totalLength);
     KTVHCRange range = KTVHCRangeWithEnsureLength(self.range, totalLength);
-    return [self requestWithRange:range];
+    return [self newRequestWithRange:range];
 }
 }
 
 
 @end
 @end

+ 7 - 12
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataResponse.h

@@ -14,17 +14,12 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers;
-
-@property (nonatomic, copy, readonly) NSURL * URL;
-@property (nonatomic, copy, readonly) NSDictionary * headers;
-@property (nonatomic, copy, readonly) NSDictionary * headersWithoutRangeAndLength;
-
-@property (nonatomic, copy, readonly) NSString * contentType;
-@property (nonatomic, assign, readonly) KTVHCRange range;
-@property (nonatomic, assign, readonly) long long totalLength;
-@property (nonatomic, assign, readonly) long long currentLength;
-
-- (KTVHCDataResponse *)responseWithRange:(KTVHCRange)range;
+@property (nonatomic, copy, readonly) NSURL *URL;
+@property (nonatomic, copy, readonly) NSDictionary *headers;
+@property (nonatomic, copy, readonly) NSString *contentType;
+@property (nonatomic, copy, readonly) NSString *contentRangeString;
+@property (nonatomic, readonly) KTVHCRange contentRange;
+@property (nonatomic, readonly) long long contentLength;
+@property (nonatomic, readonly) long long totalLength;
 
 
 @end
 @end

+ 11 - 41
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataResponse.m

@@ -7,27 +7,22 @@
 //
 //
 
 
 #import "KTVHCDataResponse.h"
 #import "KTVHCDataResponse.h"
+#import "KTVHCData+Internal.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @implementation KTVHCDataResponse
 @implementation KTVHCDataResponse
 
 
 - (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers
 - (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
-        _URL = URL;
-        _headers = headers;
-        NSMutableDictionary * headersWithoutRangeAndLength = [headers mutableCopy];
-        for (NSString * key in [self withoutHeaderKeys])
-        {
-            [headersWithoutRangeAndLength removeObjectForKey:key];
-        }
-        _headersWithoutRangeAndLength = [headersWithoutRangeAndLength copy];
-        _contentType = [self headerValueWithKey:@"Content-Type"];
-        _currentLength = [self headerValueWithKey:@"Content-Length"].longLongValue;
-        _range = KTVHCRangeWithResponseHeaderValue([self headerValueWithKey:@"Content-Range"], &_totalLength);
-        KTVHCLogDataResponse(@"%p Create data response\nURL : %@\nHeaders : %@\nheadersWithoutRangeAndLength : %@\ncontentType : %@\ntotalLength : %lld\ncurrentLength : %lld", self, self.URL, self.headers, self.headersWithoutRangeAndLength, self.contentType, self.totalLength, self.currentLength);
+        self->_URL = URL;
+        self->_headers = headers;
+        self->_contentType = [self headerValueWithKey:@"Content-Type"];
+        self->_contentRangeString = [self headerValueWithKey:@"Content-Range"];
+        self->_contentLength = [self headerValueWithKey:@"Content-Length"].longLongValue;
+        self->_contentRange = KTVHCRangeWithResponseHeaderValue(self.contentRangeString, &self->_totalLength);
+        KTVHCLogDataResponse(@"%p Create data response\nURL : %@\nHeaders : %@\ncontentType : %@\ntotalLength : %lld\ncurrentLength : %lld", self, self.URL, self.headers, self.contentType, self.totalLength, self.contentLength);
     }
     }
     return self;
     return self;
 }
 }
@@ -39,36 +34,11 @@
 
 
 - (NSString *)headerValueWithKey:(NSString *)key
 - (NSString *)headerValueWithKey:(NSString *)key
 {
 {
-    NSString * value = [self.headers objectForKey:key];
-    if (!value)
-    {
+    NSString *value = [self.headers objectForKey:key];
+    if (!value) {
         value = [self.headers objectForKey:[key lowercaseString]];
         value = [self.headers objectForKey:[key lowercaseString]];
     }
     }
     return value;
     return value;
 }
 }
 
 
-- (NSArray <NSString *> *)withoutHeaderKeys
-{
-    static NSArray * obj = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        obj = @[@"Content-Length",
-                @"content-length",
-                @"Content-Range",
-                @"content-range"];
-    });
-    return obj;
-}
-
-- (KTVHCDataResponse *)responseWithRange:(KTVHCRange)range
-{
-    if (!KTVHCEqualRanges(self.range, range))
-    {
-        NSDictionary * headers = KTVHCRangeFillToResponseHeaders(range, self.headers, self.totalLength);
-        KTVHCDataResponse * obj = [[KTVHCDataResponse alloc] initWithURL:self.URL headers:headers];
-        return obj;
-    }
-    return self;
-}
-
 @end
 @end

+ 9 - 20
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceManager.h

@@ -7,41 +7,30 @@
 //
 //
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
-#import "KTVHCDataFileSource.h"
 #import "KTVHCDataNetworkSource.h"
 #import "KTVHCDataNetworkSource.h"
+#import "KTVHCDataFileSource.h"
 
 
 @class KTVHCDataSourceManager;
 @class KTVHCDataSourceManager;
 
 
 @protocol KTVHCDataSourceManagerDelegate <NSObject>
 @protocol KTVHCDataSourceManagerDelegate <NSObject>
 
 
-- (void)sourceManagerDidPrepared:(KTVHCDataSourceManager *)sourceManager;
-- (void)sourceManagerHasAvailableData:(KTVHCDataSourceManager *)sourceManager;
-- (void)sourceManager:(KTVHCDataSourceManager *)sourceManager didFailed:(NSError *)error;
-- (void)sourceManager:(KTVHCDataSourceManager *)sourceManager didReceiveResponse:(KTVHCDataResponse *)response;
+- (void)ktv_sourceManagerDidPrepare:(KTVHCDataSourceManager *)sourceManager;
+- (void)ktv_sourceManagerHasAvailableData:(KTVHCDataSourceManager *)sourceManager;
+- (void)ktv_sourceManager:(KTVHCDataSourceManager *)sourceManager didFailWithError:(NSError *)error;
+- (void)ktv_sourceManager:(KTVHCDataSourceManager *)sourceManager didReceiveResponse:(KTVHCDataResponse *)response;
 
 
 @end
 @end
 
 
-@interface KTVHCDataSourceManager : NSObject
+@interface KTVHCDataSourceManager : NSObject <KTVHCDataSource>
 
 
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithDelegate:(id <KTVHCDataSourceManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
+- (instancetype)initWithSources:(NSArray<id<KTVHCDataSource>> *)sources
+                       delegate:(id <KTVHCDataSourceManagerDelegate>)delegate
+                  delegateQueue:(dispatch_queue_t)delegateQueue NS_DESIGNATED_INITIALIZER;
 
 
 @property (nonatomic, weak, readonly) id <KTVHCDataSourceManagerDelegate> delegate;
 @property (nonatomic, weak, readonly) id <KTVHCDataSourceManagerDelegate> delegate;
 @property (nonatomic, strong, readonly) dispatch_queue_t delegateQueue;
 @property (nonatomic, strong, readonly) dispatch_queue_t delegateQueue;
 
 
-@property (nonatomic, strong, readonly) NSError * error;
-
-@property (nonatomic, assign, readonly) BOOL didClosed;
-@property (nonatomic, assign, readonly) BOOL didPrepared;
-@property (nonatomic, assign, readonly) BOOL didFinished;
-
-- (void)putSource:(id<KTVHCDataSourceProtocol>)source;
-
-- (void)prepare;
-- (void)close;
-
-- (NSData *)readDataOfLength:(NSUInteger)length;
-
 @end
 @end

+ 121 - 91
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceManager.m

@@ -7,32 +7,36 @@
 //
 //
 
 
 #import "KTVHCDataSourceManager.h"
 #import "KTVHCDataSourceManager.h"
-#import "KTVHCDataSourceQueue.h"
 #import "KTVHCDataCallback.h"
 #import "KTVHCDataCallback.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCDataSourceManager () <NSLocking, KTVHCDataFileSourceDelegate, KTVHCDataNetworkSourceDelegate>
 @interface KTVHCDataSourceManager () <NSLocking, KTVHCDataFileSourceDelegate, KTVHCDataNetworkSourceDelegate>
 
 
-@property (nonatomic, strong) NSLock * coreLock;
-@property (nonatomic, assign) BOOL didCalledPrepare;
-@property (nonatomic, assign) BOOL didCalledReceiveResponse;
-
-@property (nonatomic, strong) KTVHCDataSourceQueue * sourceQueue;
-@property (nonatomic, strong) id <KTVHCDataSourceProtocol> currentSource;
-@property (nonatomic, strong) KTVHCDataNetworkSource * currentNetworkSource;
+@property (nonatomic, strong) NSLock *coreLock;
+@property (nonatomic, strong) id <KTVHCDataSource> currentSource;
+@property (nonatomic, strong) KTVHCDataNetworkSource *currentNetworkSource;
+@property (nonatomic, strong) NSMutableArray<id<KTVHCDataSource>> *sources;
+@property (nonatomic) BOOL calledPrepare;
+@property (nonatomic) BOOL calledReceiveResponse;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataSourceManager
 @implementation KTVHCDataSourceManager
 
 
-- (instancetype)initWithDelegate:(id <KTVHCDataSourceManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
+@synthesize error = _error;
+@synthesize range = _range;
+@synthesize closed = _closed;
+@synthesize prepared = _prepared;
+@synthesize finished = _finished;
+@synthesize readedLength = _readedLength;
+
+- (instancetype)initWithSources:(NSArray<id<KTVHCDataSource>> *)sources delegate:(id<KTVHCDataSourceManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
-        _delegate = delegate;
-        _delegateQueue = delegateQueue;
-        self.sourceQueue = [KTVHCDataSourceQueue sourceQueue];
+        self->_sources = [sources mutableCopy];
+        self->_delegate = delegate;
+        self->_delegateQueue = delegateQueue;
     }
     }
     return self;
     return self;
 }
 }
@@ -43,108 +47,141 @@
     KTVHCLogDataReader(@"%p, Destory reader\nError : %@\ncurrentSource : %@\ncurrentNetworkSource : %@", self, self.error, self.currentSource, self.currentNetworkSource);
     KTVHCLogDataReader(@"%p, Destory reader\nError : %@\ncurrentSource : %@\ncurrentNetworkSource : %@", self, self.error, self.currentSource, self.currentNetworkSource);
 }
 }
 
 
-- (void)putSource:(id<KTVHCDataSourceProtocol>)source
-{
-    KTVHCLogDataSourceManager(@"%p, Put source : %@", self, source);
-    [self.sourceQueue putSource:source];
-}
-
 - (void)prepare
 - (void)prepare
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    if (self.didCalledPrepare)
-    {
+    if (self.calledPrepare) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didCalledPrepare = YES;
+    self->_calledPrepare = YES;
     KTVHCLogDataSourceManager(@"%p, Call prepare", self);
     KTVHCLogDataSourceManager(@"%p, Call prepare", self);
-    [self.sourceQueue sortSources];
-    [self.sourceQueue setAllSourceDelegate:self delegateQueue:self.delegateQueue];
-    self.currentSource = [self.sourceQueue firstSource];
-    self.currentNetworkSource = [self.sourceQueue firstNetworkSource];
+    KTVHCLogDataSourceManager(@"%p, Sort sources - Begin\nSources : %@", self, self.sources);
+    [self.sources sortUsingComparator:^NSComparisonResult(id <KTVHCDataSource> obj1, id <KTVHCDataSource> obj2) {
+        if (obj1.range.start < obj2.range.start) {
+            return NSOrderedAscending;
+        }
+        return NSOrderedDescending;
+    }];
+    KTVHCLogDataSourceManager(@"%p, Sort sources - End  \nSources : %@", self, self.sources);
+    for (id <KTVHCDataSource> obj in self.sources) {
+        if ([obj isKindOfClass:[KTVHCDataFileSource class]]) {
+            KTVHCDataFileSource *source = (KTVHCDataFileSource *)obj;
+            [source setDelegate:self delegateQueue:self.delegateQueue];
+        }
+        else if ([obj isKindOfClass:[KTVHCDataNetworkSource class]]) {
+            KTVHCDataNetworkSource *source = (KTVHCDataNetworkSource *)obj;
+            [source setDelegate:self delegateQueue:self.delegateQueue];
+        }
+    }
+    self.currentSource = self.sources.firstObject;
+    for (id<KTVHCDataSource> obj in self.sources) {
+        if ([obj isKindOfClass:[KTVHCDataNetworkSource class]]) {
+            self.currentNetworkSource = obj;
+            break;
+        }
+    }
     KTVHCLogDataSourceManager(@"%p, Sort source\ncurrentSource : %@\ncurrentNetworkSource : %@", self, self.currentSource, self.currentNetworkSource);
     KTVHCLogDataSourceManager(@"%p, Sort source\ncurrentSource : %@\ncurrentNetworkSource : %@", self, self.currentSource, self.currentNetworkSource);
     [self.currentSource prepare];
     [self.currentSource prepare];
-    if (self.currentSource != self.currentNetworkSource)
-    {
-        [self.currentNetworkSource prepare];
-    }
+    [self.currentNetworkSource prepare];
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (void)close
 - (void)close
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _didClosed = YES;
+    self->_closed = YES;
     KTVHCLogDataSourceManager(@"%p, Call close", self);
     KTVHCLogDataSourceManager(@"%p, Call close", self);
-    [self.sourceQueue closeAllSource];
+    for (id <KTVHCDataSource> obj in self.sources) {
+        [obj close];
+    }
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (NSData *)readDataOfLength:(NSUInteger)length
 - (NSData *)readDataOfLength:(NSUInteger)length
 {
 {
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    if (self.didFinished)
-    {
+    if (self.isFinished) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    if (self.error)
-    {
+    if (self.error) {
         [self unlock];
         [self unlock];
         return nil;
         return nil;
     }
     }
-    NSData * data = [self.currentSource readDataOfLength:length];
+    NSData *data = [self.currentSource readDataOfLength:length];
+    self->_readedLength += data.length;
     KTVHCLogDataSourceManager(@"%p, Read data : %lld", self, (long long)data.length);
     KTVHCLogDataSourceManager(@"%p, Read data : %lld", self, (long long)data.length);
-    if (self.currentSource.didFinished)
-    {
-        self.currentSource = [self.sourceQueue nextSource:self.currentSource];
-        if (self.currentSource)
-        {
+    if (self.currentSource.isFinished) {
+        self.currentSource = [self nextSource];
+        if (self.currentSource) {
             KTVHCLogDataSourceManager(@"%p, Switch to next source, %@", self, self.currentSource);
             KTVHCLogDataSourceManager(@"%p, Switch to next source, %@", self, self.currentSource);
-            if ([self.currentSource isKindOfClass:[KTVHCDataFileSource class]])
-            {
+            if ([self.currentSource isKindOfClass:[KTVHCDataFileSource class]]) {
                 [self.currentSource prepare];
                 [self.currentSource prepare];
             }
             }
-        }
-        else
-        {
+        } else {
             KTVHCLogDataSourceManager(@"%p, Read data did finished", self);
             KTVHCLogDataSourceManager(@"%p, Read data did finished", self);
-            _didFinished = YES;
+            self->_finished = YES;
         }
         }
     }
     }
     [self unlock];
     [self unlock];
     return data;
     return data;
 }
 }
 
 
-- (void)fileSourceDidPrepared:(KTVHCDataFileSource *)fileSource
+- (id<KTVHCDataSource>)nextSource
+{
+    NSUInteger index = [self.sources indexOfObject:self.currentSource] + 1;
+    if (index < self.sources.count) {
+        KTVHCLogDataSourceManager(@"%p, Fetch next source : %@", self, [self.sources objectAtIndex:index]);
+        return [self.sources objectAtIndex:index];
+    }
+    KTVHCLogDataSourceManager(@"%p, Fetch netxt source failed", self);
+    return nil;
+}
+
+- (KTVHCDataNetworkSource *)nextNetworkSource
+{
+    NSUInteger index = [self.sources indexOfObject:self.currentNetworkSource] + 1;
+    for (; index < self.sources.count; index++) {
+        id <KTVHCDataSource> obj = [self.sources objectAtIndex:index];
+        if ([obj isKindOfClass:[KTVHCDataNetworkSource class]]) {
+            KTVHCLogDataSourceManager(@"%p, Fetch next network source : %@", self, obj);
+            return obj;
+        }
+    }
+    KTVHCLogDataSourceManager(@"%p, Fetch netxt network source failed", self);
+    return nil;
+}
+
+#pragma mark - KTVHCDataFileSourceDelegate
+
+- (void)ktv_fileSourceDidPrepare:(KTVHCDataFileSource *)fileSource
 {
 {
     [self lock];
     [self lock];
     [self callbackForPrepared];
     [self callbackForPrepared];
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)fileSource:(KTVHCDataFileSource *)fileSource didFailed:(NSError *)error
+- (void)ktv_fileSource:(KTVHCDataFileSource *)fileSource didFailWithError:(NSError *)error
 {
 {
     [self callbackForFailed:error];
     [self callbackForFailed:error];
 }
 }
 
 
-- (void)networkSourceDidPrepared:(KTVHCDataNetworkSource *)networkSource
+#pragma mark - KTVHCDataNetworkSourceDelegate
+
+- (void)ktv_networkSourceDidPrepare:(KTVHCDataNetworkSource *)networkSource
 {
 {
     [self lock];
     [self lock];
     [self callbackForPrepared];
     [self callbackForPrepared];
@@ -152,105 +189,98 @@
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)networkSourceHasAvailableData:(KTVHCDataNetworkSource *)networkSource
+- (void)ktv_networkSourceHasAvailableData:(KTVHCDataNetworkSource *)networkSource
 {
 {
     [self lock];
     [self lock];
-    if ([self.delegate respondsToSelector:@selector(sourceManagerHasAvailableData:)])
-    {
+    if ([self.delegate respondsToSelector:@selector(ktv_sourceManagerHasAvailableData:)]) {
         KTVHCLogDataSourceManager(@"%p, Callback for has available data - Begin\nSource : %@", self, networkSource);
         KTVHCLogDataSourceManager(@"%p, Callback for has available data - Begin\nSource : %@", self, networkSource);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataSourceManager(@"%p, Callback for has available data - End", self);
             KTVHCLogDataSourceManager(@"%p, Callback for has available data - End", self);
-            [self.delegate sourceManagerHasAvailableData:self];
+            [self.delegate ktv_sourceManagerHasAvailableData:self];
         }];
         }];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)networkSourceDidFinishedDownload:(KTVHCDataNetworkSource *)networkSource
+- (void)ktv_networkSourceDidFinisheDownload:(KTVHCDataNetworkSource *)networkSource
 {
 {
     [self lock];
     [self lock];
-    self.currentNetworkSource = [self.sourceQueue nextNetworkSource:self.currentNetworkSource];
+    self.currentNetworkSource = [self nextNetworkSource];
     [self.currentNetworkSource prepare];
     [self.currentNetworkSource prepare];
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)networkSource:(KTVHCDataNetworkSource *)networkSource didFailed:(NSError *)error
+- (void)ktv_networkSource:(KTVHCDataNetworkSource *)networkSource didFailWithError:(NSError *)error
 {
 {
     [self callbackForFailed:error];
     [self callbackForFailed:error];
 }
 }
 
 
+#pragma mark - Callback
+
 - (void)callbackForPrepared
 - (void)callbackForPrepared
 {
 {
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         return;
         return;
     }
     }
-    if (self.didPrepared)
-    {
+    if (self.isPrepared) {
         return;
         return;
     }
     }
-    _didPrepared = YES;
-    if ([self.delegate respondsToSelector:@selector(sourceManagerDidPrepared:)])
-    {
+    self->_prepared = YES;
+    if ([self.delegate respondsToSelector:@selector(ktv_sourceManagerDidPrepare:)]) {
         KTVHCLogDataSourceManager(@"%p, Callback for prepared - Begin", self);
         KTVHCLogDataSourceManager(@"%p, Callback for prepared - Begin", self);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataSourceManager(@"%p, Callback for prepared - End", self);
             KTVHCLogDataSourceManager(@"%p, Callback for prepared - End", self);
-            [self.delegate sourceManagerDidPrepared:self];
+            [self.delegate ktv_sourceManagerDidPrepare:self];
         }];
         }];
     }
     }
 }
 }
 
 
 - (void)callbackForReceiveResponse:(KTVHCDataResponse *)response
 - (void)callbackForReceiveResponse:(KTVHCDataResponse *)response
 {
 {
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         return;
         return;
     }
     }
-    if (self.didCalledReceiveResponse)
-    {
+    if (self.calledReceiveResponse) {
         return;
         return;
     }
     }
-    _didCalledReceiveResponse = YES;
-    if ([self.delegate respondsToSelector:@selector(sourceManager:didReceiveResponse:)])
-    {
+    self->_calledReceiveResponse = YES;
+    if ([self.delegate respondsToSelector:@selector(ktv_sourceManager:didReceiveResponse:)]) {
         KTVHCLogDataSourceManager(@"%p, Callback for did receive response - End", self);
         KTVHCLogDataSourceManager(@"%p, Callback for did receive response - End", self);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataSourceManager(@"%p, Callback for did receive response - End", self);
             KTVHCLogDataSourceManager(@"%p, Callback for did receive response - End", self);
-            [self.delegate sourceManager:self didReceiveResponse:response];
+            [self.delegate ktv_sourceManager:self didReceiveResponse:response];
         }];
         }];
     }
     }
 }
 }
 
 
 - (void)callbackForFailed:(NSError *)error
 - (void)callbackForFailed:(NSError *)error
 {
 {
-    if (!error)
-    {
+    if (!error) {
         return;
         return;
     }
     }
     [self lock];
     [self lock];
-    if (self.didClosed)
-    {
+    if (self.isClosed) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    if (self.error)
-    {
+    if (self.error) {
         [self unlock];
         [self unlock];
         return;
         return;
     }
     }
-    _error = error;
+    self->_error = error;
     KTVHCLogDataSourceManager(@"failure, %d", (int)self.error.code);
     KTVHCLogDataSourceManager(@"failure, %d", (int)self.error.code);
-    if (self.error && [self.delegate respondsToSelector:@selector(sourceManager:didFailed:)])
-    {
+    if (self.error && [self.delegate respondsToSelector:@selector(ktv_sourceManager:didFailWithError:)]) {
         KTVHCLogDataSourceManager(@"%p, Callback for network source failed - Begin\nError : %@", self, self.error);
         KTVHCLogDataSourceManager(@"%p, Callback for network source failed - Begin\nError : %@", self, self.error);
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
         [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
             KTVHCLogDataSourceManager(@"%p, Callback for network source failed - End", self);
             KTVHCLogDataSourceManager(@"%p, Callback for network source failed - End", self);
-            [self.delegate sourceManager:self didFailed:self.error];
+            [self.delegate ktv_sourceManager:self didFailWithError:self.error];
         }];
         }];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
+#pragma mark - NSLocking
+
 - (void)lock
 - (void)lock
 {
 {
     if (!self.coreLock) {
     if (!self.coreLock) {

+ 3 - 3
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.h

@@ -23,7 +23,7 @@
 /**
 /**
  *  Return file path if the content did finished cache.
  *  Return file path if the content did finished cache.
  */
  */
-- (NSURL *)completeFileURLIfExistedWithURL:(NSURL *)URL;
+- (NSURL *)completeFileURLWithURL:(NSURL *)URL;
 
 
 /**
 /**
  *  Reader for certain request.
  *  Reader for certain request.
@@ -39,12 +39,12 @@
  *  Get cache item.
  *  Get cache item.
  */
  */
 - (KTVHCDataCacheItem *)cacheItemWithURL:(NSURL *)URL;
 - (KTVHCDataCacheItem *)cacheItemWithURL:(NSURL *)URL;
-- (NSArray <KTVHCDataCacheItem *> *)allCacheItems;
+- (NSArray<KTVHCDataCacheItem *> *)allCacheItems;
 
 
 /**
 /**
  *  Get cache length.
  *  Get cache length.
  */
  */
-@property (nonatomic, assign) long long maxCacheLength;     // Default is 500M.
+@property (nonatomic) long long maxCacheLength;     // Default is 500M.
 - (long long)totalCacheLength;
 - (long long)totalCacheLength;
 
 
 /**
 /**

+ 11 - 13
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.m

@@ -7,6 +7,7 @@
 //
 //
 
 
 #import "KTVHCDataStorage.h"
 #import "KTVHCDataStorage.h"
+#import "KTVHCData+Internal.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
@@ -14,7 +15,7 @@
 
 
 + (instancetype)storage
 + (instancetype)storage
 {
 {
-    static KTVHCDataStorage * obj = nil;
+    static KTVHCDataStorage *obj = nil;
     static dispatch_once_t onceToken;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     dispatch_once(&onceToken, ^{
         obj = [[self alloc] init];
         obj = [[self alloc] init];
@@ -24,40 +25,37 @@
 
 
 - (instancetype)init
 - (instancetype)init
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         self.maxCacheLength = 500 * 1024 * 1024;
         self.maxCacheLength = 500 * 1024 * 1024;
     }
     }
     return self;
     return self;
 }
 }
 
 
-- (NSURL *)completeFileURLIfExistedWithURL:(NSURL *)URL
+- (NSURL *)completeFileURLWithURL:(NSURL *)URL
 {
 {
-    KTVHCDataUnit * unit = [[KTVHCDataUnitPool pool] unitWithURL:URL];
-    NSURL * fileURL = unit.fileURL;
+    KTVHCDataUnit *unit = [[KTVHCDataUnitPool pool] unitWithURL:URL];
+    NSURL *completeURL = unit.completeURL;
     [unit workingRelease];
     [unit workingRelease];
-    return fileURL;
+    return completeURL;
 }
 }
 
 
 - (KTVHCDataReader *)readerWithRequest:(KTVHCDataRequest *)request
 - (KTVHCDataReader *)readerWithRequest:(KTVHCDataRequest *)request
 {
 {
-    if (!request || request.URL.absoluteString.length <= 0)
-    {
+    if (!request || request.URL.absoluteString.length <= 0) {
         KTVHCLogDataStorage(@"Invaild reader request, %@", request.URL);
         KTVHCLogDataStorage(@"Invaild reader request, %@", request.URL);
         return nil;
         return nil;
     }
     }
-    KTVHCDataReader * reader = [KTVHCDataReader readerWithRequest:request];
+    KTVHCDataReader *reader = [[KTVHCDataReader alloc] initWithRequest:request];
     return reader;
     return reader;
 }
 }
 
 
 - (KTVHCDataLoader *)loaderWithRequest:(KTVHCDataRequest *)request
 - (KTVHCDataLoader *)loaderWithRequest:(KTVHCDataRequest *)request
 {
 {
-    if (!request || request.URL.absoluteString.length <= 0)
-    {
+    if (!request || request.URL.absoluteString.length <= 0) {
         KTVHCLogDataStorage(@"Invaild loader request, %@", request.URL);
         KTVHCLogDataStorage(@"Invaild loader request, %@", request.URL);
         return nil;
         return nil;
     }
     }
-    KTVHCDataLoader * loader = [KTVHCDataLoader loaderWithRequest:request];
+    KTVHCDataLoader *loader = [[KTVHCDataLoader alloc] initWithRequest:request];
     return loader;
     return loader;
 }
 }
 
 

+ 16 - 21
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnit.h

@@ -11,9 +11,9 @@
 
 
 @class KTVHCDataUnit;
 @class KTVHCDataUnit;
 
 
-@protocol KTVHCDataUnitFileDelegate <NSObject>
+@protocol KTVHCDataUnitDelegate <NSObject>
 
 
-- (void)unitShouldRearchive:(KTVHCDataUnit *)unit;
+- (void)ktv_unitDidChangeMetadata:(KTVHCDataUnit *)unit;
 
 
 @end
 @end
 
 
@@ -22,40 +22,35 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-+ (instancetype)unitWithURL:(NSURL *)URL;
+- (instancetype)initWithURL:(NSURL *)URL;
 
 
-@property (nonatomic, assign, readonly) BOOL valid;
+@property (nonatomic, copy, readonly) NSError *error;
 
 
-@property (nonatomic, copy, readonly) NSURL * URL;
-@property (nonatomic, copy, readonly) NSURL * fileURL;
-@property (nonatomic, copy, readonly) NSString * key;       // Unique Identifier.
-
-@property (nonatomic, assign, readonly) NSTimeInterval createTimeInterval;
-@property (nonatomic, assign, readonly) NSTimeInterval lastItemCreateInterval;
-
-@property (nonatomic, copy, readonly) NSDictionary * requestHeaders;
-@property (nonatomic, copy, readonly) NSDictionary * responseHeaders;
-
-@property (nonatomic, assign, readonly) long long totalLength;
-@property (nonatomic, assign, readonly) long long cacheLength;
-@property (nonatomic, assign, readonly) long long validLength;
+@property (nonatomic, copy, readonly) NSURL *URL;
+@property (nonatomic, copy, readonly) NSURL *completeURL;
+@property (nonatomic, copy, readonly) NSString *key;       // Unique Identifier.
+@property (nonatomic, copy, readonly) NSDictionary *responseHeaders;
+@property (nonatomic, readonly) NSTimeInterval createTimeInterval;
+@property (nonatomic, readonly) NSTimeInterval lastItemCreateInterval;
+@property (nonatomic, readonly) long long totalLength;
+@property (nonatomic, readonly) long long cacheLength;
+@property (nonatomic, readonly) long long validLength;
 
 
 /**
 /**
  *  Unit Item
  *  Unit Item
  */
  */
-- (NSArray <KTVHCDataUnitItem *> *)unitItems;
+- (NSArray<KTVHCDataUnitItem *> *)unitItems;
 - (void)insertUnitItem:(KTVHCDataUnitItem *)unitItem;
 - (void)insertUnitItem:(KTVHCDataUnitItem *)unitItem;
 
 
 /**
 /**
  *  Info Sync
  *  Info Sync
  */
  */
-- (void)updateRequestHeaders:(NSDictionary *)requestHeaders;
 - (void)updateResponseHeaders:(NSDictionary *)responseHeaders totalLength:(long long)totalLength;
 - (void)updateResponseHeaders:(NSDictionary *)responseHeaders totalLength:(long long)totalLength;
 
 
 /**
 /**
  *  Working
  *  Working
  */
  */
-@property (nonatomic, assign, readonly) NSInteger workingCount;
+@property (nonatomic, readonly) NSInteger workingCount;
 
 
 - (void)workingRetain;
 - (void)workingRetain;
 - (void)workingRelease;
 - (void)workingRelease;
@@ -63,7 +58,7 @@
 /**
 /**
  *  File Control
  *  File Control
  */
  */
-@property (nonatomic, weak) id <KTVHCDataUnitFileDelegate> fileDelegate;
+@property (nonatomic, weak) id <KTVHCDataUnitDelegate> delegate;
 
 
 - (void)deleteFiles;
 - (void)deleteFiles;
 
 

+ 127 - 175
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnit.m

@@ -7,61 +7,49 @@
 //
 //
 
 
 #import "KTVHCDataUnit.h"
 #import "KTVHCDataUnit.h"
-#import "KTVHCURLTools.h"
-#import "KTVHCPathTools.h"
+#import "KTVHCPathTool.h"
+#import "KTVHCURLTool.h"
+#import "KTVHCError.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCDataUnit ()
 @interface KTVHCDataUnit ()
 
 
-@property (nonatomic, strong) NSRecursiveLock * coreLock;
-@property (nonatomic, strong) NSMutableArray <KTVHCDataUnitItem *> * unitItemsInternal;
-@property (nonatomic, strong) NSMutableArray <NSArray <KTVHCDataUnitItem *> *> * lockingUnitItems;
+@property (nonatomic, strong) NSRecursiveLock *coreLock;
+@property (nonatomic, strong) NSMutableArray<KTVHCDataUnitItem *> *unitItemsInternal;
+@property (nonatomic, strong) NSMutableArray<NSArray<KTVHCDataUnitItem *> *> *lockingUnitItems;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataUnit
 @implementation KTVHCDataUnit
 
 
-+ (instancetype)unitWithURL:(NSURL *)URL
-{
-    return [[self alloc] initWithURL:URL];
-}
-
 - (instancetype)initWithURL:(NSURL *)URL
 - (instancetype)initWithURL:(NSURL *)URL
 {
 {
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        _URL = URL;
-        _key = [KTVHCURLTools keyWithURL:self.URL];
-        _createTimeInterval = [NSDate date].timeIntervalSince1970;
-        _valid = YES;
-        [self prepare];
+    if (self = [super init]) {
+        self->_URL = [URL copy];
+        self->_key = [[KTVHCURLTool tool] keyWithURL:self.URL];
+        self->_createTimeInterval = [NSDate date].timeIntervalSince1970;
+        [self commonInit];
     }
     }
     return self;
     return self;
 }
 }
 
 
 - (instancetype)initWithCoder:(NSCoder *)aDecoder
 - (instancetype)initWithCoder:(NSCoder *)aDecoder
 {
 {
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
+    if (self = [super init]) {
         @try {
         @try {
-            _URL = [NSURL URLWithString:[aDecoder decodeObjectForKey:@"URLString"]];
-            _key = [aDecoder decodeObjectForKey:@"uniqueIdentifier"];
-            _valid = YES;
-        } @catch (NSException * exception) {
-            _valid = NO;
+            self->_URL = [NSURL URLWithString:[aDecoder decodeObjectForKey:@"URLString"]];
+            self->_key = [aDecoder decodeObjectForKey:@"uniqueIdentifier"];
+        } @catch (NSException *exception) {
+            self->_error = [KTVHCError errorForException:exception];
         }
         }
         @try {
         @try {
-            _createTimeInterval = [[aDecoder decodeObjectForKey:@"createTimeInterval"] doubleValue];
-            _requestHeaders = [aDecoder decodeObjectForKey:@"requestHeaderFields"];
-            _responseHeaders = [aDecoder decodeObjectForKey:@"responseHeaderFields"];
-            _totalLength = [[aDecoder decodeObjectForKey:@"totalContentLength"] longLongValue];
-            self.unitItemsInternal = [aDecoder decodeObjectForKey:@"unitItems"];
-            [self prepare];
-            _valid = _valid && YES;
-        } @catch (NSException * exception) {
-            _valid = NO;
+            self->_createTimeInterval = [[aDecoder decodeObjectForKey:@"createTimeInterval"] doubleValue];
+            self->_responseHeaders = [aDecoder decodeObjectForKey:@"responseHeaderFields"];
+            self->_totalLength = [[aDecoder decodeObjectForKey:@"totalContentLength"] longLongValue];
+            self->_unitItemsInternal = [[aDecoder decodeObjectForKey:@"unitItems"] mutableCopy];
+            [self commonInit];
+        } @catch (NSException *exception) {
+            self->_error = [KTVHCError errorForException:exception];
         }
         }
     }
     }
     return self;
     return self;
@@ -73,7 +61,6 @@
     [aCoder encodeObject:self.URL.absoluteString forKey:@"URLString"];
     [aCoder encodeObject:self.URL.absoluteString forKey:@"URLString"];
     [aCoder encodeObject:self.key forKey:@"uniqueIdentifier"];
     [aCoder encodeObject:self.key forKey:@"uniqueIdentifier"];
     [aCoder encodeObject:@(self.createTimeInterval) forKey:@"createTimeInterval"];
     [aCoder encodeObject:@(self.createTimeInterval) forKey:@"createTimeInterval"];
-    [aCoder encodeObject:self.requestHeaders forKey:@"requestHeaderFields"];
     [aCoder encodeObject:self.responseHeaders forKey:@"responseHeaderFields"];
     [aCoder encodeObject:self.responseHeaders forKey:@"responseHeaderFields"];
     [aCoder encodeObject:@(self.totalLength) forKey:@"totalContentLength"];
     [aCoder encodeObject:@(self.totalLength) forKey:@"totalContentLength"];
     [aCoder encodeObject:self.unitItemsInternal forKey:@"unitItems"];
     [aCoder encodeObject:self.unitItemsInternal forKey:@"unitItems"];
@@ -85,63 +72,53 @@
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
 }
 }
 
 
-- (void)prepare
+- (void)commonInit
 {
 {
+    KTVHCLogAlloc(self);
     [self lock];
     [self lock];
-    if (!self.unitItemsInternal)
-    {
+    if (!self.unitItemsInternal) {
         self.unitItemsInternal = [NSMutableArray array];
         self.unitItemsInternal = [NSMutableArray array];
     }
     }
-    if (self.unitItemsInternal.count > 0)
-    {
-        NSMutableArray * removeArray = [NSMutableArray array];
-        for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-        {
-            if (obj.length <= 0)
-            {
-                [KTVHCPathTools deleteFileAtPath:obj.absolutePath];
-                [removeArray addObject:obj];
-            }
+    NSMutableArray *removal = [NSMutableArray array];
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
+        if (obj.length == 0) {
+            [KTVHCPathTool deleteFileAtPath:obj.absolutePath];
+            [removal addObject:obj];
         }
         }
-        [self.unitItemsInternal removeObjectsInArray:removeArray];
-        [removeArray removeAllObjects];
-        [self sortUnitItems];
     }
     }
-    KTVHCLogDataUnit(@"%p, Create Unit\nURL : %@\nkey : %@\ntimeInterval : %@\ntotalLength : %lld\ncacheLength : %lld\nvaildLength : %lld\nrequestHeaders : %@\nresponseHeaders : %@\nunitItems : %@", self, self.URL, self.key, [NSDate dateWithTimeIntervalSince1970:self.createTimeInterval], self.totalLength, self.cacheLength, self.validLength, self.requestHeaders, self.responseHeaders, self.unitItemsInternal);
+    [self.unitItemsInternal removeObjectsInArray:removal];
+    [self sortUnitItems];
+    KTVHCLogDataUnit(@"%p, Create Unit\nURL : %@\nkey : %@\ntimeInterval : %@\ntotalLength : %lld\ncacheLength : %lld\nvaildLength : %lld\nresponseHeaders : %@\nunitItems : %@", self, self.URL, self.key, [NSDate dateWithTimeIntervalSince1970:self.createTimeInterval], self.totalLength, self.cacheLength, self.validLength, self.responseHeaders, self.unitItemsInternal);
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (void)sortUnitItems
 - (void)sortUnitItems
 {
 {
     [self lock];
     [self lock];
-    KTVHCLogDataSourceQueue(@"%p, Sort unitItems - Begin\n%@", self, self.unitItemsInternal);
-    [self.unitItemsInternal sortUsingComparator:^NSComparisonResult(KTVHCDataUnitItem * obj1, KTVHCDataUnitItem * obj2) {
+    KTVHCLogDataUnit(@"%p, Sort unitItems - Begin\n%@", self, self.unitItemsInternal);
+    [self.unitItemsInternal sortUsingComparator:^NSComparisonResult(KTVHCDataUnitItem *obj1, KTVHCDataUnitItem *obj2) {
         NSComparisonResult result = NSOrderedDescending;
         NSComparisonResult result = NSOrderedDescending;
-        if (obj1.offset < obj2.offset)
-        {
+        if (obj1.offset < obj2.offset) {
             result = NSOrderedAscending;
             result = NSOrderedAscending;
-        }
-        else if ((obj1.offset == obj2.offset) && (obj1.length > obj2.length))
-        {
+        } else if ((obj1.offset == obj2.offset) && (obj1.length > obj2.length)) {
             result = NSOrderedAscending;
             result = NSOrderedAscending;
         }
         }
         return result;
         return result;
     }];
     }];
-    KTVHCLogDataSourceQueue(@"%p, Sort unitItems - End  \n%@", self, self.unitItemsInternal);
+    KTVHCLogDataUnit(@"%p, Sort unitItems - End  \n%@", self, self.unitItemsInternal);
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (NSArray <KTVHCDataUnitItem *> *)unitItems
+- (NSArray<KTVHCDataUnitItem *> *)unitItems
 {
 {
     [self lock];
     [self lock];
-    NSMutableArray * objs = [NSMutableArray array];
-    for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-    {
+    NSMutableArray *objs = [NSMutableArray array];
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
         [objs addObject:[obj copy]];
         [objs addObject:[obj copy]];
     }
     }
-    KTVHCLogDataSourceQueue(@"%p, Get unitItems\n%@", self, self.unitItemsInternal);
+    KTVHCLogDataUnit(@"%p, Get unitItems\n%@", self, self.unitItemsInternal);
     [self unlock];
     [self unlock];
-    return [objs copy];
+    return objs;
 }
 }
 
 
 - (void)insertUnitItem:(KTVHCDataUnitItem *)unitItem
 - (void)insertUnitItem:(KTVHCDataUnitItem *)unitItem
@@ -151,48 +128,58 @@
     [self sortUnitItems];
     [self sortUnitItems];
     KTVHCLogDataUnit(@"%p, Insert unitItem, %@", self, unitItem);
     KTVHCLogDataUnit(@"%p, Insert unitItem, %@", self, unitItem);
     [self unlock];
     [self unlock];
-    [self.fileDelegate unitShouldRearchive:self];
-}
-
-- (void)updateRequestHeaders:(NSDictionary *)requestHeaders
-{
-    [self lock];
-    _requestHeaders = requestHeaders;
-    KTVHCLogDataUnit(@"%p, Update requestHeaders\n%@", self, self.requestHeaders);
-    [self unlock];
-    [self.fileDelegate unitShouldRearchive:self];
+    [self.delegate ktv_unitDidChangeMetadata:self];
 }
 }
 
 
 - (void)updateResponseHeaders:(NSDictionary *)responseHeaders totalLength:(long long)totalLength
 - (void)updateResponseHeaders:(NSDictionary *)responseHeaders totalLength:(long long)totalLength
 {
 {
     [self lock];
     [self lock];
-    _responseHeaders = responseHeaders;
-    _totalLength = totalLength;
+    BOOL needs = NO;
+    static NSArray *whiteList = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        whiteList = @[@"Accept-Ranges",
+                      @"Connection",
+                      @"Content-Type",
+                      @"Server"];
+    });
+    NSMutableDictionary *headers = [NSMutableDictionary dictionary];
+    for (NSString *key in whiteList) {
+        NSString *value = [responseHeaders objectForKey:key];
+        if (value) {
+            [headers setObject:value forKey:key];
+        }
+    }
+    if (self.totalLength != totalLength || ![self.responseHeaders isEqualToDictionary:headers]) {
+        self->_responseHeaders = headers;
+        self->_totalLength = totalLength;
+        needs = YES;
+    }
     KTVHCLogDataUnit(@"%p, Update responseHeaders\ntotalLength : %lld\n%@", self, self.totalLength, self.responseHeaders);
     KTVHCLogDataUnit(@"%p, Update responseHeaders\ntotalLength : %lld\n%@", self, self.totalLength, self.responseHeaders);
     [self unlock];
     [self unlock];
-    [self.fileDelegate unitShouldRearchive:self];
+    if (needs) {
+        [self.delegate ktv_unitDidChangeMetadata:self];
+    }
 }
 }
 
 
-- (NSURL *)fileURL
+- (NSURL *)completeURL
 {
 {
     [self lock];
     [self lock];
-    NSURL * fileURL = nil;
-    KTVHCDataUnitItem * item = self.unitItemsInternal.firstObject;
-    if (item.offset == 0 && item.length > 0 && item.length == self.totalLength)
-    {
-        fileURL = [NSURL fileURLWithPath:item.absolutePath];
-        KTVHCLogDataUnit(@"%p, Get file path\n%@", self, fileURL);
+    NSURL *completeURL = nil;
+    KTVHCDataUnitItem *item = self.unitItemsInternal.firstObject;
+    if (item.offset == 0 && item.length > 0 && item.length == self.totalLength) {
+        completeURL = [NSURL fileURLWithPath:item.absolutePath];
+        KTVHCLogDataUnit(@"%p, Get file path\n%@", self, completeURL);
     }
     }
     [self unlock];
     [self unlock];
-    return fileURL;
+    return completeURL;
 }
 }
 
 
 - (long long)cacheLength
 - (long long)cacheLength
 {
 {
     [self lock];
     [self lock];
     long long length = 0;
     long long length = 0;
-    for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-    {
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
         length += obj.length;
         length += obj.length;
     }
     }
     [self unlock];
     [self unlock];
@@ -204,8 +191,7 @@
     [self lock];
     [self lock];
     long long offset = 0;
     long long offset = 0;
     long long length = 0;
     long long length = 0;
-    for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-    {
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
         long long invalidLength = MAX(offset - obj.offset, 0);
         long long invalidLength = MAX(offset - obj.offset, 0);
         long long vaildLength = MAX(obj.length - invalidLength, 0);
         long long vaildLength = MAX(obj.length - invalidLength, 0);
         offset = MAX(offset, obj.offset + obj.length);
         offset = MAX(offset, obj.offset + obj.length);
@@ -219,10 +205,8 @@
 {
 {
     [self lock];
     [self lock];
     NSTimeInterval timeInterval = self.createTimeInterval;
     NSTimeInterval timeInterval = self.createTimeInterval;
-    for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-    {
-        if (obj.createTimeInterval > timeInterval)
-        {
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
+        if (obj.createTimeInterval > timeInterval) {
             timeInterval = obj.createTimeInterval;
             timeInterval = obj.createTimeInterval;
         }
         }
     }
     }
@@ -233,37 +217,31 @@
 - (void)workingRetain
 - (void)workingRetain
 {
 {
     [self lock];
     [self lock];
-    _workingCount++;
+    self->_workingCount += 1;
     KTVHCLogDataUnit(@"%p, Working retain  : %ld", self, (long)self.workingCount);
     KTVHCLogDataUnit(@"%p, Working retain  : %ld", self, (long)self.workingCount);
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (void)workingRelease
 - (void)workingRelease
 {
 {
-    BOOL mergeSuccess = NO;
     [self lock];
     [self lock];
-    _workingCount--;
+    self->_workingCount -= 1;
     KTVHCLogDataUnit(@"%p, Working release : %ld", self, (long)self.workingCount);
     KTVHCLogDataUnit(@"%p, Working release : %ld", self, (long)self.workingCount);
-    if (self.workingCount <= 0)
-    {
-        mergeSuccess = [self mergeFilesIfNeeded];
-    }
+    BOOL needs = [self mergeFilesIfNeeded];
     [self unlock];
     [self unlock];
-    if (mergeSuccess)
-    {
-        [self.fileDelegate unitShouldRearchive:self];
+    if (needs) {
+        [self.delegate ktv_unitDidChangeMetadata:self];
     }
     }
 }
 }
 
 
 - (void)deleteFiles
 - (void)deleteFiles
 {
 {
-    if (!self.URL)
-    {
+    if (!self.URL) {
         return;
         return;
     }
     }
     [self lock];
     [self lock];
-    NSString * path = [KTVHCPathTools directoryPathWithURL:self.URL];
-    [KTVHCPathTools deleteDirectoryAtPath:path];
+    NSString *path = [KTVHCPathTool directoryPathWithURL:self.URL];
+    [KTVHCPathTool deleteDirectoryAtPath:path];
     KTVHCLogDataUnit(@"%p, Delete files", self);
     KTVHCLogDataUnit(@"%p, Delete files", self);
     [self unlock];
     [self unlock];
 }
 }
@@ -271,72 +249,56 @@
 - (BOOL)mergeFilesIfNeeded
 - (BOOL)mergeFilesIfNeeded
 {
 {
     [self lock];
     [self lock];
-    if (self.workingCount > 0 || self.totalLength <= 0 || self.unitItemsInternal.count <= 0)
-    {
+    if (self.workingCount > 0 || self.totalLength == 0 || self.unitItemsInternal.count == 0) {
         [self unlock];
         [self unlock];
         return NO;
         return NO;
     }
     }
-    NSString * path = [KTVHCPathTools completeFilePathWithURL:self.URL];
-    if ([self.unitItemsInternal.firstObject.absolutePath isEqualToString:path])
-    {
+    NSString *path = [KTVHCPathTool completeFilePathWithURL:self.URL];
+    if ([self.unitItemsInternal.firstObject.absolutePath isEqualToString:path]) {
         [self unlock];
         [self unlock];
         return NO;
         return NO;
     }
     }
-    if (self.totalLength != self.validLength)
-    {
+    if (self.totalLength != self.validLength) {
         [self unlock];
         [self unlock];
         return NO;
         return NO;
     }
     }
-    BOOL failed = NO;
+    NSError *error = nil;
     long long offset = 0;
     long long offset = 0;
-    [KTVHCPathTools deleteFileAtPath:path];
-    [KTVHCPathTools createFileAtPath:path];
-    NSFileHandle * writingHandle = [NSFileHandle fileHandleForWritingAtPath:path];
-    for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-    {
-        if (failed)
-        {
+    [KTVHCPathTool deleteFileAtPath:path];
+    [KTVHCPathTool createFileAtPath:path];
+    NSFileHandle *writingHandle = [NSFileHandle fileHandleForWritingAtPath:path];
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
+        if (error) {
             break;
             break;
         }
         }
         NSAssert(offset >= obj.offset, @"invaild unit item.");
         NSAssert(offset >= obj.offset, @"invaild unit item.");
-        if (offset >= (obj.offset + obj.length))
-        {
+        if (offset >= (obj.offset + obj.length)) {
             KTVHCLogDataUnit(@"%p, Merge files continue", self);
             KTVHCLogDataUnit(@"%p, Merge files continue", self);
             continue;
             continue;
         }
         }
-        NSFileHandle * readingHandle = [NSFileHandle fileHandleForReadingAtPath:obj.absolutePath];
-        @try
-        {
+        NSFileHandle *readingHandle = [NSFileHandle fileHandleForReadingAtPath:obj.absolutePath];
+        @try {
             [readingHandle seekToFileOffset:offset - obj.offset];
             [readingHandle seekToFileOffset:offset - obj.offset];
-        }
-        @catch (NSException * exception)
-        {
+        } @catch (NSException *exception) {
             KTVHCLogDataUnit(@"%p, Merge files seek exception\n%@", self, exception);
             KTVHCLogDataUnit(@"%p, Merge files seek exception\n%@", self, exception);
-            failed = YES;
+            error = [KTVHCError errorForException:exception];
         }
         }
-        if (failed)
-        {
+        if (error) {
             break;
             break;
         }
         }
-        while (!failed)
-        {
-            @autoreleasepool
-            {
-                NSData * data = [readingHandle readDataOfLength:1024 * 1024 * 1];
-                if (data.length <= 0)
-                {
+        while (!error) {
+            @autoreleasepool {
+                NSData *data = [readingHandle readDataOfLength:1024 * 1024 * 1];
+                if (data.length == 0) {
                     KTVHCLogDataUnit(@"%p, Merge files break", self);
                     KTVHCLogDataUnit(@"%p, Merge files break", self);
                     break;
                     break;
                 }
                 }
                 KTVHCLogDataUnit(@"%p, Merge write data : %lld", self, (long long)data.length);
                 KTVHCLogDataUnit(@"%p, Merge write data : %lld", self, (long long)data.length);
-                @try
-                {
+                @try {
                     [writingHandle writeData:data];
                     [writingHandle writeData:data];
-                }
-                @catch (NSException * exception)
-                {
+                } @catch (NSException *exception) {
                     KTVHCLogDataUnit(@"%p, Merge files write exception\n%@", self, exception);
                     KTVHCLogDataUnit(@"%p, Merge files write exception\n%@", self, exception);
-                    failed = YES;
+                    error = [KTVHCError errorForException:exception];
                 }
                 }
             }
             }
         }
         }
@@ -344,28 +306,23 @@
         offset = obj.offset + obj.length;
         offset = obj.offset + obj.length;
         KTVHCLogDataUnit(@"%p, Merge next : %lld", self, offset);
         KTVHCLogDataUnit(@"%p, Merge next : %lld", self, offset);
     }
     }
-    @try
-    {
+    @try {
         [writingHandle synchronizeFile];
         [writingHandle synchronizeFile];
         [writingHandle closeFile];
         [writingHandle closeFile];
-    }
-    @catch (NSException * exception)
-    {
-        KTVHCLogDataUnit(@"%p, Merge files close exception, %d\n%@", self, failed, exception);
-        failed = YES;
+    } @catch (NSException *exception) {
+        KTVHCLogDataUnit(@"%p, Merge files close exception, %@", self, exception);
+        error = [KTVHCError errorForException:exception];
     }
     }
     KTVHCLogDataUnit(@"%p, Merge finished\ntotalLength : %lld\noffset : %lld", self, self.totalLength, offset);
     KTVHCLogDataUnit(@"%p, Merge finished\ntotalLength : %lld\noffset : %lld", self, self.totalLength, offset);
-    if (failed || [KTVHCPathTools sizeOfItemAtPath:path] != self.totalLength)
-    {
-        [KTVHCPathTools deleteFileAtPath:path];
+    if (error || [KTVHCPathTool sizeAtPath:path] != self.totalLength) {
+        [KTVHCPathTool deleteFileAtPath:path];
         [self unlock];
         [self unlock];
         return NO;
         return NO;
     }
     }
     KTVHCLogDataUnit(@"%p, Merge replace items", self);
     KTVHCLogDataUnit(@"%p, Merge replace items", self);
-    KTVHCDataUnitItem * item = [[KTVHCDataUnitItem alloc] initWithPath:path offset:0];
-    for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
-    {
-        [KTVHCPathTools deleteFileAtPath:obj.absolutePath];
+    KTVHCDataUnitItem *item = [[KTVHCDataUnitItem alloc] initWithPath:path];
+    for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
+        [KTVHCPathTool deleteFileAtPath:obj.absolutePath];
     }
     }
     [self.unitItemsInternal removeAllObjects];
     [self.unitItemsInternal removeAllObjects];
     [self.unitItemsInternal addObject:item];
     [self.unitItemsInternal addObject:item];
@@ -375,33 +332,28 @@
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSRecursiveLock alloc] init];
         self.coreLock = [[NSRecursiveLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];
-    if (!self.lockingUnitItems)
-    {
+    if (!self.lockingUnitItems) {
         self.lockingUnitItems = [NSMutableArray array];
         self.lockingUnitItems = [NSMutableArray array];
     }
     }
-    NSArray <KTVHCDataUnitItem *> * objs = [NSArray arrayWithArray:self.unitItemsInternal];
+    NSArray<KTVHCDataUnitItem *> *objs = [NSArray arrayWithArray:self.unitItemsInternal];
     [self.lockingUnitItems addObject:objs];
     [self.lockingUnitItems addObject:objs];
-    for (KTVHCDataUnitItem * obj in objs)
-    {
+    for (KTVHCDataUnitItem *obj in objs) {
         [obj lock];
         [obj lock];
     }
     }
 }
 }
 
 
 - (void)unlock
 - (void)unlock
 {
 {
-    NSArray <KTVHCDataUnitItem *> * objs = self.lockingUnitItems.lastObject;
+    NSArray<KTVHCDataUnitItem *> *objs = self.lockingUnitItems.lastObject;
     [self.lockingUnitItems removeLastObject];
     [self.lockingUnitItems removeLastObject];
-    if (self.lockingUnitItems.count <= 0)
-    {
+    if (self.lockingUnitItems.count <= 0) {
         self.lockingUnitItems = nil;
         self.lockingUnitItems = nil;
     }
     }
-    for (KTVHCDataUnitItem * obj in objs)
-    {
+    for (KTVHCDataUnitItem *obj in objs) {
         [obj unlock];
         [obj unlock];
     }
     }
     [self.coreLock unlock];
     [self.coreLock unlock];

+ 8 - 10
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitItem.h

@@ -11,18 +11,16 @@
 @interface KTVHCDataUnitItem : NSObject <NSCopying, NSCoding, NSLocking>
 @interface KTVHCDataUnitItem : NSObject <NSCopying, NSCoding, NSLocking>
 
 
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
-- (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithPath:(NSString *)path offset:(long long)offset;
+- (instancetype)initWithPath:(NSString *)path;
+- (instancetype)initWithPath:(NSString *)path offset:(uint64_t)offset;
 
 
-@property (nonatomic, assign, readonly) NSTimeInterval createTimeInterval;
+@property (nonatomic, copy, readonly) NSString *relativePath;
+@property (nonatomic, copy, readonly) NSString *absolutePath;
+@property (nonatomic, readonly) NSTimeInterval createTimeInterval;
+@property (nonatomic, readonly) long long offset;
+@property (nonatomic, readonly) long long length;
 
 
-@property (nonatomic, copy, readonly) NSString * relativePath;
-@property (nonatomic, copy, readonly) NSString * absolutePath;
-
-@property (nonatomic, assign, readonly) long long offset;
-@property (nonatomic, assign, readonly) long long length;
-
-- (void)setLength:(long long)length;
+- (void)updateLength:(long long)length;
 
 
 @end
 @end

+ 25 - 31
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitItem.m

@@ -7,12 +7,12 @@
 //
 //
 
 
 #import "KTVHCDataUnitItem.h"
 #import "KTVHCDataUnitItem.h"
-#import "KTVHCPathTools.h"
+#import "KTVHCPathTool.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCDataUnitItem ()
 @interface KTVHCDataUnitItem ()
 
 
-@property (nonatomic, strong) NSRecursiveLock * coreLock;
+@property (nonatomic, strong) NSRecursiveLock *coreLock;
 
 
 @end
 @end
 
 
@@ -21,7 +21,7 @@
 - (id)copyWithZone:(NSZone *)zone
 - (id)copyWithZone:(NSZone *)zone
 {
 {
     [self lock];
     [self lock];
-    KTVHCDataUnitItem * obj = [[KTVHCDataUnitItem alloc] initForCopy];
+    KTVHCDataUnitItem *obj = [[KTVHCDataUnitItem alloc] init];
     obj->_relativePath = self.relativePath;
     obj->_relativePath = self.relativePath;
     obj->_absolutePath = self.absolutePath;
     obj->_absolutePath = self.absolutePath;
     obj->_createTimeInterval = self.createTimeInterval;
     obj->_createTimeInterval = self.createTimeInterval;
@@ -31,37 +31,33 @@
     return obj;
     return obj;
 }
 }
 
 
-- (instancetype)initForCopy
+- (instancetype)initWithPath:(NSString *)path
 {
 {
-    if (self = [super init])
-    {
-        
-    }
-    return self;
+    return [self initWithPath:path offset:0];
 }
 }
 
 
-- (instancetype)initWithPath:(NSString *)path offset:(long long)offset
+- (instancetype)initWithPath:(NSString *)path offset:(uint64_t)offset
 {
 {
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        _createTimeInterval = [NSDate date].timeIntervalSince1970;
-        _relativePath = [KTVHCPathTools relativePathWithAbsoultePath:path];
-        _offset = offset;
-        [self prepare];
+    if (self = [super init]) {
+        self->_createTimeInterval = [NSDate date].timeIntervalSince1970;
+        self->_relativePath = [KTVHCPathTool converToRelativePath:path];
+        self->_absolutePath = [KTVHCPathTool converToAbsoultePath:path];
+        self->_offset = offset;
+        self->_length = [KTVHCPathTool sizeAtPath:self.absolutePath];
+        [self commonInit];
     }
     }
     return self;
     return self;
 }
 }
 
 
 - (instancetype)initWithCoder:(NSCoder *)aDecoder
 - (instancetype)initWithCoder:(NSCoder *)aDecoder
 {
 {
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        _createTimeInterval = [[aDecoder decodeObjectForKey:@"createTimeInterval"] doubleValue];
-        _relativePath = [aDecoder decodeObjectForKey:@"relativePath"];
-        _offset = [[aDecoder decodeObjectForKey:@"offset"] longLongValue];
-        [self prepare];
+    if (self = [super init]) {
+        self->_createTimeInterval = [[aDecoder decodeObjectForKey:@"createTimeInterval"] doubleValue];
+        self->_relativePath = [aDecoder decodeObjectForKey:@"relativePath"];
+        self->_absolutePath = [KTVHCPathTool converToAbsoultePath:self.relativePath];
+        self->_offset = [[aDecoder decodeObjectForKey:@"offset"] longLongValue];
+        self->_length = [KTVHCPathTool sizeAtPath:self.absolutePath];
+        [self commonInit];
     }
     }
     return self;
     return self;
 }
 }
@@ -78,25 +74,23 @@
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
 }
 }
 
 
-- (void)prepare
+- (void)commonInit
 {
 {
-    _absolutePath = [KTVHCPathTools absoultePathWithRelativePath:self.relativePath];
-    self.length = [KTVHCPathTools sizeOfItemAtPath:self.absolutePath];
+    KTVHCLogAlloc(self);
     KTVHCLogDataUnitItem(@"%p, Create Unit Item\nabsolutePath : %@\nrelativePath : %@\nOffset : %lld\nLength : %lld", self, self.absolutePath, self.relativePath, self.offset, self.length);
     KTVHCLogDataUnitItem(@"%p, Create Unit Item\nabsolutePath : %@\nrelativePath : %@\nOffset : %lld\nLength : %lld", self, self.absolutePath, self.relativePath, self.offset, self.length);
 }
 }
 
 
-- (void)setLength:(long long)length
+- (void)updateLength:(long long)length
 {
 {
     [self lock];
     [self lock];
-    _length = length;
+    self->_length = length;
     KTVHCLogDataUnitItem(@"%p, Set length : %lld", self, length);
     KTVHCLogDataUnitItem(@"%p, Set length : %lld", self, length);
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSRecursiveLock alloc] init];
         self.coreLock = [[NSRecursiveLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];

+ 1 - 1
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitPool.h

@@ -21,7 +21,7 @@
 
 
 - (long long)totalCacheLength;
 - (long long)totalCacheLength;
 
 
-- (NSArray <KTVHCDataCacheItem *> *)allCacheItem;
+- (NSArray<KTVHCDataCacheItem *> *)allCacheItem;
 - (KTVHCDataCacheItem *)cacheItemWithURL:(NSURL *)URL;
 - (KTVHCDataCacheItem *)cacheItemWithURL:(NSURL *)URL;
 
 
 - (void)deleteUnitWithURL:(NSURL *)URL;
 - (void)deleteUnitWithURL:(NSURL *)URL;

+ 71 - 91
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitPool.m

@@ -8,20 +8,20 @@
 
 
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataUnitQueue.h"
 #import "KTVHCDataUnitQueue.h"
-#import "KTVHCDataPrivate.h"
-#import "KTVHCPathTools.h"
-#import "KTVHCURLTools.h"
+#import "KTVHCData+Internal.h"
+#import "KTVHCPathTool.h"
+#import "KTVHCURLTool.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 
 
-@interface KTVHCDataUnitPool () <NSLocking, KTVHCDataUnitFileDelegate>
+@interface KTVHCDataUnitPool () <NSLocking, KTVHCDataUnitDelegate>
 
 
-@property (nonatomic, strong) NSRecursiveLock * coreLock;
-@property (nonatomic, strong) KTVHCDataUnitQueue * unitQueue;
-@property (nonatomic, assign) int64_t expectArchiveIndex;
-@property (nonatomic, assign) int64_t actualArchiveIndex;
+@property (nonatomic, strong) NSRecursiveLock *coreLock;
+@property (nonatomic, strong) KTVHCDataUnitQueue *unitQueue;
 @property (nonatomic, strong) dispatch_queue_t archiveQueue;
 @property (nonatomic, strong) dispatch_queue_t archiveQueue;
+@property (nonatomic) int64_t expectArchiveIndex;
+@property (nonatomic) int64_t actualArchiveIndex;
 
 
 @end
 @end
 
 
@@ -29,7 +29,7 @@
 
 
 + (instancetype)pool
 + (instancetype)pool
 {
 {
-    static KTVHCDataUnitPool * obj = nil;
+    static KTVHCDataUnitPool *obj = nil;
     static dispatch_once_t onceToken;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     dispatch_once(&onceToken, ^{
         obj = [[self alloc] init];
         obj = [[self alloc] init];
@@ -39,12 +39,10 @@
 
 
 - (instancetype)init
 - (instancetype)init
 {
 {
-    if (self = [super init])
-    {
-        self.unitQueue = [KTVHCDataUnitQueue queueWithPath:[KTVHCPathTools archivePath]];
-        for (KTVHCDataUnit * obj in self.unitQueue.allUnits)
-        {
-            obj.fileDelegate = self;
+    if (self = [super init]) {
+        self.unitQueue = [[KTVHCDataUnitQueue alloc] initWithPath:[KTVHCPathTool archivePath]];
+        for (KTVHCDataUnit *obj in self.unitQueue.allUnits) {
+            obj.delegate = self;
         }
         }
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
         [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
         [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
@@ -61,17 +59,15 @@
 
 
 - (KTVHCDataUnit *)unitWithURL:(NSURL *)URL
 - (KTVHCDataUnit *)unitWithURL:(NSURL *)URL
 {
 {
-    if (URL.absoluteString.length <= 0)
-    {
+    if (URL.absoluteString.length <= 0) {
         return nil;
         return nil;
     }
     }
     [self lock];
     [self lock];
-    NSString * key = [KTVHCURLTools keyWithURL:URL];
-    KTVHCDataUnit * unit = [self.unitQueue unitWithKey:key];
-    if (!unit)
-    {
-        unit = [KTVHCDataUnit unitWithURL:URL];
-        unit.fileDelegate = self;
+    NSString *key = [[KTVHCURLTool tool] keyWithURL:URL];
+    KTVHCDataUnit *unit = [self.unitQueue unitWithKey:key];
+    if (!unit) {
+        unit = [[KTVHCDataUnit alloc] initWithURL:URL];
+        unit.delegate = self;
         KTVHCLogDataUnitPool(@"%p, Insert Unit, %@", self, unit);
         KTVHCLogDataUnitPool(@"%p, Insert Unit, %@", self, unit);
         [self.unitQueue putUnit:unit];
         [self.unitQueue putUnit:unit];
         [self setNeedsArchive];
         [self setNeedsArchive];
@@ -85,9 +81,8 @@
 {
 {
     [self lock];
     [self lock];
     long long length = 0;
     long long length = 0;
-    NSArray <KTVHCDataUnit *> * units = [self.unitQueue allUnits];
-    for (KTVHCDataUnit * obj in units)
-    {
+    NSArray<KTVHCDataUnit *> *units = [self.unitQueue allUnits];
+    for (KTVHCDataUnit *obj in units) {
         length += obj.cacheLength;
         length += obj.cacheLength;
     }
     }
     [self unlock];
     [self unlock];
@@ -96,48 +91,45 @@
 
 
 - (KTVHCDataCacheItem *)cacheItemWithURL:(NSURL *)URL
 - (KTVHCDataCacheItem *)cacheItemWithURL:(NSURL *)URL
 {
 {
-    if (URL.absoluteString.length <= 0)
-    {
+    if (URL.absoluteString.length <= 0) {
         return nil;
         return nil;
     }
     }
     [self lock];
     [self lock];
-    KTVHCDataCacheItem * cacheItem = nil;
-    NSString * key = [KTVHCURLTools keyWithURL:URL];
-    KTVHCDataUnit * obj = [self.unitQueue unitWithKey:key];
-    if (obj)
-    {
-        NSArray * items = obj.unitItems;
-        NSMutableArray * itemZones = [NSMutableArray array];
-        for (KTVHCDataUnitItem * unitItem in items)
-        {
-            KTVHCDataCacheItemZone * itemZone = [KTVHCDataCacheItemZone itemZoneWithOffset:unitItem.offset length:unitItem.length];
-            [itemZones addObject:itemZone];
+    KTVHCDataCacheItem *cacheItem = nil;
+    NSString *key = [[KTVHCURLTool tool] keyWithURL:URL];
+    KTVHCDataUnit *obj = [self.unitQueue unitWithKey:key];
+    if (obj) {
+        NSArray *items = obj.unitItems;
+        NSMutableArray *zones = [NSMutableArray array];
+        for (KTVHCDataUnitItem *item in items) {
+            KTVHCDataCacheItemZone *zone = [[KTVHCDataCacheItemZone alloc] initWithOffset:item.offset length:item.length];
+            [zones addObject:zone];
         }
         }
-        if (itemZones.count <= 0)
-        {
-            itemZones = nil;
+        if (zones.count == 0) {
+            zones = nil;
         }
         }
-        cacheItem = [KTVHCDataCacheItem itemWithURL:obj.URL totalLength:obj.totalLength cacheLength:obj.cacheLength vaildLength:obj.validLength zones:itemZones];
+        cacheItem = [[KTVHCDataCacheItem alloc] initWithURL:obj.URL
+                                                      zones:zones
+                                                totalLength:obj.totalLength
+                                                cacheLength:obj.cacheLength
+                                                vaildLength:obj.validLength];
     }
     }
     [self unlock];
     [self unlock];
     return cacheItem;
     return cacheItem;
 }
 }
 
 
-- (NSArray <KTVHCDataCacheItem *> *)allCacheItem
+- (NSArray<KTVHCDataCacheItem *> *)allCacheItem
 {
 {
     [self lock];
     [self lock];
-    NSMutableArray * cacheItems = [NSMutableArray array];
-    NSArray <KTVHCDataUnit *> * units = [self.unitQueue allUnits];
-    for (KTVHCDataUnit * obj in units)
-    {
-        KTVHCDataCacheItem * cacheItem = [self cacheItemWithURL:obj.URL];
-        if (cacheItem)
-        {
+    NSMutableArray *cacheItems = [NSMutableArray array];
+    NSArray<KTVHCDataUnit *> *units = [self.unitQueue allUnits];
+    for (KTVHCDataUnit *obj in units) {
+        KTVHCDataCacheItem *cacheItem = [self cacheItemWithURL:obj.URL];
+        if (cacheItem) {
             [cacheItems addObject:cacheItem];
             [cacheItems addObject:cacheItem];
         }
         }
     }
     }
-    if (cacheItems.count <= 0)
-    {
+    if (cacheItems.count == 0) {
         cacheItems = nil;
         cacheItems = nil;
     }
     }
     [self unlock];
     [self unlock];
@@ -146,15 +138,13 @@
 
 
 - (void)deleteUnitWithURL:(NSURL *)URL
 - (void)deleteUnitWithURL:(NSURL *)URL
 {
 {
-    if (URL.absoluteString.length <= 0)
-    {
+    if (URL.absoluteString.length <= 0) {
         return;
         return;
     }
     }
     [self lock];
     [self lock];
-    NSString * key = [KTVHCURLTools keyWithURL:URL];
-    KTVHCDataUnit * obj = [self.unitQueue unitWithKey:key];
-    if (obj && obj.workingCount <= 0)
-    {
+    NSString *key = [[KTVHCURLTool tool] keyWithURL:URL];
+    KTVHCDataUnit *obj = [self.unitQueue unitWithKey:key];
+    if (obj && obj.workingCount <= 0) {
         KTVHCLogDataUnit(@"%p, Delete Unit\nUnit : %@\nFunc : %s", self, obj, __func__);
         KTVHCLogDataUnit(@"%p, Delete Unit\nUnit : %@\nFunc : %s", self, obj, __func__);
         [obj deleteFiles];
         [obj deleteFiles];
         [self.unitQueue popUnit:obj];
         [self.unitQueue popUnit:obj];
@@ -165,15 +155,14 @@
 
 
 - (void)deleteUnitsWithLength:(long long)length
 - (void)deleteUnitsWithLength:(long long)length
 {
 {
-    if (length <= 0)
-    {
+    if (length <= 0) {
         return;
         return;
     }
     }
     [self lock];
     [self lock];
     BOOL needArchive = NO;
     BOOL needArchive = NO;
     long long currentLength = 0;
     long long currentLength = 0;
-    NSArray <KTVHCDataUnit *> * units = [self.unitQueue allUnits];
-    [units sortedArrayUsingComparator:^NSComparisonResult(KTVHCDataUnit * obj1, KTVHCDataUnit * obj2) {
+    NSArray<KTVHCDataUnit *> *units = [self.unitQueue allUnits];
+    [units sortedArrayUsingComparator:^NSComparisonResult(KTVHCDataUnit *obj1, KTVHCDataUnit *obj2) {
         NSComparisonResult result = NSOrderedDescending;
         NSComparisonResult result = NSOrderedDescending;
         [obj1 lock];
         [obj1 lock];
         [obj2 lock];
         [obj2 lock];
@@ -188,10 +177,8 @@
         [obj2 unlock];
         [obj2 unlock];
         return result;
         return result;
     }];
     }];
-    for (KTVHCDataUnit * obj in units)
-    {
-        if (obj.workingCount <= 0)
-        {
+    for (KTVHCDataUnit *obj in units) {
+        if (obj.workingCount <= 0) {
             [obj lock];
             [obj lock];
             currentLength += obj.cacheLength;
             currentLength += obj.cacheLength;
             KTVHCLogDataUnit(@"%p, Delete Unit\nUnit : %@\nFunc : %s", self, obj, __func__);
             KTVHCLogDataUnit(@"%p, Delete Unit\nUnit : %@\nFunc : %s", self, obj, __func__);
@@ -200,13 +187,11 @@
             [self.unitQueue popUnit:obj];
             [self.unitQueue popUnit:obj];
             needArchive = YES;
             needArchive = YES;
         }
         }
-        if (currentLength >= length)
-        {
+        if (currentLength >= length) {
             break;
             break;
         }
         }
     }
     }
-    if (needArchive)
-    {
+    if (needArchive) {
         [self setNeedsArchive];
         [self setNeedsArchive];
     }
     }
     [self unlock];
     [self unlock];
@@ -216,43 +201,33 @@
 {
 {
     [self lock];
     [self lock];
     BOOL needArchive = NO;
     BOOL needArchive = NO;
-    NSArray <KTVHCDataUnit *> * units = [self.unitQueue allUnits];
-    for (KTVHCDataUnit * obj in units)
-    {
-        if (obj.workingCount <= 0)
-        {
+    NSArray<KTVHCDataUnit *> *units = [self.unitQueue allUnits];
+    for (KTVHCDataUnit *obj in units) {
+        if (obj.workingCount <= 0) {
             KTVHCLogDataUnit(@"%p, Delete Unit\nUnit : %@\nFunc : %s", self, obj, __func__);
             KTVHCLogDataUnit(@"%p, Delete Unit\nUnit : %@\nFunc : %s", self, obj, __func__);
             [obj deleteFiles];
             [obj deleteFiles];
             [self.unitQueue popUnit:obj];
             [self.unitQueue popUnit:obj];
             needArchive = YES;
             needArchive = YES;
         }
         }
     }
     }
-    if (needArchive)
-    {
+    if (needArchive) {
         [self setNeedsArchive];
         [self setNeedsArchive];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)unitShouldRearchive:(KTVHCDataUnit *)unit
-{
-    [self setNeedsArchive];
-}
-
 - (void)setNeedsArchive
 - (void)setNeedsArchive
 {
 {
     [self lock];
     [self lock];
     self.expectArchiveIndex += 1;
     self.expectArchiveIndex += 1;
     int64_t expectArchiveIndex = self.expectArchiveIndex;
     int64_t expectArchiveIndex = self.expectArchiveIndex;
     [self unlock];
     [self unlock];
-    if (!self.archiveQueue)
-    {
+    if (!self.archiveQueue) {
         self.archiveQueue = dispatch_queue_create("KTVHTTPCache-archiveQueue", DISPATCH_QUEUE_SERIAL);
         self.archiveQueue = dispatch_queue_create("KTVHTTPCache-archiveQueue", DISPATCH_QUEUE_SERIAL);
     }
     }
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), self.archiveQueue, ^{
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), self.archiveQueue, ^{
         [self lock];
         [self lock];
-        if (self.expectArchiveIndex == expectArchiveIndex)
-        {
+        if (self.expectArchiveIndex == expectArchiveIndex) {
             [self archiveIfNeeded];
             [self archiveIfNeeded];
         }
         }
         [self unlock];
         [self unlock];
@@ -262,14 +237,20 @@
 - (void)archiveIfNeeded
 - (void)archiveIfNeeded
 {
 {
     [self lock];
     [self lock];
-    if (self.actualArchiveIndex != self.expectArchiveIndex)
-    {
+    if (self.actualArchiveIndex != self.expectArchiveIndex) {
         self.actualArchiveIndex = self.expectArchiveIndex;
         self.actualArchiveIndex = self.expectArchiveIndex;
         [self.unitQueue archive];
         [self.unitQueue archive];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
+#pragma mark - KTVHCDataUnitDelegate
+
+- (void)ktv_unitDidChangeMetadata:(KTVHCDataUnit *)unit
+{
+    [self setNeedsArchive];
+}
+
 #pragma mark - UIApplicationWillTerminateNotification
 #pragma mark - UIApplicationWillTerminateNotification
 
 
 - (void)applicationWillTerminate:(NSNotification *)notification
 - (void)applicationWillTerminate:(NSNotification *)notification
@@ -291,8 +272,7 @@
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSRecursiveLock alloc] init];
         self.coreLock = [[NSRecursiveLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];

+ 2 - 2
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitQueue.h

@@ -14,9 +14,9 @@
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-+ (instancetype)queueWithPath:(NSString *)path;
+- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
 
 
-- (NSArray <KTVHCDataUnit *> *)allUnits;
+- (NSArray<KTVHCDataUnit *> *)allUnits;
 - (KTVHCDataUnit *)unitWithKey:(NSString *)key;
 - (KTVHCDataUnit *)unitWithKey:(NSString *)key;
 
 
 - (void)putUnit:(KTVHCDataUnit *)unit;
 - (void)putUnit:(KTVHCDataUnit *)unit;

+ 20 - 35
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataUnitQueue.m

@@ -11,62 +11,51 @@
 
 
 @interface KTVHCDataUnitQueue ()
 @interface KTVHCDataUnitQueue ()
 
 
-@property (nonatomic, copy) NSString * path;
-@property (nonatomic, strong) NSMutableArray <KTVHCDataUnit *> * unitArray;
+@property (nonatomic, copy) NSString *path;
+@property (nonatomic, strong) NSMutableArray<KTVHCDataUnit *> *unitArray;
 
 
 @end
 @end
 
 
 @implementation KTVHCDataUnitQueue
 @implementation KTVHCDataUnitQueue
 
 
-+ (instancetype)queueWithPath:(NSString *)path
-{
-    return [[self alloc] initWithPath:path];
-}
-
 - (instancetype)initWithPath:(NSString *)path
 - (instancetype)initWithPath:(NSString *)path
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         self.path = path;
         self.path = path;
-        NSMutableArray * unitArray = nil;
+        NSMutableArray *unitArray = nil;
         @try {
         @try {
             unitArray = [NSKeyedUnarchiver unarchiveObjectWithFile:self.path];
             unitArray = [NSKeyedUnarchiver unarchiveObjectWithFile:self.path];
-        } @catch (NSException * exception) {
+        } @catch (NSException *exception) {
             KTVHCLogDataUnitQueue(@"%p, Init exception\nname : %@\breason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
             KTVHCLogDataUnitQueue(@"%p, Init exception\nname : %@\breason : %@\nuserInfo : %@", self, exception.name, exception.reason, exception.userInfo);
         }
         }
         self.unitArray = [NSMutableArray array];
         self.unitArray = [NSMutableArray array];
-        for (KTVHCDataUnit * obj in unitArray) {
-            if (obj.valid) {
-                [self.unitArray addObject:obj];
-            } else {
+        for (KTVHCDataUnit *obj in unitArray) {
+            if (obj.error) {
                 [obj deleteFiles];
                 [obj deleteFiles];
+            } else {
+                [self.unitArray addObject:obj];
             }
             }
         }
         }
     }
     }
     return self;
     return self;
 }
 }
 
 
-- (NSArray <KTVHCDataUnit *> *)allUnits
+- (NSArray<KTVHCDataUnit *> *)allUnits
 {
 {
-    if (self.unitArray.count <= 0)
-    {
+    if (self.unitArray.count <= 0) {
         return nil;
         return nil;
     }
     }
-    NSArray <KTVHCDataUnit *> * units = [self.unitArray copy];
-    return units;
+    return [self.unitArray copy];
 }
 }
 
 
 - (KTVHCDataUnit *)unitWithKey:(NSString *)key
 - (KTVHCDataUnit *)unitWithKey:(NSString *)key
 {
 {
-    if (key.length <= 0)
-    {
+    if (key.length <= 0) {
         return nil;
         return nil;
     }
     }
-    KTVHCDataUnit * unit = nil;
-    for (KTVHCDataUnit * obj in self.unitArray)
-    {
-        if ([obj.key isEqualToString:key])
-        {
+    KTVHCDataUnit *unit = nil;
+    for (KTVHCDataUnit *obj in self.unitArray) {
+        if ([obj.key isEqualToString:key]) {
             unit = obj;
             unit = obj;
             break;
             break;
         }
         }
@@ -76,24 +65,20 @@
 
 
 - (void)putUnit:(KTVHCDataUnit *)unit
 - (void)putUnit:(KTVHCDataUnit *)unit
 {
 {
-    if (!unit)
-    {
+    if (!unit) {
         return;
         return;
     }
     }
-    if (![self.unitArray containsObject:unit])
-    {
+    if (![self.unitArray containsObject:unit]) {
         [self.unitArray addObject:unit];
         [self.unitArray addObject:unit];
     }
     }
 }
 }
 
 
 - (void)popUnit:(KTVHCDataUnit *)unit
 - (void)popUnit:(KTVHCDataUnit *)unit
 {
 {
-    if (!unit)
-    {
+    if (!unit) {
         return;
         return;
     }
     }
-    if ([self.unitArray containsObject:unit])
-    {
+    if ([self.unitArray containsObject:unit]) {
         [self.unitArray removeObject:unit];
         [self.unitArray removeObject:unit];
     }
     }
 }
 }

+ 10 - 10
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDownload/KTVHCDownload.h

@@ -7,9 +7,9 @@
 //
 //
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
-#import "KTVHCDataRequest.h"
 #import "KTVHCDataResponse.h"
 #import "KTVHCDataResponse.h"
-#import "KTVHCCommon.h"
+#import "KTVHCDataRequest.h"
+#import "KTVHCMacro.h"
 
 
 KTVHTTPCACHE_EXTERN NSString * const KTVHCContentTypeVideo;
 KTVHTTPCACHE_EXTERN NSString * const KTVHCContentTypeVideo;
 KTVHTTPCACHE_EXTERN NSString * const KTVHCContentTypeAudio;
 KTVHTTPCACHE_EXTERN NSString * const KTVHCContentTypeAudio;
@@ -21,9 +21,9 @@ KTVHTTPCACHE_EXTERN NSString * const KTVHCContentTypeBinaryOctetStream;
 
 
 @protocol KTVHCDownloadDelegate <NSObject>
 @protocol KTVHCDownloadDelegate <NSObject>
 
 
-- (void)download:(KTVHCDownload *)download didCompleteWithError:(NSError *)error;
-- (void)download:(KTVHCDownload *)download didReceiveResponse:(KTVHCDataResponse *)response;
-- (void)download:(KTVHCDownload *)download didReceiveData:(NSData *)data;
+- (void)ktv_download:(KTVHCDownload *)download didCompleteWithError:(NSError *)error;
+- (void)ktv_download:(KTVHCDownload *)download didReceiveResponse:(KTVHCDataResponse *)response;
+- (void)ktv_download:(KTVHCDownload *)download didReceiveData:(NSData *)data;
 
 
 @end
 @end
 
 
@@ -34,19 +34,19 @@ KTVHTTPCACHE_EXTERN NSString * const KTVHCContentTypeBinaryOctetStream;
 
 
 + (instancetype)download;
 + (instancetype)download;
 
 
-@property (nonatomic, assign) NSTimeInterval timeoutInterval;
+@property (nonatomic) NSTimeInterval timeoutInterval;
 
 
 /**
 /**
  *  Header Fields
  *  Header Fields
  */
  */
-@property (nonatomic, copy) NSArray <NSString *> * whitelistHeaderKeys;
-@property (nonatomic, copy) NSDictionary <NSString *, NSString *> * additionalHeaders;
+@property (nonatomic, copy) NSArray<NSString *> *whitelistHeaderKeys;
+@property (nonatomic, copy) NSDictionary<NSString *, NSString *> *additionalHeaders;
 
 
 /**
 /**
  *  Content-Type
  *  Content-Type
  */
  */
-@property (nonatomic, copy) NSArray <NSString *> * acceptContentTypes;
-@property (nonatomic, copy) BOOL (^unsupportContentTypeFilter)(NSURL * URL, NSString * contentType);
+@property (nonatomic, copy) NSArray<NSString *> *acceptableContentTypes;
+@property (nonatomic, copy) BOOL (^unacceptableContentTypeDisposer)(NSURL *URL, NSString *contentType);
 
 
 - (NSURLSessionTask *)downloadWithRequest:(KTVHCDataRequest *)request delegate:(id<KTVHCDownloadDelegate>)delegate;
 - (NSURLSessionTask *)downloadWithRequest:(KTVHCDataRequest *)request delegate:(id<KTVHCDownloadDelegate>)delegate;
 
 

+ 118 - 135
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDownload/KTVHCDownload.m

@@ -7,6 +7,7 @@
 //
 //
 
 
 #import "KTVHCDownload.h"
 #import "KTVHCDownload.h"
+#import "KTVHCData+Internal.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataUnitPool.h"
 #import "KTVHCDataStorage.h"
 #import "KTVHCDataStorage.h"
 #import "KTVHCError.h"
 #import "KTVHCError.h"
@@ -22,13 +23,14 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 
 
 @interface KTVHCDownload () <NSURLSessionDataDelegate, NSLocking>
 @interface KTVHCDownload () <NSURLSessionDataDelegate, NSLocking>
 
 
-@property (nonatomic, strong) NSLock * coreLock;
-@property (nonatomic, strong) NSURLSession * session;
-@property (nonatomic, strong) NSOperationQueue * sessionDelegateQueue;
-@property (nonatomic, strong) NSURLSessionConfiguration * sessionConfiguration;
-@property (nonatomic, strong) NSMutableDictionary <NSURLSessionTask *, NSError *> * errorDictionary;
-@property (nonatomic, strong) NSMutableDictionary <NSURLSessionTask *, KTVHCDataRequest *> * requestDictionary;
-@property (nonatomic, strong) NSMutableDictionary <NSURLSessionTask *, id<KTVHCDownloadDelegate>> * delegateDictionary;
+@property (nonatomic, strong) NSLock *coreLock;
+@property (nonatomic, strong) NSURLSession *session;
+@property (nonatomic, strong) NSOperationQueue *sessionDelegateQueue;
+@property (nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
+@property (nonatomic, strong) NSMutableDictionary<NSURLSessionTask *, NSError *> *errorDictionary;
+@property (nonatomic, strong) NSMutableDictionary<NSURLSessionTask *, KTVHCDataRequest *> *requestDictionary;
+@property (nonatomic, strong) NSMutableDictionary<NSURLSessionTask *, id<KTVHCDownloadDelegate>> *delegateDictionary;
+@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
 
 
 @end
 @end
 
 
@@ -36,7 +38,7 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 
 
 + (instancetype)download
 + (instancetype)download
 {
 {
-    static KTVHCDownload * obj = nil;
+    static KTVHCDownload *obj = nil;
     static dispatch_once_t onceToken;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     dispatch_once(&onceToken, ^{
         obj = [[self alloc] init];
         obj = [[self alloc] init];
@@ -46,10 +48,10 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 
 
 - (instancetype)init
 - (instancetype)init
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
         self.timeoutInterval = 30.0f;
         self.timeoutInterval = 30.0f;
+        self.backgroundTask = UIBackgroundTaskInvalid;
         self.errorDictionary = [NSMutableDictionary dictionary];
         self.errorDictionary = [NSMutableDictionary dictionary];
         self.requestDictionary = [NSMutableDictionary dictionary];
         self.requestDictionary = [NSMutableDictionary dictionary];
         self.delegateDictionary = [NSMutableDictionary dictionary];
         self.delegateDictionary = [NSMutableDictionary dictionary];
@@ -61,11 +63,11 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
         self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration
         self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration
                                                      delegate:self
                                                      delegate:self
                                                 delegateQueue:self.sessionDelegateQueue];
                                                 delegateQueue:self.sessionDelegateQueue];
-        self.acceptContentTypes = @[KTVHCContentTypeVideo,
-                                    KTVHCContentTypeAudio,
-                                    KTVHCContentTypeApplicationMPEG4,
-                                    KTVHCContentTypeApplicationOctetStream,
-                                    KTVHCContentTypeBinaryOctetStream];
+        self.acceptableContentTypes = @[KTVHCContentTypeVideo,
+                                        KTVHCContentTypeAudio,
+                                        KTVHCContentTypeApplicationMPEG4,
+                                        KTVHCContentTypeApplicationOctetStream,
+                                        KTVHCContentTypeBinaryOctetStream];
         [[NSNotificationCenter defaultCenter] addObserver:self
         [[NSNotificationCenter defaultCenter] addObserver:self
                                                  selector:@selector(applicationDidEnterBackground:)
                                                  selector:@selector(applicationDidEnterBackground:)
                                                      name:UIApplicationDidEnterBackgroundNotification
                                                      name:UIApplicationDidEnterBackgroundNotification
@@ -81,43 +83,45 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 - (void)dealloc
 - (void)dealloc
 {
 {
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 }
 
 
-- (NSArray <NSString *> *)availableHeaderKeys
+- (NSArray<NSString *> *)availableHeaderKeys
 {
 {
-    static NSArray <NSString *> * availableHeaderKeys = nil;
+    static NSArray<NSString *> *obj = nil;
     static dispatch_once_t onceToken;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     dispatch_once(&onceToken, ^{
-        availableHeaderKeys = @[@"User-Agent",
-                                @"Connection",
-                                @"Accept",
-                                @"Accept-Encoding",
-                                @"Accept-Language",
-                                @"Range"];
+        obj = @[@"User-Agent",
+                @"Connection",
+                @"Accept",
+                @"Accept-Encoding",
+                @"Accept-Language",
+                @"Range"];
     });
     });
-    return availableHeaderKeys;
+    return obj;
 }
 }
 
 
 - (NSURLSessionTask *)downloadWithRequest:(KTVHCDataRequest *)request delegate:(id<KTVHCDownloadDelegate>)delegate
 - (NSURLSessionTask *)downloadWithRequest:(KTVHCDataRequest *)request delegate:(id<KTVHCDownloadDelegate>)delegate
 {
 {
     [self lock];
     [self lock];
-    NSMutableURLRequest * HTTPRequest = [NSMutableURLRequest requestWithURL:request.URL];
-    [request.headers enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSString * obj, BOOL * stop) {
-        if ([[self availableHeaderKeys] containsObject:key] || [self.whitelistHeaderKeys containsObject:key]) {
-            [HTTPRequest setValue:obj forHTTPHeaderField:key];
+    NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:request.URL];
+    mRequest.timeoutInterval = self.timeoutInterval;
+    mRequest.cachePolicy = NSURLRequestReloadIgnoringCacheData;
+    [request.headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
+        if ([self.availableHeaderKeys containsObject:key] ||
+            [self.whitelistHeaderKeys containsObject:key]) {
+            [mRequest setValue:obj forHTTPHeaderField:key];
         }
         }
     }];
     }];
-    HTTPRequest.timeoutInterval = self.timeoutInterval;
-    HTTPRequest.cachePolicy = NSURLRequestReloadIgnoringCacheData;
-    [self.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
-        [HTTPRequest setValue:obj forHTTPHeaderField:key];
+    [self.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
+        [mRequest setValue:obj forHTTPHeaderField:key];
     }];
     }];
-    NSURLSessionDataTask * task = [self.session dataTaskWithRequest:HTTPRequest];
-    task.priority = 1.0;
+    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:mRequest];
     [self.requestDictionary setObject:request forKey:task];
     [self.requestDictionary setObject:request forKey:task];
     [self.delegateDictionary setObject:delegate forKey:task];
     [self.delegateDictionary setObject:delegate forKey:task];
-    KTVHCLogDownload(@"%p, Add Request\nrequest : %@\nURL : %@\nheaders : %@\nHTTPRequest headers : %@\nCount : %d", self, request, request.URL, request.headers, HTTPRequest.allHTTPHeaderFields, (int)self.delegateDictionary.count);
+    task.priority = 1.0;
     [task resume];
     [task resume];
+    KTVHCLogDownload(@"%p, Add Request\nrequest : %@\nURL : %@\nheaders : %@\nHTTPRequest headers : %@\nCount : %d", self, request, request.URL, request.headers, mRequest.allHTTPHeaderFields, (int)self.delegateDictionary.count);
     [self unlock];
     [self unlock];
     return task;
     return task;
 }
 }
@@ -126,92 +130,84 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 {
 {
     [self lock];
     [self lock];
     KTVHCLogDownload(@"%p, Complete\nError : %@", self, error);
     KTVHCLogDownload(@"%p, Complete\nError : %@", self, error);
-    id <KTVHCDownloadDelegate> delegate = [self.delegateDictionary objectForKey:task];
-    NSError * cancelError = [self.errorDictionary objectForKey:task];
-    if (cancelError)
-    {
-        error = cancelError;
+    if ([self.errorDictionary objectForKey:task]) {
+        error = [self.errorDictionary objectForKey:task];
     }
     }
-    [delegate download:self didCompleteWithError:error];
+    id<KTVHCDownloadDelegate> delegate = [self.delegateDictionary objectForKey:task];
+    [delegate ktv_download:self didCompleteWithError:error];
     [self.delegateDictionary removeObjectForKey:task];
     [self.delegateDictionary removeObjectForKey:task];
     [self.requestDictionary removeObjectForKey:task];
     [self.requestDictionary removeObjectForKey:task];
     [self.errorDictionary removeObjectForKey:task];
     [self.errorDictionary removeObjectForKey:task];
-    if (self.delegateDictionary.count <= 0)
-    {
-        [self cleanBackgroundTaskAsync];
+    if (self.delegateDictionary.count <= 0) {
+        [self endBackgroundTaskDelay];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
-- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
+- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
 {
 {
     [self lock];
     [self lock];
-    NSHTTPURLResponse * HTTPResponse = (NSHTTPURLResponse *)response;
-    KTVHCDataRequest * dataRequest = [self.requestDictionary objectForKey:dataTask];
-    KTVHCDataResponse * dataResponse = [[KTVHCDataResponse alloc] initWithURL:dataRequest.URL headers:HTTPResponse.allHeaderFields];
-    KTVHCLogDownload(@"%p, Receive response\nrequest : %@\nresponse : %@\nHTTPResponse : %@", self, dataRequest, dataResponse, [(NSHTTPURLResponse *)response allHeaderFields]);
-    NSError * error = nil;
-    if (!error)
-    {
-        if (HTTPResponse.statusCode > 400)
-        {
-            error = [KTVHCError errorForResponseUnavailable:dataTask.currentRequest.URL request:dataTask.currentRequest response:dataTask.response];
+    KTVHCDataRequest *dataRequest = [self.requestDictionary objectForKey:task];
+    KTVHCDataResponse *dataResponse = [[KTVHCDataResponse alloc] initWithURL:dataRequest.URL headers:response.allHeaderFields];
+    KTVHCLogDownload(@"%p, Receive response\nrequest : %@\nresponse : %@\nHTTPResponse : %@", self, dataRequest, dataResponse, response.allHeaderFields);
+    NSError *error = nil;
+    if (!error) {
+        if (response.statusCode > 400) {
+            error = [KTVHCError errorForResponseUnavailable:task.currentRequest.URL
+                                                    request:task.currentRequest
+                                                   response:task.response];
         }
         }
-        if (!error)
-        {
-            BOOL contentTypeVaild = NO;
-            if (dataResponse.contentType.length > 0)
-            {
-                for (NSString * obj in self.acceptContentTypes)
-                {
-                    if ([[dataResponse.contentType lowercaseString] containsString:[obj lowercaseString]])
-                    {
-                        contentTypeVaild = YES;
-                    }
-                }
-                if (!contentTypeVaild && self.unsupportContentTypeFilter)
-                {
-                    contentTypeVaild = self.unsupportContentTypeFilter(dataRequest.URL, dataResponse.contentType);
+    }
+    if (!error) {
+        BOOL vaild = NO;
+        if (dataResponse.contentType.length > 0) {
+            for (NSString *obj in self.acceptableContentTypes) {
+                if ([[dataResponse.contentType lowercaseString] containsString:[obj lowercaseString]]) {
+                    vaild = YES;
                 }
                 }
             }
             }
-            if (!contentTypeVaild)
-            {
-                error = [KTVHCError errorForUnsupportContentType:dataTask.currentRequest.URL request:dataTask.currentRequest response:dataTask.response];
+            if (!vaild && self.unacceptableContentTypeDisposer) {
+                vaild = self.unacceptableContentTypeDisposer(dataRequest.URL, dataResponse.contentType);
             }
             }
-            if (!error)
-            {
-                if (dataResponse.currentLength <= 0 ||
-                    (!KTVHCRangeIsFull(dataRequest.range) &&
-                     (dataResponse.currentLength != KTVHCRangeGetLength(dataRequest.range))))
-                {
-                    error = [KTVHCError errorForUnsupportContentType:dataTask.currentRequest.URL request:dataTask.currentRequest response:dataTask.response];
-                }
-                if (!error)
-                {
-                    long long length = dataResponse.currentLength + [KTVHCDataStorage storage].totalCacheLength - [KTVHCDataStorage storage].maxCacheLength;
-                    if (length > 0)
-                    {
-                        [[KTVHCDataUnitPool pool] deleteUnitsWithLength:length];
-                        length = dataResponse.currentLength + [KTVHCDataStorage storage].totalCacheLength - [KTVHCDataStorage storage].maxCacheLength;
-                        if (length > 0)
-                        {
-                            error = [KTVHCError errorForNotEnoughDiskSpace:dataResponse.totalLength request:dataResponse.currentLength totalCacheLength:[KTVHCDataStorage storage].totalCacheLength maxCacheLength:[KTVHCDataStorage storage].maxCacheLength];
-                        }
-                    }
-                }
+        }
+        if (!vaild) {
+            error = [KTVHCError errorForUnsupportContentType:task.currentRequest.URL
+                                                     request:task.currentRequest
+                                                    response:task.response];
+        }
+    }
+    if (!error) {
+        if (dataResponse.contentLength <= 0 ||
+            (!KTVHCRangeIsFull(dataRequest.range) &&
+             (dataResponse.contentLength != KTVHCRangeGetLength(dataRequest.range)))) {
+                error = [KTVHCError errorForUnsupportContentType:task.currentRequest.URL
+                                                         request:task.currentRequest
+                                                        response:task.response];
+            }
+    }
+    if (!error) {
+        long long (^getDeletionLength)(long long) = ^(long long desireLength){
+            return desireLength + [KTVHCDataStorage storage].totalCacheLength - [KTVHCDataStorage storage].maxCacheLength;
+        };
+        long long length = getDeletionLength(dataResponse.contentLength);
+        if (length > 0) {
+            [[KTVHCDataUnitPool pool] deleteUnitsWithLength:length];
+            length = getDeletionLength(dataResponse.contentLength);
+            if (length > 0) {
+                error = [KTVHCError errorForNotEnoughDiskSpace:dataResponse.totalLength
+                                                       request:dataResponse.contentLength
+                                              totalCacheLength:[KTVHCDataStorage storage].totalCacheLength
+                                                maxCacheLength:[KTVHCDataStorage storage].maxCacheLength];
             }
             }
         }
         }
     }
     }
-    if (error)
-    {
+    if (error) {
         KTVHCLogDownload(@"%p, Invaild response\nError : %@", self, error);
         KTVHCLogDownload(@"%p, Invaild response\nError : %@", self, error);
-        [self.errorDictionary setObject:error forKey:dataTask];
+        [self.errorDictionary setObject:error forKey:task];
         completionHandler(NSURLSessionResponseCancel);
         completionHandler(NSURLSessionResponseCancel);
-    }
-    else
-    {
-        id <KTVHCDownloadDelegate> delegate = [self.delegateDictionary objectForKey:dataTask];
-        [delegate download:self didReceiveResponse:dataResponse];
+    } else {
+        id<KTVHCDownloadDelegate> delegate = [self.delegateDictionary objectForKey:task];
+        [delegate ktv_download:self didReceiveResponse:dataResponse];
         completionHandler(NSURLSessionResponseAllow);
         completionHandler(NSURLSessionResponseAllow);
     }
     }
     [self unlock];
     [self unlock];
@@ -229,16 +225,15 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 {
 {
     [self lock];
     [self lock];
     KTVHCLogDownload(@"%p, Receive data - Begin\nLength : %lld\nURL : %@", self, (long long)data.length, dataTask.originalRequest.URL.absoluteString);
     KTVHCLogDownload(@"%p, Receive data - Begin\nLength : %lld\nURL : %@", self, (long long)data.length, dataTask.originalRequest.URL.absoluteString);
-    id <KTVHCDownloadDelegate> delegate = [self.delegateDictionary objectForKey:dataTask];
-    [delegate download:self didReceiveData:data];
+    id<KTVHCDownloadDelegate> delegate = [self.delegateDictionary objectForKey:dataTask];
+    [delegate ktv_download:self didReceiveData:data];
     KTVHCLogDownload(@"%p, Receive data - End\nLength : %lld\nURL : %@", self, (long long)data.length, dataTask.originalRequest.URL.absoluteString);
     KTVHCLogDownload(@"%p, Receive data - End\nLength : %lld\nURL : %@", self, (long long)data.length, dataTask.originalRequest.URL.absoluteString);
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (void)lock
 - (void)lock
 {
 {
-    if (!self.coreLock)
-    {
+    if (!self.coreLock) {
         self.coreLock = [[NSLock alloc] init];
         self.coreLock = [[NSLock alloc] init];
     }
     }
     [self.coreLock lock];
     [self.coreLock lock];
@@ -251,53 +246,41 @@ NSString * const KTVHCContentTypeBinaryOctetStream      = @"binary/octet-stream"
 
 
 #pragma mark - Background Task
 #pragma mark - Background Task
 
 
-static UIBackgroundTaskIdentifier backgroundTaskIdentifier = -1;
-
 - (void)applicationDidEnterBackground:(NSNotification *)notification
 - (void)applicationDidEnterBackground:(NSNotification *)notification
 {
 {
-    [self cleanBackgroundTask];
     [self lock];
     [self lock];
-    if (self.delegateDictionary.count > 0)
-    {
-        backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
-            [self cleanBackgroundTask];
-        }];
-        UIBackgroundTaskIdentifier blockIdentifier = backgroundTaskIdentifier;
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(300 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-            if (blockIdentifier == backgroundTaskIdentifier)
-            {
-                [self cleanBackgroundTask];
-            }
-        });
+    if (self.delegateDictionary.count > 0) {
+        [self beginBackgroundTask];
     }
     }
     [self unlock];
     [self unlock];
 }
 }
 
 
 - (void)applicationWillEnterForeground:(NSNotification *)notification
 - (void)applicationWillEnterForeground:(NSNotification *)notification
 {
 {
-    [self cleanBackgroundTask];
+    [self endBackgroundTask];
 }
 }
 
 
-- (void)cleanBackgroundTask
+- (void)beginBackgroundTask
 {
 {
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        backgroundTaskIdentifier = UIBackgroundTaskInvalid;
-    });
-    if (backgroundTaskIdentifier != UIBackgroundTaskInvalid)
-    {
-        [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];
-        backgroundTaskIdentifier = UIBackgroundTaskInvalid;
+    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
+        [self endBackgroundTask];
+    }];
+}
+
+- (void)endBackgroundTask
+{
+    if (self.backgroundTask != UIBackgroundTaskInvalid) {
+        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
+        self.backgroundTask = UIBackgroundTaskInvalid;
     }
     }
 }
 }
 
 
-- (void)cleanBackgroundTaskAsync
+- (void)endBackgroundTaskDelay
 {
 {
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         [self lock];
         [self lock];
-        if (self.delegateDictionary.count <= 0)
-        {
-            [self cleanBackgroundTask];
+        if (self.delegateDictionary.count <= 0) {
+            [self endBackgroundTask];
         }
         }
         [self unlock];
         [self unlock];
     });
     });

+ 0 - 2
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPConnection.h

@@ -11,6 +11,4 @@
 
 
 @interface KTVHCHTTPConnection : HTTPConnection
 @interface KTVHCHTTPConnection : HTTPConnection
 
 
-+ (NSString *)pingResponseValue;
-
 @end
 @end

+ 8 - 30
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPConnection.m

@@ -7,23 +7,16 @@
 //
 //
 
 
 #import "KTVHCHTTPConnection.h"
 #import "KTVHCHTTPConnection.h"
-#import "KTVHCHTTPRequest.h"
 #import "KTVHCHTTPResponse.h"
 #import "KTVHCHTTPResponse.h"
-#import "KTVHCHTTPPingResponse.h"
-#import "KTVHCHTTPURL.h"
+#import "KTVHCDataStorage.h"
+#import "KTVHCURLTool.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @implementation KTVHCHTTPConnection
 @implementation KTVHCHTTPConnection
 
 
-+ (NSString *)pingResponseValue
-{
-    return KTVHCHTTPPingResponseResponseValue;
-}
-
 - (id)initWithAsyncSocket:(GCDAsyncSocket *)newSocket configuration:(HTTPConfig *)aConfig
 - (id)initWithAsyncSocket:(GCDAsyncSocket *)newSocket configuration:(HTTPConfig *)aConfig
 {
 {
-    if (self = [super initWithAsyncSocket:newSocket configuration:aConfig])
-    {
+    if (self = [super initWithAsyncSocket:newSocket configuration:aConfig]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
     }
     }
     return self;
     return self;
@@ -37,26 +30,11 @@
 - (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
 - (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
 {
 {
     KTVHCLogHTTPConnection(@"%p, Receive request\nmethod : %@\npath : %@\nURL : %@", self, method, path, request.url);
     KTVHCLogHTTPConnection(@"%p, Receive request\nmethod : %@\npath : %@\nURL : %@", self, method, path, request.url);
-    KTVHCHTTPURL * URL = [[KTVHCHTTPURL alloc] initWithProxyURL:request.url];
-    switch (URL.type)
-    {
-        case KTVHCHTTPURLTypeUnknown:
-            return nil;
-        case KTVHCHTTPURLTypePing:
-        {
-            KTVHCHTTPPingResponse * currentResponse = [KTVHCHTTPPingResponse responseWithConnection:self];
-            return currentResponse;
-        }
-        case KTVHCHTTPURLTypeContent:
-        {
-            KTVHCHTTPRequest * currentRequest = [[KTVHCHTTPRequest alloc] initWithURL:URL.URL headers:request.allHeaderFields];
-            currentRequest.method = request.method;
-            currentRequest.version = request.version;
-            KTVHCHTTPResponse * currentResponse = [[KTVHCHTTPResponse alloc] initWithConnection:self request:currentRequest];
-            return currentResponse;
-        }
-    }
-    return nil;
+    NSDictionary<NSString *,NSString *> *parameters = [[KTVHCURLTool tool] parseQuery:request.url.query];
+    NSURL *URL = [NSURL URLWithString:[parameters objectForKey:@"url"]];
+    KTVHCDataRequest *dataRequest = [[KTVHCDataRequest alloc] initWithURL:URL headers:request.allHeaderFields];
+    KTVHCHTTPResponse *response = [[KTVHCHTTPResponse alloc] initWithConnection:self dataRequest:dataRequest];
+    return response;
 }
 }
 
 
 
 

+ 2 - 2
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPResponse.h

@@ -10,13 +10,13 @@
 #import "KTVHCHTTPHeader.h"
 #import "KTVHCHTTPHeader.h"
 
 
 @class KTVHCHTTPConnection;
 @class KTVHCHTTPConnection;
-@class KTVHCHTTPRequest;
+@class KTVHCDataRequest;
 
 
 @interface KTVHCHTTPResponse : NSObject <HTTPResponse>
 @interface KTVHCHTTPResponse : NSObject <HTTPResponse>
 
 
 + (instancetype)new NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
 
-- (instancetype)initWithConnection:(KTVHCHTTPConnection *)connection request:(KTVHCHTTPRequest *)request;
+- (instancetype)initWithConnection:(KTVHCHTTPConnection *)connection dataRequest:(KTVHCDataRequest *)dataRequest NS_DESIGNATED_INITIALIZER;
 
 
 @end
 @end

+ 28 - 31
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPResponse.m

@@ -8,34 +8,28 @@
 
 
 #import "KTVHCHTTPResponse.h"
 #import "KTVHCHTTPResponse.h"
 #import "KTVHCHTTPConnection.h"
 #import "KTVHCHTTPConnection.h"
-#import "KTVHCHTTPRequest.h"
 #import "KTVHCDataStorage.h"
 #import "KTVHCDataStorage.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCHTTPResponse () <KTVHCDataReaderDelegate>
 @interface KTVHCHTTPResponse () <KTVHCDataReaderDelegate>
 
 
-@property (nonatomic, weak) KTVHCHTTPConnection * connection;
-@property (nonatomic, strong) KTVHCHTTPRequest * request;
-@property (nonatomic, strong) KTVHCDataRequest * dataRequest;
-@property (nonatomic, strong) KTVHCDataReader * reader;
-@property (nonatomic, assign) BOOL waitingResponseHeader;
+@property (nonatomic) BOOL waitingResponse;
+@property (nonatomic, strong) KTVHCDataReader *reader;
+@property (nonatomic, weak) KTVHCHTTPConnection *connection;
 
 
 @end
 @end
 
 
 @implementation KTVHCHTTPResponse
 @implementation KTVHCHTTPResponse
 
 
-- (instancetype)initWithConnection:(KTVHCHTTPConnection *)connection request:(KTVHCHTTPRequest *)request
+- (instancetype)initWithConnection:(KTVHCHTTPConnection *)connection dataRequest:(KTVHCDataRequest *)dataRequest
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
         self.connection = connection;
         self.connection = connection;
-        self.request = request;
-        KTVHCDataRequest * dataRequest = [[KTVHCDataRequest alloc] initWithURL:self.request.URL headers:self.request.headers];
         self.reader = [[KTVHCDataStorage storage] readerWithRequest:dataRequest];
         self.reader = [[KTVHCDataStorage storage] readerWithRequest:dataRequest];
         self.reader.delegate = self;
         self.reader.delegate = self;
         [self.reader prepare];
         [self.reader prepare];
-        KTVHCLogHTTPResponse(@"%p, Create response\nrequest : %@", self, self.request);
+        KTVHCLogHTTPResponse(@"%p, Create response\nrequest : %@", self, dataRequest);
     }
     }
     return self;
     return self;
 }
 }
@@ -50,10 +44,9 @@
 
 
 - (NSData *)readDataOfLength:(NSUInteger)length
 - (NSData *)readDataOfLength:(NSUInteger)length
 {
 {
-    NSData * data = [self.reader readDataOfLength:length];
+    NSData *data = [self.reader readDataOfLength:length];
     KTVHCLogHTTPResponse(@"%p, Read data : %lld", self, (long long)data.length);
     KTVHCLogHTTPResponse(@"%p, Read data : %lld", self, (long long)data.length);
-    if (self.reader.didFinished)
-    {
+    if (self.reader.isFinished) {
         KTVHCLogHTTPResponse(@"%p, Read data did finished", self);
         KTVHCLogHTTPResponse(@"%p, Read data did finished", self);
         [self.reader close];
         [self.reader close];
         [self.connection responseDidAbort:self];
         [self.connection responseDidAbort:self];
@@ -63,9 +56,9 @@
 
 
 - (BOOL)delayResponseHeaders
 - (BOOL)delayResponseHeaders
 {
 {
-    BOOL waiting = !self.reader.didPrepared;
-    self.waitingResponseHeader = waiting;
-    KTVHCLogHTTPResponse(@"%p, Delay response : %d", self, self.waitingResponseHeader);
+    BOOL waiting = !self.reader.isPrepared;
+    self.waitingResponse = waiting;
+    KTVHCLogHTTPResponse(@"%p, Delay response : %d", self, self.waitingResponse);
     return waiting;
     return waiting;
 }
 }
 
 
@@ -77,52 +70,56 @@
 
 
 - (NSDictionary *)httpHeaders
 - (NSDictionary *)httpHeaders
 {
 {
-    KTVHCLogHTTPResponse(@"%p, Header\n%@", self, self.reader.response.headersWithoutRangeAndLength);
-    return self.reader.response.headersWithoutRangeAndLength;
+    NSMutableDictionary *headers = [self.reader.response.headers mutableCopy];
+    [headers removeObjectForKey:@"Content-Range"];
+    [headers removeObjectForKey:@"content-range"];
+    [headers removeObjectForKey:@"Content-Length"];
+    [headers removeObjectForKey:@"content-length"];
+    KTVHCLogHTTPResponse(@"%p, Header\n%@", self, headers);
+    return headers;
 }
 }
 
 
 - (UInt64)offset
 - (UInt64)offset
 {
 {
-    KTVHCLogHTTPResponse(@"%p, Offset : %lld", self, self.reader.readOffset);
-    return self.reader.readOffset;
+    KTVHCLogHTTPResponse(@"%p, Offset : %lld", self, self.reader.readedLength);
+    return self.reader.readedLength;
 }
 }
 
 
 - (void)setOffset:(UInt64)offset
 - (void)setOffset:(UInt64)offset
 {
 {
-    KTVHCLogHTTPResponse(@"%p, Set offset : %lld, %lld", self, offset, self.reader.readOffset);
+    KTVHCLogHTTPResponse(@"%p, Set offset : %lld, %lld", self, offset, self.reader.readedLength);
 }
 }
 
 
 - (BOOL)isDone
 - (BOOL)isDone
 {
 {
-    KTVHCLogHTTPResponse(@"%p, Check done : %d", self, self.reader.didFinished);
-    return self.reader.didFinished;
+    KTVHCLogHTTPResponse(@"%p, Check done : %d", self, self.reader.isFinished);
+    return self.reader.isFinished;
 }
 }
 
 
 - (void)connectionDidClose
 - (void)connectionDidClose
 {
 {
-    KTVHCLogHTTPResponse(@"%p, Connection did closed : %lld, %lld", self, self.reader.response.currentLength, self.reader.readOffset);
+    KTVHCLogHTTPResponse(@"%p, Connection did closed : %lld, %lld", self, self.reader.response.contentLength, self.reader.readedLength);
     [self.reader close];
     [self.reader close];
 }
 }
 
 
 #pragma mark - KTVHCDataReaderDelegate
 #pragma mark - KTVHCDataReaderDelegate
 
 
-- (void)readerDidPrepared:(KTVHCDataReader *)reader
+- (void)ktv_readerDidPrepare:(KTVHCDataReader *)reader
 {
 {
     KTVHCLogHTTPResponse(@"%p, Prepared", self);
     KTVHCLogHTTPResponse(@"%p, Prepared", self);
-    if (self.reader.didPrepared && self.waitingResponseHeader == YES)
-    {
+    if (self.reader.isPrepared && self.waitingResponse == YES) {
         KTVHCLogHTTPResponse(@"%p, Call connection did prepared", self);
         KTVHCLogHTTPResponse(@"%p, Call connection did prepared", self);
         [self.connection responseHasAvailableData:self];
         [self.connection responseHasAvailableData:self];
     }
     }
 }
 }
 
 
-- (void)readerHasAvailableData:(KTVHCDataReader *)reader
+- (void)ktv_readerHasAvailableData:(KTVHCDataReader *)reader
 {
 {
     KTVHCLogHTTPResponse(@"%p, Has available data", self);
     KTVHCLogHTTPResponse(@"%p, Has available data", self);
     [self.connection responseHasAvailableData:self];
     [self.connection responseHasAvailableData:self];
 }
 }
 
 
-- (void)reader:(KTVHCDataReader *)reader didFailed:(NSError *)error
+- (void)ktv_reader:(KTVHCDataReader *)reader didFailWithError:(NSError *)error
 {
 {
     KTVHCLogHTTPResponse(@"%p, Failed\nError : %@", self, error);
     KTVHCLogHTTPResponse(@"%p, Failed\nError : %@", self, error);
     [self.reader close];
     [self.reader close];

+ 2 - 2
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPServer.h

@@ -15,9 +15,9 @@
 
 
 + (instancetype)server;
 + (instancetype)server;
 
 
-@property (nonatomic, assign, readonly) BOOL running;
+@property (nonatomic, readonly, getter=isRunning) BOOL running;
 
 
-- (void)start:(NSError **)error;
+- (BOOL)start:(NSError **)error;
 - (void)stop;
 - (void)stop;
 
 
 - (NSURL *)URLWithOriginalURL:(NSURL *)URL;
 - (NSURL *)URLWithOriginalURL:(NSURL *)URL;

+ 108 - 100
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPServer.m

@@ -7,20 +7,16 @@
 //
 //
 
 
 #import "KTVHCHTTPServer.h"
 #import "KTVHCHTTPServer.h"
-#import "KTVHCHTTPHeader.h"
 #import "KTVHCHTTPConnection.h"
 #import "KTVHCHTTPConnection.h"
-#import "KTVHCHTTPURL.h"
+#import "KTVHCHTTPHeader.h"
+#import "KTVHCURLTool.h"
 #import "KTVHCLog.h"
 #import "KTVHCLog.h"
 
 
 @interface KTVHCHTTPServer ()
 @interface KTVHCHTTPServer ()
 
 
-@property (nonatomic, strong) HTTPServer * coreHTTPServer;
-
-@property (nonatomic, assign) BOOL pinging;
-@property (nonatomic, assign) BOOL pingResult;
-@property (nonatomic, strong) NSCondition * pingCondition;
-@property (nonatomic, strong) NSURLSession * pingSession;
-@property (nonatomic, strong) NSURLSessionDataTask * pingTask;
+@property (nonatomic, strong) HTTPServer *server;
+@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
+@property (nonatomic) BOOL wantsRunning;
 
 
 @end
 @end
 
 
@@ -28,7 +24,7 @@
 
 
 + (instancetype)server
 + (instancetype)server
 {
 {
-    static KTVHCHTTPServer * obj = nil;
+    static KTVHCHTTPServer *obj = nil;
     static dispatch_once_t onceToken;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     dispatch_once(&onceToken, ^{
         obj = [[self alloc] init];
         obj = [[self alloc] init];
@@ -38,9 +34,21 @@
 
 
 - (instancetype)init
 - (instancetype)init
 {
 {
-    if (self = [super init])
-    {
+    if (self = [super init]) {
         KTVHCLogAlloc(self);
         KTVHCLogAlloc(self);
+        self.backgroundTask = UIBackgroundTaskInvalid;
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(applicationDidEnterBackground)
+                                                     name:UIApplicationDidEnterBackgroundNotification
+                                                   object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(applicationWillEnterForeground)
+                                                     name:UIApplicationWillEnterForegroundNotification
+                                                   object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(HTTPConnectionDidDie)
+                                                     name:HTTPConnectionDidDieNotification
+                                                   object:nil];
     }
     }
     return self;
     return self;
 }
 }
@@ -48,119 +56,119 @@
 - (void)dealloc
 - (void)dealloc
 {
 {
     KTVHCLogDealloc(self);
     KTVHCLogDealloc(self);
-    [self stop];
+    [self stopInternal];
 }
 }
 
 
-- (BOOL)restart
+- (BOOL)isRunning
 {
 {
-    KTVHCLogHTTPServer(@"%p, Restart connection count : %lld", self, (long long)[self.coreHTTPServer numberOfHTTPConnections]);
-    [self.coreHTTPServer stop];
-    NSError * error = nil;
-    [self.coreHTTPServer start:&error];
-    if (error) {
-        KTVHCLogHTTPServer(@"%p, Restart server failed : %@", self, error);
-    } else {
-        KTVHCLogHTTPServer(@"%p, Restart server success", self);
-    }
-    return error == nil;
+    return self.server.isRunning;
 }
 }
 
 
-- (void)start:(NSError * __autoreleasing *)error
+- (BOOL)start:(NSError **)error
 {
 {
-    self.coreHTTPServer = [[HTTPServer alloc] init];
-    [self.coreHTTPServer setConnectionClass:[KTVHCHTTPConnection class]];
-    [self.coreHTTPServer setType:@"_http._tcp."];
-    NSError * tempError = nil;
-    [self.coreHTTPServer start:&tempError];
-    if (tempError) {
-        * error = tempError;
-        KTVHCLogHTTPServer(@"%p, Start server failed : %@", self, tempError);
-    } else {
-        KTVHCLogHTTPServer(@"%p, Start server success", self);
-    }
+    self.wantsRunning = YES;
+    return [self startInternal:error];
 }
 }
 
 
 - (void)stop
 - (void)stop
 {
 {
-    if (self.running)
-    {
-        [self.coreHTTPServer stop];
-        [self.pingSession invalidateAndCancel];
-        [self.pingTask cancel];
-        self.pingTask = nil;
-        self.pingSession = nil;
-        KTVHCLogHTTPServer(@"%p, Stop server", self);
-    }
+    self.wantsRunning = NO;
+    [self stopInternal];
 }
 }
 
 
 - (NSURL *)URLWithOriginalURL:(NSURL *)URL
 - (NSURL *)URLWithOriginalURL:(NSURL *)URL
 {
 {
-    BOOL success = NO;
-    for (int i = 0; i < 2 && !success && self.running && [URL.scheme hasPrefix:@"http"]; i++)
-    {
-        if (i > 0)
-        {
-            [self restart];
-        }
-        success = [self ping];
-        KTVHCLogHTTPServer(@"%p, Ping\nsuccess : %d\nindex : %d", self, success, i);
+    if (!URL || URL.isFileURL || URL.absoluteString.length == 0) {
+        return URL;
     }
     }
-    if (success)
-    {
-        KTVHCHTTPURL * HCURL = [[KTVHCHTTPURL alloc] initWithOriginalURL:URL];
-        URL = [HCURL proxyURLWithPort:self.coreHTTPServer.listeningPort];
+    if (!self.isRunning) {
+        return URL;
     }
     }
+    NSString *original = [[KTVHCURLTool tool] URLEncode:URL.absoluteString];
+    NSString *server = [NSString stringWithFormat:@"http://localhost:%d/", self.server.listeningPort];
+    NSString *extension = URL.pathExtension ? [NSString stringWithFormat:@".%@", URL.pathExtension] : @"";
+    NSString *URLString = [NSString stringWithFormat:@"%@request%@?url=%@", server, extension, original];
+    URL = [NSURL URLWithString:URLString];
     KTVHCLogHTTPServer(@"%p, Return URL\nURL : %@", self, URL);
     KTVHCLogHTTPServer(@"%p, Return URL\nURL : %@", self, URL);
     return URL;
     return URL;
 }
 }
 
 
-- (BOOL)ping
+#pragma mark - Internal
+
+- (BOOL)startInternal:(NSError **)error
 {
 {
-    if (self.running)
-    {
-        if (!self.pingCondition)
-        {
-            self.pingCondition = [[NSCondition alloc] init];
-        }
-        [self.pingCondition lock];
-        if (self.pinging)
-        {
-            [self.pingCondition wait];
-        }
-        else
-        {
-            NSURL * pingURL = [[KTVHCHTTPURL pingURL] proxyURLWithPort:self.coreHTTPServer.listeningPort];
-            if (!self.pingSession)
-            {
-                NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
-                sessionConfiguration.timeoutIntervalForRequest = 3;
-                self.pingSession = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-            }
-            self.pingTask = [self.pingSession dataTaskWithURL:pingURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
-                [self.pingCondition lock];
-                if (!error && data.length > 0) {
-                    NSString * pang = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-                    self.pingResult = [pang isEqualToString:[KTVHCHTTPConnection pingResponseValue]];
-                } else {
-                    self.pingResult = NO;
-                }
-                self.pinging = NO;
-                [self.pingCondition broadcast];
-                [self.pingCondition unlock];
-            }];
-            self.pinging = YES;
-            [self.pingTask resume];
-            [self.pingCondition wait];
-        }
-        [self.pingCondition unlock];
+    self.server = [[HTTPServer alloc] init];
+    [self.server setConnectionClass:[KTVHCHTTPConnection class]];
+    [self.server setType:@"_http._tcp."];
+    [self.server setPort:80];
+    BOOL ret = [self.server start:error];
+    if (ret) {
+        KTVHCLogHTTPServer(@"%p, Start server success", self);
+    } else {
+        KTVHCLogHTTPServer(@"%p, Start server failed", self);
+    }
+    return ret;
+}
+
+- (void)stopInternal
+{
+    [self.server stop];
+    self.server = nil;
+}
+
+#pragma mark - Background Task
+
+- (void)applicationDidEnterBackground
+{
+    if (self.server.numberOfHTTPConnections > 0) {
+        KTVHCLogHTTPServer(@"%p, enter background", self);
+        [self beginBackgroundTask];
+    } else {
+        KTVHCLogHTTPServer(@"%p, enter background and stop server", self);
+        [self stopInternal];
+    }
+}
+
+- (void)applicationWillEnterForeground
+{
+    KTVHCLogHTTPServer(@"%p, enter foreground", self);
+    if (self.backgroundTask == UIBackgroundTaskInvalid && self.wantsRunning) {
+        KTVHCLogHTTPServer(@"%p, restart server", self);
+        [self startInternal:nil];
     }
     }
-    KTVHCLogHTTPServer(@"%p, Ping result : %d", self, self.pingResult);
-    return self.pingResult;
+    [self endBackgroundTask];
 }
 }
 
 
-- (BOOL)running
+- (void)HTTPConnectionDidDie
 {
 {
-    return self.coreHTTPServer.isRunning;
+    KTVHCLogHTTPServer(@"%p, connection did die", self);
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground &&
+            self.server.numberOfHTTPConnections == 0) {
+            KTVHCLogHTTPServer(@"%p, server idle", self);
+            [self endBackgroundTask];
+            [self stopInternal];
+        }
+    });
+}
+
+- (void)beginBackgroundTask
+{
+    KTVHCLogHTTPServer(@"%p, begin background task", self);
+    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
+        KTVHCLogHTTPServer(@"%p, background task expiration", self);
+        [self endBackgroundTask];
+        [self stopInternal];
+    }];
+}
+
+- (void)endBackgroundTask
+{
+    if (self.backgroundTask != UIBackgroundTaskInvalid) {
+        KTVHCLogHTTPServer(@"%p, end background task", self);
+        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
+        self.backgroundTask = UIBackgroundTaskInvalid;
+    }
 }
 }
 
 
 @end
 @end

+ 335 - 8
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/KTVHTTPCache.h

@@ -2,18 +2,28 @@
 //  KTVHTTPCache.h
 //  KTVHTTPCache.h
 //  KTVHTTPCache
 //  KTVHTTPCache
 //
 //
-//  Created by Single on 2017/8/10.
+//  Created by Single on 2017/8/13.
 //  Copyright © 2017年 Single. All rights reserved.
 //  Copyright © 2017年 Single. All rights reserved.
 //
 //
 
 
-#import <UIKit/UIKit.h>
+#import <Foundation/Foundation.h>
 
 
-#pragma mark - Interface
+#if __has_include(<KTVHTTPCache/KTVHTTPCache.h>)
 
 
-#import "KTVHTTPCacheImp.h"
+FOUNDATION_EXPORT double KTVHTTPCacheVersionNumber;
+FOUNDATION_EXPORT const unsigned char KTVHTTPCacheVersionString[];
 
 
-#pragma mark - Data Storage
+#import <KTVHTTPCache/KTVHCRange.h>
+#import <KTVHTTPCache/KTVHCDataReader.h>
+#import <KTVHTTPCache/KTVHCDataLoader.h>
+#import <KTVHTTPCache/KTVHCDataRequest.h>
+#import <KTVHTTPCache/KTVHCDataResponse.h>
+#import <KTVHTTPCache/KTVHCDataCacheItem.h>
+#import <KTVHTTPCache/KTVHCDataCacheItemZone.h>
+
+#else
 
 
+#import "KTVHCRange.h"
 #import "KTVHCDataReader.h"
 #import "KTVHCDataReader.h"
 #import "KTVHCDataLoader.h"
 #import "KTVHCDataLoader.h"
 #import "KTVHCDataRequest.h"
 #import "KTVHCDataRequest.h"
@@ -21,7 +31,324 @@
 #import "KTVHCDataCacheItem.h"
 #import "KTVHCDataCacheItem.h"
 #import "KTVHCDataCacheItemZone.h"
 #import "KTVHCDataCacheItemZone.h"
 
 
-#pragma mark - Common
+#endif
 
 
-#import "KTVHCRange.h"
-#import "KTVHCCommon.h"
+/**
+ *  KTVHTTPCache is a smart media cache framework.
+ */
+@interface KTVHTTPCache : NSObject
+
+/**
+ *  HTTP Server
+ *
+ *  This part is used to access the local HTTP server module.
+ *  The prefix for API is 'proxy'.
+ */
+#pragma mark - HTTP Server
+
+/**
+ *  Start the proxy service.
+ *
+ *  @param error : Pointer to receive service error.
+ *  @return YES when the proxy service is successfully started, otherwise NO.
+ */
++ (BOOL)proxyStart:(NSError **)error;
+
+/**
+ *  Stop the proxy service.
+ */
++ (void)proxyStop;
+
+/**
+ *  Proxy service running status.
+ *
+ *  @return YES when the proxy service is running, otherwise NO.
+ */
++ (BOOL)proxyIsRunning;
+
+/**
+ *  Convert the URL to the proxy URL.
+ *
+ *  @param URL : The URL for HTTP content.
+ *  @return If the param is a file URL or the proxy service isn't running, return URL. Otherwise reutrn the proxy URL.
+ */
++ (NSURL *)proxyURLWithOriginalURL:(NSURL *)URL;
+
+/**
+ *  Data Storage
+ *
+ *  This part is used to access the data storage module.
+ *  The prefix for API is 'cache'.
+ */
+#pragma mark - Data Storage
+
+/**
+ *  Convert the URL to the file URL if the cache is complete.
+ *
+ *  @param URL : The URL for HTTP content.
+ *  @return If the contents of the URL have all been cached, return the complete file URL. Otherwise return nil.
+ */
++ (NSURL *)cacheCompleteFileURLWithURL:(NSURL *)URL;
+
+/**
+ *  Create the data reader for the request.
+ *
+ *  @param request : The request of the expected data.
+ *  @return The data reader for request.
+ */
++ (KTVHCDataReader *)cacheReaderWithRequest:(KTVHCDataRequest *)request;
+
+/**
+ *  Create the data loader for the request.
+ *
+ *  @param request : The request of the expected data.
+ *  @return The data loader for request.
+ */
++ (KTVHCDataLoader *)cacheLoaderWithRequest:(KTVHCDataRequest *)request;
+
+/**
+ *  Set the maximum cache length.
+ *  If the current cache length exceeds the maximum length, it will be deleted starting with the oldest cached data.
+ *
+ *  @param maxCacheLength : The maximum cache length.
+ */
++ (void)cacheSetMaxCacheLength:(long long)maxCacheLength;
+
+/**
+ *  Get the maximum cache length.
+ *
+ *  @return Maximum cache length.
+ */
++ (long long)cacheMaxCacheLength;
+
+/**
+ *  Get the current cached length.
+ *
+ *  @return Current cached length
+ */
++ (long long)cacheTotalCacheLength;
+
+/**
+ *  Create the cache item for the URL.
+ *
+ *  @param URL : The URL for HTTP content.
+ *  @return The cache item for URL.
+ */
++ (KTVHCDataCacheItem *)cacheCacheItemWithURL:(NSURL *)URL;
+
+/**
+ *  Get all cache items.
+ *
+ *  @return All cache items.
+ */
++ (NSArray<KTVHCDataCacheItem *> *)cacheAllCacheItems;
+
+/**
+ *  Delete cache for URL.
+ *
+ *  @param URL : The URL for HTTP content.
+ */
++ (void)cacheDeleteCacheWithURL:(NSURL *)URL;
+
+/**
+ *  Delete all caches.
+ */
++ (void)cacheDeleteAllCaches;
+
+/**
+ *  Encode
+ *
+ *  This part is used to access the encode module.
+ *  The prefix for API is 'encode'.
+ */
+#pragma mark - Encode
+
+/**
+ *  Set URL converter.
+ *  If the URL contains authentication parameters. It can be removed here to ensure that the indeterminate URL can use the same cache.
+ *
+ *  @warning High frequency call. Make it simple.
+ *
+ *  @param URLConverter : The URLConverter.
+ */
++ (void)encodeSetURLConverter:(NSURL * (^)(NSURL *URL))URLConverter;
+
+/**
+ *  Download
+ *
+ *  This part is used to access the download module.
+ *  The prefix for API is 'download'.
+ */
+#pragma mark - Download
+
+/**
+ *  Set the HTTP timeout interval.
+ *
+ *  @param timeoutInterval : The HTTP timeout interval.
+ */
++ (void)downloadSetTimeoutInterval:(NSTimeInterval)timeoutInterval;
+
+/**
+ *  Set HTTP timeout interval.
+ *
+ *  @return The current HTTP timeout interval.
+ */
++ (NSTimeInterval)downloadTimeoutInterval;
+
+/**
+ *  Set the whitelist header keys.
+ *  The following keys are only supported by default:
+ *      User-Agent, Connection, Accept, Accept-Encoding, Accept-Language, Range
+ *  If you want to allow other keys, set them here.
+ *
+ *  @param whitelistHeaderKeys : The keys can be allowed.
+ */
++ (void)downloadSetWhitelistHeaderKeys:(NSArray<NSString *> *)whitelistHeaderKeys;
+
+/**
+ *  Get the current whitelist header keys.
+ */
++ (NSArray<NSString *> *)downloadWhitelistHeaderKeys;
+
+/**
+ *  Set the additional headers.
+ *  If you want to add extra headers, set them here.
+ *
+ *  @param additionalHeaders : The headers will be added.
+ */
++ (void)downloadSetAdditionalHeaders:(NSDictionary<NSString *, NSString *> *)additionalHeaders;
+
+/**
+ *  Get the current additional headers.
+ */
++ (NSDictionary<NSString *, NSString *> *)downloadAdditionalHeaders;
+
+/**
+ *  Set the acceptable content types.
+ *  The following values are only supported by default:
+ *      video/x, audio/x, application/mp4, application/octet-stream, binary/octet-stream
+ *  If you want to allow other content types, set them here.
+ *
+ *  @param acceptableContentTypes : The content types can be allowed.
+ */
++ (void)downloadSetAcceptableContentTypes:(NSArray<NSString *> *)acceptableContentTypes;
+
+/**
+ *  Get the current acceptable content types.
+ */
++ (NSArray<NSString *> *)downloadAcceptableContentTypes;
+
+/**
+ *  Set the unacceptable content type disposer.
+ *  If the receive response's Content-Type not included in acceptContentTypes, this method will be called.
+ *  If the return value of block is YES, you can continue to load resources. Otherwise the HTTP task will be rejected.
+ *
+ *  @param unacceptableContentTypeDisposer : The unacceptable content type disposer.
+ */
++ (void)downloadSetUnacceptableContentTypeDisposer:(BOOL(^)(NSURL *URL, NSString *contentType))unacceptableContentTypeDisposer;
+
+/**
+ *  Log
+ *
+ *  This part is used to access the Log module.
+ *  The prefix for API is 'log'.
+ */
+#pragma mark - Log
+
+/**
+ *  Add an external log.
+ *
+ *  @param log : An external log.
+ */
++ (void)logAddLog:(NSString *)log;
+
+/**
+ *  Set whether to enable the console log.
+ *  Default is NO.
+ *
+ *  @param consoleLogEnable : The value to enable the console log.
+ */
++ (void)logSetConsoleLogEnable:(BOOL)consoleLogEnable;
+
+/**
+ *  Get the value that enables the console log.
+ *
+ *  @return The value that enables the console log.
+ */
++ (BOOL)logConsoleLogEnable;
+
+/**
+ *  Set whether to enable the record log.
+ *  Default is NO.
+ *
+ *  @param recordLogEnable : The value to enable the record log.
+ */
++ (void)logSetRecordLogEnable:(BOOL)recordLogEnable;
+
+/**
+ *  Get the value that enables the record log.
+ *
+ *  @return The value that enables the record log.
+ */
++ (BOOL)logRecordLogEnable;
+
+/**
+ *  Get the path to the log file.
+ *
+ *  @return The path to the log file.
+ */
++ (NSURL *)logRecordLogFileURL;
+
+/**
+ *  Delete the log file.
+ */
++ (void)logDeleteRecordLogFile;
+
+/**
+ *  Get all errors
+ *
+ *  @return All errors.
+ */
++ (NSDictionary<NSURL *, NSError *> *)logErrors;
+
+/**
+ *  Get the error for the URL.
+ *
+ *  @param URL : The URL for HTTP content.
+ *  @return The error for the URL.
+ */
++ (NSError *)logErrorForURL:(NSURL *)URL;
+
+/**
+ *  Delete the error for the URL.
+ *
+ *  @param URL : The URL for HTTP content.
+ */
++ (void)logCleanErrorForURL:(NSURL *)URL;
+
+@end
+
+/**
+ *  Deprecated
+ *
+ *  This part is for compatibility with historical versions.
+ *
+ *  @warning This part will be removed in future versions.
+ */
+#pragma mark - Deprecated
+
+@interface KTVHTTPCache (Deprecated)
+
++ (void)logDeleteRecordLog                                                      __attribute__((deprecated("Use +logDeleteRecordLogFile instead.")));
++ (NSString *)logRecordLogFilePath                                              __attribute__((deprecated("Use +logRecordLogFileURL instead.")));
++ (NSString *)proxyURLStringWithOriginalURLString:(NSString *)URLString         __attribute__((deprecated("Use +proxyURLWithOriginalURL: instead.")));
++ (NSURL *)cacheCompleteFileURLIfExistedWithURL:(NSURL *)URL                    __attribute__((deprecated("Use +cacheCompleteFileURLWithURL: instead.")));
++ (NSString *)cacheCompleteFilePathIfExistedWithURLString:(NSString *)URLString __attribute__((deprecated("Use +cacheCompleteFileURLWithURL: instead.")));
++ (KTVHCDataCacheItem *)cacheCacheItemWithURLString:(NSString *)URLString       __attribute__((deprecated("Use +cacheCacheItemWithURL: instead.")));
++ (void)cacheDeleteCacheWithURLString:(NSString *)URLString                     __attribute__((deprecated("Use +cacheDeleteCacheWithURL: instead.")));
++ (void)tokenSetURLFilter:(NSURL * (^)(NSURL * URL))URLFilter                   __attribute__((deprecated("Use +encodeSetURLConverter: instead.")));
++ (void)downloadSetAcceptContentTypes:(NSArray<NSString *> *)acceptContentTypes __attribute__((deprecated("Use +downloadSetAcceptableContentTypes: instead.")));
++ (NSArray<NSString *> *)downloadAcceptContentTypes                             __attribute__((deprecated("Use +downloadAcceptableContentTypes instead.")));
++ (void)downloadSetUnsupportContentTypeFilter:(BOOL(^)(NSURL *URL, NSString *contentType))contentTypeFilter __attribute__((deprecated("Use +downloadSetUnacceptableContentTypeDisposer: instead.")));
+
+@end

+ 1 - 1
Carthage/Checkouts/KTVHTTPCache/LICENSE

@@ -1,6 +1,6 @@
 MIT License
 MIT License
 
 
-Copyright (c) 2017 唱吧
+Copyright (c) 2017 Single
 
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 of this software and associated documentation files (the "Software"), to deal

+ 2 - 2
Carthage/Checkouts/PDFGenerator/PDFGenerator.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name             = "PDFGenerator"
   s.name             = "PDFGenerator"
-  s.version          = "2.1.1"
+  s.version          = "2.1"
   s.summary          = "A simple PDF generator."
   s.summary          = "A simple PDF generator."
   s.homepage         = "https://github.com/sgr-ksmt/PDFGenerator"
   s.homepage         = "https://github.com/sgr-ksmt/PDFGenerator"
   # s.screenshots     = ""
   # s.screenshots     = ""
@@ -9,6 +9,6 @@ Pod::Spec.new do |s|
   s.source           = { :git => "https://github.com/sgr-ksmt/PDFGenerator.git", :tag => s.version.to_s }
   s.source           = { :git => "https://github.com/sgr-ksmt/PDFGenerator.git", :tag => s.version.to_s }
   s.platform         = :ios, '8.0'
   s.platform         = :ios, '8.0'
   s.requires_arc     = true
   s.requires_arc     = true
-  s.source_files     = "PDFGenerator/**/*.swift"
+  s.source_files     = "PDFGenerator/**/*"
   s.frameworks   = 'WebKit'
   s.frameworks   = 'WebKit'
 end
 end

+ 1 - 1
Carthage/Checkouts/SVGKit/Source/DOM classes/Core DOM/DOMGlobalSettings.h

@@ -1 +1 @@
-#define DEBUG_DOM_PARSING 0
+#define DEBUG_DOM_PARSING 0

+ 1 - 1
Carthage/Checkouts/SVGKit/Source/DOM classes/SVG-DOM/SVGNumber.h

@@ -9,4 +9,4 @@
 typedef struct
 typedef struct
 {
 {
 	float value;
 	float value;
-} SVGNumber;
+} SVGNumber;

+ 1 - 1
Carthage/Checkouts/SVGKit/Source/DOM classes/Unported or Partial DOM/SVGElement.h

@@ -61,4 +61,4 @@
 -(NSString*) cascadedValueForStylableProperty:(NSString*) stylableProperty;
 -(NSString*) cascadedValueForStylableProperty:(NSString*) stylableProperty;
 -(NSString*) cascadedValueForStylableProperty:(NSString*) stylableProperty inherit:(BOOL)inherit;
 -(NSString*) cascadedValueForStylableProperty:(NSString*) stylableProperty inherit:(BOOL)inherit;
 
 
-@end
+@end

+ 1 - 1
Carthage/Checkouts/SVGKit/Source/Foundation additions/NSData+NSInputStream.h

@@ -17,4 +17,4 @@
  */
  */
 +(NSData*)dataWithContentsOfStream:(NSInputStream*)input initialCapacity:(NSUInteger)capacity error:(NSError **)error;
 +(NSData*)dataWithContentsOfStream:(NSInputStream*)input initialCapacity:(NSUInteger)capacity error:(NSError **)error;
 
 
-@end
+@end

+ 1 - 1
Carthage/Checkouts/SVGKit/Source/Foundation additions/NSData+NSInputStream.m

@@ -57,4 +57,4 @@
 }
 }
 
 
 
 
-@end
+@end

+ 6 - 1
Carthage/Checkouts/SVGKit/Source/UIKit additions/SVGKFastImageView.m

@@ -39,7 +39,12 @@
 	self = [super initWithFrame:frame];
 	self = [super initWithFrame:frame];
 	if( self )
 	if( self )
 	{
 	{
-        [self populateFromImage:nil];
+#if SVGKIT_UIKIT
+		self.backgroundColor = [UIColor clearColor];
+#else
+        self.layer.backgroundColor = [NSColor clearColor].CGColor;
+#endif
+        
 	}
 	}
 	return self;
 	return self;
 }
 }

+ 5 - 1
Carthage/Checkouts/SVGKit/Source/UIKit additions/SVGKLayeredImageView.m

@@ -46,7 +46,11 @@
 	self = [super initWithFrame:frame];
 	self = [super initWithFrame:frame];
 	if( self )
 	if( self )
 	{
 	{
-        [self populateFromImage:nil];
+#if SVGKIT_UIKIT
+		self.backgroundColor = [UIColor clearColor];
+#else
+        self.layer.backgroundColor = [NSColor clearColor].CGColor;
+#endif
 	}
 	}
 	return self;
 	return self;
 }
 }

+ 1 - 1
Carthage/Checkouts/TLPhotoPicker/.swift-version

@@ -1 +1 @@
-4.2
+5.0

+ 3 - 3
Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker.podspec

@@ -8,7 +8,7 @@
 
 
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name             = 'TLPhotoPicker'
   s.name             = 'TLPhotoPicker'
-  s.version          = '1.8.3'
+  s.version          = '1.8.5'
   s.summary          = 'multiple phassets picker for iOS lib. like facebook'
   s.summary          = 'multiple phassets picker for iOS lib. like facebook'
 
 
 # This description is used to generate tags and improve search results.
 # This description is used to generate tags and improve search results.
@@ -29,8 +29,8 @@ TODO: Add long description of the pod here.
   # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
   # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
 
 
   s.ios.deployment_target = '9.1'
   s.ios.deployment_target = '9.1'
-  s.swift_version = '4.2'
-  s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' }
+  s.swift_version = '5.0'
+  s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5.0' }
 
 
   s.source_files = 'TLPhotoPicker/Classes/**/*'
   s.source_files = 'TLPhotoPicker/Classes/**/*'
   
   

+ 5 - 2
Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker/Classes/TLAssetsCollection.swift

@@ -26,6 +26,8 @@ public struct TLPHAsset {
     
     
     var state = CloudDownloadState.ready
     var state = CloudDownloadState.ready
     public var phAsset: PHAsset? = nil
     public var phAsset: PHAsset? = nil
+    //Bool to check if TLPHAsset returned is created using camera.
+    public var isSelectedFromCamera = false
     public var selectedOrder: Int = 0
     public var selectedOrder: Int = 0
     public var type: AssetType {
     public var type: AssetType {
         get {
         get {
@@ -137,7 +139,7 @@ public struct TLPHAsset {
     }
     }
     
     
     @discardableResult
     @discardableResult
-    //convertLivePhotosToPNG
+    //convertLivePhotosToJPG
     // false : If you want mov file at live photos
     // false : If you want mov file at live photos
     // true  : If you want png file at live photos ( HEIC )
     // true  : If you want png file at live photos ( HEIC )
     public func tempCopyMediaFile(videoRequestOptions: PHVideoRequestOptions? = nil, imageRequestOptions: PHImageRequestOptions? = nil, exportPreset: String = AVAssetExportPresetHighestQuality, convertLivePhotosToJPG: Bool = false, progressBlock:((Double) -> Void)? = nil, completionBlock:@escaping ((URL,String) -> Void)) -> PHImageRequestID? {
     public func tempCopyMediaFile(videoRequestOptions: PHVideoRequestOptions? = nil, imageRequestOptions: PHImageRequestOptions? = nil, exportPreset: String = AVAssetExportPresetHighestQuality, convertLivePhotosToJPG: Bool = false, progressBlock:((Double) -> Void)? = nil, completionBlock:@escaping ((URL,String) -> Void)) -> PHImageRequestID? {
@@ -202,7 +204,8 @@ public struct TLPHAsset {
             return PHImageManager.default().requestImageData(for: phAsset, options: requestOptions, resultHandler: { (data, uti, orientation, info) in
             return PHImageManager.default().requestImageData(for: phAsset, options: requestOptions, resultHandler: { (data, uti, orientation, info) in
                 do {
                 do {
                     var data = data
                     var data = data
-                    if convertLivePhotosToJPG == true, let imgData = data, let rawImage = UIImage(data: imgData)?.upOrientationImage() {
+                    let needConvertLivePhotoToJPG = phAsset.mediaSubtypes.contains(.photoLive) == true && convertLivePhotosToJPG == true
+                    if needConvertLivePhotoToJPG, let imgData = data, let rawImage = UIImage(data: imgData)?.upOrientationImage() {
                         data = rawImage.jpegData(compressionQuality: 1)
                         data = rawImage.jpegData(compressionQuality: 1)
                     }
                     }
                     try data?.write(to: localURL)
                     try data?.write(to: localURL)

+ 10 - 10
Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker/Classes/TLPhotoLibrary.swift

@@ -34,13 +34,13 @@ class TLPhotoLibrary {
         options.progressHandler = progressBlock
         options.progressHandler = progressBlock
         let scale = min(UIScreen.main.scale,2)
         let scale = min(UIScreen.main.scale,2)
         let targetSize = CGSize(width: size.width*scale, height: size.height*scale)
         let targetSize = CGSize(width: size.width*scale, height: size.height*scale)
-        let requestId = self.imageManager.requestLivePhoto(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { (livePhoto, info) in
+        let requestID = self.imageManager.requestLivePhoto(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { (livePhoto, info) in
             let complete = (info?["PHImageResultIsDegradedKey"] as? Bool) == false
             let complete = (info?["PHImageResultIsDegradedKey"] as? Bool) == false
             if let livePhoto = livePhoto {
             if let livePhoto = livePhoto {
                 completionBlock(livePhoto,complete)
                 completionBlock(livePhoto,complete)
             }
             }
         }
         }
-        return requestId
+        return requestID
     }
     }
     
     
     @discardableResult
     @discardableResult
@@ -49,10 +49,10 @@ class TLPhotoLibrary {
         options.isNetworkAccessAllowed = true
         options.isNetworkAccessAllowed = true
         options.deliveryMode = .automatic
         options.deliveryMode = .automatic
         options.progressHandler = progressBlock
         options.progressHandler = progressBlock
-        let requestId = self.imageManager.requestPlayerItem(forVideo: asset, options: options, resultHandler: { playerItem, info in
+        let requestID = self.imageManager.requestPlayerItem(forVideo: asset, options: options, resultHandler: { playerItem, info in
             completionBlock(playerItem,info)
             completionBlock(playerItem,info)
         })
         })
-        return requestId
+        return requestID
     }
     }
     
     
     @discardableResult
     @discardableResult
@@ -67,17 +67,17 @@ class TLPhotoLibrary {
         }
         }
         let scale = min(UIScreen.main.scale,2)
         let scale = min(UIScreen.main.scale,2)
         let targetSize = CGSize(width: size.width*scale, height: size.height*scale)
         let targetSize = CGSize(width: size.width*scale, height: size.height*scale)
-        let requestId = self.imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { image, info in
+        let requestID = self.imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { image, info in
             let complete = (info?["PHImageResultIsDegradedKey"] as? Bool) == false
             let complete = (info?["PHImageResultIsDegradedKey"] as? Bool) == false
             if let image = image {
             if let image = image {
                 completionBlock(image,complete)
                 completionBlock(image,complete)
             }
             }
         }
         }
-        return requestId
+        return requestID
     }
     }
     
     
-    func cancelPHImageRequest(requestId: PHImageRequestID) {
-        self.imageManager.cancelImageRequest(requestId)
+    func cancelPHImageRequest(requestID: PHImageRequestID) {
+        self.imageManager.cancelImageRequest(requestID)
     }
     }
     
     
     @discardableResult
     @discardableResult
@@ -91,14 +91,14 @@ class TLPhotoLibrary {
         options.progressHandler = { (progress,error,stop,info) in
         options.progressHandler = { (progress,error,stop,info) in
             progressBlock(progress)
             progressBlock(progress)
         }
         }
-        let requestId = PHCachingImageManager().requestImageData(for: asset, options: options) { (imageData, dataUTI, orientation, info) in
+        let requestID = PHCachingImageManager().requestImageData(for: asset, options: options) { (imageData, dataUTI, orientation, info) in
             if let data = imageData,let _ = info {
             if let data = imageData,let _ = info {
                 completionBlock(UIImage(data: data))
                 completionBlock(UIImage(data: data))
             }else{
             }else{
                 completionBlock(nil)//error
                 completionBlock(nil)//error
             }
             }
         }
         }
-        return requestId
+        return requestID
     }
     }
     
     
     @discardableResult
     @discardableResult

+ 44 - 38
Carthage/Checkouts/TLPhotoPicker/TLPhotoPicker/Classes/TLPhotosPickerViewController.swift

@@ -157,8 +157,8 @@ open class TLPhotosPickerViewController: UIViewController {
     
     
     private var collections = [TLAssetsCollection]()
     private var collections = [TLAssetsCollection]()
     private var focusedCollection: TLAssetsCollection? = nil
     private var focusedCollection: TLAssetsCollection? = nil
-    private var requestIds = [IndexPath:PHImageRequestID]()
-    private var playRequestId: (indexPath: IndexPath, requestId: PHImageRequestID)? = nil
+    private var requestIDs = SynchronizedDictionary<IndexPath,PHImageRequestID>()
+    private var playRequestID: (indexPath: IndexPath, requestID: PHImageRequestID)? = nil
     private var photoLibrary = TLPhotoLibrary()
     private var photoLibrary = TLPhotoLibrary()
     private var queue = DispatchQueue(label: "tilltue.photos.pikcker.queue")
     private var queue = DispatchQueue(label: "tilltue.photos.pikcker.queue")
     private var queueForGroupedBy = DispatchQueue(label: "tilltue.photos.pikcker.queue.for.groupedBy", qos: .utility)
     private var queueForGroupedBy = DispatchQueue(label: "tilltue.photos.pikcker.queue.for.groupedBy", qos: .utility)
@@ -216,6 +216,8 @@ open class TLPhotosPickerViewController: UIViewController {
         case .restricted: fallthrough
         case .restricted: fallthrough
         case .denied:
         case .denied:
             handleDeniedAlbumsAuthorization()
             handleDeniedAlbumsAuthorization()
+        @unknown default:
+            break
         }
         }
     }
     }
     
     
@@ -276,7 +278,7 @@ extension TLPhotosPickerViewController {
     }
     }
     
     
     private func initItemSize() {
     private func initItemSize() {
-        guard var layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
+        guard let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
             return
             return
         }
         }
         let count = CGFloat(self.configure.numberOfColumn)
         let count = CGFloat(self.configure.numberOfColumn)
@@ -372,7 +374,7 @@ extension TLPhotosPickerViewController {
     }
     }
     
     
     private func getfocusedIndex() -> Int {
     private func getfocusedIndex() -> Int {
-        guard let focused = self.focusedCollection, let result = self.collections.index(where: { $0 == focused }) else { return 0 }
+        guard let focused = self.focusedCollection, let result = self.collections.firstIndex(where: { $0 == focused }) else { return 0 }
         return result
         return result
     }
     }
     
     
@@ -401,10 +403,10 @@ extension TLPhotosPickerViewController {
     }
     }
     
     
     private func cancelAllImageAssets() {
     private func cancelAllImageAssets() {
-        for (_,requestId) in self.requestIds {
-            self.photoLibrary.cancelPHImageRequest(requestId: requestId)
+        self.requestIDs.forEach{ (indexPath, requestID) in
+            self.photoLibrary.cancelPHImageRequest(requestID: requestID)
         }
         }
-        self.requestIds.removeAll()
+        self.requestIDs.removeAll()
     }
     }
     
     
     // User Action
     // User Action
@@ -506,6 +508,8 @@ extension TLPhotosPickerViewController: UIImagePickerControllerDelegate, UINavig
             })
             })
         case .restricted, .denied:
         case .restricted, .denied:
             self.handleDeniedCameraAuthorization()
             self.handleDeniedCameraAuthorization()
+        @unknown default:
+            break
         }
         }
     }
     }
 
 
@@ -551,6 +555,7 @@ extension TLPhotosPickerViewController: UIImagePickerControllerDelegate, UINavig
                     guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil).firstObject else { return }
                     guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil).firstObject else { return }
                     var result = TLPHAsset(asset: asset)
                     var result = TLPHAsset(asset: asset)
                     result.selectedOrder = self.selectedAssets.count + 1
                     result.selectedOrder = self.selectedAssets.count + 1
+                    result.isSelectedFromCamera = true
                     self.selectedAssets.append(result)
                     self.selectedAssets.append(result)
                     self.logDelegate?.selectedPhoto(picker: self, at: 1)
                     self.logDelegate?.selectedPhoto(picker: self, at: 1)
                 }
                 }
@@ -566,6 +571,7 @@ extension TLPhotosPickerViewController: UIImagePickerControllerDelegate, UINavig
                     guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil).firstObject else { return }
                     guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil).firstObject else { return }
                     var result = TLPHAsset(asset: asset)
                     var result = TLPHAsset(asset: asset)
                     result.selectedOrder = self.selectedAssets.count + 1
                     result.selectedOrder = self.selectedAssets.count + 1
+                    result.isSelectedFromCamera = true
                     self.selectedAssets.append(result)
                     self.selectedAssets.append(result)
                     self.logDelegate?.selectedPhoto(picker: self, at: 1)
                     self.logDelegate?.selectedPhoto(picker: self, at: 1)
                 }
                 }
@@ -590,12 +596,12 @@ extension TLPhotosPickerViewController {
     
     
     private func videoCheck() {
     private func videoCheck() {
         func play(asset: (IndexPath,TLPHAsset)) {
         func play(asset: (IndexPath,TLPHAsset)) {
-            if self.playRequestId?.indexPath != asset.0 {
+            if self.playRequestID?.indexPath != asset.0 {
                 playVideo(asset: asset.1, indexPath: asset.0)
                 playVideo(asset: asset.1, indexPath: asset.0)
             }
             }
         }
         }
         guard self.configure.autoPlay else { return }
         guard self.configure.autoPlay else { return }
-        guard self.playRequestId == nil else { return }
+        guard self.playRequestID == nil else { return }
         let visibleIndexPaths = self.collectionView.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row })
         let visibleIndexPaths = self.collectionView.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row })
         #if swift(>=4.1)
         #if swift(>=4.1)
         let boundAssets = visibleIndexPaths.compactMap{ indexPath -> (IndexPath,TLPHAsset)? in
         let boundAssets = visibleIndexPaths.compactMap{ indexPath -> (IndexPath,TLPHAsset)? in
@@ -619,8 +625,8 @@ extension TLPhotosPickerViewController {
 // MARK: - Video & LivePhotos Control PHLivePhotoViewDelegate
 // MARK: - Video & LivePhotos Control PHLivePhotoViewDelegate
 extension TLPhotosPickerViewController: PHLivePhotoViewDelegate {
 extension TLPhotosPickerViewController: PHLivePhotoViewDelegate {
     private func stopPlay() {
     private func stopPlay() {
-        guard let playRequest = self.playRequestId else { return }
-        self.playRequestId = nil
+        guard let playRequest = self.playRequestID else { return }
+        self.playRequestID = nil
         guard let cell = self.collectionView.cellForItem(at: playRequest.indexPath) as? TLPhotoCollectionViewCell else { return }
         guard let cell = self.collectionView.cellForItem(at: playRequest.indexPath) as? TLPhotoCollectionViewCell else { return }
         cell.stopPlay()
         cell.stopPlay()
     }
     }
@@ -630,7 +636,7 @@ extension TLPhotosPickerViewController: PHLivePhotoViewDelegate {
         guard let phAsset = asset.phAsset else { return }
         guard let phAsset = asset.phAsset else { return }
         if asset.type == .video {
         if asset.type == .video {
             guard let cell = self.collectionView.cellForItem(at: indexPath) as? TLPhotoCollectionViewCell else { return }
             guard let cell = self.collectionView.cellForItem(at: indexPath) as? TLPhotoCollectionViewCell else { return }
-            let requestId = self.photoLibrary.videoAsset(asset: phAsset, completionBlock: { (playerItem, info) in
+            let requestID = self.photoLibrary.videoAsset(asset: phAsset, completionBlock: { (playerItem, info) in
                 DispatchQueue.main.sync { [weak self, weak cell] in
                 DispatchQueue.main.sync { [weak self, weak cell] in
                     guard let `self` = self, let cell = cell, cell.player == nil else { return }
                     guard let `self` = self, let cell = cell, cell.player == nil else { return }
                     let player = AVPlayer(playerItem: playerItem)
                     let player = AVPlayer(playerItem: playerItem)
@@ -639,19 +645,19 @@ extension TLPhotosPickerViewController: PHLivePhotoViewDelegate {
                     player.isMuted = self.configure.muteAudio
                     player.isMuted = self.configure.muteAudio
                 }
                 }
             })
             })
-            if requestId > 0 {
-                self.playRequestId = (indexPath,requestId)
+            if requestID > 0 {
+                self.playRequestID = (indexPath,requestID)
             }
             }
         }else if asset.type == .livePhoto && self.allowedLivePhotos {
         }else if asset.type == .livePhoto && self.allowedLivePhotos {
             guard let cell = self.collectionView.cellForItem(at: indexPath) as? TLPhotoCollectionViewCell else { return }
             guard let cell = self.collectionView.cellForItem(at: indexPath) as? TLPhotoCollectionViewCell else { return }
-            let requestId = self.photoLibrary.livePhotoAsset(asset: phAsset, size: self.thumbnailSize, completionBlock: { [weak cell] (livePhoto,complete) in
+            let requestID = self.photoLibrary.livePhotoAsset(asset: phAsset, size: self.thumbnailSize, completionBlock: { [weak cell] (livePhoto,complete) in
                 cell?.livePhotoView?.isHidden = false
                 cell?.livePhotoView?.isHidden = false
                 cell?.livePhotoView?.livePhoto = livePhoto
                 cell?.livePhotoView?.livePhoto = livePhoto
                 cell?.livePhotoView?.isMuted = true
                 cell?.livePhotoView?.isMuted = true
                 cell?.livePhotoView?.startPlayback(with: .hint)
                 cell?.livePhotoView?.startPlayback(with: .hint)
             })
             })
-            if requestId > 0 {
-                self.playRequestId = (indexPath,requestId)
+            if requestID > 0 {
+                self.playRequestID = (indexPath,requestID)
             }
             }
         }
         }
     }
     }
@@ -742,7 +748,7 @@ extension TLPhotosPickerViewController: PHPhotoLibraryChangeObserver {
 // MARK: - UICollectionView delegate & datasource
 // MARK: - UICollectionView delegate & datasource
 extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDataSourcePrefetching {
 extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDataSourcePrefetching {
     private func getSelectedAssets(_ asset: TLPHAsset) -> TLPHAsset? {
     private func getSelectedAssets(_ asset: TLPHAsset) -> TLPHAsset? {
-        if let index = self.selectedAssets.index(where: { $0.phAsset == asset.phAsset }) {
+        if let index = self.selectedAssets.firstIndex(where: { $0.phAsset == asset.phAsset }) {
             return self.selectedAssets[index]
             return self.selectedAssets[index]
         }
         }
         return nil
         return nil
@@ -782,7 +788,7 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
         }
         }
         guard var asset = collection.getTLAsset(at: indexPath), let phAsset = asset.phAsset else { return }
         guard var asset = collection.getTLAsset(at: indexPath), let phAsset = asset.phAsset else { return }
         cell.popScaleAnim()
         cell.popScaleAnim()
-        if let index = self.selectedAssets.index(where: { $0.phAsset == asset.phAsset }) {
+        if let index = self.selectedAssets.firstIndex(where: { $0.phAsset == asset.phAsset }) {
         //deselect
         //deselect
             self.logDelegate?.deselectedPhoto(picker: self, at: indexPath.row)
             self.logDelegate?.deselectedPhoto(picker: self, at: indexPath.row)
             self.selectedAssets.remove(at: index)
             self.selectedAssets.remove(at: index)
@@ -802,7 +808,7 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
             cell.selectedAsset = false
             cell.selectedAsset = false
             cell.stopPlay()
             cell.stopPlay()
             self.orderUpdateCells()
             self.orderUpdateCells()
-            if self.playRequestId?.indexPath == indexPath {
+            if self.playRequestID?.indexPath == indexPath {
                 stopPlay()
                 stopPlay()
             }
             }
         }else {
         }else {
@@ -824,13 +830,13 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
         if let cell = cell as? TLPhotoCollectionViewCell {
         if let cell = cell as? TLPhotoCollectionViewCell {
             cell.endDisplayingCell()
             cell.endDisplayingCell()
             cell.stopPlay()
             cell.stopPlay()
-            if indexPath == self.playRequestId?.indexPath {
-                self.playRequestId = nil
+            if indexPath == self.playRequestID?.indexPath {
+                self.playRequestID = nil
             }
             }
         }
         }
-        guard let requestId = self.requestIds[indexPath] else { return }
-        self.requestIds.removeValue(forKey: indexPath)
-        self.photoLibrary.cancelPHImageRequest(requestId: requestId)
+        guard let requestID = self.requestIDs[indexPath] else { return }
+        self.requestIDs.removeValue(forKey: indexPath)
+        self.photoLibrary.cancelPHImageRequest(requestID: requestID)
     }
     }
     
     
     //Datasource
     //Datasource
@@ -873,10 +879,10 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
                 options.deliveryMode = .opportunistic
                 options.deliveryMode = .opportunistic
                 options.resizeMode = .exact
                 options.resizeMode = .exact
                 options.isNetworkAccessAllowed = true
                 options.isNetworkAccessAllowed = true
-                let requestId = self.photoLibrary.imageAsset(asset: phAsset, size: self.thumbnailSize, options: options) { [weak self, weak cell] (image,complete) in
+                let requestID = self.photoLibrary.imageAsset(asset: phAsset, size: self.thumbnailSize, options: options) { [weak self, weak cell] (image,complete) in
                     guard let `self` = self else { return }
                     guard let `self` = self else { return }
                     DispatchQueue.main.async {
                     DispatchQueue.main.async {
-                        if self.requestIds[indexPath] != nil {
+                        if self.requestIDs[indexPath] != nil {
                             cell?.imageView?.image = image
                             cell?.imageView?.image = image
                             cell?.update(with: phAsset)
                             cell?.update(with: phAsset)
                             if self.allowedVideo {
                             if self.allowedVideo {
@@ -884,20 +890,20 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
                                 cell?.duration = asset.type == .video ? phAsset.duration : nil
                                 cell?.duration = asset.type == .video ? phAsset.duration : nil
                             }
                             }
                             if complete {
                             if complete {
-                                self.requestIds.removeValue(forKey: indexPath)
+                                self.requestIDs.removeValue(forKey: indexPath)
                             }
                             }
                         }
                         }
                     }
                     }
                 }
                 }
-                if requestId > 0 {
-                    self.requestIds[indexPath] = requestId
+                if requestID > 0 {
+                    self.requestIDs[indexPath] = requestID
                 }
                 }
             }else {
             }else {
                 queue.async { [weak self, weak cell] in
                 queue.async { [weak self, weak cell] in
                     guard let `self` = self else { return }
                     guard let `self` = self else { return }
-                    let requestId = self.photoLibrary.imageAsset(asset: phAsset, size: self.thumbnailSize, completionBlock: { (image,complete) in
+                    let requestID = self.photoLibrary.imageAsset(asset: phAsset, size: self.thumbnailSize, completionBlock: { (image,complete) in
                         DispatchQueue.main.async {
                         DispatchQueue.main.async {
-                            if self.requestIds[indexPath] != nil {
+                            if self.requestIDs[indexPath] != nil {
                                 cell?.imageView?.image = image
                                 cell?.imageView?.image = image
                                 cell?.update(with: phAsset)
                                 cell?.update(with: phAsset)
                                 if self.allowedVideo {
                                 if self.allowedVideo {
@@ -905,13 +911,13 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
                                     cell?.duration = asset.type == .video ? phAsset.duration : nil
                                     cell?.duration = asset.type == .video ? phAsset.duration : nil
                                 }
                                 }
                                 if complete {
                                 if complete {
-                                    self.requestIds.removeValue(forKey: indexPath)
+                                    self.requestIDs.removeValue(forKey: indexPath)
                                 }
                                 }
                             }
                             }
                         }
                         }
                     })
                     })
-                    if requestId > 0 {
-                        self.requestIds[indexPath] = requestId
+                    if requestID > 0 {
+                        self.requestIDs[indexPath] = requestID
                     }
                     }
                 }
                 }
             }
             }
@@ -959,9 +965,9 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
     open func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
     open func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
         if self.usedPrefetch {
         if self.usedPrefetch {
             for indexPath in indexPaths {
             for indexPath in indexPaths {
-                guard let requestId = self.requestIds[indexPath] else { continue }
-                self.photoLibrary.cancelPHImageRequest(requestId: requestId)
-                self.requestIds.removeValue(forKey: indexPath)
+                guard let requestID = self.requestIDs[indexPath] else { continue }
+                self.photoLibrary.cancelPHImageRequest(requestID: requestID)
+                self.requestIDs.removeValue(forKey: indexPath)
             }
             }
             queue.async { [weak self] in
             queue.async { [weak self] in
                 guard let `self` = self, let collection = self.focusedCollection else { return }
                 guard let `self` = self, let collection = self.focusedCollection else { return }

+ 87 - 39
Carthage/Checkouts/realm-cocoa/.jenkins.yml

@@ -7,6 +7,7 @@ xcode_version:
   - 9.4
   - 9.4
   - 10.0
   - 10.0
   - 10.1
   - 10.1
+  - 10.2
 target:
 target:
   - osx
   - osx
   - docs
   - docs
@@ -15,17 +16,21 @@ target:
   - ios-swift
   - ios-swift
   - osx-swift
   - osx-swift
   - watchos
   - watchos
-  - cocoapods
+  - cocoapods-ios
+  - cocoapods-osx
+  - cocoapods-watchos
   - swiftlint
   - swiftlint
   - tvos
   - tvos
   - osx-encryption
   - osx-encryption
   - osx-object-server
   - osx-object-server
 
 
-  - ios-device-objc-ios8
+  # These are disabled because the machinen with the devices attached is currently offline
+  # - ios-device-objc-ios8
+  # - ios-device-objc-ios10
+  # - tvos-device
+  # These are disabled because they were very unreliable on CI
   # - ios-device-swift-ios8
   # - ios-device-swift-ios8
-  - ios-device-objc-ios10
   # - ios-device-swift-ios10
   # - ios-device-swift-ios10
-  - tvos-device
 configuration:
 configuration:
   - Debug
   - Debug
   - Release
   - Release
@@ -33,30 +38,33 @@ configuration:
 # Combinations have to be excluded in a way that's hard to read.
 # Combinations have to be excluded in a way that's hard to read.
 # This table shows which jobs will run:
 # This table shows which jobs will run:
 
 
-# +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-# | Configuration Matrix | osx | docs | ios-static | ios-dynamic | ios-swift | osx-swift | watchos | cocoapods | swiftlint | tvos | osx-encryption | osx-object-server | ios-device-objc-ios8 | ios-device-swift-ios8 | ios-device-objc-ios10 | ios-device-swift-ios10 | tvos-device |
-# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | --------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 9.2   | Debug        | X   |      | X          |             |           |           |         |           |           |      |                |                   |                      |                       |                       |                        |             |
-# | 9.2   | Release      | X   |      | X          | X           | X         | X         | X       | X         |           | X    | X              | X                 | X                    |                       | X                     |                        |             |
-# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | --------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 9.3   | Debug        | X   |      |            |             |           |           |         |           |           |      |                |                   |                      |                       |                       |                        |             |
-# | 9.3   | Release      | X   |      | X          | X           | X         | X         | X       | X         |           | X    |                |                   |                      |                       |                       |                        |             |
-# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | --------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 9.4   | Debug        | X   |      |            |             |           |           |         |           |           |      |                |                   |                      |                       |                       |                        |             |
-# | 9.4   | Release      | X   |      | X          | X           | X         | X         | X       | X         |           | X    |                |                   |                      |                       |                       |                        |             |
-# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | --------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 10.0  | Debug        | X   |      |            |             |           |           |         |           |           |      |                |                   |                      |                       |                       |                        |             |
-# | 10.0  | Release      | X   |      | X          | X           | X         | X         | X       | X         |           | X    |                |                   |                      |                       |                       |                        |             |
-# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | --------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 10.1  | Debug        | X   |      |            | X           | X         | X         | X       |           |           | X    |                |                   |                      |                       |                       |                        |             |
-# | 10.1  | Release      | X   | X    | X          | X           | X         | X         | X       | X         | X         | X    | X              | X                 |                      |                       | X                     |                        | X           |
-# +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+# +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+# | Configuration Matrix | osx | docs | ios-static | ios-dynamic | ios-swift | osx-swift | watchos | cocoapods-ios | cocoapods-osx | cocoapods-watchos | swiftlint | tvos | osx-encryption | osx-object-server | ios-device-objc-ios8 | ios-device-swift-ios8 | ios-device-objc-ios10 | ios-device-swift-ios10 | tvos-device |
+# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
+# | 9.2   | Debug        | X   |      | X          |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
+# | 9.2   | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    | X              | X                 | X                    |                       | X                     |                        |             |
+# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
+# | 9.3   | Debug        | X   |      |            |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
+# | 9.3   | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    |                |                   |                      |                       |                       |                        |             |
+# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
+# | 9.4   | Debug        | X   |      |            |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
+# | 9.4   | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    |                |                   |                      |                       |                       |                        |             |
+# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
+# | 10.0  | Debug        | X   |      |            |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
+# | 10.0  | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    |                |                   |                      |                       |                       |                        |             |
+# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
+# | 10.1  | Debug        | X   |      |            |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
+# | 10.1  | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    |                |                   |                      |                       |                       |                        |             |
+# | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
+# | 10.2  | Debug        | X   |      |            | X           | X         | X         | X       |               |               |                   |           | X    |                |                   |                      |                       |                       |                        |             |
+# | 10.2  | Release      | X   | X    | X          | X           | X         | X         | X       | X             | X             | X                 | X         | X    | X              | X                 |                      |                       | X                     |                        | X           |
+# +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 
 exclude:
 exclude:
   ################
   ################
   # docs
   # docs
   ################
   ################
-  # Just run on 10.0 Release
+  # Just run on 10.2 Release
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: docs
     target: docs
   - xcode_version: 9.3
   - xcode_version: 9.3
@@ -65,13 +73,15 @@ exclude:
     target: docs
     target: docs
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: docs
     target: docs
+  - xcode_version: 10.1
+    target: docs
   - target: docs
   - target: docs
     configuration: Debug
     configuration: Debug
 
 
   ################
   ################
   # ios-static
   # ios-static
   ################
   ################
-  # Skip on 9.3/9.4/10.0 Debug
+  # Skip Debug on everything but 9.2
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: ios-static
     target: ios-static
     configuration: Debug
     configuration: Debug
@@ -84,11 +94,14 @@ exclude:
   - xcode_version: 10.1
   - xcode_version: 10.1
     target: ios-static
     target: ios-static
     configuration: Debug
     configuration: Debug
+  - xcode_version: 10.2
+    target: ios-static
+    configuration: Debug
 
 
   ################
   ################
   # ios-dynamic
   # ios-dynamic
   ################
   ################
-  # Skip on 9.2/9.3/0.2 Debug
+  # Skip Debug on everything but 10.2
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: ios-dynamic
     target: ios-dynamic
     configuration: Debug
     configuration: Debug
@@ -101,11 +114,14 @@ exclude:
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: ios-dynamic
     target: ios-dynamic
     configuration: Debug
     configuration: Debug
+  - xcode_version: 10.1
+    target: ios-dynamic
+    configuration: Debug
 
 
   ################
   ################
   # ios-swift
   # ios-swift
   ################
   ################
-  # Skip 9.2/9.3/9.4/10.0 Debug
+  # Skip Debug on everything but 10.2
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: ios-swift
     target: ios-swift
     configuration: Debug
     configuration: Debug
@@ -118,11 +134,14 @@ exclude:
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: ios-swift
     target: ios-swift
     configuration: Debug
     configuration: Debug
+  - xcode_version: 10.1
+    target: ios-swift
+    configuration: Debug
 
 
   ################
   ################
   # osx-swift
   # osx-swift
   ################
   ################
-  # Skip 9.2/9.3/9.4/10.0 Debug
+  # Skip Debug on everything but 10.2
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: osx-swift
     target: osx-swift
     configuration: Debug
     configuration: Debug
@@ -135,11 +154,14 @@ exclude:
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: osx-swift
     target: osx-swift
     configuration: Debug
     configuration: Debug
+  - xcode_version: 10.1
+    target: osx-swift
+    configuration: Debug
 
 
   ################
   ################
   # watchos
   # watchos
   ################
   ################
-  # Skip 9.2/9.3/9.4/10.0 Debug
+  # Skip Debug on everything but 10.2
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: watchos
     target: watchos
     configuration: Debug
     configuration: Debug
@@ -152,18 +174,25 @@ exclude:
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: watchos
     target: watchos
     configuration: Debug
     configuration: Debug
+  - xcode_version: 10.1
+    target: watchos
+    configuration: Debug
 
 
   ################
   ################
   # cocoapods
   # cocoapods
   ################
   ################
   # Skip Debug
   # Skip Debug
-  - target: cocoapods
+  - target: cocoapods-ios
+    configuration: Debug
+  - target: cocoapods-osx
+    configuration: Debug
+  - target: cocoapods-watchos
     configuration: Debug
     configuration: Debug
 
 
   ################
   ################
   # swiftlint
   # swiftlint
   ################
   ################
-  # Just run on 10.1 Release
+  # Just run on 10.2 Release
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: swiftlint
     target: swiftlint
   - xcode_version: 9.3
   - xcode_version: 9.3
@@ -172,13 +201,15 @@ exclude:
     target: swiftlint
     target: swiftlint
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: swiftlint
     target: swiftlint
+  - xcode_version: 10.1
+    target: swiftlint
   - target: swiftlint
   - target: swiftlint
     configuration: Debug
     configuration: Debug
 
 
   ################
   ################
   # tvos
   # tvos
   ################
   ################
-  # Skip 9.2/9.3/9.4/10.0 Debug
+  # Skip Debug on everything but 10.2
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: tvos
     target: tvos
     configuration: Debug
     configuration: Debug
@@ -191,29 +222,36 @@ exclude:
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: tvos
     target: tvos
     configuration: Debug
     configuration: Debug
+  - xcode_version: 10.1
+    target: tvos
+    configuration: Debug
 
 
   ################
   ################
   # osx-encryption
   # osx-encryption
   ################
   ################
-  # Just run on 9.2/10.1 Release
+  # Just run on 9.2/10.2 Release
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: osx-encryption
     target: osx-encryption
   - xcode_version: 9.4
   - xcode_version: 9.4
     target: osx-encryption
     target: osx-encryption
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: osx-encryption
     target: osx-encryption
+  - xcode_version: 10.1
+    target: osx-encryption
   - target: osx-encryption
   - target: osx-encryption
     configuration: Debug
     configuration: Debug
 
 
   ################
   ################
   # osx-object-server
   # osx-object-server
   ################
   ################
-  # Just run on 9.2/10.1 Release
+  # Just run on 9.2/10.2 Release
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: osx-object-server
     target: osx-object-server
   - xcode_version: 9.4
   - xcode_version: 9.4
     target: osx-object-server
     target: osx-object-server
-  - xcode_version: 10.01
+  - xcode_version: 10.0
+    target: osx-object-server
+  - xcode_version: 10.1
     target: osx-object-server
     target: osx-object-server
   - target: osx-object-server
   - target: osx-object-server
     configuration: Debug
     configuration: Debug
@@ -221,22 +259,26 @@ exclude:
   ################
   ################
   # ios-device-objc-ios8
   # ios-device-objc-ios8
   ################
   ################
-  # Just run on 9.2/10.1 Release
+  # Just run on 9.2/10.2 Release
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: ios-device-objc-ios8
     target: ios-device-objc-ios8
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: ios-device-objc-ios8
     target: ios-device-objc-ios8
+  - xcode_version: 10.1
+    target: ios-device-objc-ios8
   - target: ios-device-objc-ios8
   - target: ios-device-objc-ios8
     configuration: Debug
     configuration: Debug
 
 
   ################
   ################
   # ios-device-swift-ios8
   # ios-device-swift-ios8
   ################
   ################
-  # Just run on 9.2/10.1 Release
+  # Just run on 9.2/10.2 Release
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: ios-device-swift-ios8
     target: ios-device-swift-ios8
   - xcode_version: 9.4
   - xcode_version: 9.4
     target: ios-device-swift-ios8
     target: ios-device-swift-ios8
+  - xcode_version: 10.0
+    target: ios-device-swift-ios8
   - xcode_version: 10.1
   - xcode_version: 10.1
     target: ios-device-swift-ios8
     target: ios-device-swift-ios8
   - target: ios-device-swift-ios8
   - target: ios-device-swift-ios8
@@ -245,24 +287,28 @@ exclude:
   ################
   ################
   # ios-device-objc-ios10
   # ios-device-objc-ios10
   ################
   ################
-  # Just run on 9.2/10.1 Release
+  # Just run on 9.2/10.2 Release
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: ios-device-objc-ios10
     target: ios-device-objc-ios10
   - xcode_version: 9.4
   - xcode_version: 9.4
     target: ios-device-objc-ios10
     target: ios-device-objc-ios10
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: ios-device-objc-ios10
     target: ios-device-objc-ios10
+  - xcode_version: 10.1
+    target: ios-device-objc-ios10
   - target: ios-device-objc-ios10
   - target: ios-device-objc-ios10
     configuration: Debug
     configuration: Debug
 
 
   ################
   ################
   # ios-device-swift-ios10
   # ios-device-swift-ios10
   ################
   ################
-  # Just run on 9.2/10.1 Release
+  # Just run on 9.2/10.2 Release
   - xcode_version: 9.3
   - xcode_version: 9.3
     target: ios-device-swift-ios10
     target: ios-device-swift-ios10
   - xcode_version: 9.4
   - xcode_version: 9.4
     target: ios-device-swift-ios10
     target: ios-device-swift-ios10
+  - xcode_version: 10.0
+    target: ios-device-swift-ios10
   - xcode_version: 10.1
   - xcode_version: 10.1
     target: ios-device-swift-ios10
     target: ios-device-swift-ios10
   - target: ios-device-swift-ios10
   - target: ios-device-swift-ios10
@@ -271,7 +317,7 @@ exclude:
   ################
   ################
   # tvos-device
   # tvos-device
   ################
   ################
-  # Just run on 10.1 Release
+  # Just run on 10.2 Release
   - xcode_version: 9.2
   - xcode_version: 9.2
     target: tvos-device
     target: tvos-device
   - xcode_version: 9.3
   - xcode_version: 9.3
@@ -280,5 +326,7 @@ exclude:
     target: tvos-device
     target: tvos-device
   - xcode_version: 10.0
   - xcode_version: 10.0
     target: tvos-device
     target: tvos-device
+  - xcode_version: 10.1
+    target: tvos-device
   - target: tvos-device
   - target: tvos-device
     configuration: Debug
     configuration: Debug

+ 4 - 0
Carthage/Checkouts/realm-cocoa/.swiftlint.yml

@@ -19,6 +19,10 @@ identifier_name:
     - to
     - to
 disabled_rules:
 disabled_rules:
   - block_based_kvo
   - block_based_kvo
+  # SwiftLint considers 'Realm' and 'Realm.Private' to be duplicate imports
+  # because we're using submodules in an unsual way, and normally the parent
+  # module re-exports all of its children.
+  - duplicate_imports
   - file_length
   - file_length
   - force_cast
   - force_cast
   - force_try
   - force_try

+ 49 - 0
Carthage/Checkouts/realm-cocoa/CHANGELOG.md

@@ -1,3 +1,52 @@
+3.14.1 Release notes (2019-04-04)
+=============================================================
+
+### Fixed
+
+* Fix "Cannot find interface declaration for 'RealmSwiftObject', superclass of
+  'MyRealmObjectClass'" errors when building for a simulator with Xcode 10.2
+  with "Install Objective-C Compatibility Header" enabled.
+
+### Compatibility
+
+* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
+* Realm Object Server: 3.11.0 or later.
+
+3.14.0 Release notes (2019-03-27)
+=============================================================
+
+### Enhancements
+
+* Reduce memory usage when committing write transactions.
+* Improve performance of compacting encrypted Realm files.
+  ([PR #3221](https://github.com/realm/realm-core/pull/3221)).
+* Add a Xcode 10.2 build to the release package.
+
+### Fixed
+
+* Fix a memory leak whenever Realm makes a HTTP(s) request to the Realm Object
+  Server (Issue [#6058](https://github.com/realm/realm-cocoa/issues/6058), since 3.8.0).
+* Fix an assertion failure when creating an object in a synchronized Realm
+  after creating an object with a null int primary key in the same write
+  transaction.
+  ([PR #3227](https://github.com/realm/realm-core/pull/3227)).
+* Fix some new warnings when building with Xcode 10.2 beta.
+* Properly clean up sync sessions when the last Realm object using the session
+  is deallocated while the session is explicitly suspended (since 3.9.0).
+
+### Compatibility
+
+* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
+* Realm Object Server: 3.11.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.
+
+### Internal
+
+* Throw an exception rather than crashing with an assertion failure in more
+  cases when opening invalid Realm files.
+* Upgrade to REALM_CORE_VERSION=5.14.0
+* Upgrade to REALM_SYNC_VERSION=3.15.1
+
 3.13.1 Release notes (2019-01-03)
 3.13.1 Release notes (2019-01-03)
 =============================================================
 =============================================================
 
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Configuration/Base.xcconfig

@@ -58,4 +58,4 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 WATCHOS_DEPLOYMENT_TARGET = 2.0;
 WATCHOS_DEPLOYMENT_TARGET = 2.0;
 TVOS_DEPLOYMENT_TARGET = 9.0;
 TVOS_DEPLOYMENT_TARGET = 9.0;
 
 
-SWIFT_VERSION = 3.0;
+SWIFT_VERSION = 4.0;

+ 12 - 14
Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability

@@ -1,8 +1,8 @@
-swiftVersions = ['3.2.3', '3.3', '3.3.2', '3.4', '3.4.1', '4.0.3', '4.1', '4.1.2', '4.2', '4.2.1']
+xcodeVersions = ['9.2', '9.3', '9.4', '10.0', '10.1', '10.2']
 platforms = ['osx', 'ios', 'watchos', 'tvos']
 platforms = ['osx', 'ios', 'watchos', 'tvos']
 platformNames = ['osx': 'macOS', 'ios': 'iOS', 'watchos': 'watchOS', 'tvos': 'tvOS']
 platformNames = ['osx': 'macOS', 'ios': 'iOS', 'watchos': 'watchOS', 'tvos': 'tvOS']
-carthageXcodeVersion = '10.1'
-carthageSwiftVersion = '3.4.1'
+carthageXcodeVersion = '10.2'
+docsSwiftVersion = '5.0'
 
 
 def installationTest(platform, test, language) {
 def installationTest(platform, test, language) {
   return {
   return {
@@ -24,8 +24,6 @@ def installationTest(platform, test, language) {
         find . -name 'realm-${language}-*' -print0 | xargs -J% mv % realm-${language}-latest
         find . -name 'realm-${language}-*' -print0 | xargs -J% mv % realm-${language}-latest
       fi
       fi
 
 
-      sed -i '' 's/swift-3.[0-9.]*/swift-${carthageSwiftVersion}/g' osx/swift/DynamicExample/DynamicExample.xcodeproj/project.pbxproj
-      sed -i '' 's/swift-3.[0-9.]*/swift-${carthageSwiftVersion}/g' ios/swift/DynamicExample/DynamicExample.xcodeproj/project.pbxproj
       export REALM_XCODE_VERSION=${carthageXcodeVersion}
       export REALM_XCODE_VERSION=${carthageXcodeVersion}
       ./build.sh test-${platform}-${language}-${test}
       ./build.sh test-${platform}-${language}-${test}
       """
       """
@@ -74,7 +72,7 @@ def doBuild() {
           deleteDir()
           deleteDir()
           unstash 'source'
           unstash 'source'
           sh """
           sh """
-          export REALM_SWIFT_VERSION=${swiftVersions.last()}
+          export REALM_SWIFT_VERSION=${docsSwiftVersion}
           ./scripts/reset-simulators.sh
           ./scripts/reset-simulators.sh
           ./build.sh docs
           ./build.sh docs
           cd docs
           cd docs
@@ -127,16 +125,16 @@ def doBuild() {
     for (def p in platforms) {
     for (def p in platforms) {
       def platform = p
       def platform = p
       def platformName = platformNames[platform]
       def platformName = platformNames[platform]
-      for (def v in swiftVersions) {
-        def swiftVersion = v
-        parallelBuilds["${platformName} Swift ${swiftVersion}"] = {
+      for (def v in xcodeVersions) {
+        def xcodeVersion = v
+        parallelBuilds["${platformName} Swift ${xcodeVersion}"] = {
           node('osx') {
           node('osx') {
             deleteDir()
             deleteDir()
             unstash 'source'
             unstash 'source'
-            sh "XCMODE=xcpretty ./build.sh package-${platform}-swift-${swiftVersion}"
+            sh "XCMODE=xcpretty ./build.sh package-${platform}-swift-${xcodeVersion}"
             dir("build/${platform}") {
             dir("build/${platform}") {
-              stash includes: "realm-swift-framework-${platform}-swift-${swiftVersion}.zip",
-                    name: "${platform}-swift-${swiftVersion}"
+              stash includes: "realm-swift-framework-${platform}-swift-${xcodeVersion}.zip",
+                    name: "${platform}-swift-${xcodeVersion}"
             }
             }
           }
           }
         }
         }
@@ -170,8 +168,8 @@ def doBuild() {
           deleteDir()
           deleteDir()
 
 
           for (def platform in platforms) {
           for (def platform in platforms) {
-            for (def swiftVersion in swiftVersions) {
-              unstash "${platform}-swift-${swiftVersion}"
+            for (def xcodeVersion in xcodeVersions) {
+              unstash "${platform}-swift-${xcodeVersion}"
             }
             }
           }
           }
 
 

+ 1 - 46
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm

@@ -1518,15 +1518,9 @@
 
 
             return 0;
             return 0;
         };
         };
-        NSUInteger sizeBefore = fileSize(c.pathOnDisk);
-        @autoreleasepool {
-            // We have partial transaction logs but no data
-            XCTAssertGreaterThan(sizeBefore, 0U);
-            XCTAssertTrue([[RLMRealm realmWithConfiguration:c error:nil] isEmpty]);
-        }
         XCTAssertNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
         XCTAssertNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
         [self waitForExpectationsWithTimeout:10.0 handler:nil];
         [self waitForExpectationsWithTimeout:10.0 handler:nil];
-        XCTAssertGreaterThan(fileSize(c.pathOnDisk), sizeBefore);
+        XCTAssertGreaterThan(fileSize(c.pathOnDisk), 0U);
         XCTAssertNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
         XCTAssertNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
     } else {
     } else {
         RLMRealm *realm = [self openRealmForURL:url user:user];
         RLMRealm *realm = [self openRealmForURL:url user:user];
@@ -1590,45 +1584,6 @@
     CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
     CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
 }
 }
 
 
-- (void)testDownloadWhileOpeningRealm {
-    const NSInteger NUMBER_OF_BIG_OBJECTS = 2;
-    NSURL *url = REALM_URL();
-    // Log in the user.
-    RLMSyncUser *user = [self logInUserForCredentials:[RLMObjectServerTests basicCredentialsWithName:NSStringFromSelector(_cmd)
-                                                                                            register:self.isParent]
-                                               server:[RLMObjectServerTests authServerURL]];
-    if (self.isParent) {
-        // Wait for the child process to upload everything.
-        RLMRunChildAndWait();
-        XCTestExpectation *ex = [self expectationWithDescription:@"download-realm"];
-        RLMRealmConfiguration *c = [user configurationWithURL:url fullSynchronization:true];
-        XCTAssertFalse([[NSFileManager defaultManager] fileExistsAtPath:c.pathOnDisk isDirectory:nil]);
-        [RLMRealm asyncOpenWithConfiguration:c
-                               callbackQueue:dispatch_get_main_queue()
-                                    callback:^(RLMRealm * _Nullable realm, NSError * _Nullable error) {
-            XCTAssertNil(error);
-            CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
-            [ex fulfill];
-        }];
-        RLMRealm *realm = [RLMRealm realmWithConfiguration:c error:nil];
-        CHECK_COUNT(0, HugeSyncObject, realm);
-        XCTAssertNotNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
-        [self waitForExpectationsWithTimeout:10.0 handler:nil];
-        CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
-        XCTAssertNotNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
-    } else {
-        RLMRealm *realm = [self openRealmForURL:url user:user];
-        // Write lots of data to the Realm, then wait for it to be uploaded.
-        [realm beginWriteTransaction];
-        for (NSInteger i=0; i<NUMBER_OF_BIG_OBJECTS; i++) {
-            [realm addObject:[HugeSyncObject object]];
-        }
-        [realm commitWriteTransaction];
-        [self waitForUploadsForRealm:realm];
-        CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
-    }
-}
-
 - (void)testDownloadCancelsOnAuthError {
 - (void)testDownloadCancelsOnAuthError {
     RLMSyncUser *user = [self logInUserForCredentials:[RLMObjectServerTests basicCredentialsWithName:NSStringFromSelector(_cmd)
     RLMSyncUser *user = [self logInUserForCredentials:[RLMObjectServerTests basicCredentialsWithName:NSStringFromSelector(_cmd)
                                                                                             register:self.isParent]
                                                                                             register:self.isParent]

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMSyncTestCase.mm

@@ -82,7 +82,7 @@ static NSString *nodePath() {
     const NSInteger fakeDataSize = 1000000;
     const NSInteger fakeDataSize = 1000000;
     HugeSyncObject *object = [[self alloc] init];
     HugeSyncObject *object = [[self alloc] init];
     char fakeData[fakeDataSize];
     char fakeData[fakeDataSize];
-    memset(fakeData, sizeof(fakeData), 16);
+    memset(fakeData, 16, sizeof(fakeData));
     object.dataProp = [NSData dataWithBytes:fakeData length:sizeof(fakeData)];
     object.dataProp = [NSData dataWithBytes:fakeData length:sizeof(fakeData)];
     return object;
     return object;
 }
 }

+ 5 - 14
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift

@@ -235,26 +235,24 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
     func testStreamingUploadNotifier() {
     func testStreamingUploadNotifier() {
         let bigObjectCount = 2
         let bigObjectCount = 2
         do {
         do {
-            var callCount = 0
             var transferred = 0
             var transferred = 0
             var transferrable = 0
             var transferrable = 0
             let user = try synchronouslyLogInUser(for: basicCredentials(register: isParent), server: authURL)
             let user = try synchronouslyLogInUser(for: basicCredentials(register: isParent), server: authURL)
             let realm = try synchronouslyOpenRealm(url: realmURL, user: user)
             let realm = try synchronouslyOpenRealm(url: realmURL, user: user)
             let session = realm.syncSession
             let session = realm.syncSession
             XCTAssertNotNil(session)
             XCTAssertNotNil(session)
-            let ex = expectation(description: "streaming-uploads-expectation")
-            var hasBeenFulfilled = false
+            var ex = expectation(description: "initial upload")
             let token = session!.addProgressNotification(for: .upload, mode: .reportIndefinitely) { p in
             let token = session!.addProgressNotification(for: .upload, mode: .reportIndefinitely) { p in
-                callCount += 1
                 XCTAssert(p.transferredBytes >= transferred)
                 XCTAssert(p.transferredBytes >= transferred)
                 XCTAssert(p.transferrableBytes >= transferrable)
                 XCTAssert(p.transferrableBytes >= transferrable)
                 transferred = p.transferredBytes
                 transferred = p.transferredBytes
                 transferrable = p.transferrableBytes
                 transferrable = p.transferrableBytes
-                if p.transferredBytes > 0 && p.isTransferComplete && !hasBeenFulfilled {
+                if p.transferredBytes > 0 && p.isTransferComplete {
                     ex.fulfill()
                     ex.fulfill()
-                    hasBeenFulfilled = true
                 }
                 }
             }
             }
+            waitForExpectations(timeout: 10.0, handler: nil)
+            ex = expectation(description: "write transaction upload")
             try realm.write {
             try realm.write {
                 for _ in 0..<bigObjectCount {
                 for _ in 0..<bigObjectCount {
                     realm.add(SwiftHugeSyncObject())
                     realm.add(SwiftHugeSyncObject())
@@ -262,7 +260,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
             }
             }
             waitForExpectations(timeout: 10.0, handler: nil)
             waitForExpectations(timeout: 10.0, handler: nil)
             token!.invalidate()
             token!.invalidate()
-            XCTAssert(callCount > 1)
             XCTAssert(transferred >= transferrable)
             XCTAssert(transferred >= transferrable)
         } catch {
         } catch {
             XCTFail("Got an error: \(error) (process: \(isParent ? "parent" : "child"))")
             XCTFail("Got an error: \(error) (process: \(isParent ? "parent" : "child"))")
@@ -293,15 +290,9 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
                     }
                     }
                     return 0
                     return 0
                 }
                 }
-                let sizeBefore = fileSize(path: pathOnDisk)
-                autoreleasepool {
-                    // We have partial transaction logs but no data
-                    XCTAssertGreaterThan(sizeBefore, 0)
-                    XCTAssert(try! Realm(configuration: config).isEmpty)
-                }
                 XCTAssertFalse(RLMHasCachedRealmForPath(pathOnDisk))
                 XCTAssertFalse(RLMHasCachedRealmForPath(pathOnDisk))
                 waitForExpectations(timeout: 10.0, handler: nil)
                 waitForExpectations(timeout: 10.0, handler: nil)
-                XCTAssertGreaterThan(fileSize(path: pathOnDisk), sizeBefore)
+                XCTAssertGreaterThan(fileSize(path: pathOnDisk), 0)
                 XCTAssertFalse(RLMHasCachedRealmForPath(pathOnDisk))
                 XCTAssertFalse(RLMHasCachedRealmForPath(pathOnDisk))
             } else {
             } else {
                 let realm = try synchronouslyOpenRealm(url: realmURL, user: user)
                 let realm = try synchronouslyOpenRealm(url: realmURL, user: user)

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/CMake/RealmCore.cmake

@@ -260,8 +260,8 @@ macro(build_realm_core)
     set(core_release_binary_dir "${SOURCE_DIR}/build.release")
     set(core_release_binary_dir "${SOURCE_DIR}/build.release")
     set(core_library_debug "${core_debug_binary_dir}/src/realm/${CMAKE_STATIC_LIBRARY_PREFIX}realm-dbg${CMAKE_STATIC_LIBRARY_SUFFIX}")
     set(core_library_debug "${core_debug_binary_dir}/src/realm/${CMAKE_STATIC_LIBRARY_PREFIX}realm-dbg${CMAKE_STATIC_LIBRARY_SUFFIX}")
     set(core_library_release "${core_release_binary_dir}/src/realm/${CMAKE_STATIC_LIBRARY_PREFIX}realm${CMAKE_STATIC_LIBRARY_SUFFIX}")
     set(core_library_release "${core_release_binary_dir}/src/realm/${CMAKE_STATIC_LIBRARY_PREFIX}realm${CMAKE_STATIC_LIBRARY_SUFFIX}")
-    set(core_parser_library_debug "${core_debug_binary_dir}/src/realm/${CMAKE_STATIC_LIBRARY_PREFIX}realm-parser-dbg${CMAKE_STATIC_LIBRARY_SUFFIX}")
-    set(core_parser_library_release "${core_release_binary_dir}/src/realm/${CMAKE_STATIC_LIBRARY_PREFIX}realm-parser${CMAKE_STATIC_LIBRARY_SUFFIX}")
+    set(core_parser_library_debug "${core_debug_binary_dir}/src/realm/parser/${CMAKE_STATIC_LIBRARY_PREFIX}realm-parser-dbg${CMAKE_STATIC_LIBRARY_SUFFIX}")
+    set(core_parser_library_release "${core_release_binary_dir}/src/realm/parser/${CMAKE_STATIC_LIBRARY_PREFIX}realm-parser${CMAKE_STATIC_LIBRARY_SUFFIX}")
 
 
     ExternalProject_Add_Step(realm-core ensure-libraries
     ExternalProject_Add_Step(realm-core ensure-libraries
         DEPENDEES build
         DEPENDEES build

+ 5 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/CMakeLists.txt

@@ -30,6 +30,11 @@ if(REALM_CORE_PREFIX AND REALM_ENABLE_SYNC AND NOT REALM_SYNC_PREFIX)
     message(FATAL_ERROR "REALM_SYNC_PREFIX must be set when specifying REALM_CORE_PREFIX when REALM_ENABLE_SYNC is set.")
     message(FATAL_ERROR "REALM_SYNC_PREFIX must be set when specifying REALM_CORE_PREFIX when REALM_ENABLE_SYNC is set.")
 endif()
 endif()
 
 
+set(REALM_ENABLE_SERVER OFF CACHE BOOL "Enable the server-only functionality.")
+if(REALM_ENABLE_SERVER AND NOT REALM_ENABLE_SYNC)
+    message(FATAL_ERROR "REALM_ENABLE_SERVER requires REALM_ENABLE_SYNC.")
+endif()
+
 include(RealmCore)
 include(RealmCore)
 use_realm_core("${REALM_ENABLE_SYNC}" "${REALM_CORE_PREFIX}" "${REALM_SYNC_PREFIX}")
 use_realm_core("${REALM_ENABLE_SYNC}" "${REALM_CORE_PREFIX}" "${REALM_SYNC_PREFIX}")
 
 

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list

@@ -1,4 +1,4 @@
-REALM_CORE_VERSION=5.12.0
-REALM_SYNC_VERSION=3.12.10
+REALM_CORE_VERSION=5.12.7
+REALM_SYNC_VERSION=3.14.12
 ANDROID_OPENSSL_VERSION=1.0.2k
 ANDROID_OPENSSL_VERSION=1.0.2k
 REALM_CORE_PACKAGING=2
 REALM_CORE_PACKAGING=2

+ 16 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/CMakeLists.txt

@@ -64,14 +64,16 @@ set(HEADERS
 
 
     util/aligned_union.hpp
     util/aligned_union.hpp
     util/atomic_shared_ptr.hpp
     util/atomic_shared_ptr.hpp
+    util/event_loop_dispatcher.hpp
     util/event_loop_signal.hpp
     util/event_loop_signal.hpp
+    util/fifo.hpp
     util/tagged_bool.hpp
     util/tagged_bool.hpp
     util/uuid.hpp)
     util/uuid.hpp)
 
 
 if(APPLE)
 if(APPLE)
-    list(APPEND SOURCES impl/apple/external_commit_helper.cpp impl/apple/keychain_helper.cpp)
+    list(APPEND SOURCES impl/apple/external_commit_helper.cpp impl/apple/keychain_helper.cpp util/fifo.cpp)
 elseif(REALM_HAVE_EPOLL)
 elseif(REALM_HAVE_EPOLL)
-    list(APPEND SOURCES impl/epoll/external_commit_helper.cpp)
+    list(APPEND SOURCES impl/epoll/external_commit_helper.cpp util/fifo.cpp)
 elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows")
 elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows")
     list(APPEND SOURCES impl/windows/external_commit_helper.cpp)
     list(APPEND SOURCES impl/windows/external_commit_helper.cpp)
 else()
 else()
@@ -119,6 +121,18 @@ if(REALM_ENABLE_SYNC)
     list(APPEND INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS})
     list(APPEND INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS})
 endif()
 endif()
 
 
+if(REALM_ENABLE_SERVER)
+    list(APPEND HEADERS
+        server/adapter.hpp
+        server/admin_realm.hpp
+        server/global_notifier.hpp)
+    list(APPEND SOURCES
+        server/adapter.cpp
+        server/admin_realm.cpp
+        server/global_notifier.cpp)
+    list(APPEND INCLUDE_DIRS ../external/json)
+endif()
+
 add_library(realm-object-store STATIC ${SOURCES} ${HEADERS})
 add_library(realm-object-store STATIC ${SOURCES} ${HEADERS})
 set_target_properties(realm-object-store PROPERTIES POSITION_INDEPENDENT_CODE 1)
 set_target_properties(realm-object-store PROPERTIES POSITION_INDEPENDENT_CODE 1)
 target_compile_definitions(realm-object-store PRIVATE ${PLATFORM_DEFINES})
 target_compile_definitions(realm-object-store PRIVATE ${PLATFORM_DEFINES})

+ 38 - 24
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp

@@ -17,8 +17,10 @@
 ////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////
 
 
 #include "impl/external_commit_helper.hpp"
 #include "impl/external_commit_helper.hpp"
-
 #include "impl/realm_coordinator.hpp"
 #include "impl/realm_coordinator.hpp"
+#include "util/fifo.hpp"
+
+#include <realm/group_shared_options.hpp>
 
 
 #include <asl.h>
 #include <asl.h>
 #include <assert.h>
 #include <assert.h>
@@ -53,6 +55,7 @@ void notify_fd(int fd, int read_fd)
         read(read_fd, buff, sizeof buff);
         read(read_fd, buff, sizeof buff);
     }
     }
 }
 }
+
 } // anonymous namespace
 } // anonymous namespace
 
 
 void ExternalCommitHelper::FdHolder::close()
 void ExternalCommitHelper::FdHolder::close()
@@ -95,27 +98,38 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
     }
     }
 
 
 #if !TARGET_OS_TV
 #if !TARGET_OS_TV
-    auto path = parent.get_path() + ".note";
 
 
-    // Create and open the named pipe
-    int ret = mkfifo(path.c_str(), 0600);
-    if (ret == -1) {
-        int err = errno;
-        if (err == ENOTSUP) {
-            // Filesystem doesn't support named pipes, so try putting it in tmp instead
-            // Hash collisions are okay here because they just result in doing
-            // extra work, as opposed to correctness problems
-            std::ostringstream ss;
-            ss << getenv("TMPDIR");
-            ss << "realm_" << std::hash<std::string>()(path) << ".note";
-            path = ss.str();
-            ret = mkfifo(path.c_str(), 0600);
-            err = errno;
-        }
-        // the fifo already existing isn't an error
-        if (ret == -1 && err != EEXIST) {
-            throw std::system_error(err, std::system_category());
-        }
+
+    // Object Store needs to create a named pipe in order to coordinate notifications.
+    // This can be a problem on some file systems (e.g. FAT32) or due to security policies in SELinux. Most commonly
+    // it is a problem when saving Realms on external storage: https://stackoverflow.com/questions/2740321/how-to-create-named-pipe-mkfifo-in-android
+    //
+    // For this reason we attempt to create this file in a temporary location known to be safe to write these files.
+    //
+    // In order of priority we attempt to write the file in the following locations:
+    //  1) Next to the Realm file itself
+    //  2) A location defined by `Realm::Config::fifo_files_fallback_path`
+    //  3) A location defined by `SharedGroupOptions::set_sys_tmp_dir()`
+    //
+    // Core has a similar policy for its named pipes.
+    //
+    // Also see https://github.com/realm/realm-java/issues/3140
+    // Note that hash collisions are okay here because they just result in doing extra work instead of resulting
+    // in correctness problems.
+
+    std::string path;
+    std::string temp_dir = util::normalize_dir(parent.get_config().fifo_files_fallback_path);
+    std::string sys_temp_dir = util::normalize_dir(SharedGroupOptions::get_sys_tmp_dir());
+
+    path = parent.get_path() + ".note";
+    bool fifo_created = util::try_create_fifo(path);
+    if (!fifo_created && !temp_dir.empty()) {
+        path = util::format("%1realm_%2.note", temp_dir, std::hash<std::string>()(parent.get_path()));
+        fifo_created = util::try_create_fifo(path);
+    }
+    if (!fifo_created && !sys_temp_dir.empty()) {
+        path = util::format("%1realm_%2.note", sys_temp_dir, std::hash<std::string>()(parent.get_path()));
+        util::create_fifo(path);
     }
     }
 
 
     m_notify_fd = open(path.c_str(), O_RDWR);
     m_notify_fd = open(path.c_str(), O_RDWR);
@@ -125,7 +139,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
 
 
     // Make writing to the pipe return -1 when the pipe's buffer is full
     // Make writing to the pipe return -1 when the pipe's buffer is full
     // rather than blocking until there's space available
     // rather than blocking until there's space available
-    ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK);
+    int ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK);
     if (ret == -1) {
     if (ret == -1) {
         throw std::system_error(errno, std::system_category());
         throw std::system_error(errno, std::system_category());
     }
     }
@@ -154,7 +168,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
     m_shutdown_read_fd = shutdown_pipe[0];
     m_shutdown_read_fd = shutdown_pipe[0];
     m_shutdown_write_fd = shutdown_pipe[1];
     m_shutdown_write_fd = shutdown_pipe[1];
 
 
-    m_thread = std::async(std::launch::async, [=] {
+    m_thread = std::thread([=] {
         try {
         try {
             listen();
             listen();
         }
         }
@@ -177,7 +191,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
 ExternalCommitHelper::~ExternalCommitHelper()
 ExternalCommitHelper::~ExternalCommitHelper()
 {
 {
     notify_fd(m_shutdown_write_fd, m_shutdown_read_fd);
     notify_fd(m_shutdown_write_fd, m_shutdown_read_fd);
-    m_thread.wait(); // Wait for the thread to exit
+    m_thread.join(); // Wait for the thread to exit
 }
 }
 
 
 void ExternalCommitHelper::listen()
 void ExternalCommitHelper::listen()

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/apple/external_commit_helper.hpp

@@ -16,7 +16,7 @@
 //
 //
 ////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////
 
 
-#include <future>
+#include <thread>
 
 
 namespace realm {
 namespace realm {
 class Realm;
 class Realm;
@@ -59,7 +59,7 @@ private:
     RealmCoordinator& m_parent;
     RealmCoordinator& m_parent;
 
 
     // The listener thread
     // The listener thread
-    std::future<void> m_thread;
+    std::thread m_thread;
 
 
     // Pipe which is waited on for changes and written to when there is a new
     // Pipe which is waited on for changes and written to when there is a new
     // commit to notify others of. When using a named pipe m_notify_fd is
     // commit to notify others of. When using a named pipe m_notify_fd is

+ 30 - 32
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/epoll/external_commit_helper.cpp

@@ -18,6 +18,7 @@
 
 
 #include "impl/external_commit_helper.hpp"
 #include "impl/external_commit_helper.hpp"
 #include "impl/realm_coordinator.hpp"
 #include "impl/realm_coordinator.hpp"
+#include "util/fifo.hpp"
 
 
 #include <realm/util/assert.hpp>
 #include <realm/util/assert.hpp>
 #include <realm/group_shared_options.hpp>
 #include <realm/group_shared_options.hpp>
@@ -29,8 +30,6 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <sys/epoll.h>
 #include <sys/epoll.h>
 #include <sys/time.h>
 #include <sys/time.h>
-#include <sys/stat.h>
-#include <system_error>
 #include <unistd.h>
 #include <unistd.h>
 
 
 #ifdef __ANDROID__
 #ifdef __ANDROID__
@@ -115,36 +114,35 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
 : m_parent(parent)
 : m_parent(parent)
 {
 {
     std::string path;
     std::string path;
-    std::string temporary_dir = SharedGroupOptions::get_sys_tmp_dir();
-    if (temporary_dir.empty()) {
-        path = parent.get_path() + ".note";
-    } else {
-        // The fifo is always created in the temporary directory if it is provided.
-        // See https://github.com/realm/realm-java/issues/3140
-        // We create .note file on the temp directory always for simplicity no matter where the Realm file is.
-        // Hash collisions are okay here because they just result in doing extra work.
-        path = util::format("%1%2_realm.note", temporary_dir, std::hash<std::string>()(parent.get_path()));
+    std::string temp_dir = util::normalize_dir(parent.get_config().fifo_files_fallback_path);
+    std::string sys_temp_dir = util::normalize_dir(SharedGroupOptions::get_sys_tmp_dir());
+
+    // Object Store needs to create a named pipe in order to coordinate notifications.
+    // This can be a problem on some file systems (e.g. FAT32) or due to security policies in SELinux. Most commonly
+    // it is a problem when saving Realms on external storage: https://stackoverflow.com/questions/2740321/how-to-create-named-pipe-mkfifo-in-android
+    //
+    // For this reason we attempt to create this file in a temporary location known to be safe to write these files.
+    //
+    // In order of priority we attempt to write the file in the following locations:
+    //  1) Next to the Realm file itself
+    //  2) A location defined by `Realm::Config::fifo_files_fallback_path`
+    //  3) A location defined by `SharedGroupOptions::set_sys_tmp_dir()`
+    //
+    // Core has a similar policy for its named pipes.
+    //
+    // Also see https://github.com/realm/realm-java/issues/3140
+    // Note that hash collisions are okay here because they just result in doing extra work instead of resulting
+    // in correctness problems.
+
+    path = parent.get_path() + ".note";
+    bool fifo_created = util::try_create_fifo(path);
+    if (!fifo_created && !temp_dir.empty()) {
+        path = util::format("%1realm_%2.note", temp_dir, std::hash<std::string>()(parent.get_path()));
+        fifo_created = util::try_create_fifo(path);
     }
     }
-
-    // Create and open the named pipe
-    int ret = mkfifo(path.c_str(), 0600);
-    if (ret == -1) {
-        int err = errno;
-        // the fifo already existing isn't an error
-        if (err != EEXIST) {
-            // Workaround for a mkfifo bug on Blackberry devices:
-            // When the fifo already exists, mkfifo fails with error ENOSYS which is not correct.
-            // In this case, we use stat to check if the path exists and it is a fifo.
-            struct stat stat_buf;
-            if (err == ENOSYS && stat(path.c_str(), &stat_buf) == 0) {
-                if ((stat_buf.st_mode & S_IFMT) != S_IFIFO) {
-                    throw std::runtime_error(path + " exists and it is not a fifo.");
-                }
-            }
-            else {
-                throw std::system_error(err, std::system_category());
-            }
-        }
+    if (!fifo_created && !sys_temp_dir.empty()) {
+        path = util::format("%1realm_%2.note", sys_temp_dir, std::hash<std::string>()(parent.get_path()));
+        util::create_fifo(path);
     }
     }
 
 
     m_notify_fd = open(path.c_str(), O_RDWR);
     m_notify_fd = open(path.c_str(), O_RDWR);
@@ -154,7 +152,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent)
 
 
     // Make writing to the pipe return -1 when the pipe's buffer is full
     // Make writing to the pipe return -1 when the pipe's buffer is full
     // rather than blocking until there's space available
     // rather than blocking until there's space available
-    ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK);
+    int ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK);
     if (ret == -1) {
     if (ret == -1) {
         throw std::system_error(errno, std::system_category());
         throw std::system_error(errno, std::system_category());
     }
     }

+ 27 - 9
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.cpp

@@ -196,6 +196,7 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
     auto schema = std::move(config.schema);
     auto schema = std::move(config.schema);
     auto migration_function = std::move(config.migration_function);
     auto migration_function = std::move(config.migration_function);
     auto initialization_function = std::move(config.initialization_function);
     auto initialization_function = std::move(config.initialization_function);
+    auto audit_factory = std::move(config.audit_factory);
     config.schema = {};
     config.schema = {};
 
 
     if (config.cache) {
     if (config.cache) {
@@ -239,6 +240,9 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
     if (realm->config().sync_config)
     if (realm->config().sync_config)
         create_sync_session();
         create_sync_session();
 
 
+    if (!m_audit_context && audit_factory)
+        m_audit_context = audit_factory();
+
     if (schema) {
     if (schema) {
         lock.unlock();
         lock.unlock();
         realm->update_schema(std::move(*schema), config.schema_version, std::move(migration_function),
         realm->update_schema(std::move(*schema), config.schema_version, std::move(migration_function),
@@ -321,10 +325,19 @@ RealmCoordinator::~RealmCoordinator()
 
 
 void RealmCoordinator::unregister_realm(Realm* realm)
 void RealmCoordinator::unregister_realm(Realm* realm)
 {
 {
-    std::lock_guard<std::mutex> lock(m_realm_mutex);
-    auto new_end = remove_if(begin(m_weak_realm_notifiers), end(m_weak_realm_notifiers),
-                             [=](auto& notifier) { return notifier.expired() || notifier.is_for_realm(realm); });
-    m_weak_realm_notifiers.erase(new_end, end(m_weak_realm_notifiers));
+    // Normally results notifiers are cleaned up by the background worker thread
+    // but if that's disabled we need to ensure that any notifiers from this
+    // Realm get cleaned up
+    if (!m_config.automatic_change_notifications) {
+        std::unique_lock<std::mutex> lock(m_notifier_mutex);
+        clean_up_dead_notifiers();
+    }
+    {
+        std::lock_guard<std::mutex> lock(m_realm_mutex);
+        auto new_end = remove_if(begin(m_weak_realm_notifiers), end(m_weak_realm_notifiers),
+                                 [=](auto& notifier) { return notifier.expired() || notifier.is_for_realm(realm); });
+        m_weak_realm_notifiers.erase(new_end, end(m_weak_realm_notifiers));
+    }
 }
 }
 
 
 void RealmCoordinator::clear_cache()
 void RealmCoordinator::clear_cache()
@@ -864,11 +877,10 @@ void RealmCoordinator::process_available_async(Realm& realm)
     if (notifiers.empty())
     if (notifiers.empty())
         return;
         return;
 
 
-    if (realm.m_binding_context)
-        realm.m_binding_context->will_send_notifications();
-
     if (auto error = m_async_error) {
     if (auto error = m_async_error) {
         lock.unlock();
         lock.unlock();
+        if (realm.m_binding_context)
+            realm.m_binding_context->will_send_notifications();
         for (auto& notifier : notifiers)
         for (auto& notifier : notifiers)
             notifier->deliver_error(m_async_error);
             notifier->deliver_error(m_async_error);
         if (realm.m_binding_context)
         if (realm.m_binding_context)
@@ -878,19 +890,25 @@ void RealmCoordinator::process_available_async(Realm& realm)
 
 
     bool in_read = realm.is_in_read_transaction();
     bool in_read = realm.is_in_read_transaction();
     auto& sg = Realm::Internal::get_shared_group(realm);
     auto& sg = Realm::Internal::get_shared_group(realm);
-    if (!sg) // i.e. the Realm was closed in a callback above
-        return;
     auto version = sg->get_version_of_current_transaction();
     auto version = sg->get_version_of_current_transaction();
     auto package = [&](auto& notifier) {
     auto package = [&](auto& notifier) {
         return !(notifier->has_run() && (!in_read || notifier->version() == version) && notifier->package_for_delivery());
         return !(notifier->has_run() && (!in_read || notifier->version() == version) && notifier->package_for_delivery());
     };
     };
     notifiers.erase(std::remove_if(begin(notifiers), end(notifiers), package), end(notifiers));
     notifiers.erase(std::remove_if(begin(notifiers), end(notifiers), package), end(notifiers));
+    if (notifiers.empty())
+        return;
     lock.unlock();
     lock.unlock();
 
 
     // no before advance because the Realm is already at the given version,
     // no before advance because the Realm is already at the given version,
     // because we're either sending initial notifications or the write was
     // because we're either sending initial notifications or the write was
     // done on this Realm instance
     // done on this Realm instance
 
 
+    if (realm.m_binding_context) {
+        realm.m_binding_context->will_send_notifications();
+        if (!sg) // i.e. the Realm was closed in the callback above
+            return;
+    }
+
     // Skip delivering if the Realm isn't in a read transaction
     // Skip delivering if the Realm isn't in a read transaction
     if (in_read) {
     if (in_read) {
         for (auto& notifier : notifiers)
         for (auto& notifier : notifiers)

+ 4 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.hpp

@@ -146,6 +146,8 @@ public:
     partial_sync::WorkQueue& partial_sync_work_queue();
     partial_sync::WorkQueue& partial_sync_work_queue();
 #endif
 #endif
 
 
+    AuditInterface* audit_context() const noexcept { return m_audit_context.get(); }
+
 private:
 private:
     Realm::Config m_config;
     Realm::Config m_config;
 
 
@@ -184,6 +186,8 @@ private:
     std::unique_ptr<partial_sync::WorkQueue> m_partial_sync_work_queue;
     std::unique_ptr<partial_sync::WorkQueue> m_partial_sync_work_queue;
 #endif
 #endif
 
 
+    std::shared_ptr<AuditInterface> m_audit_context;
+
     // must be called with m_notifier_mutex locked
     // must be called with m_notifier_mutex locked
     void pin_version(VersionID version);
     void pin_version(VersionID version);
 
 

+ 3 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.cpp

@@ -20,6 +20,7 @@
 
 
 #include "impl/realm_coordinator.hpp"
 #include "impl/realm_coordinator.hpp"
 #include "impl/results_notifier.hpp"
 #include "impl/results_notifier.hpp"
+#include "audit.hpp"
 #include "object_schema.hpp"
 #include "object_schema.hpp"
 #include "object_store.hpp"
 #include "object_store.hpp"
 #include "schema.hpp"
 #include "schema.hpp"
@@ -267,6 +268,8 @@ void Results::evaluate_query_if_needed(bool wants_notifications)
                 prepare_async(ForCallback{false});
                 prepare_async(ForCallback{false});
             m_has_used_table_view = true;
             m_has_used_table_view = true;
             m_table_view.sync_if_needed();
             m_table_view.sync_if_needed();
+            if (auto audit = m_realm->audit_context())
+                audit->record_query(m_realm->read_transaction_version(), m_table_view);
             break;
             break;
     }
     }
 }
 }

+ 31 - 11
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.cpp

@@ -21,7 +21,9 @@
 #include "impl/collection_notifier.hpp"
 #include "impl/collection_notifier.hpp"
 #include "impl/realm_coordinator.hpp"
 #include "impl/realm_coordinator.hpp"
 #include "impl/transact_log_handler.hpp"
 #include "impl/transact_log_handler.hpp"
+#include "util/fifo.hpp"
 
 
+#include "audit.hpp"
 #include "binding_context.hpp"
 #include "binding_context.hpp"
 #include "list.hpp"
 #include "list.hpp"
 #include "object.hpp"
 #include "object.hpp"
@@ -144,7 +146,7 @@ REALM_NOINLINE static void translate_file_exception(StringData path, bool immuta
 static bool is_nonupgradable_history(IncompatibleHistories const& ex)
 static bool is_nonupgradable_history(IncompatibleHistories const& ex)
 {
 {
     // FIXME: Replace this with a proper specific exception type once Core adds support for it.
     // FIXME: Replace this with a proper specific exception type once Core adds support for it.
-    return ex.what() == std::string("Incompatible histories. Nonupgradable history schema");
+    return std::string(ex.what()).find(std::string("Incompatible histories. Nonupgradable history schema")) != npos;
 }
 }
 #endif
 #endif
 
 
@@ -180,6 +182,8 @@ void Realm::open_with_config(const Config& config,
             SharedGroupOptions options;
             SharedGroupOptions options;
             options.durability = config.in_memory ? SharedGroupOptions::Durability::MemOnly :
             options.durability = config.in_memory ? SharedGroupOptions::Durability::MemOnly :
                                                     SharedGroupOptions::Durability::Full;
                                                     SharedGroupOptions::Durability::Full;
+
+            options.temp_dir = util::normalize_dir(config.fifo_files_fallback_path);
             options.encryption_key = config.encryption_key.data();
             options.encryption_key = config.encryption_key.data();
             options.allow_file_format_upgrade = !config.disable_format_upgrade &&
             options.allow_file_format_upgrade = !config.disable_format_upgrade &&
                                                 config.schema_mode != SchemaMode::ResetFile;
                                                 config.schema_mode != SchemaMode::ResetFile;
@@ -205,7 +209,7 @@ void Realm::open_with_config(const Config& config,
             translate_file_exception(config.path, config.immutable()); // Throws
             translate_file_exception(config.path, config.immutable()); // Throws
 
 
         // Move the Realm file into the recovery directory.
         // Move the Realm file into the recovery directory.
-        std::string recovery_directory = SyncManager::shared().recovery_directory_path();
+        std::string recovery_directory = SyncManager::shared().recovery_directory_path(config.sync_config ? config.sync_config->recovery_directory : none);
         std::string new_realm_path = util::reserve_unique_file_name(recovery_directory, "synced-realm-XXXXXXX");
         std::string new_realm_path = util::reserve_unique_file_name(recovery_directory, "synced-realm-XXXXXXX");
         util::File::move(config.path, new_realm_path);
         util::File::move(config.path, new_realm_path);
 
 
@@ -585,14 +589,14 @@ void Realm::notify_schema_changed()
     }
     }
 }
 }
 
 
-static void check_read_write(Realm *realm)
+static void check_read_write(const Realm* realm)
 {
 {
     if (realm->config().immutable()) {
     if (realm->config().immutable()) {
         throw InvalidTransactionException("Can't perform transactions on read-only Realms.");
         throw InvalidTransactionException("Can't perform transactions on read-only Realms.");
     }
     }
 }
 }
 
 
-static void check_write(Realm* realm)
+static void check_write(const Realm* realm)
 {
 {
     if (realm->config().immutable() || realm->config().read_only_alternative()) {
     if (realm->config().immutable() || realm->config().read_only_alternative()) {
         throw InvalidTransactionException("Can't perform transactions on read-only Realms.");
         throw InvalidTransactionException("Can't perform transactions on read-only Realms.");
@@ -623,6 +627,14 @@ void Realm::verify_open() const
     }
     }
 }
 }
 
 
+VersionID Realm::read_transaction_version() const
+{
+    verify_thread();
+    verify_open();
+    check_read_write(this);
+    return m_shared_group->get_version_of_current_transaction();
+}
+
 bool Realm::is_in_transaction() const noexcept
 bool Realm::is_in_transaction() const noexcept
 {
 {
     if (!m_shared_group) {
     if (!m_shared_group) {
@@ -678,7 +690,15 @@ void Realm::commit_transaction()
         throw InvalidTransactionException("Can't commit a non-existing write transaction");
         throw InvalidTransactionException("Can't commit a non-existing write transaction");
     }
     }
 
 
-    m_coordinator->commit_write(*this);
+    if (auto audit = audit_context()) {
+        auto prev_version = m_shared_group->pin_version();
+        m_coordinator->commit_write(*this);
+        audit->record_write(prev_version, m_shared_group->get_version_of_current_transaction());
+        m_shared_group->unpin_version(prev_version);
+    }
+    else {
+        m_coordinator->commit_write(*this);
+    }
     cache_new_schema();
     cache_new_schema();
     invalidate_permission_cache();
     invalidate_permission_cache();
 }
 }
@@ -864,7 +884,7 @@ bool Realm::refresh()
 
 
 bool Realm::can_deliver_notifications() const noexcept
 bool Realm::can_deliver_notifications() const noexcept
 {
 {
-    if (m_config.immutable()) {
+    if (m_config.immutable() || !m_config.automatic_change_notifications) {
         return false;
         return false;
     }
     }
 
 
@@ -987,6 +1007,11 @@ template Object Realm::resolve_thread_safe_reference(ThreadSafeReference<Object>
 template List Realm::resolve_thread_safe_reference(ThreadSafeReference<List> reference);
 template List Realm::resolve_thread_safe_reference(ThreadSafeReference<List> reference);
 template Results Realm::resolve_thread_safe_reference(ThreadSafeReference<Results> reference);
 template Results Realm::resolve_thread_safe_reference(ThreadSafeReference<Results> reference);
 
 
+AuditInterface* Realm::audit_context() const noexcept
+{
+    return m_coordinator ? m_coordinator->audit_context() : nullptr;
+}
+
 #if REALM_ENABLE_SYNC
 #if REALM_ENABLE_SYNC
 static_assert(static_cast<int>(ComputedPrivileges::Read) == static_cast<int>(sync::Privilege::Read), "");
 static_assert(static_cast<int>(ComputedPrivileges::Read) == static_cast<int>(sync::Privilege::Read), "");
 static_assert(static_cast<int>(ComputedPrivileges::Update) == static_cast<int>(sync::Privilege::Update), "");
 static_assert(static_cast<int>(ComputedPrivileges::Update) == static_cast<int>(sync::Privilege::Update), "");
@@ -1107,8 +1132,3 @@ Group& RealmFriend::read_group_to(Realm& realm, VersionID version)
     realm.begin_read(version);
     realm.begin_read(version);
     return *realm.m_group;
     return *realm.m_group;
 }
 }
-
-std::size_t Realm::compute_size() {
-    Group& group = read_group();
-    return group.compute_aggregated_byte_size();
-}

+ 18 - 8
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.hpp

@@ -32,6 +32,7 @@
 #include <memory>
 #include <memory>
 
 
 namespace realm {
 namespace realm {
+class AuditInterface;
 class BindingContext;
 class BindingContext;
 class Group;
 class Group;
 class Realm;
 class Realm;
@@ -188,6 +189,11 @@ public:
         // User-supplied encryption key. Must be either empty or 64 bytes.
         // User-supplied encryption key. Must be either empty or 64 bytes.
         std::vector<char> encryption_key;
         std::vector<char> encryption_key;
 
 
+        // Core and Object Store will in some cases need to create named pipes alongside the Realm file.
+        // But on some filesystems this can be a problem (e.g. external storage on Android that uses FAT32).
+        // In order to work around this, a separate path can be specified for these files.
+        std::string fifo_files_fallback_path;
+
         bool in_memory = false;
         bool in_memory = false;
         SchemaMode schema_mode = SchemaMode::Automatic;
         SchemaMode schema_mode = SchemaMode::Automatic;
 
 
@@ -242,9 +248,12 @@ public:
         /// A data structure storing data used to configure the Realm for sync support.
         /// A data structure storing data used to configure the Realm for sync support.
         std::shared_ptr<SyncConfig> sync_config;
         std::shared_ptr<SyncConfig> sync_config;
 
 
-        // FIXME: Realm Java manages sync at the Java level, so it needs to create Realms using the sync history
-        //        format.
+        // Open the Realm using the sync history mode even if a sync
+        // configuration is not supplied.
         bool force_sync_history = false;
         bool force_sync_history = false;
+
+        // A factory function which produces an audit implementation.
+        std::function<std::shared_ptr<AuditInterface>()> audit_factory;
     };
     };
 
 
     // Get a cached Realm or create a new one if no cached copies exists
     // Get a cached Realm or create a new one if no cached copies exists
@@ -279,7 +288,10 @@ public:
     void commit_transaction();
     void commit_transaction();
     void cancel_transaction();
     void cancel_transaction();
     bool is_in_transaction() const noexcept;
     bool is_in_transaction() const noexcept;
+
     bool is_in_read_transaction() const { return !!m_group; }
     bool is_in_read_transaction() const { return !!m_group; }
+    VersionID read_transaction_version() const;
+    Group& read_group();
 
 
     bool is_in_migration() const noexcept { return m_in_migration; }
     bool is_in_migration() const noexcept { return m_in_migration; }
 
 
@@ -329,6 +341,8 @@ public:
     ComputedPrivileges get_privileges(StringData object_type);
     ComputedPrivileges get_privileges(StringData object_type);
     ComputedPrivileges get_privileges(RowExpr row);
     ComputedPrivileges get_privileges(RowExpr row);
 
 
+    AuditInterface* audit_context() const noexcept;
+
     static SharedRealm make_shared_realm(Config config, std::shared_ptr<_impl::RealmCoordinator> coordinator = nullptr) {
     static SharedRealm make_shared_realm(Config config, std::shared_ptr<_impl::RealmCoordinator> coordinator = nullptr) {
         struct make_shared_enabler : public Realm {
         struct make_shared_enabler : public Realm {
             make_shared_enabler(Config config, std::shared_ptr<_impl::RealmCoordinator> coordinator)
             make_shared_enabler(Config config, std::shared_ptr<_impl::RealmCoordinator> coordinator)
@@ -426,12 +440,8 @@ private:
 public:
 public:
     std::unique_ptr<BindingContext> m_binding_context;
     std::unique_ptr<BindingContext> m_binding_context;
 
 
-    // FIXME private
-    Group& read_group();
-
-    std::size_t compute_size();
-    
-    Replication *history() { return m_history.get(); }
+    // FIXME: This is currently needed by the adapter to get access to its changeset cooker
+    Replication* history() { return m_history.get(); }
 
 
     friend class _impl::RealmFriend;
     friend class _impl::RealmFriend;
 };
 };

+ 2 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/CMakeLists.txt

@@ -5,6 +5,7 @@ set(HEADERS
     util/index_helpers.hpp
     util/index_helpers.hpp
     util/templated_test_case.hpp
     util/templated_test_case.hpp
     util/test_file.hpp
     util/test_file.hpp
+    util/test_utils.hpp
 )
 )
 
 
 set(SOURCES
 set(SOURCES
@@ -25,6 +26,7 @@ set(SOURCES
 
 
     util/event_loop.cpp
     util/event_loop.cpp
     util/test_file.cpp
     util/test_file.cpp
+    util/test_utils.cpp
 )
 )
 
 
 
 

+ 52 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp

@@ -21,6 +21,7 @@
 #include "util/event_loop.hpp"
 #include "util/event_loop.hpp"
 #include "util/test_file.hpp"
 #include "util/test_file.hpp"
 #include "util/templated_test_case.hpp"
 #include "util/templated_test_case.hpp"
+#include "util/test_utils.hpp"
 
 
 #include "binding_context.hpp"
 #include "binding_context.hpp"
 #include "object_schema.hpp"
 #include "object_schema.hpp"
@@ -152,6 +153,53 @@ TEST_CASE("SharedRealm: get_shared_realm()") {
         }
         }
     }
     }
 
 
+
+// Windows doesn't use fifos
+#ifndef _WIN32
+    SECTION("should be able to set a FIFO fallback path") {
+        std::string fallback_dir = tmp_dir() + "/fallback/";
+        realm::util::try_make_dir(fallback_dir);
+        TestFile config;
+        config.fifo_files_fallback_path = fallback_dir;
+        config.schema_version = 1;
+        config.schema = Schema{
+            {"object", {
+                {"value", PropertyType::Int}
+            }},
+        };
+
+        realm::util::make_dir(config.path + ".note");
+        auto realm = Realm::get_shared_realm(config);
+        auto fallback_file = util::format("%1realm_%2.note", fallback_dir, std::hash<std::string>()(config.path)); // Mirror internal implementation
+        REQUIRE(File::exists(fallback_file));
+        realm::util::remove_dir(config.path + ".note");
+        realm::util::remove_dir_recursive(fallback_dir);
+    }
+#endif
+
+// Windows doesn't use fifos
+#ifndef _WIN32
+    SECTION("automatically append dir separator to end of fallback path") {
+        std::string fallback_dir = tmp_dir() + "/fallback";
+        realm::util::try_make_dir(fallback_dir);
+        TestFile config;
+        config.fifo_files_fallback_path = fallback_dir;
+        config.schema_version = 1;
+        config.schema = Schema{
+            {"object", {
+                {"value", PropertyType::Int}
+            }},
+        };
+
+        realm::util::make_dir(config.path + ".note");
+        auto realm = Realm::get_shared_realm(config);
+        auto fallback_file = util::format("%1/realm_%2.note", fallback_dir, std::hash<std::string>()(config.path)); // Mirror internal implementation
+        REQUIRE(File::exists(fallback_file));
+        realm::util::remove_dir(config.path + ".note");
+        realm::util::remove_dir_recursive(fallback_dir);
+    }
+#endif
+
     SECTION("should verify that the schema is valid") {
     SECTION("should verify that the schema is valid") {
         config.schema = Schema{
         config.schema = Schema{
             {"object",
             {"object",
@@ -337,8 +385,11 @@ TEST_CASE("SharedRealm: get_shared_realm()") {
 #ifndef _WIN32
 #ifndef _WIN32
     SECTION("should throw when creating the notification pipe fails") {
     SECTION("should throw when creating the notification pipe fails") {
         util::try_make_dir(config.path + ".note");
         util::try_make_dir(config.path + ".note");
+        auto sys_fallback_file = util::format("%1realm_%2.note", SharedGroupOptions::get_sys_tmp_dir(), std::hash<std::string>()(config.path)); // Mirror internal implementation
+        util::try_make_dir(sys_fallback_file);
         REQUIRE_THROWS(Realm::get_shared_realm(config));
         REQUIRE_THROWS(Realm::get_shared_realm(config));
         util::remove_dir(config.path + ".note");
         util::remove_dir(config.path + ".note");
+        util::remove_dir(sys_fallback_file);
     }
     }
 #endif
 #endif
 
 
@@ -1580,7 +1631,7 @@ TEST_CASE("Statistics on Realms") {
     });
     });
 
 
     SECTION("compute_size") {
     SECTION("compute_size") {
-        auto s = r->compute_size();
+        auto s = r->read_group().compute_aggregated_byte_size();
         REQUIRE(s > 0);
         REQUIRE(s > 0);
     }
     }
 }
 }

+ 40 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/results.cpp

@@ -41,6 +41,15 @@
 #include "sync/sync_session.hpp"
 #include "sync/sync_session.hpp"
 #endif
 #endif
 
 
+namespace realm {
+class TestHelper {
+public:
+    static SharedGroup& get_shared_group(SharedRealm const& shared_realm)
+    {
+        return *Realm::Internal::get_shared_group(*shared_realm);
+    }
+};
+}
 
 
 using namespace realm;
 using namespace realm;
 using namespace std::string_literals;
 using namespace std::string_literals;
@@ -1897,7 +1906,7 @@ TEST_CASE("results: notifications after move") {
     }
     }
 }
 }
 
 
-TEST_CASE("results: implicit background notifier") {
+TEST_CASE("results: notifier with no callbacks") {
     _impl::RealmCoordinator::assert_no_open_realms();
     _impl::RealmCoordinator::assert_no_open_realms();
 
 
     InMemoryTestFile config;
     InMemoryTestFile config;
@@ -1917,6 +1926,11 @@ TEST_CASE("results: implicit background notifier") {
     results.last(); // force evaluation and creation of TableView
     results.last(); // force evaluation and creation of TableView
 
 
     SECTION("refresh() does not block due to implicit notifier") {
     SECTION("refresh() does not block due to implicit notifier") {
+        // Create and then immediately remove a callback because
+        // `automatic_change_notifications = false` makes Results not implicitly
+        // create a notifier
+        results.add_notification_callback([](CollectionChangeSet const&, std::exception_ptr) {});
+
         auto r2 = coordinator->get_realm();
         auto r2 = coordinator->get_realm();
         r2->begin_transaction();
         r2->begin_transaction();
         r2->read_group().get_table("class_object")->add_empty_row();
         r2->read_group().get_table("class_object")->add_empty_row();
@@ -1926,6 +1940,8 @@ TEST_CASE("results: implicit background notifier") {
     }
     }
 
 
     SECTION("refresh() does not attempt to deliver stale results") {
     SECTION("refresh() does not attempt to deliver stale results") {
+        results.add_notification_callback([](CollectionChangeSet const&, std::exception_ptr) {});
+
         // Create version 1
         // Create version 1
         r->begin_transaction();
         r->begin_transaction();
         table->add_empty_row();
         table->add_empty_row();
@@ -1942,6 +1958,29 @@ TEST_CASE("results: implicit background notifier") {
         // they're for version 1 and the realm is at 2)
         // they're for version 1 and the realm is at 2)
         r->refresh();
         r->refresh();
     }
     }
+
+    SECTION("should not pin the source version even after the Realm has been closed") {
+        auto r2 = coordinator->get_realm();
+        REQUIRE(r != r2);
+        r->close();
+
+        auto& shared_group = TestHelper::get_shared_group(r2);
+        // There's always at least 2 live versions because the previous version
+        // isn't clean up until the *next* commit
+        REQUIRE(shared_group.get_number_of_versions() == 2);
+
+        auto table = r2->read_group().get_table("class_object");
+
+        r2->begin_transaction();
+        table->add_empty_row();
+        r2->commit_transaction();
+        r2->begin_transaction();
+        table->add_empty_row();
+        r2->commit_transaction();
+
+        // Would now be 3 if the closed Realm is still pinning the version it was at
+        REQUIRE(shared_group.get_number_of_versions() == 2);
+    }
 }
 }
 
 
 TEST_CASE("results: error messages") {
 TEST_CASE("results: error messages") {

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/workflow/build.sh

@@ -27,7 +27,7 @@ if [ "${flavor}" = "android" ]; then
 fi
 fi
 
 
 if [ "${sync}" = "sync" ]; then
 if [ "${sync}" = "sync" ]; then
-    cmake_flags="${cmake_flags} -DREALM_ENABLE_SYNC=1"
+    cmake_flags="${cmake_flags} -DREALM_ENABLE_SYNC=1 -DREALM_ENABLE_SERVER=1"
 fi
 fi
 
 
 cmake ${cmake_flags} ..
 cmake ${cmake_flags} ..

+ 2 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMCollection.h

@@ -18,12 +18,13 @@
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
 
 
+#import <Realm/RLMConstants.h>
 #import <Realm/RLMThreadSafeReference.h>
 #import <Realm/RLMThreadSafeReference.h>
 
 
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
 
 
 @class RLMRealm, RLMResults, RLMSortDescriptor, RLMNotificationToken, RLMCollectionChange;
 @class RLMRealm, RLMResults, RLMSortDescriptor, RLMNotificationToken, RLMCollectionChange;
-typedef NS_ENUM(int32_t, RLMPropertyType);
+typedef RLM_CLOSED_ENUM(int32_t, RLMPropertyType);
 
 
 /**
 /**
  A homogenous collection of Realm-managed objects. Examples of conforming types
  A homogenous collection of Realm-managed objects. Examples of conforming types

+ 10 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMConstants.h

@@ -29,6 +29,15 @@ NS_ASSUME_NONNULL_BEGIN
 #define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(fully_qualified, _) NS_SWIFT_NAME(fully_qualified)
 #define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(fully_qualified, _) NS_SWIFT_NAME(fully_qualified)
 #endif
 #endif
 
 
+// Swift 5 considers NS_ENUM to be "open", meaning there could be values present
+// other than the defined cases (which allows adding more cases later without
+// it being a breaking change), while older versions consider it "closed".
+#ifdef NS_CLOSED_ENUM
+#define RLM_CLOSED_ENUM NS_CLOSED_ENUM
+#else
+#define RLM_CLOSED_ENUM NS_ENUM
+#endif
+
 #if __has_attribute(ns_error_domain) && (!defined(__cplusplus) || !__cplusplus || __cplusplus >= 201103L)
 #if __has_attribute(ns_error_domain) && (!defined(__cplusplus) || !__cplusplus || __cplusplus >= 201103L)
 #define RLM_ERROR_ENUM(type, name, domain) \
 #define RLM_ERROR_ENUM(type, name, domain) \
     _Pragma("clang diagnostic push") \
     _Pragma("clang diagnostic push") \
@@ -47,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 
  For more information, see [Realm Models](https://realm.io/docs/objc/latest/#models).
  For more information, see [Realm Models](https://realm.io/docs/objc/latest/#models).
  */
  */
-typedef NS_ENUM(int32_t, RLMPropertyType) {
+typedef RLM_CLOSED_ENUM(int32_t, RLMPropertyType) {
 
 
 #pragma mark - Primitive types
 #pragma mark - Primitive types
 
 

+ 10 - 15
Carthage/Checkouts/realm-cocoa/Realm/RLMNetworkClient.mm

@@ -310,7 +310,7 @@ didCompleteWithError:(NSError *)error
         return;
         return;
     }
     }
 
 
-    if (![self validateResponse:task.response data:_data error:&error]) {
+    if (NSError *error = [self validateResponse:task.response data:_data]) {
         _completionBlock(error, nil);
         _completionBlock(error, nil);
         return;
         return;
     }
     }
@@ -330,11 +330,10 @@ didCompleteWithError:(NSError *)error
     _completionBlock(nil, (NSDictionary *)json);
     _completionBlock(nil, (NSDictionary *)json);
 }
 }
 
 
-- (BOOL)validateResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError * __autoreleasing *)error {
+- (NSError *)validateResponse:(NSURLResponse *)response data:(NSData *)data {
     if (![response isKindOfClass:[NSHTTPURLResponse class]]) {
     if (![response isKindOfClass:[NSHTTPURLResponse class]]) {
         // FIXME: Provide error message
         // FIXME: Provide error message
-        *error = make_auth_error_bad_response();
-        return NO;
+        return make_auth_error_bad_response();
     }
     }
 
 
     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
@@ -353,28 +352,22 @@ didCompleteWithError:(NSError *)error
                 case RLMSyncAuthErrorExpiredPermissionOffer:
                 case RLMSyncAuthErrorExpiredPermissionOffer:
                 case RLMSyncAuthErrorAmbiguousPermissionOffer:
                 case RLMSyncAuthErrorAmbiguousPermissionOffer:
                 case RLMSyncAuthErrorFileCannotBeShared:
                 case RLMSyncAuthErrorFileCannotBeShared:
-                    *error = make_auth_error(responseModel);
-                    break;
+                    return make_auth_error(responseModel);
                 default:
                 default:
                     // Right now we assume that any codes not described
                     // Right now we assume that any codes not described
                     // above are generic HTTP error codes.
                     // above are generic HTTP error codes.
-                    *error = make_auth_error_http_status(responseModel.status);
-                    break;
+                    return make_auth_error_http_status(responseModel.status);
             }
             }
-        } else {
-            *error = make_auth_error_http_status(httpResponse.statusCode);
         }
         }
-
-        return NO;
+        return make_auth_error_http_status(httpResponse.statusCode);
     }
     }
 
 
     if (!data) {
     if (!data) {
         // FIXME: provide error message
         // FIXME: provide error message
-        *error = make_auth_error_bad_response();
-        return NO;
+        return make_auth_error_bad_response();
     }
     }
 
 
-    return YES;
+    return nil;
 }
 }
 
 
 - (RLMSyncErrorResponseModel *)responseModelFromData:(NSData *)data {
 - (RLMSyncErrorResponseModel *)responseModelFromData:(NSData *)data {
@@ -425,6 +418,8 @@ didCompleteWithError:(NSError *)error
 
 
     // Add the request to a task and start it
     // Add the request to a task and start it
     [[session dataTaskWithRequest:request] resume];
     [[session dataTaskWithRequest:request] resume];
+    // Tell the session to destroy itself once it's done with the request
+    [session finishTasksAndInvalidate];
 }
 }
 @end
 @end
 
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMRealm.mm

@@ -389,7 +389,7 @@ REALM_NOINLINE static void translateSharedGroupOpenException(RLMRealmConfigurati
     configuration = [configuration copy];
     configuration = [configuration copy];
     Realm::Config& config = configuration.config;
     Realm::Config& config = configuration.config;
 
 
-    RLMRealm *realm = [[RLMRealm alloc] initPrivate];
+    RLMRealm *realm = [[self alloc] initPrivate];
     realm->_dynamic = dynamic;
     realm->_dynamic = dynamic;
 
 
     // protects the realm cache and accessors cache
     // protects the realm cache and accessors cache

+ 3 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncConfiguration_Private.h

@@ -18,9 +18,11 @@
 
 
 #import <Realm/RLMSyncConfiguration.h>
 #import <Realm/RLMSyncConfiguration.h>
 
 
+#import <Realm/RLMConstants.h>
+
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
 
 
-typedef NS_ENUM(NSUInteger, RLMSyncStopPolicy) {
+typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncStopPolicy) {
     RLMSyncStopPolicyImmediately,
     RLMSyncStopPolicyImmediately,
     RLMSyncStopPolicyLiveIndefinitely,
     RLMSyncStopPolicyLiveIndefinitely,
     RLMSyncStopPolicyAfterChangesUploaded,
     RLMSyncStopPolicyAfterChangesUploaded,

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h

@@ -23,7 +23,7 @@
 @class RLMSyncSession;
 @class RLMSyncSession;
 
 
 /// An enum representing different levels of sync-related logging that can be configured.
 /// An enum representing different levels of sync-related logging that can be configured.
-typedef NS_ENUM(NSUInteger, RLMSyncLogLevel) {
+typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncLogLevel) {
     /// Nothing will ever be logged.
     /// Nothing will ever be logged.
     RLMSyncLogLevelOff,
     RLMSyncLogLevelOff,
     /// Only fatal errors will be logged.
     /// Only fatal errors will be logged.

+ 2 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncPermission.h

@@ -16,6 +16,7 @@
 //
 //
 ////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////
 
 
+#import <Realm/RLMConstants.h>
 #import <Realm/RLMObject.h>
 #import <Realm/RLMObject.h>
 
 
 @protocol RLMPermission, RLMPermissionUser;
 @protocol RLMPermission, RLMPermissionUser;
@@ -362,7 +363,7 @@ FOUNDATION_EXTERN id RLMPermissionForRole(RLMArray *array, id role);
  access to a Realm can always read from that Realm, and users with
  access to a Realm can always read from that Realm, and users with
  administrative access can always read or write from the Realm.
  administrative access can always read or write from the Realm.
  */
  */
-typedef NS_ENUM(NSUInteger, RLMSyncAccessLevel) {
+typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncAccessLevel) {
     /// No access whatsoever.
     /// No access whatsoever.
     RLMSyncAccessLevelNone          = 0,
     RLMSyncAccessLevelNone          = 0,
     /**
     /**

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSession.h

@@ -57,7 +57,7 @@ typedef NS_ENUM(NSUInteger, RLMSyncConnectionState) {
  Progress notification blocks can be registered on sessions if your app wishes to be informed
  Progress notification blocks can be registered on sessions if your app wishes to be informed
  how many bytes have been uploaded or downloaded, for example to show progress indicator UIs.
  how many bytes have been uploaded or downloaded, for example to show progress indicator UIs.
  */
  */
-typedef NS_ENUM(NSUInteger, RLMSyncProgressDirection) {
+typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncProgressDirection) {
     /// For monitoring upload progress.
     /// For monitoring upload progress.
     RLMSyncProgressDirectionUpload,
     RLMSyncProgressDirectionUpload,
     /// For monitoring download progress.
     /// For monitoring download progress.

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.h

@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
 /**
 /**
  `RLMSyncSubscriptionState` is an enumeration representing the possible state of a sync subscription.
  `RLMSyncSubscriptionState` is an enumeration representing the possible state of a sync subscription.
  */
  */
-typedef NS_ENUM(NSInteger, RLMSyncSubscriptionState) {
+typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
     /**
     /**
      An error occurred while creating the subscription or while the server was processing it.
      An error occurred while creating the subscription or while the server was processing it.
      */
      */

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist

@@ -17,11 +17,11 @@
 	<key>CFBundlePackageType</key>
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
 	<key>CFBundleShortVersionString</key>
-	<string>3.13.1</string>
+	<string>3.14.1</string>
 	<key>CFBundleSignature</key>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<string>????</string>
 	<key>CFBundleVersion</key>
 	<key>CFBundleVersion</key>
-	<string>3.13.1</string>
+	<string>3.14.1</string>
 	<key>NSHumanReadableCopyright</key>
 	<key>NSHumanReadableCopyright</key>
 	<string>Copyright © 2014 Realm. All rights reserved.</string>
 	<string>Copyright © 2014 Realm. All rights reserved.</string>
 	<key>NSPrincipalClass</key>
 	<key>NSPrincipalClass</key>

+ 9 - 1
Carthage/Checkouts/realm-cocoa/Realm/Tests/AsyncTests.mm

@@ -30,6 +30,14 @@
 // A whole bunch of blocks don't use their RLMResults parameter
 // A whole bunch of blocks don't use their RLMResults parameter
 #pragma clang diagnostic ignored "-Wunused-parameter"
 #pragma clang diagnostic ignored "-Wunused-parameter"
 
 
+@interface ManualRefreshRealm : RLMRealm
+@end
+@implementation ManualRefreshRealm
+- (void)verifyNotificationsAreSupported:(__unused bool)isCollection {
+    // The normal implementation of this will reject realms with automatic change notifications disabled
+}
+@end
+
 @interface AsyncTests : RLMTestCase
 @interface AsyncTests : RLMTestCase
 @end
 @end
 
 
@@ -583,7 +591,7 @@
     // Create ten RLMRealm instances, each with a different read version
     // Create ten RLMRealm instances, each with a different read version
     RLMRealm *realms[10];
     RLMRealm *realms[10];
     for (int i = 0; i < 10; ++i) {
     for (int i = 0; i < 10; ++i) {
-        RLMRealm *realm = realms[i] = [RLMRealm realmWithConfiguration:config error:nil];
+        RLMRealm *realm = realms[i] = [ManualRefreshRealm realmWithConfiguration:config error:nil];
         [realm transactionWithBlock:^{
         [realm transactionWithBlock:^{
             [IntObject createInRealm:realm withValue:@[@(i)]];
             [IntObject createInRealm:realm withValue:@[@(i)]];
         }];
         }];

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m

@@ -378,7 +378,7 @@
     else {
     else {
         RLMRealm *realm = RLMRealm.defaultRealm;
         RLMRealm *realm = RLMRealm.defaultRealm;
         [realm beginWriteTransaction];
         [realm beginWriteTransaction];
-        abort();
+        _Exit(1);
     }
     }
 }
 }
 
 
@@ -394,7 +394,7 @@
     else {
     else {
         RLMRealm *realm = RLMRealm.defaultRealm;
         RLMRealm *realm = RLMRealm.defaultRealm;
         [realm beginWriteTransaction];
         [realm beginWriteTransaction];
-        abort();
+        _Exit(1);
     }
     }
 }
 }
 
 

+ 6 - 0
Carthage/Checkouts/realm-cocoa/Realm/Tests/RealmTests.mm

@@ -1779,10 +1779,16 @@
     assert(![manager fileExistsAtPath:fifoURL.path]);
     assert(![manager fileExistsAtPath:fifoURL.path]);
     [manager createDirectoryAtPath:fifoURL.path withIntermediateDirectories:YES attributes:nil error:nil];
     [manager createDirectoryAtPath:fifoURL.path withIntermediateDirectories:YES attributes:nil error:nil];
 
 
+    // Ensure that it doesn't try to fall back to putting it in the temp directory
+    auto oldTempDir = realm::SharedGroupOptions::get_sys_tmp_dir();
+    realm::SharedGroupOptions::set_sys_tmp_dir("");
+
     NSError *error;
     NSError *error;
     XCTAssertNil([RLMRealm realmWithConfiguration:configuration error:&error], @"Should not have been able to open FIFO");
     XCTAssertNil([RLMRealm realmWithConfiguration:configuration error:&error], @"Should not have been able to open FIFO");
     XCTAssertNotNil(error);
     XCTAssertNotNil(error);
     RLMValidateRealmError(error, RLMErrorFileAccess, @"Is a directory", nil);
     RLMValidateRealmError(error, RLMErrorFileAccess, @"Is a directory", nil);
+
+    realm::SharedGroupOptions::set_sys_tmp_dir(std::move(oldTempDir));
 }
 }
 #endif
 #endif
 
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/RealmSwift/Object.swift

@@ -269,7 +269,7 @@ open class Object: RLMObjectBase, ThreadConfined, RealmCollectionValue {
 
 
      Objects are considered the same if and only if they are both managed by the same
      Objects are considered the same if and only if they are both managed by the same
      Realm and point to the same underlying object in the database.
      Realm and point to the same underlying object in the database.
-     
+
      - note: Equality comparison is implemented by `isEqual(_:)`. If the object type
      - note: Equality comparison is implemented by `isEqual(_:)`. If the object type
              is defined with a primary key, `isEqual(_:)` behaves identically to this
              is defined with a primary key, `isEqual(_:)` behaves identically to this
              method. If the object type is not defined with a primary key,
              method. If the object type is not defined with a primary key,

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