diff --git a/.gitignore b/.gitignore index 7e11480..c67c252 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ profile DerivedData # Demo Images -FastImageCacheDemo/Demo Images/*.jpg +FastImageCache/FastImageCacheDemo/Demo Images/*.jpg +Carthage diff --git a/FastImageCache/FICUtilities.h b/FastImageCache/FICUtilities.h deleted file mode 100644 index d6292e6..0000000 --- a/FastImageCache/FICUtilities.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FICUtilities.h -// FastImageCache -// -// Copyright (c) 2013 Path, Inc. -// See LICENSE for full license agreement. -// - -#import "FICImports.h" - -size_t FICByteAlign(size_t bytesPerRow, size_t alignment); -size_t FICByteAlignForCoreAnimation(size_t bytesPerRow); - -NSString * FICStringWithUUIDBytes(CFUUIDBytes UUIDBytes); -CFUUIDBytes FICUUIDBytesWithString(NSString *string); -CFUUIDBytes FICUUIDBytesFromMD5HashOfString(NSString *MD5Hash); // Useful for computing an entity's UUID from a URL, for example - diff --git a/FastImageCache/FastImageCache.xcodeproj/project.pbxproj b/FastImageCache/FastImageCache.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d889c59 --- /dev/null +++ b/FastImageCache/FastImageCache.xcodeproj/project.pbxproj @@ -0,0 +1,662 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + B2E5676E1B316D5800906840 /* FastImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E5676D1B316D5800906840 /* FastImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E567741B316D5800906840 /* FastImageCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2E567681B316D5800906840 /* FastImageCache.framework */; }; + B2E5677B1B316D5800906840 /* FastImageCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5677A1B316D5800906840 /* FastImageCacheTests.m */; }; + B2E567941B316D9600906840 /* FICEntity.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E567851B316D9600906840 /* FICEntity.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E567951B316D9600906840 /* FICImageCache+FICErrorLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E567861B316D9600906840 /* FICImageCache+FICErrorLogging.h */; }; + B2E567961B316D9600906840 /* FICImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E567871B316D9600906840 /* FICImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E567971B316D9600906840 /* FICImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567881B316D9600906840 /* FICImageCache.m */; }; + B2E567981B316D9600906840 /* FICImageFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E567891B316D9600906840 /* FICImageFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E567991B316D9600906840 /* FICImageFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5678A1B316D9600906840 /* FICImageFormat.m */; }; + B2E5679A1B316D9600906840 /* FICImageTable.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E5678B1B316D9600906840 /* FICImageTable.h */; }; + B2E5679B1B316D9600906840 /* FICImageTable.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5678C1B316D9600906840 /* FICImageTable.m */; }; + B2E5679C1B316D9600906840 /* FICImageTableChunk.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E5678D1B316D9600906840 /* FICImageTableChunk.h */; }; + B2E5679D1B316D9600906840 /* FICImageTableChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5678E1B316D9600906840 /* FICImageTableChunk.m */; }; + B2E5679E1B316D9600906840 /* FICImageTableEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E5678F1B316D9600906840 /* FICImageTableEntry.h */; }; + B2E5679F1B316D9600906840 /* FICImageTableEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567901B316D9600906840 /* FICImageTableEntry.m */; }; + B2E567A01B316D9600906840 /* FICImports.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E567911B316D9600906840 /* FICImports.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E567A11B316D9600906840 /* FICUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E567921B316D9600906840 /* FICUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E567A21B316D9600906840 /* FICUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567931B316D9600906840 /* FICUtilities.m */; }; + B2E567AC1B316DCA00906840 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567AB1B316DCA00906840 /* main.m */; }; + B2E567DA1B316E1000906840 /* FICDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567CF1B316E1000906840 /* FICDAppDelegate.m */; }; + B2E567DB1B316E1000906840 /* FICDFullscreenPhotoDisplayController.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567D11B316E1000906840 /* FICDFullscreenPhotoDisplayController.m */; }; + B2E567DC1B316E1000906840 /* FICDPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567D31B316E1000906840 /* FICDPhoto.m */; }; + B2E567DD1B316E1000906840 /* FICDPhotosTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567D51B316E1000906840 /* FICDPhotosTableViewCell.m */; }; + B2E567DE1B316E1000906840 /* FICDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567D71B316E1000906840 /* FICDTableView.m */; }; + B2E567DF1B316E1000906840 /* FICDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567D91B316E1000906840 /* FICDViewController.m */; }; + B2E567E41B316E2200906840 /* fetch_demo_images.sh in Resources */ = {isa = PBXBuildFile; fileRef = B2E567E31B316E2200906840 /* fetch_demo_images.sh */; }; + B2E567E61B316E3700906840 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B2E567E51B316E3700906840 /* Assets.xcassets */; }; + B2E567E71B316E5F00906840 /* FICUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567931B316D9600906840 /* FICUtilities.m */; }; + B2E567E81B316E6600906840 /* FICImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567881B316D9600906840 /* FICImageCache.m */; }; + B2E567E91B316E6600906840 /* FICImageFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5678A1B316D9600906840 /* FICImageFormat.m */; }; + B2E567EA1B316E6600906840 /* FICImageTable.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5678C1B316D9600906840 /* FICImageTable.m */; }; + B2E567EB1B316E6600906840 /* FICImageTableChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E5678E1B316D9600906840 /* FICImageTableChunk.m */; }; + B2E567EC1B316E6600906840 /* FICImageTableEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = B2E567901B316D9600906840 /* FICImageTableEntry.m */; }; + BFD6BFFB1B68FD5D005292DC /* Demo Images in Resources */ = {isa = PBXBuildFile; fileRef = BFD6BFFA1B68FD5D005292DC /* Demo Images */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + B2E567751B316D5800906840 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B2E5675F1B316D5800906840 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B2E567671B316D5800906840; + remoteInfo = FastImageCache; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + B2E567681B316D5800906840 /* FastImageCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FastImageCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B2E5676C1B316D5800906840 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B2E5676D1B316D5800906840 /* FastImageCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FastImageCache.h; sourceTree = ""; }; + B2E567731B316D5800906840 /* FastImageCacheTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FastImageCacheTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + B2E567791B316D5800906840 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B2E5677A1B316D5800906840 /* FastImageCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FastImageCacheTests.m; sourceTree = ""; }; + B2E567851B316D9600906840 /* FICEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICEntity.h; sourceTree = ""; }; + B2E567861B316D9600906840 /* FICImageCache+FICErrorLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FICImageCache+FICErrorLogging.h"; sourceTree = ""; }; + B2E567871B316D9600906840 /* FICImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageCache.h; sourceTree = ""; }; + B2E567881B316D9600906840 /* FICImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageCache.m; sourceTree = ""; }; + B2E567891B316D9600906840 /* FICImageFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageFormat.h; sourceTree = ""; }; + B2E5678A1B316D9600906840 /* FICImageFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageFormat.m; sourceTree = ""; }; + B2E5678B1B316D9600906840 /* FICImageTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageTable.h; sourceTree = ""; }; + B2E5678C1B316D9600906840 /* FICImageTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageTable.m; sourceTree = ""; }; + B2E5678D1B316D9600906840 /* FICImageTableChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageTableChunk.h; sourceTree = ""; }; + B2E5678E1B316D9600906840 /* FICImageTableChunk.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageTableChunk.m; sourceTree = ""; }; + B2E5678F1B316D9600906840 /* FICImageTableEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageTableEntry.h; sourceTree = ""; }; + B2E567901B316D9600906840 /* FICImageTableEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageTableEntry.m; sourceTree = ""; }; + B2E567911B316D9600906840 /* FICImports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImports.h; sourceTree = ""; }; + B2E567921B316D9600906840 /* FICUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICUtilities.h; sourceTree = ""; }; + B2E567931B316D9600906840 /* FICUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICUtilities.m; sourceTree = ""; }; + B2E567A71B316DCA00906840 /* FastImageCacheDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FastImageCacheDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + B2E567AA1B316DCA00906840 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B2E567AB1B316DCA00906840 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + B2E567CE1B316E1000906840 /* FICDAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDAppDelegate.h; sourceTree = ""; }; + B2E567CF1B316E1000906840 /* FICDAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDAppDelegate.m; sourceTree = ""; }; + B2E567D01B316E1000906840 /* FICDFullscreenPhotoDisplayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDFullscreenPhotoDisplayController.h; sourceTree = ""; }; + B2E567D11B316E1000906840 /* FICDFullscreenPhotoDisplayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDFullscreenPhotoDisplayController.m; sourceTree = ""; }; + B2E567D21B316E1000906840 /* FICDPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDPhoto.h; sourceTree = ""; }; + B2E567D31B316E1000906840 /* FICDPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDPhoto.m; sourceTree = ""; }; + B2E567D41B316E1000906840 /* FICDPhotosTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDPhotosTableViewCell.h; sourceTree = ""; }; + B2E567D51B316E1000906840 /* FICDPhotosTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDPhotosTableViewCell.m; sourceTree = ""; }; + B2E567D61B316E1000906840 /* FICDTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDTableView.h; sourceTree = ""; }; + B2E567D71B316E1000906840 /* FICDTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDTableView.m; sourceTree = ""; }; + B2E567D81B316E1000906840 /* FICDViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDViewController.h; sourceTree = ""; }; + B2E567D91B316E1000906840 /* FICDViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDViewController.m; sourceTree = ""; }; + B2E567E31B316E2200906840 /* fetch_demo_images.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = fetch_demo_images.sh; sourceTree = ""; }; + B2E567E51B316E3700906840 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + B2E567ED1B316EBF00906840 /* FastImageCacheDemo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FastImageCacheDemo-Prefix.pch"; sourceTree = ""; }; + BFD6BFFA1B68FD5D005292DC /* Demo Images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Demo Images"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B2E567641B316D5800906840 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B2E567701B316D5800906840 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E567741B316D5800906840 /* FastImageCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B2E567A41B316DCA00906840 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B2E5675E1B316D5800906840 = { + isa = PBXGroup; + children = ( + B2E5676A1B316D5800906840 /* FastImageCache */, + B2E567771B316D5800906840 /* FastImageCacheTests */, + B2E567A81B316DCA00906840 /* FastImageCacheDemo */, + B2E567691B316D5800906840 /* Products */, + ); + sourceTree = ""; + }; + B2E567691B316D5800906840 /* Products */ = { + isa = PBXGroup; + children = ( + B2E567681B316D5800906840 /* FastImageCache.framework */, + B2E567731B316D5800906840 /* FastImageCacheTests.xctest */, + B2E567A71B316DCA00906840 /* FastImageCacheDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + B2E5676A1B316D5800906840 /* FastImageCache */ = { + isa = PBXGroup; + children = ( + B2E567841B316D9600906840 /* FastImageCache */, + B2E5676D1B316D5800906840 /* FastImageCache.h */, + B2E5676B1B316D5800906840 /* Supporting Files */, + ); + path = FastImageCache; + sourceTree = ""; + }; + B2E5676B1B316D5800906840 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + B2E5676C1B316D5800906840 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + B2E567771B316D5800906840 /* FastImageCacheTests */ = { + isa = PBXGroup; + children = ( + B2E5677A1B316D5800906840 /* FastImageCacheTests.m */, + B2E567781B316D5800906840 /* Supporting Files */, + ); + path = FastImageCacheTests; + sourceTree = ""; + }; + B2E567781B316D5800906840 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + B2E567791B316D5800906840 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + B2E567841B316D9600906840 /* FastImageCache */ = { + isa = PBXGroup; + children = ( + B2E567851B316D9600906840 /* FICEntity.h */, + B2E567861B316D9600906840 /* FICImageCache+FICErrorLogging.h */, + B2E567871B316D9600906840 /* FICImageCache.h */, + B2E567881B316D9600906840 /* FICImageCache.m */, + B2E567891B316D9600906840 /* FICImageFormat.h */, + B2E5678A1B316D9600906840 /* FICImageFormat.m */, + B2E5678B1B316D9600906840 /* FICImageTable.h */, + B2E5678C1B316D9600906840 /* FICImageTable.m */, + B2E5678D1B316D9600906840 /* FICImageTableChunk.h */, + B2E5678E1B316D9600906840 /* FICImageTableChunk.m */, + B2E5678F1B316D9600906840 /* FICImageTableEntry.h */, + B2E567901B316D9600906840 /* FICImageTableEntry.m */, + B2E567911B316D9600906840 /* FICImports.h */, + B2E567921B316D9600906840 /* FICUtilities.h */, + B2E567931B316D9600906840 /* FICUtilities.m */, + ); + path = FastImageCache; + sourceTree = ""; + }; + B2E567A81B316DCA00906840 /* FastImageCacheDemo */ = { + isa = PBXGroup; + children = ( + B2E567E31B316E2200906840 /* fetch_demo_images.sh */, + BFD6BFFA1B68FD5D005292DC /* Demo Images */, + B2E567CD1B316E1000906840 /* Classes */, + B2E567A91B316DCA00906840 /* Supporting Files */, + ); + path = FastImageCacheDemo; + sourceTree = ""; + }; + B2E567A91B316DCA00906840 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + B2E567ED1B316EBF00906840 /* FastImageCacheDemo-Prefix.pch */, + B2E567E51B316E3700906840 /* Assets.xcassets */, + B2E567AA1B316DCA00906840 /* Info.plist */, + B2E567AB1B316DCA00906840 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + B2E567CD1B316E1000906840 /* Classes */ = { + isa = PBXGroup; + children = ( + B2E567CE1B316E1000906840 /* FICDAppDelegate.h */, + B2E567CF1B316E1000906840 /* FICDAppDelegate.m */, + B2E567D01B316E1000906840 /* FICDFullscreenPhotoDisplayController.h */, + B2E567D11B316E1000906840 /* FICDFullscreenPhotoDisplayController.m */, + B2E567D21B316E1000906840 /* FICDPhoto.h */, + B2E567D31B316E1000906840 /* FICDPhoto.m */, + B2E567D41B316E1000906840 /* FICDPhotosTableViewCell.h */, + B2E567D51B316E1000906840 /* FICDPhotosTableViewCell.m */, + B2E567D61B316E1000906840 /* FICDTableView.h */, + B2E567D71B316E1000906840 /* FICDTableView.m */, + B2E567D81B316E1000906840 /* FICDViewController.h */, + B2E567D91B316E1000906840 /* FICDViewController.m */, + ); + path = Classes; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + B2E567651B316D5800906840 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E5679A1B316D9600906840 /* FICImageTable.h in Headers */, + B2E5679E1B316D9600906840 /* FICImageTableEntry.h in Headers */, + B2E567941B316D9600906840 /* FICEntity.h in Headers */, + B2E567A01B316D9600906840 /* FICImports.h in Headers */, + B2E567981B316D9600906840 /* FICImageFormat.h in Headers */, + B2E567A11B316D9600906840 /* FICUtilities.h in Headers */, + B2E5679C1B316D9600906840 /* FICImageTableChunk.h in Headers */, + B2E567951B316D9600906840 /* FICImageCache+FICErrorLogging.h in Headers */, + B2E567961B316D9600906840 /* FICImageCache.h in Headers */, + B2E5676E1B316D5800906840 /* FastImageCache.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + B2E567671B316D5800906840 /* FastImageCache */ = { + isa = PBXNativeTarget; + buildConfigurationList = B2E5677E1B316D5800906840 /* Build configuration list for PBXNativeTarget "FastImageCache" */; + buildPhases = ( + B2E567631B316D5800906840 /* Sources */, + B2E567641B316D5800906840 /* Frameworks */, + B2E567651B316D5800906840 /* Headers */, + B2E567661B316D5800906840 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FastImageCache; + productName = FastImageCache; + productReference = B2E567681B316D5800906840 /* FastImageCache.framework */; + productType = "com.apple.product-type.framework"; + }; + B2E567721B316D5800906840 /* FastImageCacheTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = B2E567811B316D5800906840 /* Build configuration list for PBXNativeTarget "FastImageCacheTests" */; + buildPhases = ( + B2E5676F1B316D5800906840 /* Sources */, + B2E567701B316D5800906840 /* Frameworks */, + B2E567711B316D5800906840 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + B2E567761B316D5800906840 /* PBXTargetDependency */, + ); + name = FastImageCacheTests; + productName = FastImageCacheTests; + productReference = B2E567731B316D5800906840 /* FastImageCacheTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + B2E567A61B316DCA00906840 /* FastImageCacheDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = B2E567C71B316DCB00906840 /* Build configuration list for PBXNativeTarget "FastImageCacheDemo" */; + buildPhases = ( + B2E567A31B316DCA00906840 /* Sources */, + B2E567A41B316DCA00906840 /* Frameworks */, + B2E567A51B316DCA00906840 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FastImageCacheDemo; + productName = FastImageCacheDemo; + productReference = B2E567A71B316DCA00906840 /* FastImageCacheDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B2E5675F1B316D5800906840 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = Path; + TargetAttributes = { + B2E567671B316D5800906840 = { + CreatedOnToolsVersion = 6.3.2; + }; + B2E567721B316D5800906840 = { + CreatedOnToolsVersion = 6.3.2; + }; + B2E567A61B316DCA00906840 = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = B2E567621B316D5800906840 /* Build configuration list for PBXProject "FastImageCache" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = B2E5675E1B316D5800906840; + productRefGroup = B2E567691B316D5800906840 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B2E567671B316D5800906840 /* FastImageCache */, + B2E567721B316D5800906840 /* FastImageCacheTests */, + B2E567A61B316DCA00906840 /* FastImageCacheDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + B2E567661B316D5800906840 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B2E567711B316D5800906840 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B2E567A51B316DCA00906840 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E567E41B316E2200906840 /* fetch_demo_images.sh in Resources */, + BFD6BFFB1B68FD5D005292DC /* Demo Images in Resources */, + B2E567E61B316E3700906840 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B2E567631B316D5800906840 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E5679B1B316D9600906840 /* FICImageTable.m in Sources */, + B2E5679D1B316D9600906840 /* FICImageTableChunk.m in Sources */, + B2E567971B316D9600906840 /* FICImageCache.m in Sources */, + B2E567A21B316D9600906840 /* FICUtilities.m in Sources */, + B2E5679F1B316D9600906840 /* FICImageTableEntry.m in Sources */, + B2E567991B316D9600906840 /* FICImageFormat.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B2E5676F1B316D5800906840 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E5677B1B316D5800906840 /* FastImageCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B2E567A31B316DCA00906840 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E567DA1B316E1000906840 /* FICDAppDelegate.m in Sources */, + B2E567EB1B316E6600906840 /* FICImageTableChunk.m in Sources */, + B2E567E91B316E6600906840 /* FICImageFormat.m in Sources */, + B2E567AC1B316DCA00906840 /* main.m in Sources */, + B2E567EA1B316E6600906840 /* FICImageTable.m in Sources */, + B2E567DD1B316E1000906840 /* FICDPhotosTableViewCell.m in Sources */, + B2E567E81B316E6600906840 /* FICImageCache.m in Sources */, + B2E567EC1B316E6600906840 /* FICImageTableEntry.m in Sources */, + B2E567DF1B316E1000906840 /* FICDViewController.m in Sources */, + B2E567DC1B316E1000906840 /* FICDPhoto.m in Sources */, + B2E567DB1B316E1000906840 /* FICDFullscreenPhotoDisplayController.m in Sources */, + B2E567DE1B316E1000906840 /* FICDTableView.m in Sources */, + B2E567E71B316E5F00906840 /* FICUtilities.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + B2E567761B316D5800906840 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B2E567671B316D5800906840 /* FastImageCache */; + targetProxy = B2E567751B316D5800906840 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + B2E5677C1B316D5800906840 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B2E5677D1B316D5800906840 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B2E5677F1B316D5800906840 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = FastImageCache/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.path.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + B2E567801B316D5800906840 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = FastImageCache/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.path.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + B2E567821B316D5800906840 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = FastImageCacheTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.path.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + B2E567831B316D5800906840 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = FastImageCacheTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.path.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + B2E567C81B316DCB00906840 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = Icon; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = FastImageCacheDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.path.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + B2E567C91B316DCB00906840 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = Icon; + INFOPLIST_FILE = FastImageCacheDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.path.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B2E567621B316D5800906840 /* Build configuration list for PBXProject "FastImageCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B2E5677C1B316D5800906840 /* Debug */, + B2E5677D1B316D5800906840 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B2E5677E1B316D5800906840 /* Build configuration list for PBXNativeTarget "FastImageCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B2E5677F1B316D5800906840 /* Debug */, + B2E567801B316D5800906840 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B2E567811B316D5800906840 /* Build configuration list for PBXNativeTarget "FastImageCacheTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B2E567821B316D5800906840 /* Debug */, + B2E567831B316D5800906840 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B2E567C71B316DCB00906840 /* Build configuration list for PBXNativeTarget "FastImageCacheDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B2E567C81B316DCB00906840 /* Debug */, + B2E567C91B316DCB00906840 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B2E5675F1B316D5800906840 /* Project object */; +} diff --git a/FastImageCache/FastImageCache.xcodeproj/xcshareddata/xcschemes/FastImageCache.xcscheme b/FastImageCache/FastImageCache.xcodeproj/xcshareddata/xcschemes/FastImageCache.xcscheme new file mode 100644 index 0000000..e561d4a --- /dev/null +++ b/FastImageCache/FastImageCache.xcodeproj/xcshareddata/xcschemes/FastImageCache.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FastImageCache/FastImageCache/FastImageCache.h b/FastImageCache/FastImageCache/FastImageCache.h new file mode 100644 index 0000000..a78ddc1 --- /dev/null +++ b/FastImageCache/FastImageCache/FastImageCache.h @@ -0,0 +1,19 @@ +// +// FastImageCache.h +// FastImageCache +// +// Created by Rui Peres on 17/06/2015. +// Copyright (c) 2015 Path. All rights reserved. +// + +#import + +//! Project version number for FastImageCache. +FOUNDATION_EXPORT double FastImageCacheVersionNumber; + +//! Project version string for FastImageCache. +FOUNDATION_EXPORT const unsigned char FastImageCacheVersionString[]; + +#import +#import +#import \ No newline at end of file diff --git a/FastImageCache/FICEntity.h b/FastImageCache/FastImageCache/FastImageCache/FICEntity.h similarity index 89% rename from FastImageCache/FICEntity.h rename to FastImageCache/FastImageCache/FastImageCache/FICEntity.h index 04ad9b0..5a4eccd 100644 --- a/FastImageCache/FICEntity.h +++ b/FastImageCache/FastImageCache/FastImageCache/FICEntity.h @@ -9,6 +9,8 @@ #import "FICImports.h" @class FICImageFormat; +NS_ASSUME_NONNULL_BEGIN + typedef void (^FICEntityImageDrawingBlock)(CGContextRef context, CGSize contextSize); /** @@ -24,7 +26,7 @@ typedef void (^FICEntityImageDrawingBlock)(CGContextRef context, CGSize contextS @discussion Within each image table, each entry is identified by an entity's UUID. Ideally, this value should never change for an entity. For example, if your entity class is a person model, its UUID might be an API-assigned, unchanging, unique user ID. No matter how the properties of the person change, its user ID should never change. */ -@property (nonatomic, copy, readonly) NSString *UUID; +@property (nonatomic, copy, readonly) NSString *fic_UUID; /** A string that uniquely identifies an entity's source image. @@ -32,7 +34,7 @@ typedef void (^FICEntityImageDrawingBlock)(CGContextRef context, CGSize contextS @discussion While `` should be unchanging, a source image UUID might change. For example, if your entity class is a person model, its source image UUID might change every time the person changes their profile photo. In this case, the source image UUID might be a hash of the profile photo URL (assuming each image is given a unique URL). */ -@property (nonatomic, copy, readonly) NSString *sourceImageUUID; +@property (nonatomic, copy, readonly) NSString *fic_sourceImageUUID; /** Returns the source image URL associated with a specific format name. @@ -52,7 +54,8 @@ typedef void (^FICEntityImageDrawingBlock)(CGContextRef context, CGSize contextS @see FICImageFormat @see [FICImageCacheDelegate imageCache:wantsSourceImageForEntity:withFormatName:completionBlock:] */ -- (NSURL *)sourceImageURLWithFormatName:(NSString *)formatName; +- (nullable NSURL *)fic_sourceImageURLWithFormatName:(NSString *)formatName; + /** Returns the drawing block for a specific image and format name. @@ -73,7 +76,7 @@ typedef void (^FICEntityImageDrawingBlock)(CGContextRef context, CGSize contextS @note This block will always be called from the serial dispatch queue used by the image cache. */ -- (FICEntityImageDrawingBlock)drawingBlockForImage:(UIImage *)image withFormatName:(NSString *)formatName; +- (nullable FICEntityImageDrawingBlock)fic_drawingBlockForImage:(UIImage *)image withFormatName:(NSString *)formatName; @optional /** @@ -81,6 +84,8 @@ typedef void (^FICEntityImageDrawingBlock)(CGContextRef context, CGSize contextS @param format The image format that identifies which image table is requesting the source image. */ -- (UIImage *)imageForFormat:(FICImageFormat *)format; +- (nullable UIImage *)fic_imageForFormat:(FICImageFormat *)format; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/FastImageCache/FICImageCache+FICErrorLogging.h b/FastImageCache/FastImageCache/FastImageCache/FICImageCache+FICErrorLogging.h similarity index 100% rename from FastImageCache/FICImageCache+FICErrorLogging.h rename to FastImageCache/FastImageCache/FastImageCache/FICImageCache+FICErrorLogging.h diff --git a/FastImageCache/FICImageCache.h b/FastImageCache/FastImageCache/FastImageCache/FICImageCache.h similarity index 93% rename from FastImageCache/FICImageCache.h rename to FastImageCache/FastImageCache/FastImageCache/FICImageCache.h index f4eea5b..bb102a0 100644 --- a/FastImageCache/FICImageCache.h +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageCache.h @@ -13,8 +13,10 @@ @protocol FICEntity; @protocol FICImageCacheDelegate; -typedef void (^FICImageCacheCompletionBlock)(id entity, NSString *formatName, UIImage *image); -typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); +typedef void (^FICImageCacheCompletionBlock)(id _Nullable entity, NSString * _Nonnull formatName, UIImage * _Nullable image); +typedef void (^FICImageRequestCompletionBlock)(UIImage * _Nullable sourceImage); + +NS_ASSUME_NONNULL_BEGIN /** `FICImageCache` is the primary class for managing and interacting with the image cache. Applications using the image cache create one or more `` @@ -98,7 +100,7 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); @note Once the image formats have been set, subsequent calls to this method will do nothing. */ -- (void)setFormats:(NSArray *)formats; +- (void)setFormats:(NSArray *)formats; /** Returns an image format previously associated with the image cache. @@ -107,7 +109,7 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); @return An image format with the name `formatName` or `nil` if no format with that name exists. */ -- (FICImageFormat *)formatWithName:(NSString *)formatName; +- (nullable FICImageFormat *)formatWithName:(NSString *)formatName; /** Returns all the image formats of the same family previously associated with the image cache. @@ -116,7 +118,7 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); @return An array of `` objects whose family is `family` or `nil` if no format belongs to that family. */ -- (NSArray *)formatsWithFamily:(NSString *)family; +- (nullable NSArray *)formatsWithFamily:(NSString *)family; ///----------------------------------------------- /// @name Storing, Retrieving, and Deleting Images @@ -141,14 +143,14 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); typedef void (^FICImageCacheCompletionBlock)(id entity, NSString *formatName, UIImage *image) */ -- (void)setImage:(UIImage *)image forEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(FICImageCacheCompletionBlock)completionBlock; +- (void)setImage:(UIImage *)image forEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(nullable FICImageCacheCompletionBlock)completionBlock; /** Attempts to synchronously retrieve an image from the image cache. @param entity The entity that uniquely identifies the source image. - @param formatName The format name that uniquely identifies which image table to look in for the cached image. + @param formatName The format name that uniquely identifies which image table to look in for the cached image. Must not be nil. @param completionBlock The completion block that is called when the requested image is available or if an error occurs. @@ -168,14 +170,14 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); @note You can always rely on the completion block being called. If an error occurs for any reason, the `image` parameter of the completion block will be `nil`. See <[FICImageCacheDelegate imageCache:errorDidOccurWithMessage:]> for information about being notified when errors occur. */ -- (BOOL)retrieveImageForEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(FICImageCacheCompletionBlock)completionBlock; +- (BOOL)retrieveImageForEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(nullable FICImageCacheCompletionBlock)completionBlock; /** Asynchronously retrieves an image from the image cache. @param entity The entity that uniquely identifies the source image. - @param formatName The format name that uniquely identifies which image table to look in for the cached image. + @param formatName The format name that uniquely identifies which image table to look in for the cached image. Must not be nil. @param completionBlock The completion block that is called when the requested image is available or if an error occurs. @@ -193,7 +195,7 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); @see [FICImageCache retrieveImageForEntity:withFormatName:completionBlock:] */ -- (BOOL)asynchronouslyRetrieveImageForEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(FICImageCacheCompletionBlock)completionBlock; +- (BOOL)asynchronouslyRetrieveImageForEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(nullable FICImageCacheCompletionBlock)completionBlock; /** Deletes an image from the image cache. @@ -281,7 +283,7 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); the URL returned by <[FICEntity sourceImageURLWithFormatName:]>, deserializing the image data when the request completes, and finally calling this method's completion block to provide the image cache with the source image. */ -- (void)imageCache:(FICImageCache *)imageCache wantsSourceImageForEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(FICImageRequestCompletionBlock)completionBlock; +- (void)imageCache:(FICImageCache *)imageCache wantsSourceImageForEntity:(id )entity withFormatName:(NSString *)formatName completionBlock:(nullable FICImageRequestCompletionBlock)completionBlock; /** This method is called on the delegate when the image cache has received an image retrieval cancellation request. @@ -332,3 +334,5 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage); - (void)imageCache:(FICImageCache *)imageCache errorDidOccurWithMessage:(NSString *)errorMessage; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/FastImageCache/FICImageCache.m b/FastImageCache/FastImageCache/FastImageCache/FICImageCache.m similarity index 69% rename from FastImageCache/FICImageCache.m rename to FastImageCache/FastImageCache/FastImageCache/FICImageCache.m index a3ba54f..1aee1cf 100644 --- a/FastImageCache/FICImageCache.m +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageCache.m @@ -25,7 +25,6 @@ @interface FICImageCache () { NSMutableDictionary *_formats; NSMutableDictionary *_imageTables; NSMutableDictionary *_requests; - __weak id _delegate; BOOL _delegateImplementsWantsSourceImageForEntityWithFormatNameCompletionBlock; BOOL _delegateImplementsShouldProcessAllFormatsInFamilyForEntity; @@ -54,18 +53,15 @@ - (void)setDelegate:(id)delegate { } } -static FICImageCache *__imageCache = nil; - #pragma mark - Object Lifecycle + (instancetype)sharedImageCache { - if (__imageCache == nil) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - __imageCache = [[[self class] alloc] init]; - }); - } - + static dispatch_once_t onceToken; + static FICImageCache *__imageCache = nil; + dispatch_once(&onceToken, ^{ + __imageCache = [[[self class] alloc] init]; + }); + return __imageCache; } @@ -162,11 +158,13 @@ - (BOOL)asynchronouslyRetrieveImageForEntity:(id )entity withFormatNa } - (BOOL)_retrieveImageForEntity:(id )entity withFormatName:(NSString *)formatName loadSynchronously:(BOOL)loadSynchronously completionBlock:(FICImageCacheCompletionBlock)completionBlock { + NSParameterAssert(formatName); + BOOL imageExists = NO; FICImageTable *imageTable = [_imageTables objectForKey:formatName]; - NSString *entityUUID = [entity UUID]; - NSString *sourceImageUUID = [entity sourceImageUUID]; + NSString *entityUUID = [entity fic_UUID]; + NSString *sourceImageUUID = [entity fic_sourceImageUUID]; if (loadSynchronously == NO && [imageTable entryExistsForEntityUUID:entityUUID sourceImageUUID:sourceImageUUID]) { imageExists = YES; @@ -198,34 +196,40 @@ - (BOOL)_retrieveImageForEntity:(id )entity withFormatName:(NSString if (image == nil) { // No image for this UUID exists in the image table. We'll need to ask the delegate to retrieve the source asset. - NSURL *sourceImageURL = [entity sourceImageURLWithFormatName:formatName]; + NSURL *sourceImageURL = [entity fic_sourceImageURLWithFormatName:formatName]; if (sourceImageURL != nil) { // We check to see if this image is already being fetched. - NSMutableDictionary *requestDictionary = [_requests objectForKey:sourceImageURL]; - if (requestDictionary == nil) { - // If we're here, then we aren't currently fetching this image. - NSMutableDictionary *requestDictionary = [NSMutableDictionary dictionary]; - [_requests setObject:requestDictionary forKey:sourceImageURL]; - - _FICAddCompletionBlockForEntity(formatName, requestDictionary, entity, completionBlock); - UIImage *image; - if ([entity respondsToSelector:@selector(imageForFormat:)]){ - FICImageFormat *format = [self formatWithName:formatName]; - image = [entity imageForFormat:format]; + BOOL needsToFetch = NO; + @synchronized (_requests) { + NSMutableDictionary *requestDictionary = [_requests objectForKey:sourceImageURL]; + if (requestDictionary == nil) { + // If we're here, then we aren't currently fetching this image. + requestDictionary = [NSMutableDictionary dictionary]; + [_requests setObject:requestDictionary forKey:sourceImageURL]; + needsToFetch = YES; } - if (image){ - [self _imageDidLoad:image forURL:sourceImageURL]; - } else if (_delegateImplementsWantsSourceImageForEntityWithFormatNameCompletionBlock){ - [_delegate imageCache:self wantsSourceImageForEntity:entity withFormatName:formatName completionBlock:^(UIImage *sourceImage) { - [self _imageDidLoad:sourceImage forURL:sourceImageURL]; - }]; - } - } else { - // We have an existing request dictionary, which means this URL is currently being fetched. _FICAddCompletionBlockForEntity(formatName, requestDictionary, entity, completionBlock); } + + if (needsToFetch) { + @autoreleasepool { + UIImage *image; + if ([entity respondsToSelector:@selector(fic_imageForFormat:)]){ + FICImageFormat *format = [self formatWithName:formatName]; + image = [entity fic_imageForFormat:format]; + } + + if (image){ + [self _imageDidLoad:image forURL:sourceImageURL]; + } else if (_delegateImplementsWantsSourceImageForEntityWithFormatNameCompletionBlock){ + [_delegate imageCache:self wantsSourceImageForEntity:entity withFormatName:formatName completionBlock:^(UIImage *sourceImage) { + [self _imageDidLoad:sourceImage forURL:sourceImageURL]; + }]; + } + } + } } else { NSString *message = [NSString stringWithFormat:@"*** FIC Error: %s entity %@ returned a nil source image URL for image format %@.", __PRETTY_FUNCTION__, entity, formatName]; [self _logMessage:message]; @@ -241,14 +245,20 @@ - (BOOL)_retrieveImageForEntity:(id )entity withFormatName:(NSString } - (void)_imageDidLoad:(UIImage *)image forURL:(NSURL *)URL { - NSDictionary *requestDictionary = [_requests objectForKey:URL]; + NSDictionary *requestDictionary; + @synchronized (_requests) { + requestDictionary = [_requests objectForKey:URL]; + [_requests removeObjectForKey:URL]; + // Now safe to use requestsDictionary outside the lock, because we've taken ownership from _requests + } + if (requestDictionary != nil) { for (NSMutableDictionary *entityDictionary in [requestDictionary allValues]) { id entity = [entityDictionary objectForKey:FICImageCacheEntityKey]; NSString *formatName = [entityDictionary objectForKey:FICImageCacheFormatKey]; NSDictionary *completionBlocksDictionary = [entityDictionary objectForKey:FICImageCacheCompletionBlocksKey]; if (image != nil){ - [self _processImage:image forEntity:entity withFormatName:formatName completionBlocksDictionary:completionBlocksDictionary]; + [self _processImage:image forEntity:entity completionBlocksDictionary:completionBlocksDictionary]; } else { NSArray *completionBlocks = [completionBlocksDictionary objectForKey:formatName]; if (completionBlocks != nil) { @@ -261,12 +271,10 @@ - (void)_imageDidLoad:(UIImage *)image forURL:(NSURL *)URL { } } } - - [_requests removeObjectForKey:URL]; } static void _FICAddCompletionBlockForEntity(NSString *formatName, NSMutableDictionary *entityRequestsDictionary, id entity, FICImageCacheCompletionBlock completionBlock) { - NSString *entityUUID = [entity UUID]; + NSString *entityUUID = [entity fic_UUID]; NSMutableDictionary *requestDictionary = [entityRequestsDictionary objectForKey:entityUUID]; NSMutableDictionary *completionBlocks = nil; @@ -307,67 +315,44 @@ - (void)setImage:(UIImage *)image forEntity:(id )entity withFormatNam completionBlocksDictionary = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:[completionBlock copy]] forKey:formatName]; } - NSString *entityUUID = [entity UUID]; + NSString *entityUUID = [entity fic_UUID]; FICImageTable *imageTable = [_imageTables objectForKey:formatName]; if (imageTable) { [imageTable deleteEntryForEntityUUID:entityUUID]; - [self _processImage:image forEntity:entity withFormatName:formatName completionBlocksDictionary:completionBlocksDictionary]; + [self _processImage:image forEntity:entity completionBlocksDictionary:completionBlocksDictionary]; } else { [self _logMessage:[NSString stringWithFormat:@"*** FIC Error: %s Couldn't find image table with format name %@", __PRETTY_FUNCTION__, formatName]]; } } } -- (void)_processImage:(UIImage *)image forEntity:(id )entity withFormatName:(NSString *)formatName completionBlocksDictionary:(NSDictionary *)completionBlocksDictionary { - FICImageFormat *imageFormat = [_formats objectForKey:formatName]; - NSString *formatFamily = [imageFormat family]; - NSString *entityUUID = [entity UUID]; - NSString *sourceImageUUID = [entity sourceImageUUID]; - - if (formatFamily != nil) { - BOOL shouldProcessAllFormatsInFamily = YES; - if (_delegateImplementsShouldProcessAllFormatsInFamilyForEntity) { - shouldProcessAllFormatsInFamily = [_delegate imageCache:self shouldProcessAllFormatsInFamily:formatFamily forEntity:entity]; - } - // All of the formats in a given family use the same source asset, so once we have that source asset, we can generate all of the family's formats. - for (FICImageTable *table in [_imageTables allValues]) { - FICImageFormat *imageFormat = [table imageFormat]; - NSString *tableFormatFamily = [imageFormat family]; - if ([formatFamily isEqualToString:tableFormatFamily]) { - NSArray *completionBlocks = [completionBlocksDictionary objectForKey:[imageFormat name]]; - - BOOL imageExistsForEntity = [table entryExistsForEntityUUID:entityUUID sourceImageUUID:sourceImageUUID]; - BOOL shouldProcessFamilyFormat = shouldProcessAllFormatsInFamily && imageExistsForEntity == NO; - if (shouldProcessFamilyFormat || [completionBlocks count] > 0) { - [self _processImage:image forEntity:entity imageTable:table completionBlocks:completionBlocks]; - } - } - } - } else { - FICImageTable *imageTable = [_imageTables objectForKey:formatName]; - NSArray *completionBlocks = [completionBlocksDictionary objectForKey:formatName]; +- (void)_processImage:(UIImage *)image forEntity:(id )entity completionBlocksDictionary:(NSDictionary *)completionBlocksDictionary { + for (NSString *formatToProcess in [self formatsToProcessForCompletionBlocks:completionBlocksDictionary + entity:entity]) { + FICImageTable *imageTable = [_imageTables objectForKey:formatToProcess]; + NSArray *completionBlocks = [completionBlocksDictionary objectForKey:formatToProcess]; [self _processImage:image forEntity:entity imageTable:imageTable completionBlocks:completionBlocks]; } } - (void)_processImage:(UIImage *)image forEntity:(id )entity imageTable:(FICImageTable *)imageTable completionBlocks:(NSArray *)completionBlocks { if (imageTable != nil) { - if ([entity UUID] == nil) { + if ([entity fic_UUID] == nil) { [self _logMessage:[NSString stringWithFormat:@"*** FIC Error: %s entity %@ is missing its UUID.", __PRETTY_FUNCTION__, entity]]; return; } - if ([entity sourceImageUUID] == nil) { + if ([entity fic_sourceImageUUID] == nil) { [self _logMessage:[NSString stringWithFormat:@"*** FIC Error: %s entity %@ is missing its source image UUID.", __PRETTY_FUNCTION__, entity]]; return; } - NSString *entityUUID = [entity UUID]; - NSString *sourceImageUUID = [entity sourceImageUUID]; + NSString *entityUUID = [entity fic_UUID]; + NSString *sourceImageUUID = [entity fic_sourceImageUUID]; FICImageFormat *imageFormat = [imageTable imageFormat]; NSString *imageFormatName = [imageFormat name]; - FICEntityImageDrawingBlock imageDrawingBlock = [entity drawingBlockForImage:image withFormatName:imageFormatName]; + FICEntityImageDrawingBlock imageDrawingBlock = [entity fic_drawingBlockForImage:image withFormatName:imageFormatName]; dispatch_async([FICImageCache dispatchQueue], ^{ [imageTable setEntryForEntityUUID:entityUUID sourceImageUUID:sourceImageUUID imageDrawingBlock:imageDrawingBlock]; @@ -386,12 +371,64 @@ - (void)_processImage:(UIImage *)image forEntity:(id )entity imageTab } } +- (NSSet *)formatsToProcessForCompletionBlocks:(NSDictionary *)completionBlocksDictionary entity:(id )entity { + // At the very least, we must process all formats with pending completion blocks + NSMutableSet *formatsToProcess = [NSMutableSet setWithArray:completionBlocksDictionary.allKeys]; + + // Get the list of format families included by the formats we have to process + NSMutableSet *families; + for (NSString *formatToProcess in formatsToProcess) { + FICImageTable *imageTable = _imageTables[formatToProcess]; + FICImageFormat *imageFormat = imageTable.imageFormat; + NSString *tableFormatFamily = imageFormat.family; + if (tableFormatFamily) { + if (!families) { + families = [NSMutableSet set]; + } + [families addObject:tableFormatFamily]; + } + } + + // The delegate can override the list of families to process + if (_delegateImplementsShouldProcessAllFormatsInFamilyForEntity) { + [families minusSet:[families objectsPassingTest:^BOOL(NSString *familyName, BOOL *stop) { + return ![_delegate imageCache:self shouldProcessAllFormatsInFamily:familyName forEntity:entity]; + }]]; + } + + // Ensure that all formats from all of those families are included in the list + if (families.count) { + for (FICImageTable *table in _imageTables.allValues) { + FICImageFormat *imageFormat = table.imageFormat; + NSString *imageFormatName = imageFormat.name; + // If we're already processing this format, keep looking + if ([formatsToProcess containsObject:imageFormatName]) { + continue; + } + + // If this format isn't included in any referenced family, keep looking + if (![families containsObject:imageFormat.family]) { + continue; + } + + // If the image already exists, keep going + if ([table entryExistsForEntityUUID:entity.fic_UUID sourceImageUUID:entity.fic_sourceImageUUID]) { + continue; + } + + [formatsToProcess addObject:imageFormatName]; + } + } + + return formatsToProcess; +} + #pragma mark - Checking for Image Existence - (BOOL)imageExistsForEntity:(id )entity withFormatName:(NSString *)formatName { FICImageTable *imageTable = [_imageTables objectForKey:formatName]; - NSString *entityUUID = [entity UUID]; - NSString *sourceImageUUID = [entity sourceImageUUID]; + NSString *entityUUID = [entity fic_UUID]; + NSString *sourceImageUUID = [entity fic_sourceImageUUID]; BOOL imageExists = [imageTable entryExistsForEntityUUID:entityUUID sourceImageUUID:sourceImageUUID]; @@ -402,33 +439,38 @@ - (BOOL)imageExistsForEntity:(id )entity withFormatName:(NSString *)f - (void)deleteImageForEntity:(id )entity withFormatName:(NSString *)formatName { FICImageTable *imageTable = [_imageTables objectForKey:formatName]; - NSString *entityUUID = [entity UUID]; + NSString *entityUUID = [entity fic_UUID]; [imageTable deleteEntryForEntityUUID:entityUUID]; } - (void)cancelImageRetrievalForEntity:(id )entity withFormatName:(NSString *)formatName { - NSURL *sourceImageURL = [entity sourceImageURLWithFormatName:formatName]; - NSMutableDictionary *requestDictionary = [_requests objectForKey:sourceImageURL]; - if (requestDictionary) { - NSString *entityUUID = [entity UUID]; - NSMutableDictionary *entityRequestsDictionary = [requestDictionary objectForKey:entityUUID]; - if (entityRequestsDictionary) { - NSMutableDictionary *completionBlocksDictionary = [entityRequestsDictionary objectForKey:FICImageCacheCompletionBlocksKey]; - [completionBlocksDictionary removeObjectForKey:formatName]; - - if ([completionBlocksDictionary count] == 0) { - [requestDictionary removeObjectForKey:entityUUID]; - } - - if ([requestDictionary count] == 0) { - [_requests removeObjectForKey:sourceImageURL]; - - if (_delegateImplementsCancelImageLoadingForEntityWithFormatName) { - [_delegate imageCache:self cancelImageLoadingForEntity:entity withFormatName:formatName]; + NSURL *sourceImageURL = [entity fic_sourceImageURLWithFormatName:formatName]; + NSString *entityUUID = [entity fic_UUID]; + + BOOL cancelImageLoadingForEntity = NO; + @synchronized (_requests) { + NSMutableDictionary *requestDictionary = [_requests objectForKey:sourceImageURL]; + if (requestDictionary) { + NSMutableDictionary *entityRequestsDictionary = [requestDictionary objectForKey:entityUUID]; + if (entityRequestsDictionary) { + NSMutableDictionary *completionBlocksDictionary = [entityRequestsDictionary objectForKey:FICImageCacheCompletionBlocksKey]; + [completionBlocksDictionary removeObjectForKey:formatName]; + + if ([completionBlocksDictionary count] == 0) { + [requestDictionary removeObjectForKey:entityUUID]; + } + + if ([requestDictionary count] == 0) { + [_requests removeObjectForKey:sourceImageURL]; + cancelImageLoadingForEntity = YES; } } } } + + if (cancelImageLoadingForEntity && _delegateImplementsCancelImageLoadingForEntityWithFormatName) { + [_delegate imageCache:self cancelImageLoadingForEntity:entity withFormatName:formatName]; + } } - (void)reset { diff --git a/FastImageCache/FICImageFormat.h b/FastImageCache/FastImageCache/FastImageCache/FICImageFormat.h similarity index 98% rename from FastImageCache/FICImageFormat.h rename to FastImageCache/FastImageCache/FastImageCache/FICImageFormat.h index a5b70b8..31304ef 100644 --- a/FastImageCache/FICImageFormat.h +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageFormat.h @@ -34,6 +34,7 @@ typedef NS_ENUM(NSUInteger, FICImageFormatProtectionMode) { prevent the image cache from consuming too much disk space. Each `` managed by the image cache is associated with a single image format. */ +NS_ASSUME_NONNULL_BEGIN @interface FICImageFormat : NSObject ///------------------------------ @@ -152,7 +153,7 @@ typedef NS_ENUM(NSUInteger, FICImageFormatProtectionMode) { @discussion Fast Image Cache automatically serializes the image formats that it uses to disk. If an image format ever changes, Fast Image Cache automatically detects the change and invalidates the image table associated with that image format. The image table is then recreated from the updated image format. */ -@property (nonatomic, copy, readonly) NSDictionary *dictionaryRepresentation; +@property (nonatomic, copy, readonly) NSDictionary *dictionaryRepresentation; ///----------------------------------- /// @name Initializing an Image Format @@ -180,3 +181,4 @@ typedef NS_ENUM(NSUInteger, FICImageFormatProtectionMode) { + (instancetype)formatWithName:(NSString *)name family:(NSString *)family imageSize:(CGSize)imageSize style:(FICImageFormatStyle)style maximumCount:(NSInteger)maximumCount devices:(FICImageFormatDevices)devices protectionMode:(FICImageFormatProtectionMode)protectionMode; @end +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/FastImageCache/FICImageFormat.m b/FastImageCache/FastImageCache/FastImageCache/FICImageFormat.m similarity index 100% rename from FastImageCache/FICImageFormat.m rename to FastImageCache/FastImageCache/FastImageCache/FICImageFormat.m diff --git a/FastImageCache/FICImageTable.h b/FastImageCache/FastImageCache/FastImageCache/FICImageTable.h similarity index 92% rename from FastImageCache/FICImageTable.h rename to FastImageCache/FastImageCache/FastImageCache/FICImageTable.h index 616f9ab..c4f542e 100644 --- a/FastImageCache/FICImageTable.h +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageTable.h @@ -15,6 +15,8 @@ @class FICImageTableEntry; @class FICImage; +NS_ASSUME_NONNULL_BEGIN + extern NSString *const FICImageTableEntryDataVersionKey; extern NSString *const FICImageTableScreenScaleKey; @@ -81,7 +83,9 @@ extern NSString *const FICImageTableScreenScaleKey; @warning `FICImageTable` raises an exception if `imageFormat` is `nil`. `FICImageTable`'s implementation of `-init` simply calls through to this initializer, passing `nil` for `imageFormat`. */ -- (instancetype)initWithFormat:(FICImageFormat *)imageFormat imageCache:(FICImageCache *)imageCache; +- (nullable instancetype)initWithFormat:(FICImageFormat *)imageFormat imageCache:(FICImageCache *)imageCache NS_DESIGNATED_INITIALIZER; +-(instancetype) init __attribute__((unavailable("Invoke the designated initializer initWithFormat:imageCache: instead"))); ++(instancetype) new __attribute__((unavailable("Invoke the designated initializer initWithFormat:imageCache: instead"))); ///------------------------------------------------ /// @name Storing, Retrieving, and Deleting Entries @@ -123,7 +127,7 @@ extern NSString *const FICImageTableScreenScaleKey; @note If either the entity UUID or the source image UUID doesn't match the corresponding UUIDs in the entry data, then something has changed. The entry data is deleted for the provided entity UUID, and `nil` is returned. */ -- (UIImage *)newImageForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *)sourceImageUUID preheatData:(BOOL)preheatData; +- (nullable UIImage *)newImageForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *)sourceImageUUID preheatData:(BOOL)preheatData; /** Deletes image entry data in the image table. @@ -164,3 +168,5 @@ extern NSString *const FICImageTableScreenScaleKey; - (void)reset; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/FastImageCache/FICImageTable.m b/FastImageCache/FastImageCache/FastImageCache/FICImageTable.m similarity index 88% rename from FastImageCache/FICImageTable.m rename to FastImageCache/FastImageCache/FastImageCache/FICImageTable.m index ee5a2e3..2925c02 100644 --- a/FastImageCache/FICImageTable.m +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageTable.m @@ -12,6 +12,7 @@ #import "FICImageTableChunk.h" #import "FICImageTableEntry.h" #import "FICUtilities.h" +#import #import "FICImageCache+FICErrorLogging.h" @@ -62,7 +63,8 @@ @interface FICImageTable () { NSMutableOrderedSet *_MRUEntries; NSCountedSet *_inUseEntries; NSDictionary *_imageFormatDictionary; - + int32_t _metadataVersion; + NSString *_fileDataProtectionMode; BOOL _canAccessData; } @@ -231,10 +233,6 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat imageCache:(FICImag return self; } -- (instancetype)init { - return [self initWithFormat:nil imageCache:nil]; -} - - (void)dealloc { if (_fileDescriptor >= 0) { close(_fileDescriptor); @@ -430,15 +428,16 @@ - (void)deleteEntryForEntityUUID:(NSString *)entityUUID { if (entityUUID != nil) { [_lock lock]; + NSInteger MRUIndex = [_MRUEntries indexOfObject:entityUUID]; + if (MRUIndex != NSNotFound) { + [_MRUEntries removeObjectAtIndex:MRUIndex]; + } + NSInteger index = [self _indexOfEntryForEntityUUID:entityUUID]; if (index != NSNotFound) { [_sourceImageMap removeObjectForKey:entityUUID]; [_indexMap removeObjectForKey:entityUUID]; [_occupiedIndexes removeIndex:index]; - NSInteger index = [_MRUEntries indexOfObject:entityUUID]; - if (index != NSNotFound) { - [_MRUEntries removeObjectAtIndex:index]; - } [self saveMetadata]; } @@ -511,23 +510,29 @@ - (void)_setEntryCount:(NSInteger)entryCount { // accessible and when you try to use that data. Sidestep this issue altogether // by using NSFileProtectionNone - (BOOL)canAccessEntryData { - BOOL result = YES; - if ([_fileDataProtectionMode isEqualToString:NSFileProtectionComplete]) { - result = [[UIApplication sharedApplication] isProtectedDataAvailable]; - } else if ([_fileDataProtectionMode isEqualToString:NSFileProtectionCompleteUntilFirstUserAuthentication]) { - // For "complete until first auth", if we were previously able to access data, then we'll still be able to - // access it. If we haven't yet been able to access data, we'll need to try until we are successful. - if (_canAccessData == NO) { - if ([[UIApplication sharedApplication] isProtectedDataAvailable]) { - // we are unlocked, so we're good to go. - _canAccessData = YES; - } else { - // we are locked, so try to access data. - _canAccessData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_filePath] options:NSDataReadingMappedAlways error:NULL] != nil; - } - } + if ([_fileDataProtectionMode isEqualToString:NSFileProtectionNone]) + return YES; + + if ([_fileDataProtectionMode isEqualToString:NSFileProtectionCompleteUntilFirstUserAuthentication] && _canAccessData) + return YES; + + // -[UIApplication isProtectedDataAvailable] checks whether the keybag is locked or not + UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; + if (application) { + _canAccessData = [application isProtectedDataAvailable]; + } + + // We have to fallback to a direct check on the file if either: + // - The application doesn't exist (happens in some extensions) + // - The keybag is locked, but the file might still be accessible because the mode is "until first user authentication" + if (!application || (!_canAccessData && [_fileDataProtectionMode isEqualToString:NSFileProtectionCompleteUntilFirstUserAuthentication])) { + int fd; + _canAccessData = ((fd = open([_filePath fileSystemRepresentation], O_RDONLY)) != -1); + if (_canAccessData) + close(fd); } - return result; + + return _canAccessData; } - (FICImageTableEntry *)_entryDataAtIndex:(NSInteger)index { @@ -676,36 +681,61 @@ - (NSNumber *)_numberForEntryAtIndex:(NSInteger)index { #pragma mark - Working with Metadata - (void)saveMetadata { - [_lock lock]; - - NSDictionary *metadataDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - [_indexMap copy], FICImageTableIndexMapKey, - [_sourceImageMap copy], FICImageTableContextMapKey, - [[_MRUEntries array] copy], FICImageTableMRUArrayKey, - [_imageFormatDictionary copy], FICImageTableFormatKey, nil]; - [_lock unlock]; - - static dispatch_queue_t __metadataQueue = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - __metadataQueue = dispatch_queue_create("com.path.FastImageCache.ImageTableMetadataQueue", NULL); - }); - - dispatch_async(__metadataQueue, ^{ - NSData *data = [NSPropertyListSerialization dataWithPropertyList:metadataDictionary format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL]; - BOOL fileWriteResult = [data writeToFile:[self metadataFilePath] atomically:NO]; - if (fileWriteResult == NO) { - NSString *message = [NSString stringWithFormat:@"*** FIC Error: %s couldn't write metadata for format %@", __PRETTY_FUNCTION__, [_imageFormat name]]; - [self.imageCache _logMessage:message]; - } - }); + @autoreleasepool { + [_lock lock]; + + NSDictionary *metadataDictionary = [NSDictionary dictionaryWithObjectsAndKeys: + [_indexMap copy], FICImageTableIndexMapKey, + [_sourceImageMap copy], FICImageTableContextMapKey, + [[_MRUEntries array] copy], FICImageTableMRUArrayKey, + [_imageFormatDictionary copy], FICImageTableFormatKey, nil]; + + __block int32_t metadataVersion = OSAtomicIncrement32(&_metadataVersion); + + [_lock unlock]; + + static dispatch_queue_t __metadataQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + __metadataQueue = dispatch_queue_create("com.path.FastImageCache.ImageTableMetadataQueue", NULL); + }); + + dispatch_async(__metadataQueue, ^{ + // Cancel serialization if a new metadata version is queued to be saved + if (metadataVersion != _metadataVersion) { + return; + } + + @autoreleasepool { + NSData *data = [NSJSONSerialization dataWithJSONObject:metadataDictionary options:kNilOptions error:NULL]; + + // Cancel disk writing if a new metadata version is queued to be saved + if (metadataVersion != _metadataVersion) { + return; + } + + BOOL fileWriteResult = [data writeToFile:[self metadataFilePath] atomically:NO]; + if (fileWriteResult == NO) { + NSString *message = [NSString stringWithFormat:@"*** FIC Error: %s couldn't write metadata for format %@", __PRETTY_FUNCTION__, [_imageFormat name]]; + [self.imageCache _logMessage:message]; + } + } + }); + } } - (void)_loadMetadata { NSString *metadataFilePath = [self metadataFilePath]; NSData *metadataData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:metadataFilePath] options:NSDataReadingMappedAlways error:NULL]; if (metadataData != nil) { - NSDictionary *metadataDictionary = (NSDictionary *)[NSPropertyListSerialization propertyListWithData:metadataData options:0 format:NULL error:NULL]; + NSDictionary *metadataDictionary = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:metadataData options:kNilOptions error:NULL]; + + if (!metadataDictionary) { + // The image table was likely previously stored as a .plist + // We'll read it into memory as a .plist and later store it (during -saveMetadata) using NSJSONSerialization for performance reasons + metadataDictionary = (NSDictionary *)[NSPropertyListSerialization propertyListWithData:metadataData options:0 format:NULL error:NULL]; + } + NSDictionary *formatDictionary = [metadataDictionary objectForKey:FICImageTableFormatKey]; if ([formatDictionary isEqualToDictionary:_imageFormatDictionary] == NO) { // Something about this image format has changed, so the existing metadata is no longer valid. The image table file diff --git a/FastImageCache/FICImageTableChunk.h b/FastImageCache/FastImageCache/FastImageCache/FICImageTableChunk.h similarity index 89% rename from FastImageCache/FICImageTableChunk.h rename to FastImageCache/FastImageCache/FastImageCache/FICImageTableChunk.h index 53b0308..60fd8c5 100644 --- a/FastImageCache/FICImageTableChunk.h +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageTableChunk.h @@ -8,6 +8,8 @@ #import "FICImports.h" +NS_ASSUME_NONNULL_BEGIN + @class FICImageTable; /** @@ -57,6 +59,8 @@ @return A new image table chunk. */ -- (instancetype)initWithFileDescriptor:(int)fileDescriptor index:(NSInteger)index length:(size_t)length; +- (nullable instancetype)initWithFileDescriptor:(int)fileDescriptor index:(NSInteger)index length:(size_t)length; + +@end -@end \ No newline at end of file +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/FastImageCache/FICImageTableChunk.m b/FastImageCache/FastImageCache/FastImageCache/FICImageTableChunk.m similarity index 100% rename from FastImageCache/FICImageTableChunk.m rename to FastImageCache/FastImageCache/FastImageCache/FICImageTableChunk.m diff --git a/FastImageCache/FICImageTableEntry.h b/FastImageCache/FastImageCache/FastImageCache/FICImageTableEntry.h similarity index 95% rename from FastImageCache/FICImageTableEntry.h rename to FastImageCache/FastImageCache/FastImageCache/FICImageTableEntry.h index a9ef850..2b8e8d9 100644 --- a/FastImageCache/FICImageTableEntry.h +++ b/FastImageCache/FastImageCache/FastImageCache/FICImageTableEntry.h @@ -8,6 +8,8 @@ #import "FICImports.h" +NS_ASSUME_NONNULL_BEGIN + @class FICImageTableChunk; @class FICImageCache; @@ -83,7 +85,7 @@ typedef struct { @return A new image table entry. */ -- (instancetype)initWithImageTableChunk:(FICImageTableChunk *)imageTableChunk bytes:(void *)bytes length:(size_t)length; +- (nullable instancetype)initWithImageTableChunk:(FICImageTableChunk *)imageTableChunk bytes:(void *)bytes length:(size_t)length; /** Adds a block to be executed when this image table entry is deallocated. @@ -122,3 +124,5 @@ typedef struct { + (NSInteger)metadataVersion; @end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/FastImageCache/FICImageTableEntry.m b/FastImageCache/FastImageCache/FastImageCache/FICImageTableEntry.m similarity index 100% rename from FastImageCache/FICImageTableEntry.m rename to FastImageCache/FastImageCache/FastImageCache/FICImageTableEntry.m diff --git a/FastImageCache/FICImports.h b/FastImageCache/FastImageCache/FastImageCache/FICImports.h similarity index 100% rename from FastImageCache/FICImports.h rename to FastImageCache/FastImageCache/FastImageCache/FICImports.h diff --git a/FastImageCache/FastImageCache/FastImageCache/FICUtilities.h b/FastImageCache/FastImageCache/FastImageCache/FICUtilities.h new file mode 100644 index 0000000..62c6abe --- /dev/null +++ b/FastImageCache/FastImageCache/FastImageCache/FICUtilities.h @@ -0,0 +1,17 @@ +// +// FICUtilities.h +// FastImageCache +// +// Copyright (c) 2013 Path, Inc. +// See LICENSE for full license agreement. +// + +#import "FICImports.h" + +size_t FICByteAlign(size_t bytesPerRow, size_t alignment); +size_t FICByteAlignForCoreAnimation(size_t bytesPerRow); + +NSString * _Nullable FICStringWithUUIDBytes(CFUUIDBytes UUIDBytes); +CFUUIDBytes FICUUIDBytesWithString(NSString * _Nonnull string); +CFUUIDBytes FICUUIDBytesFromMD5HashOfString(NSString * _Nonnull MD5Hash); // Useful for computing an entity's UUID from a URL, for example + diff --git a/FastImageCache/FICUtilities.m b/FastImageCache/FastImageCache/FastImageCache/FICUtilities.m similarity index 100% rename from FastImageCache/FICUtilities.m rename to FastImageCache/FastImageCache/FastImageCache/FICUtilities.m diff --git a/FastImageCache/FastImageCache/Info.plist b/FastImageCache/FastImageCache/Info.plist new file mode 100644 index 0000000..d3de8ee --- /dev/null +++ b/FastImageCache/FastImageCache/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/Contents.json b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/Contents.json similarity index 95% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/Contents.json rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/Contents.json index 6fb4d76..2e6e194 100644 --- a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/Contents.json +++ b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/Contents.json @@ -33,6 +33,11 @@ "filename" : "iPhone-App-iOS7@2x.png", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App-iOS7.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App-iOS7.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App-iOS7.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App-iOS7.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App-iOS7@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App-iOS7@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App-iOS7@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App-iOS7@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPad-App@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPad-App@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPhone-App-iOS7@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPhone-App-iOS7@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPhone-App-iOS7@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPhone-App-iOS7@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPhone-App.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPhone-App.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPhone-App.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPhone-App.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPhone-App@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPhone-App@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Icon.appiconset/iPhone-App@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Icon.appiconset/iPhone-App@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/Contents.json b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/Contents.json similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/Contents.json rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/Contents.json diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-1004h@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPad-Portrait-iOS7@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x-1.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x-1.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x-1.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x-1.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-R4@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-iOS7@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-iOS7@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-iOS7@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait-iOS7@2x.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait.png diff --git a/FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait@2x.png b/FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait@2x.png similarity index 100% rename from FastImageCacheDemo/Supporting Files/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait@2x.png rename to FastImageCache/FastImageCacheDemo/Assets.xcassets/Launch Image.launchimage/iPhone-Portrait@2x.png diff --git a/FastImageCacheDemo/Classes/FICDAppDelegate.h b/FastImageCache/FastImageCacheDemo/Classes/FICDAppDelegate.h similarity index 93% rename from FastImageCacheDemo/Classes/FICDAppDelegate.h rename to FastImageCache/FastImageCacheDemo/Classes/FICDAppDelegate.h index e946626..51e41f3 100644 --- a/FastImageCacheDemo/Classes/FICDAppDelegate.h +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDAppDelegate.h @@ -6,6 +6,8 @@ // See LICENSE for full license agreement. // +#import + @class FICDViewController; @interface FICDAppDelegate : UIResponder diff --git a/FastImageCacheDemo/Classes/FICDAppDelegate.m b/FastImageCache/FastImageCacheDemo/Classes/FICDAppDelegate.m similarity index 100% rename from FastImageCacheDemo/Classes/FICDAppDelegate.m rename to FastImageCache/FastImageCacheDemo/Classes/FICDAppDelegate.m diff --git a/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h b/FastImageCache/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h similarity index 96% rename from FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h rename to FastImageCache/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h index 821f7f8..2ccc662 100644 --- a/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h @@ -6,6 +6,9 @@ // See LICENSE for full license agreement. // +#import +#import + @class FICDPhoto; @protocol FICDFullscreenPhotoDisplayControllerDelegate; diff --git a/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.m b/FastImageCache/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.m similarity index 100% rename from FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.m rename to FastImageCache/FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.m diff --git a/FastImageCacheDemo/Classes/FICDPhoto.h b/FastImageCache/FastImageCacheDemo/Classes/FICDPhoto.h similarity index 100% rename from FastImageCacheDemo/Classes/FICDPhoto.h rename to FastImageCache/FastImageCacheDemo/Classes/FICDPhoto.h diff --git a/FastImageCacheDemo/Classes/FICDPhoto.m b/FastImageCache/FastImageCacheDemo/Classes/FICDPhoto.m similarity index 96% rename from FastImageCacheDemo/Classes/FICDPhoto.m rename to FastImageCache/FastImageCacheDemo/Classes/FICDPhoto.m index 425c4f2..b169cad 100644 --- a/FastImageCacheDemo/Classes/FICDPhoto.m +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDPhoto.m @@ -167,7 +167,7 @@ - (void)deleteThumbnail { #pragma mark - FICImageCacheEntity -- (NSString *)UUID { +- (NSString *)fic_UUID { if (_UUID == nil) { // MD5 hashing is expensive enough that we only want to do it once NSString *imageName = [_sourceImageURL lastPathComponent]; @@ -178,15 +178,15 @@ - (NSString *)UUID { return _UUID; } -- (NSString *)sourceImageUUID { - return [self UUID]; +- (NSString *)fic_sourceImageUUID { + return [self fic_UUID]; } -- (NSURL *)sourceImageURLWithFormatName:(NSString *)formatName { +- (NSURL *)fic_sourceImageURLWithFormatName:(NSString *)formatName { return _sourceImageURL; } -- (FICEntityImageDrawingBlock)drawingBlockForImage:(UIImage *)image withFormatName:(NSString *)formatName { +- (FICEntityImageDrawingBlock)fic_drawingBlockForImage:(UIImage *)image withFormatName:(NSString *)formatName { FICEntityImageDrawingBlock drawingBlock = ^(CGContextRef contextRef, CGSize contextSize) { CGRect contextBounds = CGRectZero; contextBounds.size = contextSize; diff --git a/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h b/FastImageCache/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h similarity index 89% rename from FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h rename to FastImageCache/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h index a925b6d..11d3b07 100644 --- a/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h @@ -6,6 +6,8 @@ // See LICENSE for full license agreement. // +#import + @class FICDPhoto; @protocol FICDPhotosTableViewCellDelegate; @@ -20,7 +22,7 @@ + (NSString *)reuseIdentifier; + (NSInteger)photosPerRow; + (CGFloat)outerPadding; -+ (CGFloat)rowHeightForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; ++ (CGFloat)rowHeight; @end diff --git a/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m b/FastImageCache/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m similarity index 70% rename from FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m rename to FastImageCache/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m index cf35c31..5c7c29d 100644 --- a/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m @@ -19,7 +19,7 @@ @interface FICDPhotosTableViewCell () { NSArray *_photos; NSString *_imageFormatName; - NSMutableArray *_imageViews; + NSArray *_imageViews; UITapGestureRecognizer *_tapGestureRecognizer; } @@ -39,42 +39,28 @@ @implementation FICDPhotosTableViewCell - (void)setPhotos:(NSArray *)photos { if (photos != _photos) { _photos = [photos copy]; - - // Either create the image views for this cell or clear them out if they already exist - if (_imageViews == nil) { - NSInteger photosPerRow = [[self class] photosPerRow]; - _imageViews = [[NSMutableArray alloc] initWithCapacity:photosPerRow]; - - for (NSInteger i = 0; i < photosPerRow; i++) { - UIImageView *imageView = [[UIImageView alloc] init]; - [imageView setContentMode:UIViewContentModeScaleAspectFill]; - [_imageViews addObject:imageView]; - } - } else { - for (UIImageView *imageView in _imageViews) { - [imageView setImage:nil]; - [imageView removeFromSuperview]; - } - } - - NSInteger photosCount = [_photos count]; - for (NSInteger i = 0; i < photosCount; i++) { - FICDPhoto *photo = [_photos objectAtIndex:i]; + + for (NSInteger i = 0; i < [_imageViews count]; i++) { UIImageView *imageView = [_imageViews objectAtIndex:i]; - - if (_usesImageTable) { - [[FICImageCache sharedImageCache] retrieveImageForEntity:photo withFormatName:_imageFormatName completionBlock:^(id entity, NSString *formatName, UIImage *image) { - // This completion block may be called much later. We should check to make sure this cell hasn't been reused for different photos before displaying the image that has loaded. - if (photos == [self photos]) { - [imageView setImage:image]; - } - }]; + + if (i < [_photos count]) { + FICDPhoto *photo = [_photos objectAtIndex:i]; + + if (_usesImageTable) { + [[FICImageCache sharedImageCache] retrieveImageForEntity:photo withFormatName:_imageFormatName completionBlock:^(id entity, NSString *formatName, UIImage *image) { + // This completion block may be called much later. We should check to make sure this cell hasn't been reused for different photos before displaying the image that has loaded. + if (photos == [self photos]) { + [imageView setImage:image]; + } + }]; + } else { + [imageView setImage:[photo thumbnailImage]]; + } } else { - [imageView setImage:[photo thumbnailImage]]; + // Last row might not be full + [imageView setImage:nil]; } } - - [self setNeedsLayout]; } } @@ -103,7 +89,7 @@ + (CGFloat)outerPadding { return outerPadding; } -+ (CGFloat)rowHeightForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { ++ (CGFloat)rowHeight { CGFloat rowHeight = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) ? 84 : 79; return rowHeight; @@ -117,6 +103,18 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus if (self != nil) { _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapGestureRecognizerStateDidChange)]; [self addGestureRecognizer:_tapGestureRecognizer]; + + NSInteger photosPerRow = [[self class] photosPerRow]; + NSMutableArray *imageViews = [[NSMutableArray alloc] initWithCapacity:photosPerRow]; + + for (NSInteger i = 0; i < photosPerRow; i++) { + UIImageView *imageView = [[UIImageView alloc] init]; + [imageView setContentMode:UIViewContentModeScaleAspectFill]; + [imageViews addObject:imageView]; + [self.contentView addSubview:imageView]; + } + + _imageViews = [imageViews copy]; } return self; @@ -139,14 +137,12 @@ - (void)layoutSubviews { CGFloat outerPadding = [[self class] outerPadding]; CGRect imageViewFrame = CGRectMake(outerPadding, outerPadding, FICDPhotoSquareImageSize.width, FICDPhotoSquareImageSize.height); - - UIView *contentView = [self contentView]; + NSInteger count = [_photos count]; for (NSInteger i = 0; i < count; i++) { UIImageView *imageView = [_imageViews objectAtIndex:i]; [imageView setFrame:imageViewFrame]; - [contentView addSubview:imageView]; imageViewFrame.origin.x += imageViewFrame.size.width + innerPadding; } diff --git a/FastImageCacheDemo/Classes/FICDTableView.h b/FastImageCache/FastImageCacheDemo/Classes/FICDTableView.h similarity index 91% rename from FastImageCacheDemo/Classes/FICDTableView.h rename to FastImageCache/FastImageCacheDemo/Classes/FICDTableView.h index 500fec9..14e8b39 100644 --- a/FastImageCacheDemo/Classes/FICDTableView.h +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDTableView.h @@ -6,6 +6,8 @@ // See LICENSE for full license agreement. // +#import + @interface FICDTableView : UITableView @property (nonatomic, assign, readonly) CGFloat averageFPS; diff --git a/FastImageCacheDemo/Classes/FICDTableView.m b/FastImageCache/FastImageCacheDemo/Classes/FICDTableView.m similarity index 100% rename from FastImageCacheDemo/Classes/FICDTableView.m rename to FastImageCache/FastImageCacheDemo/Classes/FICDTableView.m diff --git a/FastImageCacheDemo/Classes/FICDViewController.h b/FastImageCache/FastImageCacheDemo/Classes/FICDViewController.h similarity index 89% rename from FastImageCacheDemo/Classes/FICDViewController.h rename to FastImageCache/FastImageCacheDemo/Classes/FICDViewController.h index 54f3023..0cbe5fb 100644 --- a/FastImageCacheDemo/Classes/FICDViewController.h +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDViewController.h @@ -6,6 +6,8 @@ // See LICENSE for full license agreement. // +#import + @class FICDTableView; @interface FICDViewController : UIViewController diff --git a/FastImageCacheDemo/Classes/FICDViewController.m b/FastImageCache/FastImageCacheDemo/Classes/FICDViewController.m similarity index 96% rename from FastImageCacheDemo/Classes/FICDViewController.m rename to FastImageCache/FastImageCacheDemo/Classes/FICDViewController.m index 3495167..c81c8bd 100644 --- a/FastImageCacheDemo/Classes/FICDViewController.m +++ b/FastImageCache/FastImageCacheDemo/Classes/FICDViewController.m @@ -95,6 +95,7 @@ - (void)loadView { [_tableView setDelegate:self]; [_tableView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; + [_tableView registerClass:[FICDPhotosTableViewCell class] forCellReuseIdentifier:[FICDPhotosTableViewCell reuseIdentifier]]; CGFloat tableViewCellOuterPadding = [FICDPhotosTableViewCell outerPadding]; [_tableView setContentInset:UIEdgeInsetsMake(0, 0, tableViewCellOuterPadding, 0)]; @@ -110,13 +111,12 @@ - (void)loadView { // Configure the navigation item UINavigationItem *navigationItem = [self navigationItem]; - UIBarButtonItem *resetBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Reset" style:UIBarButtonItemStyleBordered target:self action:@selector(_reset)]; + UIBarButtonItem *resetBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Reset" style:UIBarButtonItemStylePlain target:self action:@selector(_reset)]; [navigationItem setLeftBarButtonItem:resetBarButtonItem]; UISegmentedControl *methodSegmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Conventional", @"Image Table", nil]]; [methodSegmentedControl setSelectedSegmentIndex:0]; [methodSegmentedControl addTarget:self action:@selector(_methodSegmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged]; - [methodSegmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar]; [methodSegmentedControl sizeToFit]; [navigationItem setTitleView:methodSegmentedControl]; @@ -152,7 +152,6 @@ - (void)loadView { UISegmentedControl *imageFormatStyleSegmentedControl = [[UISegmentedControl alloc] initWithItems:imageFormatStyleSegmentedControlTitles]; [imageFormatStyleSegmentedControl setSelectedSegmentIndex:0]; [imageFormatStyleSegmentedControl addTarget:self action:@selector(_imageFormatStyleSegmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged]; - [imageFormatStyleSegmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar]; [imageFormatStyleSegmentedControl setApportionsSegmentWidthsByContent:userInterfaceIdiomIsPhone]; [imageFormatStyleSegmentedControl sizeToFit]; @@ -463,13 +462,9 @@ - (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger) - (UITableViewCell*)tableView:(UITableView*)table cellForRowAtIndexPath:(NSIndexPath*)indexPath { NSString *reuseIdentifier = [FICDPhotosTableViewCell reuseIdentifier]; - FICDPhotosTableViewCell *tableViewCell = (FICDPhotosTableViewCell *)[table dequeueReusableCellWithIdentifier:reuseIdentifier]; - if (tableViewCell == nil) { - tableViewCell = [[FICDPhotosTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; - [tableViewCell setBackgroundColor:[table backgroundColor]]; - [tableViewCell setSelectionStyle:UITableViewCellSelectionStyleNone]; - } - + FICDPhotosTableViewCell *tableViewCell = (FICDPhotosTableViewCell *)[table dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; + tableViewCell.selectionStyle = UITableViewCellSeparatorStyleNone; + [tableViewCell setDelegate:self]; [tableViewCell setImageFormatName:_imageFormatName]; @@ -487,9 +482,7 @@ - (UITableViewCell*)tableView:(UITableView*)table cellForRowAtIndexPath:(NSIndex #pragma mark - UITableViewDelegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - CGFloat rowHeight = [FICDPhotosTableViewCell rowHeightForInterfaceOrientation:[self interfaceOrientation]]; - - return rowHeight; + return [FICDPhotosTableViewCell rowHeight]; } - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { @@ -553,7 +546,7 @@ - (void)photoDisplayController:(FICDFullscreenPhotoDisplayController *)photoDisp [self _updateStatusBarStyleForColorAveragedImage:colorAveragedImage]; } } else { - [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES]; + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES]; } } diff --git a/FastImageCacheDemo/Demo Images/README b/FastImageCache/FastImageCacheDemo/Demo Images/README similarity index 100% rename from FastImageCacheDemo/Demo Images/README rename to FastImageCache/FastImageCacheDemo/Demo Images/README diff --git a/FastImageCacheDemo/Supporting Files/FastImageCacheDemo-Prefix.pch b/FastImageCache/FastImageCacheDemo/FastImageCacheDemo-Prefix.pch similarity index 100% rename from FastImageCacheDemo/Supporting Files/FastImageCacheDemo-Prefix.pch rename to FastImageCache/FastImageCacheDemo/FastImageCacheDemo-Prefix.pch diff --git a/FastImageCacheDemo/Supporting Files/FastImageCacheDemo-Info.plist b/FastImageCache/FastImageCacheDemo/Info.plist similarity index 69% rename from FastImageCacheDemo/Supporting Files/FastImageCacheDemo-Info.plist rename to FastImageCache/FastImageCacheDemo/Info.plist index b48b80f..eabb3ae 100644 --- a/FastImageCacheDemo/Supporting Files/FastImageCacheDemo-Info.plist +++ b/FastImageCache/FastImageCacheDemo/Info.plist @@ -4,20 +4,14 @@ CFBundleDevelopmentRegion en - CFBundleDisplayName - FIC Demo CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIcons - - CFBundleIcons~ipad - + $(EXECUTABLE_NAME) CFBundleIdentifier - com.path.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString @@ -25,27 +19,27 @@ CFBundleSignature ???? CFBundleVersion - 1.0 + 1 LSRequiresIPhoneOS + UILaunchStoryboardName + LaunchScreen UIRequiredDeviceCapabilities armv7 - UIStatusBarHidden - - UIStatusBarHidden~ipad - UISupportedInterfaceOrientations UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight - UIViewControllerBasedStatusBarAppearance - diff --git a/FastImageCacheDemo/fetch_demo_images.sh b/FastImageCache/FastImageCacheDemo/fetch_demo_images.sh similarity index 100% rename from FastImageCacheDemo/fetch_demo_images.sh rename to FastImageCache/FastImageCacheDemo/fetch_demo_images.sh diff --git a/FastImageCacheDemo/Supporting Files/main.m b/FastImageCache/FastImageCacheDemo/main.m similarity index 57% rename from FastImageCacheDemo/Supporting Files/main.m rename to FastImageCache/FastImageCacheDemo/main.m index 3d5d2d3..0f2990b 100644 --- a/FastImageCacheDemo/Supporting Files/main.m +++ b/FastImageCache/FastImageCacheDemo/main.m @@ -2,13 +2,14 @@ // main.m // FastImageCacheDemo // -// Copyright (c) 2013 Path, Inc. -// See LICENSE for full license agreement. +// Created by Rui Peres on 17/06/2015. +// Copyright (c) 2015 Path. All rights reserved. // +#import #import "FICDAppDelegate.h" -int main(int argc, char *argv[]) { +int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([FICDAppDelegate class])); } diff --git a/FastImageCache/FastImageCacheTests/FastImageCacheTests.m b/FastImageCache/FastImageCacheTests/FastImageCacheTests.m new file mode 100644 index 0000000..8a16cdb --- /dev/null +++ b/FastImageCache/FastImageCacheTests/FastImageCacheTests.m @@ -0,0 +1,40 @@ +// +// FastImageCacheTests.m +// FastImageCacheTests +// +// Created by Rui Peres on 17/06/2015. +// Copyright (c) 2015 Path. All rights reserved. +// + +#import +#import + +@interface FastImageCacheTests : XCTestCase + +@end + +@implementation FastImageCacheTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + XCTAssert(YES, @"Pass"); +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/FastImageCache/FastImageCacheTests/Info.plist b/FastImageCache/FastImageCacheTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/FastImageCache/FastImageCacheTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/FastImageCacheDemo/FastImageCacheDemo.xcodeproj/project.pbxproj b/FastImageCacheDemo/FastImageCacheDemo.xcodeproj/project.pbxproj deleted file mode 100644 index 8decd75..0000000 --- a/FastImageCacheDemo/FastImageCacheDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,380 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 2E095B1417AEBB1200ECE160 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E095B1317AEBB1200ECE160 /* UIKit.framework */; }; - 2E095B1617AEBB1200ECE160 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E095B1517AEBB1200ECE160 /* Foundation.framework */; }; - 2E1BC8F017C57C4700836A7E /* FICImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8E417C57C4700836A7E /* FICImageCache.m */; }; - 2E1BC8F117C57C4700836A7E /* FICImageFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8E617C57C4700836A7E /* FICImageFormat.m */; }; - 2E1BC8F217C57C4700836A7E /* FICImageTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8E817C57C4700836A7E /* FICImageTable.m */; }; - 2E1BC8F317C57C4700836A7E /* FICImageTableChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8EA17C57C4700836A7E /* FICImageTableChunk.m */; }; - 2E1BC8F417C57C4700836A7E /* FICImageTableEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8EC17C57C4700836A7E /* FICImageTableEntry.m */; }; - 2E1BC8FE17C57CDF00836A7E /* FICDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8F717C57CD300836A7E /* FICDAppDelegate.m */; }; - 2E1BC8FF17C57CDF00836A7E /* FICDPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8F917C57CD300836A7E /* FICDPhoto.m */; }; - 2E1BC90017C57CDF00836A7E /* FICDPhotosTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8FB17C57CD300836A7E /* FICDPhotosTableViewCell.m */; }; - 2E1BC90117C57CDF00836A7E /* FICDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8FD17C57CD300836A7E /* FICDViewController.m */; }; - 2E64541017FF24C0001D0531 /* FICDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E64540F17FF24C0001D0531 /* FICDTableView.m */; }; - 2EA7994417B2A10200684B86 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA7993F17B2A10200684B86 /* main.m */; }; - EB171332181F089F00EB0E24 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB171331181F089F00EB0E24 /* CoreImage.framework */; }; - EB642D8017DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m in Sources */ = {isa = PBXBuildFile; fileRef = EB642D7F17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m */; }; - EB6BD53818079DAB00D762CE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB6BD53718079DAB00D762CE /* CoreGraphics.framework */; }; - EB6BD53A18079EA800D762CE /* FICUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8EE17C57C4700836A7E /* FICUtilities.m */; }; - EBB922BD17DA8E6A00211050 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBB922BC17DA8E6A00211050 /* QuartzCore.framework */; }; - EBB922BF17DC08E900211050 /* Demo Images in Resources */ = {isa = PBXBuildFile; fileRef = EBB922BE17DC08E900211050 /* Demo Images */; }; - EBC8A5F217FF6DEF007FECD4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EBC8A5F117FF6DEF007FECD4 /* Assets.xcassets */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 2E095B1017AEBB1200ECE160 /* FastImageCacheDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FastImageCacheDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 2E095B1317AEBB1200ECE160 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 2E095B1517AEBB1200ECE160 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 2E1BC8E317C57C4700836A7E /* FICImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageCache.h; sourceTree = ""; }; - 2E1BC8E417C57C4700836A7E /* FICImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageCache.m; sourceTree = ""; }; - 2E1BC8E517C57C4700836A7E /* FICImageFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageFormat.h; sourceTree = ""; }; - 2E1BC8E617C57C4700836A7E /* FICImageFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageFormat.m; sourceTree = ""; }; - 2E1BC8E717C57C4700836A7E /* FICImageTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageTable.h; sourceTree = ""; }; - 2E1BC8E817C57C4700836A7E /* FICImageTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageTable.m; sourceTree = ""; }; - 2E1BC8E917C57C4700836A7E /* FICImageTableChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageTableChunk.h; sourceTree = ""; }; - 2E1BC8EA17C57C4700836A7E /* FICImageTableChunk.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageTableChunk.m; sourceTree = ""; }; - 2E1BC8EB17C57C4700836A7E /* FICImageTableEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICImageTableEntry.h; sourceTree = ""; }; - 2E1BC8EC17C57C4700836A7E /* FICImageTableEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICImageTableEntry.m; sourceTree = ""; }; - 2E1BC8ED17C57C4700836A7E /* FICUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICUtilities.h; sourceTree = ""; }; - 2E1BC8EE17C57C4700836A7E /* FICUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICUtilities.m; sourceTree = ""; }; - 2E1BC8F617C57CD300836A7E /* FICDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FICDAppDelegate.h; sourceTree = ""; }; - 2E1BC8F717C57CD300836A7E /* FICDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FICDAppDelegate.m; sourceTree = ""; }; - 2E1BC8F817C57CD300836A7E /* FICDPhoto.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FICDPhoto.h; sourceTree = ""; }; - 2E1BC8F917C57CD300836A7E /* FICDPhoto.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FICDPhoto.m; sourceTree = ""; }; - 2E1BC8FA17C57CD300836A7E /* FICDPhotosTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FICDPhotosTableViewCell.h; sourceTree = ""; }; - 2E1BC8FB17C57CD300836A7E /* FICDPhotosTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FICDPhotosTableViewCell.m; sourceTree = ""; }; - 2E1BC8FC17C57CD300836A7E /* FICDViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FICDViewController.h; sourceTree = ""; }; - 2E1BC8FD17C57CD300836A7E /* FICDViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FICDViewController.m; sourceTree = ""; }; - 2E64540E17FF24C0001D0531 /* FICDTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDTableView.h; sourceTree = ""; }; - 2E64540F17FF24C0001D0531 /* FICDTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDTableView.m; sourceTree = ""; }; - 2EA7993F17B2A10200684B86 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - EB171331181F089F00EB0E24 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; - EB642D3717DC9C690013D644 /* FastImageCacheDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "FastImageCacheDemo-Info.plist"; sourceTree = ""; }; - EB642D7E17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDFullscreenPhotoDisplayController.h; sourceTree = ""; }; - EB642D7F17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDFullscreenPhotoDisplayController.m; sourceTree = ""; }; - EB6BD53718079DAB00D762CE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - EB6BD53918079E2D00D762CE /* FICImports.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FICImports.h; sourceTree = ""; }; - EBB922BA17D8EC7F00211050 /* FastImageCacheDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FastImageCacheDemo-Prefix.pch"; sourceTree = ""; }; - EBB922BC17DA8E6A00211050 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - EBB922BE17DC08E900211050 /* Demo Images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Demo Images"; sourceTree = ""; }; - EBC8A5F117FF6DEF007FECD4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - EBC8A63718036430007FECD4 /* FICEntity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FICEntity.h; sourceTree = ""; }; - EBC8A6381804B63A007FECD4 /* FICImageCache+FICErrorLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FICImageCache+FICErrorLogging.h"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 2E095B0D17AEBB1200ECE160 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EB6BD53818079DAB00D762CE /* CoreGraphics.framework in Frameworks */, - EB171332181F089F00EB0E24 /* CoreImage.framework in Frameworks */, - EBB922BD17DA8E6A00211050 /* QuartzCore.framework in Frameworks */, - 2E095B1417AEBB1200ECE160 /* UIKit.framework in Frameworks */, - 2E095B1617AEBB1200ECE160 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 2E095B0717AEBB1200ECE160 = { - isa = PBXGroup; - children = ( - 2E1BC8E017C57C4700836A7E /* FastImageCache */, - 2EA7993A17B2A0CF00684B86 /* Demo App */, - 2E095B1217AEBB1200ECE160 /* Frameworks */, - 2E095B1117AEBB1200ECE160 /* Products */, - ); - sourceTree = ""; - }; - 2E095B1117AEBB1200ECE160 /* Products */ = { - isa = PBXGroup; - children = ( - 2E095B1017AEBB1200ECE160 /* FastImageCacheDemo.app */, - ); - name = Products; - sourceTree = ""; - }; - 2E095B1217AEBB1200ECE160 /* Frameworks */ = { - isa = PBXGroup; - children = ( - EB6BD53718079DAB00D762CE /* CoreGraphics.framework */, - EB171331181F089F00EB0E24 /* CoreImage.framework */, - 2E095B1517AEBB1200ECE160 /* Foundation.framework */, - EBB922BC17DA8E6A00211050 /* QuartzCore.framework */, - 2E095B1317AEBB1200ECE160 /* UIKit.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2E095B1A17AEBB1200ECE160 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - EBC8A5F117FF6DEF007FECD4 /* Assets.xcassets */, - 2EA7993F17B2A10200684B86 /* main.m */, - EBB922BA17D8EC7F00211050 /* FastImageCacheDemo-Prefix.pch */, - EB642D3717DC9C690013D644 /* FastImageCacheDemo-Info.plist */, - ); - path = "Supporting Files"; - sourceTree = ""; - }; - 2E1BC8E017C57C4700836A7E /* FastImageCache */ = { - isa = PBXGroup; - children = ( - EBC8A63718036430007FECD4 /* FICEntity.h */, - EBC8A6381804B63A007FECD4 /* FICImageCache+FICErrorLogging.h */, - 2E1BC8E317C57C4700836A7E /* FICImageCache.h */, - 2E1BC8E417C57C4700836A7E /* FICImageCache.m */, - 2E1BC8E517C57C4700836A7E /* FICImageFormat.h */, - 2E1BC8E617C57C4700836A7E /* FICImageFormat.m */, - 2E1BC8E717C57C4700836A7E /* FICImageTable.h */, - 2E1BC8E817C57C4700836A7E /* FICImageTable.m */, - 2E1BC8E917C57C4700836A7E /* FICImageTableChunk.h */, - 2E1BC8EA17C57C4700836A7E /* FICImageTableChunk.m */, - 2E1BC8EB17C57C4700836A7E /* FICImageTableEntry.h */, - 2E1BC8EC17C57C4700836A7E /* FICImageTableEntry.m */, - EB6BD53918079E2D00D762CE /* FICImports.h */, - 2E1BC8ED17C57C4700836A7E /* FICUtilities.h */, - 2E1BC8EE17C57C4700836A7E /* FICUtilities.m */, - ); - name = FastImageCache; - path = ../FastImageCache; - sourceTree = ""; - }; - 2EA7993A17B2A0CF00684B86 /* Demo App */ = { - isa = PBXGroup; - children = ( - EB642D3917DC9D970013D644 /* Classes */, - EBB922BE17DC08E900211050 /* Demo Images */, - 2E095B1A17AEBB1200ECE160 /* Supporting Files */, - ); - name = "Demo App"; - sourceTree = ""; - }; - EB642D3917DC9D970013D644 /* Classes */ = { - isa = PBXGroup; - children = ( - 2E1BC8F617C57CD300836A7E /* FICDAppDelegate.h */, - 2E1BC8F717C57CD300836A7E /* FICDAppDelegate.m */, - EB642D7E17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.h */, - EB642D7F17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m */, - 2E1BC8F817C57CD300836A7E /* FICDPhoto.h */, - 2E1BC8F917C57CD300836A7E /* FICDPhoto.m */, - 2E1BC8FA17C57CD300836A7E /* FICDPhotosTableViewCell.h */, - 2E1BC8FB17C57CD300836A7E /* FICDPhotosTableViewCell.m */, - 2E64540E17FF24C0001D0531 /* FICDTableView.h */, - 2E64540F17FF24C0001D0531 /* FICDTableView.m */, - 2E1BC8FC17C57CD300836A7E /* FICDViewController.h */, - 2E1BC8FD17C57CD300836A7E /* FICDViewController.m */, - ); - path = Classes; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 2E095B0F17AEBB1200ECE160 /* FastImageCacheDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2E095B3617AEBB1200ECE160 /* Build configuration list for PBXNativeTarget "FastImageCacheDemo" */; - buildPhases = ( - 2E095B0C17AEBB1200ECE160 /* Sources */, - 2E095B0D17AEBB1200ECE160 /* Frameworks */, - 2E095B0E17AEBB1200ECE160 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = FastImageCacheDemo; - productName = "Image Cache"; - productReference = 2E095B1017AEBB1200ECE160 /* FastImageCacheDemo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 2E095B0817AEBB1200ECE160 /* Project object */ = { - isa = PBXProject; - attributes = { - CLASSPREFIX = PT; - LastUpgradeCheck = 0460; - ORGANIZATIONNAME = Path; - }; - buildConfigurationList = 2E095B0B17AEBB1200ECE160 /* Build configuration list for PBXProject "FastImageCacheDemo" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 2E095B0717AEBB1200ECE160; - productRefGroup = 2E095B1117AEBB1200ECE160 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 2E095B0F17AEBB1200ECE160 /* FastImageCacheDemo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 2E095B0E17AEBB1200ECE160 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EBB922BF17DC08E900211050 /* Demo Images in Resources */, - EBC8A5F217FF6DEF007FECD4 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 2E095B0C17AEBB1200ECE160 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2EA7994417B2A10200684B86 /* main.m in Sources */, - 2E1BC8F017C57C4700836A7E /* FICImageCache.m in Sources */, - 2E1BC8F117C57C4700836A7E /* FICImageFormat.m in Sources */, - 2E1BC8F217C57C4700836A7E /* FICImageTable.m in Sources */, - EB642D8017DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m in Sources */, - EB6BD53A18079EA800D762CE /* FICUtilities.m in Sources */, - 2E1BC8F317C57C4700836A7E /* FICImageTableChunk.m in Sources */, - 2E1BC8F417C57C4700836A7E /* FICImageTableEntry.m in Sources */, - 2E64541017FF24C0001D0531 /* FICDTableView.m in Sources */, - 2E1BC8FE17C57CDF00836A7E /* FICDAppDelegate.m in Sources */, - 2E1BC8FF17C57CDF00836A7E /* FICDPhoto.m in Sources */, - 2E1BC90017C57CDF00836A7E /* FICDPhotosTableViewCell.m in Sources */, - 2E1BC90117C57CDF00836A7E /* FICDViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 2E095B3417AEBB1200ECE160 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = NO; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = fast; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 2E095B3517AEBB1200ECE160 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = NO; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; - OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 2E095B3717AEBB1200ECE160 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = Icon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Launch Image"; - "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = ""; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Supporting Files/FastImageCacheDemo-Prefix.pch"; - INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/FastImageCacheDemo-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - PRODUCT_NAME = FastImageCacheDemo; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 2E095B3817AEBB1200ECE160 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = Icon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Launch Image"; - "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = ""; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Supporting Files/FastImageCacheDemo-Prefix.pch"; - INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/FastImageCacheDemo-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - PRODUCT_NAME = FastImageCacheDemo; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2E095B0B17AEBB1200ECE160 /* Build configuration list for PBXProject "FastImageCacheDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2E095B3417AEBB1200ECE160 /* Debug */, - 2E095B3517AEBB1200ECE160 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2E095B3617AEBB1200ECE160 /* Build configuration list for PBXNativeTarget "FastImageCacheDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2E095B3717AEBB1200ECE160 /* Debug */, - 2E095B3817AEBB1200ECE160 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 2E095B0817AEBB1200ECE160 /* Project object */; -} diff --git a/README.md b/README.md index 1a0381a..6a6654c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ![Fast Image Cache Logo](https://s3.amazonaws.com/fast-image-cache/readme-resources/logo.png) --- +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) Fast Image Cache is an efficient, persistent, and—above all—fast way to store and retrieve images in your iOS application. Part of any good iOS application's user experience is fast, smooth scrolling, and Fast Image Cache helps make this easier. @@ -73,7 +74,7 @@ Consider the workflow that occurs when loading an image from disk and displaying 1 `60FPS` ≈ `0.01666s per frame` = `16.7ms per frame`. This means that any main-thread work that takes longer than 16ms will cause your application to drop animation frames. -2 The documentation for [`CALayer`](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCwQFjAA&url=https%3A%2F%2Fdeveloper.apple.com%2Flibrary%2Fios%2Fdocumentation%2Fgraphicsimaging%2Freference%2FCALayer_class%2FIntroduction%2FIntroduction.html&ei=P29XUpj2LeahiALptICgCQ&usg=AFQjCNGwJuHcQV4593kuookUcvNZYTvx5w&sig2=zi1audY4ZsNE_xLeESVD_Q)'s [`contents`](https://developer.apple.com/library/ios/documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004500-CH1-SW24) property states that "assigning a value to this property causes the layer to use your image rather than [creating] a separate backing store." However, the meaning of "use your image" is still vague. Profiling an application using [Instruments](https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004652-CH1-SW1) often reveals calls to `CA::Render::copy_image`, even when the Core Animation Instrument has indicated that none of the images have been copied. One reason that Core Animation will require a copy of an image is improper [byte alignment](#byte-alignment). +2 The documentation for [`CALayer`](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCwQFjAA&url=https%3A%2F%2Fdeveloper.apple.com%2Flibrary%2Fios%2Fdocumentation%2Fgraphicsimaging%2Freference%2FCALayer_class%2FIntroduction%2FIntroduction.html&ei=P29XUpj2LeahiALptICgCQ&usg=AFQjCNGwJuHcQV4593kuookUcvNZYTvx5w&sig2=zi1audY4ZsNE_xLeESVD_Q)'s [`contents`](https://developer.apple.com/library/ios/documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004500-CH1-SW24) property states that "assigning a value to this property causes the layer to use your image rather than [creating] a separate backing store." However, the meaning of "use your image" is still vague. Profiling an application using [Instruments](https://developer.apple.com/library/prerelease/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/) often reveals calls to `CA::Render::copy_image`, even when the Core Animation Instrument has indicated that none of the images have been copied. One reason that Core Animation will require a copy of an image is improper [byte alignment](#byte-alignment). 3 As of iOS 7, Apple does not make their hardware JPEG decoder available for third-party applications to use. As a result, only a slower, software decoder is used for this step. @@ -161,8 +162,8 @@ For easy project integration, Fast Image Cache is available as a [CocoaPod](http - Clone this repository, or [download the latest archive of `master`](https://github.com/path/FastImageCache/archive/master.zip). - From the `FastImageCache` root directory, copy the source files from the inner [`FastImageCache`](./FastImageCache) subdirectory to your Xcode project. -- Import [`FICImageCache.h`](./FastImageCache/FICImageCache.h) wherever you use the image cache. -- Import [`FICEntity.h`](./FastImageCache/FICEntity.h) for each class that conforms to [`FICEntity`](https://s3.amazonaws.com/fast-image-cache/documentation/Protocols/FICEntity.html). +- Import [`FICImageCache.h`](./FastImageCache/FastImageCache/FastImageCache/FICImageCache.h) wherever you use the image cache. +- Import [`FICEntity.h`](./FastImageCache/FastImageCache/FastImageCache/FICEntity.h) for each class that conforms to [`FICEntity`](https://s3.amazonaws.com/fast-image-cache/documentation/Protocols/FICEntity.html). ### Initial Configuration @@ -378,7 +379,7 @@ When this happens, Fast Image Cache cleans up its internal bookkeeping, and any ### Working with Image Format Families -The advantage of classifying image formats into families is that the image cache's delegate can tell the image cache to process entity source images for **all** image formats in a family when **any** image format in that family is processed. +The advantage of classifying image formats into families is that the image cache's delegate can tell the image cache to process entity source images for **all** image formats in a family when **any** image format in that family is processed. By default, all image formats are processed for a given family unless you implement this delegate and return otherwise. ```objective-c - (BOOL)imageCache:(FICImageCache *)imageCache shouldProcessAllFormatsInFamily:(NSString *)formatFamily forEntity:(id)entity { @@ -407,7 +408,7 @@ HTML documentation can be [found here](https://s3.amazonaws.com/fast-image-cache Included with this repository is a demo app Xcode project. It demonstrates the difference between the conventional approach for loading and displaying images and the Fast Image Cache approach. See the [requirements for running the demo app Xcode project](#requirements). -> **Note**: The demo application must either be supplied with JPEG images, or the included [`fetch_demo_images.sh`](./FastImageCacheDemo/fetch_demo_images.sh) script in the [`FastImageCacheDemo`](./FastImageCacheDemo) directory must be run. +> **Note**: The demo application must either be supplied with JPEG images, or the included [`fetch_demo_images.sh`](./FastImageCache/FastImageCacheDemo/fetch_demo_images.sh) script in the [`FastImageCacheDemo`](./FastImageCache/FastImageCacheDemo) directory must be run. ### Video