├── .gitignore ├── LICENSE ├── README.md ├── Reveal.framework ├── Headers ├── Reveal └── Versions │ ├── A │ ├── Headers │ │ ├── IBARevealLoader.h │ │ ├── IBARevealLogger.h │ │ └── Reveal.h │ └── Reveal │ └── Current ├── TLSFOC-Demo.xcodeproj └── project.pbxproj ├── TLSFOC-Demo ├── Classes │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── TLContainerViewController.h │ ├── TLContainerViewController.m │ ├── TLTableViewController.h │ └── TLTableViewController.m ├── Other Sources │ ├── TLSFOC-Demo-Prefix.pch │ └── main.m ├── Resources │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── MainStoryboard.storyboard │ └── TLSFOC-Demo-Info.plist └── Tests │ ├── TLSFOC-DemoTests-Info.plist │ └── TLSFOC_DemoTests.m ├── TLSwipeForOptionsCell ├── TLOverlayView.h ├── TLOverlayView.m ├── TLSwipeForOptionsCell.h └── TLSwipeForOptionsCell.m ├── UITableViewCell-Swipe-for-Options.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── ash.xcuserdatad │ └── xcschemes │ ├── UITableViewCell-Swipe-for-Options.xcscheme │ └── xcschememanagement.plist └── UITableViewCell-Swipe-for-Options ├── Images.xcassets ├── AppIcon.appiconset │ └── Contents.json └── LaunchImage.launchimage │ └── Contents.json ├── MainStoryboard.storyboard ├── TLAppDelegate.h ├── TLAppDelegate.m ├── TLContainerViewController.h ├── TLContainerViewController.m ├── TLSwipeForOptionsCell.h ├── TLSwipeForOptionsCell.m ├── TLTableViewController.h ├── TLTableViewController.m ├── UITableViewCell-Swipe-for-Options-Info.plist ├── UITableViewCell-Swipe-for-Options-Prefix.pch ├── en.lproj └── InfoPlist.strings └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | *.xcuserstate 20 | *xcuserdata* 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Teehan+Lax 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UITableViewCell-Swipe-for-Options 2 | ================================= 3 | 4 | A reproduction of the iOS 7 Mail app's swipe-to-reveal options. Licensed under MIT. 5 | 6 | You can check out the [accompanying tutorial](http://www.teehanlax.com/blog/reproducing-the-ios-7-mail-apps-interface/), too. 7 | 8 | ![](http://f.cl.ly/items/0c1H1l0P320T0J1l2B3s/iOS6.gif) 9 | ![](http://f.cl.ly/items/2R1K282y2K3N1V1N1w3J/iOS7.gif) 10 | -------------------------------------------------------------------------------- /Reveal.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Reveal.framework/Reveal: -------------------------------------------------------------------------------- 1 | Versions/Current/Reveal -------------------------------------------------------------------------------- /Reveal.framework/Versions/A/Headers/IBARevealLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 Itty Bitty Apps. All rights reserved. 3 | 4 | #import 5 | 6 | extern NSString * const IBARevealLoaderRequestStartNotification; 7 | extern NSString * const IBARevealLoaderRequestStopNotification; 8 | 9 | extern NSString * const IBARevealLoaderSetOptionsNotification; 10 | extern NSString * const IBARevealLoaderOptionsLogLevelMaskKey; 11 | 12 | @interface IBARevealLoader : NSObject 13 | 14 | + (void)startServer; 15 | + (void)stopServer; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Reveal.framework/Versions/A/Headers/IBARevealLogger.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Itty Bitty Apps Pty Ltd. All rights reserved. 2 | // 3 | 4 | #import 5 | 6 | /*! 7 | \brief The Reveal Log level bit flags. 8 | \discussion These flags are addative. Ie, you should bitwise OR them together. 9 | 10 | \seealso IBARevealLoggerSetLevelMask 11 | \seealso IBARevealLoggerGetLevelMask 12 | 13 | Example: 14 | 15 | // Enable Error, Warning and Info logger levels. 16 | IBARevealLoggerSetLevelMask(IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo); 17 | 18 | */ 19 | typedef NS_OPTIONS(int32_t, IBARevealLogLevel) 20 | { 21 | IBARevealLogLevelNone = 0, 22 | IBARevealLogLevelDebug = (1 << 0), 23 | IBARevealLogLevelInfo = (1 << 1), 24 | IBARevealLogLevelWarn = (1 << 2), 25 | IBARevealLogLevelError = (1 << 3) 26 | }; 27 | 28 | /*! 29 | \brief Set the Reveal logger level mask. 30 | \param mask A bit mask which is a combination of the IBARevealLogLevel enum options. 31 | 32 | \discussion If you do not wish to see log messages from Reveal you should call this function with an appropriate level mask as early in your application's lifecycle as possible. For example in your application's main() function. 33 | 34 | Example: 35 | 36 | // Enable Error, Warning and Info logger levels. 37 | IBARevealLoggerSetLevelMask(IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo); 38 | 39 | */ 40 | extern void IBARevealLoggerSetLevelMask(int32_t mask); 41 | 42 | /*! 43 | \brief Get the current Reveal logger level mask. 44 | \return A bit mask representing the levels at which Reveal is currently logging. 45 | \discussion The default Reveal Logger level mask is IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo. 46 | 47 | Example: 48 | 49 | // Turn off the Info log level. 50 | IBARevealLoggerSetLevelMask(IBARevealLoggerGetLevelMask() & ~IBARevealLogLevelInfo); 51 | 52 | */ 53 | extern int32_t IBARevealLoggerGetLevelMask(void); 54 | -------------------------------------------------------------------------------- /Reveal.framework/Versions/A/Headers/Reveal.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Itty Bitty Apps Pty Ltd. All rights reserved. 2 | // 3 | 4 | #import "IBARevealLogger.h" 5 | #import "IBARevealLoader.h" -------------------------------------------------------------------------------- /Reveal.framework/Versions/A/Reveal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeehanLax/UITableViewCell-Swipe-for-Options/137b7c354c8feec5f59632e8840527454e6fb150/Reveal.framework/Versions/A/Reveal -------------------------------------------------------------------------------- /Reveal.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /TLSFOC-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DA3B2D7917C5843B00DB8C9F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2D7817C5843B00DB8C9F /* Foundation.framework */; }; 11 | DA3B2D7B17C5843B00DB8C9F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2D7A17C5843B00DB8C9F /* CoreGraphics.framework */; }; 12 | DA3B2D7D17C5843B00DB8C9F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2D7C17C5843B00DB8C9F /* UIKit.framework */; }; 13 | DA3B2D9B17C5843B00DB8C9F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2D9A17C5843B00DB8C9F /* XCTest.framework */; }; 14 | DA3B2D9C17C5843B00DB8C9F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2D7817C5843B00DB8C9F /* Foundation.framework */; }; 15 | DA3B2D9D17C5843B00DB8C9F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2D7C17C5843B00DB8C9F /* UIKit.framework */; }; 16 | DA3B2DC217C5849900DB8C9F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DB317C5849900DB8C9F /* AppDelegate.m */; }; 17 | DA3B2DC317C5849900DB8C9F /* TLContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DB517C5849900DB8C9F /* TLContainerViewController.m */; }; 18 | DA3B2DC417C5849900DB8C9F /* TLTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DB717C5849900DB8C9F /* TLTableViewController.m */; }; 19 | DA3B2DC517C5849900DB8C9F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DB917C5849900DB8C9F /* main.m */; }; 20 | DA3B2DC617C5849900DB8C9F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA3B2DBC17C5849900DB8C9F /* Images.xcassets */; }; 21 | DA3B2DC717C5849900DB8C9F /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA3B2DBD17C5849900DB8C9F /* MainStoryboard.storyboard */; }; 22 | DA3B2DD417C5853E00DB8C9F /* TLSFOC_DemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DD217C5853E00DB8C9F /* TLSFOC_DemoTests.m */; }; 23 | DA3B2DD617C5862200DB8C9F /* Reveal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2DD517C5862200DB8C9F /* Reveal.framework */; }; 24 | DA3B2DD917C5863200DB8C9F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2DD717C5863200DB8C9F /* CFNetwork.framework */; }; 25 | DA3B2DDA17C5863200DB8C9F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B2DD817C5863200DB8C9F /* QuartzCore.framework */; }; 26 | DA3B2DE017C5869900DB8C9F /* TLOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DDD17C5869900DB8C9F /* TLOverlayView.m */; }; 27 | DA3B2DE117C5869900DB8C9F /* TLSwipeForOptionsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B2DDF17C5869900DB8C9F /* TLSwipeForOptionsCell.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | DA3B2D9E17C5843B00DB8C9F /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = DA3B2D6D17C5843B00DB8C9F /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = DA3B2D7417C5843B00DB8C9F; 36 | remoteInfo = "TLSFOC-Demo"; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | DA3B2D7517C5843B00DB8C9F /* TLSFOC-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TLSFOC-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | DA3B2D7817C5843B00DB8C9F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 43 | DA3B2D7A17C5843B00DB8C9F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 44 | DA3B2D7C17C5843B00DB8C9F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 45 | DA3B2D9917C5843B00DB8C9F /* TLSFOC-DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TLSFOC-DemoTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | DA3B2D9A17C5843B00DB8C9F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 47 | DA3B2DB217C5849900DB8C9F /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | DA3B2DB317C5849900DB8C9F /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | DA3B2DB417C5849900DB8C9F /* TLContainerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLContainerViewController.h; sourceTree = ""; }; 50 | DA3B2DB517C5849900DB8C9F /* TLContainerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLContainerViewController.m; sourceTree = ""; }; 51 | DA3B2DB617C5849900DB8C9F /* TLTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLTableViewController.h; sourceTree = ""; }; 52 | DA3B2DB717C5849900DB8C9F /* TLTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLTableViewController.m; sourceTree = ""; }; 53 | DA3B2DB917C5849900DB8C9F /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54 | DA3B2DBA17C5849900DB8C9F /* TLSFOC-Demo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TLSFOC-Demo-Prefix.pch"; sourceTree = ""; }; 55 | DA3B2DBC17C5849900DB8C9F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 56 | DA3B2DBD17C5849900DB8C9F /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = ""; }; 57 | DA3B2DBE17C5849900DB8C9F /* TLSFOC-Demo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TLSFOC-Demo-Info.plist"; sourceTree = ""; }; 58 | DA3B2DD117C5853E00DB8C9F /* TLSFOC-DemoTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TLSFOC-DemoTests-Info.plist"; sourceTree = ""; }; 59 | DA3B2DD217C5853E00DB8C9F /* TLSFOC_DemoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLSFOC_DemoTests.m; sourceTree = ""; }; 60 | DA3B2DD517C5862200DB8C9F /* Reveal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Reveal.framework; sourceTree = ""; }; 61 | DA3B2DD717C5863200DB8C9F /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 62 | DA3B2DD817C5863200DB8C9F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 63 | DA3B2DDC17C5869900DB8C9F /* TLOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLOverlayView.h; sourceTree = ""; }; 64 | DA3B2DDD17C5869900DB8C9F /* TLOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLOverlayView.m; sourceTree = ""; }; 65 | DA3B2DDE17C5869900DB8C9F /* TLSwipeForOptionsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLSwipeForOptionsCell.h; sourceTree = ""; }; 66 | DA3B2DDF17C5869900DB8C9F /* TLSwipeForOptionsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLSwipeForOptionsCell.m; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | DA3B2D7217C5843B00DB8C9F /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | DA3B2D7B17C5843B00DB8C9F /* CoreGraphics.framework in Frameworks */, 75 | DA3B2D7D17C5843B00DB8C9F /* UIKit.framework in Frameworks */, 76 | DA3B2D7917C5843B00DB8C9F /* Foundation.framework in Frameworks */, 77 | DA3B2DD617C5862200DB8C9F /* Reveal.framework in Frameworks */, 78 | DA3B2DD917C5863200DB8C9F /* CFNetwork.framework in Frameworks */, 79 | DA3B2DDA17C5863200DB8C9F /* QuartzCore.framework in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | DA3B2D9617C5843B00DB8C9F /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | DA3B2D9B17C5843B00DB8C9F /* XCTest.framework in Frameworks */, 88 | DA3B2D9D17C5843B00DB8C9F /* UIKit.framework in Frameworks */, 89 | DA3B2D9C17C5843B00DB8C9F /* Foundation.framework in Frameworks */, 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | /* End PBXFrameworksBuildPhase section */ 94 | 95 | /* Begin PBXGroup section */ 96 | DA3B2D6C17C5843B00DB8C9F = { 97 | isa = PBXGroup; 98 | children = ( 99 | DA3B2DB017C5849900DB8C9F /* TLSFOC-Demo */, 100 | DA3B2DD017C5853E00DB8C9F /* TLSFOC-DemoTests */, 101 | DA3B2D7717C5843B00DB8C9F /* Frameworks */, 102 | DA3B2D7617C5843B00DB8C9F /* Products */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | DA3B2D7617C5843B00DB8C9F /* Products */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | DA3B2D7517C5843B00DB8C9F /* TLSFOC-Demo.app */, 110 | DA3B2D9917C5843B00DB8C9F /* TLSFOC-DemoTests.xctest */, 111 | ); 112 | name = Products; 113 | sourceTree = ""; 114 | }; 115 | DA3B2D7717C5843B00DB8C9F /* Frameworks */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | DA3B2D7817C5843B00DB8C9F /* Foundation.framework */, 119 | DA3B2D7A17C5843B00DB8C9F /* CoreGraphics.framework */, 120 | DA3B2D7C17C5843B00DB8C9F /* UIKit.framework */, 121 | DA3B2D9A17C5843B00DB8C9F /* XCTest.framework */, 122 | DA3B2DD517C5862200DB8C9F /* Reveal.framework */, 123 | DA3B2DD717C5863200DB8C9F /* CFNetwork.framework */, 124 | DA3B2DD817C5863200DB8C9F /* QuartzCore.framework */, 125 | ); 126 | name = Frameworks; 127 | sourceTree = ""; 128 | }; 129 | DA3B2DB017C5849900DB8C9F /* TLSFOC-Demo */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | DA3B2DB117C5849900DB8C9F /* Classes */, 133 | DA3B2DB817C5849900DB8C9F /* Other Sources */, 134 | DA3B2DBB17C5849900DB8C9F /* Resources */, 135 | ); 136 | path = "TLSFOC-Demo"; 137 | sourceTree = ""; 138 | }; 139 | DA3B2DB117C5849900DB8C9F /* Classes */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | DA3B2DB217C5849900DB8C9F /* AppDelegate.h */, 143 | DA3B2DB317C5849900DB8C9F /* AppDelegate.m */, 144 | DA3B2DB417C5849900DB8C9F /* TLContainerViewController.h */, 145 | DA3B2DB517C5849900DB8C9F /* TLContainerViewController.m */, 146 | DA3B2DB617C5849900DB8C9F /* TLTableViewController.h */, 147 | DA3B2DB717C5849900DB8C9F /* TLTableViewController.m */, 148 | DA3B2DDB17C5869900DB8C9F /* TLSwipeForOptionsCell */, 149 | ); 150 | path = Classes; 151 | sourceTree = ""; 152 | }; 153 | DA3B2DB817C5849900DB8C9F /* Other Sources */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | DA3B2DB917C5849900DB8C9F /* main.m */, 157 | DA3B2DBA17C5849900DB8C9F /* TLSFOC-Demo-Prefix.pch */, 158 | ); 159 | path = "Other Sources"; 160 | sourceTree = ""; 161 | }; 162 | DA3B2DBB17C5849900DB8C9F /* Resources */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | DA3B2DBC17C5849900DB8C9F /* Images.xcassets */, 166 | DA3B2DBD17C5849900DB8C9F /* MainStoryboard.storyboard */, 167 | DA3B2DBE17C5849900DB8C9F /* TLSFOC-Demo-Info.plist */, 168 | ); 169 | path = Resources; 170 | sourceTree = ""; 171 | }; 172 | DA3B2DD017C5853E00DB8C9F /* TLSFOC-DemoTests */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | DA3B2DD217C5853E00DB8C9F /* TLSFOC_DemoTests.m */, 176 | DA3B2DD117C5853E00DB8C9F /* TLSFOC-DemoTests-Info.plist */, 177 | ); 178 | name = "TLSFOC-DemoTests"; 179 | path = "TLSFOC-Demo/Tests"; 180 | sourceTree = ""; 181 | }; 182 | DA3B2DDB17C5869900DB8C9F /* TLSwipeForOptionsCell */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | DA3B2DDC17C5869900DB8C9F /* TLOverlayView.h */, 186 | DA3B2DDD17C5869900DB8C9F /* TLOverlayView.m */, 187 | DA3B2DDE17C5869900DB8C9F /* TLSwipeForOptionsCell.h */, 188 | DA3B2DDF17C5869900DB8C9F /* TLSwipeForOptionsCell.m */, 189 | ); 190 | path = TLSwipeForOptionsCell; 191 | sourceTree = SOURCE_ROOT; 192 | }; 193 | /* End PBXGroup section */ 194 | 195 | /* Begin PBXNativeTarget section */ 196 | DA3B2D7417C5843B00DB8C9F /* TLSFOC-Demo */ = { 197 | isa = PBXNativeTarget; 198 | buildConfigurationList = DA3B2DAA17C5843B00DB8C9F /* Build configuration list for PBXNativeTarget "TLSFOC-Demo" */; 199 | buildPhases = ( 200 | DA3B2D7117C5843B00DB8C9F /* Sources */, 201 | DA3B2D7217C5843B00DB8C9F /* Frameworks */, 202 | DA3B2D7317C5843B00DB8C9F /* Resources */, 203 | ); 204 | buildRules = ( 205 | ); 206 | dependencies = ( 207 | ); 208 | name = "TLSFOC-Demo"; 209 | productName = "TLSFOC-Demo"; 210 | productReference = DA3B2D7517C5843B00DB8C9F /* TLSFOC-Demo.app */; 211 | productType = "com.apple.product-type.application"; 212 | }; 213 | DA3B2D9817C5843B00DB8C9F /* TLSFOC-DemoTests */ = { 214 | isa = PBXNativeTarget; 215 | buildConfigurationList = DA3B2DAD17C5843B00DB8C9F /* Build configuration list for PBXNativeTarget "TLSFOC-DemoTests" */; 216 | buildPhases = ( 217 | DA3B2D9517C5843B00DB8C9F /* Sources */, 218 | DA3B2D9617C5843B00DB8C9F /* Frameworks */, 219 | DA3B2D9717C5843B00DB8C9F /* Resources */, 220 | ); 221 | buildRules = ( 222 | ); 223 | dependencies = ( 224 | DA3B2D9F17C5843B00DB8C9F /* PBXTargetDependency */, 225 | ); 226 | name = "TLSFOC-DemoTests"; 227 | productName = "TLSFOC-DemoTests"; 228 | productReference = DA3B2D9917C5843B00DB8C9F /* TLSFOC-DemoTests.xctest */; 229 | productType = "com.apple.product-type.bundle.unit-test"; 230 | }; 231 | /* End PBXNativeTarget section */ 232 | 233 | /* Begin PBXProject section */ 234 | DA3B2D6D17C5843B00DB8C9F /* Project object */ = { 235 | isa = PBXProject; 236 | attributes = { 237 | LastUpgradeCheck = 0500; 238 | ORGANIZATIONNAME = "Teehan+Lax"; 239 | TargetAttributes = { 240 | DA3B2D9817C5843B00DB8C9F = { 241 | TestTargetID = DA3B2D7417C5843B00DB8C9F; 242 | }; 243 | }; 244 | }; 245 | buildConfigurationList = DA3B2D7017C5843B00DB8C9F /* Build configuration list for PBXProject "TLSFOC-Demo" */; 246 | compatibilityVersion = "Xcode 3.2"; 247 | developmentRegion = English; 248 | hasScannedForEncodings = 0; 249 | knownRegions = ( 250 | en, 251 | Base, 252 | ); 253 | mainGroup = DA3B2D6C17C5843B00DB8C9F; 254 | productRefGroup = DA3B2D7617C5843B00DB8C9F /* Products */; 255 | projectDirPath = ""; 256 | projectRoot = ""; 257 | targets = ( 258 | DA3B2D7417C5843B00DB8C9F /* TLSFOC-Demo */, 259 | DA3B2D9817C5843B00DB8C9F /* TLSFOC-DemoTests */, 260 | ); 261 | }; 262 | /* End PBXProject section */ 263 | 264 | /* Begin PBXResourcesBuildPhase section */ 265 | DA3B2D7317C5843B00DB8C9F /* Resources */ = { 266 | isa = PBXResourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | DA3B2DC717C5849900DB8C9F /* MainStoryboard.storyboard in Resources */, 270 | DA3B2DC617C5849900DB8C9F /* Images.xcassets in Resources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | DA3B2D9717C5843B00DB8C9F /* Resources */ = { 275 | isa = PBXResourcesBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | /* End PBXResourcesBuildPhase section */ 282 | 283 | /* Begin PBXSourcesBuildPhase section */ 284 | DA3B2D7117C5843B00DB8C9F /* Sources */ = { 285 | isa = PBXSourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | DA3B2DC217C5849900DB8C9F /* AppDelegate.m in Sources */, 289 | DA3B2DC317C5849900DB8C9F /* TLContainerViewController.m in Sources */, 290 | DA3B2DC417C5849900DB8C9F /* TLTableViewController.m in Sources */, 291 | DA3B2DC517C5849900DB8C9F /* main.m in Sources */, 292 | DA3B2DE017C5869900DB8C9F /* TLOverlayView.m in Sources */, 293 | DA3B2DE117C5869900DB8C9F /* TLSwipeForOptionsCell.m in Sources */, 294 | ); 295 | runOnlyForDeploymentPostprocessing = 0; 296 | }; 297 | DA3B2D9517C5843B00DB8C9F /* Sources */ = { 298 | isa = PBXSourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | DA3B2DD417C5853E00DB8C9F /* TLSFOC_DemoTests.m in Sources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | /* End PBXSourcesBuildPhase section */ 306 | 307 | /* Begin PBXTargetDependency section */ 308 | DA3B2D9F17C5843B00DB8C9F /* PBXTargetDependency */ = { 309 | isa = PBXTargetDependency; 310 | target = DA3B2D7417C5843B00DB8C9F /* TLSFOC-Demo */; 311 | targetProxy = DA3B2D9E17C5843B00DB8C9F /* PBXContainerItemProxy */; 312 | }; 313 | /* End PBXTargetDependency section */ 314 | 315 | /* Begin XCBuildConfiguration section */ 316 | DA3B2DA817C5843B00DB8C9F /* Debug */ = { 317 | isa = XCBuildConfiguration; 318 | buildSettings = { 319 | ALWAYS_SEARCH_USER_PATHS = NO; 320 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 321 | CLANG_CXX_LIBRARY = "libc++"; 322 | CLANG_ENABLE_MODULES = YES; 323 | CLANG_ENABLE_OBJC_ARC = YES; 324 | CLANG_WARN_BOOL_CONVERSION = YES; 325 | CLANG_WARN_CONSTANT_CONVERSION = YES; 326 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 327 | CLANG_WARN_EMPTY_BODY = YES; 328 | CLANG_WARN_ENUM_CONVERSION = YES; 329 | CLANG_WARN_INT_CONVERSION = YES; 330 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 331 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 332 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 333 | COPY_PHASE_STRIP = NO; 334 | GCC_C_LANGUAGE_STANDARD = gnu99; 335 | GCC_DYNAMIC_NO_PIC = NO; 336 | GCC_OPTIMIZATION_LEVEL = 0; 337 | GCC_PREPROCESSOR_DEFINITIONS = ( 338 | "DEBUG=1", 339 | "$(inherited)", 340 | ); 341 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 342 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 343 | GCC_WARN_UNDECLARED_SELECTOR = YES; 344 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 345 | GCC_WARN_UNUSED_FUNCTION = YES; 346 | GCC_WARN_UNUSED_VARIABLE = YES; 347 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 348 | ONLY_ACTIVE_ARCH = YES; 349 | SDKROOT = iphoneos; 350 | }; 351 | name = Debug; 352 | }; 353 | DA3B2DA917C5843B00DB8C9F /* Release */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ALWAYS_SEARCH_USER_PATHS = NO; 357 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 358 | CLANG_CXX_LIBRARY = "libc++"; 359 | CLANG_ENABLE_MODULES = YES; 360 | CLANG_ENABLE_OBJC_ARC = YES; 361 | CLANG_WARN_BOOL_CONVERSION = YES; 362 | CLANG_WARN_CONSTANT_CONVERSION = YES; 363 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 364 | CLANG_WARN_EMPTY_BODY = YES; 365 | CLANG_WARN_ENUM_CONVERSION = YES; 366 | CLANG_WARN_INT_CONVERSION = YES; 367 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 368 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 369 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 370 | COPY_PHASE_STRIP = YES; 371 | ENABLE_NS_ASSERTIONS = NO; 372 | GCC_C_LANGUAGE_STANDARD = gnu99; 373 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 374 | GCC_WARN_UNDECLARED_SELECTOR = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 376 | GCC_WARN_UNUSED_FUNCTION = YES; 377 | GCC_WARN_UNUSED_VARIABLE = YES; 378 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 379 | SDKROOT = iphoneos; 380 | VALIDATE_PRODUCT = YES; 381 | }; 382 | name = Release; 383 | }; 384 | DA3B2DAB17C5843B00DB8C9F /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 388 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 389 | FRAMEWORK_SEARCH_PATHS = ( 390 | "$(inherited)", 391 | "$(SRCROOT)", 392 | "/App\\ Development/github/UITableViewCell-Swipe-for-Options", 393 | ); 394 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 395 | GCC_PREFIX_HEADER = "TLSFOC-Demo/Other Sources/TLSFOC-Demo-Prefix.pch"; 396 | INFOPLIST_FILE = "$(SRCROOT)/TLSFOC-Demo/Resources/TLSFOC-Demo-Info.plist"; 397 | OTHER_LDFLAGS = "-ObjC"; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | WRAPPER_EXTENSION = app; 400 | }; 401 | name = Debug; 402 | }; 403 | DA3B2DAC17C5843B00DB8C9F /* Release */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 407 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 408 | FRAMEWORK_SEARCH_PATHS = ( 409 | "$(inherited)", 410 | "$(SRCROOT)", 411 | "/App\\ Development/github/UITableViewCell-Swipe-for-Options", 412 | ); 413 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 414 | GCC_PREFIX_HEADER = "TLSFOC-Demo/Other Sources/TLSFOC-Demo-Prefix.pch"; 415 | INFOPLIST_FILE = "$(SRCROOT)/TLSFOC-Demo/Resources/TLSFOC-Demo-Info.plist"; 416 | OTHER_LDFLAGS = "-ObjC"; 417 | PRODUCT_NAME = "$(TARGET_NAME)"; 418 | WRAPPER_EXTENSION = app; 419 | }; 420 | name = Release; 421 | }; 422 | DA3B2DAE17C5843B00DB8C9F /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/TLSFOC-Demo.app/TLSFOC-Demo"; 426 | FRAMEWORK_SEARCH_PATHS = ( 427 | "$(SDKROOT)/Developer/Library/Frameworks", 428 | "$(inherited)", 429 | "$(DEVELOPER_FRAMEWORKS_DIR)", 430 | ); 431 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 432 | GCC_PREFIX_HEADER = "TLSFOC-Demo/TLSFOC-Demo-Prefix.pch"; 433 | GCC_PREPROCESSOR_DEFINITIONS = ( 434 | "DEBUG=1", 435 | "$(inherited)", 436 | ); 437 | INFOPLIST_FILE = "TLSFOC-Demo/Tests/TLSFOC-DemoTests-Info.plist"; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | TEST_HOST = "$(BUNDLE_LOADER)"; 440 | WRAPPER_EXTENSION = xctest; 441 | }; 442 | name = Debug; 443 | }; 444 | DA3B2DAF17C5843B00DB8C9F /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/TLSFOC-Demo.app/TLSFOC-Demo"; 448 | FRAMEWORK_SEARCH_PATHS = ( 449 | "$(SDKROOT)/Developer/Library/Frameworks", 450 | "$(inherited)", 451 | "$(DEVELOPER_FRAMEWORKS_DIR)", 452 | ); 453 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 454 | GCC_PREFIX_HEADER = "TLSFOC-Demo/TLSFOC-Demo-Prefix.pch"; 455 | INFOPLIST_FILE = "TLSFOC-Demo/Tests/TLSFOC-DemoTests-Info.plist"; 456 | PRODUCT_NAME = "$(TARGET_NAME)"; 457 | TEST_HOST = "$(BUNDLE_LOADER)"; 458 | WRAPPER_EXTENSION = xctest; 459 | }; 460 | name = Release; 461 | }; 462 | /* End XCBuildConfiguration section */ 463 | 464 | /* Begin XCConfigurationList section */ 465 | DA3B2D7017C5843B00DB8C9F /* Build configuration list for PBXProject "TLSFOC-Demo" */ = { 466 | isa = XCConfigurationList; 467 | buildConfigurations = ( 468 | DA3B2DA817C5843B00DB8C9F /* Debug */, 469 | DA3B2DA917C5843B00DB8C9F /* Release */, 470 | ); 471 | defaultConfigurationIsVisible = 0; 472 | defaultConfigurationName = Release; 473 | }; 474 | DA3B2DAA17C5843B00DB8C9F /* Build configuration list for PBXNativeTarget "TLSFOC-Demo" */ = { 475 | isa = XCConfigurationList; 476 | buildConfigurations = ( 477 | DA3B2DAB17C5843B00DB8C9F /* Debug */, 478 | DA3B2DAC17C5843B00DB8C9F /* Release */, 479 | ); 480 | defaultConfigurationIsVisible = 0; 481 | defaultConfigurationName = Release; 482 | }; 483 | DA3B2DAD17C5843B00DB8C9F /* Build configuration list for PBXNativeTarget "TLSFOC-DemoTests" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | DA3B2DAE17C5843B00DB8C9F /* Debug */, 487 | DA3B2DAF17C5843B00DB8C9F /* Release */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | /* End XCConfigurationList section */ 493 | }; 494 | rootObject = DA3B2D6D17C5843B00DB8C9F /* Project object */; 495 | } 496 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 14 | // Override point for customization after application launch. 15 | return YES; 16 | } 17 | 18 | - (void)applicationWillResignActive:(UIApplication *)application { 19 | // 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. 20 | // 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. 21 | } 22 | 23 | - (void)applicationDidEnterBackground:(UIApplication *)application { 24 | // 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. 25 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 26 | } 27 | 28 | - (void)applicationWillEnterForeground:(UIApplication *)application { 29 | // 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. 30 | } 31 | 32 | - (void)applicationDidBecomeActive:(UIApplication *)application { 33 | // 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. 34 | } 35 | 36 | - (void)applicationWillTerminate:(UIApplication *)application { 37 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Classes/TLContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLContainerViewController.h 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TLContainerViewController : UIViewController 12 | 13 | @property (nonatomic, weak) IBOutlet UIToolbar *toolbar; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Classes/TLContainerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLContainerViewController.m 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLContainerViewController.h" 10 | #import "TLTableViewController.h" 11 | 12 | @interface TLContainerViewController () 13 | 14 | @property (nonatomic, weak) TLTableViewController *tableViewController; 15 | 16 | @end 17 | 18 | @implementation TLContainerViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | self.navigationItem.leftBarButtonItem = self.tableViewController.navigationItem.leftBarButtonItem; 24 | self.navigationItem.rightBarButtonItem = self.tableViewController.navigationItem.rightBarButtonItem; 25 | 26 | self.navigationItem.title = @"Table View"; 27 | 28 | [self setAppropriateToolbarItems]; 29 | } 30 | 31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 32 | if ([segue.identifier isEqualToString:@"embed"]) { 33 | self.tableViewController = segue.destinationViewController; 34 | self.tableViewController.delegate = self; 35 | } 36 | } 37 | 38 | #pragma mark - Private Methods 39 | 40 | // Sets the appropriate UIBarButtonItems for our toolbar depending on the editing property of self.tableViewController. 41 | - (void)setAppropriateToolbarItems { 42 | NSArray *itemsArray; 43 | 44 | if (self.tableViewController.editing) { 45 | itemsArray = @[[[UIBarButtonItem alloc] initWithTitle:@"Trash" style:UIBarButtonItemStylePlain target:self action:@selector(userDidPressTrashButton:)], 46 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 47 | [[UIBarButtonItem alloc] initWithTitle:@"Move" style:UIBarButtonItemStylePlain target:self action:@selector(userDidPressMoveButton:)], 48 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 49 | [[UIBarButtonItem alloc] initWithTitle:@"Mark" style:UIBarButtonItemStylePlain target:self action:@selector(userDidPressMarkButton:)]]; 50 | } else { 51 | itemsArray = @[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 52 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(userDidPressAddButton:)]]; 53 | } 54 | 55 | [self.toolbar setItems:itemsArray animated:NO]; 56 | } 57 | 58 | #pragma mark - User Interface Methods 59 | 60 | /* 61 | These are all configurable to do whatever you want with them. We only really use the userDidPressTrashButton: method. 62 | */ 63 | 64 | - (void)userDidPressAddButton:(id)sender { 65 | [self.tableViewController insertNewObject:nil]; 66 | } 67 | 68 | - (void)userDidPressTrashButton:(id)sender { 69 | [self.tableViewController deleteSelectedCells]; 70 | [self.tableViewController setEditing:NO animated:YES]; 71 | } 72 | 73 | - (void)userDidPressMoveButton:(id)sender { 74 | [self.tableViewController setEditing:NO animated:YES]; 75 | } 76 | 77 | - (void)userDidPressMarkButton:(id)sender { 78 | [self.tableViewController setEditing:NO animated:YES]; 79 | } 80 | 81 | #pragma mark - TLTableViewControllerDelegate Methods 82 | 83 | - (void)tableViewController:(TLTableViewController *)viewController didChangeEditing:(BOOL)editing { 84 | [self setAppropriateToolbarItems]; 85 | } 86 | 87 | - (void)presentActionSheet:(UIActionSheet *)actionSheet fromViewController:(TLTableViewController *)viewController { 88 | [actionSheet showFromToolbar:self.toolbar]; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Classes/TLTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLTableViewController.h 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class TLTableViewController; 12 | 13 | @protocol TLTableViewControllerDelegate 14 | 15 | - (void)tableViewController:(TLTableViewController *)viewController didChangeEditing:(BOOL)editing; 16 | - (void)presentActionSheet:(UIActionSheet *)actionSheet fromViewController:(TLTableViewController *)viewController; 17 | 18 | @end 19 | 20 | @interface TLTableViewController : UITableViewController 21 | 22 | @property (nonatomic, weak) id delegate; 23 | 24 | - (void)insertNewObject:(id)sender; 25 | - (void)deleteSelectedCells; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Classes/TLTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLTableViewController.m 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLTableViewController.h" 10 | 11 | #import "TLSwipeForOptionsCell.h" 12 | #import "TLContainerViewController.h" 13 | #import "TLOverlayView.h" 14 | 15 | @interface TLTableViewController () { 16 | NSMutableArray *_objects; 17 | } 18 | 19 | // We need to keep track of the most recently selected cell for the action sheet. 20 | @property (nonatomic, weak) UITableViewCell *cellDisplayingMenuOptions; 21 | @property (nonatomic, weak) UITableViewCell *mostRecentlySelectedMoreCell; 22 | @property (nonatomic, strong) TLOverlayView *overlayView; 23 | 24 | @end 25 | 26 | @implementation TLTableViewController 27 | 28 | - (void)viewDidLoad { 29 | [super viewDidLoad]; 30 | self.navigationItem.rightBarButtonItem = self.editButtonItem; 31 | 32 | self.tableView.allowsSelectionDuringEditing = YES; 33 | self.tableView.allowsMultipleSelectionDuringEditing = YES; 34 | } 35 | 36 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 37 | [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 38 | 39 | // Need to do this to keep the view in a consistent state (layoutSubviews in the cell expects itself to be "closed") 40 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellShouldHideMenuNotification object:self.tableView]; 41 | } 42 | 43 | #pragma mark - Public Methods 44 | 45 | // Method to delete the cells that are currently selected. 46 | - (void)deleteSelectedCells { 47 | NSArray *indexPathsOfSelectedCells = [self.tableView indexPathsForSelectedRows]; 48 | 49 | // MUST be enumerated in reverse order otherwise the _objects indices become invalid. 50 | [indexPathsOfSelectedCells enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSIndexPath *obj, NSUInteger idx, BOOL *stop) { 51 | [_objects removeObjectAtIndex:obj.row]; 52 | }]; 53 | 54 | [self.tableView deleteRowsAtIndexPaths:indexPathsOfSelectedCells withRowAnimation:UITableViewRowAnimationAutomatic]; 55 | } 56 | 57 | // Inserts a new object into the _objects array. 58 | - (void)insertNewObject:(id)sender { 59 | if (!_objects) { 60 | _objects = [[NSMutableArray alloc] init]; 61 | } 62 | [_objects insertObject:[NSDate date] atIndex:0]; 63 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 64 | [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 65 | 66 | // Need to call this whenever we scroll our table view programmatically 67 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellShouldHideMenuNotification object:self.tableView]; 68 | } 69 | 70 | #pragma mark - Table View 71 | 72 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 73 | return _objects.count; 74 | } 75 | 76 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 77 | TLSwipeForOptionsCell *cell = (TLSwipeForOptionsCell *)[tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 78 | 79 | NSDate *object = _objects[indexPath.row]; 80 | cell.textLabel.text = [object description]; 81 | cell.delegate = self; 82 | 83 | return cell; 84 | } 85 | 86 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 87 | // Return NO if you do not want the specified item to be editable. 88 | return YES; 89 | } 90 | 91 | - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 92 | return UITableViewCellEditingStyleNone; 93 | } 94 | 95 | - (void)setEditing:(BOOL)editing animated:(BOOL)animated { 96 | [super setEditing:editing animated:animated]; 97 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellShouldHideMenuNotification object:self.tableView]; 98 | [self.delegate tableViewController:self didChangeEditing:editing]; 99 | } 100 | 101 | #pragma UIScrollViewDelegate Methods 102 | 103 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 104 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellShouldHideMenuNotification object:scrollView]; 105 | } 106 | 107 | #pragma mark - TLOverlayViewDelegate Methods 108 | 109 | - (UIView *)overlayView:(TLOverlayView *)view didHitTest:(CGPoint)point withEvent:(UIEvent *)event { 110 | BOOL shouldInterceptTouches = YES; 111 | 112 | CGPoint location = [self.view convertPoint:point fromView:view]; 113 | CGRect rect = [self.view convertRect:self.cellDisplayingMenuOptions.frame toView:self.view]; 114 | 115 | shouldInterceptTouches = CGRectContainsPoint(rect, location); 116 | if (!shouldInterceptTouches) 117 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellShouldHideMenuNotification object:self.tableView]; 118 | 119 | return shouldInterceptTouches?[self.cellDisplayingMenuOptions hitTest:point withEvent:event]:view; 120 | } 121 | 122 | #pragma mark - TLSwipeForOptionsCellDelegate Methods 123 | 124 | - (void)cell:(TLSwipeForOptionsCell *)cell didShowMenu:(BOOL)isShowingMenu { 125 | self.cellDisplayingMenuOptions = cell; 126 | [self.tableView setScrollEnabled:!isShowingMenu]; 127 | if (isShowingMenu) { 128 | if (!self.overlayView) { 129 | self.overlayView = [[TLOverlayView alloc] initWithFrame:self.view.bounds]; 130 | [self.overlayView setDelegate:self]; 131 | } 132 | 133 | [self.overlayView setFrame:self.view.bounds]; 134 | [self.view addSubview:self.overlayView]; 135 | 136 | for (id subview in [self.tableView subviews]) { 137 | if (![subview isEqual:cell] && [subview isKindOfClass:[TLSwipeForOptionsCell class]]) 138 | [subview setUserInteractionEnabled:NO]; 139 | } 140 | } else { 141 | [self.overlayView removeFromSuperview]; 142 | 143 | for (id subview in [self.tableView subviews]) { 144 | if (![subview isEqual:cell] && [subview isKindOfClass:[TLSwipeForOptionsCell class]]) 145 | [subview setUserInteractionEnabled:YES]; 146 | } 147 | } 148 | } 149 | 150 | - (void)cellDidSelectDelete:(TLSwipeForOptionsCell *)cell { 151 | NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; 152 | 153 | [_objects removeObjectAtIndex:indexPath.row]; 154 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 155 | } 156 | 157 | - (void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell { 158 | self.mostRecentlySelectedMoreCell = cell; 159 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Flag", @"Mark as Unread", @"Move to Junk", @"Move Messages...", nil]; 160 | [self.delegate presentActionSheet:actionSheet fromViewController:self]; 161 | } 162 | 163 | - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 164 | if (buttonIndex == actionSheet.cancelButtonIndex) { 165 | //nop 166 | } else if (buttonIndex == actionSheet.destructiveButtonIndex) { 167 | NSIndexPath *indexPath = [self.tableView indexPathForCell:self.mostRecentlySelectedMoreCell]; 168 | 169 | [_objects removeObjectAtIndex:indexPath.row]; 170 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 171 | } else { 172 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellShouldHideMenuNotification object:self.tableView]; 173 | } 174 | } 175 | 176 | @end 177 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Other Sources/TLSFOC-Demo-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_6_0 10 | #warning "This project uses features only available in iOS SDK 6.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Other Sources/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TLSFOC-Demo 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | typedef int (*PYStdWriter)(void *, const char *, int); 13 | static PYStdWriter _oldStdWrite; 14 | 15 | int __pyStderrWrite(void *inFD, const char *buffer, int size) { 16 | if (strncmp(buffer, "AssertMacros:", 13) == 0) { 17 | return 0; 18 | } 19 | return _oldStdWrite(inFD, buffer, size); 20 | } 21 | 22 | void __iOS7B5CleanConsoleOutput(void) { 23 | _oldStdWrite = stderr->_write; 24 | stderr->_write = __pyStderrWrite; 25 | } 26 | 27 | int main(int argc, char * argv[]) { 28 | __iOS7B5CleanConsoleOutput(); 29 | @autoreleasepool { 30 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Resources/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 | } -------------------------------------------------------------------------------- /TLSFOC-Demo/Resources/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 | } -------------------------------------------------------------------------------- /TLSFOC-Demo/Resources/MainStoryboard.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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Resources/TLSFOC-Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | TLSFOC 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.teehanlax.${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 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Tests/TLSFOC-DemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.teehanlax.${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 | -------------------------------------------------------------------------------- /TLSFOC-Demo/Tests/TLSFOC_DemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLSFOC_DemoTests.m 3 | // TLSFOC-DemoTests 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TLSFOC_DemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TLSFOC_DemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Set-up code here. 21 | } 22 | 23 | - (void)tearDown { 24 | // Tear-down code here. 25 | 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample { 30 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /TLSwipeForOptionsCell/TLOverlayView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLOverlayView.h 3 | // https://github.com/daria-kopaliani/DAContextMenuTableViewController 4 | // 5 | // Created by Daria Kopaliani on 7/25/13. 6 | // Copyright (c) 2013 Daria Kopaliani. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class TLOverlayView; 12 | 13 | ///---------------- 14 | /// @name Delegate 15 | ///---------------- 16 | 17 | /** 18 | The delegate of a `TLOverlayView` object must adopt the `TLOverlayViewDelegate` protocol. 19 | */ 20 | @protocol TLOverlayViewDelegate 21 | 22 | /** 23 | Asks the delegate for the view that should receive the touch `point`. 24 | 25 | @param view The overlay view that received the touch. 26 | @param point A point specified in the receiver’s local coordinate system (bounds). 27 | @param event The event that warranted a call to this method. If you are calling this method from outside your event-handling code, you may specify `nil`. 28 | */ 29 | - (UIView *)overlayView:(TLOverlayView *)view didHitTest:(CGPoint)point withEvent:(UIEvent *)event; 30 | 31 | @end 32 | 33 | ///------------- 34 | /// @name Class 35 | ///------------- 36 | 37 | /** 38 | The `TLOverlayView` class defines a rectangular area on the screen whose touches should be received from. 39 | */ 40 | @interface TLOverlayView : UIView 41 | 42 | ///------------------ 43 | /// @name Properties 44 | ///------------------ 45 | 46 | /** 47 | The object that acts as the delegate of the receiving overlay view. 48 | 49 | @discussion The delegate must adopt the `TLOverlayViewDelegate` protocol. 50 | */ 51 | @property (weak, nonatomic) id delegate; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /TLSwipeForOptionsCell/TLOverlayView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLOverlayView.m 3 | // https://github.com/daria-kopaliani/DAContextMenuTableViewController 4 | // 5 | // Created by Daria Kopaliani on 7/25/13. 6 | // Copyright (c) 2013 Daria Kopaliani. All rights reserved. 7 | // 8 | 9 | #import "TLOverlayView.h" 10 | 11 | @implementation TLOverlayView 12 | 13 | - (id)initWithFrame:(CGRect)frame { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | self.backgroundColor = [UIColor clearColor]; 17 | } 18 | return self; 19 | } 20 | 21 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 22 | return [self.delegate overlayView:self didHitTest:point withEvent:event]; 23 | } 24 | 25 | @end -------------------------------------------------------------------------------- /TLSwipeForOptionsCell/TLSwipeForOptionsCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLSwipeForOptionsCell.h 3 | // TLSwipeForOptionsCell 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class TLSwipeForOptionsCell; 12 | 13 | ///---------------- 14 | /// @name Delegate 15 | ///---------------- 16 | 17 | /** 18 | The delegate of a `TLSwipeForOptionsCell` object must adopt the `TLSwipeForOptionsCellDelegate` protocol. 19 | */ 20 | @protocol TLSwipeForOptionsCellDelegate 21 | 22 | /** 23 | Tells the delegate that the specified cell’s menu is now shown or hidden. 24 | 25 | @param cell The cell whose menu was shown or hidden. 26 | @param isShowingMenu `YES` if the menu was shown; otherwise, `NO`. 27 | */ 28 | - (void)cell:(TLSwipeForOptionsCell *)cell didShowMenu:(BOOL)isShowingMenu; 29 | 30 | /** 31 | Tells the delegate that the specified cell’s “Delete” button is pressed. 32 | 33 | @param cell The cell whose “Delete” button was pressed. 34 | */ 35 | - (void)cellDidSelectDelete:(TLSwipeForOptionsCell *)cell; 36 | 37 | /** 38 | Tells the delegate that the specified cell’s “More” button is pressed. 39 | 40 | @param cell The cell whose “More” button was pressed. 41 | */ 42 | - (void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell; 43 | 44 | @end 45 | 46 | /** 47 | Notifies cells that their menus should be hidden. Upon hiding its menu, a cell will call its delegate’s `cell:didShowMenu:` method. 48 | 49 | @see cell:didShowMenu: 50 | */ 51 | extern NSString *const TLSwipeForOptionsCellShouldHideMenuNotification; 52 | 53 | ///------------- 54 | /// @name Class 55 | ///------------- 56 | 57 | /** 58 | A reproduction of the iOS 7 Mail app’s swipe-to-reveal options. 59 | */ 60 | @interface TLSwipeForOptionsCell : UITableViewCell 61 | 62 | ///------------------ 63 | /// @name Properties 64 | ///------------------ 65 | 66 | /** 67 | The object that acts as the delegate of the receiving cell. 68 | 69 | @discussion The delegate must adopt the `TLSwipeForOptionsCellDelegate` protocol. 70 | */ 71 | @property (nonatomic, weak) id delegate; 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /TLSwipeForOptionsCell/TLSwipeForOptionsCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLSwipeForOptionsCell.m 3 | // TLSwipeForOptionsCell 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLSwipeForOptionsCell.h" 10 | 11 | NSString *const TLSwipeForOptionsCellShouldHideMenuNotification = @"TLSwipeForOptionsCellShouldHideMenuNotification"; 12 | 13 | #define kCatchWidth 148.0f 14 | 15 | @interface TLSwipeForOptionsCell () 16 | 17 | @property (nonatomic, weak) UIScrollView *scrollView; 18 | 19 | @property (nonatomic, weak) UIView *scrollViewContentView; //The cell content (like the label) goes in this view. 20 | @property (nonatomic, weak) UIView *scrollViewButtonView; //Contains our two buttons 21 | 22 | @property (nonatomic, weak) UILabel *scrollViewLabel; 23 | 24 | @property (nonatomic, assign) BOOL isShowingMenu; 25 | 26 | @end 27 | 28 | @implementation TLSwipeForOptionsCell 29 | 30 | - (void)awakeFromNib { 31 | [super awakeFromNib]; 32 | [self setup]; 33 | } 34 | 35 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 36 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 37 | if (self) { 38 | [self setup]; 39 | } 40 | return self; 41 | } 42 | 43 | - (void)setup { 44 | // Set up our contentView hierarchy 45 | 46 | self.isShowingMenu = NO; 47 | 48 | UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; 49 | scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) + kCatchWidth, CGRectGetHeight(self.bounds)); 50 | scrollView.delegate = self; 51 | scrollView.showsHorizontalScrollIndicator = NO; 52 | 53 | [self.contentView addSubview:scrollView]; 54 | self.scrollView = scrollView; 55 | 56 | UIView *scrollViewButtonView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds) - kCatchWidth, 0.0f, kCatchWidth, CGRectGetHeight(self.bounds))]; 57 | self.scrollViewButtonView = scrollViewButtonView; 58 | [self.scrollView addSubview:scrollViewButtonView]; 59 | 60 | // Set up our two buttons 61 | UIButton *moreButton = [UIButton buttonWithType:UIButtonTypeCustom]; 62 | moreButton.backgroundColor = [UIColor colorWithRed:0.78f green:0.78f blue:0.8f alpha:1.0f]; 63 | moreButton.frame = CGRectMake(0.0f, 0.0f, kCatchWidth / 2.0f, CGRectGetHeight(self.bounds)); 64 | [moreButton setTitle:@"More" forState:UIControlStateNormal]; 65 | [moreButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 66 | [moreButton addTarget:self action:@selector(userPressedMoreButton:) forControlEvents:UIControlEventTouchUpInside]; 67 | [self.scrollViewButtonView addSubview:moreButton]; 68 | 69 | UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; 70 | deleteButton.backgroundColor = [UIColor colorWithRed:1.0f green:0.231f blue:0.188f alpha:1.0f]; 71 | deleteButton.frame = CGRectMake(kCatchWidth / 2.0f, 0.0f, kCatchWidth / 2.0f, CGRectGetHeight(self.bounds)); 72 | [deleteButton setTitle:@"Delete" forState:UIControlStateNormal]; 73 | [deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 74 | [deleteButton addTarget:self action:@selector(userPressedDeleteButton:) forControlEvents:UIControlEventTouchUpInside]; 75 | [self.scrollViewButtonView addSubview:deleteButton]; 76 | 77 | UIView *scrollViewContentView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; 78 | scrollViewContentView.backgroundColor = [UIColor whiteColor]; 79 | [self.scrollView addSubview:scrollViewContentView]; 80 | self.scrollViewContentView = scrollViewContentView; 81 | 82 | UILabel *scrollViewLabel = [[UILabel alloc] initWithFrame:CGRectInset(self.scrollViewContentView.bounds, 10.0f, 0.0f)]; 83 | self.scrollViewLabel = scrollViewLabel; 84 | [self.scrollViewContentView addSubview:scrollViewLabel]; 85 | 86 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hideMenuOptions) name:TLSwipeForOptionsCellShouldHideMenuNotification object:nil]; 87 | } 88 | 89 | - (void)hideMenuOptions { 90 | [self.scrollView setContentOffset:CGPointZero animated:YES]; 91 | } 92 | 93 | #pragma mark - Private Methods 94 | 95 | - (void)userPressedDeleteButton:(id)sender { 96 | [self.delegate cellDidSelectDelete:self]; 97 | [self.scrollView setContentOffset:CGPointZero animated:YES]; 98 | } 99 | 100 | - (void)userPressedMoreButton:(id)sender { 101 | [self.delegate cellDidSelectMore:self]; 102 | } 103 | 104 | #pragma mark - Overridden Methods 105 | 106 | - (void)layoutSubviews { 107 | [super layoutSubviews]; 108 | 109 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) + kCatchWidth, CGRectGetHeight(self.bounds)); 110 | self.scrollView.frame = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 111 | self.scrollViewButtonView.frame = CGRectMake(CGRectGetWidth(self.bounds) - kCatchWidth, 0.0f, kCatchWidth, CGRectGetHeight(self.bounds)); 112 | self.scrollViewContentView.frame = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 113 | } 114 | 115 | - (void)prepareForReuse { 116 | [super prepareForReuse]; 117 | [self.scrollView setContentOffset:CGPointZero animated:NO]; 118 | } 119 | 120 | - (void)setEditing:(BOOL)editing animated:(BOOL)animated { 121 | [super setEditing:editing animated:animated]; 122 | self.scrollView.scrollEnabled = !self.editing; 123 | 124 | // Corrects effect of showing the button labels while selected on editing mode (comment line, build, run, add new items to table, enter edit mode and select an entry) 125 | self.scrollViewButtonView.hidden = editing; 126 | 127 | // NSLog(@"%d", editing); 128 | } 129 | 130 | - (UILabel *)textLabel { 131 | // Kind of a cheat to reduce our external dependencies 132 | return self.scrollViewLabel; 133 | } 134 | 135 | #pragma mark - UIScrollViewDelegate Methods 136 | 137 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 138 | if (scrollView.contentOffset.x > kCatchWidth) { 139 | targetContentOffset->x = kCatchWidth; 140 | } else { 141 | *targetContentOffset = CGPointZero; 142 | 143 | // Need to call this subsequently to remove flickering. Strange. 144 | dispatch_async(dispatch_get_main_queue(), ^{ 145 | [scrollView setContentOffset:CGPointZero animated:YES]; 146 | }); 147 | } 148 | } 149 | 150 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 151 | if (scrollView.contentOffset.x < 0.0f) { 152 | scrollView.contentOffset = CGPointZero; 153 | } 154 | 155 | self.scrollViewButtonView.frame = CGRectMake(scrollView.contentOffset.x + (CGRectGetWidth(self.bounds) - kCatchWidth), 0.0f, kCatchWidth, CGRectGetHeight(self.bounds)); 156 | 157 | if (scrollView.contentOffset.x >= kCatchWidth) { 158 | if (!self.isShowingMenu) { 159 | self.isShowingMenu = YES; 160 | [self.delegate cell:self didShowMenu:self.isShowingMenu]; 161 | } 162 | } else if (scrollView.contentOffset.x == 0.0f) { 163 | if (self.isShowingMenu) { 164 | self.isShowingMenu = NO; 165 | [self.delegate cell:self didShowMenu:self.isShowingMenu]; 166 | } 167 | } 168 | } 169 | 170 | @end 171 | 172 | #undef kCatchWidth 173 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5E13E00417A7056000AD06FC /* TLContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E13E00317A7056000AD06FC /* TLContainerViewController.m */; }; 11 | 5E8B74EB17A808DD00B9187A /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5E8B74EA17A808DD00B9187A /* MainStoryboard.storyboard */; }; 12 | 5EA94CC717A6B60D0038BF1C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EA94CC617A6B60D0038BF1C /* Foundation.framework */; }; 13 | 5EA94CC917A6B60D0038BF1C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EA94CC817A6B60D0038BF1C /* CoreGraphics.framework */; }; 14 | 5EA94CCB17A6B60D0038BF1C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EA94CCA17A6B60D0038BF1C /* UIKit.framework */; }; 15 | 5EA94CD117A6B60D0038BF1C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5EA94CCF17A6B60D0038BF1C /* InfoPlist.strings */; }; 16 | 5EA94CD317A6B60D0038BF1C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EA94CD217A6B60D0038BF1C /* main.m */; }; 17 | 5EA94CD717A6B60D0038BF1C /* TLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EA94CD617A6B60D0038BF1C /* TLAppDelegate.m */; }; 18 | 5EA94CDD17A6B60D0038BF1C /* TLTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EA94CDC17A6B60D0038BF1C /* TLTableViewController.m */; }; 19 | 5EA94CE217A6B60D0038BF1C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5EA94CE117A6B60D0038BF1C /* Images.xcassets */; }; 20 | 5EA94D0017A6C1140038BF1C /* TLSwipeForOptionsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EA94CFF17A6C1140038BF1C /* TLSwipeForOptionsCell.m */; }; 21 | 5EA94D0217A6C3F10038BF1C /* Reveal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EA94D0117A6C3F10038BF1C /* Reveal.framework */; }; 22 | 5EA94D0417A6C3F90038BF1C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EA94D0317A6C3F90038BF1C /* QuartzCore.framework */; }; 23 | 5EA94D0617A6C3FF0038BF1C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EA94D0517A6C3FF0038BF1C /* CFNetwork.framework */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 5E13E00217A7056000AD06FC /* TLContainerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLContainerViewController.h; sourceTree = ""; }; 28 | 5E13E00317A7056000AD06FC /* TLContainerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLContainerViewController.m; sourceTree = ""; }; 29 | 5E8B74EA17A808DD00B9187A /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = ""; }; 30 | 5EA94CC317A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "UITableViewCell-Swipe-for-Options.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 5EA94CC617A6B60D0038BF1C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 32 | 5EA94CC817A6B60D0038BF1C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 33 | 5EA94CCA17A6B60D0038BF1C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 34 | 5EA94CCE17A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "UITableViewCell-Swipe-for-Options-Info.plist"; sourceTree = ""; }; 35 | 5EA94CD017A6B60D0038BF1C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 36 | 5EA94CD217A6B60D0038BF1C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 37 | 5EA94CD417A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITableViewCell-Swipe-for-Options-Prefix.pch"; sourceTree = ""; }; 38 | 5EA94CD517A6B60D0038BF1C /* TLAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TLAppDelegate.h; sourceTree = ""; }; 39 | 5EA94CD617A6B60D0038BF1C /* TLAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TLAppDelegate.m; sourceTree = ""; }; 40 | 5EA94CDB17A6B60D0038BF1C /* TLTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TLTableViewController.h; sourceTree = ""; }; 41 | 5EA94CDC17A6B60D0038BF1C /* TLTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TLTableViewController.m; sourceTree = ""; }; 42 | 5EA94CE117A6B60D0038BF1C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 43 | 5EA94CE817A6B60D0038BF1C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 44 | 5EA94CFE17A6C1140038BF1C /* TLSwipeForOptionsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLSwipeForOptionsCell.h; sourceTree = ""; }; 45 | 5EA94CFF17A6C1140038BF1C /* TLSwipeForOptionsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLSwipeForOptionsCell.m; sourceTree = ""; }; 46 | 5EA94D0117A6C3F10038BF1C /* Reveal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Reveal.framework; sourceTree = ""; }; 47 | 5EA94D0317A6C3F90038BF1C /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 48 | 5EA94D0517A6C3FF0038BF1C /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 49 | /* End PBXFileReference section */ 50 | 51 | /* Begin PBXFrameworksBuildPhase section */ 52 | 5EA94CC017A6B60D0038BF1C /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | 5EA94D0617A6C3FF0038BF1C /* CFNetwork.framework in Frameworks */, 57 | 5EA94D0417A6C3F90038BF1C /* QuartzCore.framework in Frameworks */, 58 | 5EA94CC917A6B60D0038BF1C /* CoreGraphics.framework in Frameworks */, 59 | 5EA94CCB17A6B60D0038BF1C /* UIKit.framework in Frameworks */, 60 | 5EA94CC717A6B60D0038BF1C /* Foundation.framework in Frameworks */, 61 | 5EA94D0217A6C3F10038BF1C /* Reveal.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 5EA94CBA17A6B60D0038BF1C = { 69 | isa = PBXGroup; 70 | children = ( 71 | 5EA94CCC17A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options */, 72 | 5EA94CC517A6B60D0038BF1C /* Frameworks */, 73 | 5EA94CC417A6B60D0038BF1C /* Products */, 74 | ); 75 | sourceTree = ""; 76 | }; 77 | 5EA94CC417A6B60D0038BF1C /* Products */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 5EA94CC317A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options.app */, 81 | ); 82 | name = Products; 83 | sourceTree = ""; 84 | }; 85 | 5EA94CC517A6B60D0038BF1C /* Frameworks */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 5EA94D0517A6C3FF0038BF1C /* CFNetwork.framework */, 89 | 5EA94D0317A6C3F90038BF1C /* QuartzCore.framework */, 90 | 5EA94D0117A6C3F10038BF1C /* Reveal.framework */, 91 | 5EA94CC617A6B60D0038BF1C /* Foundation.framework */, 92 | 5EA94CC817A6B60D0038BF1C /* CoreGraphics.framework */, 93 | 5EA94CCA17A6B60D0038BF1C /* UIKit.framework */, 94 | 5EA94CE817A6B60D0038BF1C /* XCTest.framework */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | 5EA94CCC17A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 5EA94CD517A6B60D0038BF1C /* TLAppDelegate.h */, 103 | 5EA94CD617A6B60D0038BF1C /* TLAppDelegate.m */, 104 | 5E8B74EA17A808DD00B9187A /* MainStoryboard.storyboard */, 105 | 5EA94CDB17A6B60D0038BF1C /* TLTableViewController.h */, 106 | 5EA94CDC17A6B60D0038BF1C /* TLTableViewController.m */, 107 | 5E13E00217A7056000AD06FC /* TLContainerViewController.h */, 108 | 5E13E00317A7056000AD06FC /* TLContainerViewController.m */, 109 | 5EA94CFE17A6C1140038BF1C /* TLSwipeForOptionsCell.h */, 110 | 5EA94CFF17A6C1140038BF1C /* TLSwipeForOptionsCell.m */, 111 | 5EA94CE117A6B60D0038BF1C /* Images.xcassets */, 112 | 5EA94CCD17A6B60D0038BF1C /* Supporting Files */, 113 | ); 114 | path = "UITableViewCell-Swipe-for-Options"; 115 | sourceTree = ""; 116 | }; 117 | 5EA94CCD17A6B60D0038BF1C /* Supporting Files */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 5EA94CCE17A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options-Info.plist */, 121 | 5EA94CCF17A6B60D0038BF1C /* InfoPlist.strings */, 122 | 5EA94CD217A6B60D0038BF1C /* main.m */, 123 | 5EA94CD417A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options-Prefix.pch */, 124 | ); 125 | name = "Supporting Files"; 126 | sourceTree = ""; 127 | }; 128 | /* End PBXGroup section */ 129 | 130 | /* Begin PBXNativeTarget section */ 131 | 5EA94CC217A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options */ = { 132 | isa = PBXNativeTarget; 133 | buildConfigurationList = 5EA94CF817A6B60D0038BF1C /* Build configuration list for PBXNativeTarget "UITableViewCell-Swipe-for-Options" */; 134 | buildPhases = ( 135 | 5EA94CBF17A6B60D0038BF1C /* Sources */, 136 | 5EA94CC017A6B60D0038BF1C /* Frameworks */, 137 | 5EA94CC117A6B60D0038BF1C /* Resources */, 138 | ); 139 | buildRules = ( 140 | ); 141 | dependencies = ( 142 | ); 143 | name = "UITableViewCell-Swipe-for-Options"; 144 | productName = "UITableViewCell-Swipe-for-Options"; 145 | productReference = 5EA94CC317A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options.app */; 146 | productType = "com.apple.product-type.application"; 147 | }; 148 | /* End PBXNativeTarget section */ 149 | 150 | /* Begin PBXProject section */ 151 | 5EA94CBB17A6B60D0038BF1C /* Project object */ = { 152 | isa = PBXProject; 153 | attributes = { 154 | CLASSPREFIX = TL; 155 | LastUpgradeCheck = 0500; 156 | ORGANIZATIONNAME = "Teehan+Lax"; 157 | }; 158 | buildConfigurationList = 5EA94CBE17A6B60D0038BF1C /* Build configuration list for PBXProject "UITableViewCell-Swipe-for-Options" */; 159 | compatibilityVersion = "Xcode 3.2"; 160 | developmentRegion = English; 161 | hasScannedForEncodings = 0; 162 | knownRegions = ( 163 | en, 164 | Base, 165 | ); 166 | mainGroup = 5EA94CBA17A6B60D0038BF1C; 167 | productRefGroup = 5EA94CC417A6B60D0038BF1C /* Products */; 168 | projectDirPath = ""; 169 | projectRoot = ""; 170 | targets = ( 171 | 5EA94CC217A6B60D0038BF1C /* UITableViewCell-Swipe-for-Options */, 172 | ); 173 | }; 174 | /* End PBXProject section */ 175 | 176 | /* Begin PBXResourcesBuildPhase section */ 177 | 5EA94CC117A6B60D0038BF1C /* Resources */ = { 178 | isa = PBXResourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 5EA94CE217A6B60D0038BF1C /* Images.xcassets in Resources */, 182 | 5EA94CD117A6B60D0038BF1C /* InfoPlist.strings in Resources */, 183 | 5E8B74EB17A808DD00B9187A /* MainStoryboard.storyboard in Resources */, 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXResourcesBuildPhase section */ 188 | 189 | /* Begin PBXSourcesBuildPhase section */ 190 | 5EA94CBF17A6B60D0038BF1C /* Sources */ = { 191 | isa = PBXSourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | 5EA94CDD17A6B60D0038BF1C /* TLTableViewController.m in Sources */, 195 | 5EA94CD717A6B60D0038BF1C /* TLAppDelegate.m in Sources */, 196 | 5EA94CD317A6B60D0038BF1C /* main.m in Sources */, 197 | 5E13E00417A7056000AD06FC /* TLContainerViewController.m in Sources */, 198 | 5EA94D0017A6C1140038BF1C /* TLSwipeForOptionsCell.m in Sources */, 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | /* End PBXSourcesBuildPhase section */ 203 | 204 | /* Begin PBXVariantGroup section */ 205 | 5EA94CCF17A6B60D0038BF1C /* InfoPlist.strings */ = { 206 | isa = PBXVariantGroup; 207 | children = ( 208 | 5EA94CD017A6B60D0038BF1C /* en */, 209 | ); 210 | name = InfoPlist.strings; 211 | sourceTree = ""; 212 | }; 213 | /* End PBXVariantGroup section */ 214 | 215 | /* Begin XCBuildConfiguration section */ 216 | 5EA94CF617A6B60D0038BF1C /* Debug */ = { 217 | isa = XCBuildConfiguration; 218 | buildSettings = { 219 | ALWAYS_SEARCH_USER_PATHS = NO; 220 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 221 | CLANG_CXX_LIBRARY = "libc++"; 222 | CLANG_ENABLE_MODULES = YES; 223 | CLANG_ENABLE_OBJC_ARC = YES; 224 | CLANG_WARN_BOOL_CONVERSION = YES; 225 | CLANG_WARN_CONSTANT_CONVERSION = YES; 226 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 227 | CLANG_WARN_EMPTY_BODY = YES; 228 | CLANG_WARN_ENUM_CONVERSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 232 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 233 | COPY_PHASE_STRIP = NO; 234 | GCC_C_LANGUAGE_STANDARD = gnu99; 235 | GCC_DYNAMIC_NO_PIC = NO; 236 | GCC_OPTIMIZATION_LEVEL = 0; 237 | GCC_PREPROCESSOR_DEFINITIONS = ( 238 | "DEBUG=1", 239 | "$(inherited)", 240 | ); 241 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 242 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 243 | GCC_WARN_UNDECLARED_SELECTOR = YES; 244 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 245 | GCC_WARN_UNUSED_FUNCTION = YES; 246 | GCC_WARN_UNUSED_VARIABLE = YES; 247 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 248 | ONLY_ACTIVE_ARCH = YES; 249 | SDKROOT = iphoneos; 250 | }; 251 | name = Debug; 252 | }; 253 | 5EA94CF717A6B60D0038BF1C /* Release */ = { 254 | isa = XCBuildConfiguration; 255 | buildSettings = { 256 | ALWAYS_SEARCH_USER_PATHS = NO; 257 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 258 | CLANG_CXX_LIBRARY = "libc++"; 259 | CLANG_ENABLE_MODULES = YES; 260 | CLANG_ENABLE_OBJC_ARC = YES; 261 | CLANG_WARN_BOOL_CONVERSION = YES; 262 | CLANG_WARN_CONSTANT_CONVERSION = YES; 263 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 264 | CLANG_WARN_EMPTY_BODY = YES; 265 | CLANG_WARN_ENUM_CONVERSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 269 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 270 | COPY_PHASE_STRIP = YES; 271 | ENABLE_NS_ASSERTIONS = NO; 272 | GCC_C_LANGUAGE_STANDARD = gnu99; 273 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 274 | GCC_WARN_UNDECLARED_SELECTOR = YES; 275 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 276 | GCC_WARN_UNUSED_FUNCTION = YES; 277 | GCC_WARN_UNUSED_VARIABLE = YES; 278 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 279 | SDKROOT = iphoneos; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Release; 283 | }; 284 | 5EA94CF917A6B60D0038BF1C /* Debug */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 288 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 289 | FRAMEWORK_SEARCH_PATHS = ( 290 | "$(inherited)", 291 | "$(SRCROOT)", 292 | ); 293 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 294 | GCC_PREFIX_HEADER = "UITableViewCell-Swipe-for-Options/UITableViewCell-Swipe-for-Options-Prefix.pch"; 295 | INFOPLIST_FILE = "UITableViewCell-Swipe-for-Options/UITableViewCell-Swipe-for-Options-Info.plist"; 296 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 297 | OTHER_LDFLAGS = "-ObjC"; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | WRAPPER_EXTENSION = app; 300 | }; 301 | name = Debug; 302 | }; 303 | 5EA94CFA17A6B60D0038BF1C /* Release */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 307 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 308 | FRAMEWORK_SEARCH_PATHS = ( 309 | "$(inherited)", 310 | "$(SRCROOT)", 311 | ); 312 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 313 | GCC_PREFIX_HEADER = "UITableViewCell-Swipe-for-Options/UITableViewCell-Swipe-for-Options-Prefix.pch"; 314 | INFOPLIST_FILE = "UITableViewCell-Swipe-for-Options/UITableViewCell-Swipe-for-Options-Info.plist"; 315 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 316 | OTHER_LDFLAGS = "-ObjC"; 317 | PRODUCT_NAME = "$(TARGET_NAME)"; 318 | WRAPPER_EXTENSION = app; 319 | }; 320 | name = Release; 321 | }; 322 | /* End XCBuildConfiguration section */ 323 | 324 | /* Begin XCConfigurationList section */ 325 | 5EA94CBE17A6B60D0038BF1C /* Build configuration list for PBXProject "UITableViewCell-Swipe-for-Options" */ = { 326 | isa = XCConfigurationList; 327 | buildConfigurations = ( 328 | 5EA94CF617A6B60D0038BF1C /* Debug */, 329 | 5EA94CF717A6B60D0038BF1C /* Release */, 330 | ); 331 | defaultConfigurationIsVisible = 0; 332 | defaultConfigurationName = Release; 333 | }; 334 | 5EA94CF817A6B60D0038BF1C /* Build configuration list for PBXNativeTarget "UITableViewCell-Swipe-for-Options" */ = { 335 | isa = XCConfigurationList; 336 | buildConfigurations = ( 337 | 5EA94CF917A6B60D0038BF1C /* Debug */, 338 | 5EA94CFA17A6B60D0038BF1C /* Release */, 339 | ); 340 | defaultConfigurationIsVisible = 0; 341 | defaultConfigurationName = Release; 342 | }; 343 | /* End XCConfigurationList section */ 344 | }; 345 | rootObject = 5EA94CBB17A6B60D0038BF1C /* Project object */; 346 | } 347 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options.xcodeproj/xcuserdata/ash.xcuserdatad/xcschemes/UITableViewCell-Swipe-for-Options.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 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options.xcodeproj/xcuserdata/ash.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | UITableViewCell-Swipe-for-Options.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5EA94CC217A6B60D0038BF1C 16 | 17 | primary 18 | 19 | 20 | 5EA94CE617A6B60D0038BF1C 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/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 | } -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/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 | } -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/MainStoryboard.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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLAppDelegate.h 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TLAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLAppDelegate.m 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLAppDelegate.h" 10 | 11 | @implementation TLAppDelegate 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 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLContainerViewController.h 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TLContainerViewController : UIViewController 12 | 13 | @property (nonatomic, weak) IBOutlet UIToolbar *toolbar; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLContainerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLContainerViewController.m 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLContainerViewController.h" 10 | 11 | #import "TLTableViewController.h" 12 | 13 | @interface TLContainerViewController () 14 | 15 | @property (nonatomic, weak) TLTableViewController *tableViewController; 16 | 17 | @end 18 | 19 | @implementation TLContainerViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | 25 | self.navigationItem.leftBarButtonItem = self.tableViewController.navigationItem.leftBarButtonItem; 26 | self.navigationItem.rightBarButtonItem = self.tableViewController.navigationItem.rightBarButtonItem; 27 | 28 | self.navigationItem.title = @"Table View"; 29 | 30 | [self setAppropriateToolbarItems]; 31 | } 32 | 33 | -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 34 | if ([segue.identifier isEqualToString:@"embed"]) { 35 | self.tableViewController = segue.destinationViewController; 36 | self.tableViewController.delegate = self; 37 | } 38 | } 39 | 40 | #pragma mark - Private Methods 41 | 42 | // Sets the appropriate UIBarButtonItems for our toolbar depending on the editing property of self.tableViewController. 43 | -(void)setAppropriateToolbarItems { 44 | NSArray *itemsArray; 45 | 46 | if (self.tableViewController.editing) { 47 | itemsArray = @[[[UIBarButtonItem alloc] initWithTitle:@"Trash" style:UIBarButtonItemStylePlain target:self action:@selector(userDidPressTrashButton:)], 48 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 49 | [[UIBarButtonItem alloc] initWithTitle:@"Move" style:UIBarButtonItemStylePlain target:self action:@selector(userDidPressMoveButton:)], 50 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 51 | [[UIBarButtonItem alloc] initWithTitle:@"Mark" style:UIBarButtonItemStylePlain target:self action:@selector(userDidPressMarkButton:)]]; 52 | } 53 | else { 54 | itemsArray = @[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 55 | [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(suerDidPressAddButton:)]]; 56 | } 57 | 58 | [self.toolbar setItems:itemsArray animated:NO]; 59 | } 60 | 61 | #pragma mark - User Interface Methods 62 | 63 | /* 64 | These are all configurable to do whatever you want with them. We only really use the userDidPressTrashButton: method. 65 | */ 66 | 67 | - (void)suerDidPressAddButton:(id)sender { 68 | [self.tableViewController insertNewObject:nil]; 69 | } 70 | 71 | - (void)userDidPressTrashButton:(id)sender { 72 | [self.tableViewController deleteSelectedCells]; 73 | [self.tableViewController setEditing:NO animated:YES]; 74 | } 75 | 76 | - (void)userDidPressMoveButton:(id)sender { 77 | [self.tableViewController setEditing:NO animated:YES]; 78 | } 79 | 80 | - (void)userDidPressMarkButton:(id)sender { 81 | [self.tableViewController setEditing:NO animated:YES]; 82 | } 83 | 84 | #pragma mark - TLTableViewControllerDelegate Methods 85 | 86 | -(void)tableViewController:(TLTableViewController *)viewController didChangeEditing:(BOOL)editing { 87 | [self setAppropriateToolbarItems]; 88 | } 89 | 90 | -(void)presentActionSheet:(UIActionSheet *)actionSheet fromViewController:(TLTableViewController *)viewController { 91 | [actionSheet showFromToolbar:self.toolbar]; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLSwipeForOptionsCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLSwipeForOptionsCell.h 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class TLSwipeForOptionsCell; 12 | 13 | @protocol TLSwipeForOptionsCellDelegate 14 | 15 | -(void)cellDidSelectDelete:(TLSwipeForOptionsCell *)cell; 16 | -(void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell; 17 | 18 | @end 19 | 20 | extern NSString *const TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification; 21 | 22 | @interface TLSwipeForOptionsCell : UITableViewCell 23 | 24 | @property (nonatomic, weak) id delegate; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLSwipeForOptionsCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLSwipeForOptionsCell.m 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLSwipeForOptionsCell.h" 10 | 11 | NSString *const TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification = @"TLSwipeForOptionsCellEnclosingTableViewDidScrollNotification"; 12 | 13 | #define kCatchWidth 180 14 | 15 | @interface TLSwipeForOptionsCell () 16 | 17 | @property (nonatomic, weak) UIScrollView *scrollView; 18 | 19 | @property (nonatomic, weak) UIView *scrollViewContentView; //The cell content (like the label) goes in this view. 20 | @property (nonatomic, weak) UIView *scrollViewButtonView; //Contains our two buttons 21 | 22 | @property (nonatomic, weak) UILabel *scrollViewLabel; 23 | 24 | @end 25 | 26 | @implementation TLSwipeForOptionsCell 27 | 28 | -(void)awakeFromNib { 29 | [super awakeFromNib]; 30 | 31 | [self setup]; 32 | } 33 | 34 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 35 | { 36 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 37 | if (self) { 38 | [self setup]; 39 | } 40 | return self; 41 | } 42 | 43 | -(void)setup { 44 | // Set up our contentView hierarchy 45 | 46 | UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; 47 | scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) + kCatchWidth, CGRectGetHeight(self.bounds)); 48 | scrollView.delegate = self; 49 | scrollView.showsHorizontalScrollIndicator = NO; 50 | 51 | [self.contentView addSubview:scrollView]; 52 | self.scrollView = scrollView; 53 | 54 | UIView *scrollViewButtonView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds) - kCatchWidth, 0, kCatchWidth, CGRectGetHeight(self.bounds))]; 55 | self.scrollViewButtonView = scrollViewButtonView; 56 | [self.scrollView addSubview:scrollViewButtonView]; 57 | 58 | // Set up our two buttons 59 | UIButton *moreButton = [UIButton buttonWithType:UIButtonTypeCustom]; 60 | moreButton.backgroundColor = [UIColor colorWithRed:0.78f green:0.78f blue:0.8f alpha:1.0f]; 61 | moreButton.frame = CGRectMake(0, 0, kCatchWidth / 2.0f, CGRectGetHeight(self.bounds)); 62 | [moreButton setTitle:@"More" forState:UIControlStateNormal]; 63 | [moreButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 64 | [moreButton addTarget:self action:@selector(userPressedMoreButton:) forControlEvents:UIControlEventTouchUpInside]; 65 | [self.scrollViewButtonView addSubview:moreButton]; 66 | 67 | UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; 68 | deleteButton.backgroundColor = [UIColor colorWithRed:1.0f green:0.231f blue:0.188f alpha:1.0f]; 69 | deleteButton.frame = CGRectMake(kCatchWidth / 2.0f, 0, kCatchWidth / 2.0f, CGRectGetHeight(self.bounds)); 70 | [deleteButton setTitle:@"Delete" forState:UIControlStateNormal]; 71 | [deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 72 | [deleteButton addTarget:self action:@selector(userPressedDeleteButton:) forControlEvents:UIControlEventTouchUpInside]; 73 | [self.scrollViewButtonView addSubview:deleteButton]; 74 | 75 | UIView *scrollViewContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; 76 | scrollViewContentView.backgroundColor = [UIColor whiteColor]; 77 | [self.scrollView addSubview:scrollViewContentView]; 78 | self.scrollViewContentView = scrollViewContentView; 79 | 80 | UILabel *scrollViewLabel = [[UILabel alloc] initWithFrame:CGRectInset(self.scrollViewContentView.bounds, 10, 0)]; 81 | self.scrollViewLabel = scrollViewLabel; 82 | [self.scrollViewContentView addSubview:scrollViewLabel]; 83 | 84 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enclosingTableViewDidScroll) name:TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification object:nil]; 85 | } 86 | 87 | -(void)enclosingTableViewDidScroll { 88 | [self.scrollView setContentOffset:CGPointZero animated:YES]; 89 | } 90 | 91 | #pragma mark - Private Methods 92 | 93 | -(void)userPressedDeleteButton:(id)sender { 94 | [self.delegate cellDidSelectDelete:self]; 95 | [self.scrollView setContentOffset:CGPointZero animated:YES]; 96 | } 97 | 98 | -(void)userPressedMoreButton:(id)sender { 99 | [self.delegate cellDidSelectMore:self]; 100 | } 101 | 102 | #pragma mark - Overridden Methods 103 | 104 | -(void)layoutSubviews { 105 | [super layoutSubviews]; 106 | 107 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) + kCatchWidth, CGRectGetHeight(self.bounds)); 108 | self.scrollView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 109 | self.scrollViewButtonView.frame = CGRectMake(CGRectGetWidth(self.bounds) - kCatchWidth, 0, kCatchWidth, CGRectGetHeight(self.bounds)); 110 | self.scrollViewContentView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 111 | } 112 | 113 | -(void)prepareForReuse { 114 | [super prepareForReuse]; 115 | 116 | [self.scrollView setContentOffset:CGPointZero animated:NO]; 117 | } 118 | 119 | -(void)setEditing:(BOOL)editing animated:(BOOL)animated { 120 | [super setEditing:editing animated:animated]; 121 | 122 | self.scrollView.scrollEnabled = !self.editing; 123 | 124 | // Corrects effect of showing the button labels while selected on editing mode (comment line, build, run, add new items to table, enter edit mode and select an entry) 125 | self.scrollViewButtonView.hidden = editing; 126 | 127 | NSLog(@"%d", editing); 128 | } 129 | 130 | -(UILabel *)textLabel { 131 | // Kind of a cheat to reduce our external dependencies 132 | return self.scrollViewLabel; 133 | } 134 | 135 | #pragma mark - UIScrollViewDelegate Methods 136 | 137 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 138 | 139 | if (scrollView.contentOffset.x > kCatchWidth) { 140 | targetContentOffset->x = kCatchWidth; 141 | } 142 | else { 143 | *targetContentOffset = CGPointZero; 144 | 145 | // Need to call this subsequently to remove flickering. Strange. 146 | dispatch_async(dispatch_get_main_queue(), ^{ 147 | [scrollView setContentOffset:CGPointZero animated:YES]; 148 | }); 149 | } 150 | } 151 | 152 | -(void)scrollViewDidScroll:(UIScrollView *)scrollView { 153 | if (scrollView.contentOffset.x < 0) { 154 | scrollView.contentOffset = CGPointZero; 155 | } 156 | 157 | self.scrollViewButtonView.frame = CGRectMake(scrollView.contentOffset.x + (CGRectGetWidth(self.bounds) - kCatchWidth), 0.0f, kCatchWidth, CGRectGetHeight(self.bounds)); 158 | } 159 | 160 | @end 161 | 162 | #undef kCatchWidth 163 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLMasterViewController.h 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class TLTableViewController; 12 | 13 | @protocol TLTableViewControllerDelegate 14 | 15 | -(void)tableViewController:(TLTableViewController *)viewController didChangeEditing:(BOOL)editing; 16 | -(void)presentActionSheet:(UIActionSheet *)actionSheet fromViewController:(TLTableViewController *)viewController; 17 | 18 | @end 19 | 20 | @interface TLTableViewController : UITableViewController 21 | 22 | @property (nonatomic, weak) id delegate; 23 | 24 | - (void)insertNewObject:(id)sender; 25 | - (void)deleteSelectedCells; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/TLTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLMasterViewController.m 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import "TLTableViewController.h" 10 | 11 | #import "TLSwipeForOptionsCell.h" 12 | #import "TLContainerViewController.h" 13 | 14 | @interface TLTableViewController () { 15 | NSMutableArray *_objects; 16 | } 17 | 18 | // We need to keep track of the most recently selected cell for the action sheet. 19 | @property (nonatomic, weak) UITableViewCell *mostRecentlySelectedMoreCell; 20 | 21 | @end 22 | 23 | @implementation TLTableViewController 24 | 25 | - (void)viewDidLoad 26 | { 27 | [super viewDidLoad]; 28 | self.navigationItem.rightBarButtonItem = self.editButtonItem; 29 | 30 | self.tableView.allowsSelectionDuringEditing = YES; 31 | self.tableView.allowsMultipleSelectionDuringEditing = YES; 32 | } 33 | 34 | -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 35 | [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 36 | 37 | // Need to do this to keep the view in a consistent state (layoutSubviews in the cell expects itself to be "closed") 38 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification object:self.tableView]; 39 | } 40 | 41 | #pragma mark - Public Methods 42 | 43 | // Method to delete the cells that are currently selected. 44 | - (void)deleteSelectedCells { 45 | NSArray *indexPathsOfSelectedCells = [self.tableView indexPathsForSelectedRows]; 46 | 47 | // MUST be enumerated in reverse order otherwise the _objects indices become invalid. 48 | [indexPathsOfSelectedCells enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSIndexPath *obj, NSUInteger idx, BOOL *stop) { 49 | [_objects removeObjectAtIndex:obj.row]; 50 | }]; 51 | 52 | [self.tableView deleteRowsAtIndexPaths:indexPathsOfSelectedCells withRowAnimation:UITableViewRowAnimationAutomatic]; 53 | } 54 | 55 | // Inserts a new object into the _objects array. 56 | - (void)insertNewObject:(id)sender 57 | { 58 | if (!_objects) { 59 | _objects = [[NSMutableArray alloc] init]; 60 | } 61 | [_objects insertObject:[NSDate date] atIndex:0]; 62 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 63 | [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 64 | 65 | // Need to call this whenever we scroll our table view programmatically 66 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification object:self.tableView]; 67 | } 68 | 69 | #pragma mark - Table View 70 | 71 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 72 | { 73 | return _objects.count; 74 | } 75 | 76 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 77 | { 78 | TLSwipeForOptionsCell *cell = (TLSwipeForOptionsCell *)[tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 79 | 80 | NSDate *object = _objects[indexPath.row]; 81 | cell.textLabel.text = [object description]; 82 | cell.delegate = self; 83 | 84 | return cell; 85 | } 86 | 87 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 88 | { 89 | // Return NO if you do not want the specified item to be editable. 90 | return YES; 91 | } 92 | 93 | - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 94 | return UITableViewCellEditingStyleNone; 95 | } 96 | 97 | -(void)setEditing:(BOOL)editing animated:(BOOL)animated { 98 | [super setEditing:editing animated:animated]; 99 | 100 | [self.delegate tableViewController:self didChangeEditing:editing]; 101 | } 102 | 103 | #pragma UIScrollViewDelegate Methods 104 | 105 | -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 106 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification object:scrollView]; 107 | } 108 | 109 | #pragma mark - TLSwipeForOptionsCellDelegate Methods 110 | 111 | -(void)cellDidSelectDelete:(TLSwipeForOptionsCell *)cell { 112 | NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; 113 | 114 | [_objects removeObjectAtIndex:indexPath.row]; 115 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 116 | } 117 | 118 | -(void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell { 119 | self.mostRecentlySelectedMoreCell = cell; 120 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Flag", @"Mark as Unread", @"Move to Junk", @"Move Messages...", nil]; 121 | [self.delegate presentActionSheet:actionSheet fromViewController:self]; 122 | } 123 | 124 | - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 125 | if (buttonIndex == actionSheet.cancelButtonIndex) { 126 | //nop 127 | } 128 | else if (buttonIndex == actionSheet.destructiveButtonIndex) { 129 | NSIndexPath *indexPath = [self.tableView indexPathForCell:self.mostRecentlySelectedMoreCell]; 130 | 131 | [_objects removeObjectAtIndex:indexPath.row]; 132 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 133 | } 134 | else { 135 | [[NSNotificationCenter defaultCenter] postNotificationName:TLSwipeForOptionsCellEnclosingTableViewDidBeginScrollingNotification object:self.tableView]; 136 | } 137 | } 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/UITableViewCell-Swipe-for-Options-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.teehanlax.${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 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/UITableViewCell-Swipe-for-Options-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 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /UITableViewCell-Swipe-for-Options/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // UITableViewCell-Swipe-for-Options 4 | // 5 | // Created by Ash Furrow on 2013-07-29. 6 | // Copyright (c) 2013 Teehan+Lax. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "TLAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([TLAppDelegate class])); 17 | } 18 | } 19 | --------------------------------------------------------------------------------