├── .DS_Store
├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── LICENSE
├── Package.swift
├── README.md
├── Tests
├── LinuxMain.swift
└── ZHTableViewGroupTests
│ ├── XCTestManifests.swift
│ └── ZHTableViewGroupTests.swift
├── ZHTableViewGroupExample
├── ZHTableViewGroupExample.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── ZHTableViewGroupObjc.xcscheme
├── ZHTableViewGroupExample
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── HiddenViewController.h
│ ├── HiddenViewController.m
│ ├── Info.plist
│ ├── ReloadCellDataViewController.h
│ ├── ReloadCellDataViewController.m
│ ├── ReloadCellViewController.h
│ ├── ReloadCellViewController.m
│ ├── ReloadHeightViewController.h
│ ├── ReloadHeightViewController.m
│ ├── SceneDelegate.h
│ ├── SceneDelegate.m
│ ├── SetHeightViewController.h
│ ├── SetHeightViewController.m
│ ├── TableViewController.h
│ ├── TableViewController.m
│ ├── TableViewController.xib
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
└── ZHTableViewGroupObjc
│ ├── Info.plist
│ ├── ZHAutoConfigurationCollectionViewDelegate.h
│ ├── ZHAutoConfigurationCollectionViewDelegate.m
│ ├── ZHAutoConfigurationTableViewDelegate.h
│ ├── ZHAutoConfigurationTableViewDelegate.m
│ ├── ZHCollectionViewBaseModel.h
│ ├── ZHCollectionViewBaseModel.m
│ ├── ZHCollectionViewCell.h
│ ├── ZHCollectionViewCell.m
│ ├── ZHCollectionViewDataSource.h
│ ├── ZHCollectionViewDataSource.m
│ ├── ZHCollectionViewGroup.h
│ ├── ZHCollectionViewGroup.m
│ ├── ZHCollectionViewHeaderFooter.h
│ ├── ZHCollectionViewHeaderFooter.m
│ ├── ZHTableViewBaseModel.h
│ ├── ZHTableViewBaseModel.m
│ ├── ZHTableViewCell.h
│ ├── ZHTableViewCell.m
│ ├── ZHTableViewDataSource.h
│ ├── ZHTableViewDataSource.m
│ ├── ZHTableViewGroup.h
│ ├── ZHTableViewGroup.m
│ ├── ZHTableViewGroupObjc.h
│ ├── ZHTableViewHeaderFooter.h
│ ├── ZHTableViewHeaderFooter.m
│ └── include
│ ├── ZHAutoConfigurationCollectionViewDelegate.h
│ ├── ZHAutoConfigurationTableViewDelegate.h
│ ├── ZHCollectionViewBaseModel.h
│ ├── ZHCollectionViewCell.h
│ ├── ZHCollectionViewDataSource.h
│ ├── ZHCollectionViewGroup.h
│ ├── ZHCollectionViewHeaderFooter.h
│ ├── ZHTableViewBaseModel.h
│ ├── ZHTableViewCell.h
│ ├── ZHTableViewDataSource.h
│ ├── ZHTableViewGroup.h
│ ├── ZHTableViewGroupObjc.h
│ └── ZHTableViewHeaderFooter.h
├── ZHTableViewGroupObjc.podspec
└── images
├── 2019-08-20-034515.png
├── 2019-08-20-035055.png
├── image-20190820115521632.png
├── image-20190820115538881.png
├── image-20190820115647037.png
└── image-20190820115743952.png
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata/
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | Carthage
26 | # We recommend against adding the Pods directory to your .gitignore. However
27 | # you should judge for yourself, the pros and cons are mentioned at:
28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
29 | #
30 | # Note: if you ignore the Pods directory, make sure to uncomment
31 | # `pod install` in .travis.yml
32 | #
33 | # Pods/
34 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 15038777234 <15038777234@163.com>
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "ZHTableViewGroup",
8 | products: [
9 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
10 | .library(
11 | name: "ZHTableViewGroup",
12 | targets: ["ZHTableViewGroup"]),
13 | ],
14 | dependencies: [
15 | // Dependencies declare other packages that this package depends on.
16 | // .package(url: /* package url */, from: "1.0.0"),
17 | ],
18 | targets: [
19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
21 | .target(
22 | name: "ZHTableViewGroup",
23 | dependencies: [],
24 | path:"ZHTableViewGroupExample/ZHTableViewGroupObjc"),
25 | .testTarget(
26 | name: "ZHTableViewGroupTests",
27 | dependencies: ["ZHTableViewGroup"]),
28 | ]
29 | )
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | filename:images
3 | ---
4 |
5 |
6 |
7 | ## Swift 版本请移步[这里](https://github.com/josercc/SwiftTableViewGroup)
8 |
9 | `ZHTableViewGroup`为 `UITableView`和 `UICollectionView` 而生
10 |
11 | ## 演示
12 |
13 | ### 简单的列表
14 |
15 | 
16 |
17 | ```objc
18 | ZHTableViewDataSource *dataSource = [[ZHTableViewDataSource alloc] initWithTableView:self.tableView];
19 | [dataSource clearData];
20 | [dataSource addGroupWithCompletionHandle:^(ZHTableViewGroup * _Nonnull group) {
21 | [group addCellWithCompletionHandle:^(ZHTableViewCell *tableViewCell) {
22 | tableViewCell.anyClass = [UITableViewCell class];
23 | tableViewCell.identifier = @"UITableViewCell";
24 | NSArray *titles = @[@"刷新高度",@"刷新Cell",@"刷新数据",@"显示和隐藏"];
25 | tableViewCell.cellNumber = titles.count;
26 | [tableViewCell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
27 | cell.textLabel.text = titles[indexPath.row];
28 | }];
29 | }];
30 | }];
31 | [dataSource reloadTableViewData];
32 | ```
33 |
34 | ### 动态刷新高度
35 |
36 | 
37 |
38 | ```objc
39 | [self.tableViewDataSource clearData];
40 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
41 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
42 | self->_weakCell = cell;
43 | cell.anyClass = [ReloadHeightCell1 class];
44 | cell.identifier = @"ReloadHeightCell1";
45 | [cell setConfigCompletionHandle:^(ReloadHeightCell1 *cell1, NSIndexPath *indexPath) {
46 | cell1.textLabel.text = @"ReloadHeightCell1";
47 | }];
48 | }];
49 | }];
50 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
51 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
52 | cell.anyClass = [ReloadHeightCell2 class];
53 | cell.identifier = @"ReloadHeightCell2";
54 | cell.cellNumber = 2;
55 | [cell setConfigCompletionHandle:^(ReloadHeightCell2 *cell1, NSIndexPath *indexPath) {
56 | cell1.textLabel.text = @"ReloadHeightCell2";
57 | }];
58 | }];
59 | }];
60 | [self.tableViewDataSource reloadTableViewData];
61 | ```
62 |
63 | #### identifier更新自动高度
64 |
65 | ```objc
66 | [self.tableViewDataSource reloadCellAutomaticHeightWithIdentifier:@"ReloadHeightCell1"]
67 | ```
68 |
69 | #### identifier更新固定250高度
70 |
71 | ```objc
72 | [self.tableViewDataSource reloadCellFixedHeight:250 identifier:@"ReloadHeightCell1"]
73 | ```
74 |
75 | #### Class更新自动高度
76 |
77 | ```objc
78 | [self.tableViewDataSource reloadCellAutomaticHeightWithClass:NSClassFromString(@"ReloadHeightCell1")]
79 | ```
80 |
81 | #### Class更新固定260高度
82 |
83 | ```objc
84 | [self.tableViewDataSource reloadCellFixedHeight:260 className:NSClassFromString(@"ReloadHeightCell1")]
85 | ```
86 |
87 | #### 指定ZHTableViewCell更新自动高度
88 |
89 | ```objc
90 | [self.tableViewDataSource reloadCellAutomaticHeightWithTableViewCell:self.tableViewDataSource.groups[0].cells[0]]
91 | ```
92 |
93 | #### 指定ZHTableViewCell更新固定270高度
94 |
95 | ```objc
96 | [self.tableViewDataSource reloadCellFixedHeight:270 tableViewCell:self.tableViewDataSource.groups[0].cells[0]]
97 | ```
98 |
99 | #### 指定索引更新自动高度
100 |
101 | ```objc
102 | [self.tableViewDataSource reloadCellAutomicHeightWithGroupIndex:1 cellIndex:0]
103 | ```
104 |
105 | #### 指定索引更新固定280高度
106 |
107 | ```objc
108 | [self.tableViewDataSource reloadCellFixedHeight:280 groupIndex:1 cellIndex:0]
109 | ```
110 |
111 | ### 刷新值
112 |
113 | 
114 |
115 | ```objc
116 | [self.tableViewDataSource clearData];
117 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
118 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
119 | cell.anyClass = [UITableViewCell class];
120 | cell.identifier = @"UITableViewCell";
121 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
122 | cell.textLabel.text = [@(random() % 99 + 1) stringValue];
123 | }];
124 | }];
125 | }];
126 | [self.tableViewDataSource reloadTableViewData];
127 | ```
128 |
129 | #### 通过Identifier刷新
130 |
131 | ```objc
132 | [self.tableViewDataSource reloadCellWithIdentifier:@"UITableViewCell"]
133 | ```
134 |
135 | #### 通过Class刷新
136 |
137 | ```objc
138 | [self.tableViewDataSource reloadCellWithClassName:[UITableViewCell class]]
139 | ```
140 |
141 | #### 通过指定UITableViewCell更新
142 |
143 | ```objc
144 | [self.tableViewDataSource reloadCellWithTableViewCell:self.tableViewDataSource.groups[0].cells[0]]
145 | ```
146 |
147 | #### 通过索引更新
148 |
149 | ```objc
150 | [self.tableViewDataSource reloadCellWithGroupIndex:0 cellIndex:0]
151 | ```
152 |
153 | ### 刷新个数
154 |
155 | 
156 |
157 | ```objc
158 | _randoms = [NSMutableArray arrayWithArray:@[@"random"]];
159 | [self.tableViewDataSource clearData];
160 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
161 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
162 | cell.anyClass = [UITableViewCell class];
163 | cell.identifier = @"UITableViewCell";
164 | cell.cellNumber = _randoms.count;
165 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
166 | cell.textLabel.text = _randoms[indexPath.row];
167 | }];
168 | }];
169 | }];
170 | [self.tableViewDataSource reloadTableViewData];
171 | ```
172 |
173 | #### identifier刷新个数
174 |
175 | ```objc
176 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count identifier:@"UITableViewCell"]
177 | ```
178 |
179 | #### Class刷新个数
180 |
181 | ```objc
182 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count className:[UITableViewCell class]]
183 | ```
184 |
185 | #### UITableViewCell刷新个数
186 |
187 | ```swift
188 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count tableViewCell:self.tableViewDataSource.groups[0].cells[0]]
189 | ```
190 |
191 | #### 索引刷新个数
192 |
193 | ```objc
194 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count groupIndex:0 cellIndex:0]
195 | ```
196 |
197 | ### 显示和隐藏
198 |
199 | 
200 |
201 | ```objc
202 | [self.tableViewDataSource clearData];
203 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
204 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
205 | cell.anyClass = [UITableViewCell class];
206 | cell.identifier = @"UITableViewCell";
207 | cell.cellNumber = 10;
208 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
209 | cell.textLabel.text = [@(indexPath.row + 1) stringValue];
210 | }];
211 | [cell setHiddenBlock:^BOOL(NSIndexPath *indexPath) {
212 | return _hidden && indexPath.row >= 5 && indexPath.row <= 8;
213 | }];
214 | }];
215 | }];
216 | [self.tableViewDataSource reloadTableViewData];
217 | ```
218 |
219 | #### 隐藏Cell
220 |
221 | ```objc
222 | [self.tableViewDataSource reloadAllHiddenCell]
223 | ```
224 |
225 | ## 怎么安装
226 |
227 | ### Cocoapods
228 |
229 | ```ruby
230 | pod 'ZHTableViewGroup'
231 | ```
232 |
233 | ### Carthage
234 |
235 | ```ruby
236 | github "josercc/ZHTableViewGroup"
237 | ```
238 |
239 | ### Swift Package Manager
240 |
241 | ```swift
242 | .package(url: "https://github.com/josercc/ZHTableViewGroup.git", from: "3.0.0")
243 | ```
244 |
245 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import ZHTableViewGroupTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += ZHTableViewGroupTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/Tests/ZHTableViewGroupTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(ZHTableViewGroupTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Tests/ZHTableViewGroupTests/ZHTableViewGroupTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import ZHTableViewGroup
3 |
4 | final class ZHTableViewGroupTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | }
10 |
11 | static var allTests = [
12 | ("testExample", testExample),
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 17722FBC2404A78200CEC436 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 17722FBB2404A78200CEC436 /* AppDelegate.m */; };
11 | 17722FBF2404A78200CEC436 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 17722FBE2404A78200CEC436 /* SceneDelegate.m */; };
12 | 17722FC22404A78200CEC436 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17722FC12404A78200CEC436 /* ViewController.m */; };
13 | 17722FC52404A78200CEC436 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 17722FC32404A78200CEC436 /* Main.storyboard */; };
14 | 17722FC72404A78400CEC436 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 17722FC62404A78400CEC436 /* Assets.xcassets */; };
15 | 17722FCA2404A78400CEC436 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 17722FC82404A78400CEC436 /* LaunchScreen.storyboard */; };
16 | 17722FCD2404A78500CEC436 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 17722FCC2404A78500CEC436 /* main.m */; };
17 | 178360BE240E34A800FEEC2E /* ZHTableViewGroupObjc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 178360B7240E34A800FEEC2E /* ZHTableViewGroupObjc.framework */; };
18 | 178360BF240E34A800FEEC2E /* ZHTableViewGroupObjc.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 178360B7240E34A800FEEC2E /* ZHTableViewGroupObjc.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
19 | 178360DC240E34C100FEEC2E /* ZHCollectionViewBaseModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360C3240E34C000FEEC2E /* ZHCollectionViewBaseModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
20 | 178360DE240E34C100FEEC2E /* ZHCollectionViewBaseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360C5240E34C000FEEC2E /* ZHCollectionViewBaseModel.m */; };
21 | 178360DF240E34C100FEEC2E /* ZHTableViewHeaderFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360C6240E34C100FEEC2E /* ZHTableViewHeaderFooter.h */; settings = {ATTRIBUTES = (Public, ); }; };
22 | 178360E0240E34C100FEEC2E /* ZHCollectionViewGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360C7240E34C100FEEC2E /* ZHCollectionViewGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
23 | 178360E1240E34C100FEEC2E /* ZHTableViewBaseModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360C8240E34C100FEEC2E /* ZHTableViewBaseModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
24 | 178360E2240E34C100FEEC2E /* ZHTableViewDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360C9240E34C100FEEC2E /* ZHTableViewDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
25 | 178360E3240E34C100FEEC2E /* ZHCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360CA240E34C100FEEC2E /* ZHCollectionViewCell.m */; };
26 | 178360E4240E34C100FEEC2E /* ZHTableViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360CB240E34C100FEEC2E /* ZHTableViewDataSource.m */; };
27 | 178360E5240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360CC240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.m */; };
28 | 178360E6240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360CD240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.m */; };
29 | 178360E7240E34C100FEEC2E /* ZHTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360CE240E34C100FEEC2E /* ZHTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
30 | 178360E8240E34C100FEEC2E /* ZHTableViewGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360CF240E34C100FEEC2E /* ZHTableViewGroup.m */; };
31 | 178360E9240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360D0240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
32 | 178360EA240E34C100FEEC2E /* ZHTableViewGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360D1240E34C100FEEC2E /* ZHTableViewGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
33 | 178360EB240E34C100FEEC2E /* ZHTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360D2240E34C100FEEC2E /* ZHTableViewCell.m */; };
34 | 178360EC240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360D3240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
35 | 178360ED240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360D4240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.m */; };
36 | 178360EE240E34C100FEEC2E /* ZHCollectionViewGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360D5240E34C100FEEC2E /* ZHCollectionViewGroup.m */; };
37 | 178360EF240E34C100FEEC2E /* ZHCollectionViewDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360D6240E34C100FEEC2E /* ZHCollectionViewDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
38 | 178360F0240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360D7240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.h */; settings = {ATTRIBUTES = (Public, ); }; };
39 | 178360F1240E34C100FEEC2E /* ZHTableViewHeaderFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360D8240E34C100FEEC2E /* ZHTableViewHeaderFooter.m */; };
40 | 178360F2240E34C100FEEC2E /* ZHCollectionViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360D9240E34C100FEEC2E /* ZHCollectionViewDataSource.m */; };
41 | 178360F3240E34C100FEEC2E /* ZHTableViewBaseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 178360DA240E34C100FEEC2E /* ZHTableViewBaseModel.m */; };
42 | 178360F4240E34C100FEEC2E /* ZHCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 178360DB240E34C100FEEC2E /* ZHCollectionViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
43 | 17C9D6502404CACF00D7B871 /* ReloadHeightViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C9D64A2404C3F500D7B871 /* ReloadHeightViewController.m */; };
44 | 17C9D6592404F1F300D7B871 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C9D6572404F1F300D7B871 /* TableViewController.m */; };
45 | 17C9D65A2404F1F300D7B871 /* TableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17C9D6582404F1F300D7B871 /* TableViewController.xib */; };
46 | 17C9D65D2404FF0900D7B871 /* SetHeightViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C9D65C2404FF0900D7B871 /* SetHeightViewController.m */; };
47 | 17C9D660240514F900D7B871 /* ReloadCellViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C9D65F240514F900D7B871 /* ReloadCellViewController.m */; };
48 | 17C9D6632405198D00D7B871 /* ReloadCellDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C9D6622405198D00D7B871 /* ReloadCellDataViewController.m */; };
49 | 17C9D6662406252200D7B871 /* HiddenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C9D6652406252200D7B871 /* HiddenViewController.m */; };
50 | 17E7C23D240F558A0073409B /* ZHTableViewGroupObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 17E7C23C240F558A0073409B /* ZHTableViewGroupObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
51 | /* End PBXBuildFile section */
52 |
53 | /* Begin PBXContainerItemProxy section */
54 | 178360BC240E34A800FEEC2E /* PBXContainerItemProxy */ = {
55 | isa = PBXContainerItemProxy;
56 | containerPortal = 17722FAF2404A78200CEC436 /* Project object */;
57 | proxyType = 1;
58 | remoteGlobalIDString = 178360B6240E34A800FEEC2E;
59 | remoteInfo = ZHTableViewGroupObjc;
60 | };
61 | /* End PBXContainerItemProxy section */
62 |
63 | /* Begin PBXCopyFilesBuildPhase section */
64 | 17722FE42404A7D300CEC436 /* Embed Frameworks */ = {
65 | isa = PBXCopyFilesBuildPhase;
66 | buildActionMask = 2147483647;
67 | dstPath = "";
68 | dstSubfolderSpec = 10;
69 | files = (
70 | 178360BF240E34A800FEEC2E /* ZHTableViewGroupObjc.framework in Embed Frameworks */,
71 | );
72 | name = "Embed Frameworks";
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | /* End PBXCopyFilesBuildPhase section */
76 |
77 | /* Begin PBXFileReference section */
78 | 17722FB72404A78200CEC436 /* ZHTableViewGroupExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZHTableViewGroupExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
79 | 17722FBA2404A78200CEC436 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
80 | 17722FBB2404A78200CEC436 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
81 | 17722FBD2404A78200CEC436 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; };
82 | 17722FBE2404A78200CEC436 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; };
83 | 17722FC02404A78200CEC436 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
84 | 17722FC12404A78200CEC436 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
85 | 17722FC42404A78200CEC436 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
86 | 17722FC62404A78400CEC436 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
87 | 17722FC92404A78400CEC436 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
88 | 17722FCB2404A78400CEC436 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
89 | 17722FCC2404A78500CEC436 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
90 | 178360B7240E34A800FEEC2E /* ZHTableViewGroupObjc.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ZHTableViewGroupObjc.framework; sourceTree = BUILT_PRODUCTS_DIR; };
91 | 178360BA240E34A800FEEC2E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
92 | 178360C3240E34C000FEEC2E /* ZHCollectionViewBaseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHCollectionViewBaseModel.h; sourceTree = ""; };
93 | 178360C5240E34C000FEEC2E /* ZHCollectionViewBaseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHCollectionViewBaseModel.m; sourceTree = ""; };
94 | 178360C6240E34C100FEEC2E /* ZHTableViewHeaderFooter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHTableViewHeaderFooter.h; sourceTree = ""; };
95 | 178360C7240E34C100FEEC2E /* ZHCollectionViewGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHCollectionViewGroup.h; sourceTree = ""; };
96 | 178360C8240E34C100FEEC2E /* ZHTableViewBaseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHTableViewBaseModel.h; sourceTree = ""; };
97 | 178360C9240E34C100FEEC2E /* ZHTableViewDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHTableViewDataSource.h; sourceTree = ""; };
98 | 178360CA240E34C100FEEC2E /* ZHCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHCollectionViewCell.m; sourceTree = ""; };
99 | 178360CB240E34C100FEEC2E /* ZHTableViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHTableViewDataSource.m; sourceTree = ""; };
100 | 178360CC240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHAutoConfigurationTableViewDelegate.m; sourceTree = ""; };
101 | 178360CD240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHCollectionViewHeaderFooter.m; sourceTree = ""; };
102 | 178360CE240E34C100FEEC2E /* ZHTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHTableViewCell.h; sourceTree = ""; };
103 | 178360CF240E34C100FEEC2E /* ZHTableViewGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHTableViewGroup.m; sourceTree = ""; };
104 | 178360D0240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHAutoConfigurationCollectionViewDelegate.h; sourceTree = ""; };
105 | 178360D1240E34C100FEEC2E /* ZHTableViewGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHTableViewGroup.h; sourceTree = ""; };
106 | 178360D2240E34C100FEEC2E /* ZHTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHTableViewCell.m; sourceTree = ""; };
107 | 178360D3240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHAutoConfigurationTableViewDelegate.h; sourceTree = ""; };
108 | 178360D4240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHAutoConfigurationCollectionViewDelegate.m; sourceTree = ""; };
109 | 178360D5240E34C100FEEC2E /* ZHCollectionViewGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHCollectionViewGroup.m; sourceTree = ""; };
110 | 178360D6240E34C100FEEC2E /* ZHCollectionViewDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHCollectionViewDataSource.h; sourceTree = ""; };
111 | 178360D7240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHCollectionViewHeaderFooter.h; sourceTree = ""; };
112 | 178360D8240E34C100FEEC2E /* ZHTableViewHeaderFooter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHTableViewHeaderFooter.m; sourceTree = ""; };
113 | 178360D9240E34C100FEEC2E /* ZHCollectionViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHCollectionViewDataSource.m; sourceTree = ""; };
114 | 178360DA240E34C100FEEC2E /* ZHTableViewBaseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZHTableViewBaseModel.m; sourceTree = ""; };
115 | 178360DB240E34C100FEEC2E /* ZHCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHCollectionViewCell.h; sourceTree = ""; };
116 | 17C9D6492404C3F500D7B871 /* ReloadHeightViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReloadHeightViewController.h; sourceTree = ""; };
117 | 17C9D64A2404C3F500D7B871 /* ReloadHeightViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReloadHeightViewController.m; sourceTree = ""; };
118 | 17C9D6562404F1F300D7B871 /* TableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; };
119 | 17C9D6572404F1F300D7B871 /* TableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; };
120 | 17C9D6582404F1F300D7B871 /* TableViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TableViewController.xib; sourceTree = ""; };
121 | 17C9D65B2404FF0900D7B871 /* SetHeightViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SetHeightViewController.h; sourceTree = ""; };
122 | 17C9D65C2404FF0900D7B871 /* SetHeightViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SetHeightViewController.m; sourceTree = ""; };
123 | 17C9D65E240514F900D7B871 /* ReloadCellViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReloadCellViewController.h; sourceTree = ""; };
124 | 17C9D65F240514F900D7B871 /* ReloadCellViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReloadCellViewController.m; sourceTree = ""; };
125 | 17C9D6612405198D00D7B871 /* ReloadCellDataViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReloadCellDataViewController.h; sourceTree = ""; };
126 | 17C9D6622405198D00D7B871 /* ReloadCellDataViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReloadCellDataViewController.m; sourceTree = ""; };
127 | 17C9D6642406252200D7B871 /* HiddenViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HiddenViewController.h; sourceTree = ""; };
128 | 17C9D6652406252200D7B871 /* HiddenViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HiddenViewController.m; sourceTree = ""; };
129 | 17E7C23C240F558A0073409B /* ZHTableViewGroupObjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZHTableViewGroupObjc.h; sourceTree = ""; };
130 | /* End PBXFileReference section */
131 |
132 | /* Begin PBXFrameworksBuildPhase section */
133 | 17722FB42404A78200CEC436 /* Frameworks */ = {
134 | isa = PBXFrameworksBuildPhase;
135 | buildActionMask = 2147483647;
136 | files = (
137 | 178360BE240E34A800FEEC2E /* ZHTableViewGroupObjc.framework in Frameworks */,
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | 178360B4240E34A800FEEC2E /* Frameworks */ = {
142 | isa = PBXFrameworksBuildPhase;
143 | buildActionMask = 2147483647;
144 | files = (
145 | );
146 | runOnlyForDeploymentPostprocessing = 0;
147 | };
148 | /* End PBXFrameworksBuildPhase section */
149 |
150 | /* Begin PBXGroup section */
151 | 17722FAE2404A78200CEC436 = {
152 | isa = PBXGroup;
153 | children = (
154 | 17722FB92404A78200CEC436 /* ZHTableViewGroupExample */,
155 | 178360B8240E34A800FEEC2E /* ZHTableViewGroupObjc */,
156 | 17722FB82404A78200CEC436 /* Products */,
157 | );
158 | sourceTree = "";
159 | };
160 | 17722FB82404A78200CEC436 /* Products */ = {
161 | isa = PBXGroup;
162 | children = (
163 | 17722FB72404A78200CEC436 /* ZHTableViewGroupExample.app */,
164 | 178360B7240E34A800FEEC2E /* ZHTableViewGroupObjc.framework */,
165 | );
166 | name = Products;
167 | sourceTree = "";
168 | };
169 | 17722FB92404A78200CEC436 /* ZHTableViewGroupExample */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 17722FBA2404A78200CEC436 /* AppDelegate.h */,
173 | 17722FBB2404A78200CEC436 /* AppDelegate.m */,
174 | 17722FBD2404A78200CEC436 /* SceneDelegate.h */,
175 | 17722FBE2404A78200CEC436 /* SceneDelegate.m */,
176 | 17722FC02404A78200CEC436 /* ViewController.h */,
177 | 17722FC12404A78200CEC436 /* ViewController.m */,
178 | 17C9D6492404C3F500D7B871 /* ReloadHeightViewController.h */,
179 | 17C9D64A2404C3F500D7B871 /* ReloadHeightViewController.m */,
180 | 17C9D65B2404FF0900D7B871 /* SetHeightViewController.h */,
181 | 17C9D65C2404FF0900D7B871 /* SetHeightViewController.m */,
182 | 17C9D65E240514F900D7B871 /* ReloadCellViewController.h */,
183 | 17C9D65F240514F900D7B871 /* ReloadCellViewController.m */,
184 | 17C9D6612405198D00D7B871 /* ReloadCellDataViewController.h */,
185 | 17C9D6622405198D00D7B871 /* ReloadCellDataViewController.m */,
186 | 17C9D6642406252200D7B871 /* HiddenViewController.h */,
187 | 17C9D6652406252200D7B871 /* HiddenViewController.m */,
188 | 17C9D6562404F1F300D7B871 /* TableViewController.h */,
189 | 17C9D6572404F1F300D7B871 /* TableViewController.m */,
190 | 17C9D6582404F1F300D7B871 /* TableViewController.xib */,
191 | 17722FC32404A78200CEC436 /* Main.storyboard */,
192 | 17722FC62404A78400CEC436 /* Assets.xcassets */,
193 | 17722FC82404A78400CEC436 /* LaunchScreen.storyboard */,
194 | 17722FCB2404A78400CEC436 /* Info.plist */,
195 | 17722FCC2404A78500CEC436 /* main.m */,
196 | );
197 | path = ZHTableViewGroupExample;
198 | sourceTree = "";
199 | };
200 | 178360B8240E34A800FEEC2E /* ZHTableViewGroupObjc */ = {
201 | isa = PBXGroup;
202 | children = (
203 | 178360D0240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.h */,
204 | 17E7C23C240F558A0073409B /* ZHTableViewGroupObjc.h */,
205 | 178360D4240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.m */,
206 | 178360D3240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.h */,
207 | 178360CC240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.m */,
208 | 178360C3240E34C000FEEC2E /* ZHCollectionViewBaseModel.h */,
209 | 178360C5240E34C000FEEC2E /* ZHCollectionViewBaseModel.m */,
210 | 178360DB240E34C100FEEC2E /* ZHCollectionViewCell.h */,
211 | 178360CA240E34C100FEEC2E /* ZHCollectionViewCell.m */,
212 | 178360D6240E34C100FEEC2E /* ZHCollectionViewDataSource.h */,
213 | 178360D9240E34C100FEEC2E /* ZHCollectionViewDataSource.m */,
214 | 178360C7240E34C100FEEC2E /* ZHCollectionViewGroup.h */,
215 | 178360D5240E34C100FEEC2E /* ZHCollectionViewGroup.m */,
216 | 178360D7240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.h */,
217 | 178360CD240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.m */,
218 | 178360C8240E34C100FEEC2E /* ZHTableViewBaseModel.h */,
219 | 178360DA240E34C100FEEC2E /* ZHTableViewBaseModel.m */,
220 | 178360CE240E34C100FEEC2E /* ZHTableViewCell.h */,
221 | 178360D2240E34C100FEEC2E /* ZHTableViewCell.m */,
222 | 178360C9240E34C100FEEC2E /* ZHTableViewDataSource.h */,
223 | 178360CB240E34C100FEEC2E /* ZHTableViewDataSource.m */,
224 | 178360D1240E34C100FEEC2E /* ZHTableViewGroup.h */,
225 | 178360CF240E34C100FEEC2E /* ZHTableViewGroup.m */,
226 | 178360C6240E34C100FEEC2E /* ZHTableViewHeaderFooter.h */,
227 | 178360D8240E34C100FEEC2E /* ZHTableViewHeaderFooter.m */,
228 | 178360BA240E34A800FEEC2E /* Info.plist */,
229 | );
230 | path = ZHTableViewGroupObjc;
231 | sourceTree = "";
232 | };
233 | /* End PBXGroup section */
234 |
235 | /* Begin PBXHeadersBuildPhase section */
236 | 178360B2240E34A800FEEC2E /* Headers */ = {
237 | isa = PBXHeadersBuildPhase;
238 | buildActionMask = 2147483647;
239 | files = (
240 | 178360E1240E34C100FEEC2E /* ZHTableViewBaseModel.h in Headers */,
241 | 178360E2240E34C100FEEC2E /* ZHTableViewDataSource.h in Headers */,
242 | 178360DC240E34C100FEEC2E /* ZHCollectionViewBaseModel.h in Headers */,
243 | 178360F4240E34C100FEEC2E /* ZHCollectionViewCell.h in Headers */,
244 | 178360EF240E34C100FEEC2E /* ZHCollectionViewDataSource.h in Headers */,
245 | 178360E7240E34C100FEEC2E /* ZHTableViewCell.h in Headers */,
246 | 178360DF240E34C100FEEC2E /* ZHTableViewHeaderFooter.h in Headers */,
247 | 178360E9240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.h in Headers */,
248 | 17E7C23D240F558A0073409B /* ZHTableViewGroupObjc.h in Headers */,
249 | 178360E0240E34C100FEEC2E /* ZHCollectionViewGroup.h in Headers */,
250 | 178360F0240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.h in Headers */,
251 | 178360EA240E34C100FEEC2E /* ZHTableViewGroup.h in Headers */,
252 | 178360EC240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.h in Headers */,
253 | );
254 | runOnlyForDeploymentPostprocessing = 0;
255 | };
256 | /* End PBXHeadersBuildPhase section */
257 |
258 | /* Begin PBXNativeTarget section */
259 | 17722FB62404A78200CEC436 /* ZHTableViewGroupExample */ = {
260 | isa = PBXNativeTarget;
261 | buildConfigurationList = 17722FD02404A78500CEC436 /* Build configuration list for PBXNativeTarget "ZHTableViewGroupExample" */;
262 | buildPhases = (
263 | 17722FB32404A78200CEC436 /* Sources */,
264 | 17722FB42404A78200CEC436 /* Frameworks */,
265 | 17722FB52404A78200CEC436 /* Resources */,
266 | 17722FE42404A7D300CEC436 /* Embed Frameworks */,
267 | );
268 | buildRules = (
269 | );
270 | dependencies = (
271 | 178360BD240E34A800FEEC2E /* PBXTargetDependency */,
272 | );
273 | name = ZHTableViewGroupExample;
274 | productName = ZHTableViewGroupExample;
275 | productReference = 17722FB72404A78200CEC436 /* ZHTableViewGroupExample.app */;
276 | productType = "com.apple.product-type.application";
277 | };
278 | 178360B6240E34A800FEEC2E /* ZHTableViewGroupObjc */ = {
279 | isa = PBXNativeTarget;
280 | buildConfigurationList = 178360C0240E34A800FEEC2E /* Build configuration list for PBXNativeTarget "ZHTableViewGroupObjc" */;
281 | buildPhases = (
282 | 178360B2240E34A800FEEC2E /* Headers */,
283 | 178360B3240E34A800FEEC2E /* Sources */,
284 | 178360B4240E34A800FEEC2E /* Frameworks */,
285 | 178360B5240E34A800FEEC2E /* Resources */,
286 | );
287 | buildRules = (
288 | );
289 | dependencies = (
290 | );
291 | name = ZHTableViewGroupObjc;
292 | productName = ZHTableViewGroupObjc;
293 | productReference = 178360B7240E34A800FEEC2E /* ZHTableViewGroupObjc.framework */;
294 | productType = "com.apple.product-type.framework";
295 | };
296 | /* End PBXNativeTarget section */
297 |
298 | /* Begin PBXProject section */
299 | 17722FAF2404A78200CEC436 /* Project object */ = {
300 | isa = PBXProject;
301 | attributes = {
302 | LastUpgradeCheck = 1110;
303 | ORGANIZATIONNAME = josercc;
304 | TargetAttributes = {
305 | 17722FB62404A78200CEC436 = {
306 | CreatedOnToolsVersion = 11.1;
307 | };
308 | 178360B6240E34A800FEEC2E = {
309 | CreatedOnToolsVersion = 11.1;
310 | };
311 | };
312 | };
313 | buildConfigurationList = 17722FB22404A78200CEC436 /* Build configuration list for PBXProject "ZHTableViewGroupExample" */;
314 | compatibilityVersion = "Xcode 9.3";
315 | developmentRegion = en;
316 | hasScannedForEncodings = 0;
317 | knownRegions = (
318 | en,
319 | Base,
320 | );
321 | mainGroup = 17722FAE2404A78200CEC436;
322 | productRefGroup = 17722FB82404A78200CEC436 /* Products */;
323 | projectDirPath = "";
324 | projectRoot = "";
325 | targets = (
326 | 17722FB62404A78200CEC436 /* ZHTableViewGroupExample */,
327 | 178360B6240E34A800FEEC2E /* ZHTableViewGroupObjc */,
328 | );
329 | };
330 | /* End PBXProject section */
331 |
332 | /* Begin PBXResourcesBuildPhase section */
333 | 17722FB52404A78200CEC436 /* Resources */ = {
334 | isa = PBXResourcesBuildPhase;
335 | buildActionMask = 2147483647;
336 | files = (
337 | 17722FCA2404A78400CEC436 /* LaunchScreen.storyboard in Resources */,
338 | 17722FC72404A78400CEC436 /* Assets.xcassets in Resources */,
339 | 17C9D65A2404F1F300D7B871 /* TableViewController.xib in Resources */,
340 | 17722FC52404A78200CEC436 /* Main.storyboard in Resources */,
341 | );
342 | runOnlyForDeploymentPostprocessing = 0;
343 | };
344 | 178360B5240E34A800FEEC2E /* Resources */ = {
345 | isa = PBXResourcesBuildPhase;
346 | buildActionMask = 2147483647;
347 | files = (
348 | );
349 | runOnlyForDeploymentPostprocessing = 0;
350 | };
351 | /* End PBXResourcesBuildPhase section */
352 |
353 | /* Begin PBXSourcesBuildPhase section */
354 | 17722FB32404A78200CEC436 /* Sources */ = {
355 | isa = PBXSourcesBuildPhase;
356 | buildActionMask = 2147483647;
357 | files = (
358 | 17722FC22404A78200CEC436 /* ViewController.m in Sources */,
359 | 17C9D6592404F1F300D7B871 /* TableViewController.m in Sources */,
360 | 17C9D6662406252200D7B871 /* HiddenViewController.m in Sources */,
361 | 17C9D65D2404FF0900D7B871 /* SetHeightViewController.m in Sources */,
362 | 17C9D6632405198D00D7B871 /* ReloadCellDataViewController.m in Sources */,
363 | 17C9D660240514F900D7B871 /* ReloadCellViewController.m in Sources */,
364 | 17722FBC2404A78200CEC436 /* AppDelegate.m in Sources */,
365 | 17722FCD2404A78500CEC436 /* main.m in Sources */,
366 | 17C9D6502404CACF00D7B871 /* ReloadHeightViewController.m in Sources */,
367 | 17722FBF2404A78200CEC436 /* SceneDelegate.m in Sources */,
368 | );
369 | runOnlyForDeploymentPostprocessing = 0;
370 | };
371 | 178360B3240E34A800FEEC2E /* Sources */ = {
372 | isa = PBXSourcesBuildPhase;
373 | buildActionMask = 2147483647;
374 | files = (
375 | 178360E3240E34C100FEEC2E /* ZHCollectionViewCell.m in Sources */,
376 | 178360F1240E34C100FEEC2E /* ZHTableViewHeaderFooter.m in Sources */,
377 | 178360F3240E34C100FEEC2E /* ZHTableViewBaseModel.m in Sources */,
378 | 178360F2240E34C100FEEC2E /* ZHCollectionViewDataSource.m in Sources */,
379 | 178360EB240E34C100FEEC2E /* ZHTableViewCell.m in Sources */,
380 | 178360E6240E34C100FEEC2E /* ZHCollectionViewHeaderFooter.m in Sources */,
381 | 178360ED240E34C100FEEC2E /* ZHAutoConfigurationCollectionViewDelegate.m in Sources */,
382 | 178360E4240E34C100FEEC2E /* ZHTableViewDataSource.m in Sources */,
383 | 178360E8240E34C100FEEC2E /* ZHTableViewGroup.m in Sources */,
384 | 178360E5240E34C100FEEC2E /* ZHAutoConfigurationTableViewDelegate.m in Sources */,
385 | 178360EE240E34C100FEEC2E /* ZHCollectionViewGroup.m in Sources */,
386 | 178360DE240E34C100FEEC2E /* ZHCollectionViewBaseModel.m in Sources */,
387 | );
388 | runOnlyForDeploymentPostprocessing = 0;
389 | };
390 | /* End PBXSourcesBuildPhase section */
391 |
392 | /* Begin PBXTargetDependency section */
393 | 178360BD240E34A800FEEC2E /* PBXTargetDependency */ = {
394 | isa = PBXTargetDependency;
395 | target = 178360B6240E34A800FEEC2E /* ZHTableViewGroupObjc */;
396 | targetProxy = 178360BC240E34A800FEEC2E /* PBXContainerItemProxy */;
397 | };
398 | /* End PBXTargetDependency section */
399 |
400 | /* Begin PBXVariantGroup section */
401 | 17722FC32404A78200CEC436 /* Main.storyboard */ = {
402 | isa = PBXVariantGroup;
403 | children = (
404 | 17722FC42404A78200CEC436 /* Base */,
405 | );
406 | name = Main.storyboard;
407 | sourceTree = "";
408 | };
409 | 17722FC82404A78400CEC436 /* LaunchScreen.storyboard */ = {
410 | isa = PBXVariantGroup;
411 | children = (
412 | 17722FC92404A78400CEC436 /* Base */,
413 | );
414 | name = LaunchScreen.storyboard;
415 | sourceTree = "";
416 | };
417 | /* End PBXVariantGroup section */
418 |
419 | /* Begin XCBuildConfiguration section */
420 | 17722FCE2404A78500CEC436 /* Debug */ = {
421 | isa = XCBuildConfiguration;
422 | buildSettings = {
423 | ALWAYS_SEARCH_USER_PATHS = NO;
424 | CLANG_ANALYZER_NONNULL = YES;
425 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
426 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
427 | CLANG_CXX_LIBRARY = "libc++";
428 | CLANG_ENABLE_MODULES = YES;
429 | CLANG_ENABLE_OBJC_ARC = YES;
430 | CLANG_ENABLE_OBJC_WEAK = YES;
431 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
432 | CLANG_WARN_BOOL_CONVERSION = YES;
433 | CLANG_WARN_COMMA = YES;
434 | CLANG_WARN_CONSTANT_CONVERSION = YES;
435 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
436 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
437 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
438 | CLANG_WARN_EMPTY_BODY = YES;
439 | CLANG_WARN_ENUM_CONVERSION = YES;
440 | CLANG_WARN_INFINITE_RECURSION = YES;
441 | CLANG_WARN_INT_CONVERSION = YES;
442 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
443 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
444 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
445 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
446 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
447 | CLANG_WARN_STRICT_PROTOTYPES = YES;
448 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
449 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
450 | CLANG_WARN_UNREACHABLE_CODE = YES;
451 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
452 | COPY_PHASE_STRIP = NO;
453 | DEBUG_INFORMATION_FORMAT = dwarf;
454 | ENABLE_STRICT_OBJC_MSGSEND = YES;
455 | ENABLE_TESTABILITY = YES;
456 | GCC_C_LANGUAGE_STANDARD = gnu11;
457 | GCC_DYNAMIC_NO_PIC = NO;
458 | GCC_NO_COMMON_BLOCKS = YES;
459 | GCC_OPTIMIZATION_LEVEL = 0;
460 | GCC_PREPROCESSOR_DEFINITIONS = (
461 | "DEBUG=1",
462 | "$(inherited)",
463 | );
464 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
465 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
466 | GCC_WARN_UNDECLARED_SELECTOR = YES;
467 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
468 | GCC_WARN_UNUSED_FUNCTION = YES;
469 | GCC_WARN_UNUSED_VARIABLE = YES;
470 | IPHONEOS_DEPLOYMENT_TARGET = 13.1;
471 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
472 | MTL_FAST_MATH = YES;
473 | ONLY_ACTIVE_ARCH = YES;
474 | SDKROOT = iphoneos;
475 | };
476 | name = Debug;
477 | };
478 | 17722FCF2404A78500CEC436 /* Release */ = {
479 | isa = XCBuildConfiguration;
480 | buildSettings = {
481 | ALWAYS_SEARCH_USER_PATHS = NO;
482 | CLANG_ANALYZER_NONNULL = YES;
483 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
484 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
485 | CLANG_CXX_LIBRARY = "libc++";
486 | CLANG_ENABLE_MODULES = YES;
487 | CLANG_ENABLE_OBJC_ARC = YES;
488 | CLANG_ENABLE_OBJC_WEAK = YES;
489 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
490 | CLANG_WARN_BOOL_CONVERSION = YES;
491 | CLANG_WARN_COMMA = YES;
492 | CLANG_WARN_CONSTANT_CONVERSION = YES;
493 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
494 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
495 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
496 | CLANG_WARN_EMPTY_BODY = YES;
497 | CLANG_WARN_ENUM_CONVERSION = YES;
498 | CLANG_WARN_INFINITE_RECURSION = YES;
499 | CLANG_WARN_INT_CONVERSION = YES;
500 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
501 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
502 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
503 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
504 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
505 | CLANG_WARN_STRICT_PROTOTYPES = YES;
506 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
507 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
508 | CLANG_WARN_UNREACHABLE_CODE = YES;
509 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
510 | COPY_PHASE_STRIP = NO;
511 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
512 | ENABLE_NS_ASSERTIONS = NO;
513 | ENABLE_STRICT_OBJC_MSGSEND = YES;
514 | GCC_C_LANGUAGE_STANDARD = gnu11;
515 | GCC_NO_COMMON_BLOCKS = YES;
516 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
517 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
518 | GCC_WARN_UNDECLARED_SELECTOR = YES;
519 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
520 | GCC_WARN_UNUSED_FUNCTION = YES;
521 | GCC_WARN_UNUSED_VARIABLE = YES;
522 | IPHONEOS_DEPLOYMENT_TARGET = 13.1;
523 | MTL_ENABLE_DEBUG_INFO = NO;
524 | MTL_FAST_MATH = YES;
525 | SDKROOT = iphoneos;
526 | VALIDATE_PRODUCT = YES;
527 | };
528 | name = Release;
529 | };
530 | 17722FD12404A78500CEC436 /* Debug */ = {
531 | isa = XCBuildConfiguration;
532 | buildSettings = {
533 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
534 | CODE_SIGN_STYLE = Automatic;
535 | DEVELOPMENT_TEAM = 9RWES6K38C;
536 | INFOPLIST_FILE = ZHTableViewGroupExample/Info.plist;
537 | LD_RUNPATH_SEARCH_PATHS = (
538 | "$(inherited)",
539 | "@executable_path/Frameworks",
540 | );
541 | PRODUCT_BUNDLE_IDENTIFIER = com.globalegrow.ZHTableViewGroupExample;
542 | PRODUCT_NAME = "$(TARGET_NAME)";
543 | TARGETED_DEVICE_FAMILY = "1,2";
544 | };
545 | name = Debug;
546 | };
547 | 17722FD22404A78500CEC436 /* Release */ = {
548 | isa = XCBuildConfiguration;
549 | buildSettings = {
550 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
551 | CODE_SIGN_STYLE = Automatic;
552 | DEVELOPMENT_TEAM = 9RWES6K38C;
553 | INFOPLIST_FILE = ZHTableViewGroupExample/Info.plist;
554 | LD_RUNPATH_SEARCH_PATHS = (
555 | "$(inherited)",
556 | "@executable_path/Frameworks",
557 | );
558 | PRODUCT_BUNDLE_IDENTIFIER = com.globalegrow.ZHTableViewGroupExample;
559 | PRODUCT_NAME = "$(TARGET_NAME)";
560 | TARGETED_DEVICE_FAMILY = "1,2";
561 | };
562 | name = Release;
563 | };
564 | 178360C1240E34A800FEEC2E /* Debug */ = {
565 | isa = XCBuildConfiguration;
566 | buildSettings = {
567 | CODE_SIGN_STYLE = Automatic;
568 | CURRENT_PROJECT_VERSION = 1;
569 | DEFINES_MODULE = YES;
570 | DEVELOPMENT_TEAM = 9RWES6K38C;
571 | DYLIB_COMPATIBILITY_VERSION = 1;
572 | DYLIB_CURRENT_VERSION = 1;
573 | DYLIB_INSTALL_NAME_BASE = "@rpath";
574 | INFOPLIST_FILE = ZHTableViewGroupObjc/Info.plist;
575 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
576 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
577 | LD_RUNPATH_SEARCH_PATHS = (
578 | "$(inherited)",
579 | "@executable_path/Frameworks",
580 | "@loader_path/Frameworks",
581 | );
582 | PRODUCT_BUNDLE_IDENTIFIER = com.globalegrow.ZHTableViewGroupObjc;
583 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
584 | SKIP_INSTALL = YES;
585 | TARGETED_DEVICE_FAMILY = "1,2";
586 | VERSIONING_SYSTEM = "apple-generic";
587 | VERSION_INFO_PREFIX = "";
588 | };
589 | name = Debug;
590 | };
591 | 178360C2240E34A800FEEC2E /* Release */ = {
592 | isa = XCBuildConfiguration;
593 | buildSettings = {
594 | CODE_SIGN_STYLE = Automatic;
595 | CURRENT_PROJECT_VERSION = 1;
596 | DEFINES_MODULE = YES;
597 | DEVELOPMENT_TEAM = 9RWES6K38C;
598 | DYLIB_COMPATIBILITY_VERSION = 1;
599 | DYLIB_CURRENT_VERSION = 1;
600 | DYLIB_INSTALL_NAME_BASE = "@rpath";
601 | INFOPLIST_FILE = ZHTableViewGroupObjc/Info.plist;
602 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
603 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
604 | LD_RUNPATH_SEARCH_PATHS = (
605 | "$(inherited)",
606 | "@executable_path/Frameworks",
607 | "@loader_path/Frameworks",
608 | );
609 | PRODUCT_BUNDLE_IDENTIFIER = com.globalegrow.ZHTableViewGroupObjc;
610 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
611 | SKIP_INSTALL = YES;
612 | TARGETED_DEVICE_FAMILY = "1,2";
613 | VERSIONING_SYSTEM = "apple-generic";
614 | VERSION_INFO_PREFIX = "";
615 | };
616 | name = Release;
617 | };
618 | /* End XCBuildConfiguration section */
619 |
620 | /* Begin XCConfigurationList section */
621 | 17722FB22404A78200CEC436 /* Build configuration list for PBXProject "ZHTableViewGroupExample" */ = {
622 | isa = XCConfigurationList;
623 | buildConfigurations = (
624 | 17722FCE2404A78500CEC436 /* Debug */,
625 | 17722FCF2404A78500CEC436 /* Release */,
626 | );
627 | defaultConfigurationIsVisible = 0;
628 | defaultConfigurationName = Release;
629 | };
630 | 17722FD02404A78500CEC436 /* Build configuration list for PBXNativeTarget "ZHTableViewGroupExample" */ = {
631 | isa = XCConfigurationList;
632 | buildConfigurations = (
633 | 17722FD12404A78500CEC436 /* Debug */,
634 | 17722FD22404A78500CEC436 /* Release */,
635 | );
636 | defaultConfigurationIsVisible = 0;
637 | defaultConfigurationName = Release;
638 | };
639 | 178360C0240E34A800FEEC2E /* Build configuration list for PBXNativeTarget "ZHTableViewGroupObjc" */ = {
640 | isa = XCConfigurationList;
641 | buildConfigurations = (
642 | 178360C1240E34A800FEEC2E /* Debug */,
643 | 178360C2240E34A800FEEC2E /* Release */,
644 | );
645 | defaultConfigurationIsVisible = 0;
646 | defaultConfigurationName = Release;
647 | };
648 | /* End XCConfigurationList section */
649 | };
650 | rootObject = 17722FAF2404A78200CEC436 /* Project object */;
651 | }
652 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample.xcodeproj/xcshareddata/xcschemes/ZHTableViewGroupObjc.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
57 |
58 |
59 |
60 |
62 |
63 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | #pragma mark - UISceneSession lifecycle
25 |
26 |
27 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
28 | // Called when a new scene session is being created.
29 | // Use this method to select a configuration to create the new scene with.
30 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
31 | }
32 |
33 |
34 | - (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions {
35 | // Called when the user discards a scene session.
36 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
37 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
38 | }
39 |
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/HiddenViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // HiddenViewController.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/26.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HiddenViewController : TableViewController
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/HiddenViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // HiddenViewController.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/26.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "HiddenViewController.h"
10 |
11 | @interface HiddenViewController ()
12 |
13 | @end
14 |
15 | @implementation HiddenViewController {
16 | BOOL _hidden;
17 | }
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 | [self.tableViewDataSource clearData];
22 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
23 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
24 | cell.anyClass = [UITableViewCell class];
25 | cell.identifier = @"UITableViewCell";
26 | cell.cellNumber = 10;
27 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
28 | cell.textLabel.text = [@(indexPath.row + 1) stringValue];
29 | }];
30 | [cell setHiddenBlock:^BOOL(NSIndexPath *indexPath) {
31 | return _hidden && indexPath.row >= 5 && indexPath.row <= 8;
32 | }];
33 | }];
34 | }];
35 | [self.tableViewDataSource reloadTableViewData];
36 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"刷新" style:UIBarButtonItemStylePlain target:self action:@selector(refresh)];
37 | }
38 |
39 | - (void)refresh {
40 | _hidden = !_hidden;
41 | [self.tableViewDataSource reloadAllHiddenCell];
42 | }
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 | UISupportedInterfaceOrientations~ipad
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ReloadCellDataViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ReloadCellDataViewController.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface ReloadCellDataViewController : TableViewController
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ReloadCellDataViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ReloadCellDataViewController.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "ReloadCellDataViewController.h"
10 |
11 | @interface ReloadCellDataViewController ()
12 |
13 | @end
14 |
15 | @implementation ReloadCellDataViewController {
16 | NSUInteger _index;
17 | NSMutableArray *_randoms;
18 | }
19 |
20 | - (void)viewDidLoad {
21 | [super viewDidLoad];
22 | _randoms = [NSMutableArray arrayWithArray:@[@"random"]];
23 | [self.tableViewDataSource clearData];
24 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
25 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
26 | cell.anyClass = [UITableViewCell class];
27 | cell.identifier = @"UITableViewCell";
28 | cell.cellNumber = _randoms.count;
29 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
30 | cell.textLabel.text = _randoms[indexPath.row];
31 | }];
32 | }];
33 | }];
34 | [self.tableViewDataSource reloadTableViewData];
35 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"刷新" style:UIBarButtonItemStylePlain target:self action:@selector(refresh)];
36 | }
37 |
38 | - (void)refresh {
39 | _index = MIN(3, _index);
40 | NSUInteger randomCount = random() % 9 + 1;
41 | [_randoms removeAllObjects];
42 | for (NSUInteger i = 0; i < randomCount; i++) {
43 | [_randoms addObject:[NSString stringWithFormat:@"random:%@",@(i)]];
44 | }
45 | if (_index == 0) {
46 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count identifier:@"UITableViewCell"];
47 | } else if (_index == 1) {
48 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count className:[UITableViewCell class]];
49 | } else if (_index == 2) {
50 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count tableViewCell:self.tableViewDataSource.groups[0].cells[0]];
51 | } else if (_index == 3) {
52 | [self.tableViewDataSource reloadCellWithDataCount:_randoms.count groupIndex:0 cellIndex:0];
53 | }
54 | _index += 1;
55 | }
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ReloadCellViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ReloadCellViewController.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface ReloadCellViewController : TableViewController
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ReloadCellViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ReloadCellViewController.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "ReloadCellViewController.h"
10 |
11 | @interface ReloadCellViewController ()
12 |
13 | @end
14 |
15 | @implementation ReloadCellViewController {
16 | NSUInteger _index;
17 | }
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 |
22 | [self.tableViewDataSource clearData];
23 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
24 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
25 | cell.anyClass = [UITableViewCell class];
26 | cell.identifier = @"UITableViewCell";
27 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
28 | cell.textLabel.text = [@(random() % 99 + 1) stringValue];
29 | }];
30 | }];
31 | }];
32 | [self.tableViewDataSource reloadTableViewData];
33 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"刷新" style:UIBarButtonItemStylePlain target:self action:@selector(refresh)];
34 | }
35 |
36 | - (void)refresh {
37 | _index = MIN(3, _index);
38 | if (_index == 0) {
39 | [self.tableViewDataSource reloadCellWithIdentifier:@"UITableViewCell"];
40 | } else if (_index == 1) {
41 | [self.tableViewDataSource reloadCellWithClassName:[UITableViewCell class]];
42 | } else if (_index == 2) {
43 | [self.tableViewDataSource reloadCellWithTableViewCell:self.tableViewDataSource.groups[0].cells[0]];
44 | } else if (_index == 3) {
45 | [self.tableViewDataSource reloadCellWithGroupIndex:0 cellIndex:0];
46 | }
47 | _index += 1;
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ReloadHeightViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ReloadHeightViewController.h
3 | // ZHTableViewGroupObjc
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TableViewController.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 | @class ReloadHeightCell1, ReloadHeightCell2;
14 |
15 | @interface ReloadHeightViewController : TableViewController
16 |
17 | @end
18 |
19 | @interface ReloadHeightCell1 : UITableViewCell
20 |
21 | @end
22 |
23 | @interface ReloadHeightCell2 : UITableViewCell
24 |
25 | @end
26 |
27 | NS_ASSUME_NONNULL_END
28 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ReloadHeightViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ReloadHeightViewController.m
3 | // ZHTableViewGroupObjc
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "ReloadHeightViewController.h"
10 | #import
11 | #import "SetHeightViewController.h"
12 |
13 | @interface ReloadHeightViewController ()
14 |
15 |
16 | @end
17 |
18 | @implementation ReloadHeightViewController {
19 | __block ZHTableViewCell *_weakCell;
20 | }
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 | [self.tableViewDataSource clearData];
25 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
26 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
27 | self->_weakCell = cell;
28 | cell.anyClass = [ReloadHeightCell1 class];
29 | cell.identifier = @"ReloadHeightCell1";
30 | [cell setConfigCompletionHandle:^(ReloadHeightCell1 *cell1, NSIndexPath *indexPath) {
31 | cell1.textLabel.text = @"ReloadHeightCell1";
32 | }];
33 | }];
34 | }];
35 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
36 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
37 | cell.anyClass = [ReloadHeightCell2 class];
38 | cell.identifier = @"ReloadHeightCell2";
39 | cell.cellNumber = 2;
40 | [cell setConfigCompletionHandle:^(ReloadHeightCell2 *cell1, NSIndexPath *indexPath) {
41 | cell1.textLabel.text = @"ReloadHeightCell2";
42 | }];
43 | }];
44 | }];
45 | [self.tableViewDataSource reloadTableViewData];
46 |
47 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"刷新高度"
48 | style:UIBarButtonItemStylePlain
49 | target:self
50 | action:@selector(reloadHeight)];
51 | }
52 |
53 | - (void)reloadHeight {
54 | SetHeightViewController *controller = [[SetHeightViewController alloc] initWithNibName:nil bundle:nil];
55 | controller.updateTableViewDataSource = self.tableViewDataSource;
56 | [self presentViewController:controller animated:YES completion:nil];
57 | }
58 |
59 |
60 | @end
61 |
62 | @implementation ReloadHeightCell1
63 |
64 | - (CGSize)sizeThatFits:(CGSize)size {
65 | return CGSizeMake(size.width, 85);
66 | }
67 |
68 | @end
69 |
70 | @implementation ReloadHeightCell2
71 |
72 | - (CGSize)sizeThatFits:(CGSize)size {
73 | return CGSizeMake(size.width, 105);
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/SceneDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SceneDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow * window;
14 |
15 | @end
16 |
17 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/SceneDelegate.m:
--------------------------------------------------------------------------------
1 | #import "SceneDelegate.h"
2 |
3 | @interface SceneDelegate ()
4 |
5 | @end
6 |
7 | @implementation SceneDelegate
8 |
9 |
10 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
11 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
12 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
13 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
14 | }
15 |
16 |
17 | - (void)sceneDidDisconnect:(UIScene *)scene {
18 | // Called as the scene is being released by the system.
19 | // This occurs shortly after the scene enters the background, or when its session is discarded.
20 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
21 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
22 | }
23 |
24 |
25 | - (void)sceneDidBecomeActive:(UIScene *)scene {
26 | // Called when the scene has moved from an inactive state to an active state.
27 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
28 | }
29 |
30 |
31 | - (void)sceneWillResignActive:(UIScene *)scene {
32 | // Called when the scene will move from an active state to an inactive state.
33 | // This may occur due to temporary interruptions (ex. an incoming phone call).
34 | }
35 |
36 |
37 | - (void)sceneWillEnterForeground:(UIScene *)scene {
38 | // Called as the scene transitions from the background to the foreground.
39 | // Use this method to undo the changes made on entering the background.
40 | }
41 |
42 |
43 | - (void)sceneDidEnterBackground:(UIScene *)scene {
44 | // Called as the scene transitions from the foreground to the background.
45 | // Use this method to save data, release shared resources, and store enough scene-specific state information
46 | // to restore the scene back to its current state.
47 | }
48 |
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/SetHeightViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SetHeightViewController.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface SetHeightViewController : TableViewController
14 |
15 | @property (nonatomic, weak) ZHTableViewDataSource *updateTableViewDataSource;
16 |
17 | @end
18 |
19 | NS_ASSUME_NONNULL_END
20 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/SetHeightViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SetHeightViewController.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "SetHeightViewController.h"
10 |
11 | @interface SetHeightViewController ()
12 |
13 | @end
14 |
15 | @implementation SetHeightViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | NSArray *titles = @[
20 | @"identifier更新自动高度",
21 | @"identifier更新固定250高度",
22 | @"Class更新自动高度",
23 | @"Class更新固定260高度",
24 | @"指定ZHTableViewCell更新自动高度",
25 | @"指定ZHTableViewCell更新固定270高度",
26 | @"指定索引更新自动高度",
27 | @"指定索引更新固定280高度",
28 | ];
29 | [self.tableViewDataSource clearData];
30 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
31 | [group addCellWithCompletionHandle:^(ZHTableViewCell *cell) {
32 | cell.anyClass = [UITableViewCell class];
33 | cell.identifier = @"UITableViewCell";
34 | cell.cellNumber = titles.count;
35 | [cell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
36 | cell.textLabel.text = titles[indexPath.row];
37 | }];
38 | [cell setDidSelectRowCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
39 | if (indexPath.row == 0) {
40 | [self.updateTableViewDataSource reloadCellAutomaticHeightWithIdentifier:@"ReloadHeightCell1"];
41 | } else if (indexPath.row == 1) {
42 | [self.updateTableViewDataSource reloadCellFixedHeight:250 identifier:@"ReloadHeightCell1"];
43 | } else if (indexPath.row == 2) {
44 | [self.updateTableViewDataSource reloadCellAutomaticHeightWithClass:NSClassFromString(@"ReloadHeightCell1")];
45 | } else if (indexPath.row == 3) {
46 | [self.updateTableViewDataSource reloadCellFixedHeight:260 className:NSClassFromString(@"ReloadHeightCell1")];
47 | } else if (indexPath.row == 4) {
48 | [self.updateTableViewDataSource reloadCellAutomaticHeightWithTableViewCell:self.updateTableViewDataSource.groups[0].cells[0]];
49 | } else if (indexPath.row == 5) {
50 | [self.updateTableViewDataSource reloadCellFixedHeight:270 tableViewCell:self.updateTableViewDataSource.groups[0].cells[0]];
51 | } else if (indexPath.row == 6) {
52 | [self.updateTableViewDataSource reloadCellAutomicHeightWithGroupIndex:1 cellIndex:0];
53 | } else if (indexPath.row == 7) {
54 | [self.updateTableViewDataSource reloadCellFixedHeight:280 groupIndex:1 cellIndex:0];
55 | }
56 | [self dismissViewControllerAnimated:YES completion:nil];
57 | }];
58 | }];
59 | }];
60 | [self.tableViewDataSource reloadTableViewData];
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/TableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TableViewController.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface TableViewController : UIViewController
15 |
16 | @property (nonatomic, weak) IBOutlet UITableView *tableView;
17 | @property (nonatomic, strong, readonly) ZHTableViewDataSource *tableViewDataSource;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/TableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TableViewController.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 |
11 | @interface TableViewController ()
12 |
13 | @property (nonatomic, strong) ZHTableViewDataSource *tableViewDataSource;
14 |
15 | @end
16 |
17 | @implementation TableViewController
18 |
19 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
20 | nibNameOrNil = nibNameOrNil ?: @"TableViewController";
21 | nibBundleOrNil = nibBundleOrNil ?: [NSBundle mainBundle];
22 | if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
23 |
24 | }
25 | return self;
26 | }
27 |
28 | - (void)viewDidLoad {
29 | [super viewDidLoad];
30 |
31 | }
32 |
33 | - (ZHTableViewDataSource *)tableViewDataSource {
34 | if (!_tableViewDataSource) {
35 | _tableViewDataSource = [[ZHTableViewDataSource alloc] initWithTableView:self.tableView];
36 | }
37 | return _tableViewDataSource;
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/TableViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import
11 | #import "ReloadHeightViewController.h"
12 | #import "ReloadCellViewController.h"
13 | #import "ReloadCellDataViewController.h"
14 | #import "HiddenViewController.h"
15 |
16 | @interface ViewController ()
17 |
18 | @property (nonatomic, weak) IBOutlet UITableView *tableView;
19 | @property (nonatomic, strong) ZHTableViewDataSource *tableViewDataSource;
20 |
21 | @end
22 |
23 | @implementation ViewController
24 |
25 | - (void)viewDidLoad {
26 | [super viewDidLoad];
27 | [self.tableViewDataSource clearData];
28 | __weak typeof(self) weakSelf = self;
29 | [self.tableViewDataSource addGroupWithCompletionHandle:^(ZHTableViewGroup *group) {
30 | __strong typeof(weakSelf) strongSelf = weakSelf;
31 | [strongSelf addReloadHeightInGroup:group];
32 | [strongSelf addReloadCellInGroup:group];
33 | [strongSelf addReloadDataInGroup:group];
34 | [strongSelf addHiddenInGroup:group];
35 | }];
36 | [self.tableViewDataSource reloadTableViewData];
37 |
38 | }
39 |
40 | - (void)addReloadHeightInGroup:(ZHTableViewGroup *)group {
41 | [group addCellWithCompletionHandle:^(ZHTableViewCell *tableViewCell) {
42 | tableViewCell.anyClass = [UITableViewCell class];
43 | tableViewCell.identifier = @"UITableViewCell";
44 | [tableViewCell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
45 | cell.textLabel.text = @"刷新高度";
46 | NSLog(@"%@",cell);
47 | }];
48 | [tableViewCell setDidSelectRowCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
49 | ReloadHeightViewController *controller = [[ReloadHeightViewController alloc] initWithNibName:nil bundle:nil];
50 | [self.navigationController pushViewController:controller animated:YES];
51 | }];
52 | }];
53 | }
54 |
55 | - (void)addReloadCellInGroup:(ZHTableViewGroup *)group {
56 | [group addCellWithCompletionHandle:^(ZHTableViewCell *tableViewCell) {
57 | tableViewCell.anyClass = [UITableViewCell class];
58 | tableViewCell.identifier = @"UITableViewCell";
59 | [tableViewCell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
60 | cell.textLabel.text = @"刷新Cell";
61 | }];
62 | [tableViewCell setDidSelectRowCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
63 | ReloadCellViewController *controller = [[ReloadCellViewController alloc] initWithNibName:nil bundle:nil];
64 | [self.navigationController pushViewController:controller animated:YES];
65 | }];
66 | }];
67 | }
68 |
69 | - (void)addReloadDataInGroup:(ZHTableViewGroup *)group {
70 | [group addCellWithCompletionHandle:^(ZHTableViewCell *tableViewCell) {
71 | tableViewCell.anyClass = [UITableViewCell class];
72 | tableViewCell.identifier = @"UITableViewCell";
73 | [tableViewCell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
74 | cell.textLabel.text = @"刷新数据";
75 | }];
76 | [tableViewCell setDidSelectRowCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
77 | ReloadCellDataViewController *controller = [[ReloadCellDataViewController alloc] initWithNibName:nil bundle:nil];
78 | [self.navigationController pushViewController:controller animated:YES];
79 | }];
80 | }];
81 | }
82 |
83 | - (void)addHiddenInGroup:(ZHTableViewGroup *)group {
84 | [group addCellWithCompletionHandle:^(ZHTableViewCell *tableViewCell) {
85 | tableViewCell.anyClass = [UITableViewCell class];
86 | tableViewCell.identifier = @"UITableViewCell";
87 | [tableViewCell setConfigCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
88 | cell.textLabel.text = @"显示和隐藏";
89 | }];
90 | [tableViewCell setDidSelectRowCompletionHandle:^(UITableViewCell *cell, NSIndexPath *indexPath) {
91 | HiddenViewController *controller = [[HiddenViewController alloc] initWithNibName:nil bundle:nil];
92 | [self.navigationController pushViewController:controller animated:YES];
93 | }];
94 | }];
95 | }
96 |
97 | - (ZHTableViewDataSource *)tableViewDataSource {
98 | if (!_tableViewDataSource) {
99 | _tableViewDataSource = [[ZHTableViewDataSource alloc] initWithTableView:self.tableView];
100 | }
101 | return _tableViewDataSource;
102 | }
103 |
104 | @end
105 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupExample/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ZHTableViewGroupExample
4 | //
5 | // Created by josercc on 2020/2/25.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | NSString * appDelegateClassName;
14 | @autoreleasepool {
15 | // Setup code that might create autoreleased objects goes here.
16 | appDelegateClassName = NSStringFromClass([AppDelegate class]);
17 | }
18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName);
19 | }
20 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHAutoConfigurationCollectionViewDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHAutoConfigurationCollectionViewDelegate.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/4/20.
6 | //
7 | //
8 |
9 | #import
10 |
11 | typedef NS_ENUM(NSUInteger, ZHCollectionViewCustomHeightType) {
12 | ZHCollectionViewCustomHeightTypeCell,
13 | ZHCollectionViewCustomHeightTypeHeader,
14 | ZHCollectionViewCustomHeightTypeFooter
15 | };
16 |
17 | @class ZHCollectionViewDataSource;
18 |
19 | /**
20 | 自动配置 UICollectionView 的数据源和代理
21 | 默认实现 UICollectionView 的数据源方法和代理方法如下
22 | */
23 | @interface ZHAutoConfigurationCollectionViewDelegate : NSObject
24 |
25 | /**
26 | 初始化自动配置ZHAutoConfigurationCollectionViewDelegate对象
27 |
28 | @param dataSource ZHCollectionViewDataSource
29 | @return ZHAutoConfigurationCollectionViewDelegate
30 | */
31 | - (instancetype)initWithDataSource:(ZHCollectionViewDataSource *)dataSource;
32 |
33 | @end
34 |
35 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHAutoConfigurationCollectionViewDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHAutoConfigurationCollectionViewDelegate.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/4/20.
6 | //
7 | //
8 |
9 | #import "ZHAutoConfigurationCollectionViewDelegate.h"
10 | #import "ZHCollectionViewDataSource.h"
11 |
12 | @interface ZHAutoConfigurationCollectionViewDelegate ()
13 |
14 | @property (nonatomic, weak) ZHCollectionViewDataSource *dataSource;
15 |
16 | @end
17 |
18 |
19 | @implementation ZHAutoConfigurationCollectionViewDelegate {
20 |
21 | }
22 |
23 | - (instancetype)initWithDataSource:(ZHCollectionViewDataSource *)dataSource {
24 | if (self = [super init]) {
25 | _dataSource = dataSource;
26 | }
27 | return self;
28 | }
29 |
30 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
31 | return [ZHCollectionViewDataSource numberOfSectionsWithDataSource:_dataSource];
32 | }
33 |
34 | - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
35 | return [ZHCollectionViewDataSource cellForRowAtWithDataSource:_dataSource indexPath:indexPath];
36 | }
37 |
38 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
39 | return [ZHCollectionViewDataSource numberOfRowsInSectionWithDataSource:_dataSource section:section];
40 | }
41 |
42 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
43 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
44 | return [ZHCollectionViewDataSource viewForHeaderInSectionWithDataSource:_dataSource section:indexPath.section];
45 | } else {
46 | return [ZHCollectionViewDataSource viewForFooterInSectionWithDataSource:_dataSource section:indexPath.section];
47 | }
48 | }
49 |
50 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
51 | [collectionView deselectItemAtIndexPath:indexPath animated:YES];
52 | [ZHCollectionViewDataSource didSelectRowAtWithDataSource:_dataSource indexPath:indexPath];
53 | }
54 |
55 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
56 | return [ZHCollectionViewDataSource sizeForItemWithDataSource:_dataSource indexPath:indexPath];
57 | }
58 |
59 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
60 | return [ZHCollectionViewDataSource referenceSizeForHeaderFooterWithDataSource:_dataSource style:ZHCollectionViewHeaderFooterStyleHeader section:section];
61 | }
62 |
63 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section {
64 | return [ZHCollectionViewDataSource referenceSizeForHeaderFooterWithDataSource:_dataSource style:ZHCollectionViewHeaderFooterStyleFooter section:section];
65 | }
66 |
67 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
68 | ZHCollectionViewGroup *group = _dataSource.groups[section];
69 | return group.sectionEdgeInsets;
70 | }
71 |
72 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
73 | if (_dataSource.scrollViewDidEndDraggingWillDecelerate) {
74 | _dataSource.scrollViewDidEndDraggingWillDecelerate(scrollView, decelerate);
75 | }
76 |
77 | }
78 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
79 | if (_dataSource.scrollViewDidEndDecelerating) {
80 | _dataSource.scrollViewDidEndDecelerating(scrollView);
81 | }
82 | }
83 |
84 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
85 | if (_dataSource.scrollViewDidEndScrollingAnimation) {
86 | _dataSource.scrollViewDidEndScrollingAnimation(scrollView);
87 | }
88 | }
89 |
90 | @end
91 |
92 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHAutoConfigurationTableViewDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHAutoConfigurationTableViewDelegate.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/4/20.
6 | //
7 | //
8 |
9 | #import
10 |
11 | typedef NS_ENUM(NSUInteger, ZHTableViewCustomHeightType) {
12 | ZHTableViewCustomHeightTypeCell,
13 | ZHTableViewCustomHeightTypeHeader,
14 | ZHTableViewCustomHeightTypeFooter
15 | };
16 |
17 | @class ZHTableViewDataSource;
18 |
19 | /**
20 | 自动配置 UITableView 的数据源和代理
21 | 默认实现 UITableView 的数据源方法和代理方法如下
22 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
23 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
24 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
25 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
26 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
27 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
28 | - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
29 | - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
30 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
31 | */
32 | @interface ZHAutoConfigurationTableViewDelegate : NSObject
33 |
34 | /**
35 | 初始化自动配置ZHAutoConfigurationTableViewDelegate对象
36 |
37 | @param dataSource ZHTableViewDataSource
38 | @return ZHAutoConfigurationTableViewDelegate
39 | */
40 | - (instancetype)initWithDataSource:(ZHTableViewDataSource *)dataSource;
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHAutoConfigurationTableViewDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHAutoConfigurationTableViewDelegate.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/4/20.
6 | //
7 | //
8 |
9 | #import "ZHAutoConfigurationTableViewDelegate.h"
10 | #import "ZHTableViewDataSource.h"
11 |
12 | @interface ZHAutoConfigurationTableViewDelegate ()
13 |
14 | @property (nonatomic, weak) ZHTableViewDataSource *dataSource;
15 |
16 | @end
17 |
18 | @implementation ZHAutoConfigurationTableViewDelegate
19 |
20 | - (instancetype)initWithDataSource:(ZHTableViewDataSource *)dataSource {
21 | if (self = [super init]) {
22 | _dataSource = dataSource;
23 | }
24 | return self;
25 | }
26 |
27 | - (ZHTableViewDataSourceCustomHeightCompletionHandle)completionHandleWithTableView:(UITableView *)tableView
28 | heightAtIndexPath:(NSIndexPath *)indexPath {
29 | return ^CGFloat(ZHTableViewBaseModel *model) {
30 | if (!model.customHeightCompletionHandle) {
31 | return model.height;
32 | }
33 | NSIndexPath *reallyIndexPath = [ZHTableViewDataSource indexPathWithDataSource:self->_dataSource
34 | indexPath:indexPath];
35 | return model.customHeightCompletionHandle(tableView,reallyIndexPath,model);
36 | };;
37 | }
38 |
39 | - (CGFloat)tableView:(UITableView *)tableView
40 | heightForRowAtIndexPath:(NSIndexPath *)indexPath {
41 | ZHTableViewDataSourceCustomHeightCompletionHandle handle = [self completionHandleWithTableView:tableView
42 | heightAtIndexPath:indexPath];
43 | CGFloat height = [ZHTableViewDataSource heightForRowAtDataSource:_dataSource
44 | indexPath:indexPath
45 | customHeightCompletionHandle:handle];
46 | if (_dataSource.heightForRowAtIndexPath) {
47 | _dataSource.heightForRowAtIndexPath(tableView, indexPath, height);
48 | }
49 | return height;
50 | }
51 | - (CGFloat)tableView:(UITableView *)tableView
52 | heightForHeaderInSection:(NSInteger)section {
53 | CGFloat height = [ZHTableViewDataSource heightForHeaderInSectionWithDataSource:_dataSource
54 | section:section
55 | customHeightCompletionHandle:[self completionHandleWithTableView:tableView
56 | heightAtIndexPath:[NSIndexPath indexPathForRow:0
57 | inSection:section]]];
58 | if (_dataSource.heightForHeaderInSection) {
59 | _dataSource.heightForHeaderInSection(tableView, section, height);
60 | }
61 | return height;
62 | }
63 | - (CGFloat)tableView:(UITableView *)tableView
64 | heightForFooterInSection:(NSInteger)section {
65 | CGFloat height = [ZHTableViewDataSource heightForFooterInSectionWithDataSource:_dataSource section:section customHeightCompletionHandle:[self completionHandleWithTableView:tableView heightAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]]];
66 | if (_dataSource.heightForFooterInSection) {
67 | _dataSource.heightForFooterInSection(tableView, section, height);
68 | }
69 | return height;
70 | }
71 | - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
72 | return [ZHTableViewDataSource viewForHeaderInSectionWithDataSource:_dataSource section:section];
73 | }
74 | - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
75 | return [ZHTableViewDataSource viewForFooterInSectionWithDataSource:_dataSource section:section];
76 | }
77 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
78 | return [ZHTableViewDataSource numberOfRowsInSectionWithDataSource:_dataSource section:section];
79 | }
80 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
81 | return [ZHTableViewDataSource cellForRowAtWithDataSource:_dataSource indexPath:indexPath];
82 | }
83 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
84 | return [ZHTableViewDataSource numberOfSectionsWithDataSource:_dataSource];
85 | }
86 |
87 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
88 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
89 | [ZHTableViewDataSource didSelectRowAtWithDataSource:_dataSource indexPath:indexPath];
90 | }
91 |
92 | - (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section {
93 |
94 | }
95 |
96 | - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
97 |
98 | }
99 |
100 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
101 | [ZHTableViewDataSource dataSource:_dataSource willDisplayCell:cell forRowAtIndexPath:indexPath];
102 | }
103 |
104 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
105 | if (_dataSource.scrollViewDidScrollCompletionHandle) {
106 | _dataSource.scrollViewDidScrollCompletionHandle(scrollView);
107 | }
108 | }
109 |
110 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView {
111 | if (_dataSource.scrollViewDidZoom) {
112 | _dataSource.scrollViewDidZoom(scrollView);
113 | }
114 | }
115 |
116 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
117 | if (_dataSource.scrollViewWillBeginDraggingCompletionHandle) {
118 | _dataSource.scrollViewWillBeginDraggingCompletionHandle(scrollView);
119 | }
120 | }
121 |
122 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
123 | if (_dataSource.scrollViewWillEndDragging) {
124 | _dataSource.scrollViewWillEndDragging(scrollView, velocity, targetContentOffset);
125 | }
126 | }
127 |
128 |
129 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
130 | if (_dataSource.scrollViewDidEndDragging) {
131 | _dataSource.scrollViewDidEndDragging(scrollView, decelerate);
132 | }
133 | }
134 |
135 | - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
136 | if (_dataSource.scrollViewWillBeginDecelerating) {
137 | _dataSource.scrollViewWillBeginDecelerating(scrollView);
138 | }
139 | }
140 |
141 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
142 | if (_dataSource.scrollViewDidEndDecelerating) {
143 | _dataSource.scrollViewDidEndDecelerating(scrollView);
144 | }
145 | }
146 |
147 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
148 | if (_dataSource.scrollViewDidEndScrollingAnimation) {
149 | _dataSource.scrollViewDidEndScrollingAnimation(scrollView);
150 | }
151 | }
152 |
153 | - (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
154 | if (_dataSource.viewForZoomingInScrollView) {
155 | return _dataSource.viewForZoomingInScrollView(scrollView);
156 | }
157 | return nil;
158 | }
159 |
160 | - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view {
161 | if (_dataSource.scrollViewWillBeginZooming) {
162 | _dataSource.scrollViewWillBeginZooming(scrollView,view);
163 | }
164 | }
165 |
166 | - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale {
167 | if (_dataSource.scrollViewDidEndZooming) {
168 | _dataSource.scrollViewDidEndZooming(scrollView,view,scale);
169 | }
170 | }
171 |
172 | - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
173 | if (_dataSource.scrollViewShouldScrollToTop) {
174 | return _dataSource.scrollViewShouldScrollToTop(scrollView);
175 | }
176 | return YES;
177 | }
178 |
179 | - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView {
180 | if (_dataSource.scrollViewDidScrollToTop) {
181 | _dataSource.scrollViewDidScrollToTop(scrollView);
182 | }
183 | }
184 |
185 | - (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView {
186 | if (_dataSource.scrollViewDidChangeAdjustedContentInset) {
187 | _dataSource.scrollViewDidChangeAdjustedContentInset(scrollView);
188 | }
189 | }
190 |
191 | @end
192 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewBaseModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewBaseModel.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import
10 | @class ZHCollectionViewBaseModel;
11 |
12 | typedef CGFloat (^ZHCollectionViewBaseModelCustomHeightCompletionHandle)(UICollectionView *collectionView, NSIndexPath *indexPath, ZHCollectionViewBaseModel *model);
13 |
14 | /**
15 | 配置 Cell Header Footer 的数据 Model
16 | */
17 | @interface ZHCollectionViewBaseModel : NSObject
18 |
19 | /**
20 | 标识符
21 | */
22 | @property (nonatomic, copy) NSString *identifier;
23 | /**
24 | 自定义类 Class
25 | */
26 | @property (nonatomic, strong) Class anyClass;
27 | /**
28 | 高度 默认为 NSNotFound
29 | height 属性废弃 用size
30 | */
31 | //@property (nonatomic, assign) CGFloat height;
32 |
33 |
34 | /**
35 | * 设置 UICollectionCell UICollectionReusableView 的大小
36 | * 默认 CGSizeZero
37 | */
38 | @property (nonatomic, assign) CGSize size;
39 |
40 | /**
41 | * 自定义高度
42 | */
43 | @property (nonatomic, copy) ZHCollectionViewBaseModelCustomHeightCompletionHandle customHeightCompletionHandle;
44 |
45 | @end
46 |
47 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewBaseModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewBaseModel.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import "ZHCollectionViewBaseModel.h"
10 |
11 | @implementation ZHCollectionViewBaseModel
12 |
13 | - (instancetype)init {
14 | if (self = [super init]) {
15 | _size = CGSizeZero;
16 | }
17 | return self;
18 | }
19 |
20 | @end
21 |
22 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | //
3 | // ZHCollectionViewCell.h
4 | // Pods
5 | //
6 | // Created by 张行 on 2018/2/6.
7 | //
8 | //
9 |
10 | #import "ZHCollectionViewBaseModel.h"
11 |
12 | /**
13 | 注册 Cell 样式
14 | */
15 | @interface ZHCollectionViewCell : ZHCollectionViewBaseModel
16 |
17 | /**
18 | Cell 的个数 默认为1
19 | */
20 | @property (nonatomic, assign) NSInteger cellNumber;
21 | /**
22 | 配置 Cell的回调
23 | */
24 | @property (nonatomic, copy) void(^configCompletionHandle)(CellType cell, NSIndexPath *indexPath);
25 | /**
26 | 点击 Cell 的回调
27 | */
28 | @property (nonatomic, copy) void(^didSelectRowCompletionHandle)(CellType cell, NSIndexPath *indexPath);
29 | @property (nonatomic, copy) CGSize(^customSizeBlock)(CellType cell, NSIndexPath *indexPath);
30 |
31 | /**
32 | * 为了是支持泛型
33 |
34 | @param configCompletionHandle 设置的Block
35 | */
36 | - (void)setConfigCompletionHandle:(void (^)(CellType cell, NSIndexPath * indexPath))configCompletionHandle;
37 |
38 | /**
39 | * 为了支持泛型
40 |
41 | @param didSelectRowCompletionHandle 点击回调的block
42 | */
43 | - (void)setDidSelectRowCompletionHandle:(void (^)(CellType cell, NSIndexPath * indexPath))didSelectRowCompletionHandle;
44 |
45 | /**
46 | 点击所在的 Cell 的执行方法
47 |
48 | @param cell 点击的 Cell
49 | @param indexPath 点击 cell 所在的索引
50 | */
51 | - (void)didSelectRowAtWithCell:(CellType)cell
52 | indexPath:(NSIndexPath *)indexPath;
53 |
54 | /**
55 | 配置 Cell 的执行方法
56 |
57 | @param cell 配置的 Cell
58 | @param indexPath 配置 Cell 所在的索引
59 | */
60 | - (void)configCellWithCell:(CellType)cell
61 | indexPath:(NSIndexPath *)indexPath;
62 |
63 | /**
64 | 一个方法配置所有的参数
65 |
66 | @param cellNumber cell 的数量
67 | @param identifier 标识符
68 | @param anyClass cell 的类名
69 | @param size 高度
70 | @param configCompletionHandle 配置 cell
71 | @param didSelectRowCompletionHandle 点击 cell 方法
72 | */
73 | - (void)configurationCellWithCellNumber:(NSUInteger)cellNumber
74 | identifier:(NSString *)identifier
75 | anyClass:(Class)anyClass
76 | size:(CGSize)size
77 | configCompletionHandle:(void(^)(CellType cell, NSIndexPath *indexPath))configCompletionHandle
78 | didSelectRowCompletionHandle:(void(^)(CellType cell, NSIndexPath *indexPath))didSelectRowCompletionHandle;
79 |
80 | @end
81 |
82 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewCell.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import "ZHCollectionViewCell.h"
10 |
11 | @implementation ZHCollectionViewCell {
12 | }
13 |
14 | - (instancetype)init {
15 | if (self = [super init]) {
16 | _cellNumber = 1;
17 | }
18 | return self;
19 | }
20 |
21 | - (void)setConfigCompletionHandle:(void (^)(UICollectionViewCell *, NSIndexPath *))configCompletionHandle {
22 | _configCompletionHandle = configCompletionHandle;
23 | }
24 |
25 | - (void)setDidSelectRowCompletionHandle:(void (^)(UICollectionViewCell *, NSIndexPath *))didSelectRowCompletionHandle {
26 | _didSelectRowCompletionHandle = didSelectRowCompletionHandle;
27 | }
28 |
29 | - (void)didSelectRowAtWithCell:(UICollectionViewCell *)cell
30 | indexPath:(NSIndexPath *)indexPath {
31 | if (!self.didSelectRowCompletionHandle) {
32 | return;
33 | }
34 | self.didSelectRowCompletionHandle(cell,indexPath);
35 | }
36 |
37 | - (void)configCellWithCell:(UICollectionViewCell *)cell
38 | indexPath:(NSIndexPath *)indexPath {
39 | if (!self.configCompletionHandle) {
40 | return;
41 | }
42 | self.configCompletionHandle(cell,indexPath);
43 | }
44 |
45 | - (void)configurationCellWithCellNumber:(NSUInteger)cellNumber
46 | identifier:(NSString *)identifier
47 | anyClass:(Class)anyClass
48 | size:(CGSize)size
49 | configCompletionHandle:(void (^)(UICollectionViewCell *, NSIndexPath *))configCompletionHandle
50 | didSelectRowCompletionHandle:(void (^)(UICollectionViewCell *, NSIndexPath *))didSelectRowCompletionHandle {
51 | self.cellNumber = cellNumber;
52 | self.identifier = identifier;
53 | self.anyClass = anyClass;
54 | self.size = size;
55 | self.configCompletionHandle = configCompletionHandle;
56 | self.didSelectRowCompletionHandle = didSelectRowCompletionHandle;
57 | }
58 |
59 | @end
60 |
61 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewDataSource.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewDataSource.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import
10 | #import "ZHCollectionViewGroup.h"
11 | #import "ZHAutoConfigurationCollectionViewDelegate.h"
12 |
13 | /**
14 | 添加分组的回调
15 |
16 | @param group 创建的分组对象
17 | */
18 | typedef void(^ZHCollectionViewDataSourceAddGroupCompletionHandle)(ZHCollectionViewGroup *group);
19 |
20 | /**
21 | 自定义高度的回调
22 |
23 | @return 自定义算法返回的高度
24 | */
25 | typedef CGFloat (^ZHCollectionViewDataSourceCustomHeightCompletionHandle)(ZHCollectionViewBaseModel *model);
26 |
27 | /**
28 | 进行 UICollectionView 进行数据托管的数据源
29 | */
30 | @interface ZHCollectionViewDataSource : NSObject
31 |
32 | /**
33 | 自动配置 UICollectionView 的 DataSource 和 Delegate 默认为 YES
34 | */
35 | @property (nonatomic, assign, getter=isAutoConfigurationCollectionViewDelegate) BOOL autoConfigurationCollectionViewDelegate;
36 |
37 | @property (nonatomic, strong, readonly) NSMutableArray *groups;
38 |
39 | /**
40 | 唯一的初始化ZHCollectionViewDataSource
41 |
42 | @param CollectionView 托管的 UICollectionView 的对象 必须存在
43 | @return ZHCollectionViewDataSource的对象
44 | */
45 | - (instancetype)initWithCollectionView:(UICollectionView *)CollectionView;
46 |
47 | /**
48 | 添加一个分组
49 |
50 | @param completionHandle 返回新注册的分组对象 可以进行配置
51 | */
52 | - (void)addGroupWithCompletionHandle:(ZHCollectionViewDataSourceAddGroupCompletionHandle)completionHandle;
53 |
54 | /**
55 | 进行刷新 UICollectionView
56 | */
57 | - (void)reloadCollectionViewData;
58 |
59 | /**
60 | 获取分组Cell的个数 如果autoConfigurationCollectionViewDelegate = YES 此方法不用调用
61 |
62 | @param dataSource ZHCollectionViewDataSource数据源
63 | @param section 所在组索引
64 | @return 分组 Cell 的个数
65 | */
66 | + (NSInteger)numberOfRowsInSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource section:(NSInteger)section;
67 |
68 | /**
69 | 获取对应索引的UICollectionViewCell 如果autoConfigurationCollectionViewDelegate = YES 此方法不用调用
70 |
71 | @param dataSource ZHCollectionViewDataSource数据源
72 | @param indexPath 所在的索引
73 | @return UICollectionViewCell
74 | */
75 | + (UICollectionViewCell *)cellForRowAtWithDataSource:(ZHCollectionViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
76 |
77 | /**
78 | 获取分组的个数 如果autoConfigurationCollectionViewDelegate = YES 此方法不用调用
79 |
80 | @param dataSource ZHCollectionViewDataSource的数据源
81 | @return 分组的个数
82 | */
83 | + (NSInteger)numberOfSectionsWithDataSource:(ZHCollectionViewDataSource *)dataSource;
84 |
85 | /**
86 | 点击 Cell 的回调
87 |
88 | @param dataSource ZHCollectionViewDataSource数据源
89 | @param indexPath 点击的索引
90 | */
91 | + (void)didSelectRowAtWithDataSource:(ZHCollectionViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
92 |
93 | /**
94 | 获取Header
95 |
96 | @param dataSource ZHCollectionViewDataSource数据源
97 | @param section 分组的索引
98 | @return 分组 Header 试图
99 | */
100 | + (UICollectionReusableView *)viewForHeaderInSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource section:(NSInteger)section;
101 | /**
102 | 获取Footer
103 |
104 | @param dataSource ZHCollectionViewDataSource数据源
105 | @param section 分组的索引
106 | @return 分组 Footer 试图
107 | */
108 | + (UICollectionReusableView *)viewForFooterInSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource section:(NSInteger)section;
109 |
110 | /**
111 | 清空之前数据
112 | */
113 | - (void)clearData;
114 |
115 | + (NSIndexPath *)indexPathWithDataSource:(ZHCollectionViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
116 |
117 | + (CGSize)sizeForItemWithDataSource:(ZHCollectionViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
118 |
119 | + (CGSize)referenceSizeForHeaderFooterWithDataSource:(ZHCollectionViewDataSource *)dataSource style:(ZHCollectionViewHeaderFooterStyle)style section:(NSUInteger)section;
120 |
121 | @property (nonatomic, copy) void (^scrollViewDidEndDraggingWillDecelerate)(UIScrollView *scrollView, BOOL willDecelerate);
122 | @property (nonatomic, copy) void (^scrollViewDidEndDecelerating)(UIScrollView *scrollView);
123 | @property (nonatomic, copy) void (^scrollViewDidEndScrollingAnimation)(UIScrollView *scrollView);
124 |
125 | @end
126 |
127 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewDataSource.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewDataSource.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import "ZHCollectionViewDataSource.h"
10 | #import "ZHAutoConfigurationCollectionViewDelegate.h"
11 |
12 | @interface ZHCollectionViewDataSource ()
13 |
14 | @property (nonatomic, strong) NSMutableArray *groups;
15 | @property (nonatomic, weak) UICollectionView *collectionView;
16 | @property (nonatomic, strong) ZHAutoConfigurationCollectionViewDelegate *autoConfiguration;
17 |
18 | @end
19 |
20 | @implementation ZHCollectionViewDataSource {
21 |
22 | }
23 |
24 | - (void)dealloc {
25 | NSLog(@"ZHCollectionViewDataSource 释放了");
26 | }
27 |
28 | - (instancetype)initWithCollectionView:(UICollectionView *)CollectionView {
29 | if (self = [super init]) {
30 | _collectionView = CollectionView;
31 | _autoConfigurationCollectionViewDelegate = YES;
32 | }
33 | return self;
34 | }
35 |
36 | - (void)addGroupWithCompletionHandle:(ZHCollectionViewDataSourceAddGroupCompletionHandle)completionHandle {
37 | ZHCollectionViewGroup *group = [[ZHCollectionViewGroup alloc] init];
38 | if (completionHandle) {
39 | completionHandle(group);
40 | }
41 | [self.groups addObject:group];
42 | }
43 |
44 | - (void)reloadCollectionViewData {
45 | if (!self.collectionView.dataSource && self.isAutoConfigurationCollectionViewDelegate) {
46 | self.collectionView.dataSource = self.autoConfiguration;
47 | }
48 | if (!self.collectionView.delegate && self.isAutoConfigurationCollectionViewDelegate) {
49 | self.collectionView.delegate = self.autoConfiguration;
50 | }
51 | [self registerClasss];
52 | [self.collectionView reloadData];
53 | }
54 |
55 | + (NSInteger)numberOfRowsInSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource
56 | section:(NSInteger)section {
57 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:section];
58 | if (!group) {
59 | return 0;
60 | }
61 | return group.cellCount;
62 | }
63 |
64 | + (UICollectionViewCell *)cellForRowAtWithDataSource:(ZHCollectionViewDataSource *)dataSource
65 | indexPath:(NSIndexPath *)indexPath {
66 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
67 | UICollectionViewCell *cell = [[UICollectionViewCell alloc] initWithFrame:CGRectZero];
68 | if (!group) {
69 | return cell;
70 | }
71 | UICollectionViewCell *resultCell = [group cellForCollectionViewWithCollectionView:dataSource.collectionView indexPath:indexPath];
72 | if (!resultCell) {
73 | return cell;
74 | }
75 | return resultCell;
76 | }
77 |
78 | + (NSInteger)numberOfSectionsWithDataSource:(ZHCollectionViewDataSource *)dataSource {
79 | if (!dataSource) {
80 | return 0;
81 | }
82 | return dataSource.groups.count;
83 | }
84 |
85 | + (void)didSelectRowAtWithDataSource:(ZHCollectionViewDataSource *)dataSource
86 | indexPath:(NSIndexPath *)indexPath {
87 | ZHCollectionViewCell *CollectionViewCell = [self cellForIndexPath:dataSource indexPath:indexPath];
88 | if (!CollectionViewCell) {
89 | return;
90 | }
91 | UICollectionViewCell *cell = [self cellForRowAtWithDataSource:dataSource indexPath:indexPath];
92 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
93 | [CollectionViewCell didSelectRowAtWithCell:cell indexPath:[group indexPathWithCell:CollectionViewCell indexPath:indexPath]];
94 | }
95 |
96 | + (UICollectionReusableView *)viewForHeaderInSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource
97 | section:(NSInteger)section {
98 | return [self viewHeaderFooterInSectionWithDtaSource:dataSource section:section style:ZHCollectionViewHeaderFooterStyleHeader];
99 | }
100 |
101 | + (UICollectionReusableView *)viewForFooterInSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource
102 | section:(NSInteger)section {
103 | return [self viewHeaderFooterInSectionWithDtaSource:dataSource section:section style:ZHCollectionViewHeaderFooterStyleFooter];
104 | }
105 |
106 | - (void)clearData {
107 | [self.groups removeAllObjects];
108 | }
109 |
110 | + (UICollectionReusableView *)viewHeaderFooterInSectionWithDtaSource:(ZHCollectionViewDataSource *)dataSource
111 | section:(NSInteger)section style:(ZHCollectionViewHeaderFooterStyle)style {
112 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:section];
113 | if (!group) {
114 | return nil;
115 | }
116 | return [group headerFooterForStyle:style collectionView:dataSource.collectionView section:section];
117 | }
118 |
119 | + (CGFloat)heightWithCustomHandle:(CGFloat)height
120 | customCompletionHandle:(ZHCollectionViewDataSourceCustomHeightCompletionHandle)customCompletionHandle
121 | baseModel:(ZHCollectionViewBaseModel *)baseModel {
122 | if (height != 0 && height != NSNotFound && height != CGFLOAT_MAX) {
123 | return height;
124 | }
125 | if (customCompletionHandle) {
126 | return customCompletionHandle(baseModel);
127 | }
128 | return 44;
129 | }
130 |
131 |
132 | + (ZHCollectionViewGroup *)groupForSectionWithDataSource:(ZHCollectionViewDataSource *)dataSource
133 | section:(NSInteger)section {
134 | if (!dataSource) {
135 | return nil;
136 | }
137 | if (dataSource.groups.count <= section) {
138 | return nil;
139 | }
140 | return dataSource.groups[section];
141 | }
142 |
143 | + (ZHCollectionViewCell *)cellForIndexPath:(ZHCollectionViewDataSource *)dataSource
144 | indexPath:(NSIndexPath *)indexPath {
145 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
146 | if (!group) {
147 | return nil;
148 | }
149 | return [group CollectionViewCellForIndexPath:indexPath];
150 | }
151 |
152 | + (NSIndexPath *)indexPathWithDataSource:(ZHCollectionViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath {
153 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
154 | ZHCollectionViewCell *CollectionViewCell = [self cellForIndexPath:dataSource indexPath:indexPath];
155 | return [group indexPathWithCell:CollectionViewCell indexPath:indexPath];
156 | }
157 |
158 | + (CGSize)sizeForItemWithDataSource:(ZHCollectionViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath {
159 | ZHCollectionViewCell *cell = [self cellForIndexPath:dataSource indexPath:indexPath];
160 | if (!CGSizeEqualToSize(cell.size, CGSizeZero)) {
161 | return cell.size;
162 | }
163 | UICollectionViewCell *collectionViewCell = [dataSource collectionViewWithClass:cell.anyClass];
164 | [cell configCellWithCell:collectionViewCell indexPath:indexPath];
165 | return [collectionViewCell sizeThatFits:[dataSource sizeFit]];
166 | }
167 |
168 | + (CGSize)referenceSizeForHeaderFooterWithDataSource:(ZHCollectionViewDataSource *)dataSource style:(ZHCollectionViewHeaderFooterStyle)style section:(NSUInteger)section {
169 | ZHCollectionViewGroup *group = [self groupForSectionWithDataSource:dataSource section:section];
170 | ZHCollectionViewHeaderFooter *headerFooter = style == ZHCollectionViewHeaderFooterStyleHeader ? group.header : group.footer;
171 | if (!CGSizeEqualToSize(headerFooter.size, CGSizeZero)) {
172 | return headerFooter.size;
173 | }
174 | UICollectionReusableView *view = [[headerFooter.anyClass alloc] initWithFrame:CGRectZero];
175 | [headerFooter setHeaderFooter:view section:section];
176 | return [view sizeThatFits:[dataSource sizeFit]];
177 | }
178 |
179 | - (UICollectionViewCell *)collectionViewWithClass:(Class)class {
180 | UICollectionViewCell *cell = [[class alloc] initWithFrame:CGRectZero];
181 | return cell;
182 | }
183 |
184 | - (CGSize)sizeFit {
185 | return CGSizeMake(CGRectGetWidth(_collectionView.frame), CGFLOAT_MAX);
186 | }
187 |
188 | - (void)registerClasss {
189 | for (ZHCollectionViewGroup *group in self.groups) {
190 | [group registerHeaderFooterCellWithCollectionView:self.collectionView];
191 | }
192 | }
193 |
194 | - (NSMutableArray *)groups {
195 | if (!_groups) {
196 | _groups = [NSMutableArray array];
197 | }
198 | return _groups;
199 | }
200 |
201 | - (ZHAutoConfigurationCollectionViewDelegate *)autoConfiguration {
202 | if (!_autoConfiguration) {
203 | _autoConfiguration = [[ZHAutoConfigurationCollectionViewDelegate alloc] initWithDataSource:self];
204 | }
205 | return _autoConfiguration;
206 | }
207 |
208 | @end
209 |
210 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewGroup.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewGroup.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import
10 | #import "ZHCollectionViewHeaderFooter.h"
11 | #import "ZHCollectionViewCell.h"
12 |
13 | typedef void(^ZHCollectionViewGroupAddCellCompletionHandle)(ZHCollectionViewCell *cell);
14 | typedef void(^ZHCollectionViewGroupAddHeaderFooterCompletionHandle)(ZHCollectionViewHeaderFooter *headerFooter);
15 |
16 | @interface ZHCollectionViewGroup : NSObject
17 |
18 | @property (nonatomic, strong) ZHCollectionViewHeaderFooter *header;
19 | @property (nonatomic, strong) ZHCollectionViewHeaderFooter *footer;
20 | @property (nonatomic, assign, readonly) NSInteger cellCount;
21 | @property (nonatomic, strong, readonly) NSMutableArray *cells;
22 | @property (nonatomic, assign) UIEdgeInsets sectionEdgeInsets;
23 |
24 | - (void)registerHeaderFooterCellWithCollectionView:(UICollectionView *)CollectionView;
25 |
26 | - (UICollectionViewCell *)cellForCollectionViewWithCollectionView:(UICollectionView *)CollectionView indexPath:(NSIndexPath *)indexPath;
27 |
28 | - (void)addCellWithCompletionHandle:(ZHCollectionViewGroupAddCellCompletionHandle)completionHandle;
29 |
30 | - (void)addHeaderWithCompletionHandle:(ZHCollectionViewGroupAddHeaderFooterCompletionHandle)completionHandle;
31 |
32 | - (void)addFooterWithCompletionHandle:(ZHCollectionViewGroupAddHeaderFooterCompletionHandle)completionHandle;
33 |
34 | - (ZHCollectionViewCell *)CollectionViewCellForIndexPath:(NSIndexPath *)indexPath;
35 |
36 | - (UICollectionReusableView *)headerFooterForStyle:(ZHCollectionViewHeaderFooterStyle)style collectionView:(UICollectionView *)collectionView section:(NSUInteger)section;
37 |
38 | - (NSIndexPath *)indexPathWithCell:(ZHCollectionViewCell *)cell indexPath:(NSIndexPath *)indexPath;
39 | @end
40 |
41 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewGroup.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewGroup.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import "ZHCollectionViewGroup.h"
10 |
11 | @interface ZHCollectionViewGroup ()
12 |
13 | @property (nonatomic, strong) NSMutableArray *cells;
14 |
15 | @end
16 |
17 | @implementation ZHCollectionViewGroup
18 |
19 | - (instancetype)init {
20 | if (self = [super init]) {
21 | _sectionEdgeInsets = UIEdgeInsetsZero;
22 | }
23 | return self;
24 | }
25 |
26 | - (void)registerHeaderFooterCellWithCollectionView:(UICollectionView *)collectionView {
27 | if (self.header && self.header.identifier) {
28 | [collectionView registerClass:self.header.anyClass forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:self.header.identifier];
29 | }
30 | if (self.footer && self.footer.identifier) {
31 | [collectionView registerClass:self.footer.anyClass forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:self.footer.identifier];
32 | }
33 | for (ZHCollectionViewCell *collectionViewCell in self.cells) {
34 | if (collectionViewCell.identifier) {
35 | [collectionView registerClass:collectionViewCell.anyClass forCellWithReuseIdentifier:collectionViewCell.identifier];
36 | }
37 | }
38 | }
39 |
40 | - (void)addCellWithCompletionHandle:(ZHCollectionViewGroupAddCellCompletionHandle)completionHandle {
41 | ZHCollectionViewCell *cell = [[ZHCollectionViewCell alloc] init];
42 | if (completionHandle) {
43 | completionHandle(cell);
44 | }
45 | [self.cells addObject:cell];
46 | }
47 |
48 | - (void)addHeaderWithCompletionHandle:(ZHCollectionViewGroupAddHeaderFooterCompletionHandle)completionHandle {
49 | ZHCollectionViewHeaderFooter *header= [[ZHCollectionViewHeaderFooter alloc] initWithStyle:ZHCollectionViewHeaderFooterStyleHeader];
50 | if (completionHandle) {
51 | completionHandle(header);
52 | }
53 | _header = header;
54 | }
55 |
56 | - (void)addFooterWithCompletionHandle:(ZHCollectionViewGroupAddHeaderFooterCompletionHandle)completionHandle {
57 | ZHCollectionViewHeaderFooter *footer = [[ZHCollectionViewHeaderFooter alloc] initWithStyle:ZHCollectionViewHeaderFooterStyleFooter];
58 | if (completionHandle) {
59 | completionHandle(footer);
60 | }
61 | _footer = footer;
62 | }
63 |
64 | - (UICollectionViewCell *)cellForCollectionViewWithCollectionView:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath {
65 | if (!collectionView) {
66 | return nil;
67 | }
68 | ZHCollectionViewCell *collectionViewCell = [self CollectionViewCellForIndexPath:indexPath];
69 | if (!collectionViewCell) {
70 | return nil;
71 | }
72 | if (!collectionViewCell.identifier) {
73 | return nil;
74 | }
75 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionViewCell.identifier forIndexPath:indexPath];
76 | [collectionViewCell configCellWithCell:cell indexPath:[self indexPathWithCell:collectionViewCell indexPath:indexPath]];
77 | return cell;
78 | }
79 |
80 | - (NSIndexPath *)indexPathWithCell:(ZHCollectionViewCell *)cell indexPath:(NSIndexPath *)indexPath {
81 | __block NSUInteger startIndex = 0;
82 | [self.cells enumerateObjectsUsingBlock:^(ZHCollectionViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
83 | if (obj == cell) {
84 | *stop = YES;
85 | return;
86 | }
87 | startIndex += obj.cellNumber;
88 | }];
89 | return [NSIndexPath indexPathForRow:indexPath.row - startIndex inSection:indexPath.section];
90 | }
91 |
92 | - (ZHCollectionViewCell *)CollectionViewCellForIndexPath:(NSIndexPath *)indexPath {
93 | if (indexPath.row >= self.cellCount) {
94 | return nil;
95 | }
96 | NSInteger count = 0;
97 | ZHCollectionViewCell *CollectionViewCell;
98 | for (NSUInteger i = 0; i < self.cells.count; i ++) {
99 | ZHCollectionViewCell *cell = self.cells[i];
100 | NSUInteger tempCount = count;
101 | count += cell.cellNumber;
102 | if (indexPath.row >= tempCount && indexPath.row < count) {
103 | CollectionViewCell = cell;
104 | break;
105 | }
106 | }
107 | return CollectionViewCell;
108 | }
109 |
110 | - (UICollectionReusableView *)headerFooterForStyle:(ZHCollectionViewHeaderFooterStyle)style collectionView:(UICollectionView *)collectionView section:(NSUInteger)section {
111 | if (!collectionView) {
112 | return nil;
113 | }
114 | ZHCollectionViewHeaderFooter *headerFooter;
115 | NSString *kind;
116 | switch (style) {
117 | case ZHCollectionViewHeaderFooterStyleHeader: {
118 | headerFooter = self.header;
119 | kind = UICollectionElementKindSectionHeader;
120 | }
121 | break;
122 | case ZHCollectionViewHeaderFooterStyleFooter: {
123 | headerFooter = self.footer;
124 | kind = UICollectionElementKindSectionFooter;
125 | }
126 | break;
127 | }
128 | if (!headerFooter) {
129 | return nil;
130 | }
131 | if (!headerFooter.identifier) {
132 | return nil;
133 | }
134 | UICollectionReusableView *headerFooterView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:headerFooter.identifier forIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]];
135 | [headerFooter setHeaderFooter:headerFooterView section:section];
136 | return headerFooterView;
137 | }
138 |
139 |
140 | - (NSMutableArray *)cells {
141 | if (!_cells) {
142 | _cells = [NSMutableArray array];
143 | }
144 | return _cells;
145 | }
146 |
147 | - (NSInteger)cellCount {
148 | NSInteger count = 0;
149 | for (ZHCollectionViewCell *collectionViewCell in self.cells) {
150 | count += collectionViewCell.cellNumber;
151 | }
152 | return count;
153 | }
154 |
155 | @end
156 |
157 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewHeaderFooter.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionVieweaderFooter.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import
10 | #import "ZHCollectionViewBaseModel.h"
11 |
12 | /**
13 | * 配置UICollectionVieweaderFooterView的回调
14 |
15 | @param headerFooterView 需要设置配置的UICollectionVieweaderFooterView
16 | @param section 需要配置的组
17 | */
18 | typedef void(^ZHCollectionViewHeaderFooterCompletionHandle)(UICollectionReusableView *headerFooterView, NSUInteger section);
19 |
20 | typedef NS_ENUM(NSUInteger, ZHCollectionViewHeaderFooterStyle) {
21 | ZHCollectionViewHeaderFooterStyleHeader,
22 | ZHCollectionViewHeaderFooterStyleFooter
23 | };
24 |
25 | @interface ZHCollectionViewHeaderFooter : ZHCollectionViewBaseModel
26 |
27 | @property (nonatomic, assign) ZHCollectionViewHeaderFooterStyle style;
28 | @property (nonatomic, copy) CGSize(^customSizeBlock)(HeaderFooter view, NSUInteger section);
29 |
30 | /**
31 | * 根据样式进行初始化ZHCollectionVieweaderFooter
32 |
33 | @param style 样式
34 | @return ZHCollectionVieweaderFooter
35 | */
36 | - (instancetype)initWithStyle:(ZHCollectionViewHeaderFooterStyle)style;
37 |
38 | /**
39 | * 执行配置UICollectionVieweaderFooterView
40 |
41 | @param headerFooter UICollectionVieweaderFooterView的泛型
42 | @param section 配置所在的Section
43 | */
44 | - (void)setHeaderFooter:(HeaderFooter)headerFooter section:(NSUInteger)section;
45 |
46 | /**
47 | * 配置Header的回调
48 |
49 | @param block 配置的Block
50 | */
51 | - (void)configurationHeader:(void(^)(HeaderFooter header, NSUInteger section))block;
52 | /**
53 | * 配置Footer的回调
54 |
55 | @param block 配置的Block
56 | */
57 | - (void)configurationFooter:(void(^)(HeaderFooter footer, NSUInteger section))block;
58 |
59 | @end
60 |
61 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHCollectionViewHeaderFooter.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHCollectionViewHeaderFooter.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2018/2/6.
6 | //
7 | //
8 |
9 | #import "ZHCollectionViewHeaderFooter.h"
10 |
11 | @implementation ZHCollectionViewHeaderFooter {
12 | ZHCollectionViewHeaderFooterCompletionHandle _headerBlock;
13 | ZHCollectionViewHeaderFooterCompletionHandle _footerBlock;
14 | }
15 |
16 | - (instancetype)initWithStyle:(ZHCollectionViewHeaderFooterStyle)style {
17 | if (self = [super init]) {
18 | _style = style;
19 | }
20 | return self;
21 | }
22 |
23 | - (void)setHeaderFooter:(UICollectionReusableView *)headerFooter section:(NSUInteger)section {
24 | switch (self.style) {
25 | case ZHCollectionViewHeaderFooterStyleHeader: {
26 | if (_headerBlock) {
27 | _headerBlock(headerFooter,section);
28 | }
29 | }
30 | break;
31 | case ZHCollectionViewHeaderFooterStyleFooter: {
32 | if (_footerBlock) {
33 | _footerBlock(headerFooter,section);
34 | }
35 | }
36 | break;
37 | default:
38 | break;
39 | }
40 | }
41 |
42 | - (void)configurationHeader:(void (^)(UICollectionReusableView *header, NSUInteger section))block {
43 | _headerBlock = block;
44 | }
45 |
46 | -(void)configurationFooter:(void (^)(UICollectionReusableView *footer, NSUInteger section))block {
47 | _footerBlock = block;
48 | }
49 |
50 | @end
51 |
52 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewBaseModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewBaseModel.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 | #import
9 | @class ZHTableViewBaseModel;
10 |
11 | typedef CGFloat (^ZHTableViewBaseModelCustomHeightCompletionHandle)(UITableView *tableView, NSIndexPath *indexPath, ZHTableViewBaseModel *model);
12 |
13 | /**
14 | 配置 Cell Header Footer 的数据 Model
15 | */
16 | @interface ZHTableViewBaseModel : NSObject
17 |
18 | /**
19 | 标识符
20 | */
21 | @property (nonatomic, copy) NSString *identifier;
22 | /**
23 | 自定义类 Class
24 | */
25 | @property (nonatomic, strong) Class anyClass;
26 | /**
27 | 高度 默认为 NSNotFound
28 | */
29 | @property (nonatomic, assign) CGFloat height;
30 | /**
31 | * 自定义高度
32 | */
33 | @property (nonatomic, copy) ZHTableViewBaseModelCustomHeightCompletionHandle customHeightCompletionHandle;
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewBaseModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewBaseModel.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewBaseModel.h"
10 |
11 | @implementation ZHTableViewBaseModel
12 |
13 | - (instancetype)init {
14 | if (self = [super init]) {
15 | _height = NSNotFound;
16 | }
17 | return self;
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewCell.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewBaseModel.h"
10 |
11 | /**
12 | 注册 Cell 样式
13 | */
14 | @interface ZHTableViewCell : ZHTableViewBaseModel
15 |
16 | /**
17 | Cell 的个数 默认为1
18 | */
19 | @property (nonatomic, assign) NSInteger cellNumber;
20 | /**
21 | 配置 Cell的回调
22 | */
23 | @property (nonatomic, copy) void(^configCompletionHandle)(CellType cell, NSIndexPath *indexPath);
24 | /**
25 | 点击 Cell 的回调
26 | */
27 | @property (nonatomic, copy) void(^didSelectRowCompletionHandle)(CellType cell, NSIndexPath *indexPath);
28 |
29 | @property (nonatomic, copy) CGFloat(^customHeightBlock)(CellType cell, NSIndexPath *indexPath);
30 | @property (nonatomic, copy) BOOL(^hiddenBlock)(NSIndexPath *indexPath);
31 |
32 | /// 为指定的索引设置是否隐藏
33 | /// @param hidden 是否隐藏
34 | /// @param indexPath 指定索引
35 | - (void)setHidden:(BOOL)hidden
36 | indexPath:(NSIndexPath *)indexPath;
37 |
38 | /// 获取指定的索引已经显示内容是否隐藏 如果不存在默认位显示
39 | /// @param indexPath 指定的索引
40 | - (BOOL)isHiddenDisplayWithIndexPath:(NSIndexPath *)indexPath;
41 |
42 | /// 获取最新当前索引是否隐藏
43 | /// @param indexPath 指定索引
44 | - (BOOL)isHiddenWithIndexPath:(NSIndexPath *)indexPath;
45 | /**
46 | * 为了是支持泛型
47 |
48 | @param configCompletionHandle 设置的Block
49 | */
50 | - (void)setConfigCompletionHandle:(void (^)(CellType cell, NSIndexPath * indexPath))configCompletionHandle;
51 |
52 | /**
53 | * 为了支持泛型
54 |
55 | @param didSelectRowCompletionHandle 点击回调的block
56 | */
57 | - (void)setDidSelectRowCompletionHandle:(void (^)(CellType cell, NSIndexPath * indexPath))didSelectRowCompletionHandle;
58 |
59 | /**
60 | 点击所在的 Cell 的执行方法
61 |
62 | @param cell 点击的 Cell
63 | @param indexPath 点击 cell 所在的索引
64 | */
65 | - (void)didSelectRowAtWithCell:(CellType)cell
66 | indexPath:(NSIndexPath *)indexPath;
67 |
68 | /**
69 | 配置 Cell 的执行方法
70 |
71 | @param cell 配置的 Cell
72 | @param indexPath 配置 Cell 所在的索引
73 | */
74 | - (void)configCellWithCell:(CellType)cell
75 | indexPath:(NSIndexPath *)indexPath;
76 |
77 | /**
78 | 一个方法配置所有的参数
79 |
80 | @param cellNumber cell 的数量
81 | @param identifier 标识符
82 | @param anyClass cell 的类名
83 | @param height 高度
84 | @param configCompletionHandle 配置 cell
85 | @param didSelectRowCompletionHandle 点击 cell 方法
86 | */
87 | - (void)configurationCellWithCellNumber:(NSUInteger)cellNumber
88 | identifier:(NSString *)identifier
89 | anyClass:(Class)anyClass
90 | height:(CGFloat)height
91 | configCompletionHandle:(void(^)(CellType cell, NSIndexPath *indexPath))configCompletionHandle
92 | didSelectRowCompletionHandle:(void(^)(CellType cell, NSIndexPath *indexPath))didSelectRowCompletionHandle;
93 |
94 | @end
95 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewCell.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewCell.h"
10 |
11 | @implementation ZHTableViewCell {
12 | NSMutableDictionary *_hiddenMap;
13 | }
14 |
15 | - (instancetype)init {
16 | if (self = [super init]) {
17 | _cellNumber = 1;
18 | _hiddenMap = [NSMutableDictionary dictionary];
19 | }
20 | return self;
21 | }
22 |
23 | - (void)setConfigCompletionHandle:(void (^)(UITableViewCell *, NSIndexPath *))configCompletionHandle {
24 | _configCompletionHandle = configCompletionHandle;
25 | }
26 |
27 | - (void)setDidSelectRowCompletionHandle:(void (^)(UITableViewCell *, NSIndexPath *))didSelectRowCompletionHandle {
28 | _didSelectRowCompletionHandle = didSelectRowCompletionHandle;
29 | }
30 |
31 | - (void)didSelectRowAtWithCell:(UITableViewCell *)cell
32 | indexPath:(NSIndexPath *)indexPath {
33 | if (!self.didSelectRowCompletionHandle) {
34 | return;
35 | }
36 | self.didSelectRowCompletionHandle(cell,indexPath);
37 | }
38 |
39 | - (void)configCellWithCell:(UITableViewCell *)cell
40 | indexPath:(NSIndexPath *)indexPath {
41 | if (!self.configCompletionHandle) {
42 | return;
43 | }
44 | self.configCompletionHandle(cell,indexPath);
45 | }
46 |
47 | - (void)configurationCellWithCellNumber:(NSUInteger)cellNumber identifier:(NSString *)identifier anyClass:(Class)anyClass height:(CGFloat)height configCompletionHandle:(void (^)(UITableViewCell *, NSIndexPath *))configCompletionHandle didSelectRowCompletionHandle:(void (^)(UITableViewCell *, NSIndexPath *))didSelectRowCompletionHandle {
48 | self.cellNumber = cellNumber;
49 | self.identifier = identifier;
50 | self.anyClass = anyClass;
51 | self.height = height;
52 | self.configCompletionHandle = configCompletionHandle;
53 | self.didSelectRowCompletionHandle = didSelectRowCompletionHandle;
54 | }
55 |
56 | - (void)setHidden:(BOOL)hidden
57 | indexPath:(NSIndexPath *)indexPath {
58 | NSString *key = [self hiddenKeyWithIndexPath:indexPath];
59 | _hiddenMap[key] = @(hidden);
60 | }
61 |
62 | - (BOOL)isHiddenDisplayWithIndexPath:(NSIndexPath *)indexPath {
63 | NSString *key = [self hiddenKeyWithIndexPath:indexPath];
64 | NSNumber *hiddenNumber = _hiddenMap[key];
65 | if (!hiddenNumber) {
66 | return NO;
67 | }
68 | return [hiddenNumber boolValue];
69 | }
70 |
71 | - (BOOL)isHiddenWithIndexPath:(NSIndexPath *)indexPath {
72 | BOOL isHidden = self.hiddenBlock && self.hiddenBlock(indexPath);
73 | return isHidden;
74 | }
75 |
76 | - (NSString *)hiddenKeyWithIndexPath:(NSIndexPath *)indexPath {
77 | return [NSString stringWithFormat:@"hidden-%@-%@",@(indexPath.section),@(indexPath.row)];
78 | }
79 |
80 | @end
81 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewDataSource.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewDataSource.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import
10 | #import "ZHTableViewGroup.h"
11 | #import "ZHAutoConfigurationTableViewDelegate.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 | /**
15 | 添加分组的回调
16 |
17 | @param group 创建的分组对象
18 | */
19 | typedef void(^ZHTableViewDataSourceAddGroupCompletionHandle)(ZHTableViewGroup * group);
20 |
21 | /**
22 | 自定义高度的回调
23 |
24 | @return 自定义算法返回的高度
25 | */
26 | typedef CGFloat (^ZHTableViewDataSourceCustomHeightCompletionHandle)(ZHTableViewBaseModel * model);
27 |
28 | /**
29 | 进行 UITableView 进行数据托管的数据源
30 | */
31 | @interface ZHTableViewDataSource : NSObject
32 |
33 | /**
34 | 自动配置 UITableView 的 DataSource 和 Delegate 默认为 YES
35 | */
36 | @property (nonatomic, assign, getter=isAutoConfigurationTableViewDelegate) BOOL autoConfigurationTableViewDelegate;
37 |
38 | /**
39 | * 是否开启即将展示 复制数据 默认为 NO
40 | */
41 | @property (nonatomic, assign) BOOL isWillDisplayData;
42 | /**
43 | 添加优先级 如果 YES 启用新的优先级 先判断设置的高度 没有获取自定义 Block 的高度 其次是自动计算高度
44 | */
45 | @property (nonatomic, assign) BOOL priorityHeight;
46 |
47 | @property (nonatomic, strong, readonly) NSMutableArray * groups;
48 | /// 设置ZHAutoConfigurationTableViewDelegate子类的代理
49 | @property (nonatomic, strong) ZHAutoConfigurationTableViewDelegate *tableViewDelegate;
50 | @property (nonatomic, weak) UITableView *tableView;
51 | /**
52 | 唯一的初始化ZHTableViewDataSource
53 |
54 | @param tableView 托管的 UITableView 的对象 必须存在
55 | @return ZHTableViewDataSource的对象
56 | */
57 | - (instancetype)initWithTableView:(UITableView *)tableView;
58 |
59 | /**
60 | 添加一个分组
61 |
62 | @param completionHandle 返回新注册的分组对象 可以进行配置
63 | */
64 | - (ZHTableViewGroup *)addGroupWithCompletionHandle:(ZHTableViewDataSourceAddGroupCompletionHandle)completionHandle;
65 |
66 | /// 注册所有的Cell
67 | - (void)registerClass;
68 |
69 | /**
70 | 进行刷新 UITableView
71 | */
72 | - (void)reloadTableViewData;
73 |
74 | /**
75 | 获取分组Cell的个数 如果autoConfigurationTableViewDelegate = YES 此方法不用调用
76 |
77 | @param dataSource ZHTableViewDataSource数据源
78 | @param section 所在组索引
79 | @return 分组 Cell 的个数
80 | */
81 | + (NSInteger)numberOfRowsInSectionWithDataSource:(ZHTableViewDataSource *)dataSource section:(NSInteger)section;
82 |
83 | /**
84 | 获取对应索引的UITableViewCell 如果autoConfigurationTableViewDelegate = YES 此方法不用调用
85 |
86 | @param dataSource ZHTableViewDataSource数据源
87 | @param indexPath 所在的索引
88 | @return UITableViewCell
89 | */
90 | + (UITableViewCell *)cellForRowAtWithDataSource:(ZHTableViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
91 |
92 | /**
93 | 获取分组的个数 如果autoConfigurationTableViewDelegate = YES 此方法不用调用
94 |
95 | @param dataSource ZHTableViewDataSource的数据源
96 | @return 分组的个数
97 | */
98 | + (NSInteger)numberOfSectionsWithDataSource:(ZHTableViewDataSource *)dataSource;
99 |
100 | /**
101 | 获取Cell 所在索引的高度 如果autoConfigurationTableViewDelegate = YES 此方法不用调用
102 |
103 | @param dataSource ZHTableViewDataSource数据源
104 | @param indexPath 索引
105 | @param customHeightCompletionHandle 自定义高度回调 实现 ZHTableViewCell 属性 cellHeight 无效
106 | @return Cell 的高度
107 | */
108 | + (CGFloat)heightForRowAtDataSource:(ZHTableViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle;
109 |
110 | /**
111 | 点击 Cell 的回调
112 |
113 | @param dataSource ZHTableViewDataSource数据源
114 | @param indexPath 点击的索引
115 | */
116 | + (void)didSelectRowAtWithDataSource:(ZHTableViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
117 |
118 | /**
119 | 获取 Header 的高度
120 |
121 | @param dataSource ZHTableViewDataSource数据源
122 | @param section 分组索引
123 | @param customHeightCompletionHandle 自定义高度回调
124 | @return 分组 Header 高度
125 | */
126 | + (CGFloat)heightForHeaderInSectionWithDataSource:(ZHTableViewDataSource *)dataSource section:(NSInteger)section customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle;
127 |
128 | /**
129 | 获取 Footer 的高度
130 |
131 | @param dataSource ZHTableViewDataSource数据源
132 | @param section 分组索引
133 | @param customHeightCompletionHandle 自定义高度回调
134 | @return 分组 Footer 高度
135 | */
136 | + (CGFloat)heightForFooterInSectionWithDataSource:(ZHTableViewDataSource *)dataSource section:(NSInteger)section customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle;
137 |
138 | /**
139 | 获取Header
140 |
141 | @param dataSource ZHTableViewDataSource数据源
142 | @param section 分组的索引
143 | @return 分组 Header 试图
144 | */
145 | + (UITableViewHeaderFooterView *)viewForHeaderInSectionWithDataSource:(ZHTableViewDataSource *)dataSource section:(NSInteger)section;
146 | /**
147 | 获取Footer
148 |
149 | @param dataSource ZHTableViewDataSource数据源
150 | @param section 分组的索引
151 | @return 分组 Footer 试图
152 | */
153 | + (UITableViewHeaderFooterView *)viewForFooterInSectionWithDataSource:(ZHTableViewDataSource *)dataSource section:(NSInteger)section;
154 |
155 | /**
156 | 清空之前数据
157 | */
158 | - (void)clearData;
159 |
160 | + (NSIndexPath *)indexPathWithDataSource:(ZHTableViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath;
161 |
162 | + (void)dataSource:(ZHTableViewDataSource *)dataSource willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
163 |
164 | @property (nonatomic, copy) void (^heightForRowAtIndexPath)(UITableView *tableView, NSIndexPath *indexPath, CGFloat height);
165 | @property (nonatomic, copy) void (^heightForHeaderInSection)(UITableView *tableView, NSUInteger section, CGFloat height);
166 | @property (nonatomic, copy) void (^heightForFooterInSection)(UITableView *tableView, NSUInteger section, CGFloat height);
167 | #pragma mark - Delegate Block
168 | /* UITableView 滑动, scrollViewDidScroll的代理 */
169 | @property (nonatomic, copy) void (^scrollViewDidScrollCompletionHandle)(UIScrollView *scrollView);
170 | /* UITableView 滑动,scrollViewWillBeginDragging的代理 */
171 | @property (nonatomic, copy) void (^scrollViewWillBeginDraggingCompletionHandle)(UIScrollView *scrollView);
172 | @property (nonatomic, copy) void (^scrollViewDidZoom)(UIScrollView *scrollView);
173 | @property (nonatomic, copy) void (^scrollViewWillEndDragging)(UIScrollView *scrollView, CGPoint velocity, CGPoint *targetContentOffset);
174 | @property (nonatomic, copy) void (^scrollViewDidEndDragging)(UIScrollView *scrollView, BOOL decelerate);
175 | @property (nonatomic, copy) void (^scrollViewWillBeginDecelerating)(UIScrollView *scrollView);
176 | @property (nonatomic, copy) void (^scrollViewDidEndDecelerating)(UIScrollView *scrollView);
177 | @property (nonatomic, copy) void (^scrollViewDidEndScrollingAnimation)(UIScrollView *scrollView);
178 | @property (nonatomic, copy) UIView *__nullable (^viewForZoomingInScrollView)(UIScrollView *scrollView);
179 | @property (nonatomic, copy) void (^scrollViewWillBeginZooming)(UIScrollView *scrollView, UIView *view);
180 | @property (nonatomic, copy) void (^scrollViewDidEndZooming)(UIScrollView *scrollView, UIView *view, CGFloat scale);
181 | @property (nonatomic, copy) BOOL (^scrollViewShouldScrollToTop)(UIScrollView *scrollView);
182 | @property (nonatomic, copy) void (^scrollViewDidScrollToTop)(UIScrollView *scrollView);
183 | @property (nonatomic, copy) void (^scrollViewDidChangeAdjustedContentInset)(UIScrollView *scrollView);
184 |
185 |
186 | @end
187 |
188 | @interface ZHTableViewDataSource (ReloadHeight)
189 |
190 | /// 根据标识符刷新自动计算高度
191 | /// @param identifier 标识符
192 | - (void)reloadCellAutomaticHeightWithIdentifier:(NSString *)identifier;
193 | /// 根据标识符刷新固定高度
194 | /// @param height 固定高度
195 | /// @param identifier 标识符
196 | - (void)reloadCellFixedHeight:(CGFloat)height
197 | identifier:(NSString *)identifier;
198 |
199 | /// 根据类类型刷新自动计算高度
200 | /// @param className 类类型
201 | - (void)reloadCellAutomaticHeightWithClass:(Class)className;
202 | /// 根据类类型刷新固定高度
203 | /// @param height 固定高度
204 | /// @param className 类类型
205 | - (void)reloadCellFixedHeight:(CGFloat)height
206 | className:(Class)className;
207 |
208 | /// 根据指定的`ZHTableViewCell`刷新自动计算高度
209 | /// @param tableViewCell 指定的`ZHTableViewCell`
210 | - (void)reloadCellAutomaticHeightWithTableViewCell:(ZHTableViewCell *)tableViewCell;
211 | /// 根据指定的`ZHTableViewCell`刷新固定高度
212 | /// @param height 固定的高度
213 | /// @param tableViewCell 指定的`ZHTableViewCell`
214 | - (void)reloadCellFixedHeight:(NSInteger)height
215 | tableViewCell:(ZHTableViewCell *)tableViewCell;
216 |
217 | /// 根据对应分组个对应的`ZHTableViewCell`索引更新自动高度
218 | /// @param groupIndex 分组的索引
219 | /// @param cellIndex 对应的`ZHTableViewCell`索引
220 | - (void)reloadCellAutomicHeightWithGroupIndex:(NSUInteger)groupIndex
221 | cellIndex:(NSUInteger)cellIndex;
222 | /// 根据对应分组个对应的`ZHTableViewCell`索引更新固定高度
223 | /// @param height 固定高度
224 | /// @param groupIndex 分组的索引
225 | /// @param cellIndex 对应的`ZHTableViewCell`索引
226 | - (void)reloadCellFixedHeight:(CGFloat)height
227 | groupIndex:(NSUInteger)groupIndex
228 | cellIndex:(NSUInteger)cellIndex;
229 |
230 | @end
231 |
232 |
233 | @interface ZHTableViewDataSource (ReloadCell)
234 |
235 | /// 通过标识符刷新对应的ZHTableViewCell
236 | /// @param identienfier 标识符
237 | - (void)reloadCellWithIdentifier:(NSString *)identienfier;
238 | /// 通过指定Class类型刷新对应的ZHTableViewCell
239 | /// @param className Class类型
240 | - (void)reloadCellWithClassName:(Class)className;
241 | /// 通过指定的ZHTableViewCell刷新ZHTableViewCell
242 | /// @param tableViewCell 指定ZHTableViewCell对象
243 | - (void)reloadCellWithTableViewCell:(ZHTableViewCell *)tableViewCell;
244 | /// 通过指定索引刷新ZHTableViewCell
245 | /// @param groupIndex 对应分组索引
246 | /// @param cellIndex 对应ZHTableViewCell索引
247 | - (void)reloadCellWithGroupIndex:(NSUInteger)groupIndex
248 | cellIndex:(NSUInteger)cellIndex;
249 |
250 | - (NSMutableArray *)indexPathsWithTableViewCell:(ZHTableViewCell *)tableViewCell;
251 |
252 | @end
253 |
254 | @interface ZHTableViewDataSource (ReloadData)
255 |
256 | /// 根据标识符更新数据
257 | /// @param dataCount 数据的总数
258 | /// @param identifier 标识符
259 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
260 | identifier:(NSString *)identifier;
261 | /// 根据Class类型更新数据
262 | /// @param dataCount 数据的总数
263 | /// @param className Class的类型
264 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
265 | className:(Class)className;
266 | /// 根据指定ZHTableViewCell更新数据
267 | /// @param dataCount 数据的总数
268 | /// @param tableViewCell 指定的ZHTableViewCell
269 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
270 | tableViewCell:(ZHTableViewCell *)tableViewCell;
271 | /// 根据指定的索引更新数据
272 | /// @param dataCount 数据的总数
273 | /// @param groupIndex 分组的索引
274 | /// @param cellIndex ZHTableViewCell的索引
275 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
276 | groupIndex:(NSUInteger)groupIndex
277 | cellIndex:(NSUInteger)cellIndex;
278 |
279 | - (void)updatesTableView:(void(^)(void))update;
280 |
281 | @end
282 |
283 | @interface ZHTableViewDataSource (Cell)
284 |
285 | /// 根据条件过滤ZHTableViewCell
286 | /// @param config 过滤的条件
287 | - (NSArray *)filterCellWithConfig:(BOOL (^)(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell))config;
288 |
289 | /// 根据tableViewCell找到对应在UITableView所在的索引
290 | /// @param tableViewCell 对应的tableViewCell
291 | - (NSIndexPath *)indexPathWithTableViewCell:(ZHTableViewCell *)tableViewCell;
292 |
293 | @end
294 |
295 | @interface ZHTableViewDataSource (Hidden)
296 |
297 | /// 刷新当前所有隐藏的Cell
298 | - (void)reloadAllHiddenCell;
299 |
300 | @end
301 |
302 | NS_ASSUME_NONNULL_END
303 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewDataSource.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewDataSource.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewDataSource.h"
10 | #import "ZHAutoConfigurationTableViewDelegate.h"
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface ZHTableViewDataSource ()
14 |
15 | @property (nonatomic, strong) NSMutableArray *groups;
16 |
17 | @end
18 |
19 | @implementation ZHTableViewDataSource {
20 | NSCache *_cellCache;
21 | }
22 |
23 | - (instancetype)initWithTableView:(UITableView *)tableView {
24 | if (self = [super init]) {
25 | _tableView = tableView;
26 | _autoConfigurationTableViewDelegate = YES;
27 | _cellCache = [[NSCache alloc] init];
28 | }
29 | return self;
30 | }
31 |
32 | - (ZHTableViewGroup *)addGroupWithCompletionHandle:(ZHTableViewDataSourceAddGroupCompletionHandle)completionHandle {
33 | ZHTableViewGroup *group = [[ZHTableViewGroup alloc] init];
34 | if (completionHandle) {
35 | completionHandle(group);
36 | }
37 | [self.groups addObject:group];
38 | return group;
39 | }
40 |
41 | - (void)reloadTableViewData {
42 | if (!self.tableView.dataSource) {
43 | if (self.isAutoConfigurationTableViewDelegate) {
44 | self.tableView.dataSource = self.tableViewDelegate;
45 | } else {
46 | NSAssert(NO, @"必须给 UITableView 设置 DataSource 代理");
47 | }
48 | }
49 | if (!self.tableView.delegate) {
50 | if (self.isAutoConfigurationTableViewDelegate) {
51 | self.tableView.delegate = self.tableViewDelegate;
52 | }
53 | }
54 | [self registerClass];
55 | [self.tableView reloadData];
56 | }
57 |
58 | + (NSInteger)numberOfRowsInSectionWithDataSource:(ZHTableViewDataSource *)dataSource
59 | section:(NSInteger)section {
60 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:section];
61 | if (!group) {
62 | return 0;
63 | }
64 | return group.cellCount;
65 | }
66 |
67 | + (UITableViewCell *)cellForRowAtWithDataSource:(ZHTableViewDataSource *)dataSource
68 | indexPath:(NSIndexPath *)indexPath {
69 | return [self cellForRowAtWithDataSource:dataSource
70 | indexPath:indexPath
71 | config:!dataSource.isWillDisplayData];
72 | }
73 |
74 | + (UITableViewCell *)cellForRowAtWithDataSource:(ZHTableViewDataSource *)dataSource
75 | indexPath:(NSIndexPath *)indexPath
76 | config:(BOOL)config
77 | useCache:(BOOL)useCache {
78 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
79 | ZHTableViewCell *tableViewCell = [group tableViewCellForIndexPath:indexPath];
80 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
81 | if (!group) {
82 | return cell;
83 | }
84 | UITableViewCell *resultCell;
85 | if (useCache) {
86 | UITableViewCell *cacheCell = [dataSource cacheCellWithIndexPath:indexPath];
87 | if ([cacheCell isKindOfClass:tableViewCell.anyClass]) {
88 | resultCell = [dataSource cacheCellWithIndexPath:indexPath];
89 | [group tableViewCell:tableViewCell configCell:resultCell atIndexPath:indexPath];
90 | }
91 | }
92 | if (!resultCell) {
93 | resultCell = [group cellForTableViewWithTableView:dataSource.tableView
94 | indexPath:indexPath
95 | config:config];
96 | }
97 | if (!resultCell) {
98 | return cell;
99 | }
100 | NSIndexPath *realIndexPath = [group indexPathWithCell:tableViewCell indexPath:indexPath];
101 | BOOL isHidden = [tableViewCell isHiddenWithIndexPath:realIndexPath];
102 | resultCell.hidden = isHidden;
103 | if (!useCache) {
104 | [dataSource saveCacheWithCell:resultCell indexPath:indexPath];
105 | }
106 | return resultCell;
107 | }
108 |
109 | - (UITableViewCell *)cacheCellWithIndexPath:(NSIndexPath *)indexPath {
110 | return [_cellCache objectForKey:[self cacheKeyWithIndexPath:indexPath]];
111 | }
112 |
113 | - (void)saveCacheWithCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
114 | [_cellCache setObject:cell forKey:[self cacheKeyWithIndexPath:indexPath]];
115 | }
116 |
117 | - (NSString *)cacheKeyWithIndexPath:(NSIndexPath *)indexPath {
118 | return [NSString stringWithFormat:@"%@-%@",@(indexPath.section),@(indexPath.row)];
119 | }
120 |
121 | + (UITableViewCell *)cellForRowAtWithDataSource:(ZHTableViewDataSource *)dataSource
122 | indexPath:(NSIndexPath *)indexPath
123 | config:(BOOL)config {
124 | return [self cellForRowAtWithDataSource:dataSource
125 | indexPath:indexPath
126 | config:config
127 | useCache:NO];
128 | }
129 |
130 | + (NSInteger)numberOfSectionsWithDataSource:(ZHTableViewDataSource *)dataSource {
131 | if (!dataSource) {
132 | return 0;
133 | }
134 | return dataSource.groups.count;
135 | }
136 |
137 | + (CGFloat)heightForRowAtDataSource:(ZHTableViewDataSource *)dataSource
138 | indexPath:(NSIndexPath *)indexPath customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle {
139 | ZHTableViewCell *cell = [self cellForIndexPath:dataSource indexPath:indexPath];
140 |
141 | if (!cell) {
142 | return 0;
143 | }
144 | NSIndexPath *realyIndexPath = [self indexPathWithDataSource:dataSource
145 | indexPath:indexPath];
146 | if ([cell isHiddenWithIndexPath:realyIndexPath]) {
147 | return 0;
148 | }
149 | if (cell.customHeightBlock) {
150 | UITableViewCell *tableViewCell = [self cellForRowAtWithDataSource:dataSource
151 | indexPath:indexPath
152 | config:YES
153 | useCache:YES];
154 | return cell.customHeightBlock(tableViewCell, realyIndexPath);
155 | }
156 | if (!dataSource.priorityHeight) {
157 | CGFloat automaticHeight = ({
158 | automaticHeight = CGFLOAT_MAX;
159 | if (cell.height == NSNotFound) {
160 | UITableViewCell *automaticHeightCell = [self cellForRowAtWithDataSource:dataSource indexPath:indexPath config:YES
161 | useCache:YES];
162 | automaticHeight = [automaticHeightCell sizeThatFits:CGSizeMake([UIScreen mainScreen].bounds.size.width, CGFLOAT_MAX)].height;
163 | }
164 | automaticHeight;
165 | });
166 | CGFloat height = cell.height;
167 | if (cell.height == NSNotFound && automaticHeight != CGFLOAT_MAX) {
168 | height = automaticHeight;
169 | }
170 | return [self heightWithCustomHandle:height
171 | customCompletionHandle:customHeightCompletionHandle
172 | baseModel:cell];
173 | } else {
174 | CGFloat heigh = cell.height;
175 | if (heigh > 0 && heigh < CGFLOAT_MAX && heigh < NSNotFound) {
176 | return heigh;
177 | }
178 | if (customHeightCompletionHandle) {
179 | heigh = customHeightCompletionHandle(cell);
180 | if (heigh > 0 && heigh < CGFLOAT_MAX && heigh < NSNotFound) {
181 | return heigh;
182 | }
183 | }
184 | CGFloat automaticHeight = ({
185 | automaticHeight = CGFLOAT_MAX;
186 | if (cell.height == NSNotFound) {
187 | UITableViewCell *automaticHeightCell = [self cellForRowAtWithDataSource:dataSource
188 | indexPath:indexPath
189 | config:YES
190 | useCache:YES];
191 | automaticHeight = [automaticHeightCell sizeThatFits:CGSizeMake([UIScreen mainScreen].bounds.size.width, CGFLOAT_MAX)].height;
192 | }
193 | automaticHeight;
194 | });
195 | return automaticHeight;
196 | }
197 | }
198 |
199 | + (void)didSelectRowAtWithDataSource:(ZHTableViewDataSource *)dataSource
200 | indexPath:(NSIndexPath *)indexPath {
201 |
202 | ZHTableViewCell *tableViewCell = [self cellForIndexPath:dataSource indexPath:indexPath];
203 | if (!tableViewCell) {
204 | return;
205 | }
206 | __block UITableViewCell *cell = ({
207 | cell = nil;
208 | /* 因为点击的 CELL 一定是在屏幕可见的范围之内 所以直接取 */
209 | [dataSource.tableView.visibleCells enumerateObjectsUsingBlock:^(__kindof UITableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
210 | NSIndexPath *visibleIndexPath = [dataSource.tableView indexPathForCell:obj];
211 | if ([indexPath compare:visibleIndexPath] == NSOrderedSame) {
212 | cell = obj;
213 | }
214 | }];
215 | cell;
216 | });
217 | if (!cell) {
218 | return;
219 | }
220 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
221 | [tableViewCell didSelectRowAtWithCell:cell indexPath:[group indexPathWithCell:tableViewCell indexPath:indexPath]];
222 | }
223 |
224 | + (CGFloat)heightForHeaderInSectionWithDataSource:(ZHTableViewDataSource *)dataSource
225 | section:(NSInteger)section customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle {
226 | return [self heightForHeaderFooterInSectionWithDataSource:dataSource section:section style:ZHTableViewHeaderFooterStyleHeader customHeightCompletionHandle:customHeightCompletionHandle];
227 | }
228 |
229 | + (CGFloat)heightForFooterInSectionWithDataSource:(ZHTableViewDataSource *)dataSource
230 | section:(NSInteger)section customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle {
231 | return [self heightForHeaderFooterInSectionWithDataSource:dataSource section:section style:ZHTableViewHeaderFooterStyleFooter customHeightCompletionHandle:customHeightCompletionHandle];
232 | }
233 |
234 | + (UITableViewHeaderFooterView *)viewForHeaderInSectionWithDataSource:(ZHTableViewDataSource *)dataSource
235 | section:(NSInteger)section {
236 | return [self viewHeaderFooterInSectionWithDtaSource:dataSource section:section style:ZHTableViewHeaderFooterStyleHeader];
237 | }
238 |
239 | + (UITableViewHeaderFooterView *)viewForFooterInSectionWithDataSource:(ZHTableViewDataSource *)dataSource
240 | section:(NSInteger)section {
241 | return [self viewHeaderFooterInSectionWithDtaSource:dataSource section:section style:ZHTableViewHeaderFooterStyleFooter];
242 | }
243 |
244 | - (void)clearData {
245 | [self.groups removeAllObjects];
246 | [_cellCache removeAllObjects];
247 | }
248 |
249 | + (UITableViewHeaderFooterView *)viewHeaderFooterInSectionWithDtaSource:(ZHTableViewDataSource *)dataSource
250 | section:(NSInteger)section style:(ZHTableViewHeaderFooterStyle)style {
251 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:section];
252 | if (!group) {
253 | return nil;
254 | }
255 | return [group headerFooterForStyle:style tableView:dataSource.tableView section:section];
256 | }
257 |
258 | + (CGFloat)heightForHeaderFooterInSectionWithDataSource:(ZHTableViewDataSource *)dataSource
259 | section:(NSInteger)section style:(ZHTableViewHeaderFooterStyle)style
260 | customHeightCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customHeightCompletionHandle {
261 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:section];
262 | if(!group) {
263 | return 0;
264 | }
265 | NSInteger height = 0;
266 | ZHTableViewBaseModel *baseModel;
267 | UITableViewHeaderFooterView *headFooter = [self viewHeaderFooterInSectionWithDtaSource:dataSource section:section style:style];
268 | CGFloat automaticHeight = [headFooter sizeThatFits:CGSizeMake([UIScreen mainScreen].bounds.size.width, CGFLOAT_MAX)].height;
269 | switch (style) {
270 | case ZHTableViewHeaderFooterStyleHeader: {
271 | height = group.header.height;
272 | baseModel = group.header;
273 | if (group.header.customHeightBlock) {
274 | [group.header setHeaderFooter:headFooter section:section];
275 | return group.header.customHeightBlock(headFooter,section);
276 | }
277 | }
278 | break;
279 | case ZHTableViewHeaderFooterStyleFooter: {
280 | height = group.footer.height;
281 | baseModel = group.footer;
282 | if (group.footer.customHeightBlock) {
283 | [group.footer setHeaderFooter:headFooter section:section];
284 | return group.footer.customHeightBlock(headFooter,section);
285 | }
286 | }
287 | break;
288 | }
289 | if (height == NSNotFound && automaticHeight != CGFLOAT_MAX) {
290 | height = automaticHeight;
291 | }
292 | return [self heightWithCustomHandle:height customCompletionHandle:customHeightCompletionHandle baseModel:baseModel];
293 | }
294 |
295 | + (CGFloat)heightWithCustomHandle:(CGFloat)height
296 | customCompletionHandle:(ZHTableViewDataSourceCustomHeightCompletionHandle)customCompletionHandle
297 | baseModel:(ZHTableViewBaseModel *)baseModel {
298 | return [self lookBestHeightWithBlock:^CGFloat(NSUInteger index, BOOL *stop) {
299 | if (index == 0) {
300 | return height;
301 | } else if (index == 1 && customCompletionHandle) {
302 | return customCompletionHandle(baseModel);
303 | } else {
304 | *stop = YES;
305 | return 0;
306 | }
307 | }];
308 | }
309 |
310 | + (BOOL)isVirifyHeight:(CGFloat)height {
311 | return height != NSNotFound && height != CGFLOAT_MAX;
312 | }
313 |
314 | + (CGFloat)lookBestHeightWithBlock:(CGFloat(^)(NSUInteger index, BOOL *stop))block {
315 | CGFloat height = 0;
316 | BOOL stop = NO;
317 | NSUInteger index = 0;
318 | while (!stop) {
319 | height = block(index, &stop);
320 | if ([self isVirifyHeight:height]) {
321 | return height;
322 | }
323 | index ++;
324 | }
325 | return height;
326 | }
327 |
328 | + (ZHTableViewGroup *)groupForSectionWithDataSource:(ZHTableViewDataSource *)dataSource
329 | section:(NSInteger)section {
330 | if (!dataSource) {
331 | return nil;
332 | }
333 | if (dataSource.groups.count <= section) {
334 | return nil;
335 | }
336 | return dataSource.groups[section];
337 | }
338 |
339 | + (ZHTableViewCell *)cellForIndexPath:(ZHTableViewDataSource *)dataSource
340 | indexPath:(NSIndexPath *)indexPath {
341 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
342 | if (!group) {
343 | return nil;
344 | }
345 | return [group tableViewCellForIndexPath:indexPath];
346 | }
347 |
348 | + (NSIndexPath *)indexPathWithDataSource:(ZHTableViewDataSource *)dataSource indexPath:(NSIndexPath *)indexPath {
349 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource section:indexPath.section];
350 | ZHTableViewCell *tableViewCell = [self cellForIndexPath:dataSource indexPath:indexPath];
351 | return [group indexPathWithCell:tableViewCell indexPath:indexPath];
352 | }
353 |
354 | + (void)dataSource:(ZHTableViewDataSource *)dataSource
355 | willDisplayCell:(UITableViewCell *)cell
356 | forRowAtIndexPath:(NSIndexPath *)indexPath {
357 | if (!dataSource.isWillDisplayData) {
358 | return;
359 | }
360 | ZHTableViewGroup *group = [self groupForSectionWithDataSource:dataSource
361 | section:indexPath.section];
362 | ZHTableViewCell *tableViewCell = [self cellForIndexPath:dataSource
363 | indexPath:indexPath];
364 | [group tableViewCell:tableViewCell
365 | configCell:cell
366 | atIndexPath:indexPath];
367 | }
368 |
369 | - (void)registerClass {
370 | for (ZHTableViewGroup *group in self.groups) {
371 | [group registerHeaderFooterCellWithTableView:self.tableView];
372 | }
373 | }
374 |
375 | - (NSMutableArray *)groups {
376 | if (!_groups) {
377 | _groups = [NSMutableArray array];
378 | }
379 | return _groups;
380 | }
381 |
382 | - (ZHAutoConfigurationTableViewDelegate *)tableViewDelegate {
383 | if (!_tableViewDelegate) {
384 | _tableViewDelegate = [[ZHAutoConfigurationTableViewDelegate alloc] initWithDataSource:self];
385 | }
386 | return _tableViewDelegate;
387 | }
388 |
389 | @end
390 |
391 | @implementation ZHTableViewDataSource (ReloadHeight)
392 |
393 | #pragma mark - 根据标识符刷新高度
394 | - (void)reloadCellAutomaticHeightWithIdentifier:(NSString *)identifier {
395 | [self reloadCellFixedHeight:NSNotFound
396 | identifier:identifier];
397 | }
398 |
399 | - (void)reloadCellFixedHeight:(CGFloat)height
400 | identifier:(NSString *)identifier {
401 | [self reloadCellHeight:height
402 | tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
403 | return [tableViewCell.identifier isEqualToString:identifier];
404 | }];
405 | }
406 |
407 | #pragma mark - 根据类类型刷新高度
408 | - (void)reloadCellAutomaticHeightWithClass:(Class)className {
409 | [self reloadCellFixedHeight:NSNotFound
410 | className:className];
411 | }
412 |
413 | - (void)reloadCellFixedHeight:(CGFloat)height
414 | className:(Class)className {
415 | [self reloadCellHeight:height
416 | tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
417 | return tableViewCell.anyClass == className;
418 | }];
419 | }
420 |
421 | - (void)reloadCellAutomaticHeightWithTableViewCell:(ZHTableViewCell *)tableViewCell {
422 | [self reloadCellFixedHeight:NSNotFound
423 | tableViewCell:tableViewCell];
424 | }
425 |
426 | - (void)reloadCellFixedHeight:(NSInteger)height
427 | tableViewCell:(ZHTableViewCell *)tableViewCell {
428 | [self reloadCellHeight:height
429 | tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *cell) {
430 | return [cell isEqual:tableViewCell];
431 | }];
432 | }
433 |
434 | - (void)reloadCellAutomicHeightWithGroupIndex:(NSUInteger)groupIndex
435 | cellIndex:(NSUInteger)cellIndex {
436 | [self reloadCellFixedHeight:NSNotFound
437 | groupIndex:groupIndex
438 | cellIndex:cellIndex];
439 | }
440 |
441 | - (void)reloadCellFixedHeight:(CGFloat)height
442 | groupIndex:(NSUInteger)groupIndex
443 | cellIndex:(NSUInteger)cellIndex {
444 | [self reloadCellHeight:height
445 | tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
446 | return section == groupIndex && row == cellIndex;
447 | }];
448 | }
449 |
450 | - (void)reloadCellHeight:(CGFloat)height
451 | tableViewCellConfig:(BOOL (^)(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell))tableViewCellConfig {
452 | if (!tableViewCellConfig) {
453 | return;
454 | }
455 | [[self filterCellWithConfig:tableViewCellConfig] enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
456 | obj.height = height;
457 | [self.tableView beginUpdates];
458 | [self.tableView endUpdates];
459 | }];;
460 | }
461 |
462 | @end
463 |
464 | @implementation ZHTableViewDataSource (ReloadCell)
465 |
466 | - (void)reloadCellWithIdentifier:(NSString *)identienfier {
467 | [self reloadCellWithTableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
468 | return [tableViewCell.identifier isEqualToString:identienfier];
469 | }];
470 | }
471 |
472 | - (void)reloadCellWithClassName:(Class)className {
473 | [self reloadCellWithTableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
474 | return tableViewCell.anyClass == className;
475 | }];
476 | }
477 |
478 | - (void)reloadCellWithTableViewCell:(ZHTableViewCell *)tableViewCell {
479 | [self reloadCellWithTableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell1) {
480 | return [tableViewCell isEqual:tableViewCell1];
481 | }];
482 | }
483 |
484 | - (void)reloadCellWithGroupIndex:(NSUInteger)groupIndex
485 | cellIndex:(NSUInteger)cellIndex {
486 | [self reloadCellWithTableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell1) {
487 | return groupIndex == section && cellIndex == row;
488 | }];
489 | }
490 |
491 | - (void)reloadCellWithTableViewCellConfig:(BOOL (^)(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell))tableViewCellConfig {
492 | if (!tableViewCellConfig) {
493 | return;
494 | }
495 | [[self filterCellWithConfig:tableViewCellConfig] enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
496 | NSMutableArray *indexPaths = [NSMutableArray array];
497 | for (NSUInteger i = 0; i < obj.cellNumber; i++) {
498 | NSIndexPath *indexPath = [self indexPathWithTableViewCell:obj];
499 | [indexPaths addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
500 | }
501 | [self updatesTableView:^{
502 | [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
503 | }];
504 | }];
505 | }
506 |
507 | - (NSMutableArray *)indexPathsWithTableViewCell:(ZHTableViewCell *)tableViewCell {
508 | NSMutableArray *indexPaths = [NSMutableArray array];
509 | for (NSUInteger i = 0; i < tableViewCell.cellNumber; i++) {
510 | NSIndexPath *indexPath = [self indexPathWithTableViewCell:tableViewCell];
511 | [indexPaths addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
512 | }
513 | return indexPaths;
514 | }
515 |
516 | @end
517 |
518 | @implementation ZHTableViewDataSource (ReloadData)
519 |
520 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
521 | identifier:(NSString *)identifier {
522 | [self reloadCellWithDataCount:dataCount tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
523 | return [tableViewCell.identifier isEqualToString:identifier];
524 | }];
525 | }
526 |
527 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
528 | className:(Class)className {
529 | [self reloadCellWithDataCount:dataCount tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
530 | return tableViewCell.anyClass == className;
531 | }];
532 | }
533 |
534 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
535 | tableViewCell:(ZHTableViewCell *)tableViewCell {
536 | [self reloadCellWithDataCount:dataCount tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell1) {
537 | return [tableViewCell isEqual:tableViewCell1];
538 | }];
539 | }
540 |
541 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
542 | groupIndex:(NSUInteger)groupIndex
543 | cellIndex:(NSUInteger)cellIndex {
544 | [self reloadCellWithDataCount:dataCount tableViewCellConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell1) {
545 | return groupIndex == section && cellIndex == row;
546 | }];
547 | }
548 |
549 | - (void)reloadCellWithDataCount:(NSUInteger)dataCount
550 | tableViewCellConfig:(BOOL (^)(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell))tableViewCellConfig {
551 | [[self filterCellWithConfig:tableViewCellConfig] enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
552 | NSUInteger cellNumber = obj.cellNumber;
553 | NSIndexPath *indexPath = [self indexPathWithTableViewCell:obj];
554 | obj.cellNumber = dataCount;
555 | if (cellNumber == dataCount) {
556 | NSMutableArray *indexPaths = [NSMutableArray array];
557 | for (NSUInteger i = 0; i < cellNumber; i++) {
558 | [indexPaths addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
559 | }
560 | [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
561 | } else if (cellNumber < dataCount) {
562 | NSMutableArray *indexPaths = [NSMutableArray array];
563 | NSMutableArray *insertIndexPaths = [NSMutableArray array];
564 | for (NSUInteger i = 0; i < dataCount; i++) {
565 | if (i < cellNumber) {
566 | [indexPaths addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
567 | } else {
568 | [insertIndexPaths addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
569 | }
570 | }
571 | [self updatesTableView:^{
572 | [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
573 | [self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
574 | }];
575 | } else {
576 | NSMutableArray *indexPaths = [NSMutableArray array];
577 | NSMutableArray *deleteIndexPath = [NSMutableArray array];
578 | for (NSUInteger i = 0; i < cellNumber; i++) {
579 | if (i < dataCount) {
580 | [indexPaths addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
581 | } else {
582 | [deleteIndexPath addObject:[NSIndexPath indexPathForRow:(indexPath.row + i) inSection:indexPath.section]];
583 | }
584 | }
585 | [self updatesTableView:^{
586 | [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
587 | [self.tableView deleteRowsAtIndexPaths:deleteIndexPath withRowAnimation:UITableViewRowAnimationAutomatic];
588 | }];
589 | }
590 | }];
591 | }
592 |
593 | - (void)updatesTableView:(void(^)(void))update {
594 | if (@available(iOS 11.0, *)) {
595 | [self.tableView performBatchUpdates:update completion:nil];
596 | } else {
597 | [self.tableView beginUpdates];
598 | update();
599 | [self.tableView endUpdates];
600 | }
601 | }
602 |
603 | @end
604 |
605 | @implementation ZHTableViewDataSource (Cell)
606 |
607 | - (NSArray *)filterCellWithConfig:(BOOL (^)(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell))config {
608 | NSMutableArray *filterResults = [NSMutableArray array];
609 | __block NSUInteger section = 0;
610 | [self.groups enumerateObjectsUsingBlock:^(ZHTableViewGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
611 | section = idx;
612 | __block NSUInteger row = 0;
613 | [obj.cells enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
614 | row = idx;
615 | if (config(section,row,obj)) {
616 | [filterResults addObject:obj];
617 | }
618 | }];
619 | }];
620 | return filterResults;
621 | }
622 |
623 | - (NSIndexPath *)indexPathWithTableViewCell:(ZHTableViewCell *)tableViewCell {
624 | __block NSIndexPath *indexPath;
625 | __block NSUInteger section = 0;
626 | [self.groups enumerateObjectsUsingBlock:^(ZHTableViewGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
627 | section = idx;
628 | __block NSUInteger row = 0;
629 | [obj.cells enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
630 | if ([tableViewCell isEqual:obj]) {
631 | indexPath = [NSIndexPath indexPathForRow:row inSection:section];
632 | *stop = YES;
633 | return;
634 | }
635 | row += obj.cellNumber;
636 | }];
637 | }];
638 | return indexPath;
639 | }
640 |
641 | @end
642 |
643 | @implementation ZHTableViewDataSource (Hidden)
644 |
645 | - (void)reloadAllHiddenCell {
646 | NSMutableArray *needReloadIndexPath = [NSMutableArray array];
647 | [[self filterCellWithConfig:^BOOL(NSUInteger section, NSUInteger row, ZHTableViewCell *tableViewCell) {
648 | return YES;
649 | }] enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
650 | if (!obj.hiddenBlock) {
651 | return;
652 | }
653 | [[self indexPathsWithTableViewCell:obj] enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull indexPath, NSUInteger idx, BOOL * _Nonnull stop) {
654 | NSIndexPath *realIndexPath = [NSIndexPath indexPathForRow:idx inSection:0];
655 | UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
656 | if (cell && cell.isHidden == [obj isHiddenWithIndexPath:realIndexPath]) {
657 | return;
658 | }
659 | [needReloadIndexPath addObject:indexPath];
660 | }];
661 | }] ;
662 | [self updatesTableView:^{
663 | [self.tableView reloadRowsAtIndexPaths:needReloadIndexPath
664 | withRowAnimation:UITableViewRowAnimationAutomatic];
665 | }];
666 | }
667 |
668 | @end
669 | NS_ASSUME_NONNULL_END
670 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewGroup.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewGroup.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import
10 | #import "ZHTableViewHeaderFooter.h"
11 | #import "ZHTableViewCell.h"
12 |
13 | typedef void(^ZHTableViewGroupAddCellCompletionHandle)(ZHTableViewCell *cell);
14 | typedef void(^ZHTableViewGroupAddHeaderFooterCompletionHandle)(ZHTableViewHeaderFooter *headerFooter);
15 |
16 |
17 |
18 | @interface ZHTableViewGroup : NSObject
19 |
20 | @property (nonatomic, strong) ZHTableViewHeaderFooter *header;
21 | @property (nonatomic, strong) ZHTableViewHeaderFooter *footer;
22 | @property (nonatomic, assign, readonly) NSInteger cellCount;
23 | @property (nonatomic, strong, readonly) NSMutableArray *cells;
24 |
25 | - (void)registerHeaderFooterCellWithTableView:(UITableView *)tableView;
26 |
27 | - (UITableViewCell *)cellForTableViewWithTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath config:(BOOL)config;
28 |
29 | - (ZHTableViewCell *)addCellWithCompletionHandle:(ZHTableViewGroupAddCellCompletionHandle)completionHandle;
30 |
31 | - (void)addHeaderWithCompletionHandle:(ZHTableViewGroupAddHeaderFooterCompletionHandle)completionHandle;
32 |
33 | - (void)addFooterWithCompletionHandle:(ZHTableViewGroupAddHeaderFooterCompletionHandle)completionHandle;
34 |
35 | - (ZHTableViewCell *)tableViewCellForIndexPath:(NSIndexPath *)indexPath;
36 |
37 | - (UITableViewHeaderFooterView *)headerFooterForStyle:(ZHTableViewHeaderFooterStyle)style tableView:(UITableView *)tableView section:(NSUInteger)section;
38 |
39 | - (NSIndexPath *)indexPathWithCell:(ZHTableViewCell *)cell indexPath:(NSIndexPath *)indexPath;
40 |
41 | - (void)tableViewCell:(ZHTableViewCell *)tableViewCell
42 | configCell:(UITableViewCell *)cell
43 | atIndexPath:(NSIndexPath *)indexPath;
44 |
45 | - (ZHTableViewGroup *(^)(ZHTableViewHeaderFooter *))tableHeader;
46 | - (ZHTableViewGroup *(^)(ZHTableViewHeaderFooter *))tableFooter;
47 |
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewGroup.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewGroup.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewGroup.h"
10 |
11 | @interface ZHTableViewGroup ()
12 |
13 | @property (nonatomic, strong) NSMutableArray *cells;
14 |
15 | @end
16 |
17 | @implementation ZHTableViewGroup
18 |
19 | - (void)registerHeaderFooterCellWithTableView:(UITableView *)tableView {
20 | if (self.header && self.header.identifier) {
21 | [tableView registerClass:self.header.anyClass forHeaderFooterViewReuseIdentifier:self.header.identifier];
22 | }
23 | if (self.footer && self.footer.identifier) {
24 | [tableView registerClass:self.footer.anyClass forHeaderFooterViewReuseIdentifier:self.footer.identifier];
25 | }
26 | for (ZHTableViewCell *tableViewCell in self.cells) {
27 | if (tableViewCell.identifier) {
28 | [tableView registerClass:tableViewCell.anyClass forCellReuseIdentifier:tableViewCell.identifier];
29 | }
30 | }
31 | }
32 |
33 | - (ZHTableViewCell *)addCellWithCompletionHandle:(ZHTableViewGroupAddCellCompletionHandle)completionHandle {
34 | ZHTableViewCell *cell = [[ZHTableViewCell alloc] init];
35 | if (completionHandle) {
36 | completionHandle(cell);
37 | }
38 | [self.cells addObject:cell];
39 | return cell;
40 | }
41 |
42 | - (void)addHeaderWithCompletionHandle:(ZHTableViewGroupAddHeaderFooterCompletionHandle)completionHandle {
43 | ZHTableViewHeaderFooter *header= [[ZHTableViewHeaderFooter alloc] initWithStyle:ZHTableViewHeaderFooterStyleHeader];
44 | if (completionHandle) {
45 | completionHandle(header);
46 | }
47 | _header = header;
48 | }
49 |
50 | - (void)addFooterWithCompletionHandle:(ZHTableViewGroupAddHeaderFooterCompletionHandle)completionHandle {
51 | ZHTableViewHeaderFooter *footer = [[ZHTableViewHeaderFooter alloc] initWithStyle:ZHTableViewHeaderFooterStyleFooter];
52 | if (completionHandle) {
53 | completionHandle(footer);
54 | }
55 | _footer = footer;
56 | }
57 |
58 | - (UITableViewCell *)cellForTableViewWithTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath config:(BOOL)config{
59 | if (!tableView) {
60 | return nil;
61 | }
62 | ZHTableViewCell *tableViewCell = [self tableViewCellForIndexPath:indexPath];
63 | if (!tableViewCell) {
64 | return nil;
65 | }
66 | if (!tableViewCell.identifier) {
67 | return nil;
68 | }
69 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableViewCell.identifier];
70 | if (config) {
71 | [self tableViewCell:tableViewCell
72 | configCell:cell
73 | atIndexPath:indexPath];
74 | }
75 | return cell;
76 | }
77 |
78 | - (void)tableViewCell:(ZHTableViewCell *)tableViewCell
79 | configCell:(UITableViewCell *)cell
80 | atIndexPath:(NSIndexPath *)indexPath {
81 | NSIndexPath *really = [self indexPathWithCell:tableViewCell
82 | indexPath:indexPath];
83 | [tableViewCell configCellWithCell:cell
84 | indexPath:really];
85 | }
86 |
87 | - (NSIndexPath *)indexPathWithCell:(ZHTableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
88 | __block NSUInteger startIndex = 0;
89 | [self.cells enumerateObjectsUsingBlock:^(ZHTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
90 | if (obj == cell) {
91 | *stop = YES;
92 | return;
93 | }
94 | startIndex += obj.cellNumber;
95 | }];
96 | return [NSIndexPath indexPathForRow:indexPath.row - startIndex inSection:indexPath.section];
97 | }
98 |
99 | - (ZHTableViewCell *)tableViewCellForIndexPath:(NSIndexPath *)indexPath {
100 | if (indexPath.row >= self.cellCount) {
101 | return nil;
102 | }
103 | NSInteger count = 0;
104 | ZHTableViewCell *tableViewCell;
105 | for (NSUInteger i = 0; i < self.cells.count; i ++) {
106 | ZHTableViewCell *cell = self.cells[i];
107 | NSUInteger tempCount = count;
108 | count += cell.cellNumber;
109 | if (indexPath.row >= tempCount && indexPath.row < count) {
110 | tableViewCell = cell;
111 | break;
112 | }
113 | }
114 | return tableViewCell;
115 | }
116 |
117 | - (UITableViewHeaderFooterView *)headerFooterForStyle:(ZHTableViewHeaderFooterStyle)style tableView:(UITableView *)tableView section:(NSUInteger)section {
118 | if (!tableView) {
119 | return nil;
120 | }
121 | ZHTableViewHeaderFooter *headerFooter;
122 | switch (style) {
123 | case ZHTableViewHeaderFooterStyleHeader: {
124 | headerFooter = self.header;
125 | }
126 | break;
127 | case ZHTableViewHeaderFooterStyleFooter: {
128 | headerFooter = self.footer;
129 | }
130 | break;
131 | }
132 | if (!headerFooter) {
133 | return nil;
134 | }
135 | if (!headerFooter.identifier) {
136 | return nil;
137 | }
138 | UITableViewHeaderFooterView *headerFooterView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerFooter.identifier];
139 | [headerFooter setHeaderFooter:headerFooterView section:section];
140 | return headerFooterView;
141 | }
142 |
143 |
144 | - (NSMutableArray *)cells {
145 | if (!_cells) {
146 | _cells = [NSMutableArray array];
147 | }
148 | return _cells;
149 | }
150 |
151 | - (NSInteger)cellCount {
152 | NSInteger count = 0;
153 | for (ZHTableViewCell *tableViewCell in self.cells) {
154 | count += tableViewCell.cellNumber;
155 | }
156 | return count;
157 | }
158 |
159 | - (ZHTableViewGroup *(^)(ZHTableViewHeaderFooter *))tableHeader {
160 | return ^(ZHTableViewHeaderFooter *header) {
161 | return self;
162 | };
163 | }
164 |
165 | - (ZHTableViewGroup *(^)(ZHTableViewHeaderFooter *))tableFooter {
166 | return ^(ZHTableViewHeaderFooter *footer) {
167 | return self;
168 | };
169 | }
170 |
171 | @end
172 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewGroupObjc.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewGroupObjc.h
3 | // ZHTableViewGroupObjc
4 | //
5 | // Created by josercc on 2020/3/3.
6 | // Copyright © 2020 josercc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for ZHTableViewGroupObjc.
12 | FOUNDATION_EXPORT double ZHTableViewGroupObjcVersionNumber;
13 |
14 | //! Project version string for ZHTableViewGroupObjc.
15 | FOUNDATION_EXPORT const unsigned char ZHTableViewGroupObjcVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 | #import "ZHTableViewDataSource.h"
20 | #import "ZHCollectionViewDataSource.h"
21 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewHeaderFooter.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewHeaderFooter.h
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewBaseModel.h"
10 |
11 | /**
12 | * 配置UITableViewHeaderFooterView的回调
13 |
14 | @param headerFooterView 需要设置配置的UITableViewHeaderFooterView
15 | @param section 需要配置的组
16 | */
17 | typedef void(^ZHTableViewHeaderFooterCompletionHandle)(UITableViewHeaderFooterView *headerFooterView, NSUInteger section);
18 |
19 | typedef NS_ENUM(NSUInteger, ZHTableViewHeaderFooterStyle) {
20 | ZHTableViewHeaderFooterStyleHeader,
21 | ZHTableViewHeaderFooterStyleFooter
22 | };
23 |
24 | @interface ZHTableViewHeaderFooter : ZHTableViewBaseModel
25 |
26 | @property (nonatomic, assign) ZHTableViewHeaderFooterStyle style;
27 |
28 | @property (nonatomic, copy) CGFloat(^customHeightBlock)(HeaderFooter view, NSUInteger section);
29 |
30 | /**
31 | * 根据样式进行初始化ZHTableViewHeaderFooter
32 |
33 | @param style 样式
34 | @return ZHTableViewHeaderFooter
35 | */
36 | - (instancetype)initWithStyle:(ZHTableViewHeaderFooterStyle)style;
37 |
38 | /**
39 | * 执行配置UITableViewHeaderFooterView
40 |
41 | @param headerFooter UITableViewHeaderFooterView的泛型
42 | @param section 配置所在的Section
43 | */
44 | - (void)setHeaderFooter:(HeaderFooter)headerFooter section:(NSUInteger)section;
45 |
46 | /**
47 | * 配置Header的回调
48 |
49 | @param block 配置的Block
50 | */
51 | - (void)configurationHeader:(void(^)(HeaderFooter header, NSUInteger section))block;
52 | /**
53 | * 配置Footer的回调
54 |
55 | @param block 配置的Block
56 | */
57 | - (void)configurationFooter:(void(^)(HeaderFooter footer, NSUInteger section))block;
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/ZHTableViewHeaderFooter.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZHTableViewHeaderFooter.m
3 | // Pods
4 | //
5 | // Created by 张行 on 2017/3/18.
6 | //
7 | //
8 |
9 | #import "ZHTableViewHeaderFooter.h"
10 |
11 | @implementation ZHTableViewHeaderFooter {
12 | ZHTableViewHeaderFooterCompletionHandle _headerBlock;
13 | ZHTableViewHeaderFooterCompletionHandle _footerBlock;
14 | }
15 |
16 | - (instancetype)initWithStyle:(ZHTableViewHeaderFooterStyle)style {
17 | if (self = [super init]) {
18 | _style = style;
19 | }
20 | return self;
21 | }
22 |
23 | - (void)setHeaderFooter:(UITableViewHeaderFooterView *)headerFooter section:(NSUInteger)section {
24 | switch (self.style) {
25 | case ZHTableViewHeaderFooterStyleHeader: {
26 | if (_headerBlock) {
27 | _headerBlock(headerFooter,section);
28 | }
29 | }
30 | break;
31 | case ZHTableViewHeaderFooterStyleFooter: {
32 | if (_footerBlock) {
33 | _footerBlock(headerFooter,section);
34 | }
35 | }
36 | break;
37 | default:
38 | break;
39 | }
40 | }
41 |
42 | - (void)configurationHeader:(void (^)(UITableViewHeaderFooterView *header, NSUInteger section))block {
43 | _headerBlock = block;
44 | }
45 |
46 | -(void)configurationFooter:(void (^)(UITableViewHeaderFooterView *footer, NSUInteger section))block {
47 | _footerBlock = block;
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHAutoConfigurationCollectionViewDelegate.h:
--------------------------------------------------------------------------------
1 | ../ZHAutoConfigurationCollectionViewDelegate.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHAutoConfigurationTableViewDelegate.h:
--------------------------------------------------------------------------------
1 | ../ZHAutoConfigurationTableViewDelegate.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHCollectionViewBaseModel.h:
--------------------------------------------------------------------------------
1 | ../ZHCollectionViewBaseModel.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHCollectionViewCell.h:
--------------------------------------------------------------------------------
1 | ../ZHCollectionViewCell.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHCollectionViewDataSource.h:
--------------------------------------------------------------------------------
1 | ../ZHCollectionViewDataSource.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHCollectionViewGroup.h:
--------------------------------------------------------------------------------
1 | ../ZHCollectionViewGroup.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHCollectionViewHeaderFooter.h:
--------------------------------------------------------------------------------
1 | ../ZHCollectionViewHeaderFooter.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHTableViewBaseModel.h:
--------------------------------------------------------------------------------
1 | ../ZHTableViewBaseModel.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHTableViewCell.h:
--------------------------------------------------------------------------------
1 | ../ZHTableViewCell.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHTableViewDataSource.h:
--------------------------------------------------------------------------------
1 | ../ZHTableViewDataSource.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHTableViewGroup.h:
--------------------------------------------------------------------------------
1 | ../ZHTableViewGroup.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHTableViewGroupObjc.h:
--------------------------------------------------------------------------------
1 | ../ZHTableViewGroupObjc.h
--------------------------------------------------------------------------------
/ZHTableViewGroupExample/ZHTableViewGroupObjc/include/ZHTableViewHeaderFooter.h:
--------------------------------------------------------------------------------
1 | ../ZHTableViewHeaderFooter.h
--------------------------------------------------------------------------------
/ZHTableViewGroupObjc.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint ZHTableViewGroup.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 | # Any lines starting with a # are optional, but their use is encouraged
6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = 'ZHTableViewGroupObjc'
11 | s.version = '3.5.5'
12 | s.summary = 'Manger UITableView DataSource More Cell Style'
13 |
14 | s.homepage = 'https://github.com/josercc/ZHTableViewGroup'
15 | s.license = { :type => 'MIT', :file => 'LICENSE' }
16 | s.author = { '15038777234' => '15038777234@163.com' }
17 | s.source = { :git => 'https://github.com/josercc/ZHTableViewGroup.git', :tag => s.version.to_s }
18 | s.ios.deployment_target = '8.0'
19 | s.source_files = 'ZHTableViewGroupExample/ZHTableViewGroupObjc/**/*.{h,m}'
20 | end
21 |
--------------------------------------------------------------------------------
/images/2019-08-20-034515.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/images/2019-08-20-034515.png
--------------------------------------------------------------------------------
/images/2019-08-20-035055.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/images/2019-08-20-035055.png
--------------------------------------------------------------------------------
/images/image-20190820115521632.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/images/image-20190820115521632.png
--------------------------------------------------------------------------------
/images/image-20190820115538881.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/images/image-20190820115538881.png
--------------------------------------------------------------------------------
/images/image-20190820115647037.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/images/image-20190820115647037.png
--------------------------------------------------------------------------------
/images/image-20190820115743952.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josercc/ZHTableViewGroup/30d5a4246d49d70bfeb3465ad6fe931bbbe7acf2/images/image-20190820115743952.png
--------------------------------------------------------------------------------