├── SubTable@2x.png
├── SubTableExample
├── SubTableExample
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── AppDelegate.h
│ ├── SubTable
│ │ ├── SubRow
│ │ │ ├── ExpandedContainer.h
│ │ │ ├── ExpandedContainer.m
│ │ │ ├── ChildCell
│ │ │ │ ├── SubTableViewCell.h
│ │ │ │ └── SubTableViewCell.m
│ │ │ ├── SubTableView.h
│ │ │ └── SubTableView.m
│ │ ├── ParentCell
│ │ │ ├── ParentTableViewCell.h
│ │ │ └── ParentTableViewCell.m
│ │ ├── ParentTableView.h
│ │ └── ParentTableView.m
│ ├── main.m
│ ├── SubTableExample-Prefix.pch
│ ├── ViewController.h
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── SubTableExample-Info.plist
│ ├── ViewController.xib
│ ├── AppDelegate.m
│ └── ViewController.m
├── SubTableExampleTests
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── SubTableExampleTests-Info.plist
│ └── SubTableExampleTests.m
└── SubTableExample.xcodeproj
│ ├── xcuserdata
│ └── Alex.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── SubTableExample.xcscheme
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── Alex.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── SubTableExample.xccheckout
│ └── project.pbxproj
├── .gitignore
├── SubTable
├── SubRow
│ ├── ExpandedContainer.h
│ ├── ExpandedContainer.m
│ ├── ChildCell
│ │ ├── SubTableViewCell.h
│ │ └── SubTableViewCell.m
│ ├── SubTableView.h
│ └── SubTableView.m
├── ParentCell
│ ├── ParentTableViewCell.h
│ └── ParentTableViewCell.m
├── ParentTableView.h
└── ParentTableView.m
├── LICENSE
└── README.md
/SubTable@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajkoshy7/SubTable/HEAD/SubTable@2x.png
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExampleTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/xcuserdata/Alex.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajkoshy7/SubTable/HEAD/SubTableExample/SubTableExample.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # CocoaPods
2 | #
3 | # We recommend against adding the Pods directory to your .gitignore. However
4 | # you should judge for yourself, the pros and cons are mentioned at:
5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control?
6 | #
7 | # Pods/
8 |
9 |
--------------------------------------------------------------------------------
/SubTable/SubRow/ExpandedContainer.h:
--------------------------------------------------------------------------------
1 | //
2 | // ExpandedContainer.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SubTableView.h"
11 | #import "SubTableViewCell.h"
12 |
13 | @interface ExpandedContainer : SubTableView
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/SubRow/ExpandedContainer.h:
--------------------------------------------------------------------------------
1 | //
2 | // ExpandedContainer.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SubTableView.h"
11 | #import "SubTableViewCell.h"
12 |
13 | @interface ExpandedContainer : SubTableView
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "AppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTableExample-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_3_0
10 | #warning "This project uses features only available in iOS SDK 3.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ParentTableView.h"
11 |
12 | @interface ViewController : UIViewController
13 |
14 | @property (strong, nonatomic) IBOutlet ParentTableView *tableView;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SubTable/SubRow/ExpandedContainer.m:
--------------------------------------------------------------------------------
1 | //
2 | // ExpandedContainer.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ExpandedContainer.h"
10 | #import "SubTableViewCell.h"
11 |
12 | @implementation ExpandedContainer
13 |
14 | #pragma mark - Table view delegate
15 |
16 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
17 |
18 | // SubTableViewCell *cell = (SubTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
19 | // ...
20 |
21 | [self.delegate didSelectRowAtChildIndex:indexPath.row underParentIndex:self.parentIndex];
22 | }
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/SubTable/SubRow/ChildCell/SubTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableViewCell.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SubTableViewCell : UITableViewCell {
12 |
13 | UILabel *titleLabel;
14 | UILabel *subtitleLabel;
15 | }
16 |
17 | @property (strong, nonatomic) UILabel *titleLabel;
18 | @property (strong, nonatomic) UILabel *subtitleLabel;
19 |
20 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier;
21 | - (void)setupDisplay;
22 | - (void)setCellForegroundColor:(UIColor *) foregroundColor;
23 | - (void)setCellBackgroundColor:(UIColor *) backgroundColor;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/SubRow/ExpandedContainer.m:
--------------------------------------------------------------------------------
1 | //
2 | // ExpandedContainer.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ExpandedContainer.h"
10 | #import "SubTableViewCell.h"
11 |
12 | @implementation ExpandedContainer
13 |
14 | #pragma mark - Table view delegate
15 |
16 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
17 |
18 | // SubTableViewCell *cell = (SubTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
19 | // ...
20 |
21 | [self.delegate didSelectRowAtChildIndex:indexPath.row underParentIndex:self.parentIndex];
22 | }
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/SubRow/ChildCell/SubTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableViewCell.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SubTableViewCell : UITableViewCell {
12 |
13 | UILabel *titleLabel;
14 | UILabel *subtitleLabel;
15 | }
16 |
17 | @property (strong, nonatomic) UILabel *titleLabel;
18 | @property (strong, nonatomic) UILabel *subtitleLabel;
19 |
20 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier;
21 | - (void)setupDisplay;
22 | - (void)setCellForegroundColor:(UIColor *) foregroundColor;
23 | - (void)setCellBackgroundColor:(UIColor *) backgroundColor;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/SubTable/ParentCell/ParentTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableViewCell.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ParentTableViewCell : UITableViewCell {
12 |
13 | NSInteger parentIndex;
14 | UILabel *titleLabel;
15 | UILabel *subtitleLabel;
16 | }
17 |
18 | @property (nonatomic) NSInteger parentIndex;
19 | @property (strong, nonatomic) UILabel *titleLabel;
20 | @property (strong, nonatomic) UILabel *subtitleLabel;
21 |
22 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier;
23 | - (void)setCellForegroundColor:(UIColor *)foregroundColor;
24 | - (void)setCellBackgroundColor:(UIColor *)backgroundColor;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SubTableExample.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | FAEF419C197751FE00DC189F
16 |
17 | primary
18 |
19 |
20 | FAEF41B7197751FE00DC189F
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/ParentCell/ParentTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableViewCell.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ParentTableViewCell : UITableViewCell {
12 |
13 | NSInteger parentIndex;
14 | UILabel *titleLabel;
15 | UILabel *subtitleLabel;
16 | }
17 |
18 | @property (nonatomic) NSInteger parentIndex;
19 | @property (strong, nonatomic) UILabel *titleLabel;
20 | @property (strong, nonatomic) UILabel *subtitleLabel;
21 |
22 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier;
23 | - (void)setCellForegroundColor:(UIColor *)foregroundColor;
24 | - (void)setCellBackgroundColor:(UIColor *)backgroundColor;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExampleTests/SubTableExampleTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ajkoshy7.${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 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExampleTests/SubTableExampleTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableExampleTests.m
3 | // SubTableExampleTests
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SubTableExampleTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation SubTableExampleTests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/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 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Alex Koshy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/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 | }
--------------------------------------------------------------------------------
/SubTable/SubRow/SubTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableView.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol SubTableViewCellDelegate
12 |
13 | @required
14 | - (NSInteger)numberOfChildrenUnderParentIndex:(NSInteger)parentIndex;
15 | - (NSInteger)heightForChildRows;
16 |
17 | @optional
18 | - (void)didSelectRowAtChildIndex:(NSInteger)childIndex
19 | underParentIndex:(NSInteger)parentIndex;
20 | - (NSString *)titleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex;
21 | - (NSString *)subtitleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex;
22 |
23 | @end
24 |
25 |
26 |
27 | @interface SubTableView : UITableViewCell {
28 | UITableView *insideTableView;
29 | __weak id delegate;
30 | UIColor *bgColor;
31 | UIColor *fgColor;
32 | UIFont *font;
33 | }
34 |
35 | @property (nonatomic,strong) UITableView *insideTableView;
36 | @property (nonatomic,weak,getter = getDelegate, setter = setDelegate:) id delegate;
37 | @property (nonatomic) NSInteger parentIndex;
38 |
39 | @property (nonatomic, strong, getter = getSubTableForegroundColor, setter = setSubTableForegroundColor:) UIColor *fgColor;
40 | @property (nonatomic, strong, getter = getSubTableBackgroundColor, setter = setSubTableBackgroundColor:) UIColor *bgColor;
41 | @property (nonatomic, strong, getter = getSubTableFont, setter = setSubTableFont:) UIFont *font;
42 |
43 | - (void)reload;
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/SubRow/SubTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableView.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol SubTableViewCellDelegate
12 |
13 | @required
14 | - (NSInteger)numberOfChildrenUnderParentIndex:(NSInteger)parentIndex;
15 | - (NSInteger)heightForChildRows;
16 |
17 | @optional
18 | - (void)didSelectRowAtChildIndex:(NSInteger)childIndex
19 | underParentIndex:(NSInteger)parentIndex;
20 | - (NSString *)titleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex;
21 | - (NSString *)subtitleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex;
22 |
23 | @end
24 |
25 |
26 |
27 | @interface SubTableView : UITableViewCell {
28 | UITableView *insideTableView;
29 | __weak id delegate;
30 | UIColor *bgColor;
31 | UIColor *fgColor;
32 | UIFont *font;
33 | }
34 |
35 | @property (nonatomic,strong) UITableView *insideTableView;
36 | @property (nonatomic,weak,getter = getDelegate, setter = setDelegate:) id delegate;
37 | @property (nonatomic) NSInteger parentIndex;
38 |
39 | @property (nonatomic, strong, getter = getSubTableForegroundColor, setter = setSubTableForegroundColor:) UIColor *fgColor;
40 | @property (nonatomic, strong, getter = getSubTableBackgroundColor, setter = setSubTableBackgroundColor:) UIColor *bgColor;
41 | @property (nonatomic, strong, getter = getSubTableFont, setter = setSubTableFont:) UIFont *font;
42 |
43 | - (void)reload;
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTableExample-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | ajkoshy7.${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 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/project.xcworkspace/xcshareddata/SubTableExample.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 3F333FF6-F4FC-4168-B5FB-FBEB3B20FD3F
9 | IDESourceControlProjectName
10 | SubTableExample
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 0A686B62-C257-4938-A352-6A18ABFFDDD1
14 | https://github.com/ajkoshy7/SubTable.git
15 |
16 | IDESourceControlProjectPath
17 | Examples/SubTableExample/SubTableExample.xcodeproj/project.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 0A686B62-C257-4938-A352-6A18ABFFDDD1
21 | ../../../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/ajkoshy7/SubTable.git
25 | IDESourceControlProjectVersion
26 | 110
27 | IDESourceControlProjectWCCIdentifier
28 | 0A686B62-C257-4938-A352-6A18ABFFDDD1
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 0A686B62-C257-4938-A352-6A18ABFFDDD1
36 | IDESourceControlWCCName
37 | SubTableExample
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SubTable/ParentTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableView.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ExpandedContainer.h"
11 |
12 | @class ViewController;
13 |
14 | @protocol SubTableViewDelegate
15 |
16 | @optional
17 | - (void)tableView:(UITableView *)tableView didSelectCellAtChildIndex:(NSInteger)childIndex withInParentCellIndex:(NSInteger)parentIndex;
18 | - (void)tableView:(UITableView *)tableView didDeselectCellAtChildIndex:(NSInteger)childIndex withInParentCellIndex:(NSInteger)parentIndex;
19 | - (void)tableView:(UITableView *)tableView didSelectParentCellAtIndex:(NSInteger)parentIndex;
20 |
21 | @end
22 |
23 |
24 |
25 | @protocol SubTableViewDataSource
26 |
27 | @required
28 | - (NSInteger)numberOfParentCells;
29 | - (NSInteger)numberOfChildCellsUnderParentIndex:(NSInteger)parentIndex;
30 | - (NSInteger)heightForParentRows;
31 | - (NSInteger)heightForChildRows;
32 |
33 | @optional
34 |
35 | // Parent DataSource
36 | - (NSString *)titleLabelForParentCellAtIndex:(NSInteger)parentIndex;
37 | - (NSString *)subtitleLabelForParentCellAtIndex:(NSInteger)parentIndex;
38 |
39 | // Child DataSource
40 | - (NSString *)titleLabelForCellAtChildIndex:(NSInteger)childIndex withinParentCellIndex:(NSInteger)parentIndex;
41 | - (NSString *)subtitleLabelForCellAtChildIndex:(NSInteger)childIndex withinParentCellIndex:(NSInteger)parentIndex;
42 |
43 | @end
44 |
45 |
46 |
47 | @interface ParentTableView : UITableView
48 | {
49 | __weak id tableViewDelegate;
50 | __weak id dataSourceDelegate;
51 | NSMutableArray * expansionStates;
52 | }
53 |
54 | @property (nonatomic, weak) id tableViewDelegate;
55 | @property (nonatomic, weak, getter = getDataSourceDelegate, setter = setDataSourceDelegate:) id dataSourceDelegate;
56 | @property (nonatomic, strong) NSMutableArray * expansionStates;
57 |
58 | @property (assign, nonatomic) NSInteger selectedRow;
59 | - (void)collapseAllRows;
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/ParentTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableView.h
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ExpandedContainer.h"
11 |
12 | @class ViewController;
13 |
14 | @protocol SubTableViewDelegate
15 |
16 | @optional
17 | - (void)tableView:(UITableView *)tableView didSelectCellAtChildIndex:(NSInteger)childIndex withInParentCellIndex:(NSInteger)parentIndex;
18 | - (void)tableView:(UITableView *)tableView didDeselectCellAtChildIndex:(NSInteger)childIndex withInParentCellIndex:(NSInteger)parentIndex;
19 | - (void)tableView:(UITableView *)tableView didSelectParentCellAtIndex:(NSInteger)parentIndex;
20 |
21 | @end
22 |
23 |
24 |
25 | @protocol SubTableViewDataSource
26 |
27 | @required
28 | - (NSInteger)numberOfParentCells;
29 | - (NSInteger)numberOfChildCellsUnderParentIndex:(NSInteger)parentIndex;
30 | - (NSInteger)heightForParentRows;
31 | - (NSInteger)heightForChildRows;
32 |
33 | @optional
34 |
35 | // Parent DataSource
36 | - (NSString *)titleLabelForParentCellAtIndex:(NSInteger)parentIndex;
37 | - (NSString *)subtitleLabelForParentCellAtIndex:(NSInteger)parentIndex;
38 |
39 | // Child DataSource
40 | - (NSString *)titleLabelForCellAtChildIndex:(NSInteger)childIndex withinParentCellIndex:(NSInteger)parentIndex;
41 | - (NSString *)subtitleLabelForCellAtChildIndex:(NSInteger)childIndex withinParentCellIndex:(NSInteger)parentIndex;
42 |
43 | @end
44 |
45 |
46 |
47 | @interface ParentTableView : UITableView
48 | {
49 | __weak id tableViewDelegate;
50 | __weak id dataSourceDelegate;
51 | NSMutableArray * expansionStates;
52 | }
53 |
54 | @property (nonatomic, weak) id tableViewDelegate;
55 | @property (nonatomic, weak, getter = getDataSourceDelegate, setter = setDataSourceDelegate:) id dataSourceDelegate;
56 | @property (nonatomic, strong) NSMutableArray * expansionStates;
57 |
58 | @property (assign, nonatomic) NSInteger selectedRow;
59 | - (void)collapseAllRows;
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/SubTable/ParentCell/ParentTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableViewCell.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ParentTableViewCell.h"
10 |
11 | @implementation ParentTableViewCell
12 | @synthesize parentIndex;
13 | @synthesize titleLabel;
14 | @synthesize subtitleLabel;
15 |
16 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier; {
17 |
18 | self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
19 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
20 | [[self contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
21 |
22 | if (!self) {
23 | return self;
24 | }
25 |
26 | self.contentView.backgroundColor = [UIColor clearColor];
27 | self.selectionStyle = UITableViewCellSelectionStyleNone;
28 |
29 | self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 16, 200, 23)];
30 | titleLabel.backgroundColor = [UIColor clearColor];
31 | titleLabel.opaque = NO;
32 | titleLabel.textColor = [UIColor darkTextColor];
33 | titleLabel.textAlignment = NSTextAlignmentLeft;
34 | [self.contentView addSubview:titleLabel];
35 |
36 |
37 | self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 41, 200, 16)];
38 | subtitleLabel.backgroundColor = [UIColor clearColor];
39 | subtitleLabel.opaque = NO;
40 | subtitleLabel.textColor = [UIColor darkTextColor];
41 | subtitleLabel.textAlignment = NSTextAlignmentLeft;
42 | [self.contentView addSubview:subtitleLabel];
43 |
44 | UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 73, 320, 2)];
45 | bottomLine.backgroundColor = [UIColor colorWithWhite:( 42/255.0) alpha:1.0];
46 | [self.contentView addSubview:bottomLine];
47 |
48 | [self.contentView setAutoresizesSubviews:YES];
49 |
50 | return self;
51 | }
52 |
53 | - (void)setCellForegroundColor:(UIColor *)foregroundColor {
54 | self.titleLabel.textColor = foregroundColor;
55 | self.subtitleLabel.textColor = [UIColor colorWithWhite:0.9 alpha:1.0];
56 | }
57 | - (void)setCellBackgroundColor:(UIColor *)backgroundColor {
58 | self.contentView.backgroundColor = backgroundColor;
59 | }
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/ParentCell/ParentTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableViewCell.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ParentTableViewCell.h"
10 |
11 | @implementation ParentTableViewCell
12 | @synthesize parentIndex;
13 | @synthesize titleLabel;
14 | @synthesize subtitleLabel;
15 |
16 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier; {
17 |
18 | self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
19 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
20 | [[self contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
21 |
22 | if (!self) {
23 | return self;
24 | }
25 |
26 | self.contentView.backgroundColor = [UIColor clearColor];
27 | self.selectionStyle = UITableViewCellSelectionStyleNone;
28 |
29 | self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 16, 200, 23)];
30 | titleLabel.backgroundColor = [UIColor clearColor];
31 | titleLabel.opaque = NO;
32 | titleLabel.textColor = [UIColor darkTextColor];
33 | titleLabel.textAlignment = NSTextAlignmentLeft;
34 | [self.contentView addSubview:titleLabel];
35 |
36 |
37 | self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 41, 200, 16)];
38 | subtitleLabel.backgroundColor = [UIColor clearColor];
39 | subtitleLabel.opaque = NO;
40 | subtitleLabel.textColor = [UIColor darkTextColor];
41 | subtitleLabel.textAlignment = NSTextAlignmentLeft;
42 | [self.contentView addSubview:subtitleLabel];
43 |
44 | UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 73, 320, 2)];
45 | bottomLine.backgroundColor = [UIColor colorWithWhite:( 42/255.0) alpha:1.0];
46 | [self.contentView addSubview:bottomLine];
47 |
48 | [self.contentView setAutoresizesSubviews:YES];
49 |
50 | return self;
51 | }
52 |
53 | - (void)setCellForegroundColor:(UIColor *)foregroundColor {
54 | self.titleLabel.textColor = foregroundColor;
55 | self.subtitleLabel.textColor = [UIColor colorWithWhite:0.9 alpha:1.0];
56 | }
57 | - (void)setCellBackgroundColor:(UIColor *)backgroundColor {
58 | self.contentView.backgroundColor = backgroundColor;
59 | }
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/ViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/SubTable/SubRow/ChildCell/SubTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableViewCell.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "SubTableViewCell.h"
10 |
11 | @implementation SubTableViewCell
12 | @synthesize titleLabel;
13 | @synthesize subtitleLabel;
14 |
15 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
16 |
17 | self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
18 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
19 | [[self contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
20 |
21 | if (!self)
22 | return self;
23 |
24 | self.contentView.backgroundColor = [UIColor whiteColor];
25 |
26 | self.selectionStyle = UITableViewCellSelectionStyleNone;
27 |
28 | self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
29 | titleLabel.backgroundColor = [UIColor clearColor];
30 | titleLabel.opaque = NO;
31 | titleLabel.textColor = [UIColor blackColor];
32 | titleLabel.textAlignment = NSTextAlignmentLeft;
33 | [self.contentView addSubview:titleLabel];
34 |
35 | self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
36 | subtitleLabel.backgroundColor = [UIColor clearColor];
37 | subtitleLabel.opaque = NO;
38 | subtitleLabel.textColor = [UIColor blackColor];
39 | subtitleLabel.textAlignment = NSTextAlignmentLeft;
40 | [self.contentView addSubview:subtitleLabel];
41 |
42 | return self;
43 | }
44 |
45 | - (void)layoutSubviews {
46 | [super layoutSubviews];
47 | [self setupDisplay];
48 | }
49 |
50 | - (void)setupDisplay {
51 |
52 | [self.contentView setAutoresizesSubviews:YES];
53 |
54 | self.titleLabel.frame = CGRectMake(35, 10, 165, 20);
55 | self.subtitleLabel.frame = CGRectMake(35, 30, 165, 16);
56 |
57 | self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
58 | self.subtitleLabel.font = [UIFont systemFontOfSize:12];
59 | }
60 |
61 | - (void)setCellForegroundColor:(UIColor *)foregroundColor {
62 | titleLabel.textColor = foregroundColor;
63 | subtitleLabel.textColor = [UIColor colorWithWhite:0.9 alpha:1.0];
64 | }
65 |
66 | - (void)setCellBackgroundColor:(UIColor *) backgroundColor {
67 | self.contentView.backgroundColor = backgroundColor;
68 | }
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/SubRow/ChildCell/SubTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableViewCell.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "SubTableViewCell.h"
10 |
11 | @implementation SubTableViewCell
12 | @synthesize titleLabel;
13 | @synthesize subtitleLabel;
14 |
15 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
16 |
17 | self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
18 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
19 | [[self contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
20 |
21 | if (!self)
22 | return self;
23 |
24 | self.contentView.backgroundColor = [UIColor whiteColor];
25 |
26 | self.selectionStyle = UITableViewCellSelectionStyleNone;
27 |
28 | self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
29 | titleLabel.backgroundColor = [UIColor clearColor];
30 | titleLabel.opaque = NO;
31 | titleLabel.textColor = [UIColor blackColor];
32 | titleLabel.textAlignment = NSTextAlignmentLeft;
33 | [self.contentView addSubview:titleLabel];
34 |
35 | self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
36 | subtitleLabel.backgroundColor = [UIColor clearColor];
37 | subtitleLabel.opaque = NO;
38 | subtitleLabel.textColor = [UIColor blackColor];
39 | subtitleLabel.textAlignment = NSTextAlignmentLeft;
40 | [self.contentView addSubview:subtitleLabel];
41 |
42 | return self;
43 | }
44 |
45 | - (void)layoutSubviews {
46 | [super layoutSubviews];
47 | [self setupDisplay];
48 | }
49 |
50 | - (void)setupDisplay {
51 |
52 | [self.contentView setAutoresizesSubviews:YES];
53 |
54 | self.titleLabel.frame = CGRectMake(35, 10, 165, 20);
55 | self.subtitleLabel.frame = CGRectMake(35, 30, 165, 16);
56 |
57 | self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
58 | self.subtitleLabel.font = [UIFont systemFontOfSize:12];
59 | }
60 |
61 | - (void)setCellForegroundColor:(UIColor *)foregroundColor {
62 | titleLabel.textColor = foregroundColor;
63 | subtitleLabel.textColor = [UIColor colorWithWhite:0.9 alpha:1.0];
64 | }
65 |
66 | - (void)setCellBackgroundColor:(UIColor *) backgroundColor {
67 | self.contentView.backgroundColor = backgroundColor;
68 | }
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "ViewController.h"
11 |
12 | @implementation AppDelegate
13 |
14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
15 |
16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
17 | // Override point for customization after application launch.
18 | self.window.backgroundColor = [UIColor whiteColor];
19 |
20 | ViewController *vc = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
21 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
22 | nav.navigationBar.barStyle = UIBarStyleBlack;
23 | nav.navigationBar.translucent = YES;
24 | self.window.rootViewController = nav;
25 | [self.window makeKeyAndVisible];
26 |
27 | return YES;
28 | }
29 |
30 | - (void)applicationWillResignActive:(UIApplication *)application {
31 |
32 | // 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.
33 | // 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.
34 | }
35 | - (void)applicationDidEnterBackground:(UIApplication *)application {
36 |
37 | // 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.
38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
39 | }
40 | - (void)applicationWillEnterForeground:(UIApplication *)application {
41 |
42 | // 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.
43 | }
44 | - (void)applicationDidBecomeActive:(UIApplication *)application {
45 |
46 | // 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.
47 | }
48 | - (void)applicationWillTerminate:(UIApplication *)application {
49 |
50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
51 | }
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SubTable
2 | A lightweight subclass of UITableView with Expandable/Collapsible rows. Implemented by inserting a cell below an expanded parent cell to act as a container. The container is adjusted to fit the height of the combined row heights of all child row heights in the nested table view. Both the parent row and child row heights can be adjusted to suit your needs.
3 |
4 | ## Features
5 | * A UITableView subclass implemented using a second, nested table view
6 | * Support for custom and independent row heights for parent and child table views
7 | * Recycled cells for both parent and child table views, allowing for high performance at large numbers of parents and children
8 | * Easy to plug in and customize to fit your project
9 |
10 | ## Examples
11 | This repo contains an example project optimized for iPhone to use as a template for testing purposes
12 |
13 | 
14 |
15 | ## Usage
16 | The easiest way to install is by copying the SubTable directory to your project:
17 | Initialize a ParentTableView:
18 | ```objective-c
19 | ParentTableView *tableView = [[ParentTableView alloc] init];
20 | ```
21 | Optionally, add a UITableView to your xib file and set its class to `ParentTableView`
22 | Set your ViewController as it's delegate using:
23 | ```objective-c
24 | [self.tableView setDataSourceDelegate:self];
25 | [self.tableView setTableViewDelegate:self];
26 | ```
27 | Implement the following required delegate methods in your ViewController:
28 | ```objective-c
29 | - (NSInteger)numberOfParentCells;
30 | - (NSInteger)heightForParentRows;
31 | - (NSInteger)numberOfChildCellsUnderParentIndex:(NSInteger)parentIndex;
32 | - (NSInteger)heightForChildRows;
33 | ```
34 | ## License
35 |
36 | Copyright (c) 2014 Alex Koshy ajkoshy7@gmail.com
37 |
38 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
39 |
40 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
41 |
42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "ParentTableView.h"
11 | #import "ParentTableViewCell.h"
12 | #import "SubTableView.h"
13 | #import "SubTableViewCell.h"
14 |
15 | @interface ViewController ()
16 |
17 | @end
18 |
19 | @implementation ViewController
20 |
21 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
22 |
23 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
24 | if (self) {
25 | // Custom initialization
26 | self.title = @"SubTable";
27 | }
28 | return self;
29 | }
30 | - (void)viewDidLoad {
31 |
32 | [super viewDidLoad];
33 |
34 | [self.tableView setDataSourceDelegate:self];
35 | [self.tableView setTableViewDelegate:self];
36 | }
37 |
38 |
39 |
40 | #pragma mark - SubTableViewDelegate
41 |
42 | // @optional
43 | - (void)tableView:(UITableView *)tableView didSelectCellAtChildIndex:(NSInteger)childIndex withInParentCellIndex:(NSInteger)parentIndex {
44 | // ...
45 | }
46 | - (void)tableView:(UITableView *)tableView didDeselectCellAtChildIndex:(NSInteger)childIndex withInParentCellIndex:(NSInteger)parentIndex {
47 | // ...
48 | }
49 | - (void)tableView:(UITableView *)tableView didSelectParentCellAtIndex:(NSInteger)parentIndex {
50 | // ..
51 | }
52 |
53 |
54 | #pragma mark - SubTableDataSource - Parent
55 |
56 | // @required
57 | - (NSInteger)numberOfParentCells {
58 |
59 | return 50;
60 | }
61 | - (NSInteger)heightForParentRows {
62 |
63 | return 75;
64 | }
65 |
66 | // @optional
67 | - (NSString *)titleLabelForParentCellAtIndex:(NSInteger)parentIndex {
68 |
69 | return [NSString stringWithFormat:@"Parent %i",parentIndex + 1];
70 | }
71 | - (NSString *)subtitleLabelForParentCellAtIndex:(NSInteger)parentIndex {
72 |
73 | NSInteger childCount = [self numberOfChildCellsUnderParentIndex:parentIndex];
74 | if (childCount > 1)
75 | return [NSString stringWithFormat:@"%i children", (int)childCount];
76 | else if (childCount == 1)
77 | return [NSString stringWithFormat:@"%i child", (int)childCount];
78 | else
79 | return @"No children";
80 | }
81 |
82 |
83 |
84 | #pragma mark - SubTableDataSource - Child
85 |
86 | // @required
87 | - (NSInteger)numberOfChildCellsUnderParentIndex:(NSInteger)parentIndex {
88 |
89 | return 5;
90 | }
91 | - (NSInteger)heightForChildRows {
92 |
93 | return 55;
94 | }
95 |
96 | // @optional
97 | - (NSString *)titleLabelForCellAtChildIndex:(NSInteger)childIndex withinParentCellIndex:(NSInteger)parentIndex {
98 |
99 | return [NSString stringWithFormat:@"Child %i",childIndex + 1];
100 | }
101 | - (NSString *)subtitleLabelForCellAtChildIndex:(NSInteger)childIndex withinParentCellIndex:(NSInteger)parentIndex {
102 |
103 | return [NSString stringWithFormat:@"nested under parent %i",parentIndex + 1];
104 | }
105 |
106 | @end
107 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/SubTableExample.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 |
--------------------------------------------------------------------------------
/SubTable/SubRow/SubTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableView.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "SubTableView.h"
10 | #import "SubTableViewCell.h"
11 |
12 | @implementation SubTableView
13 |
14 | @synthesize insideTableView;
15 |
16 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
17 |
18 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
19 | if (self) {
20 |
21 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
22 | [[self contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
23 | fgColor = [UIColor darkTextColor];
24 | bgColor = [UIColor clearColor];
25 | font = [UIFont systemFontOfSize:16.0];
26 | [self configureInsideTableView];
27 | }
28 | return self;
29 | }
30 |
31 |
32 |
33 | #pragma mark - Configuration
34 |
35 | - (void)configureInsideTableView {
36 |
37 | self.insideTableView = [[UITableView alloc] init];
38 | insideTableView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height);
39 |
40 | insideTableView.dataSource = self;
41 | insideTableView.delegate = self;
42 |
43 | [self.insideTableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
44 | insideTableView.scrollEnabled = NO;
45 |
46 | insideTableView.backgroundColor = [UIColor clearColor];
47 | insideTableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
48 | insideTableView.separatorColor = [UIColor colorWithWhite:( 70/255.0) alpha:1.0];
49 |
50 | [self.contentView addSubview:self.insideTableView];
51 | }
52 |
53 |
54 |
55 | #pragma mark - Getters/Setters
56 |
57 | /***
58 | * Delegate
59 | */
60 | - (id)getDelegate {
61 | return delegate;
62 | }
63 | // TODO combine set delegate and parentIndex into one method for better safety
64 | - (void)setDelegate:(id)deleg {
65 |
66 | delegate = deleg;
67 | NSInteger numberOfChild = [delegate numberOfChildrenUnderParentIndex:self.parentIndex];
68 | NSInteger rowHeight = [delegate heightForChildRows];
69 | insideTableView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, rowHeight * numberOfChild);
70 | }
71 |
72 | /***
73 | * Foreground
74 | */
75 | - (UIColor *)getSubTableForegroundColor {
76 | return fgColor;
77 | }
78 | - (void)setSubTableForegroundColor:(UIColor *)p_fgColor {
79 | fgColor = p_fgColor;
80 | }
81 |
82 | /***
83 | * Background
84 | */
85 | - (UIColor *)getSubTableBackgroundColor {
86 | return bgColor;
87 | }
88 | - (void)setSubTableBackgroundColor:(UIColor *)p_bgColor {
89 | bgColor = p_bgColor;
90 | }
91 |
92 | /***
93 | * Font
94 | */
95 | - (UIFont *)getSubTableFont {
96 | return font;
97 | }
98 | - (void)setSubTableFont:(UIFont *) p_font {
99 | font = p_font;
100 | }
101 |
102 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
103 | [super setSelected:selected animated:animated];
104 | }
105 | - (void)reload {
106 | [self.insideTableView reloadData];
107 | }
108 |
109 |
110 |
111 | #pragma mark - Table view data source
112 |
113 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
114 |
115 | return 1;
116 | }
117 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
118 |
119 | NSInteger count = [self.delegate numberOfChildrenUnderParentIndex:self.parentIndex];
120 | if (count > 0)
121 | return count;
122 | else
123 | return 1;
124 | }
125 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
126 |
127 | static NSString *CELL_IDENTIFIER = @"SubTableViewCell_Reuse_Id";
128 |
129 | SubTableViewCell *cell = (SubTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CELL_IDENTIFIER];
130 | if (cell == nil) {
131 | cell = [[SubTableViewCell alloc] initWithReuseIdentifier:CELL_IDENTIFIER];
132 | }
133 |
134 | NSInteger count = [self.delegate numberOfChildrenUnderParentIndex:self.parentIndex];
135 | if (count > 0) {
136 |
137 | NSInteger row = [indexPath row];
138 | cell.titleLabel.text = [self.delegate titleLabelForChildIndex:row underParentIndex:self.parentIndex];
139 | cell.subtitleLabel.text = [self.delegate subtitleLabelForChildIndex:row underParentIndex:self.parentIndex];
140 |
141 | [cell setCellBackgroundColor:[UIColor colorWithWhite:0.15 alpha:1.0]];
142 | [cell setCellForegroundColor:fgColor];
143 | [cell.titleLabel setFont:font];
144 |
145 | cell.selectionStyle = UITableViewCellSelectionStyleNone;
146 | return cell;
147 | }
148 | else {
149 |
150 | cell.titleLabel.text = @"";
151 | cell.subtitleLabel.text = @"";
152 |
153 | [cell setCellBackgroundColor:[UIColor colorWithWhite:0.15 alpha:1.0]];
154 | [cell setCellForegroundColor:fgColor];
155 |
156 | cell.selectionStyle = UITableViewCellSelectionStyleNone;
157 | return cell;
158 | }
159 | }
160 |
161 |
162 |
163 | #pragma mark - Table view delegate
164 |
165 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
166 |
167 | return [delegate heightForChildRows];
168 | }
169 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
170 | // must be implemented by concrete subclasses
171 | }
172 |
173 | @end
174 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/SubRow/SubTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // SubTableView.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "SubTableView.h"
10 | #import "SubTableViewCell.h"
11 |
12 | @implementation SubTableView
13 |
14 | @synthesize insideTableView;
15 |
16 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
17 |
18 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
19 | if (self) {
20 |
21 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
22 | [[self contentView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
23 | fgColor = [UIColor darkTextColor];
24 | bgColor = [UIColor clearColor];
25 | font = [UIFont systemFontOfSize:16.0];
26 | [self configureInsideTableView];
27 | }
28 | return self;
29 | }
30 |
31 |
32 |
33 | #pragma mark - Configuration
34 |
35 | - (void)configureInsideTableView {
36 |
37 | self.insideTableView = [[UITableView alloc] init];
38 | insideTableView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height);
39 |
40 | insideTableView.dataSource = self;
41 | insideTableView.delegate = self;
42 |
43 | [self.insideTableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
44 | insideTableView.scrollEnabled = NO;
45 |
46 | insideTableView.backgroundColor = [UIColor clearColor];
47 | insideTableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
48 | insideTableView.separatorColor = [UIColor colorWithWhite:( 70/255.0) alpha:1.0];
49 |
50 | [self.contentView addSubview:self.insideTableView];
51 | }
52 |
53 |
54 |
55 | #pragma mark - Getters/Setters
56 |
57 | /***
58 | * Delegate
59 | */
60 | - (id)getDelegate {
61 | return delegate;
62 | }
63 | // TODO combine set delegate and parentIndex into one method for better safety
64 | - (void)setDelegate:(id)deleg {
65 |
66 | delegate = deleg;
67 | NSInteger numberOfChild = [delegate numberOfChildrenUnderParentIndex:self.parentIndex];
68 | NSInteger rowHeight = [delegate heightForChildRows];
69 | insideTableView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, rowHeight * numberOfChild);
70 | }
71 |
72 | /***
73 | * Foreground
74 | */
75 | - (UIColor *)getSubTableForegroundColor {
76 | return fgColor;
77 | }
78 | - (void)setSubTableForegroundColor:(UIColor *)p_fgColor {
79 | fgColor = p_fgColor;
80 | }
81 |
82 | /***
83 | * Background
84 | */
85 | - (UIColor *)getSubTableBackgroundColor {
86 | return bgColor;
87 | }
88 | - (void)setSubTableBackgroundColor:(UIColor *)p_bgColor {
89 | bgColor = p_bgColor;
90 | }
91 |
92 | /***
93 | * Font
94 | */
95 | - (UIFont *)getSubTableFont {
96 | return font;
97 | }
98 | - (void)setSubTableFont:(UIFont *) p_font {
99 | font = p_font;
100 | }
101 |
102 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
103 | [super setSelected:selected animated:animated];
104 | }
105 | - (void)reload {
106 | [self.insideTableView reloadData];
107 | }
108 |
109 |
110 |
111 | #pragma mark - Table view data source
112 |
113 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
114 |
115 | return 1;
116 | }
117 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
118 |
119 | NSInteger count = [self.delegate numberOfChildrenUnderParentIndex:self.parentIndex];
120 | if (count > 0)
121 | return count;
122 | else
123 | return 1;
124 | }
125 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
126 |
127 | static NSString *CELL_IDENTIFIER = @"SubTableViewCell_Reuse_Id";
128 |
129 | SubTableViewCell *cell = (SubTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CELL_IDENTIFIER];
130 | if (cell == nil) {
131 | cell = [[SubTableViewCell alloc] initWithReuseIdentifier:CELL_IDENTIFIER];
132 | }
133 |
134 | NSInteger count = [self.delegate numberOfChildrenUnderParentIndex:self.parentIndex];
135 | if (count > 0) {
136 |
137 | NSInteger row = [indexPath row];
138 | cell.titleLabel.text = [self.delegate titleLabelForChildIndex:row underParentIndex:self.parentIndex];
139 | cell.subtitleLabel.text = [self.delegate subtitleLabelForChildIndex:row underParentIndex:self.parentIndex];
140 |
141 | [cell setCellBackgroundColor:[UIColor colorWithWhite:0.15 alpha:1.0]];
142 | [cell setCellForegroundColor:fgColor];
143 | [cell.titleLabel setFont:font];
144 |
145 | cell.selectionStyle = UITableViewCellSelectionStyleNone;
146 | return cell;
147 | }
148 | else {
149 |
150 | cell.titleLabel.text = @"";
151 | cell.subtitleLabel.text = @"";
152 |
153 | [cell setCellBackgroundColor:[UIColor colorWithWhite:0.15 alpha:1.0]];
154 | [cell setCellForegroundColor:fgColor];
155 |
156 | cell.selectionStyle = UITableViewCellSelectionStyleNone;
157 | return cell;
158 | }
159 | }
160 |
161 |
162 |
163 | #pragma mark - Table view delegate
164 |
165 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
166 |
167 | return [delegate heightForChildRows];
168 | }
169 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
170 | // must be implemented by concrete subclasses
171 | }
172 |
173 | @end
174 |
--------------------------------------------------------------------------------
/SubTable/ParentTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableView.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ParentTableView.h"
10 | #import "ParentTableViewCell.h"
11 | #import "ExpandedContainer.h"
12 |
13 | @interface ParentTableView () {
14 |
15 | ParentTableViewCell *previouslySelectedCell;
16 | }
17 |
18 | @end
19 |
20 | @implementation ParentTableView
21 | @synthesize tableViewDelegate, expansionStates;
22 |
23 | - (id)initWithFrame:(CGRect)frame dataSource:dataDelegate tableViewDelegate:tableDelegate {
24 |
25 | self = [super initWithFrame:frame style:UITableViewStylePlain];
26 | if (self) {
27 | // Initialization code
28 | [self initialize];
29 | }
30 | return self;
31 | }
32 | - (id)initWithCoder:(NSCoder *)coder {
33 |
34 | self = [super initWithCoder:coder];
35 | if (self) {
36 | // Initialization code
37 | [self initialize];
38 | }
39 | return self;
40 | }
41 | - (void)initialize {
42 |
43 | [self setDataSource:self];
44 | [self setDelegate:self];
45 |
46 | self.backgroundColor = [UIColor colorWithWhite:( 20/255.0) alpha:1.0];
47 | self.separatorStyle = UITableViewCellSeparatorStyleNone;
48 | self.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
49 | self.separatorColor = [UIColor darkGrayColor];
50 |
51 | UIView *footer = [[UIView alloc] initWithFrame:CGRectZero];
52 | self.tableFooterView = footer;
53 | }
54 |
55 |
56 |
57 | #pragma mark - Configuration
58 |
59 | - (id)getDataSourceDelegate {
60 |
61 | return dataSourceDelegate;
62 | }
63 | - (void)setDataSourceDelegate:(id)deleg {
64 |
65 | dataSourceDelegate = deleg;
66 | [self initExpansionStates];
67 | }
68 | - (void)initExpansionStates {
69 |
70 | expansionStates = [[NSMutableArray alloc] initWithCapacity:[self.dataSourceDelegate numberOfParentCells]];
71 | for(int i = 0; i < [self.dataSourceDelegate numberOfParentCells]; i++) {
72 | [expansionStates addObject:@"NO"];
73 | }
74 | }
75 |
76 |
77 |
78 | #pragma mark - Table Interaction
79 |
80 | - (void)expandForParentAtRow:(NSInteger)row {
81 |
82 | NSUInteger parentIndex = [self parentIndexForRow:row];
83 |
84 | if ([[self.expansionStates objectAtIndex:parentIndex] boolValue]) {
85 | return;
86 | }
87 |
88 | // update expansionStates so backing data is ready before calling insertRowsAtIndexPaths
89 | [self.expansionStates replaceObjectAtIndex:parentIndex withObject:@"YES"];
90 | [self insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(row + 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
91 | }
92 | - (void)collapseForParentAtRow:(NSInteger)row {
93 |
94 | if (![self.dataSourceDelegate numberOfParentCells] > 0) {
95 | return;
96 | }
97 |
98 | NSUInteger parentIndex = [self parentIndexForRow:row];
99 |
100 | if (![[self.expansionStates objectAtIndex:parentIndex] boolValue]) {
101 | return;
102 | }
103 |
104 | // update expansionStates so backing data is ready before calling deleteRowsAtIndexPaths
105 | [self.expansionStates replaceObjectAtIndex:parentIndex withObject:@"NO"];
106 | [self deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(row + 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
107 | }
108 | - (void)collapseAllRows {
109 |
110 | if ([self.expansionStates containsObject:@"YES"]) {
111 |
112 | NSInteger row = [self.expansionStates indexOfObject:@"YES"];
113 |
114 | [self.expansionStates replaceObjectAtIndex:row withObject:@"NO"];
115 | [self deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(row + 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
116 | }
117 | }
118 |
119 |
120 |
121 | #pragma mark - Table Information
122 |
123 | - (NSUInteger)rowForParentIndex:(NSUInteger)parentIndex {
124 |
125 | NSUInteger row = 0;
126 | NSUInteger currentParentIndex = 0;
127 |
128 | if (parentIndex == 0) {
129 | return 0;
130 | }
131 |
132 | while (currentParentIndex < parentIndex) {
133 | BOOL expanded = [[self.expansionStates objectAtIndex:currentParentIndex] boolValue];
134 | if (expanded) {
135 | row++;
136 | }
137 | currentParentIndex++;
138 | row++;
139 | }
140 | return row;
141 | }
142 | - (NSUInteger)parentIndexForRow:(NSUInteger)row {
143 |
144 | NSUInteger parentIndex = -1;
145 |
146 | NSUInteger i = 0;
147 | while (i <= row) {
148 | parentIndex++;
149 | i++;
150 | if ([[self.expansionStates objectAtIndex:parentIndex] boolValue]) {
151 | i++;
152 | }
153 | }
154 | return parentIndex;
155 | }
156 | - (BOOL)isExpansionCell:(NSUInteger)row {
157 |
158 | if (row < 1) {
159 | return NO;
160 | }
161 | NSUInteger parentIndex = [self parentIndexForRow:row];
162 | NSUInteger parentIndex2 = [self parentIndexForRow:(row-1)];
163 | return (parentIndex == parentIndex2);
164 | }
165 |
166 |
167 |
168 | #pragma mark - UITableViewDataSource
169 |
170 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
171 |
172 | NSInteger row = indexPath.row;
173 | NSInteger rowHeight = [self.dataSourceDelegate heightForParentRows];
174 |
175 | BOOL isExpansionCell = [self isExpansionCell:row];
176 | if (isExpansionCell) {
177 |
178 | NSInteger parentIndex = [self parentIndexForRow:row];
179 | NSInteger numberOfChildren = [self.dataSourceDelegate numberOfChildCellsUnderParentIndex:parentIndex];
180 | NSInteger childRowHeight = [self.dataSourceDelegate heightForChildRows];
181 | return childRowHeight * numberOfChildren;
182 | }
183 | else
184 | return rowHeight;
185 | }
186 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
187 |
188 | return 1;
189 | }
190 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
191 |
192 | if (![self.dataSourceDelegate numberOfParentCells] > 0) {
193 | return 0;
194 | }
195 |
196 | // returns sum of parent cells and expanded cells
197 | NSInteger parentCount = [self.dataSourceDelegate numberOfParentCells];
198 | NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:self.expansionStates];
199 | NSUInteger expandedParentCount = [countedSet countForObject:@"YES"];
200 |
201 | return parentCount + expandedParentCount;
202 | }
203 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
204 |
205 | static NSString *PARENT_IDENTIFIER = @"CellReuseId_Parent";
206 | static NSString *CHILD_CONTAINER_IDENTIFIER = @"CellReuseId_Container";
207 |
208 | NSInteger row = indexPath.row;
209 | NSUInteger parentIndex = [self parentIndexForRow:row];
210 | BOOL isParentCell = ![self isExpansionCell:row];
211 |
212 | if (isParentCell) {
213 |
214 | ParentTableViewCell *cell = (ParentTableViewCell *)[self dequeueReusableCellWithIdentifier:PARENT_IDENTIFIER];
215 | if (cell == nil) {
216 | cell = [[ParentTableViewCell alloc] initWithReuseIdentifier:PARENT_IDENTIFIER];
217 | }
218 |
219 | cell.titleLabel.text = [self.dataSourceDelegate titleLabelForParentCellAtIndex:parentIndex];
220 | [cell.titleLabel setFont:[UIFont boldSystemFontOfSize:19]];
221 |
222 | cell.subtitleLabel.text = [self.dataSourceDelegate subtitleLabelForParentCellAtIndex:parentIndex];
223 | [cell.subtitleLabel setFont:[UIFont systemFontOfSize:13]];
224 |
225 | [cell setCellForegroundColor:[UIColor whiteColor]];
226 | [cell setCellBackgroundColor:[UIColor colorWithWhite:( 30/255.0) alpha:1.0]];
227 | [cell setParentIndex:parentIndex];
228 | cell.tag = parentIndex;
229 |
230 | [self deselectCell:cell];
231 | if ([[self.expansionStates objectAtIndex:[cell parentIndex]] boolValue])
232 | [self selectCell:cell];
233 |
234 | return cell;
235 | }
236 | else {
237 |
238 | ExpandedContainer *cell = (ExpandedContainer *)[self dequeueReusableCellWithIdentifier:CHILD_CONTAINER_IDENTIFIER];
239 | if (cell == nil) {
240 | cell = [[ExpandedContainer alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CHILD_CONTAINER_IDENTIFIER];
241 | }
242 |
243 | [cell setSubTableForegroundColor:[UIColor whiteColor]];
244 | [cell setSubTableBackgroundColor:[UIColor colorWithWhite:( 30/255.0) alpha:1.0]];
245 | [cell setParentIndex:parentIndex];
246 |
247 | [cell setDelegate:self];
248 | [cell reload];
249 |
250 | return cell;
251 | }
252 | }
253 |
254 |
255 |
256 | #pragma mark - Table view - Cell Selection
257 |
258 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
259 |
260 | UITableViewCell *selectedPCell = [tableView cellForRowAtIndexPath:indexPath];
261 | if ([selectedPCell isKindOfClass:[ParentTableViewCell class]]) {
262 |
263 | ParentTableViewCell *pCell = (ParentTableViewCell *)selectedPCell;
264 | self.selectedRow = [pCell parentIndex];
265 |
266 | if ([[self.expansionStates objectAtIndex:[pCell parentIndex]] boolValue]) {
267 |
268 | // clicked an already expanded cell
269 | [self collapseForParentAtRow:indexPath.row];
270 | [self deselectCell:pCell];
271 | previouslySelectedCell = nil;
272 | }
273 | else {
274 |
275 | // clicked a collapsed cell
276 | [self collapseAllRows];
277 | [self expandForParentAtRow:[pCell parentIndex]];
278 |
279 | [self deselectCell:previouslySelectedCell];
280 | previouslySelectedCell = pCell;
281 | [self selectCell:previouslySelectedCell];
282 | }
283 |
284 | if ([self.tableViewDelegate respondsToSelector:@selector(tableView:didSelectParentCellAtIndex:)]) {
285 | [self.tableViewDelegate tableView:tableView didSelectParentCellAtIndex:[pCell parentIndex]];
286 | }
287 | }
288 | }
289 | - (void)selectCell:(ParentTableViewCell *)cell {
290 |
291 | cell.titleLabel.textColor = [UIColor whiteColor];
292 | cell.subtitleLabel.textColor = [UIColor colorWithWhite:0.98 alpha:1.0];
293 | }
294 | - (void)deselectCell:(ParentTableViewCell *)cell {
295 |
296 | cell.titleLabel.textColor = [UIColor colorWithWhite:0.85 alpha:1.0];
297 | cell.subtitleLabel.textColor = [UIColor colorWithWhite:0.85 alpha:1.0];
298 | }
299 |
300 |
301 |
302 | # pragma mark - TableView - Section
303 |
304 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
305 |
306 | return 30;
307 | }
308 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
309 |
310 | return @"click to expand";
311 | }
312 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
313 |
314 | NSString *oldSectionTitle = [self tableView:tableView titleForHeaderInSection:section];
315 | NSString *sectionTitle = [NSString stringWithFormat:@" %@",oldSectionTitle];
316 | if (sectionTitle == nil) {
317 | return nil;
318 | }
319 |
320 | UILabel *label = [[UILabel alloc] init];
321 | label.frame = CGRectMake(0, 0, 320, 30);
322 | label.backgroundColor = [UIColor colorWithWhite:( 20/255.0) alpha:1.0];
323 | label.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
324 | label.shadowColor = [UIColor darkGrayColor];
325 | label.shadowOffset = CGSizeMake(-1.0, 1.0);
326 | label.font = [UIFont systemFontOfSize:17];
327 | label.text = sectionTitle;
328 |
329 | UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 28, 320, 2)];
330 | bottomLine.backgroundColor = [UIColor colorWithWhite:( 50/255.0) alpha:1.0];
331 |
332 | UIView *view = [[UIView alloc] init];
333 | [view addSubview:label];
334 | [view addSubview:bottomLine];
335 |
336 | return view;
337 | }
338 |
339 |
340 |
341 | #pragma mark - SubRow Delegate
342 |
343 | // @required
344 | - (NSInteger)numberOfChildrenUnderParentIndex:(NSInteger)parentIndex {
345 |
346 | return [self.dataSourceDelegate numberOfChildCellsUnderParentIndex:parentIndex];
347 | }
348 | - (NSInteger)heightForChildRows {
349 |
350 | return [self.dataSourceDelegate heightForChildRows];
351 | }
352 |
353 | // @optional
354 | - (void)didSelectRowAtChildIndex:(NSInteger)childIndex
355 | underParentIndex:(NSInteger)parentIndex {
356 |
357 | NSIndexPath * indexPath = [NSIndexPath indexPathForRow:[self rowForParentIndex:parentIndex] inSection:0];
358 | UITableViewCell *selectedCell = [self cellForRowAtIndexPath:indexPath];
359 | if ([selectedCell isKindOfClass:[ParentTableViewCell class]]) {
360 |
361 | // ParentTableViewCell * pCell = (ParentTableViewCell *)selectedCell;
362 |
363 | // Insert code here to detect and handle child cell selection
364 | // ...
365 | }
366 | }
367 | - (NSString *)titleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex {
368 |
369 | return [self.dataSourceDelegate titleLabelForCellAtChildIndex:childIndex withinParentCellIndex:parentIndex];
370 | }
371 | - (NSString *)subtitleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex {
372 |
373 | return [self.dataSourceDelegate subtitleLabelForCellAtChildIndex:childIndex withinParentCellIndex:parentIndex];
374 | }
375 |
376 | @end
377 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample/SubTable/ParentTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ParentTableView.m
3 | // SubTableExample
4 | //
5 | // Created by Alex Koshy on 7/16/14.
6 | // Copyright (c) 2014 ajkoshy7. All rights reserved.
7 | //
8 |
9 | #import "ParentTableView.h"
10 | #import "ParentTableViewCell.h"
11 | #import "ExpandedContainer.h"
12 |
13 | @interface ParentTableView () {
14 |
15 | ParentTableViewCell *previouslySelectedCell;
16 | }
17 |
18 | @end
19 |
20 | @implementation ParentTableView
21 | @synthesize tableViewDelegate, expansionStates;
22 |
23 | - (id)initWithFrame:(CGRect)frame dataSource:dataDelegate tableViewDelegate:tableDelegate {
24 |
25 | self = [super initWithFrame:frame style:UITableViewStylePlain];
26 | if (self) {
27 | // Initialization code
28 | [self initialize];
29 | }
30 | return self;
31 | }
32 | - (id)initWithCoder:(NSCoder *)coder {
33 |
34 | self = [super initWithCoder:coder];
35 | if (self) {
36 | // Initialization code
37 | [self initialize];
38 | }
39 | return self;
40 | }
41 | - (void)initialize {
42 |
43 | [self setDataSource:self];
44 | [self setDelegate:self];
45 |
46 | self.backgroundColor = [UIColor colorWithWhite:( 20/255.0) alpha:1.0];
47 | self.separatorStyle = UITableViewCellSeparatorStyleNone;
48 | self.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
49 | self.separatorColor = [UIColor darkGrayColor];
50 |
51 | UIView *footer = [[UIView alloc] initWithFrame:CGRectZero];
52 | self.tableFooterView = footer;
53 | }
54 |
55 |
56 |
57 | #pragma mark - Configuration
58 |
59 | - (id)getDataSourceDelegate {
60 |
61 | return dataSourceDelegate;
62 | }
63 | - (void)setDataSourceDelegate:(id)deleg {
64 |
65 | dataSourceDelegate = deleg;
66 | [self initExpansionStates];
67 | }
68 | - (void)initExpansionStates {
69 |
70 | expansionStates = [[NSMutableArray alloc] initWithCapacity:[self.dataSourceDelegate numberOfParentCells]];
71 | for(int i = 0; i < [self.dataSourceDelegate numberOfParentCells]; i++) {
72 | [expansionStates addObject:@"NO"];
73 | }
74 | }
75 |
76 |
77 |
78 | #pragma mark - Table Interaction
79 |
80 | - (void)expandForParentAtRow:(NSInteger)row {
81 |
82 | NSUInteger parentIndex = [self parentIndexForRow:row];
83 |
84 | if ([[self.expansionStates objectAtIndex:parentIndex] boolValue]) {
85 | return;
86 | }
87 |
88 | // update expansionStates so backing data is ready before calling insertRowsAtIndexPaths
89 | [self.expansionStates replaceObjectAtIndex:parentIndex withObject:@"YES"];
90 | [self insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(row + 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
91 | }
92 | - (void)collapseForParentAtRow:(NSInteger)row {
93 |
94 | if (![self.dataSourceDelegate numberOfParentCells] > 0) {
95 | return;
96 | }
97 |
98 | NSUInteger parentIndex = [self parentIndexForRow:row];
99 |
100 | if (![[self.expansionStates objectAtIndex:parentIndex] boolValue]) {
101 | return;
102 | }
103 |
104 | // update expansionStates so backing data is ready before calling deleteRowsAtIndexPaths
105 | [self.expansionStates replaceObjectAtIndex:parentIndex withObject:@"NO"];
106 | [self deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(row + 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
107 | }
108 | - (void)collapseAllRows {
109 |
110 | if ([self.expansionStates containsObject:@"YES"]) {
111 |
112 | NSInteger row = [self.expansionStates indexOfObject:@"YES"];
113 |
114 | [self.expansionStates replaceObjectAtIndex:row withObject:@"NO"];
115 | [self deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(row + 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
116 | }
117 | }
118 |
119 |
120 |
121 | #pragma mark - Table Information
122 |
123 | - (NSUInteger)rowForParentIndex:(NSUInteger)parentIndex {
124 |
125 | NSUInteger row = 0;
126 | NSUInteger currentParentIndex = 0;
127 |
128 | if (parentIndex == 0) {
129 | return 0;
130 | }
131 |
132 | while (currentParentIndex < parentIndex) {
133 | BOOL expanded = [[self.expansionStates objectAtIndex:currentParentIndex] boolValue];
134 | if (expanded) {
135 | row++;
136 | }
137 | currentParentIndex++;
138 | row++;
139 | }
140 | return row;
141 | }
142 | - (NSUInteger)parentIndexForRow:(NSUInteger)row {
143 |
144 | NSUInteger parentIndex = -1;
145 |
146 | NSUInteger i = 0;
147 | while (i <= row) {
148 | parentIndex++;
149 | i++;
150 | if ([[self.expansionStates objectAtIndex:parentIndex] boolValue]) {
151 | i++;
152 | }
153 | }
154 | return parentIndex;
155 | }
156 | - (BOOL)isExpansionCell:(NSUInteger)row {
157 |
158 | if (row < 1) {
159 | return NO;
160 | }
161 | NSUInteger parentIndex = [self parentIndexForRow:row];
162 | NSUInteger parentIndex2 = [self parentIndexForRow:(row-1)];
163 | return (parentIndex == parentIndex2);
164 | }
165 |
166 |
167 |
168 | #pragma mark - UITableViewDataSource
169 |
170 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
171 |
172 | NSInteger row = indexPath.row;
173 | NSInteger rowHeight = [self.dataSourceDelegate heightForParentRows];
174 |
175 | BOOL isExpansionCell = [self isExpansionCell:row];
176 | if (isExpansionCell) {
177 |
178 | NSInteger parentIndex = [self parentIndexForRow:row];
179 | NSInteger numberOfChildren = [self.dataSourceDelegate numberOfChildCellsUnderParentIndex:parentIndex];
180 | NSInteger childRowHeight = [self.dataSourceDelegate heightForChildRows];
181 | return childRowHeight * numberOfChildren;
182 | }
183 | else
184 | return rowHeight;
185 | }
186 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
187 |
188 | return 1;
189 | }
190 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
191 |
192 | if (![self.dataSourceDelegate numberOfParentCells] > 0) {
193 | return 0;
194 | }
195 |
196 | // returns sum of parent cells and expanded cells
197 | NSInteger parentCount = [self.dataSourceDelegate numberOfParentCells];
198 | NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:self.expansionStates];
199 | NSUInteger expandedParentCount = [countedSet countForObject:@"YES"];
200 |
201 | return parentCount + expandedParentCount;
202 | }
203 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
204 |
205 | static NSString *PARENT_IDENTIFIER = @"CellReuseId_Parent";
206 | static NSString *CHILD_CONTAINER_IDENTIFIER = @"CellReuseId_Container";
207 |
208 | NSInteger row = indexPath.row;
209 | NSUInteger parentIndex = [self parentIndexForRow:row];
210 | BOOL isParentCell = ![self isExpansionCell:row];
211 |
212 | if (isParentCell) {
213 |
214 | ParentTableViewCell *cell = (ParentTableViewCell *)[self dequeueReusableCellWithIdentifier:PARENT_IDENTIFIER];
215 | if (cell == nil) {
216 | cell = [[ParentTableViewCell alloc] initWithReuseIdentifier:PARENT_IDENTIFIER];
217 | }
218 |
219 | cell.titleLabel.text = [self.dataSourceDelegate titleLabelForParentCellAtIndex:parentIndex];
220 | [cell.titleLabel setFont:[UIFont boldSystemFontOfSize:19]];
221 |
222 | cell.subtitleLabel.text = [self.dataSourceDelegate subtitleLabelForParentCellAtIndex:parentIndex];
223 | [cell.subtitleLabel setFont:[UIFont systemFontOfSize:13]];
224 |
225 | [cell setCellForegroundColor:[UIColor whiteColor]];
226 | [cell setCellBackgroundColor:[UIColor colorWithWhite:( 30/255.0) alpha:1.0]];
227 | [cell setParentIndex:parentIndex];
228 | cell.tag = parentIndex;
229 |
230 | [self deselectCell:cell];
231 | if ([[self.expansionStates objectAtIndex:[cell parentIndex]] boolValue])
232 | [self selectCell:cell];
233 |
234 | return cell;
235 | }
236 | else {
237 |
238 | ExpandedContainer *cell = (ExpandedContainer *)[self dequeueReusableCellWithIdentifier:CHILD_CONTAINER_IDENTIFIER];
239 | if (cell == nil) {
240 | cell = [[ExpandedContainer alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CHILD_CONTAINER_IDENTIFIER];
241 | }
242 |
243 | [cell setSubTableForegroundColor:[UIColor whiteColor]];
244 | [cell setSubTableBackgroundColor:[UIColor colorWithWhite:( 30/255.0) alpha:1.0]];
245 | [cell setParentIndex:parentIndex];
246 |
247 | [cell setDelegate:self];
248 | [cell reload];
249 |
250 | return cell;
251 | }
252 | }
253 |
254 |
255 |
256 | #pragma mark - Table view - Cell Selection
257 |
258 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
259 |
260 | UITableViewCell *selectedPCell = [tableView cellForRowAtIndexPath:indexPath];
261 | if ([selectedPCell isKindOfClass:[ParentTableViewCell class]]) {
262 |
263 | ParentTableViewCell *pCell = (ParentTableViewCell *)selectedPCell;
264 | self.selectedRow = [pCell parentIndex];
265 |
266 | if ([[self.expansionStates objectAtIndex:[pCell parentIndex]] boolValue]) {
267 |
268 | // clicked an already expanded cell
269 | [self collapseForParentAtRow:indexPath.row];
270 | [self deselectCell:pCell];
271 | previouslySelectedCell = nil;
272 | }
273 | else {
274 |
275 | // clicked a collapsed cell
276 | [self collapseAllRows];
277 | [self expandForParentAtRow:[pCell parentIndex]];
278 |
279 | [self deselectCell:previouslySelectedCell];
280 | previouslySelectedCell = pCell;
281 | [self selectCell:previouslySelectedCell];
282 | }
283 |
284 | if ([self.tableViewDelegate respondsToSelector:@selector(tableView:didSelectParentCellAtIndex:)]) {
285 | [self.tableViewDelegate tableView:tableView didSelectParentCellAtIndex:[pCell parentIndex]];
286 | }
287 | }
288 | }
289 | - (void)selectCell:(ParentTableViewCell *)cell {
290 |
291 | cell.titleLabel.textColor = [UIColor whiteColor];
292 | cell.subtitleLabel.textColor = [UIColor colorWithWhite:0.98 alpha:1.0];
293 | }
294 | - (void)deselectCell:(ParentTableViewCell *)cell {
295 |
296 | cell.titleLabel.textColor = [UIColor colorWithWhite:0.85 alpha:1.0];
297 | cell.subtitleLabel.textColor = [UIColor colorWithWhite:0.85 alpha:1.0];
298 | }
299 |
300 |
301 |
302 | # pragma mark - TableView - Section
303 |
304 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
305 |
306 | return 30;
307 | }
308 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
309 |
310 | return @"click to expand";
311 | }
312 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
313 |
314 | NSString *oldSectionTitle = [self tableView:tableView titleForHeaderInSection:section];
315 | NSString *sectionTitle = [NSString stringWithFormat:@" %@",oldSectionTitle];
316 | if (sectionTitle == nil) {
317 | return nil;
318 | }
319 |
320 | UILabel *label = [[UILabel alloc] init];
321 | label.frame = CGRectMake(0, 0, 320, 30);
322 | label.backgroundColor = [UIColor colorWithWhite:( 20/255.0) alpha:1.0];
323 | label.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
324 | label.shadowColor = [UIColor darkGrayColor];
325 | label.shadowOffset = CGSizeMake(-1.0, 1.0);
326 | label.font = [UIFont systemFontOfSize:17];
327 | label.text = sectionTitle;
328 |
329 | UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 28, 320, 2)];
330 | bottomLine.backgroundColor = [UIColor colorWithWhite:( 50/255.0) alpha:1.0];
331 |
332 | UIView *view = [[UIView alloc] init];
333 | [view addSubview:label];
334 | [view addSubview:bottomLine];
335 |
336 | return view;
337 | }
338 |
339 |
340 |
341 | #pragma mark - SubRow Delegate
342 |
343 | // @required
344 | - (NSInteger)numberOfChildrenUnderParentIndex:(NSInteger)parentIndex {
345 |
346 | return [self.dataSourceDelegate numberOfChildCellsUnderParentIndex:parentIndex];
347 | }
348 | - (NSInteger)heightForChildRows {
349 |
350 | return [self.dataSourceDelegate heightForChildRows];
351 | }
352 |
353 | // @optional
354 | - (void)didSelectRowAtChildIndex:(NSInteger)childIndex
355 | underParentIndex:(NSInteger)parentIndex {
356 |
357 | NSIndexPath * indexPath = [NSIndexPath indexPathForRow:[self rowForParentIndex:parentIndex] inSection:0];
358 | UITableViewCell *selectedCell = [self cellForRowAtIndexPath:indexPath];
359 | if ([selectedCell isKindOfClass:[ParentTableViewCell class]]) {
360 |
361 | // ParentTableViewCell * pCell = (ParentTableViewCell *)selectedCell;
362 |
363 | // Insert code here to detect and handle child cell selection
364 | // ...
365 | }
366 | }
367 | - (NSString *)titleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex {
368 |
369 | return [self.dataSourceDelegate titleLabelForCellAtChildIndex:childIndex withinParentCellIndex:parentIndex];
370 | }
371 | - (NSString *)subtitleLabelForChildIndex:(NSInteger)childIndex underParentIndex:(NSInteger)parentIndex {
372 |
373 | return [self.dataSourceDelegate subtitleLabelForCellAtChildIndex:childIndex withinParentCellIndex:parentIndex];
374 | }
375 |
376 | @end
377 |
--------------------------------------------------------------------------------
/SubTableExample/SubTableExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | FA4FB0DC1978D53800CAE647 /* ExpandedContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = FA4FB0DB1978D53800CAE647 /* ExpandedContainer.m */; };
11 | FAEF41A1197751FE00DC189F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAEF41A0197751FE00DC189F /* Foundation.framework */; };
12 | FAEF41A3197751FE00DC189F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAEF41A2197751FE00DC189F /* CoreGraphics.framework */; };
13 | FAEF41A5197751FE00DC189F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAEF41A4197751FE00DC189F /* UIKit.framework */; };
14 | FAEF41AB197751FE00DC189F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAEF41A9197751FE00DC189F /* InfoPlist.strings */; };
15 | FAEF41AD197751FE00DC189F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41AC197751FE00DC189F /* main.m */; };
16 | FAEF41B1197751FE00DC189F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41B0197751FE00DC189F /* AppDelegate.m */; };
17 | FAEF41B3197751FE00DC189F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FAEF41B2197751FE00DC189F /* Images.xcassets */; };
18 | FAEF41BA197751FE00DC189F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAEF41B9197751FE00DC189F /* XCTest.framework */; };
19 | FAEF41BB197751FE00DC189F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAEF41A0197751FE00DC189F /* Foundation.framework */; };
20 | FAEF41BC197751FE00DC189F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAEF41A4197751FE00DC189F /* UIKit.framework */; };
21 | FAEF41C4197751FE00DC189F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAEF41C2197751FE00DC189F /* InfoPlist.strings */; };
22 | FAEF41C6197751FE00DC189F /* SubTableExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41C5197751FE00DC189F /* SubTableExampleTests.m */; };
23 | FAEF41E0197752D800DC189F /* ParentTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41D1197752D800DC189F /* ParentTableView.m */; };
24 | FAEF41E1197752D800DC189F /* ParentTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41D4197752D800DC189F /* ParentTableViewCell.m */; };
25 | FAEF41E2197752D800DC189F /* SubTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41D7197752D800DC189F /* SubTableView.m */; };
26 | FAEF41E3197752D800DC189F /* SubTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41DA197752D800DC189F /* SubTableViewCell.m */; };
27 | FAEF41E91977530800DC189F /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEF41E71977530800DC189F /* ViewController.m */; };
28 | FAEF41EA1977530800DC189F /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAEF41E81977530800DC189F /* ViewController.xib */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | FAEF41BD197751FE00DC189F /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = FAEF4195197751FE00DC189F /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = FAEF419C197751FE00DC189F;
37 | remoteInfo = SubTableExample;
38 | };
39 | /* End PBXContainerItemProxy section */
40 |
41 | /* Begin PBXFileReference section */
42 | FA4FB0DA1978D53800CAE647 /* ExpandedContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpandedContainer.h; sourceTree = ""; };
43 | FA4FB0DB1978D53800CAE647 /* ExpandedContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExpandedContainer.m; sourceTree = ""; };
44 | FAEF419D197751FE00DC189F /* SubTableExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SubTableExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
45 | FAEF41A0197751FE00DC189F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
46 | FAEF41A2197751FE00DC189F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
47 | FAEF41A4197751FE00DC189F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
48 | FAEF41A8197751FE00DC189F /* SubTableExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SubTableExample-Info.plist"; sourceTree = ""; };
49 | FAEF41AA197751FE00DC189F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
50 | FAEF41AC197751FE00DC189F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
51 | FAEF41AE197751FE00DC189F /* SubTableExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SubTableExample-Prefix.pch"; sourceTree = ""; };
52 | FAEF41AF197751FE00DC189F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
53 | FAEF41B0197751FE00DC189F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
54 | FAEF41B2197751FE00DC189F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
55 | FAEF41B8197751FE00DC189F /* SubTableExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SubTableExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
56 | FAEF41B9197751FE00DC189F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
57 | FAEF41C1197751FE00DC189F /* SubTableExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SubTableExampleTests-Info.plist"; sourceTree = ""; };
58 | FAEF41C3197751FE00DC189F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
59 | FAEF41C5197751FE00DC189F /* SubTableExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SubTableExampleTests.m; sourceTree = ""; };
60 | FAEF41D0197752D800DC189F /* ParentTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParentTableView.h; sourceTree = ""; };
61 | FAEF41D1197752D800DC189F /* ParentTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ParentTableView.m; sourceTree = ""; };
62 | FAEF41D3197752D800DC189F /* ParentTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParentTableViewCell.h; sourceTree = ""; };
63 | FAEF41D4197752D800DC189F /* ParentTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ParentTableViewCell.m; sourceTree = ""; };
64 | FAEF41D6197752D800DC189F /* SubTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubTableView.h; sourceTree = ""; };
65 | FAEF41D7197752D800DC189F /* SubTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SubTableView.m; sourceTree = ""; };
66 | FAEF41D9197752D800DC189F /* SubTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubTableViewCell.h; sourceTree = ""; };
67 | FAEF41DA197752D800DC189F /* SubTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SubTableViewCell.m; sourceTree = ""; };
68 | FAEF41E61977530800DC189F /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
69 | FAEF41E71977530800DC189F /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
70 | FAEF41E81977530800DC189F /* ViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ViewController.xib; sourceTree = ""; };
71 | /* End PBXFileReference section */
72 |
73 | /* Begin PBXFrameworksBuildPhase section */
74 | FAEF419A197751FE00DC189F /* Frameworks */ = {
75 | isa = PBXFrameworksBuildPhase;
76 | buildActionMask = 2147483647;
77 | files = (
78 | FAEF41A3197751FE00DC189F /* CoreGraphics.framework in Frameworks */,
79 | FAEF41A5197751FE00DC189F /* UIKit.framework in Frameworks */,
80 | FAEF41A1197751FE00DC189F /* Foundation.framework in Frameworks */,
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | FAEF41B5197751FE00DC189F /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | FAEF41BA197751FE00DC189F /* XCTest.framework in Frameworks */,
89 | FAEF41BC197751FE00DC189F /* UIKit.framework in Frameworks */,
90 | FAEF41BB197751FE00DC189F /* Foundation.framework in Frameworks */,
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | /* End PBXFrameworksBuildPhase section */
95 |
96 | /* Begin PBXGroup section */
97 | FAEF4194197751FE00DC189F = {
98 | isa = PBXGroup;
99 | children = (
100 | FAEF41A6197751FE00DC189F /* SubTableExample */,
101 | FAEF41BF197751FE00DC189F /* SubTableExampleTests */,
102 | FAEF419F197751FE00DC189F /* Frameworks */,
103 | FAEF419E197751FE00DC189F /* Products */,
104 | );
105 | sourceTree = "";
106 | };
107 | FAEF419E197751FE00DC189F /* Products */ = {
108 | isa = PBXGroup;
109 | children = (
110 | FAEF419D197751FE00DC189F /* SubTableExample.app */,
111 | FAEF41B8197751FE00DC189F /* SubTableExampleTests.xctest */,
112 | );
113 | name = Products;
114 | sourceTree = "";
115 | };
116 | FAEF419F197751FE00DC189F /* Frameworks */ = {
117 | isa = PBXGroup;
118 | children = (
119 | FAEF41A0197751FE00DC189F /* Foundation.framework */,
120 | FAEF41A2197751FE00DC189F /* CoreGraphics.framework */,
121 | FAEF41A4197751FE00DC189F /* UIKit.framework */,
122 | FAEF41B9197751FE00DC189F /* XCTest.framework */,
123 | );
124 | name = Frameworks;
125 | sourceTree = "";
126 | };
127 | FAEF41A6197751FE00DC189F /* SubTableExample */ = {
128 | isa = PBXGroup;
129 | children = (
130 | FAEF41AF197751FE00DC189F /* AppDelegate.h */,
131 | FAEF41B0197751FE00DC189F /* AppDelegate.m */,
132 | FAEF41E61977530800DC189F /* ViewController.h */,
133 | FAEF41E71977530800DC189F /* ViewController.m */,
134 | FAEF41E81977530800DC189F /* ViewController.xib */,
135 | FAEF41CF197752D800DC189F /* SubTable */,
136 | FAEF41B2197751FE00DC189F /* Images.xcassets */,
137 | FAEF41A7197751FE00DC189F /* Supporting Files */,
138 | );
139 | path = SubTableExample;
140 | sourceTree = "";
141 | };
142 | FAEF41A7197751FE00DC189F /* Supporting Files */ = {
143 | isa = PBXGroup;
144 | children = (
145 | FAEF41A8197751FE00DC189F /* SubTableExample-Info.plist */,
146 | FAEF41A9197751FE00DC189F /* InfoPlist.strings */,
147 | FAEF41AC197751FE00DC189F /* main.m */,
148 | FAEF41AE197751FE00DC189F /* SubTableExample-Prefix.pch */,
149 | );
150 | name = "Supporting Files";
151 | sourceTree = "";
152 | };
153 | FAEF41BF197751FE00DC189F /* SubTableExampleTests */ = {
154 | isa = PBXGroup;
155 | children = (
156 | FAEF41C5197751FE00DC189F /* SubTableExampleTests.m */,
157 | FAEF41C0197751FE00DC189F /* Supporting Files */,
158 | );
159 | path = SubTableExampleTests;
160 | sourceTree = "";
161 | };
162 | FAEF41C0197751FE00DC189F /* Supporting Files */ = {
163 | isa = PBXGroup;
164 | children = (
165 | FAEF41C1197751FE00DC189F /* SubTableExampleTests-Info.plist */,
166 | FAEF41C2197751FE00DC189F /* InfoPlist.strings */,
167 | );
168 | name = "Supporting Files";
169 | sourceTree = "";
170 | };
171 | FAEF41CF197752D800DC189F /* SubTable */ = {
172 | isa = PBXGroup;
173 | children = (
174 | FAEF41D0197752D800DC189F /* ParentTableView.h */,
175 | FAEF41D1197752D800DC189F /* ParentTableView.m */,
176 | FAEF41D2197752D800DC189F /* ParentCell */,
177 | FAEF41D5197752D800DC189F /* SubRow */,
178 | );
179 | path = SubTable;
180 | sourceTree = "";
181 | };
182 | FAEF41D2197752D800DC189F /* ParentCell */ = {
183 | isa = PBXGroup;
184 | children = (
185 | FAEF41D3197752D800DC189F /* ParentTableViewCell.h */,
186 | FAEF41D4197752D800DC189F /* ParentTableViewCell.m */,
187 | );
188 | path = ParentCell;
189 | sourceTree = "";
190 | };
191 | FAEF41D5197752D800DC189F /* SubRow */ = {
192 | isa = PBXGroup;
193 | children = (
194 | FA4FB0DA1978D53800CAE647 /* ExpandedContainer.h */,
195 | FA4FB0DB1978D53800CAE647 /* ExpandedContainer.m */,
196 | FAEF41D6197752D800DC189F /* SubTableView.h */,
197 | FAEF41D7197752D800DC189F /* SubTableView.m */,
198 | FAEF41D8197752D800DC189F /* ChildCell */,
199 | );
200 | path = SubRow;
201 | sourceTree = "";
202 | };
203 | FAEF41D8197752D800DC189F /* ChildCell */ = {
204 | isa = PBXGroup;
205 | children = (
206 | FAEF41D9197752D800DC189F /* SubTableViewCell.h */,
207 | FAEF41DA197752D800DC189F /* SubTableViewCell.m */,
208 | );
209 | path = ChildCell;
210 | sourceTree = "";
211 | };
212 | /* End PBXGroup section */
213 |
214 | /* Begin PBXNativeTarget section */
215 | FAEF419C197751FE00DC189F /* SubTableExample */ = {
216 | isa = PBXNativeTarget;
217 | buildConfigurationList = FAEF41C9197751FE00DC189F /* Build configuration list for PBXNativeTarget "SubTableExample" */;
218 | buildPhases = (
219 | FAEF4199197751FE00DC189F /* Sources */,
220 | FAEF419A197751FE00DC189F /* Frameworks */,
221 | FAEF419B197751FE00DC189F /* Resources */,
222 | );
223 | buildRules = (
224 | );
225 | dependencies = (
226 | );
227 | name = SubTableExample;
228 | productName = SubTableExample;
229 | productReference = FAEF419D197751FE00DC189F /* SubTableExample.app */;
230 | productType = "com.apple.product-type.application";
231 | };
232 | FAEF41B7197751FE00DC189F /* SubTableExampleTests */ = {
233 | isa = PBXNativeTarget;
234 | buildConfigurationList = FAEF41CC197751FE00DC189F /* Build configuration list for PBXNativeTarget "SubTableExampleTests" */;
235 | buildPhases = (
236 | FAEF41B4197751FE00DC189F /* Sources */,
237 | FAEF41B5197751FE00DC189F /* Frameworks */,
238 | FAEF41B6197751FE00DC189F /* Resources */,
239 | );
240 | buildRules = (
241 | );
242 | dependencies = (
243 | FAEF41BE197751FE00DC189F /* PBXTargetDependency */,
244 | );
245 | name = SubTableExampleTests;
246 | productName = SubTableExampleTests;
247 | productReference = FAEF41B8197751FE00DC189F /* SubTableExampleTests.xctest */;
248 | productType = "com.apple.product-type.bundle.unit-test";
249 | };
250 | /* End PBXNativeTarget section */
251 |
252 | /* Begin PBXProject section */
253 | FAEF4195197751FE00DC189F /* Project object */ = {
254 | isa = PBXProject;
255 | attributes = {
256 | LastUpgradeCheck = 0510;
257 | ORGANIZATIONNAME = ajkoshy7;
258 | TargetAttributes = {
259 | FAEF41B7197751FE00DC189F = {
260 | TestTargetID = FAEF419C197751FE00DC189F;
261 | };
262 | };
263 | };
264 | buildConfigurationList = FAEF4198197751FE00DC189F /* Build configuration list for PBXProject "SubTableExample" */;
265 | compatibilityVersion = "Xcode 3.2";
266 | developmentRegion = English;
267 | hasScannedForEncodings = 0;
268 | knownRegions = (
269 | en,
270 | );
271 | mainGroup = FAEF4194197751FE00DC189F;
272 | productRefGroup = FAEF419E197751FE00DC189F /* Products */;
273 | projectDirPath = "";
274 | projectRoot = "";
275 | targets = (
276 | FAEF419C197751FE00DC189F /* SubTableExample */,
277 | FAEF41B7197751FE00DC189F /* SubTableExampleTests */,
278 | );
279 | };
280 | /* End PBXProject section */
281 |
282 | /* Begin PBXResourcesBuildPhase section */
283 | FAEF419B197751FE00DC189F /* Resources */ = {
284 | isa = PBXResourcesBuildPhase;
285 | buildActionMask = 2147483647;
286 | files = (
287 | FAEF41AB197751FE00DC189F /* InfoPlist.strings in Resources */,
288 | FAEF41EA1977530800DC189F /* ViewController.xib in Resources */,
289 | FAEF41B3197751FE00DC189F /* Images.xcassets in Resources */,
290 | );
291 | runOnlyForDeploymentPostprocessing = 0;
292 | };
293 | FAEF41B6197751FE00DC189F /* Resources */ = {
294 | isa = PBXResourcesBuildPhase;
295 | buildActionMask = 2147483647;
296 | files = (
297 | FAEF41C4197751FE00DC189F /* InfoPlist.strings in Resources */,
298 | );
299 | runOnlyForDeploymentPostprocessing = 0;
300 | };
301 | /* End PBXResourcesBuildPhase section */
302 |
303 | /* Begin PBXSourcesBuildPhase section */
304 | FAEF4199197751FE00DC189F /* Sources */ = {
305 | isa = PBXSourcesBuildPhase;
306 | buildActionMask = 2147483647;
307 | files = (
308 | FAEF41E91977530800DC189F /* ViewController.m in Sources */,
309 | FAEF41B1197751FE00DC189F /* AppDelegate.m in Sources */,
310 | FA4FB0DC1978D53800CAE647 /* ExpandedContainer.m in Sources */,
311 | FAEF41E2197752D800DC189F /* SubTableView.m in Sources */,
312 | FAEF41E0197752D800DC189F /* ParentTableView.m in Sources */,
313 | FAEF41E1197752D800DC189F /* ParentTableViewCell.m in Sources */,
314 | FAEF41AD197751FE00DC189F /* main.m in Sources */,
315 | FAEF41E3197752D800DC189F /* SubTableViewCell.m in Sources */,
316 | );
317 | runOnlyForDeploymentPostprocessing = 0;
318 | };
319 | FAEF41B4197751FE00DC189F /* Sources */ = {
320 | isa = PBXSourcesBuildPhase;
321 | buildActionMask = 2147483647;
322 | files = (
323 | FAEF41C6197751FE00DC189F /* SubTableExampleTests.m in Sources */,
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | };
327 | /* End PBXSourcesBuildPhase section */
328 |
329 | /* Begin PBXTargetDependency section */
330 | FAEF41BE197751FE00DC189F /* PBXTargetDependency */ = {
331 | isa = PBXTargetDependency;
332 | target = FAEF419C197751FE00DC189F /* SubTableExample */;
333 | targetProxy = FAEF41BD197751FE00DC189F /* PBXContainerItemProxy */;
334 | };
335 | /* End PBXTargetDependency section */
336 |
337 | /* Begin PBXVariantGroup section */
338 | FAEF41A9197751FE00DC189F /* InfoPlist.strings */ = {
339 | isa = PBXVariantGroup;
340 | children = (
341 | FAEF41AA197751FE00DC189F /* en */,
342 | );
343 | name = InfoPlist.strings;
344 | sourceTree = "";
345 | };
346 | FAEF41C2197751FE00DC189F /* InfoPlist.strings */ = {
347 | isa = PBXVariantGroup;
348 | children = (
349 | FAEF41C3197751FE00DC189F /* en */,
350 | );
351 | name = InfoPlist.strings;
352 | sourceTree = "";
353 | };
354 | /* End PBXVariantGroup section */
355 |
356 | /* Begin XCBuildConfiguration section */
357 | FAEF41C7197751FE00DC189F /* Debug */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ALWAYS_SEARCH_USER_PATHS = NO;
361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
362 | CLANG_CXX_LIBRARY = "libc++";
363 | CLANG_ENABLE_MODULES = YES;
364 | CLANG_ENABLE_OBJC_ARC = YES;
365 | CLANG_WARN_BOOL_CONVERSION = YES;
366 | CLANG_WARN_CONSTANT_CONVERSION = YES;
367 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
368 | CLANG_WARN_EMPTY_BODY = YES;
369 | CLANG_WARN_ENUM_CONVERSION = YES;
370 | CLANG_WARN_INT_CONVERSION = YES;
371 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
372 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
373 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
374 | COPY_PHASE_STRIP = NO;
375 | GCC_C_LANGUAGE_STANDARD = gnu99;
376 | GCC_DYNAMIC_NO_PIC = NO;
377 | GCC_OPTIMIZATION_LEVEL = 0;
378 | GCC_PREPROCESSOR_DEFINITIONS = (
379 | "DEBUG=1",
380 | "$(inherited)",
381 | );
382 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
385 | GCC_WARN_UNDECLARED_SELECTOR = YES;
386 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
387 | GCC_WARN_UNUSED_FUNCTION = YES;
388 | GCC_WARN_UNUSED_VARIABLE = YES;
389 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
390 | ONLY_ACTIVE_ARCH = YES;
391 | SDKROOT = iphoneos;
392 | TARGETED_DEVICE_FAMILY = "1,2";
393 | };
394 | name = Debug;
395 | };
396 | FAEF41C8197751FE00DC189F /* Release */ = {
397 | isa = XCBuildConfiguration;
398 | buildSettings = {
399 | ALWAYS_SEARCH_USER_PATHS = NO;
400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
401 | CLANG_CXX_LIBRARY = "libc++";
402 | CLANG_ENABLE_MODULES = YES;
403 | CLANG_ENABLE_OBJC_ARC = YES;
404 | CLANG_WARN_BOOL_CONVERSION = YES;
405 | CLANG_WARN_CONSTANT_CONVERSION = YES;
406 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
407 | CLANG_WARN_EMPTY_BODY = YES;
408 | CLANG_WARN_ENUM_CONVERSION = YES;
409 | CLANG_WARN_INT_CONVERSION = YES;
410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
411 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
412 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
413 | COPY_PHASE_STRIP = YES;
414 | ENABLE_NS_ASSERTIONS = NO;
415 | GCC_C_LANGUAGE_STANDARD = gnu99;
416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
418 | GCC_WARN_UNDECLARED_SELECTOR = YES;
419 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
420 | GCC_WARN_UNUSED_FUNCTION = YES;
421 | GCC_WARN_UNUSED_VARIABLE = YES;
422 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
423 | SDKROOT = iphoneos;
424 | TARGETED_DEVICE_FAMILY = "1,2";
425 | VALIDATE_PRODUCT = YES;
426 | };
427 | name = Release;
428 | };
429 | FAEF41CA197751FE00DC189F /* Debug */ = {
430 | isa = XCBuildConfiguration;
431 | buildSettings = {
432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
433 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
434 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
435 | GCC_PREFIX_HEADER = "SubTableExample/SubTableExample-Prefix.pch";
436 | INFOPLIST_FILE = "SubTableExample/SubTableExample-Info.plist";
437 | PRODUCT_NAME = "$(TARGET_NAME)";
438 | WRAPPER_EXTENSION = app;
439 | };
440 | name = Debug;
441 | };
442 | FAEF41CB197751FE00DC189F /* Release */ = {
443 | isa = XCBuildConfiguration;
444 | buildSettings = {
445 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
446 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
447 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
448 | GCC_PREFIX_HEADER = "SubTableExample/SubTableExample-Prefix.pch";
449 | INFOPLIST_FILE = "SubTableExample/SubTableExample-Info.plist";
450 | PRODUCT_NAME = "$(TARGET_NAME)";
451 | WRAPPER_EXTENSION = app;
452 | };
453 | name = Release;
454 | };
455 | FAEF41CD197751FE00DC189F /* Debug */ = {
456 | isa = XCBuildConfiguration;
457 | buildSettings = {
458 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SubTableExample.app/SubTableExample";
459 | FRAMEWORK_SEARCH_PATHS = (
460 | "$(SDKROOT)/Developer/Library/Frameworks",
461 | "$(inherited)",
462 | "$(DEVELOPER_FRAMEWORKS_DIR)",
463 | );
464 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
465 | GCC_PREFIX_HEADER = "SubTableExample/SubTableExample-Prefix.pch";
466 | GCC_PREPROCESSOR_DEFINITIONS = (
467 | "DEBUG=1",
468 | "$(inherited)",
469 | );
470 | INFOPLIST_FILE = "SubTableExampleTests/SubTableExampleTests-Info.plist";
471 | PRODUCT_NAME = "$(TARGET_NAME)";
472 | TEST_HOST = "$(BUNDLE_LOADER)";
473 | WRAPPER_EXTENSION = xctest;
474 | };
475 | name = Debug;
476 | };
477 | FAEF41CE197751FE00DC189F /* Release */ = {
478 | isa = XCBuildConfiguration;
479 | buildSettings = {
480 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SubTableExample.app/SubTableExample";
481 | FRAMEWORK_SEARCH_PATHS = (
482 | "$(SDKROOT)/Developer/Library/Frameworks",
483 | "$(inherited)",
484 | "$(DEVELOPER_FRAMEWORKS_DIR)",
485 | );
486 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
487 | GCC_PREFIX_HEADER = "SubTableExample/SubTableExample-Prefix.pch";
488 | INFOPLIST_FILE = "SubTableExampleTests/SubTableExampleTests-Info.plist";
489 | PRODUCT_NAME = "$(TARGET_NAME)";
490 | TEST_HOST = "$(BUNDLE_LOADER)";
491 | WRAPPER_EXTENSION = xctest;
492 | };
493 | name = Release;
494 | };
495 | /* End XCBuildConfiguration section */
496 |
497 | /* Begin XCConfigurationList section */
498 | FAEF4198197751FE00DC189F /* Build configuration list for PBXProject "SubTableExample" */ = {
499 | isa = XCConfigurationList;
500 | buildConfigurations = (
501 | FAEF41C7197751FE00DC189F /* Debug */,
502 | FAEF41C8197751FE00DC189F /* Release */,
503 | );
504 | defaultConfigurationIsVisible = 0;
505 | defaultConfigurationName = Release;
506 | };
507 | FAEF41C9197751FE00DC189F /* Build configuration list for PBXNativeTarget "SubTableExample" */ = {
508 | isa = XCConfigurationList;
509 | buildConfigurations = (
510 | FAEF41CA197751FE00DC189F /* Debug */,
511 | FAEF41CB197751FE00DC189F /* Release */,
512 | );
513 | defaultConfigurationIsVisible = 0;
514 | defaultConfigurationName = Release;
515 | };
516 | FAEF41CC197751FE00DC189F /* Build configuration list for PBXNativeTarget "SubTableExampleTests" */ = {
517 | isa = XCConfigurationList;
518 | buildConfigurations = (
519 | FAEF41CD197751FE00DC189F /* Debug */,
520 | FAEF41CE197751FE00DC189F /* Release */,
521 | );
522 | defaultConfigurationIsVisible = 0;
523 | defaultConfigurationName = Release;
524 | };
525 | /* End XCConfigurationList section */
526 | };
527 | rootObject = FAEF4195197751FE00DC189F /* Project object */;
528 | }
529 |
--------------------------------------------------------------------------------