├── README.md ├── WZRecyclePhotoStackView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── WZRecyclePhotoStackView.xccheckout │ └── xcuserdata │ │ ├── wuwuziqi.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── z.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── wuwuziqi.xcuserdatad │ └── xcschemes │ │ ├── WZRecyclePhotoStackView.xcscheme │ │ └── xcschememanagement.plist │ └── z.xcuserdatad │ └── xcschemes │ ├── WZRecyclePhotoStackView.xcscheme │ └── xcschememanagement.plist ├── WZRecyclePhotoStackView ├── Base.lproj │ └── Main.storyboard ├── FICDDemoImage000.jpg ├── FICDDemoImage001.jpg ├── FICDDemoImage002.jpg ├── FICDDemoImage003.jpg ├── FICDDemoImage004.jpg ├── FICDDemoImage005.jpg ├── FICDDemoImage006.jpg ├── FICDDemoImage007.jpg ├── FICDDemoImage008.jpg ├── FICDDemoImage009.jpg ├── FICDDemoImage010.jpg ├── FICDDemoImage011.jpg ├── FICDDemoImage012.jpg ├── FICDDemoImage013.jpg ├── FICDDemoImage014.jpg ├── FICDDemoImage015.jpg ├── FICDDemoImage016.jpg ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── WZAppDelegate.h ├── WZAppDelegate.m ├── WZCardView.h ├── WZCardView.m ├── WZCardView.xib ├── WZPhotoStackView.h ├── WZPhotoStackView.m ├── WZRecyclePhotoStackView-Info.plist ├── WZRecyclePhotoStackView-Prefix.pch ├── WZViewController.h ├── WZViewController.m ├── en.lproj │ └── InfoPlist.strings ├── main.m ├── no.png └── yes.png ├── WZRecyclePhotoStackViewTests ├── WZRecyclePhotoStackViewTests-Info.plist ├── WZRecyclePhotoStackViewTests.m └── en.lproj │ └── InfoPlist.strings ├── 屏幕快照 2017-04-23 上午2.29.53.png ├── 屏幕快照 2017-04-23 上午2.30.06.png └── 屏幕快照 2017-04-23 上午2.48.35.png /README.md: -------------------------------------------------------------------------------- 1 | WZRecyclePhotoStackView 2 | ======================= 3 | 4 | ### 想法 ### 5 | 大家想象一下,自己当捧着一堆照片的时候,我们是如何去放置我们的照片的? 6 | 可能我们会挑选出我们喜欢的照片放到相册中珍藏,也有可能我们把不喜欢的扔掉。 7 | 同时我们还会存在犹豫不觉的情况,觉得,哎,我先放到后面去,一会再看吧。 8 | 当然,也有可能,您会考虑,哎,我之前一张是什么图来着,我忘记了,我拿回来看看。 9 | 10 | WZRecyclePhotoStackView就是模拟这种生活中的情形而产生的。 11 | 在上滑,下滑的部分,借鉴了TinderSimpleSwipeCards 12 | 13 | ### 这个StackView的优势是什么? ### 14 | - 采用了内存池的设计方式,对于非图片开销,只生成了两个(可配置个数)的容器循环复用 15 | - 避免了一次性加载数据的内存开销和时间损耗,通过可配置的方式将大量的数据通过多次小部分添加加载进内存中。 16 | 同时通过预取的方式将这些新的数据自动补充进需要显示的位置。(在预取过程中您完全可以按照需要修改为异步回调形式) 17 | - 支持左滑、右滑操作。右滑跳过当前照片,将照片置为底部,最后查看。左滑将底部照片拉回顶部,设置为当前查看。 18 | - 高度定制化 19 | 20 | ### 使用 ### 21 | typedef NS_ENUM(NSUInteger, WZPhotoStackStatus) 22 | { 23 | WZPhotoStackStatusLike = 0, //上滑 作为喜欢 24 | WZPhotoStackStatusSkip = 1, //右滑 作为将照片置于底部 25 | WZPhotoStackStatusPullBack = 2,//左滑 作为将底部照片取回 26 | WZPhotoStackStatusHate = 3 //下滑 作为讨厌 27 | }; 28 | 29 | @protocol WZPhotoStackViewDataSource 30 | @required 31 | - (UIImage *)photoForSkipQueueInStack:(WZPhotoStackView *)stackView; 32 | - (UIImage *)photoForRatingQueueInStack:(WZPhotoStackView *)stackView; 33 | - (NSUInteger)numberOfRatingPhotosInStack:(WZPhotoStackView *)stackView; 34 | - (NSUInteger)numberOfSkipPhotosInStack:(WZPhotoStackView *)stackView; 35 | - (BOOL)canFetchMoreDataInStack:(WZPhotoStackView *)stackView; 36 | - (void)fetchMoreDataFromCoreDataInStack:(WZPhotoStackView *)stackView; 37 | - (void)fetchSkipPhotosInStack:(WZPhotoStackView *)stackView; 38 | 39 | @end 40 | 41 | @protocol WZPhotoStackViewDelegate 42 | @optional 43 | - (void)didSkipPhoto:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 44 | - (void)didBringBackPhoto:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 45 | - (void)didRatePhotoAsLike:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 46 | - (void)didRatePhotoAsHate:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 47 | - (void)didFinishRateAllPhotosInStackView:(WZPhotoStackView *)stackView; 48 | @end 49 | 50 | 只要在您的viewcontroller中添加如下代码即可 51 | 52 | self.stackView = [[WZPhotoStackView alloc] initWithFrame:CGRectMake(0, 53 | 0, 54 | CGRectGetWidth(self.view.frame), 55 | CGRectGetHeight(self.view.frame))]; 56 | 57 | [self.view addSubview:self.stackView]; 58 | 59 | self.stackView.delegate = self; 60 | self.stackView.dataSource = self; 61 | 62 | ### 效果 ### 63 | 64 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 03C6F54C19AF0177003FDADF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C6F54B19AF0177003FDADF /* Foundation.framework */; }; 11 | 03C6F54E19AF0177003FDADF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C6F54D19AF0177003FDADF /* CoreGraphics.framework */; }; 12 | 03C6F55019AF0177003FDADF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C6F54F19AF0177003FDADF /* UIKit.framework */; }; 13 | 03C6F55619AF0177003FDADF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F55419AF0177003FDADF /* InfoPlist.strings */; }; 14 | 03C6F55819AF0177003FDADF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C6F55719AF0177003FDADF /* main.m */; }; 15 | 03C6F55C19AF0177003FDADF /* WZAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C6F55B19AF0177003FDADF /* WZAppDelegate.m */; }; 16 | 03C6F55F19AF0177003FDADF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F55D19AF0177003FDADF /* Main.storyboard */; }; 17 | 03C6F56219AF0177003FDADF /* WZViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C6F56119AF0177003FDADF /* WZViewController.m */; }; 18 | 03C6F56419AF0177003FDADF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F56319AF0177003FDADF /* Images.xcassets */; }; 19 | 03C6F56B19AF0177003FDADF /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C6F56A19AF0177003FDADF /* XCTest.framework */; }; 20 | 03C6F56C19AF0177003FDADF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C6F54B19AF0177003FDADF /* Foundation.framework */; }; 21 | 03C6F56D19AF0177003FDADF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C6F54F19AF0177003FDADF /* UIKit.framework */; }; 22 | 03C6F57519AF0177003FDADF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F57319AF0177003FDADF /* InfoPlist.strings */; }; 23 | 03C6F57719AF0177003FDADF /* WZRecyclePhotoStackViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C6F57619AF0177003FDADF /* WZRecyclePhotoStackViewTests.m */; }; 24 | 03C6F58519AF0571003FDADF /* WZCardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C6F58219AF0571003FDADF /* WZCardView.m */; }; 25 | 03C6F58619AF0571003FDADF /* WZPhotoStackView.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C6F58419AF0571003FDADF /* WZPhotoStackView.m */; }; 26 | 03C6F59119AF086F003FDADF /* FICDDemoImage000.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58819AF086F003FDADF /* FICDDemoImage000.jpg */; }; 27 | 03C6F59219AF086F003FDADF /* FICDDemoImage001.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58919AF086F003FDADF /* FICDDemoImage001.jpg */; }; 28 | 03C6F59319AF086F003FDADF /* FICDDemoImage002.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58A19AF086F003FDADF /* FICDDemoImage002.jpg */; }; 29 | 03C6F59419AF086F003FDADF /* FICDDemoImage003.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58B19AF086F003FDADF /* FICDDemoImage003.jpg */; }; 30 | 03C6F59519AF086F003FDADF /* FICDDemoImage004.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58C19AF086F003FDADF /* FICDDemoImage004.jpg */; }; 31 | 03C6F59619AF086F003FDADF /* FICDDemoImage005.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58D19AF086F003FDADF /* FICDDemoImage005.jpg */; }; 32 | 03C6F59719AF086F003FDADF /* FICDDemoImage006.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58E19AF086F003FDADF /* FICDDemoImage006.jpg */; }; 33 | 03C6F59819AF086F003FDADF /* FICDDemoImage007.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F58F19AF086F003FDADF /* FICDDemoImage007.jpg */; }; 34 | 03C6F59919AF086F003FDADF /* FICDDemoImage008.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59019AF086F003FDADF /* FICDDemoImage008.jpg */; }; 35 | 03C6F5A019AF087B003FDADF /* FICDDemoImage009.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59A19AF087B003FDADF /* FICDDemoImage009.jpg */; }; 36 | 03C6F5A119AF087B003FDADF /* FICDDemoImage010.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59B19AF087B003FDADF /* FICDDemoImage010.jpg */; }; 37 | 03C6F5A219AF087B003FDADF /* FICDDemoImage011.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59C19AF087B003FDADF /* FICDDemoImage011.jpg */; }; 38 | 03C6F5A319AF087B003FDADF /* FICDDemoImage012.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59D19AF087B003FDADF /* FICDDemoImage012.jpg */; }; 39 | 03C6F5A419AF087B003FDADF /* FICDDemoImage013.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59E19AF087B003FDADF /* FICDDemoImage013.jpg */; }; 40 | 03C6F5A519AF087B003FDADF /* FICDDemoImage014.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F59F19AF087B003FDADF /* FICDDemoImage014.jpg */; }; 41 | 03C6F5A819AF0C36003FDADF /* FICDDemoImage015.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F5A619AF0C36003FDADF /* FICDDemoImage015.jpg */; }; 42 | 03C6F5A919AF0C36003FDADF /* FICDDemoImage016.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F5A719AF0C36003FDADF /* FICDDemoImage016.jpg */; }; 43 | 03C6F5AB19AF13E6003FDADF /* WZCardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F5AA19AF13E6003FDADF /* WZCardView.xib */; }; 44 | 03C6F5AF19AF148F003FDADF /* no.png in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F5AD19AF148F003FDADF /* no.png */; }; 45 | 03C6F5B019AF148F003FDADF /* yes.png in Resources */ = {isa = PBXBuildFile; fileRef = 03C6F5AE19AF148F003FDADF /* yes.png */; }; 46 | /* End PBXBuildFile section */ 47 | 48 | /* Begin PBXContainerItemProxy section */ 49 | 03C6F56E19AF0177003FDADF /* PBXContainerItemProxy */ = { 50 | isa = PBXContainerItemProxy; 51 | containerPortal = 03C6F54019AF0177003FDADF /* Project object */; 52 | proxyType = 1; 53 | remoteGlobalIDString = 03C6F54719AF0177003FDADF; 54 | remoteInfo = WZRecyclePhotoStackView; 55 | }; 56 | /* End PBXContainerItemProxy section */ 57 | 58 | /* Begin PBXFileReference section */ 59 | 03C6F54819AF0177003FDADF /* WZRecyclePhotoStackView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WZRecyclePhotoStackView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 03C6F54B19AF0177003FDADF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 61 | 03C6F54D19AF0177003FDADF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 62 | 03C6F54F19AF0177003FDADF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 63 | 03C6F55319AF0177003FDADF /* WZRecyclePhotoStackView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "WZRecyclePhotoStackView-Info.plist"; sourceTree = ""; }; 64 | 03C6F55519AF0177003FDADF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 65 | 03C6F55719AF0177003FDADF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 66 | 03C6F55919AF0177003FDADF /* WZRecyclePhotoStackView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WZRecyclePhotoStackView-Prefix.pch"; sourceTree = ""; }; 67 | 03C6F55A19AF0177003FDADF /* WZAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WZAppDelegate.h; sourceTree = ""; }; 68 | 03C6F55B19AF0177003FDADF /* WZAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WZAppDelegate.m; sourceTree = ""; }; 69 | 03C6F55E19AF0177003FDADF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 70 | 03C6F56019AF0177003FDADF /* WZViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WZViewController.h; sourceTree = ""; }; 71 | 03C6F56119AF0177003FDADF /* WZViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WZViewController.m; sourceTree = ""; }; 72 | 03C6F56319AF0177003FDADF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 73 | 03C6F56919AF0177003FDADF /* WZRecyclePhotoStackViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WZRecyclePhotoStackViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 74 | 03C6F56A19AF0177003FDADF /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 75 | 03C6F57219AF0177003FDADF /* WZRecyclePhotoStackViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "WZRecyclePhotoStackViewTests-Info.plist"; sourceTree = ""; }; 76 | 03C6F57419AF0177003FDADF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 77 | 03C6F57619AF0177003FDADF /* WZRecyclePhotoStackViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WZRecyclePhotoStackViewTests.m; sourceTree = ""; }; 78 | 03C6F58119AF0571003FDADF /* WZCardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WZCardView.h; sourceTree = ""; }; 79 | 03C6F58219AF0571003FDADF /* WZCardView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WZCardView.m; sourceTree = ""; }; 80 | 03C6F58319AF0571003FDADF /* WZPhotoStackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WZPhotoStackView.h; sourceTree = ""; }; 81 | 03C6F58419AF0571003FDADF /* WZPhotoStackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WZPhotoStackView.m; sourceTree = ""; }; 82 | 03C6F58819AF086F003FDADF /* FICDDemoImage000.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage000.jpg; sourceTree = ""; }; 83 | 03C6F58919AF086F003FDADF /* FICDDemoImage001.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage001.jpg; sourceTree = ""; }; 84 | 03C6F58A19AF086F003FDADF /* FICDDemoImage002.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage002.jpg; sourceTree = ""; }; 85 | 03C6F58B19AF086F003FDADF /* FICDDemoImage003.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage003.jpg; sourceTree = ""; }; 86 | 03C6F58C19AF086F003FDADF /* FICDDemoImage004.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage004.jpg; sourceTree = ""; }; 87 | 03C6F58D19AF086F003FDADF /* FICDDemoImage005.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage005.jpg; sourceTree = ""; }; 88 | 03C6F58E19AF086F003FDADF /* FICDDemoImage006.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage006.jpg; sourceTree = ""; }; 89 | 03C6F58F19AF086F003FDADF /* FICDDemoImage007.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage007.jpg; sourceTree = ""; }; 90 | 03C6F59019AF086F003FDADF /* FICDDemoImage008.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage008.jpg; sourceTree = ""; }; 91 | 03C6F59A19AF087B003FDADF /* FICDDemoImage009.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage009.jpg; sourceTree = ""; }; 92 | 03C6F59B19AF087B003FDADF /* FICDDemoImage010.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage010.jpg; sourceTree = ""; }; 93 | 03C6F59C19AF087B003FDADF /* FICDDemoImage011.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage011.jpg; sourceTree = ""; }; 94 | 03C6F59D19AF087B003FDADF /* FICDDemoImage012.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage012.jpg; sourceTree = ""; }; 95 | 03C6F59E19AF087B003FDADF /* FICDDemoImage013.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage013.jpg; sourceTree = ""; }; 96 | 03C6F59F19AF087B003FDADF /* FICDDemoImage014.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage014.jpg; sourceTree = ""; }; 97 | 03C6F5A619AF0C36003FDADF /* FICDDemoImage015.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage015.jpg; sourceTree = ""; }; 98 | 03C6F5A719AF0C36003FDADF /* FICDDemoImage016.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = FICDDemoImage016.jpg; sourceTree = ""; }; 99 | 03C6F5AA19AF13E6003FDADF /* WZCardView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WZCardView.xib; sourceTree = ""; }; 100 | 03C6F5AD19AF148F003FDADF /* no.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = no.png; sourceTree = ""; }; 101 | 03C6F5AE19AF148F003FDADF /* yes.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = yes.png; sourceTree = ""; }; 102 | /* End PBXFileReference section */ 103 | 104 | /* Begin PBXFrameworksBuildPhase section */ 105 | 03C6F54519AF0177003FDADF /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | 03C6F54E19AF0177003FDADF /* CoreGraphics.framework in Frameworks */, 110 | 03C6F55019AF0177003FDADF /* UIKit.framework in Frameworks */, 111 | 03C6F54C19AF0177003FDADF /* Foundation.framework in Frameworks */, 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | 03C6F56619AF0177003FDADF /* Frameworks */ = { 116 | isa = PBXFrameworksBuildPhase; 117 | buildActionMask = 2147483647; 118 | files = ( 119 | 03C6F56B19AF0177003FDADF /* XCTest.framework in Frameworks */, 120 | 03C6F56D19AF0177003FDADF /* UIKit.framework in Frameworks */, 121 | 03C6F56C19AF0177003FDADF /* Foundation.framework in Frameworks */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXFrameworksBuildPhase section */ 126 | 127 | /* Begin PBXGroup section */ 128 | 03C6F53F19AF0177003FDADF = { 129 | isa = PBXGroup; 130 | children = ( 131 | 03C6F55119AF0177003FDADF /* WZRecyclePhotoStackView */, 132 | 03C6F57019AF0177003FDADF /* WZRecyclePhotoStackViewTests */, 133 | 03C6F54A19AF0177003FDADF /* Frameworks */, 134 | 03C6F54919AF0177003FDADF /* Products */, 135 | ); 136 | sourceTree = ""; 137 | }; 138 | 03C6F54919AF0177003FDADF /* Products */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 03C6F54819AF0177003FDADF /* WZRecyclePhotoStackView.app */, 142 | 03C6F56919AF0177003FDADF /* WZRecyclePhotoStackViewTests.xctest */, 143 | ); 144 | name = Products; 145 | sourceTree = ""; 146 | }; 147 | 03C6F54A19AF0177003FDADF /* Frameworks */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 03C6F54B19AF0177003FDADF /* Foundation.framework */, 151 | 03C6F54D19AF0177003FDADF /* CoreGraphics.framework */, 152 | 03C6F54F19AF0177003FDADF /* UIKit.framework */, 153 | 03C6F56A19AF0177003FDADF /* XCTest.framework */, 154 | ); 155 | name = Frameworks; 156 | sourceTree = ""; 157 | }; 158 | 03C6F55119AF0177003FDADF /* WZRecyclePhotoStackView */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 03C6F5AC19AF1482003FDADF /* Resources */, 162 | 03C6F58019AF0563003FDADF /* Library */, 163 | 03C6F55A19AF0177003FDADF /* WZAppDelegate.h */, 164 | 03C6F55B19AF0177003FDADF /* WZAppDelegate.m */, 165 | 03C6F55D19AF0177003FDADF /* Main.storyboard */, 166 | 03C6F56019AF0177003FDADF /* WZViewController.h */, 167 | 03C6F56119AF0177003FDADF /* WZViewController.m */, 168 | 03C6F56319AF0177003FDADF /* Images.xcassets */, 169 | 03C6F55219AF0177003FDADF /* Supporting Files */, 170 | ); 171 | path = WZRecyclePhotoStackView; 172 | sourceTree = ""; 173 | }; 174 | 03C6F55219AF0177003FDADF /* Supporting Files */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 03C6F55319AF0177003FDADF /* WZRecyclePhotoStackView-Info.plist */, 178 | 03C6F55419AF0177003FDADF /* InfoPlist.strings */, 179 | 03C6F55719AF0177003FDADF /* main.m */, 180 | 03C6F55919AF0177003FDADF /* WZRecyclePhotoStackView-Prefix.pch */, 181 | ); 182 | name = "Supporting Files"; 183 | sourceTree = ""; 184 | }; 185 | 03C6F57019AF0177003FDADF /* WZRecyclePhotoStackViewTests */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 03C6F57619AF0177003FDADF /* WZRecyclePhotoStackViewTests.m */, 189 | 03C6F57119AF0177003FDADF /* Supporting Files */, 190 | ); 191 | path = WZRecyclePhotoStackViewTests; 192 | sourceTree = ""; 193 | }; 194 | 03C6F57119AF0177003FDADF /* Supporting Files */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 03C6F57219AF0177003FDADF /* WZRecyclePhotoStackViewTests-Info.plist */, 198 | 03C6F57319AF0177003FDADF /* InfoPlist.strings */, 199 | ); 200 | name = "Supporting Files"; 201 | sourceTree = ""; 202 | }; 203 | 03C6F58019AF0563003FDADF /* Library */ = { 204 | isa = PBXGroup; 205 | children = ( 206 | 03C6F58119AF0571003FDADF /* WZCardView.h */, 207 | 03C6F58219AF0571003FDADF /* WZCardView.m */, 208 | 03C6F5AA19AF13E6003FDADF /* WZCardView.xib */, 209 | 03C6F58319AF0571003FDADF /* WZPhotoStackView.h */, 210 | 03C6F58419AF0571003FDADF /* WZPhotoStackView.m */, 211 | ); 212 | name = Library; 213 | sourceTree = ""; 214 | }; 215 | 03C6F58719AF084D003FDADF /* Images */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 03C6F58819AF086F003FDADF /* FICDDemoImage000.jpg */, 219 | 03C6F58919AF086F003FDADF /* FICDDemoImage001.jpg */, 220 | 03C6F58A19AF086F003FDADF /* FICDDemoImage002.jpg */, 221 | 03C6F58B19AF086F003FDADF /* FICDDemoImage003.jpg */, 222 | 03C6F58C19AF086F003FDADF /* FICDDemoImage004.jpg */, 223 | 03C6F58D19AF086F003FDADF /* FICDDemoImage005.jpg */, 224 | 03C6F58E19AF086F003FDADF /* FICDDemoImage006.jpg */, 225 | 03C6F58F19AF086F003FDADF /* FICDDemoImage007.jpg */, 226 | 03C6F59019AF086F003FDADF /* FICDDemoImage008.jpg */, 227 | 03C6F59A19AF087B003FDADF /* FICDDemoImage009.jpg */, 228 | 03C6F59B19AF087B003FDADF /* FICDDemoImage010.jpg */, 229 | 03C6F59C19AF087B003FDADF /* FICDDemoImage011.jpg */, 230 | 03C6F59D19AF087B003FDADF /* FICDDemoImage012.jpg */, 231 | 03C6F59E19AF087B003FDADF /* FICDDemoImage013.jpg */, 232 | 03C6F59F19AF087B003FDADF /* FICDDemoImage014.jpg */, 233 | 03C6F5A619AF0C36003FDADF /* FICDDemoImage015.jpg */, 234 | 03C6F5A719AF0C36003FDADF /* FICDDemoImage016.jpg */, 235 | ); 236 | name = Images; 237 | sourceTree = ""; 238 | }; 239 | 03C6F5AC19AF1482003FDADF /* Resources */ = { 240 | isa = PBXGroup; 241 | children = ( 242 | 03C6F5AD19AF148F003FDADF /* no.png */, 243 | 03C6F5AE19AF148F003FDADF /* yes.png */, 244 | 03C6F58719AF084D003FDADF /* Images */, 245 | ); 246 | name = Resources; 247 | sourceTree = ""; 248 | }; 249 | /* End PBXGroup section */ 250 | 251 | /* Begin PBXNativeTarget section */ 252 | 03C6F54719AF0177003FDADF /* WZRecyclePhotoStackView */ = { 253 | isa = PBXNativeTarget; 254 | buildConfigurationList = 03C6F57A19AF0177003FDADF /* Build configuration list for PBXNativeTarget "WZRecyclePhotoStackView" */; 255 | buildPhases = ( 256 | 03C6F54419AF0177003FDADF /* Sources */, 257 | 03C6F54519AF0177003FDADF /* Frameworks */, 258 | 03C6F54619AF0177003FDADF /* Resources */, 259 | ); 260 | buildRules = ( 261 | ); 262 | dependencies = ( 263 | ); 264 | name = WZRecyclePhotoStackView; 265 | productName = WZRecyclePhotoStackView; 266 | productReference = 03C6F54819AF0177003FDADF /* WZRecyclePhotoStackView.app */; 267 | productType = "com.apple.product-type.application"; 268 | }; 269 | 03C6F56819AF0177003FDADF /* WZRecyclePhotoStackViewTests */ = { 270 | isa = PBXNativeTarget; 271 | buildConfigurationList = 03C6F57D19AF0177003FDADF /* Build configuration list for PBXNativeTarget "WZRecyclePhotoStackViewTests" */; 272 | buildPhases = ( 273 | 03C6F56519AF0177003FDADF /* Sources */, 274 | 03C6F56619AF0177003FDADF /* Frameworks */, 275 | 03C6F56719AF0177003FDADF /* Resources */, 276 | ); 277 | buildRules = ( 278 | ); 279 | dependencies = ( 280 | 03C6F56F19AF0177003FDADF /* PBXTargetDependency */, 281 | ); 282 | name = WZRecyclePhotoStackViewTests; 283 | productName = WZRecyclePhotoStackViewTests; 284 | productReference = 03C6F56919AF0177003FDADF /* WZRecyclePhotoStackViewTests.xctest */; 285 | productType = "com.apple.product-type.bundle.unit-test"; 286 | }; 287 | /* End PBXNativeTarget section */ 288 | 289 | /* Begin PBXProject section */ 290 | 03C6F54019AF0177003FDADF /* Project object */ = { 291 | isa = PBXProject; 292 | attributes = { 293 | CLASSPREFIX = WZ; 294 | LastUpgradeCheck = 0510; 295 | ORGANIZATIONNAME = "Ziqi Wu"; 296 | TargetAttributes = { 297 | 03C6F56819AF0177003FDADF = { 298 | TestTargetID = 03C6F54719AF0177003FDADF; 299 | }; 300 | }; 301 | }; 302 | buildConfigurationList = 03C6F54319AF0177003FDADF /* Build configuration list for PBXProject "WZRecyclePhotoStackView" */; 303 | compatibilityVersion = "Xcode 3.2"; 304 | developmentRegion = English; 305 | hasScannedForEncodings = 0; 306 | knownRegions = ( 307 | en, 308 | Base, 309 | ); 310 | mainGroup = 03C6F53F19AF0177003FDADF; 311 | productRefGroup = 03C6F54919AF0177003FDADF /* Products */; 312 | projectDirPath = ""; 313 | projectRoot = ""; 314 | targets = ( 315 | 03C6F54719AF0177003FDADF /* WZRecyclePhotoStackView */, 316 | 03C6F56819AF0177003FDADF /* WZRecyclePhotoStackViewTests */, 317 | ); 318 | }; 319 | /* End PBXProject section */ 320 | 321 | /* Begin PBXResourcesBuildPhase section */ 322 | 03C6F54619AF0177003FDADF /* Resources */ = { 323 | isa = PBXResourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 03C6F56419AF0177003FDADF /* Images.xcassets in Resources */, 327 | 03C6F59119AF086F003FDADF /* FICDDemoImage000.jpg in Resources */, 328 | 03C6F5B019AF148F003FDADF /* yes.png in Resources */, 329 | 03C6F5A419AF087B003FDADF /* FICDDemoImage013.jpg in Resources */, 330 | 03C6F55619AF0177003FDADF /* InfoPlist.strings in Resources */, 331 | 03C6F5A219AF087B003FDADF /* FICDDemoImage011.jpg in Resources */, 332 | 03C6F5AB19AF13E6003FDADF /* WZCardView.xib in Resources */, 333 | 03C6F5AF19AF148F003FDADF /* no.png in Resources */, 334 | 03C6F5A319AF087B003FDADF /* FICDDemoImage012.jpg in Resources */, 335 | 03C6F59819AF086F003FDADF /* FICDDemoImage007.jpg in Resources */, 336 | 03C6F59719AF086F003FDADF /* FICDDemoImage006.jpg in Resources */, 337 | 03C6F5A919AF0C36003FDADF /* FICDDemoImage016.jpg in Resources */, 338 | 03C6F59619AF086F003FDADF /* FICDDemoImage005.jpg in Resources */, 339 | 03C6F5A119AF087B003FDADF /* FICDDemoImage010.jpg in Resources */, 340 | 03C6F59319AF086F003FDADF /* FICDDemoImage002.jpg in Resources */, 341 | 03C6F5A019AF087B003FDADF /* FICDDemoImage009.jpg in Resources */, 342 | 03C6F5A519AF087B003FDADF /* FICDDemoImage014.jpg in Resources */, 343 | 03C6F59219AF086F003FDADF /* FICDDemoImage001.jpg in Resources */, 344 | 03C6F5A819AF0C36003FDADF /* FICDDemoImage015.jpg in Resources */, 345 | 03C6F59519AF086F003FDADF /* FICDDemoImage004.jpg in Resources */, 346 | 03C6F59919AF086F003FDADF /* FICDDemoImage008.jpg in Resources */, 347 | 03C6F59419AF086F003FDADF /* FICDDemoImage003.jpg in Resources */, 348 | 03C6F55F19AF0177003FDADF /* Main.storyboard in Resources */, 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | }; 352 | 03C6F56719AF0177003FDADF /* Resources */ = { 353 | isa = PBXResourcesBuildPhase; 354 | buildActionMask = 2147483647; 355 | files = ( 356 | 03C6F57519AF0177003FDADF /* InfoPlist.strings in Resources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | /* End PBXResourcesBuildPhase section */ 361 | 362 | /* Begin PBXSourcesBuildPhase section */ 363 | 03C6F54419AF0177003FDADF /* Sources */ = { 364 | isa = PBXSourcesBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | 03C6F55819AF0177003FDADF /* main.m in Sources */, 368 | 03C6F58519AF0571003FDADF /* WZCardView.m in Sources */, 369 | 03C6F58619AF0571003FDADF /* WZPhotoStackView.m in Sources */, 370 | 03C6F55C19AF0177003FDADF /* WZAppDelegate.m in Sources */, 371 | 03C6F56219AF0177003FDADF /* WZViewController.m in Sources */, 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | }; 375 | 03C6F56519AF0177003FDADF /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | 03C6F57719AF0177003FDADF /* WZRecyclePhotoStackViewTests.m in Sources */, 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | }; 383 | /* End PBXSourcesBuildPhase section */ 384 | 385 | /* Begin PBXTargetDependency section */ 386 | 03C6F56F19AF0177003FDADF /* PBXTargetDependency */ = { 387 | isa = PBXTargetDependency; 388 | target = 03C6F54719AF0177003FDADF /* WZRecyclePhotoStackView */; 389 | targetProxy = 03C6F56E19AF0177003FDADF /* PBXContainerItemProxy */; 390 | }; 391 | /* End PBXTargetDependency section */ 392 | 393 | /* Begin PBXVariantGroup section */ 394 | 03C6F55419AF0177003FDADF /* InfoPlist.strings */ = { 395 | isa = PBXVariantGroup; 396 | children = ( 397 | 03C6F55519AF0177003FDADF /* en */, 398 | ); 399 | name = InfoPlist.strings; 400 | sourceTree = ""; 401 | }; 402 | 03C6F55D19AF0177003FDADF /* Main.storyboard */ = { 403 | isa = PBXVariantGroup; 404 | children = ( 405 | 03C6F55E19AF0177003FDADF /* Base */, 406 | ); 407 | name = Main.storyboard; 408 | sourceTree = ""; 409 | }; 410 | 03C6F57319AF0177003FDADF /* InfoPlist.strings */ = { 411 | isa = PBXVariantGroup; 412 | children = ( 413 | 03C6F57419AF0177003FDADF /* en */, 414 | ); 415 | name = InfoPlist.strings; 416 | sourceTree = ""; 417 | }; 418 | /* End PBXVariantGroup section */ 419 | 420 | /* Begin XCBuildConfiguration section */ 421 | 03C6F57819AF0177003FDADF /* Debug */ = { 422 | isa = XCBuildConfiguration; 423 | buildSettings = { 424 | ALWAYS_SEARCH_USER_PATHS = NO; 425 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 426 | CLANG_CXX_LIBRARY = "libc++"; 427 | CLANG_ENABLE_MODULES = YES; 428 | CLANG_ENABLE_OBJC_ARC = YES; 429 | CLANG_WARN_BOOL_CONVERSION = YES; 430 | CLANG_WARN_CONSTANT_CONVERSION = YES; 431 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 432 | CLANG_WARN_EMPTY_BODY = YES; 433 | CLANG_WARN_ENUM_CONVERSION = YES; 434 | CLANG_WARN_INT_CONVERSION = YES; 435 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 436 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 437 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 438 | COPY_PHASE_STRIP = NO; 439 | GCC_C_LANGUAGE_STANDARD = gnu99; 440 | GCC_DYNAMIC_NO_PIC = NO; 441 | GCC_OPTIMIZATION_LEVEL = 0; 442 | GCC_PREPROCESSOR_DEFINITIONS = ( 443 | "DEBUG=1", 444 | "$(inherited)", 445 | ); 446 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 447 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 448 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 449 | GCC_WARN_UNDECLARED_SELECTOR = YES; 450 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 451 | GCC_WARN_UNUSED_FUNCTION = YES; 452 | GCC_WARN_UNUSED_VARIABLE = YES; 453 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 454 | ONLY_ACTIVE_ARCH = YES; 455 | SDKROOT = iphoneos; 456 | }; 457 | name = Debug; 458 | }; 459 | 03C6F57919AF0177003FDADF /* Release */ = { 460 | isa = XCBuildConfiguration; 461 | buildSettings = { 462 | ALWAYS_SEARCH_USER_PATHS = NO; 463 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 464 | CLANG_CXX_LIBRARY = "libc++"; 465 | CLANG_ENABLE_MODULES = YES; 466 | CLANG_ENABLE_OBJC_ARC = YES; 467 | CLANG_WARN_BOOL_CONVERSION = YES; 468 | CLANG_WARN_CONSTANT_CONVERSION = YES; 469 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 470 | CLANG_WARN_EMPTY_BODY = YES; 471 | CLANG_WARN_ENUM_CONVERSION = YES; 472 | CLANG_WARN_INT_CONVERSION = YES; 473 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 474 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 475 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 476 | COPY_PHASE_STRIP = YES; 477 | ENABLE_NS_ASSERTIONS = NO; 478 | GCC_C_LANGUAGE_STANDARD = gnu99; 479 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 480 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 481 | GCC_WARN_UNDECLARED_SELECTOR = YES; 482 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 483 | GCC_WARN_UNUSED_FUNCTION = YES; 484 | GCC_WARN_UNUSED_VARIABLE = YES; 485 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 486 | SDKROOT = iphoneos; 487 | VALIDATE_PRODUCT = YES; 488 | }; 489 | name = Release; 490 | }; 491 | 03C6F57B19AF0177003FDADF /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 496 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 497 | GCC_PREFIX_HEADER = "WZRecyclePhotoStackView/WZRecyclePhotoStackView-Prefix.pch"; 498 | INFOPLIST_FILE = "WZRecyclePhotoStackView/WZRecyclePhotoStackView-Info.plist"; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | WRAPPER_EXTENSION = app; 501 | }; 502 | name = Debug; 503 | }; 504 | 03C6F57C19AF0177003FDADF /* Release */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 508 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 509 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 510 | GCC_PREFIX_HEADER = "WZRecyclePhotoStackView/WZRecyclePhotoStackView-Prefix.pch"; 511 | INFOPLIST_FILE = "WZRecyclePhotoStackView/WZRecyclePhotoStackView-Info.plist"; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | WRAPPER_EXTENSION = app; 514 | }; 515 | name = Release; 516 | }; 517 | 03C6F57E19AF0177003FDADF /* Debug */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/WZRecyclePhotoStackView.app/WZRecyclePhotoStackView"; 521 | FRAMEWORK_SEARCH_PATHS = ( 522 | "$(SDKROOT)/Developer/Library/Frameworks", 523 | "$(inherited)", 524 | "$(DEVELOPER_FRAMEWORKS_DIR)", 525 | ); 526 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 527 | GCC_PREFIX_HEADER = "WZRecyclePhotoStackView/WZRecyclePhotoStackView-Prefix.pch"; 528 | GCC_PREPROCESSOR_DEFINITIONS = ( 529 | "DEBUG=1", 530 | "$(inherited)", 531 | ); 532 | INFOPLIST_FILE = "WZRecyclePhotoStackViewTests/WZRecyclePhotoStackViewTests-Info.plist"; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | TEST_HOST = "$(BUNDLE_LOADER)"; 535 | WRAPPER_EXTENSION = xctest; 536 | }; 537 | name = Debug; 538 | }; 539 | 03C6F57F19AF0177003FDADF /* Release */ = { 540 | isa = XCBuildConfiguration; 541 | buildSettings = { 542 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/WZRecyclePhotoStackView.app/WZRecyclePhotoStackView"; 543 | FRAMEWORK_SEARCH_PATHS = ( 544 | "$(SDKROOT)/Developer/Library/Frameworks", 545 | "$(inherited)", 546 | "$(DEVELOPER_FRAMEWORKS_DIR)", 547 | ); 548 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 549 | GCC_PREFIX_HEADER = "WZRecyclePhotoStackView/WZRecyclePhotoStackView-Prefix.pch"; 550 | INFOPLIST_FILE = "WZRecyclePhotoStackViewTests/WZRecyclePhotoStackViewTests-Info.plist"; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | TEST_HOST = "$(BUNDLE_LOADER)"; 553 | WRAPPER_EXTENSION = xctest; 554 | }; 555 | name = Release; 556 | }; 557 | /* End XCBuildConfiguration section */ 558 | 559 | /* Begin XCConfigurationList section */ 560 | 03C6F54319AF0177003FDADF /* Build configuration list for PBXProject "WZRecyclePhotoStackView" */ = { 561 | isa = XCConfigurationList; 562 | buildConfigurations = ( 563 | 03C6F57819AF0177003FDADF /* Debug */, 564 | 03C6F57919AF0177003FDADF /* Release */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | 03C6F57A19AF0177003FDADF /* Build configuration list for PBXNativeTarget "WZRecyclePhotoStackView" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | 03C6F57B19AF0177003FDADF /* Debug */, 573 | 03C6F57C19AF0177003FDADF /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | }; 577 | 03C6F57D19AF0177003FDADF /* Build configuration list for PBXNativeTarget "WZRecyclePhotoStackViewTests" */ = { 578 | isa = XCConfigurationList; 579 | buildConfigurations = ( 580 | 03C6F57E19AF0177003FDADF /* Debug */, 581 | 03C6F57F19AF0177003FDADF /* Release */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | }; 585 | /* End XCConfigurationList section */ 586 | }; 587 | rootObject = 03C6F54019AF0177003FDADF /* Project object */; 588 | } 589 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/project.xcworkspace/xcshareddata/WZRecyclePhotoStackView.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | F8430385-C444-4333-954A-89F00DDBE724 9 | IDESourceControlProjectName 10 | WZRecyclePhotoStackView 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 9214FF5EF86A7F1EE1F9D5AB1AEA85A81909F549 14 | https://github.com/SatanWoo/WZRecyclePhotoStackView.git 15 | 16 | IDESourceControlProjectPath 17 | WZRecyclePhotoStackView.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 9214FF5EF86A7F1EE1F9D5AB1AEA85A81909F549 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/SatanWoo/WZRecyclePhotoStackView.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 9214FF5EF86A7F1EE1F9D5AB1AEA85A81909F549 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 9214FF5EF86A7F1EE1F9D5AB1AEA85A81909F549 36 | IDESourceControlWCCName 37 | WZRecyclePhotoStackView 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/project.xcworkspace/xcuserdata/wuwuziqi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView.xcodeproj/project.xcworkspace/xcuserdata/wuwuziqi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/project.xcworkspace/xcuserdata/z.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView.xcodeproj/project.xcworkspace/xcuserdata/z.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/xcuserdata/wuwuziqi.xcuserdatad/xcschemes/WZRecyclePhotoStackView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/xcuserdata/wuwuziqi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WZRecyclePhotoStackView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 03C6F54719AF0177003FDADF 16 | 17 | primary 18 | 19 | 20 | 03C6F56819AF0177003FDADF 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/xcuserdata/z.xcuserdatad/xcschemes/WZRecyclePhotoStackView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView.xcodeproj/xcuserdata/z.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WZRecyclePhotoStackView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 03C6F54719AF0177003FDADF 16 | 17 | primary 18 | 19 | 20 | 03C6F56819AF0177003FDADF 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage000.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage001.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage002.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage002.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage003.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage003.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage004.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage005.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage006.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage006.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage007.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage007.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage008.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage008.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage009.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage009.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage010.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage011.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage011.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage012.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage012.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage013.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage013.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage014.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage014.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage015.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage015.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/FICDDemoImage016.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/FICDDemoImage016.jpg -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // WZAppDelegate.h 3 | // WZRecyclePhotoStackView 4 | // 5 | // Created by satanwoo on 14-8-28. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WZAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // WZAppDelegate.m 3 | // WZRecyclePhotoStackView 4 | // 5 | // Created by satanwoo on 14-8-28. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import "WZAppDelegate.h" 10 | 11 | @implementation WZAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZCardView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WZCardView.h 3 | // iPhoto 4 | // 5 | // Created by satanwoo on 14-8-11. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, WZOverlayMode) 12 | { 13 | WZOverlayModeLike = 0, 14 | WZOverlayModeHate = 1, 15 | WZOverlayModeNormal = 2 16 | }; 17 | 18 | @interface WZCardView : UIView 19 | 20 | @property (nonatomic, weak) IBOutlet UIImageView *photoImageView; 21 | @property (nonatomic, weak) IBOutlet UIImageView *overlayImageView; 22 | 23 | @property (nonatomic, strong) UIImage *photo; 24 | @property (nonatomic, assign, readonly) WZOverlayMode mode; 25 | 26 | + (WZCardView *)createCardView; 27 | - (void)updateRotation; 28 | - (void)updateOverlay; 29 | - (void)restoreNormalCard; 30 | - (void)moveByTranslation:(CGPoint)translation; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZCardView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WZCardView.m 3 | // iPhoto 4 | // 5 | // Created by satanwoo on 14-8-11. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import "WZCardView.h" 10 | 11 | #define WZCardViewNibName @"WZCardView" 12 | #define SCALE_STRENGTH 4 //%%% how quickly the card shrinks. Higher = slower shrinking 13 | #define SCALE_MAX .93 //%%% upper bar for how much the card shrinks. Higher = shrinks less 14 | #define ROTATION_MAX 1 //%%% the maximum rotation allowed in radians. Higher = card can keep rotating longer 15 | #define ROTATION_STRENGTH 320 //%%% strength of rotation. Higher = weaker rotation 16 | #define ROTATION_ANGLE M_PI/8 //%%% Higher = stronger rotation angle 17 | 18 | #define WZRatingThreshold 80 19 | 20 | @interface WZCardView() 21 | @property (nonatomic, assign) CGFloat startCenterX; 22 | @property (nonatomic, assign) CGFloat startCenterY; 23 | @property (nonatomic, assign) WZOverlayMode mode; 24 | @end 25 | 26 | @implementation WZCardView 27 | + (WZCardView *)createCardView 28 | { 29 | WZCardView *view = [[[NSBundle mainBundle] loadNibNamed:WZCardViewNibName owner:self options:nil] lastObject]; 30 | return view; 31 | } 32 | 33 | - (id)initWithFrame:(CGRect)frame 34 | { 35 | self = [super initWithFrame:frame]; 36 | if (self) { 37 | } 38 | return self; 39 | } 40 | 41 | - (void)awakeFromNib 42 | { 43 | [super awakeFromNib]; 44 | 45 | self.layer.cornerRadius = 3.0f; 46 | self.layer.masksToBounds = YES; 47 | 48 | self.overlayImageView.alpha = 0.0f; 49 | } 50 | 51 | - (void)didMoveToSuperview 52 | { 53 | [super didMoveToSuperview]; 54 | 55 | self.startCenterX = self.center.x; 56 | self.startCenterY = self.center.y; 57 | } 58 | 59 | #pragma mark - Public 60 | - (void)updateOverlay 61 | { 62 | CGFloat offsetY = self.center.y - self.startCenterY; 63 | if (offsetY < 0) { 64 | self.mode = WZOverlayModeLike; 65 | } else { 66 | self.mode = WZOverlayModeHate; 67 | } 68 | self.overlayImageView.alpha = MIN(fabsf(offsetY)/100, 0.4); 69 | } 70 | 71 | - (void)updateRotation 72 | { 73 | CGFloat offsetX = self.center.x - self.startCenterX; 74 | CGFloat rotationStrength = MIN(offsetX / ROTATION_STRENGTH, ROTATION_MAX); 75 | CGFloat rotationAngel = (CGFloat) (ROTATION_ANGLE * rotationStrength); 76 | CGFloat scale = MAX(1 - fabsf(rotationStrength) / SCALE_STRENGTH, SCALE_MAX); 77 | 78 | CGAffineTransform transform = CGAffineTransformMakeRotation(rotationAngel); 79 | CGAffineTransform scaleTransform = CGAffineTransformScale(transform, scale, scale); 80 | 81 | self.transform = scaleTransform; 82 | } 83 | 84 | - (void)restoreNormalCard 85 | { 86 | self.overlayImageView.alpha = 0.0f; 87 | self.center = CGPointMake(self.startCenterX, self.startCenterY); 88 | self.transform = CGAffineTransformMakeRotation(0); 89 | } 90 | 91 | - (void)moveByTranslation:(CGPoint)translation 92 | { 93 | self.center = CGPointMake(self.startCenterX + translation.x, self.startCenterY + translation.y); 94 | } 95 | 96 | #pragma mark - Override 97 | - (void)setMode:(WZOverlayMode)mode 98 | { 99 | if (mode == WZOverlayModeHate) { 100 | self.overlayImageView.image = [UIImage imageNamed:@"no"]; 101 | } else { 102 | self.overlayImageView.image = [UIImage imageNamed:@"yes"]; 103 | } 104 | } 105 | 106 | - (void)setPhoto:(UIImage *)photo 107 | { 108 | if (_photo == photo) return; 109 | 110 | _photo = photo; 111 | self.photoImageView.image = photo; 112 | } 113 | @end 114 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZCardView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZPhotoStackView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WZPhotoStackView.h 3 | // iPhoto 4 | // 5 | // Created by satanwoo on 14-8-16. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class WZPhotoStackView; 12 | @class Photo; 13 | 14 | @protocol WZPhotoStackViewDataSource 15 | @required 16 | - (UIImage *)photoForSkipQueueInStack:(WZPhotoStackView *)stackView; 17 | - (UIImage *)photoForRatingQueueInStack:(WZPhotoStackView *)stackView; 18 | - (NSUInteger)numberOfRatingPhotosInStack:(WZPhotoStackView *)stackView; 19 | - (NSUInteger)numberOfSkipPhotosInStack:(WZPhotoStackView *)stackView; 20 | - (BOOL)canFetchMoreDataInStack:(WZPhotoStackView *)stackView; 21 | - (void)fetchMoreDataFromCoreDataInStack:(WZPhotoStackView *)stackView; 22 | - (void)fetchSkipPhotosInStack:(WZPhotoStackView *)stackView; 23 | 24 | @end 25 | 26 | typedef NS_ENUM(NSUInteger, WZPhotoStackStatus) 27 | { 28 | WZPhotoStackStatusLike = 0, 29 | WZPhotoStackStatusSkip = 1, 30 | WZPhotoStackStatusPullBack = 2, 31 | WZPhotoStackStatusHate = 3 32 | }; 33 | 34 | @protocol WZPhotoStackViewDelegate 35 | 36 | @optional 37 | - (void)didSkipPhoto:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 38 | - (void)didBringBackPhoto:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 39 | - (void)didRatePhotoAsLike:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 40 | - (void)didRatePhotoAsHate:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView; 41 | - (void)didFinishRateAllPhotosInStackView:(WZPhotoStackView *)stackView; 42 | @end 43 | 44 | @interface WZPhotoStackView : UIView 45 | 46 | @property (nonatomic, weak) id dataSource; 47 | @property (nonatomic, weak) id delegate; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZPhotoStackView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WZPhotoStackView.m 3 | // iPhoto 4 | // 5 | // Created by satanwoo on 14-8-16. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import "WZPhotoStackView.h" 10 | #import "WZCardView.h" 11 | 12 | @interface WZPhotoStackView() 13 | @property (nonatomic, strong) NSMutableArray *cardPools; 14 | @property (nonatomic, assign) NSUInteger cardPoolsUsingIndex; 15 | 16 | @property (nonatomic, strong) WZCardView *skipPullBackCard; 17 | 18 | @property (nonatomic, assign) CGPoint translationPoint; 19 | @property (nonatomic, assign) WZPhotoStackStatus status; 20 | 21 | @property (nonatomic, assign) BOOL isPanning; 22 | @property (nonatomic, assign) BOOL isPulling; 23 | 24 | - (void)initializeWithFrame:(CGRect)frame; 25 | - (void)initCardView; 26 | - (void)swapDataWithPhoto:(UIImage *)photo; 27 | 28 | - (void)animationPhotoWithBlock:(void(^)(WZCardView *currentCard))animationBlock completion:(void(^)(WZCardView *currentCard))completionBlock; 29 | @end 30 | 31 | @implementation WZPhotoStackView 32 | 33 | - (id)initWithFrame:(CGRect)frame 34 | { 35 | self = [super initWithFrame:frame]; 36 | if (self) { 37 | [self initializeWithFrame:self.bounds]; 38 | } 39 | return self; 40 | } 41 | 42 | #pragma mark - Private 43 | - (void)initializeWithFrame:(CGRect)frame 44 | { 45 | UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPanCard:)]; 46 | [self addGestureRecognizer:panGesture]; 47 | 48 | self.cardPools = [[NSMutableArray alloc] initWithCapacity:2]; 49 | self.cardPoolsUsingIndex = 0; 50 | 51 | self.isPanning = NO; 52 | 53 | self.skipPullBackCard = [WZCardView createCardView]; 54 | self.skipPullBackCard.hidden = YES; 55 | [self.skipPullBackCard setCenter:CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame))]; 56 | [self addSubview:self.skipPullBackCard]; 57 | 58 | WZCardView *firstCard = [WZCardView createCardView]; 59 | [self.cardPools addObject:firstCard]; 60 | [firstCard setCenter:CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame))]; 61 | 62 | WZCardView *secondCard = [WZCardView createCardView]; 63 | [self.cardPools addObject:secondCard]; 64 | [secondCard setCenter:CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame))]; 65 | 66 | [self addSubview:secondCard]; 67 | [self addSubview:firstCard]; 68 | 69 | firstCard.hidden = YES; 70 | secondCard.hidden = YES; 71 | } 72 | 73 | - (void)initCardView 74 | { 75 | if ([self.dataSource numberOfRatingPhotosInStack:self] == 0) { 76 | if (self.delegate && [self.delegate respondsToSelector:@selector(didFinishRateAllPhotosInStackView:)]) { 77 | [self.delegate didFinishRateAllPhotosInStackView:self]; 78 | } 79 | return; 80 | } 81 | 82 | WZCardView *secondCard = (WZCardView *)[self.cardPools objectAtIndex:1]; 83 | secondCard.hidden = NO; 84 | WZCardView *firstCard = (WZCardView *)[self.cardPools objectAtIndex:0]; 85 | firstCard.hidden = NO; 86 | 87 | [firstCard setPhoto:[self.dataSource photoForRatingQueueInStack:self]]; 88 | [secondCard setPhoto:[self.dataSource photoForRatingQueueInStack:self]]; 89 | } 90 | 91 | - (void)animationPhotoWithBlock:(void (^)(WZCardView *))animationBlock completion:(void (^)(WZCardView *))completionBlock 92 | { 93 | WZCardView *currentCard = self.cardPools[self.cardPoolsUsingIndex]; 94 | [UIView animateWithDuration:.25f animations:^{ 95 | if (animationBlock) animationBlock(currentCard); 96 | } completion:^(BOOL finished) { 97 | [self sendSubviewToBack:currentCard]; 98 | [currentCard restoreNormalCard]; 99 | 100 | if (completionBlock) completionBlock(currentCard); 101 | 102 | [self updateCards]; 103 | }]; 104 | } 105 | 106 | #pragma mark - Action 107 | - (void)didPanCard:(UIPanGestureRecognizer *)pan 108 | { 109 | self.translationPoint = [pan translationInView:self]; 110 | 111 | if (pan.state == UIGestureRecognizerStateBegan) { 112 | self.isPanning = YES; 113 | } else if (pan.state == UIGestureRecognizerStateChanged) { 114 | [self convertCoordinateToStatusWithX:self.translationPoint.x withY:self.translationPoint.y]; 115 | } else if (pan.state == UIGestureRecognizerStateEnded || 116 | pan.state == UIGestureRecognizerStateCancelled) { 117 | self.isPanning = NO; 118 | [self convertCoordinateToStatusWithX:self.translationPoint.x withY:self.translationPoint.y]; 119 | } 120 | } 121 | 122 | - (void)convertCoordinateToStatusWithX:(CGFloat)x withY:(CGFloat)y 123 | { 124 | CGFloat ratio = CGRectGetHeight(self.frame) / CGRectGetWidth(self.frame); 125 | 126 | CGFloat offsetX = abs(x); 127 | CGFloat offsetY = offsetX * ratio; 128 | 129 | if (y < -offsetY) { 130 | [self setStatus:WZPhotoStackStatusLike]; 131 | } else if (y > offsetY) { 132 | [self setStatus:WZPhotoStackStatusHate]; 133 | } else if (x > 0) { 134 | [self setStatus:WZPhotoStackStatusSkip]; 135 | } else { 136 | [self setStatus:WZPhotoStackStatusPullBack]; 137 | } 138 | } 139 | 140 | - (void)setStatus:(WZPhotoStackStatus)status 141 | { 142 | _status = status; 143 | 144 | switch (_status) { 145 | case WZPhotoStackStatusLike: 146 | if (self.isPanning) [self animateRateStatus]; 147 | else [self finishLikeStatus]; 148 | break; 149 | 150 | case WZPhotoStackStatusHate: 151 | if (self.isPanning) [self animateRateStatus]; 152 | else [self finishAverageStatus]; 153 | break; 154 | 155 | case WZPhotoStackStatusSkip: 156 | if (self.isPanning) [self animateSkipStatus]; 157 | else [self finishSkipStatus]; 158 | break; 159 | 160 | case WZPhotoStackStatusPullBack: 161 | if (self.isPanning) [self animatePullBackStatus]; 162 | else [self finishPullbacStatus]; 163 | break; 164 | 165 | default: 166 | break; 167 | } 168 | } 169 | 170 | - (void)animateRateStatus 171 | { 172 | self.isPulling = NO; 173 | 174 | WZCardView *currentCard = self.cardPools[self.cardPoolsUsingIndex]; 175 | [currentCard moveByTranslation:self.translationPoint]; 176 | [currentCard updateOverlay]; 177 | [currentCard updateRotation]; 178 | } 179 | 180 | - (void)finishLikeStatus 181 | { 182 | [self animationPhotoWithBlock:^(WZCardView *currentCard){ 183 | currentCard.center = CGPointMake([UIScreen mainScreen].bounds.size.width + currentCard.frame.size.width, 184 | -currentCard.frame.size.height); 185 | } completion:^(WZCardView *currentCard) { 186 | if (self.delegate && [self.delegate respondsToSelector:@selector(didRatePhotoAsLike:inStackView:)]) { 187 | [self.delegate didRatePhotoAsLike:currentCard.photo inStackView:self]; 188 | } 189 | }]; 190 | } 191 | 192 | - (void)finishAverageStatus 193 | { 194 | [self animationPhotoWithBlock:^(WZCardView *currentCard) { 195 | currentCard.center = CGPointMake(-currentCard.frame.size.width , 196 | [UIScreen mainScreen].bounds.size.height + currentCard.frame.size.height); 197 | } completion:^(WZCardView *currentCard) { 198 | if (self.delegate && [self.delegate respondsToSelector:@selector(didRatePhotoAsHate:inStackView:)]) { 199 | [self.delegate didRatePhotoAsHate:currentCard.photo inStackView:self]; 200 | } 201 | }]; 202 | } 203 | 204 | - (void)animateSkipStatus 205 | { 206 | self.isPulling = NO; 207 | [self sendSubviewToBack:self.skipPullBackCard]; 208 | [self.skipPullBackCard restoreNormalCard]; 209 | 210 | WZCardView *currentCard = self.cardPools[self.cardPoolsUsingIndex]; 211 | 212 | [currentCard moveByTranslation:self.translationPoint]; 213 | [currentCard updateRotation]; 214 | } 215 | 216 | - (void)finishSkipStatus 217 | { 218 | WZCardView *currentCard = self.cardPools[self.cardPoolsUsingIndex]; 219 | CGFloat xPos = CGRectGetMidX(self.bounds) + CGRectGetWidth(currentCard.frame); 220 | 221 | [UIView animateWithDuration:0.1 222 | animations:^{ 223 | currentCard.center = CGPointMake(xPos, CGRectGetMidY(self.bounds)); 224 | } 225 | completion:^(BOOL finished){ 226 | [self sendSubviewToBack:currentCard]; 227 | [UIView animateWithDuration:0.15f animations:^{ 228 | [currentCard restoreNormalCard]; 229 | } completion:^(BOOL finished) { 230 | if (self.delegate && 231 | [self.delegate respondsToSelector:@selector(didSkipPhoto:inStackView:)]) { 232 | [self.delegate didSkipPhoto:currentCard.photo inStackView:self]; 233 | } 234 | 235 | [self updateCards]; 236 | }]; 237 | }]; 238 | } 239 | 240 | - (void)animatePullBackStatus 241 | { 242 | if (!self.isPulling) { 243 | if ([self.dataSource numberOfSkipPhotosInStack:self] == 0) { 244 | return; 245 | } 246 | 247 | self.isPulling = YES; 248 | [self.skipPullBackCard setPhoto:[self.dataSource photoForSkipQueueInStack:self]]; 249 | } 250 | 251 | for (WZCardView *card in self.cardPools) { 252 | [card restoreNormalCard]; 253 | } 254 | 255 | self.skipPullBackCard.hidden = NO; 256 | self.skipPullBackCard.center = CGPointMake(self.skipPullBackCard.center.x + self.translationPoint.x, 257 | self.skipPullBackCard.center.y + self.translationPoint.y); 258 | } 259 | 260 | - (void)finishPullbacStatus 261 | { 262 | if (!self.isPulling) return; 263 | CGFloat xPos = CGRectGetMidX(self.bounds) - CGRectGetWidth(self.skipPullBackCard.frame); 264 | 265 | [UIView animateWithDuration:0.1 266 | animations:^{ 267 | self.skipPullBackCard.center = CGPointMake(xPos, CGRectGetMidY(self.bounds)); 268 | } 269 | completion:^(BOOL finished){ 270 | [self bringSubviewToFront: self.skipPullBackCard]; 271 | [UIView animateWithDuration:0.15f animations:^{ 272 | [self.skipPullBackCard restoreNormalCard]; 273 | } completion:^(BOOL finished) { 274 | [self sendSubviewToBack:self.skipPullBackCard]; 275 | [self swapDataWithPhoto:self.skipPullBackCard.photo]; 276 | 277 | [self.skipPullBackCard setPhoto:nil]; 278 | self.skipPullBackCard.hidden = YES; 279 | self.isPulling = NO; 280 | }]; 281 | }]; 282 | } 283 | 284 | - (void)updateCards 285 | { 286 | WZCardView *otherCard = self.cardPools[1 - self.cardPoolsUsingIndex]; 287 | [self bringSubviewToFront:otherCard]; 288 | 289 | WZCardView *card = self.cardPools[self.cardPoolsUsingIndex]; 290 | [card restoreNormalCard]; 291 | [card setPhoto:[self.dataSource photoForRatingQueueInStack:self]]; 292 | if (card.photo == nil) { 293 | if (![self.dataSource canFetchMoreDataInStack:self] && 294 | [self.dataSource numberOfRatingPhotosInStack:self] == 0) { 295 | 296 | if ([self.dataSource numberOfSkipPhotosInStack:self] == 0 && otherCard.photo == nil) { 297 | if (self.delegate && [self.delegate respondsToSelector:@selector(didFinishRateAllPhotosInStackView:)]) { 298 | [self.delegate didFinishRateAllPhotosInStackView:self]; 299 | } 300 | return; 301 | } else { 302 | [self.dataSource fetchSkipPhotosInStack:self]; 303 | [card setPhoto:[self.dataSource photoForRatingQueueInStack:self]]; 304 | } 305 | } 306 | } 307 | 308 | self.cardPoolsUsingIndex = 1 - self.cardPoolsUsingIndex; 309 | 310 | if ([self.dataSource numberOfRatingPhotosInStack:self] <= 2 && [self.dataSource canFetchMoreDataInStack:self]) { 311 | [self.dataSource fetchMoreDataFromCoreDataInStack:self]; 312 | } 313 | } 314 | 315 | - (void)swapDataWithPhoto:(UIImage *)photo 316 | { 317 | WZCardView *otherCard = self.cardPools[1 - self.cardPoolsUsingIndex]; 318 | WZCardView *currentCard = self.cardPools[self.cardPoolsUsingIndex]; 319 | 320 | if (self.delegate && [self.delegate respondsToSelector:@selector(didBringBackPhoto:inStackView:)]) { 321 | [self.delegate didBringBackPhoto:otherCard.photo inStackView:self]; 322 | } 323 | 324 | [otherCard setPhoto:currentCard.photo]; 325 | [currentCard setPhoto:photo]; 326 | } 327 | 328 | #pragma mark - Override 329 | - (void)setDataSource:(id)dataSource 330 | { 331 | _dataSource = dataSource; 332 | if (dataSource == nil) return; 333 | [self initCardView]; 334 | } 335 | 336 | @end 337 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZRecyclePhotoStackView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | Ziqi.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZRecyclePhotoStackView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WZViewController.h 3 | // WZRecyclePhotoStackView 4 | // 5 | // Created by satanwoo on 14-8-28. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WZViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/WZViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WZViewController.m 3 | // WZRecyclePhotoStackView 4 | // 5 | // Created by satanwoo on 14-8-28. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import "WZViewController.h" 10 | #import "WZPhotoStackView.h" 11 | 12 | const NSUInteger WZPhotoLoadCount = 10; 13 | 14 | @interface WZViewController () 15 | @property (nonatomic, strong) NSMutableArray *photos; 16 | @property (nonatomic, strong) NSMutableArray *skipPhotos; 17 | @property (nonatomic, strong) NSArray *datas; 18 | 19 | @property (nonatomic, strong) WZPhotoStackView *stackView; 20 | 21 | @property (nonatomic, assign) NSUInteger offset; 22 | @property (nonatomic, assign) BOOL noMoreData; 23 | 24 | - (void)loadData; 25 | - (void)configureCardView; 26 | @end 27 | 28 | @implementation WZViewController 29 | 30 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 31 | { 32 | self = [super initWithCoder:aDecoder]; 33 | if (self) { 34 | self.photos = [[NSMutableArray alloc] init]; 35 | self.skipPhotos = [[NSMutableArray alloc] init]; 36 | 37 | self.datas = @[@"FICDDemoImage000.jpg", 38 | @"FICDDemoImage001.jpg", 39 | @"FICDDemoImage002.jpg", 40 | @"FICDDemoImage003.jpg", 41 | @"FICDDemoImage004.jpg", 42 | @"FICDDemoImage005.jpg", 43 | @"FICDDemoImage006.jpg", 44 | @"FICDDemoImage007.jpg", 45 | @"FICDDemoImage008.jpg", 46 | @"FICDDemoImage009.jpg", 47 | @"FICDDemoImage010.jpg", 48 | @"FICDDemoImage011.jpg", 49 | @"FICDDemoImage012.jpg", 50 | @"FICDDemoImage013.jpg", 51 | @"FICDDemoImage014.jpg", 52 | @"FICDDemoImage015.jpg", 53 | @"FICDDemoImage016.jpg", 54 | ]; 55 | 56 | self.offset = 0; 57 | self.noMoreData = NO; 58 | } 59 | return self; 60 | } 61 | 62 | - (void)viewDidLoad 63 | { 64 | [super viewDidLoad]; 65 | 66 | [self loadData]; 67 | [self configureCardView]; 68 | } 69 | 70 | - (void)didReceiveMemoryWarning 71 | { 72 | [super didReceiveMemoryWarning]; 73 | } 74 | 75 | #pragma mark - Private 76 | - (void)configureCardView 77 | { 78 | self.stackView = [[WZPhotoStackView alloc] initWithFrame:CGRectMake(0, 79 | 0, 80 | CGRectGetWidth(self.view.frame), 81 | CGRectGetHeight(self.view.frame))]; 82 | 83 | [self.view addSubview:self.stackView]; 84 | 85 | self.stackView.delegate = self; 86 | self.stackView.dataSource = self; 87 | } 88 | 89 | - (void)loadData 90 | { 91 | NSUInteger threshold = 92 | [self.datas count] - self.offset < WZPhotoLoadCount? [self.datas count] : self.offset + WZPhotoLoadCount; 93 | 94 | NSUInteger loadedCount = threshold - self.offset; 95 | 96 | for (int i = self.offset; i < threshold; i++) { 97 | @autoreleasepool { 98 | NSString *imgName = self.datas[i]; 99 | UIImage *image = [UIImage imageNamed:imgName]; 100 | [self.photos addObject:image]; 101 | } 102 | } 103 | 104 | if (loadedCount < WZPhotoLoadCount) self.noMoreData = YES; 105 | self.offset += loadedCount; 106 | } 107 | 108 | #pragma mark - WZPhotoStackViewDataSource 109 | - (UIImage *)photoForSkipQueueInStack:(WZPhotoStackView *)stackView 110 | { 111 | if ([self.skipPhotos count] == 0) return nil; 112 | 113 | UIImage *skipPhoto = [self.skipPhotos lastObject]; 114 | [self.skipPhotos removeObject:skipPhoto]; 115 | return skipPhoto; 116 | } 117 | 118 | - (UIImage *)photoForRatingQueueInStack:(WZPhotoStackView *)stackView 119 | { 120 | if ([self.photos count] == 0) return nil; 121 | 122 | UIImage *photo = [self.photos firstObject]; 123 | [self.photos removeObject:photo]; 124 | return photo; 125 | } 126 | 127 | - (NSUInteger)numberOfRatingPhotosInStack:(WZPhotoStackView *)stackView 128 | { 129 | return [self.photos count]; 130 | } 131 | 132 | - (NSUInteger)numberOfSkipPhotosInStack:(WZPhotoStackView *)stackView 133 | { 134 | return [self.skipPhotos count]; 135 | } 136 | 137 | - (BOOL)canFetchMoreDataInStack:(WZPhotoStackView *)stackView 138 | { 139 | return !self.noMoreData; 140 | } 141 | 142 | - (void)fetchMoreDataFromCoreDataInStack:(WZPhotoStackView *)stackView 143 | { 144 | NSLog(@"refill the photos"); 145 | [self loadData]; 146 | } 147 | 148 | - (void)fetchSkipPhotosInStack:(WZPhotoStackView *)stackView 149 | { 150 | if ([self.skipPhotos count] != 0) { 151 | [self.photos addObjectsFromArray:self.skipPhotos]; 152 | [self.skipPhotos removeAllObjects]; 153 | } 154 | } 155 | 156 | #pragma mark - WZPhotoStackViewDelegate 157 | - (void)didSkipPhoto:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView 158 | { 159 | NSLog(@"skip photos"); 160 | [self.skipPhotos addObject:photo]; 161 | } 162 | 163 | - (void)didBringBackPhoto:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView 164 | { 165 | if (photo == nil) return; 166 | [self.photos insertObject:photo atIndex:0]; 167 | } 168 | 169 | - (void)didRatePhotoAsLike:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView 170 | { 171 | NSLog(@"haha you like it"); 172 | } 173 | 174 | - (void)didRatePhotoAsHate:(UIImage *)photo inStackView:(WZPhotoStackView *)stackView 175 | { 176 | NSLog(@"woops you hate it"); 177 | } 178 | 179 | - (void)didFinishRateAllPhotosInStackView:(WZPhotoStackView *)stackView 180 | { 181 | self.stackView.hidden = YES; 182 | NSLog(@"You have finish photo stack"); 183 | } 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WZRecyclePhotoStackView 4 | // 5 | // Created by satanwoo on 14-8-28. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "WZAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([WZAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/no.png -------------------------------------------------------------------------------- /WZRecyclePhotoStackView/yes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/WZRecyclePhotoStackView/yes.png -------------------------------------------------------------------------------- /WZRecyclePhotoStackViewTests/WZRecyclePhotoStackViewTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | Ziqi.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackViewTests/WZRecyclePhotoStackViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WZRecyclePhotoStackViewTests.m 3 | // WZRecyclePhotoStackViewTests 4 | // 5 | // Created by satanwoo on 14-8-28. 6 | // Copyright (c) 2014年 Ziqi Wu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WZRecyclePhotoStackViewTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WZRecyclePhotoStackViewTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /WZRecyclePhotoStackViewTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /屏幕快照 2017-04-23 上午2.29.53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/屏幕快照 2017-04-23 上午2.29.53.png -------------------------------------------------------------------------------- /屏幕快照 2017-04-23 上午2.30.06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/屏幕快照 2017-04-23 上午2.30.06.png -------------------------------------------------------------------------------- /屏幕快照 2017-04-23 上午2.48.35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatanWoo/WZRecyclePhotoStackView/f5f108b1aa9fe8c03d6fee7c5ee72489f077e5bf/屏幕快照 2017-04-23 上午2.48.35.png --------------------------------------------------------------------------------