Commit 1d417bd6 authored by 汪洋's avatar 汪洋

删除没有必要跟踪的文件

parent 27ef2100
......@@ -30,4 +30,4 @@ Carthage
# Note: if you ignore the Pods directory, make sure to uncomment
# `pod install` in .travis.yml
#
# Pods/
Pods/
{
"name": "GMCache",
"version": "0.1.0",
"summary": "缓存",
"homepage": "http://git.gengmei.cc/gengmeiios/GMCache",
"license": "MIT",
"authors": {
"wangyang": "wangyang@wanmeizhensuo.com"
},
"source": {
"git": "git@git.gengmei.cc:gengmeiios/GMCache.git",
"tag": "0.1.0"
},
"platforms": {
"ios": "8.0"
},
"source_files": "GMCache/Classes/**/*",
"public_header_files": "GMCache/Classes/WMCacheService.h",
"dependencies": {
"TMCache": [
"~> 2.1.0"
]
}
}
PODS:
- GMCache (0.1.0):
- TMCache (~> 2.1.0)
- TMCache (2.1.0)
DEPENDENCIES:
- GMCache (from `../`)
EXTERNAL SOURCES:
GMCache:
:path: "../"
SPEC CHECKSUMS:
GMCache: de23cd2fbf136d43b04baca5668602f86c023986
TMCache: 95ebcc9b3c7e90fb5fd8fc3036cba3aa781c9bed
PODFILE CHECKSUM: 58e501ebf3387a7de685a2862f8cd523abeebbb2
COCOAPODS: 1.1.1
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0E16F6F1263805586E06E2C89AD72878 /* TMCache-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 32892A54C073C84EB376D8AC4B9434E7 /* TMCache-dummy.m */; };
14E9E0A391C71BC9348730B06C0FCCD6 /* TMCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 713B926C3BB483B1F14D868E2BE4E3EE /* TMCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; };
18831D96875A8EA064FB428F0BD6A7AC /* TMDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 31486C459F463DD98F14083CE8031380 /* TMDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F6BED4324132F5FC433550FE73E1932 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F73C37C553FC33A32C7153975CCDE570 /* Foundation.framework */; };
234EB78FB9E1AC126A65B6E67A019B5E /* WMDocumentCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CF97498E7934A1CD4FFF0EFB64457227 /* WMDocumentCache.m */; };
2E86531BC0E9C1D5580F05D9973D46E2 /* TMCache-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F1449381B7D307BC962D56637E464E2F /* TMCache-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
4092902BBC13AA14A2E0D72A6457457E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F73C37C553FC33A32C7153975CCDE570 /* Foundation.framework */; };
50FDC49223E074EC07E7A06BC841978A /* TMMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B7FBE4075662277B469A4E6F12B0C2 /* TMMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
53CE43F72ECB368E174EFD157DE9373A /* GMCache-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8797BA1E36200FEAB6FA78C04EDD68AC /* GMCache-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
5882855394E8892865F0D614BA905956 /* TMCacheBackgroundTaskManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FB3646010E4384047765016B6D0CEF8C /* TMCacheBackgroundTaskManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
68E5460D211224A50309A7D62D9DF2C5 /* TMDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A2CEF2EF11436F9C1D3D4895523E629F /* TMDiskCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; };
6EBEFB94CFD088BD32DA04266CC9F034 /* TMCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 07C85208817F198446133A76F73297AB /* TMCache.framework */; };
705FC7CD6627A5DDCC78323D4471BB04 /* Pods-GMCache_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 56B5D7E5D5D846254DE804E3A6A66265 /* Pods-GMCache_Tests-dummy.m */; };
7416226E9126B4E0698A1157ED10013C /* Pods-GMCache_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DFA5FBC8248DE021F07361EC811D3693 /* Pods-GMCache_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
7BFDC6A46C331378B1872F4A3D0EFEC6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F73C37C553FC33A32C7153975CCDE570 /* Foundation.framework */; };
89773E290C9C95C7F2DF22FA35C43140 /* Pods-GMCache_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6274F1E7CF73F8A037FFA005CBFA1C18 /* Pods-GMCache_Example-dummy.m */; };
8A723221AF4F55A2F7DFA9266E7461AE /* Pods-GMCache_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AF4A3068E0819D7ADA06E914BC2EF879 /* Pods-GMCache_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
90124FEFBC6E9428589A07DD33B2BE3A /* WMDocumentCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D9B3A116DC1EB3DAD2526D0673A5F585 /* WMDocumentCache.h */; settings = {ATTRIBUTES = (Project, ); }; };
A1AB9541B51137BB502E748C3F983C4B /* WMCacheService.h in Headers */ = {isa = PBXBuildFile; fileRef = 426DC95E82F9AEA5038620EFFD4B94DC /* WMCacheService.h */; settings = {ATTRIBUTES = (Public, ); }; };
BA7C05CCB03912A283C1EFC6203B19A0 /* WMCacheService.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF6450FC86662DBA581429F25F74ECF /* WMCacheService.m */; };
E28CCC422BAA9EF68B585E53A5AEF58E /* GMCache-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 41F2D446831ABF8C05C36697808A2889 /* GMCache-dummy.m */; };
F2865E72BBBB9AB236859D9F8AB5E784 /* TMCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6FED8D39C6045E1EBAF04BB63AC7A2 /* TMCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
F553F7A2925B21418E0B0D0DFD1799D4 /* TMMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ECF40B8A894B1CEC561C49DB6B8DA622 /* TMMemoryCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; };
FACCE33F8385DB124B4F8DCEE3B85BF8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F73C37C553FC33A32C7153975CCDE570 /* Foundation.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3BB45710B0EBBE79AAD7FF7A81556D04 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3CEC93D360D00FDE7FB0084DC2464EAD;
remoteInfo = GMCache;
};
8265F31D007BF1C48D7FEAD73B42D827 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 28923DD1C76A98F6675D115FD930DB64;
remoteInfo = TMCache;
};
F61ECE6BCC033458BCA3BFC6291505E1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 28923DD1C76A98F6675D115FD930DB64;
remoteInfo = TMCache;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
07C85208817F198446133A76F73297AB /* TMCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TMCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0C41647F2DEDFC8847C5B4397ED9A8FB /* Pods-GMCache_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GMCache_Example.debug.xcconfig"; sourceTree = "<group>"; };
108A6E30490A2968F226884AFE5D768F /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1DE476B37A32AA64A88F193EE884CD91 /* Pods-GMCache_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-GMCache_Example.modulemap"; sourceTree = "<group>"; };
2D24FDC103DDFCCC646F0970D32EBE14 /* GMCache.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = GMCache.modulemap; sourceTree = "<group>"; };
31486C459F463DD98F14083CE8031380 /* TMDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TMDiskCache.h; path = TMCache/TMDiskCache.h; sourceTree = "<group>"; };
32892A54C073C84EB376D8AC4B9434E7 /* TMCache-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "TMCache-dummy.m"; sourceTree = "<group>"; };
346FD46F1B687CDF045A3DDA5298E673 /* GMCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GMCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3856560516A203CDF9A7B0E0D28705C3 /* Pods-GMCache_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-GMCache_Example-acknowledgements.markdown"; sourceTree = "<group>"; };
39D88CD11F510B75CED9FB82CAFF53D0 /* Pods-GMCache_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GMCache_Tests.debug.xcconfig"; sourceTree = "<group>"; };
3BF6450FC86662DBA581429F25F74ECF /* WMCacheService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = WMCacheService.m; sourceTree = "<group>"; };
3CF1BF681262D009AEACA342F88BB99D /* Pods-GMCache_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GMCache_Tests-resources.sh"; sourceTree = "<group>"; };
41F2D446831ABF8C05C36697808A2889 /* GMCache-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GMCache-dummy.m"; sourceTree = "<group>"; };
426DC95E82F9AEA5038620EFFD4B94DC /* WMCacheService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = WMCacheService.h; sourceTree = "<group>"; };
433750D5DEACC0626089890B07734043 /* Pods-GMCache_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GMCache_Example-acknowledgements.plist"; sourceTree = "<group>"; };
556CBEAAD9D688D4D2BE81EC05992686 /* Pods-GMCache_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GMCache_Tests.release.xcconfig"; sourceTree = "<group>"; };
56B5D7E5D5D846254DE804E3A6A66265 /* Pods-GMCache_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GMCache_Tests-dummy.m"; sourceTree = "<group>"; };
57F28D313B31A7ABFB2806FF7CE7DD87 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
589BFCB9EF9F9361FCCC79AF389A19D0 /* TMCache.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = TMCache.xcconfig; sourceTree = "<group>"; };
6274F1E7CF73F8A037FFA005CBFA1C18 /* Pods-GMCache_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GMCache_Example-dummy.m"; sourceTree = "<group>"; };
713B926C3BB483B1F14D868E2BE4E3EE /* TMCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TMCache.m; path = TMCache/TMCache.m; sourceTree = "<group>"; };
73B7FBE4075662277B469A4E6F12B0C2 /* TMMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TMMemoryCache.h; path = TMCache/TMMemoryCache.h; sourceTree = "<group>"; };
74FE66305EE553CAD8F2143E387642BF /* Pods_GMCache_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GMCache_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7D44D58D3FE4A3704CE25E139AA9F986 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7E2CA15C680F5DB955E492BA051BACFF /* Pods-GMCache_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GMCache_Example-frameworks.sh"; sourceTree = "<group>"; };
8797BA1E36200FEAB6FA78C04EDD68AC /* GMCache-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GMCache-umbrella.h"; sourceTree = "<group>"; };
8E6607154B8749248DAD5A6B470EB774 /* TMCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TMCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
92BE0E1332E5C67567899B7CC6FE3BA3 /* Pods-GMCache_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-GMCache_Tests-acknowledgements.markdown"; sourceTree = "<group>"; };
93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
9B8C129E9B2BB8FE18771CF2866D4808 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9C6FED8D39C6045E1EBAF04BB63AC7A2 /* TMCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TMCache.h; path = TMCache/TMCache.h; sourceTree = "<group>"; };
A177BF87ABE068C2BC02F4CB52F97A04 /* Pods-GMCache_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-GMCache_Tests.modulemap"; sourceTree = "<group>"; };
A2CEF2EF11436F9C1D3D4895523E629F /* TMDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TMDiskCache.m; path = TMCache/TMDiskCache.m; sourceTree = "<group>"; };
AF4A3068E0819D7ADA06E914BC2EF879 /* Pods-GMCache_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GMCache_Tests-umbrella.h"; sourceTree = "<group>"; };
C2C40A2022E2ACC897DE9BB57D381C4D /* TMCache-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TMCache-prefix.pch"; sourceTree = "<group>"; };
C8F0B63A46D21F37B1733BFE054D7222 /* Pods-GMCache_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GMCache_Example-resources.sh"; sourceTree = "<group>"; };
CF7DC6871BAE8526395FF403C53C9AD6 /* Pods-GMCache_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GMCache_Example.release.xcconfig"; sourceTree = "<group>"; };
CF97498E7934A1CD4FFF0EFB64457227 /* WMDocumentCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = WMDocumentCache.m; sourceTree = "<group>"; };
D9B3A116DC1EB3DAD2526D0673A5F585 /* WMDocumentCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = WMDocumentCache.h; sourceTree = "<group>"; };
DEE0F68D595B5E2FA076F8428EC85C03 /* Pods_GMCache_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GMCache_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DFA5FBC8248DE021F07361EC811D3693 /* Pods-GMCache_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GMCache_Example-umbrella.h"; sourceTree = "<group>"; };
E15BC9BF38D9FB30A65C3A269B382A63 /* GMCache.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GMCache.xcconfig; sourceTree = "<group>"; };
ECF40B8A894B1CEC561C49DB6B8DA622 /* TMMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TMMemoryCache.m; path = TMCache/TMMemoryCache.m; sourceTree = "<group>"; };
F1449381B7D307BC962D56637E464E2F /* TMCache-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TMCache-umbrella.h"; sourceTree = "<group>"; };
F4D347C0ECEC19004073FE3275F4D10B /* Pods-GMCache_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GMCache_Tests-acknowledgements.plist"; sourceTree = "<group>"; };
F73C37C553FC33A32C7153975CCDE570 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
FA22EA87C35F53EA0B9FFFC569079CB5 /* Pods-GMCache_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GMCache_Tests-frameworks.sh"; sourceTree = "<group>"; };
FB3646010E4384047765016B6D0CEF8C /* TMCacheBackgroundTaskManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TMCacheBackgroundTaskManager.h; path = TMCache/TMCacheBackgroundTaskManager.h; sourceTree = "<group>"; };
FB52CAC60FA56923F670E7F5DE9B71D3 /* TMCache.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = TMCache.modulemap; sourceTree = "<group>"; };
FF9E92268009168FA04BA6FC382BDDA1 /* GMCache-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GMCache-prefix.pch"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
030A56EA5CED2ABDC79FD40E1F76CD30 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1F6BED4324132F5FC433550FE73E1932 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1364738C84F9F401A2495BD7797F3204 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4092902BBC13AA14A2E0D72A6457457E /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2B6DF709527792E5B4969FBF7217506B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7BFDC6A46C331378B1872F4A3D0EFEC6 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
39222624C45ABC402D65E6F304336871 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FACCE33F8385DB124B4F8DCEE3B85BF8 /* Foundation.framework in Frameworks */,
6EBEFB94CFD088BD32DA04266CC9F034 /* TMCache.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1E21EF65D458E459D1B58725AA90C961 /* Support Files */ = {
isa = PBXGroup;
children = (
2D24FDC103DDFCCC646F0970D32EBE14 /* GMCache.modulemap */,
E15BC9BF38D9FB30A65C3A269B382A63 /* GMCache.xcconfig */,
41F2D446831ABF8C05C36697808A2889 /* GMCache-dummy.m */,
FF9E92268009168FA04BA6FC382BDDA1 /* GMCache-prefix.pch */,
8797BA1E36200FEAB6FA78C04EDD68AC /* GMCache-umbrella.h */,
9B8C129E9B2BB8FE18771CF2866D4808 /* Info.plist */,
);
name = "Support Files";
path = "Example/Pods/Target Support Files/GMCache";
sourceTree = "<group>";
};
4A300C729EBDE07BE9763DDB1E9BA16A /* Products */ = {
isa = PBXGroup;
children = (
346FD46F1B687CDF045A3DDA5298E673 /* GMCache.framework */,
74FE66305EE553CAD8F2143E387642BF /* Pods_GMCache_Example.framework */,
DEE0F68D595B5E2FA076F8428EC85C03 /* Pods_GMCache_Tests.framework */,
8E6607154B8749248DAD5A6B470EB774 /* TMCache.framework */,
);
name = Products;
sourceTree = "<group>";
};
540F4C5D027B9964717DF42075A7E0AC /* Development Pods */ = {
isa = PBXGroup;
children = (
74FB27A2F4307F45988B7BA693E75A69 /* GMCache */,
);
name = "Development Pods";
sourceTree = "<group>";
};
545AAD822800AB3F8315BACDD86C9092 /* GMCache */ = {
isa = PBXGroup;
children = (
F81F2FF95F8EFBA322E2707C96AF04EA /* Classes */,
);
path = GMCache;
sourceTree = "<group>";
};
74FB27A2F4307F45988B7BA693E75A69 /* GMCache */ = {
isa = PBXGroup;
children = (
545AAD822800AB3F8315BACDD86C9092 /* GMCache */,
1E21EF65D458E459D1B58725AA90C961 /* Support Files */,
);
name = GMCache;
path = ../..;
sourceTree = "<group>";
};
7D81E69C95966E4CC8D42E31BFF1F771 /* Support Files */ = {
isa = PBXGroup;
children = (
57F28D313B31A7ABFB2806FF7CE7DD87 /* Info.plist */,
FB52CAC60FA56923F670E7F5DE9B71D3 /* TMCache.modulemap */,
589BFCB9EF9F9361FCCC79AF389A19D0 /* TMCache.xcconfig */,
32892A54C073C84EB376D8AC4B9434E7 /* TMCache-dummy.m */,
C2C40A2022E2ACC897DE9BB57D381C4D /* TMCache-prefix.pch */,
F1449381B7D307BC962D56637E464E2F /* TMCache-umbrella.h */,
);
name = "Support Files";
path = "../Target Support Files/TMCache";
sourceTree = "<group>";
};
7DB346D0F39D3F0E887471402A8071AB = {
isa = PBXGroup;
children = (
93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */,
540F4C5D027B9964717DF42075A7E0AC /* Development Pods */,
E7006391D8A6E512B514308458AAD03C /* Frameworks */,
ADC4AC44FE991A1F54076D56F9FAE621 /* Pods */,
4A300C729EBDE07BE9763DDB1E9BA16A /* Products */,
A230864DD969F86EA1CC00ACAA017142 /* Targets Support Files */,
);
sourceTree = "<group>";
};
A230864DD969F86EA1CC00ACAA017142 /* Targets Support Files */ = {
isa = PBXGroup;
children = (
B622921743818590D182DC1D4F437E03 /* Pods-GMCache_Example */,
E787943E89402E8CF9AB2F439FF09326 /* Pods-GMCache_Tests */,
);
name = "Targets Support Files";
sourceTree = "<group>";
};
ADC4AC44FE991A1F54076D56F9FAE621 /* Pods */ = {
isa = PBXGroup;
children = (
E89E4A1A5CD0A8BB875B7C3DE1202AAE /* TMCache */,
);
name = Pods;
sourceTree = "<group>";
};
B622921743818590D182DC1D4F437E03 /* Pods-GMCache_Example */ = {
isa = PBXGroup;
children = (
108A6E30490A2968F226884AFE5D768F /* Info.plist */,
1DE476B37A32AA64A88F193EE884CD91 /* Pods-GMCache_Example.modulemap */,
3856560516A203CDF9A7B0E0D28705C3 /* Pods-GMCache_Example-acknowledgements.markdown */,
433750D5DEACC0626089890B07734043 /* Pods-GMCache_Example-acknowledgements.plist */,
6274F1E7CF73F8A037FFA005CBFA1C18 /* Pods-GMCache_Example-dummy.m */,
7E2CA15C680F5DB955E492BA051BACFF /* Pods-GMCache_Example-frameworks.sh */,
C8F0B63A46D21F37B1733BFE054D7222 /* Pods-GMCache_Example-resources.sh */,
DFA5FBC8248DE021F07361EC811D3693 /* Pods-GMCache_Example-umbrella.h */,
0C41647F2DEDFC8847C5B4397ED9A8FB /* Pods-GMCache_Example.debug.xcconfig */,
CF7DC6871BAE8526395FF403C53C9AD6 /* Pods-GMCache_Example.release.xcconfig */,
);
name = "Pods-GMCache_Example";
path = "Target Support Files/Pods-GMCache_Example";
sourceTree = "<group>";
};
DCCA6EB38B133BEE58089C33A2468992 /* iOS */ = {
isa = PBXGroup;
children = (
F73C37C553FC33A32C7153975CCDE570 /* Foundation.framework */,
);
name = iOS;
sourceTree = "<group>";
};
E7006391D8A6E512B514308458AAD03C /* Frameworks */ = {
isa = PBXGroup;
children = (
07C85208817F198446133A76F73297AB /* TMCache.framework */,
DCCA6EB38B133BEE58089C33A2468992 /* iOS */,
);
name = Frameworks;
sourceTree = "<group>";
};
E787943E89402E8CF9AB2F439FF09326 /* Pods-GMCache_Tests */ = {
isa = PBXGroup;
children = (
7D44D58D3FE4A3704CE25E139AA9F986 /* Info.plist */,
A177BF87ABE068C2BC02F4CB52F97A04 /* Pods-GMCache_Tests.modulemap */,
92BE0E1332E5C67567899B7CC6FE3BA3 /* Pods-GMCache_Tests-acknowledgements.markdown */,
F4D347C0ECEC19004073FE3275F4D10B /* Pods-GMCache_Tests-acknowledgements.plist */,
56B5D7E5D5D846254DE804E3A6A66265 /* Pods-GMCache_Tests-dummy.m */,
FA22EA87C35F53EA0B9FFFC569079CB5 /* Pods-GMCache_Tests-frameworks.sh */,
3CF1BF681262D009AEACA342F88BB99D /* Pods-GMCache_Tests-resources.sh */,
AF4A3068E0819D7ADA06E914BC2EF879 /* Pods-GMCache_Tests-umbrella.h */,
39D88CD11F510B75CED9FB82CAFF53D0 /* Pods-GMCache_Tests.debug.xcconfig */,
556CBEAAD9D688D4D2BE81EC05992686 /* Pods-GMCache_Tests.release.xcconfig */,
);
name = "Pods-GMCache_Tests";
path = "Target Support Files/Pods-GMCache_Tests";
sourceTree = "<group>";
};
E89E4A1A5CD0A8BB875B7C3DE1202AAE /* TMCache */ = {
isa = PBXGroup;
children = (
9C6FED8D39C6045E1EBAF04BB63AC7A2 /* TMCache.h */,
713B926C3BB483B1F14D868E2BE4E3EE /* TMCache.m */,
FB3646010E4384047765016B6D0CEF8C /* TMCacheBackgroundTaskManager.h */,
31486C459F463DD98F14083CE8031380 /* TMDiskCache.h */,
A2CEF2EF11436F9C1D3D4895523E629F /* TMDiskCache.m */,
73B7FBE4075662277B469A4E6F12B0C2 /* TMMemoryCache.h */,
ECF40B8A894B1CEC561C49DB6B8DA622 /* TMMemoryCache.m */,
7D81E69C95966E4CC8D42E31BFF1F771 /* Support Files */,
);
path = TMCache;
sourceTree = "<group>";
};
F81F2FF95F8EFBA322E2707C96AF04EA /* Classes */ = {
isa = PBXGroup;
children = (
426DC95E82F9AEA5038620EFFD4B94DC /* WMCacheService.h */,
3BF6450FC86662DBA581429F25F74ECF /* WMCacheService.m */,
D9B3A116DC1EB3DAD2526D0673A5F585 /* WMDocumentCache.h */,
CF97498E7934A1CD4FFF0EFB64457227 /* WMDocumentCache.m */,
);
path = Classes;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
4A64B4A69C51F780E90BC4646D1286D2 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
53CE43F72ECB368E174EFD157DE9373A /* GMCache-umbrella.h in Headers */,
A1AB9541B51137BB502E748C3F983C4B /* WMCacheService.h in Headers */,
90124FEFBC6E9428589A07DD33B2BE3A /* WMDocumentCache.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8F43A99DF67163CBCF6E654310C2D15C /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
2E86531BC0E9C1D5580F05D9973D46E2 /* TMCache-umbrella.h in Headers */,
F2865E72BBBB9AB236859D9F8AB5E784 /* TMCache.h in Headers */,
5882855394E8892865F0D614BA905956 /* TMCacheBackgroundTaskManager.h in Headers */,
18831D96875A8EA064FB428F0BD6A7AC /* TMDiskCache.h in Headers */,
50FDC49223E074EC07E7A06BC841978A /* TMMemoryCache.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C10D3B6609252FCC96A808E439F820E0 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
7416226E9126B4E0698A1157ED10013C /* Pods-GMCache_Example-umbrella.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F1CB1A55CB8556763CB1B7464AE01893 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8A723221AF4F55A2F7DFA9266E7461AE /* Pods-GMCache_Tests-umbrella.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
1C695E83E5937B7887B28B6F219A5FE1 /* Pods-GMCache_Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A6A64CDD900B193F019D101CF924125F /* Build configuration list for PBXNativeTarget "Pods-GMCache_Tests" */;
buildPhases = (
DB87AB81E878ED9357DB2F7739AE090C /* Sources */,
1364738C84F9F401A2495BD7797F3204 /* Frameworks */,
F1CB1A55CB8556763CB1B7464AE01893 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = "Pods-GMCache_Tests";
productName = "Pods-GMCache_Tests";
productReference = DEE0F68D595B5E2FA076F8428EC85C03 /* Pods_GMCache_Tests.framework */;
productType = "com.apple.product-type.framework";
};
28923DD1C76A98F6675D115FD930DB64 /* TMCache */ = {
isa = PBXNativeTarget;
buildConfigurationList = DE97E39565993D44C96E2B6A296C75C1 /* Build configuration list for PBXNativeTarget "TMCache" */;
buildPhases = (
A943B08997CB0007DB9BDCDE4F804948 /* Sources */,
2B6DF709527792E5B4969FBF7217506B /* Frameworks */,
8F43A99DF67163CBCF6E654310C2D15C /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = TMCache;
productName = TMCache;
productReference = 8E6607154B8749248DAD5A6B470EB774 /* TMCache.framework */;
productType = "com.apple.product-type.framework";
};
3CEC93D360D00FDE7FB0084DC2464EAD /* GMCache */ = {
isa = PBXNativeTarget;
buildConfigurationList = 166DCF40E1B8185EE209CEB075567FB9 /* Build configuration list for PBXNativeTarget "GMCache" */;
buildPhases = (
EC5568AD8A98604757BE2787CC99E089 /* Sources */,
39222624C45ABC402D65E6F304336871 /* Frameworks */,
4A64B4A69C51F780E90BC4646D1286D2 /* Headers */,
);
buildRules = (
);
dependencies = (
A838F00D018EAE517E0236D5AB254ABB /* PBXTargetDependency */,
);
name = GMCache;
productName = GMCache;
productReference = 346FD46F1B687CDF045A3DDA5298E673 /* GMCache.framework */;
productType = "com.apple.product-type.framework";
};
66BB126A2D51C02B93DEB0A53BEF2F1E /* Pods-GMCache_Example */ = {
isa = PBXNativeTarget;
buildConfigurationList = A162675233048ABBBD41793146762854 /* Build configuration list for PBXNativeTarget "Pods-GMCache_Example" */;
buildPhases = (
2DA5C39358F7BA55A72860DFED512905 /* Sources */,
030A56EA5CED2ABDC79FD40E1F76CD30 /* Frameworks */,
C10D3B6609252FCC96A808E439F820E0 /* Headers */,
);
buildRules = (
);
dependencies = (
66F263AF1B0ABE546C8EFF05FA883F3A /* PBXTargetDependency */,
8301154341C16443E7F30A078B66CFD5 /* PBXTargetDependency */,
);
name = "Pods-GMCache_Example";
productName = "Pods-GMCache_Example";
productReference = 74FE66305EE553CAD8F2143E387642BF /* Pods_GMCache_Example.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D41D8CD98F00B204E9800998ECF8427E /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0700;
};
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 7DB346D0F39D3F0E887471402A8071AB;
productRefGroup = 4A300C729EBDE07BE9763DDB1E9BA16A /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
3CEC93D360D00FDE7FB0084DC2464EAD /* GMCache */,
66BB126A2D51C02B93DEB0A53BEF2F1E /* Pods-GMCache_Example */,
1C695E83E5937B7887B28B6F219A5FE1 /* Pods-GMCache_Tests */,
28923DD1C76A98F6675D115FD930DB64 /* TMCache */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
2DA5C39358F7BA55A72860DFED512905 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
89773E290C9C95C7F2DF22FA35C43140 /* Pods-GMCache_Example-dummy.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A943B08997CB0007DB9BDCDE4F804948 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E16F6F1263805586E06E2C89AD72878 /* TMCache-dummy.m in Sources */,
14E9E0A391C71BC9348730B06C0FCCD6 /* TMCache.m in Sources */,
68E5460D211224A50309A7D62D9DF2C5 /* TMDiskCache.m in Sources */,
F553F7A2925B21418E0B0D0DFD1799D4 /* TMMemoryCache.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DB87AB81E878ED9357DB2F7739AE090C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
705FC7CD6627A5DDCC78323D4471BB04 /* Pods-GMCache_Tests-dummy.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
EC5568AD8A98604757BE2787CC99E089 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E28CCC422BAA9EF68B585E53A5AEF58E /* GMCache-dummy.m in Sources */,
BA7C05CCB03912A283C1EFC6203B19A0 /* WMCacheService.m in Sources */,
234EB78FB9E1AC126A65B6E67A019B5E /* WMDocumentCache.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
66F263AF1B0ABE546C8EFF05FA883F3A /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = GMCache;
target = 3CEC93D360D00FDE7FB0084DC2464EAD /* GMCache */;
targetProxy = 3BB45710B0EBBE79AAD7FF7A81556D04 /* PBXContainerItemProxy */;
};
8301154341C16443E7F30A078B66CFD5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = TMCache;
target = 28923DD1C76A98F6675D115FD930DB64 /* TMCache */;
targetProxy = 8265F31D007BF1C48D7FEAD73B42D827 /* PBXContainerItemProxy */;
};
A838F00D018EAE517E0236D5AB254ABB /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = TMCache;
target = 28923DD1C76A98F6675D115FD930DB64 /* TMCache */;
targetProxy = F61ECE6BCC033458BCA3BFC6291505E1 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
0773A7E376894A02733B080832003FF4 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0C41647F2DEDFC8847C5B4397ED9A8FB /* Pods-GMCache_Example.debug.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = "Target Support Files/Pods-GMCache_Example/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACH_O_TYPE = staticlib;
MODULEMAP_FILE = "Target Support Files/Pods-GMCache_Example/Pods-GMCache_Example.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = Pods_GMCache_Example;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
5B53986F69DFC610826CEE68531C85EF /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 589BFCB9EF9F9361FCCC79AF389A19D0 /* TMCache.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "Target Support Files/TMCache/TMCache-prefix.pch";
INFOPLIST_FILE = "Target Support Files/TMCache/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/TMCache/TMCache.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = TMCache;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
64B41BA26A4757144C9822528DAE55DA /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 556CBEAAD9D688D4D2BE81EC05992686 /* Pods-GMCache_Tests.release.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = "Target Support Files/Pods-GMCache_Tests/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACH_O_TYPE = staticlib;
MODULEMAP_FILE = "Target Support Files/Pods-GMCache_Tests/Pods-GMCache_Tests.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = Pods_GMCache_Tests;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
7A3ADD4FAFFBC6501B5399742CD76835 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 589BFCB9EF9F9361FCCC79AF389A19D0 /* TMCache.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "Target Support Files/TMCache/TMCache-prefix.pch";
INFOPLIST_FILE = "Target Support Files/TMCache/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/TMCache/TMCache.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = TMCache;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
8DED8AD26D381A6ACFF202E5217EC498 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGNING_REQUIRED = NO;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = (
"POD_CONFIGURATION_RELEASE=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
STRIP_INSTALLED_PRODUCT = NO;
SYMROOT = "${SRCROOT}/../build";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
9E1E4E48AF2EAB23169E611BF694090A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGNING_REQUIRED = NO;
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"POD_CONFIGURATION_DEBUG=1",
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
ONLY_ACTIVE_ARCH = YES;
PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
STRIP_INSTALLED_PRODUCT = NO;
SYMROOT = "${SRCROOT}/../build";
};
name = Debug;
};
B816022EBA7F00190B88C3AD0FB40A65 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 39D88CD11F510B75CED9FB82CAFF53D0 /* Pods-GMCache_Tests.debug.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = "Target Support Files/Pods-GMCache_Tests/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACH_O_TYPE = staticlib;
MODULEMAP_FILE = "Target Support Files/Pods-GMCache_Tests/Pods-GMCache_Tests.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = Pods_GMCache_Tests;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
CE4035AC9DDC23FA965108A4D0DBB5A4 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E15BC9BF38D9FB30A65C3A269B382A63 /* GMCache.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "Target Support Files/GMCache/GMCache-prefix.pch";
INFOPLIST_FILE = "Target Support Files/GMCache/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/GMCache/GMCache.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = GMCache;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
D431B342976C5521FA082EFE41E765C9 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E15BC9BF38D9FB30A65C3A269B382A63 /* GMCache.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "Target Support Files/GMCache/GMCache-prefix.pch";
INFOPLIST_FILE = "Target Support Files/GMCache/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = "Target Support Files/GMCache/GMCache.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = GMCache;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
E05208FA7214112D92C2B5CE9164880D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = CF7DC6871BAE8526395FF403C53C9AD6 /* Pods-GMCache_Example.release.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = "Target Support Files/Pods-GMCache_Example/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACH_O_TYPE = staticlib;
MODULEMAP_FILE = "Target Support Files/Pods-GMCache_Example/Pods-GMCache_Example.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
OTHER_LIBTOOLFLAGS = "";
PODS_ROOT = "$(SRCROOT)";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = Pods_GMCache_Example;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
166DCF40E1B8185EE209CEB075567FB9 /* Build configuration list for PBXNativeTarget "GMCache" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D431B342976C5521FA082EFE41E765C9 /* Debug */,
CE4035AC9DDC23FA965108A4D0DBB5A4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E1E4E48AF2EAB23169E611BF694090A /* Debug */,
8DED8AD26D381A6ACFF202E5217EC498 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A162675233048ABBBD41793146762854 /* Build configuration list for PBXNativeTarget "Pods-GMCache_Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0773A7E376894A02733B080832003FF4 /* Debug */,
E05208FA7214112D92C2B5CE9164880D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A6A64CDD900B193F019D101CF924125F /* Build configuration list for PBXNativeTarget "Pods-GMCache_Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B816022EBA7F00190B88C3AD0FB40A65 /* Debug */,
64B41BA26A4757144C9822528DAE55DA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DE97E39565993D44C96E2B6A296C75C1 /* Build configuration list for PBXNativeTarget "TMCache" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5B53986F69DFC610826CEE68531C85EF /* Debug */,
7A3ADD4FAFFBC6501B5399742CD76835 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
}
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2013] [Tumblr, Inc.]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# TMCache
## Fast parallel object cache for iOS and OS X.
[![Build Status](https://img.shields.io/travis/tumblr/TMCache.svg?style=flat)](https://travis-ci.org/tumblr/XExtensionItem)
[![Version](http://img.shields.io/cocoapods/v/TMCache.svg?style=flat)](http://cocoapods.org/?q=XExtensionItem)
[![Platform](http://img.shields.io/cocoapods/p/TMCache.svg?style=flat)]()
[![License](http://img.shields.io/cocoapods/l/TMCache.svg?style=flat)](https://github.com/tumblr/XExtensionItem/blob/master/LICENSE)
[TMCache](TMCache/TMCache.h) is a key/value store designed for persisting temporary objects that are expensive to reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar stores, one in memory ([TMMemoryCache](TMCache/TMMemoryCache.h)) and one on disk ([TMDiskCache](TMCache/TMDiskCache.h)), all backed by GCD and safe to access from multiple threads simultaneously. On iOS, `TMMemoryCache` will clear itself when the app receives a memory warning or goes into the background. Objects stored in `TMDiskCache` remain until you trim the cache yourself, either manually or by setting a byte or age limit.
`TMCache` and `TMDiskCache` accept any object conforming to [NSCoding](https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/Reference/Reference.html). Put things in like this:
```objective-c
UIImage *img = [[UIImage alloc] initWithData:data scale:[[UIScreen mainScreen] scale]];
[[TMCache sharedCache] setObject:img forKey:@"image" block:nil]; // returns immediately
```
Get them back out like this:
```objective-c
[[TMCache sharedCache] objectForKey:@"image"
block:^(TMCache *cache, NSString *key, id object) {
UIImage *image = (UIImage *)object;
NSLog(@"image scale: %f", image.scale);
}];
```
`TMMemoryCache` allows for concurrent reads and serialized writes, while `TMDiskCache` serializes disk access across all instances in the app to increase performance and prevent file contention. `TMCache` coordinates them so that objects added to memory are available immediately to other threads while being written to disk safely in the background. Both caches are public properties of `TMCache`, so it's easy to manipulate one or the other separately if necessary.
Collections work too. Thanks to the magic of `NSKeyedArchiver`, objects repeated in a collection only occupy the space of one on disk:
```objective-c
NSArray *images = @[ image, image, image ];
[[TMCache sharedCache] setObject:images forKey:@"images"];
NSLog(@"3 for the price of 1: %d", [[[TMCache sharedCache] diskCache] byteCount]);
```
## Installation
### Manually
[Download the latest tag](https://github.com/tumblr/TMCache/tags) and drag the `TMCache` folder into your Xcode project.
Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/TMCache/)
### Git Submodule
git submodule add https://github.com/tumblr/TMCache.git
git submodule update --init
### CocoaPods
Add [TMCache](http://cocoapods.org/?q=name%3ATMCache) to your `Podfile` and run `pod install`.
## Requirements
__TMCache__ requires iOS 5.0 or OS X 10.7 and greater.
## Contributing
Please see [CONTRIBUTING.md](https://github.com/tumblr/XExtensionItem/blob/master/CONTRIBUTING.md) for information on how to help out.
## Contact
[Bryan Irace](mailto:bryan@tumblr.com)
## License
Copyright 2013 Tumblr, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License.
/**
`TMCache` is a thread safe key/value store designed for persisting temporary objects that are expensive to
reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar
stores, one in memory (<TMMemoryCache>) and one on disk (<TMDiskCache>).
`TMCache` itself actually does very little; its main function is providing a front end for a common use case:
a small, fast memory cache that asynchronously persists itself to a large, slow disk cache. When objects are
removed from the memory cache in response to an "apocalyptic" event they remain in the disk cache and are
repopulated in memory the next time they are accessed. `TMCache` also does the tedious work of creating a
dispatch group to wait for both caches to finish their operations without blocking each other.
The parallel caches are accessible as public properties (<memoryCache> and <diskCache>) and can be manipulated
separately if necessary. See the docs for <TMMemoryCache> and <TMDiskCache> for more details.
*/
#import <Foundation/Foundation.h>
#import "TMDiskCache.h"
#import "TMMemoryCache.h"
@class TMCache;
typedef void (^TMCacheBlock)(TMCache *cache);
typedef void (^TMCacheObjectBlock)(TMCache *cache, NSString *key, id object);
@interface TMCache : NSObject
#pragma mark -
/// @name Core
/**
The name of this cache, used to create the <diskCache> and also appearing in stack traces.
*/
@property (readonly) NSString *name;
/**
A concurrent queue on which blocks passed to the asynchronous access methods are run.
*/
@property (readonly) dispatch_queue_t queue;
/**
Synchronously retrieves the total byte count of the <diskCache> on the shared disk queue.
*/
@property (readonly) NSUInteger diskByteCount;
/**
The underlying disk cache, see <TMDiskCache> for additional configuration and trimming options.
*/
@property (readonly) TMDiskCache *diskCache;
/**
The underlying memory cache, see <TMMemoryCache> for additional configuration and trimming options.
*/
@property (readonly) TMMemoryCache *memoryCache;
#pragma mark -
/// @name Initialization
/**
A shared cache.
@result The shared singleton cache instance.
*/
+ (instancetype)sharedCache;
/**
Multiple instances with the same name are allowed and can safely access
the same data on disk thanks to the magic of seriality. Also used to create the <diskCache>.
@see name
@param name The name of the cache.
@result A new cache with the specified name.
*/
- (instancetype)initWithName:(NSString *)name;
/**
The designated initializer. Multiple instances with the same name are allowed and can safely access
the same data on disk thanks to the magic of seriality. Also used to create the <diskCache>.
@see name
@param name The name of the cache.
@param rootPath The path of the cache on disk.
@result A new cache with the specified name.
*/
- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath;
#pragma mark -
/// @name Asynchronous Methods
/**
Retrieves the object for the specified key. This method returns immediately and executes the passed
block after the object is available, potentially in parallel with other blocks on the <queue>.
@param key The key associated with the requested object.
@param block A block to be executed concurrently when the object is available.
*/
- (void)objectForKey:(NSString *)key block:(TMCacheObjectBlock)block;
/**
Stores an object in the cache for the specified key. This method returns immediately and executes the
passed block after the object has been stored, potentially in parallel with other blocks on the <queue>.
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param block A block to be executed concurrently after the object has been stored, or nil.
*/
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key block:(TMCacheObjectBlock)block;
/**
Removes the object for the specified key. This method returns immediately and executes the passed
block after the object has been removed, potentially in parallel with other blocks on the <queue>.
@param key The key associated with the object to be removed.
@param block A block to be executed concurrently after the object has been removed, or nil.
*/
- (void)removeObjectForKey:(NSString *)key block:(TMCacheObjectBlock)block;
/**
Removes all objects from the cache that have not been used since the specified date. This method returns immediately and
executes the passed block after the cache has been trimmed, potentially in parallel with other blocks on the <queue>.
@param date Objects that haven't been accessed since this date are removed from the cache.
@param block A block to be executed concurrently after the cache has been trimmed, or nil.
*/
- (void)trimToDate:(NSDate *)date block:(TMCacheBlock)block;
/**
Removes all objects from the cache.This method returns immediately and executes the passed block after the
cache has been cleared, potentially in parallel with other blocks on the <queue>.
@param block A block to be executed concurrently after the cache has been cleared, or nil.
*/
- (void)removeAllObjects:(TMCacheBlock)block;
#pragma mark -
/// @name Synchronous Methods
/**
Retrieves the object for the specified key. This method blocks the calling thread until the object is available.
@see objectForKey:block:
@param key The key associated with the object.
@result The object for the specified key.
*/
- (id)objectForKey:(NSString *)key;
/**
Stores an object in the cache for the specified key. This method blocks the calling thread until the object has been set.
@see setObject:forKey:block:
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
*/
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key;
/**
Removes the object for the specified key. This method blocks the calling thread until the object
has been removed.
@param key The key associated with the object to be removed.
*/
- (void)removeObjectForKey:(NSString *)key;
/**
Removes all objects from the cache that have not been used since the specified date.
This method blocks the calling thread until the cache has been trimmed.
@param date Objects that haven't been accessed since this date are removed from the cache.
*/
- (void)trimToDate:(NSDate *)date;
/**
Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared.
*/
- (void)removeAllObjects;
@end
#import "TMCache.h"
NSString * const TMCachePrefix = @"com.tumblr.TMCache";
NSString * const TMCacheSharedName = @"TMCacheShared";
@interface TMCache ()
#if OS_OBJECT_USE_OBJC
@property (strong, nonatomic) dispatch_queue_t queue;
#else
@property (assign, nonatomic) dispatch_queue_t queue;
#endif
@end
@implementation TMCache
#pragma mark - Initialization -
#if !OS_OBJECT_USE_OBJC
- (void)dealloc
{
dispatch_release(_queue);
_queue = nil;
}
#endif
- (instancetype)initWithName:(NSString *)name
{
return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
}
- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath
{
if (!name)
return nil;
if (self = [super init]) {
_name = [name copy];
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", TMCachePrefix, self];
_queue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT);
_diskCache = [[TMDiskCache alloc] initWithName:_name rootPath:rootPath];
_memoryCache = [[TMMemoryCache alloc] init];
}
return self;
}
- (NSString *)description
{
return [[NSString alloc] initWithFormat:@"%@.%@.%p", TMCachePrefix, _name, self];
}
+ (instancetype)sharedCache
{
static id cache;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
cache = [[self alloc] initWithName:TMCacheSharedName];
});
return cache;
}
#pragma mark - Public Asynchronous Methods -
- (void)objectForKey:(NSString *)key block:(TMCacheObjectBlock)block
{
if (!key || !block)
return;
__weak TMCache *weakSelf = self;
dispatch_async(_queue, ^{
TMCache *strongSelf = weakSelf;
if (!strongSelf)
return;
__weak TMCache *weakSelf = strongSelf;
[strongSelf->_memoryCache objectForKey:key block:^(TMMemoryCache *cache, NSString *key, id object) {
TMCache *strongSelf = weakSelf;
if (!strongSelf)
return;
if (object) {
[strongSelf->_diskCache fileURLForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
// update the access time on disk
}];
__weak TMCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf, key, object);
});
} else {
__weak TMCache *weakSelf = strongSelf;
[strongSelf->_diskCache objectForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
TMCache *strongSelf = weakSelf;
if (!strongSelf)
return;
[strongSelf->_memoryCache setObject:object forKey:key block:nil];
__weak TMCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf, key, object);
});
}];
}
}];
});
}
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key block:(TMCacheObjectBlock)block
{
if (!key || !object)
return;
dispatch_group_t group = nil;
TMMemoryCacheObjectBlock memBlock = nil;
TMDiskCacheObjectBlock diskBlock = nil;
if (block) {
group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_enter(group);
memBlock = ^(TMMemoryCache *cache, NSString *key, id object) {
dispatch_group_leave(group);
};
diskBlock = ^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
dispatch_group_leave(group);
};
}
[_memoryCache setObject:object forKey:key block:memBlock];
[_diskCache setObject:object forKey:key block:diskBlock];
if (group) {
__weak TMCache *weakSelf = self;
dispatch_group_notify(group, _queue, ^{
TMCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf, key, object);
});
#if !OS_OBJECT_USE_OBJC
dispatch_release(group);
#endif
}
}
- (void)removeObjectForKey:(NSString *)key block:(TMCacheObjectBlock)block
{
if (!key)
return;
dispatch_group_t group = nil;
TMMemoryCacheObjectBlock memBlock = nil;
TMDiskCacheObjectBlock diskBlock = nil;
if (block) {
group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_enter(group);
memBlock = ^(TMMemoryCache *cache, NSString *key, id object) {
dispatch_group_leave(group);
};
diskBlock = ^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
dispatch_group_leave(group);
};
}
[_memoryCache removeObjectForKey:key block:memBlock];
[_diskCache removeObjectForKey:key block:diskBlock];
if (group) {
__weak TMCache *weakSelf = self;
dispatch_group_notify(group, _queue, ^{
TMCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf, key, nil);
});
#if !OS_OBJECT_USE_OBJC
dispatch_release(group);
#endif
}
}
- (void)removeAllObjects:(TMCacheBlock)block
{
dispatch_group_t group = nil;
TMMemoryCacheBlock memBlock = nil;
TMDiskCacheBlock diskBlock = nil;
if (block) {
group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_enter(group);
memBlock = ^(TMMemoryCache *cache) {
dispatch_group_leave(group);
};
diskBlock = ^(TMDiskCache *cache) {
dispatch_group_leave(group);
};
}
[_memoryCache removeAllObjects:memBlock];
[_diskCache removeAllObjects:diskBlock];
if (group) {
__weak TMCache *weakSelf = self;
dispatch_group_notify(group, _queue, ^{
TMCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf);
});
#if !OS_OBJECT_USE_OBJC
dispatch_release(group);
#endif
}
}
- (void)trimToDate:(NSDate *)date block:(TMCacheBlock)block
{
if (!date)
return;
dispatch_group_t group = nil;
TMMemoryCacheBlock memBlock = nil;
TMDiskCacheBlock diskBlock = nil;
if (block) {
group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_enter(group);
memBlock = ^(TMMemoryCache *cache) {
dispatch_group_leave(group);
};
diskBlock = ^(TMDiskCache *cache) {
dispatch_group_leave(group);
};
}
[_memoryCache trimToDate:date block:memBlock];
[_diskCache trimToDate:date block:diskBlock];
if (group) {
__weak TMCache *weakSelf = self;
dispatch_group_notify(group, _queue, ^{
TMCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf);
});
#if !OS_OBJECT_USE_OBJC
dispatch_release(group);
#endif
}
}
#pragma mark - Public Synchronous Accessors -
- (NSUInteger)diskByteCount
{
__block NSUInteger byteCount = 0;
dispatch_sync([TMDiskCache sharedQueue], ^{
byteCount = self.diskCache.byteCount;
});
return byteCount;
}
#pragma mark - Public Synchronous Methods -
- (id)objectForKey:(NSString *)key
{
if (!key)
return nil;
__block id objectForKey = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self objectForKey:key block:^(TMCache *cache, NSString *key, id object) {
objectForKey = object;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
return objectForKey;
}
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key
{
if (!object || !key)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self setObject:object forKey:key block:^(TMCache *cache, NSString *key, id object) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)removeObjectForKey:(NSString *)key
{
if (!key)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self removeObjectForKey:key block:^(TMCache *cache, NSString *key, id object) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToDate:(NSDate *)date
{
if (!date)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToDate:date block:^(TMCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)removeAllObjects
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self removeAllObjects:^(TMCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
@end
// HC SVNT DRACONES
//
// TMCacheBackgroundTaskManager.h
// TMCache
//
// Created by Bryan Irace on 4/24/15.
// Copyright (c) 2015 Tumblr. All rights reserved.
//
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
#import <UIKit/UIKit.h>
#else
typedef NSUInteger UIBackgroundTaskIdentifier;
#endif
/**
A protocol that classes who can begin and end background tasks can conform to. This protocol provides an abstraction in
order to avoid referencing `+ [UIApplication sharedApplication]` from within an iOS application extension.
*/
@protocol TMCacheBackgroundTaskManager <NSObject>
/**
Marks the beginning of a new long-running background task.
@return A unique identifier for the new background task. You must pass this value to the `endBackgroundTask:` method to
mark the end of this task. This method returns `UIBackgroundTaskInvalid` if running in the background is not possible.
*/
- (UIBackgroundTaskIdentifier)beginBackgroundTask;
/**
Marks the end of a specific long-running background task.
@param identifier An identifier returned by the `beginBackgroundTaskWithExpirationHandler:` method.
*/
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier;
@end
/**
`TMDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming
to the `NSCoding` protocol, which includes the basic Foundation data types and collection classes and also
many UIKit classes, notably `UIImage`. All work is performed on a serial queue shared by all instances in
the app, and archiving is handled by `NSKeyedArchiver`. This is a particular advantage for `UIImage` because
it skips `UIImagePNGRepresentation()` and retains information like scale and orientation.
The designated initializer for `TMDiskCache` is <initWithName:>. The <name> string is used to create a directory
under Library/Caches that scopes disk access for any instance sharing this name. Multiple instances with the
same name are allowed because all disk access is serialized on the <sharedQueue>. The <name> also appears in
stack traces and return value for `description:`.
Unless otherwise noted, all properties and methods are safe to access from any thread at any time. All blocks
will cause the queue to wait, making it safe to access and manipulate the actual cache files on disk for the
duration of the block. In addition, the <sharedQueue> can be set to target an existing serial I/O queue, should
your app already have one.
Because this cache is bound by disk I/O it can be much slower than <TMMemoryCache>, although values stored in
`TMDiskCache` persist after application relaunch. Using <TMCache> is recommended over using `TMDiskCache`
by itself, as it adds a fast layer of additional memory caching while still writing to disk.
All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an optional
<ageLimit> will trigger a GCD timer to periodically to trim the cache with <trimToDate:>.
*/
#import <Foundation/Foundation.h>
@class TMDiskCache;
@protocol TMCacheBackgroundTaskManager;
typedef void (^TMDiskCacheBlock)(TMDiskCache *cache);
typedef void (^TMDiskCacheObjectBlock)(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL);
@interface TMDiskCache : NSObject
#pragma mark -
/// @name Core
/**
The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces.
*/
@property (readonly) NSString *name;
/**
The URL of the directory used by this cache, usually `Library/Caches/com.tumblr.TMDiskCache.(name)`
@warning Do not interact with files under this URL except on the <sharedQueue>.
*/
@property (readonly) NSURL *cacheURL;
/**
The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`.
@warning This property is technically safe to access from any thread, but it reflects the value *right now*,
not taking into account any pending operations. In most cases this value should only be read from a block on the
<sharedQueue>, which will ensure its accuracy and prevent it from changing during the lifetime of the block.
For example:
// some background thread, not a block already running on the shared queue
dispatch_sync([TMDiskCache sharedQueue], ^{
NSLog(@"accurate, unchanging byte count: %d", [[TMDiskCache sharedCache] byteCount]);
});
*/
@property (readonly) NSUInteger byteCount;
/**
The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written
size exceeds the limit a trim call is queued. Defaults to `0.0`, meaning no practical limit.
@warning Do not read this property on the <sharedQueue> (including asynchronous method blocks).
*/
@property (assign) NSUInteger byteLimit;
/**
The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value
greater than `0.0` will start a recurring GCD timer with the same period that calls <trimToDate:>.
Setting it back to `0.0` will stop the timer. Defaults to `0.0`, meaning no limit.
@warning Do not read this property on the <sharedQueue> (including asynchronous method blocks).
*/
@property (assign) NSTimeInterval ageLimit;
#pragma mark -
/// @name Event Blocks
/**
A block to be executed just before an object is added to the cache. The queue waits during execution.
*/
@property (copy) TMDiskCacheObjectBlock willAddObjectBlock;
/**
A block to be executed just before an object is removed from the cache. The queue waits during execution.
*/
@property (copy) TMDiskCacheObjectBlock willRemoveObjectBlock;
/**
A block to be executed just before all objects are removed from the cache as a result of <removeAllObjects:>.
The queue waits during execution.
*/
@property (copy) TMDiskCacheBlock willRemoveAllObjectsBlock;
/**
A block to be executed just after an object is added to the cache. The queue waits during execution.
*/
@property (copy) TMDiskCacheObjectBlock didAddObjectBlock;
/**
A block to be executed just after an object is removed from the cache. The queue waits during execution.
*/
@property (copy) TMDiskCacheObjectBlock didRemoveObjectBlock;
/**
A block to be executed just after all objects are removed from the cache as a result of <removeAllObjects:>.
The queue waits during execution.
*/
@property (copy) TMDiskCacheBlock didRemoveAllObjectsBlock;
#pragma mark -
/// @name Initialization
/**
A shared cache.
@result The shared singleton cache instance.
*/
+ (instancetype)sharedCache;
/**
A shared serial queue, used by all instances of this class. Use `dispatch_set_target_queue` to integrate
this queue with an exisiting serial I/O queue.
@result The shared singleton queue instance.
*/
+ (dispatch_queue_t)sharedQueue;
/**
Empties the trash with `DISPATCH_QUEUE_PRIORITY_BACKGROUND`. Does not block the <sharedQueue>.
*/
+ (void)emptyTrash;
/**
Multiple instances with the same name are allowed and can safely access
the same data on disk thanks to the magic of seriality.
@see name
@param name The name of the cache.
@result A new cache with the specified name.
*/
- (instancetype)initWithName:(NSString *)name;
/**
The designated initializer. Multiple instances with the same name are allowed and can safely access
the same data on disk thanks to the magic of seriality.
@see name
@param name The name of the cache.
@param rootPath The path of the cache.
@result A new cache with the specified name.
*/
- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath;
#pragma mark -
/// @name Asynchronous Methods
/**
Retrieves the object for the specified key. This method returns immediately and executes the passed
block as soon as the object is available on the serial <sharedQueue>.
@warning The fileURL is only valid for the duration of this block, do not use it after the block ends.
@param key The key associated with the requested object.
@param block A block to be executed serially when the object is available.
*/
- (void)objectForKey:(NSString *)key block:(TMDiskCacheObjectBlock)block;
/**
Retrieves the fileURL for the specified key without actually reading the data from disk. This method
returns immediately and executes the passed block as soon as the object is available on the serial
<sharedQueue>.
@warning Access is protected for the duration of the block, but to maintain safe disk access do not
access this fileURL after the block has ended. Do all work on the <sharedQueue>.
@param key The key associated with the requested object.
@param block A block to be executed serially when the file URL is available.
*/
- (void)fileURLForKey:(NSString *)key block:(TMDiskCacheObjectBlock)block;
/**
Stores an object in the cache for the specified key. This method returns immediately and executes the
passed block as soon as the object has been stored.
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param block A block to be executed serially after the object has been stored, or nil.
*/
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key block:(TMDiskCacheObjectBlock)block;
/**
Removes the object for the specified key. This method returns immediately and executes the passed block
as soon as the object has been removed.
@param key The key associated with the object to be removed.
@param block A block to be executed serially after the object has been removed, or nil.
*/
- (void)removeObjectForKey:(NSString *)key block:(TMDiskCacheObjectBlock)block;
/**
Removes all objects from the cache that have not been used since the specified date.
This method returns immediately and executes the passed block as soon as the cache has been trimmed.
@param date Objects that haven't been accessed since this date are removed from the cache.
@param block A block to be executed serially after the cache has been trimmed, or nil.
*/
- (void)trimToDate:(NSDate *)date block:(TMDiskCacheBlock)block;
/**
Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount.
This method returns immediately and executes the passed block as soon as the cache has been trimmed.
@param byteCount The cache will be trimmed equal to or smaller than this size.
@param block A block to be executed serially after the cache has been trimmed, or nil.
*/
- (void)trimToSize:(NSUInteger)byteCount block:(TMDiskCacheBlock)block;
/**
Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or smaller
than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has
been trimmed.
@param byteCount The cache will be trimmed equal to or smaller than this size.
@param block A block to be executed serially after the cache has been trimmed, or nil.
*/
- (void)trimToSizeByDate:(NSUInteger)byteCount block:(TMDiskCacheBlock)block;
/**
Removes all objects from the cache. This method returns immediately and executes the passed block as soon as the
cache has been cleared.
@param block A block to be executed serially after the cache has been cleared, or nil.
*/
- (void)removeAllObjects:(TMDiskCacheBlock)block;
/**
Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually
read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available.
This method returns immediately.
@param block A block to be executed for every object in the cache.
@param completionBlock An optional block to be executed after the enumeration is complete.
*/
- (void)enumerateObjectsWithBlock:(TMDiskCacheObjectBlock)block completionBlock:(TMDiskCacheBlock)completionBlock;
#pragma mark -
/// @name Synchronous Methods
/**
Retrieves the object for the specified key. This method blocks the calling thread until the
object is available.
@see objectForKey:block:
@param key The key associated with the object.
@result The object for the specified key.
*/
- (id <NSCoding>)objectForKey:(NSString *)key;
/**
Retrieves the file URL for the specified key. This method blocks the calling thread until the
url is available. Do not use this URL anywhere but on the <sharedQueue>. This method probably
shouldn't even exist, just use the asynchronous one.
@see fileURLForKey:block:
@param key The key associated with the object.
@result The file URL for the specified key.
*/
- (NSURL *)fileURLForKey:(NSString *)key;
/**
Stores an object in the cache for the specified key. This method blocks the calling thread until
the object has been stored.
@see setObject:forKey:block:
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
*/
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key;
/**
Removes the object for the specified key. This method blocks the calling thread until the object
has been removed.
@param key The key associated with the object to be removed.
*/
- (void)removeObjectForKey:(NSString *)key;
/**
Removes all objects from the cache that have not been used since the specified date.
This method blocks the calling thread until the cache has been trimmed.
@param date Objects that haven't been accessed since this date are removed from the cache.
*/
- (void)trimToDate:(NSDate *)date;
/**
Removes objects from the cache, largest first, until the cache is equal to or smaller than the
specified byteCount. This method blocks the calling thread until the cache has been trimmed.
@param byteCount The cache will be trimmed equal to or smaller than this size.
*/
- (void)trimToSize:(NSUInteger)byteCount;
/**
Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or
smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed.
@param byteCount The cache will be trimmed equal to or smaller than this size.
*/
- (void)trimToSizeByDate:(NSUInteger)byteCount;
/**
Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared.
*/
- (void)removeAllObjects;
/**
Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually
read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available.
This method blocks the calling thread until all objects have been enumerated.
@param block A block to be executed for every object in the cache.
@warning Do not call this method within the event blocks (<didRemoveObjectBlock>, etc.)
Instead use the asynchronous version, <enumerateObjectsWithBlock:completionBlock:>.
*/
- (void)enumerateObjectsWithBlock:(TMDiskCacheObjectBlock)block;
#pragma mark -
/// @name Background Tasks
/**
Set a global manager to be used for setting up/tearing down any background tasks needed by TMCache.
@param backgroundTaskManager Background task manager.
*/
+ (void)setBackgroundTaskManager:(id <TMCacheBackgroundTaskManager>)backgroundTaskManager;
@end
#import "TMDiskCache.h"
#import "TMCacheBackgroundTaskManager.h"
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
#import <UIKit/UIKit.h>
#endif
#define TMDiskCacheError(error) if (error) { NSLog(@"%@ (%d) ERROR: %@", \
[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
__LINE__, [error localizedDescription]); }
static id <TMCacheBackgroundTaskManager> TMCacheBackgroundTaskManager;
NSString * const TMDiskCachePrefix = @"com.tumblr.TMDiskCache";
NSString * const TMDiskCacheSharedName = @"TMDiskCacheShared";
@interface TMDiskCache ()
@property (assign) NSUInteger byteCount;
@property (strong, nonatomic) NSURL *cacheURL;
@property (assign, nonatomic) dispatch_queue_t queue;
@property (strong, nonatomic) NSMutableDictionary *dates;
@property (strong, nonatomic) NSMutableDictionary *sizes;
@end
@implementation TMDiskCache
@synthesize willAddObjectBlock = _willAddObjectBlock;
@synthesize willRemoveObjectBlock = _willRemoveObjectBlock;
@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock;
@synthesize didAddObjectBlock = _didAddObjectBlock;
@synthesize didRemoveObjectBlock = _didRemoveObjectBlock;
@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock;
@synthesize byteLimit = _byteLimit;
@synthesize ageLimit = _ageLimit;
#pragma mark - Initialization -
- (instancetype)initWithName:(NSString *)name
{
return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
}
- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath
{
if (!name)
return nil;
if (self = [super init]) {
_name = [name copy];
_queue = [TMDiskCache sharedQueue];
_willAddObjectBlock = nil;
_willRemoveObjectBlock = nil;
_willRemoveAllObjectsBlock = nil;
_didAddObjectBlock = nil;
_didRemoveObjectBlock = nil;
_didRemoveAllObjectsBlock = nil;
_byteCount = 0;
_byteLimit = 0;
_ageLimit = 0.0;
_dates = [[NSMutableDictionary alloc] init];
_sizes = [[NSMutableDictionary alloc] init];
NSString *pathComponent = [[NSString alloc] initWithFormat:@"%@.%@", TMDiskCachePrefix, _name];
_cacheURL = [NSURL fileURLWithPathComponents:@[ rootPath, pathComponent ]];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
[strongSelf createCacheDirectory];
[strongSelf initializeDiskProperties];
});
}
return self;
}
- (NSString *)description
{
return [[NSString alloc] initWithFormat:@"%@.%@.%p", TMDiskCachePrefix, _name, self];
}
+ (instancetype)sharedCache
{
static id cache;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
cache = [[self alloc] initWithName:TMDiskCacheSharedName];
});
return cache;
}
+ (dispatch_queue_t)sharedQueue
{
static dispatch_queue_t queue;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
queue = dispatch_queue_create([TMDiskCachePrefix UTF8String], DISPATCH_QUEUE_SERIAL);
});
return queue;
}
#pragma mark - Private Methods -
- (NSURL *)encodedFileURLForKey:(NSString *)key
{
if (![key length])
return nil;
return [_cacheURL URLByAppendingPathComponent:[self encodedString:key]];
}
- (NSString *)keyForEncodedFileURL:(NSURL *)url
{
NSString *fileName = [url lastPathComponent];
if (!fileName)
return nil;
return [self decodedString:fileName];
}
- (NSString *)encodedString:(NSString *)string
{
if (![string length])
return @"";
CFStringRef static const charsToEscape = CFSTR(".:/");
CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL,
charsToEscape,
kCFStringEncodingUTF8);
return (__bridge_transfer NSString *)escapedString;
}
- (NSString *)decodedString:(NSString *)string
{
if (![string length])
return @"";
CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
(__bridge CFStringRef)string,
CFSTR(""),
kCFStringEncodingUTF8);
return (__bridge_transfer NSString *)unescapedString;
}
#pragma mark - Private Trash Methods -
+ (dispatch_queue_t)sharedTrashQueue
{
static dispatch_queue_t trashQueue;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.trash", TMDiskCachePrefix];
trashQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(trashQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
});
return trashQueue;
}
+ (NSURL *)sharedTrashURL
{
static NSURL *sharedTrashURL;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedTrashURL = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:TMDiskCachePrefix isDirectory:YES];
if (![[NSFileManager defaultManager] fileExistsAtPath:[sharedTrashURL path]]) {
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtURL:sharedTrashURL
withIntermediateDirectories:YES
attributes:nil
error:&error];
TMDiskCacheError(error);
}
});
return sharedTrashURL;
}
+(BOOL)moveItemAtURLToTrash:(NSURL *)itemURL
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[itemURL path]])
return NO;
NSError *error = nil;
NSString *uniqueString = [[NSProcessInfo processInfo] globallyUniqueString];
NSURL *uniqueTrashURL = [[TMDiskCache sharedTrashURL] URLByAppendingPathComponent:uniqueString];
BOOL moved = [[NSFileManager defaultManager] moveItemAtURL:itemURL toURL:uniqueTrashURL error:&error];
TMDiskCacheError(error);
return moved;
}
+ (void)emptyTrash
{
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
dispatch_async([self sharedTrashQueue], ^{
NSError *error = nil;
NSArray *trashedItems = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[self sharedTrashURL]
includingPropertiesForKeys:nil
options:0
error:&error];
TMDiskCacheError(error);
for (NSURL *trashedItemURL in trashedItems) {
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtURL:trashedItemURL error:&error];
TMDiskCacheError(error);
}
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
#pragma mark - Private Queue Methods -
- (BOOL)createCacheDirectory
{
if ([[NSFileManager defaultManager] fileExistsAtPath:[_cacheURL path]])
return NO;
NSError *error = nil;
BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:_cacheURL
withIntermediateDirectories:YES
attributes:nil
error:&error];
TMDiskCacheError(error);
return success;
}
- (void)initializeDiskProperties
{
NSUInteger byteCount = 0;
NSArray *keys = @[ NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ];
NSError *error = nil;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:_cacheURL
includingPropertiesForKeys:keys
options:NSDirectoryEnumerationSkipsHiddenFiles
error:&error];
TMDiskCacheError(error);
for (NSURL *fileURL in files) {
NSString *key = [self keyForEncodedFileURL:fileURL];
error = nil;
NSDictionary *dictionary = [fileURL resourceValuesForKeys:keys error:&error];
TMDiskCacheError(error);
NSDate *date = [dictionary objectForKey:NSURLContentModificationDateKey];
if (date && key)
[_dates setObject:date forKey:key];
NSNumber *fileSize = [dictionary objectForKey:NSURLTotalFileAllocatedSizeKey];
if (fileSize) {
[_sizes setObject:fileSize forKey:key];
byteCount += [fileSize unsignedIntegerValue];
}
}
if (byteCount > 0)
self.byteCount = byteCount; // atomic
}
- (BOOL)setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL
{
if (!date || !fileURL) {
return NO;
}
NSError *error = nil;
BOOL success = [[NSFileManager defaultManager] setAttributes:@{ NSFileModificationDate: date }
ofItemAtPath:[fileURL path]
error:&error];
TMDiskCacheError(error);
if (success) {
NSString *key = [self keyForEncodedFileURL:fileURL];
if (key) {
[_dates setObject:date forKey:key];
}
}
return success;
}
- (BOOL)removeFileAndExecuteBlocksForKey:(NSString *)key
{
NSURL *fileURL = [self encodedFileURLForKey:key];
if (!fileURL || ![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
return NO;
if (_willRemoveObjectBlock)
_willRemoveObjectBlock(self, key, nil, fileURL);
BOOL trashed = [TMDiskCache moveItemAtURLToTrash:fileURL];
if (!trashed)
return NO;
[TMDiskCache emptyTrash];
NSNumber *byteSize = [_sizes objectForKey:key];
if (byteSize)
self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic
[_sizes removeObjectForKey:key];
[_dates removeObjectForKey:key];
if (_didRemoveObjectBlock)
_didRemoveObjectBlock(self, key, nil, fileURL);
return YES;
}
- (void)trimDiskToSize:(NSUInteger)trimByteCount
{
if (_byteCount <= trimByteCount)
return;
NSArray *keysSortedBySize = [_sizes keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first
[self removeFileAndExecuteBlocksForKey:key];
if (_byteCount <= trimByteCount)
break;
}
}
- (void)trimDiskToSizeByDate:(NSUInteger)trimByteCount
{
if (_byteCount <= trimByteCount)
return;
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in keysSortedByDate) { // oldest objects first
[self removeFileAndExecuteBlocksForKey:key];
if (_byteCount <= trimByteCount)
break;
}
}
- (void)trimDiskToDate:(NSDate *)trimDate
{
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in keysSortedByDate) { // oldest files first
NSDate *accessDate = [_dates objectForKey:key];
if (!accessDate)
continue;
if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date
[self removeFileAndExecuteBlocksForKey:key];
} else {
break;
}
}
}
- (void)trimToAgeLimitRecursively
{
if (_ageLimit == 0.0)
return;
NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-_ageLimit];
[self trimDiskToDate:date];
__weak TMDiskCache *weakSelf = self;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_ageLimit * NSEC_PER_SEC));
dispatch_after(time, _queue, ^(void) {
TMDiskCache *strongSelf = weakSelf;
[strongSelf trimToAgeLimitRecursively];
});
}
#pragma mark - Public Asynchronous Methods -
- (void)objectForKey:(NSString *)key block:(TMDiskCacheObjectBlock)block
{
NSDate *now = [[NSDate alloc] init];
if (!key || !block)
return;
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
NSURL *fileURL = [strongSelf encodedFileURLForKey:key];
id <NSCoding> object = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
@try {
object = [NSKeyedUnarchiver unarchiveObjectWithFile:[fileURL path]];
}
@catch (NSException *exception) {
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtPath:[fileURL path] error:&error];
TMDiskCacheError(error);
}
[strongSelf setFileModificationDate:now forURL:fileURL];
}
block(strongSelf, key, object, fileURL);
});
}
- (void)fileURLForKey:(NSString *)key block:(TMDiskCacheObjectBlock)block
{
NSDate *now = [[NSDate alloc] init];
if (!key || !block)
return;
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
NSURL *fileURL = [strongSelf encodedFileURLForKey:key];
if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
[strongSelf setFileModificationDate:now forURL:fileURL];
} else {
fileURL = nil;
}
block(strongSelf, key, nil, fileURL);
});
}
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key block:(TMDiskCacheObjectBlock)block
{
NSDate *now = [[NSDate alloc] init];
if (!key || !object)
return;
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
NSURL *fileURL = [strongSelf encodedFileURLForKey:key];
if (strongSelf->_willAddObjectBlock)
strongSelf->_willAddObjectBlock(strongSelf, key, object, fileURL);
BOOL written = [NSKeyedArchiver archiveRootObject:object toFile:[fileURL path]];
if (written) {
[strongSelf setFileModificationDate:now forURL:fileURL];
NSError *error = nil;
NSDictionary *values = [fileURL resourceValuesForKeys:@[ NSURLTotalFileAllocatedSizeKey ] error:&error];
TMDiskCacheError(error);
NSNumber *diskFileSize = [values objectForKey:NSURLTotalFileAllocatedSizeKey];
if (diskFileSize) {
NSNumber *oldEntry = [strongSelf->_sizes objectForKey:key];
if ([oldEntry isKindOfClass:[NSNumber class]]){
strongSelf.byteCount = strongSelf->_byteCount - [oldEntry unsignedIntegerValue];
}
[strongSelf->_sizes setObject:diskFileSize forKey:key];
strongSelf.byteCount = strongSelf->_byteCount + [diskFileSize unsignedIntegerValue]; // atomic
}
if (strongSelf->_byteLimit > 0 && strongSelf->_byteCount > strongSelf->_byteLimit)
[strongSelf trimToSizeByDate:strongSelf->_byteLimit block:nil];
} else {
fileURL = nil;
}
if (strongSelf->_didAddObjectBlock)
strongSelf->_didAddObjectBlock(strongSelf, key, object, written ? fileURL : nil);
if (block)
block(strongSelf, key, object, fileURL);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
- (void)removeObjectForKey:(NSString *)key block:(TMDiskCacheObjectBlock)block
{
if (!key)
return;
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
NSURL *fileURL = [strongSelf encodedFileURLForKey:key];
[strongSelf removeFileAndExecuteBlocksForKey:key];
if (block)
block(strongSelf, key, nil, fileURL);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
- (void)trimToSize:(NSUInteger)trimByteCount block:(TMDiskCacheBlock)block
{
if (trimByteCount == 0) {
[self removeAllObjects:block];
return;
}
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
[strongSelf trimDiskToSize:trimByteCount];
if (block)
block(strongSelf);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
- (void)trimToDate:(NSDate *)trimDate block:(TMDiskCacheBlock)block
{
if (!trimDate)
return;
if ([trimDate isEqualToDate:[NSDate distantPast]]) {
[self removeAllObjects:block];
return;
}
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
[strongSelf trimDiskToDate:trimDate];
if (block)
block(strongSelf);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
- (void)trimToSizeByDate:(NSUInteger)trimByteCount block:(TMDiskCacheBlock)block
{
if (trimByteCount == 0) {
[self removeAllObjects:block];
return;
}
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
[strongSelf trimDiskToSizeByDate:trimByteCount];
if (block)
block(strongSelf);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
- (void)removeAllObjects:(TMDiskCacheBlock)block
{
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
if (strongSelf->_willRemoveAllObjectsBlock)
strongSelf->_willRemoveAllObjectsBlock(strongSelf);
[TMDiskCache moveItemAtURLToTrash:strongSelf->_cacheURL];
[TMDiskCache emptyTrash];
[strongSelf createCacheDirectory];
[strongSelf->_dates removeAllObjects];
[strongSelf->_sizes removeAllObjects];
strongSelf.byteCount = 0; // atomic
if (strongSelf->_didRemoveAllObjectsBlock)
strongSelf->_didRemoveAllObjectsBlock(strongSelf);
if (block)
block(strongSelf);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
- (void)enumerateObjectsWithBlock:(TMDiskCacheObjectBlock)block completionBlock:(TMDiskCacheBlock)completionBlock
{
if (!block)
return;
UIBackgroundTaskIdentifier taskID = [TMCacheBackgroundTaskManager beginBackgroundTask];
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf) {
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
return;
}
NSArray *keysSortedByDate = [strongSelf->_dates keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in keysSortedByDate) {
NSURL *fileURL = [strongSelf encodedFileURLForKey:key];
block(strongSelf, key, nil, fileURL);
}
if (completionBlock)
completionBlock(strongSelf);
[TMCacheBackgroundTaskManager endBackgroundTask:taskID];
});
}
#pragma mark - Public Synchronous Methods -
- (id <NSCoding>)objectForKey:(NSString *)key
{
if (!key)
return nil;
__block id <NSCoding> objectForKey = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self objectForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
objectForKey = object;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
return objectForKey;
}
- (NSURL *)fileURLForKey:(NSString *)key
{
if (!key)
return nil;
__block NSURL *fileURLForKey = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self fileURLForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
fileURLForKey = fileURL;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
return fileURLForKey;
}
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key
{
if (!object || !key)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self setObject:object forKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)removeObjectForKey:(NSString *)key
{
if (!key)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self removeObjectForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToSize:(NSUInteger)byteCount
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToSize:byteCount block:^(TMDiskCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToDate:(NSDate *)date
{
if (!date)
return;
if ([date isEqualToDate:[NSDate distantPast]]) {
[self removeAllObjects];
return;
}
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToDate:date block:^(TMDiskCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToSizeByDate:(NSUInteger)byteCount
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToSizeByDate:byteCount block:^(TMDiskCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)removeAllObjects
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self removeAllObjects:^(TMDiskCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)enumerateObjectsWithBlock:(TMDiskCacheObjectBlock)block
{
if (!block)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self enumerateObjectsWithBlock:block completionBlock:^(TMDiskCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
#pragma mark - Public Thread Safe Accessors -
- (TMDiskCacheObjectBlock)willAddObjectBlock
{
__block TMDiskCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _willAddObjectBlock;
});
return block;
}
- (void)setWillAddObjectBlock:(TMDiskCacheObjectBlock)block
{
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_willAddObjectBlock = [block copy];
});
}
- (TMDiskCacheObjectBlock)willRemoveObjectBlock
{
__block TMDiskCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _willRemoveObjectBlock;
});
return block;
}
- (void)setWillRemoveObjectBlock:(TMDiskCacheObjectBlock)block
{
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_willRemoveObjectBlock = [block copy];
});
}
- (TMDiskCacheBlock)willRemoveAllObjectsBlock
{
__block TMDiskCacheBlock block = nil;
dispatch_sync(_queue, ^{
block = _willRemoveAllObjectsBlock;
});
return block;
}
- (void)setWillRemoveAllObjectsBlock:(TMDiskCacheBlock)block
{
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_willRemoveAllObjectsBlock = [block copy];
});
}
- (TMDiskCacheObjectBlock)didAddObjectBlock
{
__block TMDiskCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _didAddObjectBlock;
});
return block;
}
- (void)setDidAddObjectBlock:(TMDiskCacheObjectBlock)block
{
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didAddObjectBlock = [block copy];
});
}
- (TMDiskCacheObjectBlock)didRemoveObjectBlock
{
__block TMDiskCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _didRemoveObjectBlock;
});
return block;
}
- (void)setDidRemoveObjectBlock:(TMDiskCacheObjectBlock)block
{
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didRemoveObjectBlock = [block copy];
});
}
- (TMDiskCacheBlock)didRemoveAllObjectsBlock
{
__block TMDiskCacheBlock block = nil;
dispatch_sync(_queue, ^{
block = _didRemoveAllObjectsBlock;
});
return block;
}
- (void)setDidRemoveAllObjectsBlock:(TMDiskCacheBlock)block
{
__weak TMDiskCache *weakSelf = self;
dispatch_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didRemoveAllObjectsBlock = [block copy];
});
}
- (NSUInteger)byteLimit
{
__block NSUInteger byteLimit = 0;
dispatch_sync(_queue, ^{
byteLimit = _byteLimit;
});
return byteLimit;
}
- (void)setByteLimit:(NSUInteger)byteLimit
{
__weak TMDiskCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_byteLimit = byteLimit;
if (byteLimit > 0)
[strongSelf trimDiskToSizeByDate:byteLimit];
});
}
- (NSTimeInterval)ageLimit
{
__block NSTimeInterval ageLimit = 0.0;
dispatch_sync(_queue, ^{
ageLimit = _ageLimit;
});
return ageLimit;
}
- (void)setAgeLimit:(NSTimeInterval)ageLimit
{
__weak TMDiskCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMDiskCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_ageLimit = ageLimit;
[strongSelf trimToAgeLimitRecursively];
});
}
#pragma mark - Background Tasks -
+ (void)setBackgroundTaskManager:(id <TMCacheBackgroundTaskManager>)backgroundTaskManager {
TMCacheBackgroundTaskManager = backgroundTaskManager;
}
@end
/**
`TMMemoryCache` is a fast, thread safe key/value store similar to `NSCache`. On iOS it will clear itself
automatically to reduce memory usage when the app receives a memory warning or goes into the background.
Access is natively asynchronous. Every method accepts a callback block that runs on a concurrent
<queue>, with cache writes protected by GCD barriers. Synchronous variations are provided.
All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an
optional <ageLimit> will trigger a GCD timer to periodically to trim the cache to that age.
Objects can optionally be set with a "cost", which could be a byte count or any other meaningful integer.
Setting a <costLimit> will automatically keep the cache below that value with <trimToCostByDate:>.
Values will not persist after application relaunch or returning from the background. See <TMCache> for
a memory cache backed by a disk cache.
*/
#import <Foundation/Foundation.h>
@class TMMemoryCache;
typedef void (^TMMemoryCacheBlock)(TMMemoryCache *cache);
typedef void (^TMMemoryCacheObjectBlock)(TMMemoryCache *cache, NSString *key, id object);
@interface TMMemoryCache : NSObject
#pragma mark -
/// @name Core
/**
A concurrent queue on which all work is done. It is exposed here so that it can be set to target some
other queue, such as a global concurrent queue with a priority other than the default.
*/
@property (readonly) dispatch_queue_t queue;
/**
The total accumulated cost.
*/
@property (readonly) NSUInteger totalCost;
/**
The maximum cost allowed to accumulate before objects begin to be removed with <trimToCostByDate:>.
*/
@property (assign) NSUInteger costLimit;
/**
The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value
greater than `0.0` will start a recurring GCD timer with the same period that calls <trimToDate:>.
Setting it back to `0.0` will stop the timer. Defaults to `0.0`.
*/
@property (assign) NSTimeInterval ageLimit;
/**
When `YES` on iOS the cache will remove all objects when the app receives a memory warning.
Defaults to `YES`.
*/
@property (assign) BOOL removeAllObjectsOnMemoryWarning;
/**
When `YES` on iOS the cache will remove all objects when the app enters the background.
Defaults to `YES`.
*/
@property (assign) BOOL removeAllObjectsOnEnteringBackground;
#pragma mark -
/// @name Event Blocks
/**
A block to be executed just before an object is added to the cache. This block will be excuted within
a barrier, i.e. all reads and writes are suspended for the duration of the block.
*/
@property (copy) TMMemoryCacheObjectBlock willAddObjectBlock;
/**
A block to be executed just before an object is removed from the cache. This block will be excuted
within a barrier, i.e. all reads and writes are suspended for the duration of the block.
*/
@property (copy) TMMemoryCacheObjectBlock willRemoveObjectBlock;
/**
A block to be executed just before all objects are removed from the cache as a result of <removeAllObjects:>.
This block will be excuted within a barrier, i.e. all reads and writes are suspended for the duration of the block.
*/
@property (copy) TMMemoryCacheBlock willRemoveAllObjectsBlock;
/**
A block to be executed just after an object is added to the cache. This block will be excuted within
a barrier, i.e. all reads and writes are suspended for the duration of the block.
*/
@property (copy) TMMemoryCacheObjectBlock didAddObjectBlock;
/**
A block to be executed just after an object is removed from the cache. This block will be excuted
within a barrier, i.e. all reads and writes are suspended for the duration of the block.
*/
@property (copy) TMMemoryCacheObjectBlock didRemoveObjectBlock;
/**
A block to be executed just after all objects are removed from the cache as a result of <removeAllObjects:>.
This block will be excuted within a barrier, i.e. all reads and writes are suspended for the duration of the block.
*/
@property (copy) TMMemoryCacheBlock didRemoveAllObjectsBlock;
/**
A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the <queue>.
This block will be executed regardless of the value of <removeAllObjectsOnMemoryWarning>. Defaults to `nil`.
*/
@property (copy) TMMemoryCacheBlock didReceiveMemoryWarningBlock;
/**
A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the <queue>.
This block will be executed regardless of the value of <removeAllObjectsOnEnteringBackground>. Defaults to `nil`.
*/
@property (copy) TMMemoryCacheBlock didEnterBackgroundBlock;
#pragma mark -
/// @name Shared Cache
/**
A shared cache.
@result The shared singleton cache instance.
*/
+ (instancetype)sharedCache;
#pragma mark -
/// @name Asynchronous Methods
/**
Retrieves the object for the specified key. This method returns immediately and executes the passed
block after the object is available, potentially in parallel with other blocks on the <queue>.
@param key The key associated with the requested object.
@param block A block to be executed concurrently when the object is available.
*/
- (void)objectForKey:(NSString *)key block:(TMMemoryCacheObjectBlock)block;
/**
Stores an object in the cache for the specified key. This method returns immediately and executes the
passed block after the object has been stored, potentially in parallel with other blocks on the <queue>.
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param block A block to be executed concurrently after the object has been stored, or nil.
*/
- (void)setObject:(id)object forKey:(NSString *)key block:(TMMemoryCacheObjectBlock)block;
/**
Stores an object in the cache for the specified key and the specified cost. If the cost causes the total
to go over the <costLimit> the cache is trimmed (oldest objects first). This method returns immediately
and executes the passed block after the object has been stored, potentially in parallel with other blocks
on the <queue>.
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param cost An amount to add to the <totalCost>.
@param block A block to be executed concurrently after the object has been stored, or nil.
*/
- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(TMMemoryCacheObjectBlock)block;
/**
Removes the object for the specified key. This method returns immediately and executes the passed
block after the object has been removed, potentially in parallel with other blocks on the <queue>.
@param key The key associated with the object to be removed.
@param block A block to be executed concurrently after the object has been removed, or nil.
*/
- (void)removeObjectForKey:(NSString *)key block:(TMMemoryCacheObjectBlock)block;
/**
Removes all objects from the cache that have not been used since the specified date.
This method returns immediately and executes the passed block after the cache has been trimmed,
potentially in parallel with other blocks on the <queue>.
@param date Objects that haven't been accessed since this date are removed from the cache.
@param block A block to be executed concurrently after the cache has been trimmed, or nil.
*/
- (void)trimToDate:(NSDate *)date block:(TMMemoryCacheBlock)block;
/**
Removes objects from the cache, costliest objects first, until the <totalCost> is below the specified
value. This method returns immediately and executes the passed block after the cache has been trimmed,
potentially in parallel with other blocks on the <queue>.
@param cost The total accumulation allowed to remain after the cache has been trimmed.
@param block A block to be executed concurrently after the cache has been trimmed, or nil.
*/
- (void)trimToCost:(NSUInteger)cost block:(TMMemoryCacheBlock)block;
/**
Removes objects from the cache, ordered by date (least recently used first), until the <totalCost> is below
the specified value. This method returns immediately and executes the passed block after the cache has been
trimmed, potentially in parallel with other blocks on the <queue>.
@param cost The total accumulation allowed to remain after the cache has been trimmed.
@param block A block to be executed concurrently after the cache has been trimmed, or nil.
*/
- (void)trimToCostByDate:(NSUInteger)cost block:(TMMemoryCacheBlock)block;
/**
Removes all objects from the cache. This method returns immediately and executes the passed block after
the cache has been cleared, potentially in parallel with other blocks on the <queue>.
@param block A block to be executed concurrently after the cache has been cleared, or nil.
*/
- (void)removeAllObjects:(TMMemoryCacheBlock)block;
/**
Loops through all objects in the cache within a memory barrier (reads and writes are suspended during the enumeration).
This method returns immediately.
@param block A block to be executed for every object in the cache.
@param completionBlock An optional block to be executed concurrently when the enumeration is complete.
*/
- (void)enumerateObjectsWithBlock:(TMMemoryCacheObjectBlock)block completionBlock:(TMMemoryCacheBlock)completionBlock;
#pragma mark -
/// @name Synchronous Methods
/**
Retrieves the object for the specified key. This method blocks the calling thread until the
object is available.
@see objectForKey:block:
@param key The key associated with the object.
@result The object for the specified key.
*/
- (id)objectForKey:(NSString *)key;
/**
Stores an object in the cache for the specified key. This method blocks the calling thread until the object
has been set.
@see setObject:forKey:block:
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
*/
- (void)setObject:(id)object forKey:(NSString *)key;
/**
Stores an object in the cache for the specified key and the specified cost. If the cost causes the total
to go over the <costLimit> the cache is trimmed (oldest objects first). This method blocks the calling thread
until the object has been stored.
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param cost An amount to add to the <totalCost>.
*/
- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost;
/**
Removes the object for the specified key. This method blocks the calling thread until the object
has been removed.
@param key The key associated with the object to be removed.
*/
- (void)removeObjectForKey:(NSString *)key;
/**
Removes all objects from the cache that have not been used since the specified date.
This method blocks the calling thread until the cache has been trimmed.
@param date Objects that haven't been accessed since this date are removed from the cache.
*/
- (void)trimToDate:(NSDate *)date;
/**
Removes objects from the cache, costliest objects first, until the <totalCost> is below the specified
value. This method blocks the calling thread until the cache has been trimmed.
@param cost The total accumulation allowed to remain after the cache has been trimmed.
*/
- (void)trimToCost:(NSUInteger)cost;
/**
Removes objects from the cache, ordered by date (least recently used first), until the <totalCost> is below
the specified value. This method blocks the calling thread until the cache has been trimmed.
@param cost The total accumulation allowed to remain after the cache has been trimmed.
*/
- (void)trimToCostByDate:(NSUInteger)cost;
/**
Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared.
*/
- (void)removeAllObjects;
/**
Loops through all objects in the cache within a memory barrier (reads and writes are suspended during the enumeration).
This method blocks the calling thread until all objects have been enumerated.
@param block A block to be executed for every object in the cache.
@warning Do not call this method within the event blocks (<didReceiveMemoryWarningBlock>, etc.)
Instead use the asynchronous version, <enumerateObjectsWithBlock:completionBlock:>.
*/
- (void)enumerateObjectsWithBlock:(TMMemoryCacheObjectBlock)block;
/**
Handle a memory warning.
*/
- (void)handleMemoryWarning __deprecated_msg("This happens automatically in TMCache 2.1. There’s no longer a need to call it directly.");
/**
Handle the application having been backgrounded.
*/
- (void)handleApplicationBackgrounding __deprecated_msg("This happens automatically in TMCache 2.1. There’s no longer a need to call it directly.");
@end
#import "TMMemoryCache.h"
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
#import <UIKit/UIKit.h>
#endif
NSString * const TMMemoryCachePrefix = @"com.tumblr.TMMemoryCache";
@interface TMMemoryCache ()
#if OS_OBJECT_USE_OBJC
@property (strong, nonatomic) dispatch_queue_t queue;
#else
@property (assign, nonatomic) dispatch_queue_t queue;
#endif
@property (strong, nonatomic) NSMutableDictionary *dictionary;
@property (strong, nonatomic) NSMutableDictionary *dates;
@property (strong, nonatomic) NSMutableDictionary *costs;
@end
@implementation TMMemoryCache
@synthesize ageLimit = _ageLimit;
@synthesize costLimit = _costLimit;
@synthesize totalCost = _totalCost;
@synthesize willAddObjectBlock = _willAddObjectBlock;
@synthesize willRemoveObjectBlock = _willRemoveObjectBlock;
@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock;
@synthesize didAddObjectBlock = _didAddObjectBlock;
@synthesize didRemoveObjectBlock = _didRemoveObjectBlock;
@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock;
@synthesize didReceiveMemoryWarningBlock = _didReceiveMemoryWarningBlock;
@synthesize didEnterBackgroundBlock = _didEnterBackgroundBlock;
#pragma mark - Initialization -
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
#if !OS_OBJECT_USE_OBJC
dispatch_release(_queue);
_queue = nil;
#endif
}
- (id)init
{
if (self = [super init]) {
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", TMMemoryCachePrefix, self];
_queue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT);
_dictionary = [[NSMutableDictionary alloc] init];
_dates = [[NSMutableDictionary alloc] init];
_costs = [[NSMutableDictionary alloc] init];
_willAddObjectBlock = nil;
_willRemoveObjectBlock = nil;
_willRemoveAllObjectsBlock = nil;
_didAddObjectBlock = nil;
_didRemoveObjectBlock = nil;
_didRemoveAllObjectsBlock = nil;
_didReceiveMemoryWarningBlock = nil;
_didEnterBackgroundBlock = nil;
_ageLimit = 0.0;
_costLimit = 0;
_totalCost = 0;
_removeAllObjectsOnMemoryWarning = YES;
_removeAllObjectsOnEnteringBackground = YES;
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleMemoryWarning)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleApplicationBackgrounding)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
#endif
}
return self;
}
+ (instancetype)sharedCache
{
static id cache;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
cache = [[self alloc] init];
});
return cache;
}
#pragma mark - Private Methods -
- (void)handleMemoryWarning
{
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
if (self.removeAllObjectsOnMemoryWarning)
[self removeAllObjects:nil];
__weak TMMemoryCache *weakSelf = self;
dispatch_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
if (strongSelf->_didReceiveMemoryWarningBlock)
strongSelf->_didReceiveMemoryWarningBlock(strongSelf);
});
#endif
}
- (void)handleApplicationBackgrounding
{
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
if (self.removeAllObjectsOnEnteringBackground)
[self removeAllObjects:nil];
__weak TMMemoryCache *weakSelf = self;
dispatch_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
if (strongSelf->_didEnterBackgroundBlock)
strongSelf->_didEnterBackgroundBlock(strongSelf);
});
#endif
}
- (void)removeObjectAndExecuteBlocksForKey:(NSString *)key
{
id object = [_dictionary objectForKey:key];
NSNumber *cost = [_costs objectForKey:key];
if (_willRemoveObjectBlock)
_willRemoveObjectBlock(self, key, object);
if (cost)
_totalCost -= [cost unsignedIntegerValue];
[_dictionary removeObjectForKey:key];
[_dates removeObjectForKey:key];
[_costs removeObjectForKey:key];
if (_didRemoveObjectBlock)
_didRemoveObjectBlock(self, key, nil);
}
- (void)trimMemoryToDate:(NSDate *)trimDate
{
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in keysSortedByDate) { // oldest objects first
NSDate *accessDate = [_dates objectForKey:key];
if (!accessDate)
continue;
if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date
[self removeObjectAndExecuteBlocksForKey:key];
} else {
break;
}
}
}
- (void)trimToCostLimit:(NSUInteger)limit
{
if (_totalCost <= limit)
return;
NSArray *keysSortedByCost = [_costs keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in [keysSortedByCost reverseObjectEnumerator]) { // costliest objects first
[self removeObjectAndExecuteBlocksForKey:key];
if (_totalCost <= limit)
break;
}
}
- (void)trimToCostLimitByDate:(NSUInteger)limit
{
if (_totalCost <= limit)
return;
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in keysSortedByDate) { // oldest objects first
[self removeObjectAndExecuteBlocksForKey:key];
if (_totalCost <= limit)
break;
}
}
- (void)trimToAgeLimitRecursively
{
if (_ageLimit == 0.0)
return;
NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-_ageLimit];
[self trimMemoryToDate:date];
__weak TMMemoryCache *weakSelf = self;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_ageLimit * NSEC_PER_SEC));
dispatch_after(time, _queue, ^(void){
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_barrier_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
[strongSelf trimToAgeLimitRecursively];
});
});
}
#pragma mark - Public Asynchronous Methods -
- (void)objectForKey:(NSString *)key block:(TMMemoryCacheObjectBlock)block
{
NSDate *now = [[NSDate alloc] init];
if (!key || !block)
return;
__weak TMMemoryCache *weakSelf = self;
dispatch_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
id object = [strongSelf->_dictionary objectForKey:key];
if (object) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_barrier_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
[strongSelf->_dates setObject:now forKey:key];
});
}
block(strongSelf, key, object);
});
}
- (void)setObject:(id)object forKey:(NSString *)key block:(TMMemoryCacheObjectBlock)block
{
[self setObject:object forKey:key withCost:0 block:block];
}
- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(TMMemoryCacheObjectBlock)block
{
NSDate *now = [[NSDate alloc] init];
if (!key || !object)
return;
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
if (strongSelf->_willAddObjectBlock)
strongSelf->_willAddObjectBlock(strongSelf, key, object);
[strongSelf->_dictionary setObject:object forKey:key];
[strongSelf->_dates setObject:now forKey:key];
[strongSelf->_costs setObject:@(cost) forKey:key];
_totalCost += cost;
if (strongSelf->_didAddObjectBlock)
strongSelf->_didAddObjectBlock(strongSelf, key, object);
if (strongSelf->_costLimit > 0)
[strongSelf trimToCostByDate:strongSelf->_costLimit block:nil];
if (block) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf, key, object);
});
}
});
}
- (void)removeObjectForKey:(NSString *)key block:(TMMemoryCacheObjectBlock)block
{
if (!key)
return;
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
[strongSelf removeObjectAndExecuteBlocksForKey:key];
if (block) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf, key, nil);
});
}
});
}
- (void)trimToDate:(NSDate *)trimDate block:(TMMemoryCacheBlock)block
{
if (!trimDate)
return;
if ([trimDate isEqualToDate:[NSDate distantPast]]) {
[self removeAllObjects:block];
return;
}
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
[strongSelf trimMemoryToDate:trimDate];
if (block) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf);
});
}
});
}
- (void)trimToCost:(NSUInteger)cost block:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
[strongSelf trimToCostLimit:cost];
if (block) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf);
});
}
});
}
- (void)trimToCostByDate:(NSUInteger)cost block:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
[strongSelf trimToCostLimitByDate:cost];
if (block) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf);
});
}
});
}
- (void)removeAllObjects:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
if (strongSelf->_willRemoveAllObjectsBlock)
strongSelf->_willRemoveAllObjectsBlock(strongSelf);
[strongSelf->_dictionary removeAllObjects];
[strongSelf->_dates removeAllObjects];
[strongSelf->_costs removeAllObjects];
strongSelf->_totalCost = 0;
if (strongSelf->_didRemoveAllObjectsBlock)
strongSelf->_didRemoveAllObjectsBlock(strongSelf);
if (block) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
block(strongSelf);
});
}
});
}
- (void)enumerateObjectsWithBlock:(TMMemoryCacheObjectBlock)block completionBlock:(TMMemoryCacheBlock)completionBlock
{
if (!block)
return;
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
NSArray *keysSortedByDate = [strongSelf->_dates keysSortedByValueUsingSelector:@selector(compare:)];
for (NSString *key in keysSortedByDate) {
block(strongSelf, key, [strongSelf->_dictionary objectForKey:key]);
}
if (completionBlock) {
__weak TMMemoryCache *weakSelf = strongSelf;
dispatch_async(strongSelf->_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (strongSelf)
completionBlock(strongSelf);
});
}
});
}
#pragma mark - Public Synchronous Methods -
- (id)objectForKey:(NSString *)key
{
if (!key)
return nil;
__block id objectForKey = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self objectForKey:key block:^(TMMemoryCache *cache, NSString *key, id object) {
objectForKey = object;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
return objectForKey;
}
- (void)setObject:(id)object forKey:(NSString *)key
{
[self setObject:object forKey:key withCost:0];
}
- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost
{
if (!object || !key)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self setObject:object forKey:key withCost:cost block:^(TMMemoryCache *cache, NSString *key, id object) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)removeObjectForKey:(NSString *)key
{
if (!key)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self removeObjectForKey:key block:^(TMMemoryCache *cache, NSString *key, id object) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToDate:(NSDate *)date
{
if (!date)
return;
if ([date isEqualToDate:[NSDate distantPast]]) {
[self removeAllObjects];
return;
}
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToDate:date block:^(TMMemoryCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToCost:(NSUInteger)cost
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToCost:cost block:^(TMMemoryCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)trimToCostByDate:(NSUInteger)cost
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self trimToCostByDate:cost block:^(TMMemoryCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)removeAllObjects
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self removeAllObjects:^(TMMemoryCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
- (void)enumerateObjectsWithBlock:(TMMemoryCacheObjectBlock)block
{
if (!block)
return;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self enumerateObjectsWithBlock:block completionBlock:^(TMMemoryCache *cache) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
#if !OS_OBJECT_USE_OBJC
dispatch_release(semaphore);
#endif
}
#pragma mark - Public Thread Safe Accessors -
- (TMMemoryCacheObjectBlock)willAddObjectBlock
{
__block TMMemoryCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = self->_willAddObjectBlock;
});
return block;
}
- (void)setWillAddObjectBlock:(TMMemoryCacheObjectBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_willAddObjectBlock = [block copy];
});
}
- (TMMemoryCacheObjectBlock)willRemoveObjectBlock
{
__block TMMemoryCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _willRemoveObjectBlock;
});
return block;
}
- (void)setWillRemoveObjectBlock:(TMMemoryCacheObjectBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_willRemoveObjectBlock = [block copy];
});
}
- (TMMemoryCacheBlock)willRemoveAllObjectsBlock
{
__block TMMemoryCacheBlock block = nil;
dispatch_sync(_queue, ^{
block = _willRemoveAllObjectsBlock;
});
return block;
}
- (void)setWillRemoveAllObjectsBlock:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_willRemoveAllObjectsBlock = [block copy];
});
}
- (TMMemoryCacheObjectBlock)didAddObjectBlock
{
__block TMMemoryCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _didAddObjectBlock;
});
return block;
}
- (void)setDidAddObjectBlock:(TMMemoryCacheObjectBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didAddObjectBlock = [block copy];
});
}
- (TMMemoryCacheObjectBlock)didRemoveObjectBlock
{
__block TMMemoryCacheObjectBlock block = nil;
dispatch_sync(_queue, ^{
block = _didRemoveObjectBlock;
});
return block;
}
- (void)setDidRemoveObjectBlock:(TMMemoryCacheObjectBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didRemoveObjectBlock = [block copy];
});
}
- (TMMemoryCacheBlock)didRemoveAllObjectsBlock
{
__block TMMemoryCacheBlock block = nil;
dispatch_sync(_queue, ^{
block = _didRemoveAllObjectsBlock;
});
return block;
}
- (void)setDidRemoveAllObjectsBlock:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didRemoveAllObjectsBlock = [block copy];
});
}
- (TMMemoryCacheBlock)didReceiveMemoryWarningBlock
{
__block TMMemoryCacheBlock block = nil;
dispatch_sync(_queue, ^{
block = _didReceiveMemoryWarningBlock;
});
return block;
}
- (void)setDidReceiveMemoryWarningBlock:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didReceiveMemoryWarningBlock = [block copy];
});
}
- (TMMemoryCacheBlock)didEnterBackgroundBlock
{
__block TMMemoryCacheBlock block = nil;
dispatch_sync(_queue, ^{
block = _didEnterBackgroundBlock;
});
return block;
}
- (void)setDidEnterBackgroundBlock:(TMMemoryCacheBlock)block
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_didEnterBackgroundBlock = [block copy];
});
}
- (NSTimeInterval)ageLimit
{
__block NSTimeInterval ageLimit = 0.0;
dispatch_sync(_queue, ^{
ageLimit = _ageLimit;
});
return ageLimit;
}
- (void)setAgeLimit:(NSTimeInterval)ageLimit
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_ageLimit = ageLimit;
[strongSelf trimToAgeLimitRecursively];
});
}
- (NSUInteger)costLimit
{
__block NSUInteger costLimit = 0;
dispatch_sync(_queue, ^{
costLimit = _costLimit;
});
return costLimit;
}
- (void)setCostLimit:(NSUInteger)costLimit
{
__weak TMMemoryCache *weakSelf = self;
dispatch_barrier_async(_queue, ^{
TMMemoryCache *strongSelf = weakSelf;
if (!strongSelf)
return;
strongSelf->_costLimit = costLimit;
if (costLimit > 0)
[strongSelf trimToCostLimitByDate:costLimit];
});
}
- (NSUInteger)totalCost
{
__block NSUInteger cost = 0;
dispatch_sync(_queue, ^{
cost = _totalCost;
});
return cost;
}
@end
#import <Foundation/Foundation.h>
@interface PodsDummy_GMCache : NSObject
@end
@implementation PodsDummy_GMCache
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "WMCacheService.h"
FOUNDATION_EXPORT double GMCacheVersionNumber;
FOUNDATION_EXPORT const unsigned char GMCacheVersionString[];
framework module GMCache {
umbrella header "GMCache-umbrella.h"
export *
module * { export * }
}
CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/GMCache
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/TMCache"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
# Acknowledgements
This application makes use of the following third party libraries:
## GMCache
Copyright (c) 2016 wangyang <wangyang@wanmeizhensuo.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
## TMCache
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2013] [Tumblr, Inc.]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Generated by CocoaPods - https://cocoapods.org
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2016 wangyang &lt;wangyang@wanmeizhensuo.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>GMCache</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string> Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2013] [Tumblr, Inc.]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</string>
<key>License</key>
<string>Apache 2.0</string>
<key>Title</key>
<string>TMCache</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - https://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_GMCache_Example : NSObject
@end
@implementation PodsDummy_Pods_GMCache_Example
@end
#!/bin/sh
set -e
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
install_framework()
{
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
local source="${BUILT_PRODUCTS_DIR}/$1"
elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
elif [ -r "$1" ]; then
local source="$1"
fi
local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L "${source}" ]; then
echo "Symlinked..."
source="$(readlink "${source}")"
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
local basename
basename="$(basename -s .framework "$1")"
binary="${destination}/${basename}.framework/${basename}"
if ! [ -r "$binary" ]; then
binary="${destination}/${basename}"
fi
# Strip invalid architectures so "fat" simulator / device frameworks work on device
if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
strip_invalid_archs "$binary"
fi
# Resign the code if required by the build settings to avoid unstable apps
code_sign_if_enabled "${destination}/$(basename "$1")"
# Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
code_sign_if_enabled "${destination}/${lib}"
done
fi
}
# Signs a framework with the provided identity
code_sign_if_enabled() {
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
# Use the current code_sign_identitiy
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\""
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1"
fi
}
# Strip invalid architectures
strip_invalid_archs() {
binary="$1"
# Get architectures for current file
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
stripped=""
for arch in $archs; do
if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
# Strip non-valid architectures in-place
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
stripped="$stripped $arch"
fi
done
if [[ "$stripped" ]]; then
echo "Stripped $binary of architectures:$stripped"
fi
}
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "$BUILT_PRODUCTS_DIR/GMCache/GMCache.framework"
install_framework "$BUILT_PRODUCTS_DIR/TMCache/TMCache.framework"
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "$BUILT_PRODUCTS_DIR/GMCache/GMCache.framework"
install_framework "$BUILT_PRODUCTS_DIR/TMCache/TMCache.framework"
fi
#!/bin/sh
set -e
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
XCASSET_FILES=()
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
install_resource()
{
if [[ "$1" = /* ]] ; then
RESOURCE_PATH="$1"
else
RESOURCE_PATH="${PODS_ROOT}/$1"
fi
if [[ ! -e "$RESOURCE_PATH" ]] ; then
cat << EOM
error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
EOM
exit 1
fi
case $RESOURCE_PATH in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.framework)
echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
echo "$RESOURCE_PATH"
echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
;;
esac
}
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
FOUNDATION_EXPORT double Pods_GMCache_ExampleVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_GMCache_ExampleVersionString[];
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/GMCache" "$PODS_CONFIGURATION_BUILD_DIR/TMCache"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/GMCache/GMCache.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/TMCache/TMCache.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "GMCache" -framework "TMCache"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}/Pods
framework module Pods_GMCache_Example {
umbrella header "Pods-GMCache_Example-umbrella.h"
export *
module * { export * }
}
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/GMCache" "$PODS_CONFIGURATION_BUILD_DIR/TMCache"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/GMCache/GMCache.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/TMCache/TMCache.framework/Headers"
OTHER_LDFLAGS = $(inherited) -framework "GMCache" -framework "TMCache"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}/Pods
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
# Acknowledgements
This application makes use of the following third party libraries:
Generated by CocoaPods - https://cocoapods.org
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - https://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_GMCache_Tests : NSObject
@end
@implementation PodsDummy_Pods_GMCache_Tests
@end
#!/bin/sh
set -e
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
install_framework()
{
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
local source="${BUILT_PRODUCTS_DIR}/$1"
elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
elif [ -r "$1" ]; then
local source="$1"
fi
local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L "${source}" ]; then
echo "Symlinked..."
source="$(readlink "${source}")"
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
local basename
basename="$(basename -s .framework "$1")"
binary="${destination}/${basename}.framework/${basename}"
if ! [ -r "$binary" ]; then
binary="${destination}/${basename}"
fi
# Strip invalid architectures so "fat" simulator / device frameworks work on device
if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
strip_invalid_archs "$binary"
fi
# Resign the code if required by the build settings to avoid unstable apps
code_sign_if_enabled "${destination}/$(basename "$1")"
# Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
code_sign_if_enabled "${destination}/${lib}"
done
fi
}
# Signs a framework with the provided identity
code_sign_if_enabled() {
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
# Use the current code_sign_identitiy
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\""
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1"
fi
}
# Strip invalid architectures
strip_invalid_archs() {
binary="$1"
# Get architectures for current file
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
stripped=""
for arch in $archs; do
if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
# Strip non-valid architectures in-place
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
stripped="$stripped $arch"
fi
done
if [[ "$stripped" ]]; then
echo "Stripped $binary of architectures:$stripped"
fi
}
#!/bin/sh
set -e
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
XCASSET_FILES=()
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
install_resource()
{
if [[ "$1" = /* ]] ; then
RESOURCE_PATH="$1"
else
RESOURCE_PATH="${PODS_ROOT}/$1"
fi
if [[ ! -e "$RESOURCE_PATH" ]] ; then
cat << EOM
error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
EOM
exit 1
fi
case $RESOURCE_PATH in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
;;
*.framework)
echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
echo "$RESOURCE_PATH"
echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
;;
esac
}
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
FOUNDATION_EXPORT double Pods_GMCache_TestsVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_GMCache_TestsVersionString[];
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/GMCache" "$PODS_CONFIGURATION_BUILD_DIR/TMCache"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/GMCache/GMCache.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/TMCache/TMCache.framework/Headers"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}/Pods
framework module Pods_GMCache_Tests {
umbrella header "Pods-GMCache_Tests-umbrella.h"
export *
module * { export * }
}
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/GMCache" "$PODS_CONFIGURATION_BUILD_DIR/TMCache"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/GMCache/GMCache.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/TMCache/TMCache.framework/Headers"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}/Pods
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_TMCache : NSObject
@end
@implementation PodsDummy_TMCache
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "TMCache.h"
#import "TMCacheBackgroundTaskManager.h"
#import "TMDiskCache.h"
#import "TMMemoryCache.h"
FOUNDATION_EXPORT double TMCacheVersionNumber;
FOUNDATION_EXPORT const unsigned char TMCacheVersionString[];
framework module TMCache {
umbrella header "TMCache-umbrella.h"
export *
module * { export * }
}
CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/TMCache
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
OTHER_LDFLAGS = -framework "Foundation" -weak_framework "UIKit"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment