├── Pod ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── AFDynamicTableHelper.h │ └── AFDynamicTableHelper.m ├── Example ├── Tests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Tests-Prefix.pch │ ├── Tests-Info.plist │ └── Tests.m ├── AFDynamicTableHelper │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── main.m │ ├── AFDynamicTableHelper-Prefix.pch │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── SimpleListController.h │ ├── AFAppDelegate.h │ ├── MyDynamicTableViewCell.h │ ├── MyDynamicTableViewCell.m │ ├── AFDynamicTableHelper-Info.plist │ ├── AFAppDelegate.m │ ├── SimpleListController.m │ └── Base.lproj │ │ └── Main.storyboard ├── AFDynamicTableHelper.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── AFDynamicTableHelper.xcscheme │ └── project.pbxproj ├── Podfile ├── Podfile.lock └── AFDynamicTableHelper.xcworkspace │ └── contents.xcworkspacedata ├── .gitignore ├── LICENSE ├── AFDynamicTableHelper.podspec └── README.md /Pod/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every test case source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | 9 | 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | 3 | target 'AFDynamicTableHelper', :exclusive => true do 4 | pod "AFDynamicTableHelper", :path => "../" 5 | end 6 | 7 | target 'Tests', :exclusive => true do 8 | pod "AFDynamicTableHelper", :path => "../" 9 | 10 | 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFDynamicTableHelper (0.1.0) 3 | 4 | DEPENDENCIES: 5 | - AFDynamicTableHelper (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | AFDynamicTableHelper: 9 | :path: ../ 10 | 11 | SPEC CHECKSUMS: 12 | AFDynamicTableHelper: f8c8e7d2081c92bb39a17444084276627f9bb660 13 | 14 | COCOAPODS: 0.34.2 15 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AFDynamicTableHelper 4 | // 5 | // Created by Oz on 10/16/2014. 6 | // Copyright (c) 2014 Oz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AFAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AFAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/AFDynamicTableHelper-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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # We recommend against adding the Pods directory to your .gitignore. However 26 | # you should judge for yourself, the pros and cons are mentioned at: 27 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 28 | # 29 | # Note: if you ignore the Pods directory, make sure to uncomment 30 | # `pod install` in .travis.yml 31 | # 32 | Pods/ 33 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.demo.${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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 appFigures Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/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 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /AFDynamicTableHelper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "AFDynamicTableHelper" 3 | s.version = "0.1.0" 4 | s.summary = "Create dynamic height table cells with auto layout in iOS >= 7.0." 5 | s.description = <<-DESC 6 | Are you building an app that targets iOS >= 7.0 and need to create table views with dynamic cell heights? This little helper takes care of all the quirks you need to do it right. On iOS 8.0 it takes advantage of the new auto-sizing capabilities automatically. 7 | DESC 8 | s.homepage = "https://github.com/appFigures/AFDynamicTableHelper" 9 | s.license = 'MIT' 10 | s.author = { "Oz" => "oz" } 11 | s.source = { :git => "https://github.com/appFigures/AFDynamicTableHelper.git", :tag => s.version.to_s } 12 | s.social_media_url = 'https://twitter.com/appFigures' 13 | 14 | s.platform = :ios, '7.0' 15 | s.requires_arc = true 16 | 17 | s.source_files = 'Pod/Classes' 18 | s.resource_bundles = { 19 | 'AFDynamicTableHelper' => ['Pod/Assets/*.png'] 20 | } 21 | 22 | s.public_header_files = 'Pod/Classes/**/*.h' 23 | s.frameworks = 'UIKit' 24 | end 25 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/SimpleListController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | @interface SimpleListController : UITableViewController 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/AFAppDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | @interface AFAppDelegate : UIResponder 24 | 25 | @property (strong, nonatomic) UIWindow *window; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/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 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/MyDynamicTableViewCell.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | @interface MyDynamicTableViewCell : UITableViewCell 24 | 25 | @property (weak, nonatomic) IBOutlet UILabel *headerLabel; 26 | @property (weak, nonatomic) IBOutlet UILabel *bodyLabel; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/MyDynamicTableViewCell.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "MyDynamicTableViewCell.h" 22 | 23 | @implementation MyDynamicTableViewCell 24 | 25 | - (void)awakeFromNib { 26 | self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/AFDynamicTableHelper-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIMainStoryboardFile~ipad 30 | Main_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeRight 39 | UIInterfaceOrientationLandscapeLeft 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Pod/Classes/AFDynamicTableHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | @import UIKit; 22 | 23 | @protocol AFDynamicTableHelperDelegate; 24 | 25 | /* 26 | Helps to compute the heights of rows for dynamic table cells that use Auto Layout for iOS 7.x 27 | If you only support 8.0+, you don't need this. 28 | 29 | For iOS >= 8.0, uses the native implementation. 30 | For iOS 7.x uses the method described in [1] with some tweaks. 31 | 32 | [1] http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights 33 | */ 34 | @interface AFDynamicTableHelper : NSObject 35 | 36 | @property (nonatomic, weak) id delegate; 37 | 38 | /// If all the identifiers are the same, set this. 39 | /// Otherwise use the delegate. 40 | @property (nonatomic, copy) NSString *reusableCellIdentifier; 41 | 42 | /// Call these methods in your table view delegate / data source 43 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 44 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 45 | 46 | // Call these when your content changes 47 | - (void)invalidateCellHeightAtIndexPath:(NSIndexPath *)indexPath; 48 | - (void)invalidateAllCellHeights; 49 | 50 | @end 51 | 52 | @protocol AFDynamicTableHelperDelegate 53 | @optional 54 | 55 | - (NSString *)dynamicTableHelper:(AFDynamicTableHelper *)tableHelper 56 | reusableCellIdentifierForRowAtIndexPath:(NSIndexPath *)indexPath 57 | tableView:(UITableView *)tableView; 58 | 59 | - (void)dynamicTableHelper:(AFDynamicTableHelper *)tableHelper 60 | prepareCell:(UITableViewCell *)cell 61 | atIndexPath:(NSIndexPath *)indexPath 62 | tableView:(UITableView *)tableView 63 | offscreen:(BOOL)offscreen; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/AFAppDelegate.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "AFAppDelegate.h" 22 | 23 | @implementation AFAppDelegate 24 | 25 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 26 | { 27 | // Override point for customization after application launch. 28 | return YES; 29 | } 30 | 31 | - (void)applicationWillResignActive:(UIApplication *)application 32 | { 33 | // 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. 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidEnterBackground:(UIApplication *)application 38 | { 39 | // 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. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | - (void)applicationWillEnterForeground:(UIApplication *)application 44 | { 45 | // 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. 46 | } 47 | 48 | - (void)applicationDidBecomeActive:(UIApplication *)application 49 | { 50 | // 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. 51 | } 52 | 53 | - (void)applicationWillTerminate:(UIApplication *)application 54 | { 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper.xcodeproj/xcshareddata/xcschemes/AFDynamicTableHelper.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AFDynamicTableHelper 2 | 3 | Create dynamic height table cells with auto layout in iOS >= 7.0. 4 | 5 | Are you building an app that targets iOS >= 7.0 and need to create table views with dynamic cell heights? This little helper takes care of all the quirks you need to do it right. On iOS 8.0 it takes advantage of the new auto-sizing capabilities automatically. 6 | 7 | If you're only targeting 8.0+ you don't need this class. Just use the built in `UITableViewAutomaticDimension`. 8 | 9 | Still here? Read on: 10 | 11 | If you're unfamilar with the quirks involved in implementing dynamic height table views for iOS 7 I highly recommend reading [this stackoverflow question](http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights). A lot of the code for this class is based on that question. 12 | 13 | ## Usage 14 | 15 | This utility is a simple `NSObject` that provides you with concrete implementations for the deceivingly-non-trivial-to-implement: 16 | 17 | tableView:heightForRowAtIndexPath: 18 | 19 | and 20 | 21 | tableView:cellForRowAtIndexPath: 22 | 23 | A simple use-case looks something like this: 24 | 25 | @implementation MyTableViewController 26 | ... 27 | - (void)awakeFromNib { 28 | self.tableHelper = [[AFDynamicTableHelper alloc] init]; 29 | self.tableHelper.delegate = self; 30 | self.tableHelper.reusableCellIdentifier = @"myCell"; 31 | } 32 | 33 | /* ... the usual tableView delegate methods... */ 34 | 35 | // Just forward these methods over to the dynamic table helper and get on with your day. 36 | 37 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 38 | return [self.tableHelper tableView:tableView cellForRowAtIndexPath:indexPath]; 39 | } 40 | 41 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 42 | return [self.tableHelper tableView:tableView heightForRowAtIndexPath:indexPath]; 43 | } 44 | 45 | Check out a complete example in the [demo project](https://github.com/appfigures/AFDynamicTableHelper/blob/master/Example/AFDynamicTableHelper/SimpleListController.m). 46 | 47 | ### Customizing your cells 48 | 49 | In order to do its magic this class needs to manage the way table cells are created and populated. The only thing it asks is that instead of setting up your cell in the usual `tableView:cellForRowAtIndexPath:` you implement the following delegate method: 50 | 51 | - (void)dynamicTableHelper:(AFDynamicTableHelper *)tableHelper 52 | prepareCell:(UITableViewCell *)cell 53 | atIndexPath:(NSIndexPath *)indexPath 54 | tableView:(UITableView *)tableView 55 | offscreen:(BOOL)offscreen 56 | { 57 | // `cell` is created for you based on 58 | // tableHelper.reusableCellIdentifier. You just 59 | // need to populate it. 60 | 61 | // `offscreen` specifies if this cell will be used solely for height 62 | // measurements purposes so you can avoid doing 63 | // any expensive setup steps that don't affect the 64 | // cell's height. 65 | 66 | // the `offscreen` argument is only here for optimization purposes 67 | // and can be safely ignored if you don't want to deal 68 | // with it. 69 | } 70 | 71 | ### What happens on iOS >= 8.0? 72 | 73 | When this class detects iOS >= 8.0 it does about 95% less work and just returns `UITableViewAutomaticDimension` when asked for a cell's height. The key thing is that your code doesn't need to change depending on the version of iOS. That logic is taken care of behind the scenes. 74 | 75 | ### What if I use multiple cell prototypes? 76 | 77 | Just implement the delegate method `dynamicTableHelper:reusableCellIdentifierForRowAtIndexPath:tableView:` 78 | 79 | ## Installation 80 | 81 | AFDynamicTableHelper is available through [CocoaPods](http://cocoapods.org). To install 82 | it, simply add the following line to your Podfile: 83 | 84 | pod "AFDynamicTableHelper" 85 | 86 | ## Author 87 | 88 | Oz Michaeli from appFigures 89 | 90 | ## License 91 | 92 | AFDynamicTableHelper is available under the MIT license. See the LICENSE file for more info. 93 | 94 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/SimpleListController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "SimpleListController.h" 22 | #import 23 | #import "MyDynamicTableViewCell.h" 24 | 25 | @interface SimpleListController () 26 | 27 | @property (nonatomic, strong) AFDynamicTableHelper *tableHelper; 28 | @property (nonatomic, strong) NSArray *data; 29 | 30 | @end 31 | 32 | @implementation SimpleListController 33 | 34 | - (void)awakeFromNib { 35 | self.tableHelper.reusableCellIdentifier = @"myDynamicCell"; 36 | } 37 | 38 | // Lazy properties 39 | - (AFDynamicTableHelper *)tableHelper { 40 | if (!_tableHelper) { 41 | _tableHelper = [[AFDynamicTableHelper alloc] init]; 42 | _tableHelper.delegate = self; 43 | } 44 | return _tableHelper; 45 | } 46 | 47 | - (NSArray *)data { 48 | if (!_data) { 49 | int num = 30; 50 | NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:num]; 51 | 52 | for (int i = 0; i < num; ++i) { 53 | int numLetters = arc4random() % 100 + 20; 54 | 55 | NSMutableString *bodyString = [[NSMutableString alloc] initWithCapacity:numLetters]; 56 | 57 | for (int j = 0; j < numLetters; ++j) { 58 | [bodyString appendString:@"A"]; 59 | } 60 | 61 | [array addObject:@{ 62 | @"title": [NSString stringWithFormat:@"This one has %i letters", numLetters], 63 | @"body": [bodyString copy] 64 | }]; 65 | } 66 | 67 | _data = [array copy]; 68 | } 69 | return _data; 70 | } 71 | 72 | - (void)viewDidLayoutSubviews { 73 | [super viewDidLayoutSubviews]; 74 | 75 | [_tableHelper invalidateAllCellHeights]; 76 | } 77 | 78 | #pragma mark - Table view data source 79 | 80 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 81 | return 1; 82 | } 83 | 84 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 85 | return self.data.count; 86 | } 87 | 88 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 89 | return [self.tableHelper tableView:tableView cellForRowAtIndexPath:indexPath]; 90 | } 91 | 92 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 93 | return [self.tableHelper tableView:tableView heightForRowAtIndexPath:indexPath]; 94 | } 95 | 96 | #pragma mark - AFDynamicTableHelper delegate 97 | 98 | - (void)dynamicTableHelper:(AFDynamicTableHelper *)tableHelper prepareCell:(UITableViewCell *)_cell atIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView offscreen:(BOOL)offscreen { 99 | MyDynamicTableViewCell *cell = (MyDynamicTableViewCell *)_cell; 100 | NSDictionary *datum = self.data[indexPath.row]; 101 | 102 | cell.headerLabel.text = datum[@"title"]; 103 | cell.bodyLabel.text = datum[@"body"]; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 28 | 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 | -------------------------------------------------------------------------------- /Pod/Classes/AFDynamicTableHelper.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 appFigures Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "AFDynamicTableHelper.h" 22 | 23 | // Tried to use the raw index path as 24 | // the dictionary key, but it didn't seem to work correctly. 25 | // Also read that it's slow: http://corecocoa.wordpress.com/2014/01/14/any-thing-can-be-a-dictionary-key-yes-but-with-a-price/ 26 | #define _indexPathString(_ip_) [NSString stringWithFormat:@"%li_%li", (long)_ip_.section, (long)_ip_.row] 27 | 28 | static BOOL isNativeSupportAvailable = NO; 29 | 30 | @interface AFDynamicTableHelper() 31 | { 32 | BOOL _delegateImpsReusableCellId; 33 | BOOL _delegateImpsPrepareCell; 34 | } 35 | 36 | // These will never invalidate. If your prototype cells change 37 | // (very unlikely) just make a new instance of this class. 38 | @property (nonatomic, strong) NSMutableDictionary *offscreenCells; 39 | @property (nonatomic, strong) NSMutableDictionary *offscreenCellsConstraints; 40 | // This little cache gives a great speed boost. 41 | @property (nonatomic, strong) NSMutableDictionary *cellHeights; 42 | 43 | @end 44 | 45 | @implementation AFDynamicTableHelper 46 | 47 | + (void)initialize { 48 | // Couldn't find a nicer way to detect availability. 49 | isNativeSupportAvailable = ([[[UIDevice currentDevice] systemVersion] compare:@"8.0" options:NSNumericSearch] != NSOrderedAscending); 50 | } 51 | 52 | - (id)init { 53 | self = [super init]; 54 | if (self) { 55 | if (!isNativeSupportAvailable) { 56 | _offscreenCells = [[NSMutableDictionary alloc] init]; 57 | _offscreenCellsConstraints = [[NSMutableDictionary alloc] init]; 58 | _cellHeights = [[NSMutableDictionary alloc] init]; 59 | } 60 | } 61 | return self; 62 | } 63 | 64 | - (void)invalidateCellHeightAtIndexPath:(NSIndexPath *)indexPath { 65 | if (isNativeSupportAvailable) { 66 | return; 67 | } 68 | 69 | if (indexPath) { 70 | NSString *indexPathString = _indexPathString(indexPath); 71 | [_cellHeights removeObjectForKey:indexPathString]; 72 | } 73 | } 74 | 75 | - (void)invalidateAllCellHeights { 76 | if (isNativeSupportAvailable) { 77 | return; 78 | } 79 | 80 | [_cellHeights removeAllObjects]; 81 | } 82 | 83 | #pragma mark - Properties 84 | 85 | - (void)setDelegate:(id)delegate { 86 | if (delegate == _delegate) return; 87 | 88 | _delegate = delegate; 89 | 90 | // Let's cache this delegate's capabilities to 91 | // avoid calling respondsToSelector: t0o much. 92 | _delegateImpsReusableCellId = [delegate respondsToSelector:@selector(dynamicTableHelper:reusableCellIdentifierForRowAtIndexPath:tableView:)]; 93 | _delegateImpsPrepareCell = [delegate respondsToSelector:@selector(dynamicTableHelper:prepareCell:atIndexPath:tableView:offscreen:)]; 94 | } 95 | 96 | #pragma mark - Private 97 | 98 | - (NSString *)_reusableCellIdWithTable:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath { 99 | if (_delegateImpsReusableCellId) { 100 | return [_delegate dynamicTableHelper:self reusableCellIdentifierForRowAtIndexPath:indexPath tableView:tableView]; 101 | } 102 | 103 | return _reusableCellIdentifier; 104 | } 105 | 106 | #pragma mark - Main 107 | 108 | // Since these methods are called a lot, they are tuned for performance 109 | 110 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 111 | if (isNativeSupportAvailable) { 112 | return UITableViewAutomaticDimension; 113 | } 114 | 115 | NSMutableDictionary *cellHeights = _cellHeights; 116 | 117 | NSString *indexPathString = _indexPathString(indexPath); 118 | NSNumber *cachedHeight = [cellHeights objectForKey:indexPathString]; 119 | 120 | if (cachedHeight) { 121 | return (CGFloat)[cachedHeight floatValue]; 122 | } 123 | 124 | NSString *reusableCellId = [self _reusableCellIdWithTable:tableView indexPath:indexPath]; 125 | 126 | NSAssert(reusableCellId, @"No valid reusableCellIndentifier provided for cell at index path %@", indexPath); 127 | 128 | NSMutableDictionary *offscreenCells = _offscreenCells; 129 | 130 | UITableViewCell *cell = [offscreenCells objectForKey:reusableCellId]; 131 | if (!cell) { 132 | cell = [tableView dequeueReusableCellWithIdentifier:reusableCellId]; 133 | 134 | NSAssert(cell, @"Couldn't dequeue cell from table with reusableIdentifier '%@'", reusableCellId); 135 | 136 | [offscreenCells setObject:cell forKey:reusableCellId]; 137 | } 138 | 139 | // Get the cell's constraint 140 | NSMutableDictionary *offscreenCellsConstraints = _offscreenCellsConstraints; 141 | NSLayoutConstraint *widthConstraint = [offscreenCellsConstraints objectForKey:reusableCellId]; 142 | if (!widthConstraint) { 143 | widthConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView 144 | attribute:NSLayoutAttributeWidth 145 | relatedBy:NSLayoutRelationEqual 146 | toItem:nil 147 | attribute:NSLayoutAttributeNotAnAttribute 148 | multiplier:1.0 149 | constant:0.0]; 150 | 151 | [_offscreenCellsConstraints setObject:widthConstraint forKey:reusableCellId]; 152 | } 153 | 154 | if (_delegateImpsPrepareCell) { 155 | [_delegate dynamicTableHelper:self prepareCell:cell atIndexPath:indexPath tableView:tableView offscreen:YES]; 156 | } 157 | 158 | // Set the width of the cell to match the width of the table view. This is important so that we'll get the 159 | // correct cell height for different table view widths if the cell's height depends on its width (due to 160 | // multi-line UILabels word wrapping, etc). We don't need to do this above in -[tableView:cellForRowAtIndexPath] 161 | // because it happens automatically when the cell is used in the table view. 162 | // Also note, the final width of the cell may not be the width of the table view in some cases, for example when a 163 | // section index is displayed along the right side of the table view. You must account for the reduced cell width. 164 | widthConstraint.constant = tableView.bounds.size.width; 165 | [cell.contentView addConstraint:widthConstraint]; 166 | 167 | // Make sure the constraints have been set up for this cell, since it may have just been created from scratch. 168 | // Use the following lines, assuming you are setting up constraints from within the cell's updateConstraints method: 169 | [cell setNeedsUpdateConstraints]; 170 | [cell updateConstraintsIfNeeded]; 171 | 172 | // Do the layout pass on the cell, which will calculate the frames for all the views based on the constraints. 173 | // (Note that you must set the preferredMaxLayoutWidth on multi-line UILabels inside the -[layoutSubviews] method 174 | // of the UITableViewCell subclass, or do it manually at this point before the below 2 lines!) 175 | [cell setNeedsLayout]; 176 | [cell layoutIfNeeded]; 177 | 178 | // Get the actual height required for the cell's contentView 179 | CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 180 | 181 | [cell.contentView removeConstraint:widthConstraint]; 182 | 183 | CGFloat height = size.height; 184 | 185 | // Add an extra point to the height to account for the cell separator, which is added between the bottom 186 | // of the cell's contentView and the bottom of the table view cell. 187 | if (tableView.separatorStyle != UITableViewCellSeparatorStyleNone) { 188 | height += 1.0f; 189 | } 190 | 191 | [cellHeights setObject:@(height) forKey:indexPathString]; 192 | 193 | return height; 194 | } 195 | 196 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 197 | NSString *reusableCellId = [self _reusableCellIdWithTable:tableView indexPath:indexPath]; 198 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reusableCellId forIndexPath:indexPath]; 199 | 200 | if (_delegateImpsPrepareCell) { 201 | [_delegate dynamicTableHelper:self prepareCell:cell atIndexPath:indexPath tableView:tableView offscreen:NO]; 202 | } 203 | 204 | // Make sure the constraints have been set up for this cell, since it may have just been created from scratch. 205 | // Use the following lines, assuming you are setting up constraints from within the cell's updateConstraints method: 206 | 207 | // NOTE: This seems to cause warnings on iOS 7.0 208 | // [cell setNeedsUpdateConstraints]; 209 | // [cell updateConstraintsIfNeeded]; 210 | 211 | return cell; 212 | } 213 | 214 | @end 215 | -------------------------------------------------------------------------------- /Example/AFDynamicTableHelper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2DB53E6619F04127002F9031 /* SimpleListController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DB53E6519F04127002F9031 /* SimpleListController.m */; }; 11 | 2DB53E6C19F047A3002F9031 /* MyDynamicTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DB53E6B19F047A3002F9031 /* MyDynamicTableViewCell.m */; }; 12 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 13 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 14 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 15 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 16 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 17 | 6003F59E195388D20070C39A /* AFAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* AFAppDelegate.m */; }; 18 | 6003F5A1195388D20070C39A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6003F59F195388D20070C39A /* Main.storyboard */; }; 19 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 20 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 21 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 22 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 23 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 24 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 25 | 7C9B49C1A176466AA5096704 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA2AF660F42AD4AC8F00FD4 /* libPods-Tests.a */; }; 26 | B94FD5FE199C76BC8F73CE67 /* libPods-AFDynamicTableHelper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9321121913AF8E1FAEF07B40 /* libPods-AFDynamicTableHelper.a */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 6003F582195388D10070C39A /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 6003F589195388D20070C39A; 35 | remoteInfo = AFDynamicTableHelper; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 27FDB01CAE8D38EA7F7A30A9 /* Pods-AFDynamicTableHelper.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFDynamicTableHelper.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFDynamicTableHelper/Pods-AFDynamicTableHelper.debug.xcconfig"; sourceTree = ""; }; 41 | 2DB53E6419F04127002F9031 /* SimpleListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleListController.h; sourceTree = ""; }; 42 | 2DB53E6519F04127002F9031 /* SimpleListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleListController.m; sourceTree = ""; }; 43 | 2DB53E6A19F047A3002F9031 /* MyDynamicTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyDynamicTableViewCell.h; sourceTree = ""; }; 44 | 2DB53E6B19F047A3002F9031 /* MyDynamicTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyDynamicTableViewCell.m; sourceTree = ""; }; 45 | 3C5208163ECBF0D23BCF4FD2 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 46 | 6003F58A195388D20070C39A /* AFDynamicTableHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AFDynamicTableHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 48 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 49 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 50 | 6003F595195388D20070C39A /* AFDynamicTableHelper-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AFDynamicTableHelper-Info.plist"; sourceTree = ""; }; 51 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 52 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 53 | 6003F59B195388D20070C39A /* AFDynamicTableHelper-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AFDynamicTableHelper-Prefix.pch"; sourceTree = ""; }; 54 | 6003F59C195388D20070C39A /* AFAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AFAppDelegate.h; sourceTree = ""; }; 55 | 6003F59D195388D20070C39A /* AFAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AFAppDelegate.m; sourceTree = ""; }; 56 | 6003F5A0195388D20070C39A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 58 | 6003F5AE195388D20070C39A /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 60 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 61 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 62 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 63 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 64 | 9321121913AF8E1FAEF07B40 /* libPods-AFDynamicTableHelper.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFDynamicTableHelper.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | A6811D720E09BD6E07574E17 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 66 | C5BDC954E7E2FE733A9027D8 /* Pods-AFDynamicTableHelper.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFDynamicTableHelper.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFDynamicTableHelper/Pods-AFDynamicTableHelper.release.xcconfig"; sourceTree = ""; }; 67 | CAA2AF660F42AD4AC8F00FD4 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | D811152B9AF6D5601FC086B5 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 69 | DBDC30D147CF5444C80A3791 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 70 | F62F1E34B8605C1F7B7FD9C4 /* AFDynamicTableHelper.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = AFDynamicTableHelper.podspec; path = ../AFDynamicTableHelper.podspec; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | 6003F587195388D20070C39A /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 79 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 80 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, 81 | B94FD5FE199C76BC8F73CE67 /* libPods-AFDynamicTableHelper.a in Frameworks */, 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 6003F5AB195388D20070C39A /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 90 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 91 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 92 | 7C9B49C1A176466AA5096704 /* libPods-Tests.a in Frameworks */, 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | /* End PBXFrameworksBuildPhase section */ 97 | 98 | /* Begin PBXGroup section */ 99 | 6003F581195388D10070C39A = { 100 | isa = PBXGroup; 101 | children = ( 102 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 103 | 6003F593195388D20070C39A /* AFDynamicTableHelper */, 104 | 6003F5B5195388D20070C39A /* Tests */, 105 | 6003F58C195388D20070C39A /* Frameworks */, 106 | 6003F58B195388D20070C39A /* Products */, 107 | 8592992F47F99E1CBF5888AA /* Pods */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 6003F58B195388D20070C39A /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 6003F58A195388D20070C39A /* AFDynamicTableHelper.app */, 115 | 6003F5AE195388D20070C39A /* Tests.xctest */, 116 | ); 117 | name = Products; 118 | sourceTree = ""; 119 | }; 120 | 6003F58C195388D20070C39A /* Frameworks */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 6003F58D195388D20070C39A /* Foundation.framework */, 124 | 6003F58F195388D20070C39A /* CoreGraphics.framework */, 125 | 6003F591195388D20070C39A /* UIKit.framework */, 126 | 6003F5AF195388D20070C39A /* XCTest.framework */, 127 | 9321121913AF8E1FAEF07B40 /* libPods-AFDynamicTableHelper.a */, 128 | CAA2AF660F42AD4AC8F00FD4 /* libPods-Tests.a */, 129 | ); 130 | name = Frameworks; 131 | sourceTree = ""; 132 | }; 133 | 6003F593195388D20070C39A /* AFDynamicTableHelper */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 6003F59C195388D20070C39A /* AFAppDelegate.h */, 137 | 6003F59D195388D20070C39A /* AFAppDelegate.m */, 138 | 6003F59F195388D20070C39A /* Main.storyboard */, 139 | 6003F5A8195388D20070C39A /* Images.xcassets */, 140 | 6003F594195388D20070C39A /* Supporting Files */, 141 | 2DB53E6419F04127002F9031 /* SimpleListController.h */, 142 | 2DB53E6519F04127002F9031 /* SimpleListController.m */, 143 | 2DB53E6A19F047A3002F9031 /* MyDynamicTableViewCell.h */, 144 | 2DB53E6B19F047A3002F9031 /* MyDynamicTableViewCell.m */, 145 | ); 146 | path = AFDynamicTableHelper; 147 | sourceTree = ""; 148 | }; 149 | 6003F594195388D20070C39A /* Supporting Files */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 6003F595195388D20070C39A /* AFDynamicTableHelper-Info.plist */, 153 | 6003F596195388D20070C39A /* InfoPlist.strings */, 154 | 6003F599195388D20070C39A /* main.m */, 155 | 6003F59B195388D20070C39A /* AFDynamicTableHelper-Prefix.pch */, 156 | ); 157 | name = "Supporting Files"; 158 | sourceTree = ""; 159 | }; 160 | 6003F5B5195388D20070C39A /* Tests */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 6003F5BB195388D20070C39A /* Tests.m */, 164 | 6003F5B6195388D20070C39A /* Supporting Files */, 165 | ); 166 | path = Tests; 167 | sourceTree = ""; 168 | }; 169 | 6003F5B6195388D20070C39A /* Supporting Files */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 6003F5B7195388D20070C39A /* Tests-Info.plist */, 173 | 6003F5B8195388D20070C39A /* InfoPlist.strings */, 174 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, 175 | ); 176 | name = "Supporting Files"; 177 | sourceTree = ""; 178 | }; 179 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | F62F1E34B8605C1F7B7FD9C4 /* AFDynamicTableHelper.podspec */, 183 | D811152B9AF6D5601FC086B5 /* README.md */, 184 | 3C5208163ECBF0D23BCF4FD2 /* LICENSE */, 185 | ); 186 | name = "Podspec Metadata"; 187 | sourceTree = ""; 188 | }; 189 | 8592992F47F99E1CBF5888AA /* Pods */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 27FDB01CAE8D38EA7F7A30A9 /* Pods-AFDynamicTableHelper.debug.xcconfig */, 193 | C5BDC954E7E2FE733A9027D8 /* Pods-AFDynamicTableHelper.release.xcconfig */, 194 | A6811D720E09BD6E07574E17 /* Pods-Tests.debug.xcconfig */, 195 | DBDC30D147CF5444C80A3791 /* Pods-Tests.release.xcconfig */, 196 | ); 197 | name = Pods; 198 | sourceTree = ""; 199 | }; 200 | /* End PBXGroup section */ 201 | 202 | /* Begin PBXNativeTarget section */ 203 | 6003F589195388D20070C39A /* AFDynamicTableHelper */ = { 204 | isa = PBXNativeTarget; 205 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "AFDynamicTableHelper" */; 206 | buildPhases = ( 207 | 7B0489B4D0F961395B7CF14D /* Check Pods Manifest.lock */, 208 | 6003F586195388D20070C39A /* Sources */, 209 | 6003F587195388D20070C39A /* Frameworks */, 210 | 6003F588195388D20070C39A /* Resources */, 211 | CB64FFAF0B26AB3D07019ED6 /* Copy Pods Resources */, 212 | ); 213 | buildRules = ( 214 | ); 215 | dependencies = ( 216 | ); 217 | name = AFDynamicTableHelper; 218 | productName = AFDynamicTableHelper; 219 | productReference = 6003F58A195388D20070C39A /* AFDynamicTableHelper.app */; 220 | productType = "com.apple.product-type.application"; 221 | }; 222 | 6003F5AD195388D20070C39A /* Tests */ = { 223 | isa = PBXNativeTarget; 224 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */; 225 | buildPhases = ( 226 | D9664848D1E3744EE50E2C04 /* Check Pods Manifest.lock */, 227 | 6003F5AA195388D20070C39A /* Sources */, 228 | 6003F5AB195388D20070C39A /* Frameworks */, 229 | 6003F5AC195388D20070C39A /* Resources */, 230 | B10F28E792EA70CAC91177ED /* Copy Pods Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | 6003F5B4195388D20070C39A /* PBXTargetDependency */, 236 | ); 237 | name = Tests; 238 | productName = AFDynamicTableHelperTests; 239 | productReference = 6003F5AE195388D20070C39A /* Tests.xctest */; 240 | productType = "com.apple.product-type.bundle.unit-test"; 241 | }; 242 | /* End PBXNativeTarget section */ 243 | 244 | /* Begin PBXProject section */ 245 | 6003F582195388D10070C39A /* Project object */ = { 246 | isa = PBXProject; 247 | attributes = { 248 | CLASSPREFIX = AF; 249 | LastUpgradeCheck = 0510; 250 | ORGANIZATIONNAME = Oz; 251 | TargetAttributes = { 252 | 6003F5AD195388D20070C39A = { 253 | TestTargetID = 6003F589195388D20070C39A; 254 | }; 255 | }; 256 | }; 257 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "AFDynamicTableHelper" */; 258 | compatibilityVersion = "Xcode 3.2"; 259 | developmentRegion = English; 260 | hasScannedForEncodings = 0; 261 | knownRegions = ( 262 | en, 263 | Base, 264 | ); 265 | mainGroup = 6003F581195388D10070C39A; 266 | productRefGroup = 6003F58B195388D20070C39A /* Products */; 267 | projectDirPath = ""; 268 | projectRoot = ""; 269 | targets = ( 270 | 6003F589195388D20070C39A /* AFDynamicTableHelper */, 271 | 6003F5AD195388D20070C39A /* Tests */, 272 | ); 273 | }; 274 | /* End PBXProject section */ 275 | 276 | /* Begin PBXResourcesBuildPhase section */ 277 | 6003F588195388D20070C39A /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 282 | 6003F5A1195388D20070C39A /* Main.storyboard in Resources */, 283 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | 6003F5AC195388D20070C39A /* Resources */ = { 288 | isa = PBXResourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | /* End PBXResourcesBuildPhase section */ 296 | 297 | /* Begin PBXShellScriptBuildPhase section */ 298 | 7B0489B4D0F961395B7CF14D /* Check Pods Manifest.lock */ = { 299 | isa = PBXShellScriptBuildPhase; 300 | buildActionMask = 2147483647; 301 | files = ( 302 | ); 303 | inputPaths = ( 304 | ); 305 | name = "Check Pods Manifest.lock"; 306 | outputPaths = ( 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | shellPath = /bin/sh; 310 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 311 | showEnvVarsInLog = 0; 312 | }; 313 | B10F28E792EA70CAC91177ED /* Copy Pods Resources */ = { 314 | isa = PBXShellScriptBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | ); 318 | inputPaths = ( 319 | ); 320 | name = "Copy Pods Resources"; 321 | outputPaths = ( 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | shellPath = /bin/sh; 325 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; 326 | showEnvVarsInLog = 0; 327 | }; 328 | CB64FFAF0B26AB3D07019ED6 /* Copy Pods Resources */ = { 329 | isa = PBXShellScriptBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | ); 333 | inputPaths = ( 334 | ); 335 | name = "Copy Pods Resources"; 336 | outputPaths = ( 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | shellPath = /bin/sh; 340 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AFDynamicTableHelper/Pods-AFDynamicTableHelper-resources.sh\"\n"; 341 | showEnvVarsInLog = 0; 342 | }; 343 | D9664848D1E3744EE50E2C04 /* Check Pods Manifest.lock */ = { 344 | isa = PBXShellScriptBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | ); 348 | inputPaths = ( 349 | ); 350 | name = "Check Pods Manifest.lock"; 351 | outputPaths = ( 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | shellPath = /bin/sh; 355 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 356 | showEnvVarsInLog = 0; 357 | }; 358 | /* End PBXShellScriptBuildPhase section */ 359 | 360 | /* Begin PBXSourcesBuildPhase section */ 361 | 6003F586195388D20070C39A /* Sources */ = { 362 | isa = PBXSourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | 2DB53E6619F04127002F9031 /* SimpleListController.m in Sources */, 366 | 2DB53E6C19F047A3002F9031 /* MyDynamicTableViewCell.m in Sources */, 367 | 6003F59E195388D20070C39A /* AFAppDelegate.m in Sources */, 368 | 6003F59A195388D20070C39A /* main.m in Sources */, 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | 6003F5AA195388D20070C39A /* Sources */ = { 373 | isa = PBXSourcesBuildPhase; 374 | buildActionMask = 2147483647; 375 | files = ( 376 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 377 | ); 378 | runOnlyForDeploymentPostprocessing = 0; 379 | }; 380 | /* End PBXSourcesBuildPhase section */ 381 | 382 | /* Begin PBXTargetDependency section */ 383 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 384 | isa = PBXTargetDependency; 385 | target = 6003F589195388D20070C39A /* AFDynamicTableHelper */; 386 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 387 | }; 388 | /* End PBXTargetDependency section */ 389 | 390 | /* Begin PBXVariantGroup section */ 391 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 392 | isa = PBXVariantGroup; 393 | children = ( 394 | 6003F597195388D20070C39A /* en */, 395 | ); 396 | name = InfoPlist.strings; 397 | sourceTree = ""; 398 | }; 399 | 6003F59F195388D20070C39A /* Main.storyboard */ = { 400 | isa = PBXVariantGroup; 401 | children = ( 402 | 6003F5A0195388D20070C39A /* Base */, 403 | ); 404 | name = Main.storyboard; 405 | sourceTree = ""; 406 | }; 407 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 408 | isa = PBXVariantGroup; 409 | children = ( 410 | 6003F5B9195388D20070C39A /* en */, 411 | ); 412 | name = InfoPlist.strings; 413 | sourceTree = ""; 414 | }; 415 | /* End PBXVariantGroup section */ 416 | 417 | /* Begin XCBuildConfiguration section */ 418 | 6003F5BD195388D20070C39A /* Debug */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 423 | CLANG_CXX_LIBRARY = "libc++"; 424 | CLANG_ENABLE_MODULES = YES; 425 | CLANG_ENABLE_OBJC_ARC = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_CONSTANT_CONVERSION = YES; 428 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 429 | CLANG_WARN_EMPTY_BODY = YES; 430 | CLANG_WARN_ENUM_CONVERSION = YES; 431 | CLANG_WARN_INT_CONVERSION = YES; 432 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 433 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 434 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 435 | COPY_PHASE_STRIP = NO; 436 | GCC_C_LANGUAGE_STANDARD = gnu99; 437 | GCC_DYNAMIC_NO_PIC = NO; 438 | GCC_OPTIMIZATION_LEVEL = 0; 439 | GCC_PREPROCESSOR_DEFINITIONS = ( 440 | "DEBUG=1", 441 | "$(inherited)", 442 | ); 443 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 444 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 445 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 446 | GCC_WARN_UNDECLARED_SELECTOR = YES; 447 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 448 | GCC_WARN_UNUSED_FUNCTION = YES; 449 | GCC_WARN_UNUSED_VARIABLE = YES; 450 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 451 | ONLY_ACTIVE_ARCH = YES; 452 | SDKROOT = iphoneos; 453 | TARGETED_DEVICE_FAMILY = "1,2"; 454 | }; 455 | name = Debug; 456 | }; 457 | 6003F5BE195388D20070C39A /* Release */ = { 458 | isa = XCBuildConfiguration; 459 | buildSettings = { 460 | ALWAYS_SEARCH_USER_PATHS = NO; 461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 462 | CLANG_CXX_LIBRARY = "libc++"; 463 | CLANG_ENABLE_MODULES = YES; 464 | CLANG_ENABLE_OBJC_ARC = YES; 465 | CLANG_WARN_BOOL_CONVERSION = YES; 466 | CLANG_WARN_CONSTANT_CONVERSION = YES; 467 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 468 | CLANG_WARN_EMPTY_BODY = YES; 469 | CLANG_WARN_ENUM_CONVERSION = YES; 470 | CLANG_WARN_INT_CONVERSION = YES; 471 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 472 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 473 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 474 | COPY_PHASE_STRIP = YES; 475 | ENABLE_NS_ASSERTIONS = NO; 476 | GCC_C_LANGUAGE_STANDARD = gnu99; 477 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 478 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 479 | GCC_WARN_UNDECLARED_SELECTOR = YES; 480 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 481 | GCC_WARN_UNUSED_FUNCTION = YES; 482 | GCC_WARN_UNUSED_VARIABLE = YES; 483 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 484 | SDKROOT = iphoneos; 485 | TARGETED_DEVICE_FAMILY = "1,2"; 486 | VALIDATE_PRODUCT = YES; 487 | }; 488 | name = Release; 489 | }; 490 | 6003F5C0195388D20070C39A /* Debug */ = { 491 | isa = XCBuildConfiguration; 492 | baseConfigurationReference = 27FDB01CAE8D38EA7F7A30A9 /* Pods-AFDynamicTableHelper.debug.xcconfig */; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 496 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 497 | GCC_PREFIX_HEADER = "AFDynamicTableHelper/AFDynamicTableHelper-Prefix.pch"; 498 | INFOPLIST_FILE = "AFDynamicTableHelper/AFDynamicTableHelper-Info.plist"; 499 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | TARGETED_DEVICE_FAMILY = 1; 502 | WRAPPER_EXTENSION = app; 503 | }; 504 | name = Debug; 505 | }; 506 | 6003F5C1195388D20070C39A /* Release */ = { 507 | isa = XCBuildConfiguration; 508 | baseConfigurationReference = C5BDC954E7E2FE733A9027D8 /* Pods-AFDynamicTableHelper.release.xcconfig */; 509 | buildSettings = { 510 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 511 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 512 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 513 | GCC_PREFIX_HEADER = "AFDynamicTableHelper/AFDynamicTableHelper-Prefix.pch"; 514 | INFOPLIST_FILE = "AFDynamicTableHelper/AFDynamicTableHelper-Info.plist"; 515 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | TARGETED_DEVICE_FAMILY = 1; 518 | WRAPPER_EXTENSION = app; 519 | }; 520 | name = Release; 521 | }; 522 | 6003F5C3195388D20070C39A /* Debug */ = { 523 | isa = XCBuildConfiguration; 524 | baseConfigurationReference = A6811D720E09BD6E07574E17 /* Pods-Tests.debug.xcconfig */; 525 | buildSettings = { 526 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/AFDynamicTableHelper.app/AFDynamicTableHelper"; 527 | FRAMEWORK_SEARCH_PATHS = ( 528 | "$(SDKROOT)/Developer/Library/Frameworks", 529 | "$(inherited)", 530 | "$(DEVELOPER_FRAMEWORKS_DIR)", 531 | ); 532 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 533 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 534 | GCC_PREPROCESSOR_DEFINITIONS = ( 535 | "DEBUG=1", 536 | "$(inherited)", 537 | ); 538 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | TEST_HOST = "$(BUNDLE_LOADER)"; 541 | WRAPPER_EXTENSION = xctest; 542 | }; 543 | name = Debug; 544 | }; 545 | 6003F5C4195388D20070C39A /* Release */ = { 546 | isa = XCBuildConfiguration; 547 | baseConfigurationReference = DBDC30D147CF5444C80A3791 /* Pods-Tests.release.xcconfig */; 548 | buildSettings = { 549 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/AFDynamicTableHelper.app/AFDynamicTableHelper"; 550 | FRAMEWORK_SEARCH_PATHS = ( 551 | "$(SDKROOT)/Developer/Library/Frameworks", 552 | "$(inherited)", 553 | "$(DEVELOPER_FRAMEWORKS_DIR)", 554 | ); 555 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 556 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 557 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 558 | PRODUCT_NAME = "$(TARGET_NAME)"; 559 | TEST_HOST = "$(BUNDLE_LOADER)"; 560 | WRAPPER_EXTENSION = xctest; 561 | }; 562 | name = Release; 563 | }; 564 | /* End XCBuildConfiguration section */ 565 | 566 | /* Begin XCConfigurationList section */ 567 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "AFDynamicTableHelper" */ = { 568 | isa = XCConfigurationList; 569 | buildConfigurations = ( 570 | 6003F5BD195388D20070C39A /* Debug */, 571 | 6003F5BE195388D20070C39A /* Release */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "AFDynamicTableHelper" */ = { 577 | isa = XCConfigurationList; 578 | buildConfigurations = ( 579 | 6003F5C0195388D20070C39A /* Debug */, 580 | 6003F5C1195388D20070C39A /* Release */, 581 | ); 582 | defaultConfigurationIsVisible = 0; 583 | defaultConfigurationName = Release; 584 | }; 585 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */ = { 586 | isa = XCConfigurationList; 587 | buildConfigurations = ( 588 | 6003F5C3195388D20070C39A /* Debug */, 589 | 6003F5C4195388D20070C39A /* Release */, 590 | ); 591 | defaultConfigurationIsVisible = 0; 592 | defaultConfigurationName = Release; 593 | }; 594 | /* End XCConfigurationList section */ 595 | }; 596 | rootObject = 6003F582195388D10070C39A /* Project object */; 597 | } 598 | --------------------------------------------------------------------------------