├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Example
├── HoloTableView.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── HoloTableView-Example.xcscheme
├── HoloTableView.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── HoloTableView
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── HoloAppDelegate.h
│ ├── HoloAppDelegate.m
│ ├── HoloExampleFooterView.h
│ ├── HoloExampleFooterView.m
│ ├── HoloExampleHeaderView.h
│ ├── HoloExampleHeaderView.m
│ ├── HoloExampleTableViewCell.h
│ ├── HoloExampleTableViewCell.m
│ ├── HoloTableView-Info.plist
│ ├── HoloTableView-Prefix.pch
│ ├── HoloViewController.h
│ ├── HoloViewController.m
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ └── main.m
├── Podfile
├── Podfile.lock
└── Tests
│ ├── HoloTableRowInsterTest.m
│ ├── HoloTableRowMakerTest.m
│ ├── HoloTableRowRemakerTest.m
│ ├── HoloTableRowRemoverTest.m
│ ├── HoloTableRowUpdaterTest.m
│ ├── HoloTableSectionInsterTest.m
│ ├── HoloTableSectionMakerTest.m
│ ├── HoloTableSectionRemakerTest.m
│ ├── HoloTableSectionRemoverTest.m
│ ├── HoloTableSectionUpdaterTest.m
│ ├── Tests-Info.plist
│ ├── Tests-Prefix.pch
│ ├── Tests.m
│ └── en.lproj
│ └── InfoPlist.strings
├── HoloTableView.podspec
├── HoloTableView
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── Core
│ ├── HoloTableViewProxy.h
│ ├── HoloTableViewProxy.m
│ ├── HoloTableViewProxyData.h
│ ├── HoloTableViewProxyData.m
│ ├── Protocol
│ │ ├── HoloTableViewCellProtocol.h
│ │ ├── HoloTableViewFooterProtocol.h
│ │ ├── HoloTableViewHeaderProtocol.h
│ │ └── HoloTableViewProtocol.h
│ ├── Row
│ │ ├── HoloTableRow.h
│ │ └── HoloTableRow.m
│ ├── Section
│ │ ├── HoloTableSection.h
│ │ └── HoloTableSection.m
│ ├── SwipeAction
│ │ ├── HoloTableViewRowSwipeAction.h
│ │ └── HoloTableViewRowSwipeAction.m
│ ├── UITableView+HoloTableViewProxy.h
│ └── UITableView+HoloTableViewProxy.m
│ ├── HoloTableView.h
│ ├── Macro
│ └── HoloTableViewMacro.h
│ ├── Maker
│ ├── Deprecated
│ │ ├── UITableView+HoloDeprecated.h
│ │ └── UITableView+HoloDeprecated.m
│ ├── Row
│ │ ├── HoloTableRowMaker.h
│ │ ├── HoloTableRowMaker.m
│ │ ├── HoloTableViewRowMaker.h
│ │ └── HoloTableViewRowMaker.m
│ ├── Section
│ │ ├── HoloTableSectionMaker.h
│ │ ├── HoloTableSectionMaker.m
│ │ ├── HoloTableViewSectionMaker.h
│ │ └── HoloTableViewSectionMaker.m
│ ├── TableView
│ │ ├── HoloTableViewMaker.h
│ │ └── HoloTableViewMaker.m
│ ├── UITableView+HoloTableView.h
│ ├── UITableView+HoloTableView.m
│ └── Update
│ │ ├── HoloTableViewUpdateRowMaker.h
│ │ └── HoloTableViewUpdateRowMaker.m
│ └── Responder Event
│ ├── UIResponder+HoloEvent.h
│ └── UIResponder+HoloEvent.m
├── LICENSE
├── README.md
└── README_CN.md
/.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 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
26 | # Carthage/Checkouts
27 |
28 | Carthage/Build
29 |
30 | # We recommend against adding the Pods directory to your .gitignore. However
31 | # you should judge for yourself, the pros and cons are mentioned at:
32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
33 | #
34 | # Note: if you ignore the Pods directory, make sure to uncomment
35 | # `pod install` in .travis.yml
36 | #
37 | Pods/
38 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | osx_image: xcode12
6 | language: objective-c
7 | # cache: cocoapods
8 | # podfile: Example/Podfile
9 | # before_install:
10 | # - gem install cocoapods # Since Travis is not always on latest version
11 | # - pod install --project-directory=Example
12 | script:
13 | # - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/HoloTableView.xcworkspace -scheme HoloTableView-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
14 | - pod lib lint --verbose
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 |
6 | ## 3.1.2 (06/03/2021)
7 |
8 | ### Updated
9 |
10 | - Check the cell class type and so on after the list appears.
11 | - Provide default cell class for row and default header and footer class for section.
12 | - Change `holo_proxy` of `UITableView+HoloTableViewProxy.h` to readonly.
13 |
14 |
15 | ## 3.1.1 (05/23/2021)
16 |
17 | ### Updated
18 |
19 | - Change api: 1, replace `holo_updateRows:inSection:` with `holo_updateRowsInSection:block:`; 2, replace `holo_remakeRows:inSection:` with `holo_remakeRowsInSection:block:`.
20 |
21 |
22 | ## 3.1.0 (05/20/2021)
23 |
24 | ### Added
25 |
26 | - Support for updating and remaking rows for a target section with a tag.
27 | - Support the `updateRows` and `remakeRows` methods for `sectionMaker`.
28 |
29 | ### Fixed
30 |
31 | - Update sections by `holo_updateSections:` method.
32 |
33 |
34 | ## 3.0.0 (05/04/2021)
35 |
36 | ### Added
37 |
38 | - Support to reload a table view by setting datasource with `HoloTableSection` and `HoloTableRow`. Add `holo_sections` for `UITableView`.
39 | - Add `holo_sectionIndexTitles` for `UITableView`.
40 | - Add `holo_sectionForSectionIndexTitleHandler` for `UITableView`.
41 | - Add `holo_scrollDelegate` for `UITableView`.
42 |
43 | ### Updated
44 |
45 | - Reuse header and footer. And if has no header and header title, return nil for header, if has no footer and footer title, return nil for footer.
46 |
47 | ### Removed
48 |
49 | - No longer support `headerFooterConfigSEL`, `headerFooterHeightSEL` and `headerFooterEstimatedHeightSEL` properties.
50 | - No longer support `rowS`, `headerS` and `footerS` properties. And no longer support to regist key-Class map (`rowsMap`, `headersMap` and `footersMap`).
51 |
52 |
53 | ## 2.4.0 (16/02/2021)
54 |
55 | - Update `HoloTableView.h`, use angle-bracketed instead of double-quoted.
56 | - Update `HoloTableViewMacro`, add `#if !defined()`.
57 | - Update `leadingSwipeActions` and `trailingSwipeActions`, only accept `HoloTableViewRowSwipeAction` type.
58 |
59 | ## 2.3.0 (09/12/2020)
60 |
61 | - Add `nullable` to property.
62 | - Delete the judgment that rows of section are greater than 0, in order to get the right section data.
63 |
64 | ## 2.2.0 (12/11/2020)
65 |
66 | - Add `beforeConfigureHandler` and `afterConfigureHandler`, performed before and after `configSEL`.
67 |
68 |
69 | ## 2.1.0 (13/08/2020)
70 |
71 | - Add `_Nullable` to method parameters in cell protocol, header protocol and footer protocol.
72 |
73 |
74 | ## 2.0.0 (23/07/2020)
75 |
76 | - Refactor the update, remake and insert methods for `UITableView` and optimize the code logic.
77 | - Provide more properties of section and row maker to handle proxy events of `UITableVIew`.
78 | - Provide more protocols, implemented in cells, headers and footers to handle proxy events of `UITableVIew`.
79 | - Support to regist maps (key-Class) for row, header and footer.
80 | - Check the index in `HoloTableViewProxy` for safety.
81 |
82 |
83 | ## 1.x (2019 ~ 2020)
84 |
85 | `HoloTableView` provides chained syntax calls that encapsulate delegate methods for `UITableView`. The delegate methods for `UITableView` is distributed to each `cell`, each `cell` having its own method for setting Class, model, height, and click event, etc.
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Example/HoloTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/HoloTableView.xcodeproj/xcshareddata/xcschemes/HoloTableView-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
64 |
70 |
71 |
72 |
73 |
79 |
81 |
87 |
88 |
89 |
90 |
92 |
93 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/Example/HoloTableView.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/HoloTableView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/HoloTableView/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 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Example/HoloTableView/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 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloAppDelegate.h
3 | // HoloTableView
4 | //
5 | // Created by gonghonglou on 07/28/2019.
6 | // Copyright (c) 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 |
11 | @interface HoloAppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloAppDelegate.m
3 | // HoloTableView
4 | //
5 | // Created by gonghonglou on 07/28/2019.
6 | // Copyright (c) 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import "HoloAppDelegate.h"
10 |
11 | @implementation HoloAppDelegate
12 |
13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 | {
15 | // Override point for customization after application launch.
16 | return YES;
17 | }
18 |
19 | - (void)applicationWillResignActive:(UIApplication *)application
20 | {
21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
23 | }
24 |
25 | - (void)applicationDidEnterBackground:(UIApplication *)application
26 | {
27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
29 | }
30 |
31 | - (void)applicationWillEnterForeground:(UIApplication *)application
32 | {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | - (void)applicationDidBecomeActive:(UIApplication *)application
37 | {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application
42 | {
43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloExampleFooterView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloExampleFooterView.h
3 | // HoloTableView_Example
4 | //
5 | // Created by 与佳期 on 2019/8/3.
6 | // Copyright © 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloExampleFooterView : UITableViewHeaderFooterView
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloExampleFooterView.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloExampleFooterView.m
3 | // HoloTableView_Example
4 | //
5 | // Created by 与佳期 on 2019/8/3.
6 | // Copyright © 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import "HoloExampleFooterView.h"
10 |
11 | @implementation HoloExampleFooterView
12 |
13 | - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {
14 | self = [super initWithReuseIdentifier:reuseIdentifier];
15 | if (self) {
16 | self.contentView.backgroundColor = [UIColor lightGrayColor];
17 | // self.textLabel.text will became nil when the footer is reused
18 | // self.textLabel.text = @"footer";
19 | }
20 | return self;
21 | }
22 |
23 | - (void)holo_configureFooterWithModel:(NSDictionary *)model {
24 | self.textLabel.text = model[@"title"];
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloExampleHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloExampleHeaderView.h
3 | // HoloTableView_Example
4 | //
5 | // Created by 与佳期 on 2019/8/3.
6 | // Copyright © 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface HoloExampleHeaderView : UITableViewHeaderFooterView
15 |
16 | @end
17 |
18 | NS_ASSUME_NONNULL_END
19 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloExampleHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloExampleHeaderView.m
3 | // HoloTableView_Example
4 | //
5 | // Created by 与佳期 on 2019/8/3.
6 | // Copyright © 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import "HoloExampleHeaderView.h"
10 |
11 | @implementation HoloExampleHeaderView
12 |
13 | - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {
14 | self = [super initWithReuseIdentifier:reuseIdentifier];
15 | if (self) {
16 | self.contentView.backgroundColor = [UIColor lightGrayColor];
17 | self.textLabel.text = @"header";
18 | }
19 | return self;
20 | }
21 |
22 | - (void)holo_configureHeaderWithModel:(NSDictionary *)model {
23 | self.textLabel.text = model[@"title"];
24 | }
25 |
26 | + (CGFloat)holo_heightForHeaderWithModel:(id)model {
27 | return 100;
28 | }
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloExampleTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloExampleTableViewCell.h
3 | // HoloTableView_Example
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | // Copyright © 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface HoloExampleTableViewCell : UITableViewCell
15 |
16 | @end
17 |
18 | NS_ASSUME_NONNULL_END
19 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloExampleTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloExampleTableViewCell.m
3 | // HoloTableView_Example
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | // Copyright © 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import "HoloExampleTableViewCell.h"
10 |
11 | @implementation HoloExampleTableViewCell
12 |
13 | - (void)holo_configureCellWithModel:(NSDictionary *)model {
14 | self.backgroundColor = model[@"bgColor"];
15 | self.textLabel.text = model[@"text"];
16 | }
17 |
18 | + (CGFloat)holo_heightForCellWithModel:(NSDictionary *)model {
19 | return [model[@"height"] floatValue];
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloTableView-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloTableView-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | @import UIKit;
15 | @import Foundation;
16 | #endif
17 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloViewController.h
3 | // HoloTableView
4 | //
5 | // Created by gonghonglou on 07/28/2019.
6 | // Copyright (c) 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 |
11 | @interface HoloViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/HoloTableView/HoloViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloViewController.m
3 | // HoloTableView
4 | //
5 | // Created by gonghonglou on 07/28/2019.
6 | // Copyright (c) 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import "HoloViewController.h"
10 | #import
11 | #import "HoloExampleHeaderView.h"
12 | #import "HoloExampleFooterView.h"
13 | #import "HoloExampleTableViewCell.h"
14 |
15 | #define HOLO_SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width
16 | #define HOLO_SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height
17 |
18 | @interface HoloViewController ()
19 |
20 | @property (nonatomic, strong) UIButton *addButton;
21 |
22 | @property (nonatomic, strong) UITableView *tableView;
23 |
24 | @property (nonatomic, copy) NSArray *modelArray;
25 |
26 | @end
27 |
28 | @implementation HoloViewController
29 |
30 | - (void)dealloc {
31 | NSLog(@"HoloExampleOneViewController dealloc");
32 | }
33 |
34 | - (void)viewDidLoad {
35 | [super viewDidLoad];
36 | // Do any additional setup after loading the view.
37 | [self.view addSubview:self.addButton];
38 | [self.view addSubview:self.tableView];
39 |
40 |
41 | [self makeSectionByMaker];
42 |
43 | // [self makeRowListWithDefaultSection];
44 |
45 | // [self makeSectionListByObject];
46 | }
47 |
48 |
49 | #pragma mark - Maker
50 |
51 | - (void)makeSectionByMaker {
52 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
53 | make.section(TAG)
54 | .header(HoloExampleHeaderView.class).headerModel(@{@"title":@"header"})
55 | .footer(HoloExampleFooterView.class).footerModel(@{@"title":@"footer"}).footerHeight(100)
56 | .makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
57 | for (NSDictionary *dict in self.modelArray) {
58 | make.row(HoloExampleTableViewCell.class).model(dict).didSelectHandler(^(id _Nullable model) {
59 | NSLog(@"did select row : %@", model);
60 | });
61 | }
62 | });
63 |
64 | // make.section(@"1")
65 | // make.section(@"2")
66 | // ...
67 | }];
68 | [self.tableView reloadData];
69 | }
70 |
71 | - (void)insertRowToSectionWithReloadAnimation {
72 | [self.tableView holo_insertRowsAtIndex:0 inSection:TAG block:^(HoloTableViewRowMaker * _Nonnull make) {
73 | make.row(HoloExampleTableViewCell.class).model(@{@"bgColor": [UIColor redColor], @"text": @"cell", @"height": @44});
74 | } withReloadAnimation:UITableViewRowAnimationNone];
75 | }
76 |
77 | - (void)makeRowListWithDefaultSection {
78 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
79 | for (NSDictionary *dict in self.modelArray) {
80 | make.row(HoloExampleTableViewCell.class).model(dict).didSelectHandler(^(id _Nullable model) {
81 | NSLog(@"did select row : %@", model);
82 | });
83 | }
84 | }];
85 | [self.tableView reloadData];
86 | }
87 |
88 |
89 | #pragma mark - Object
90 |
91 | - (void)makeSectionListByObject {
92 | HoloTableSection *section = [HoloTableSection new];
93 | section.tag = TAG;
94 |
95 | section.header = HoloExampleHeaderView.class;
96 | section.headerModel = @{@"title":@"header"};
97 |
98 | section.footer = HoloExampleFooterView.class;
99 | section.footerModel = @{@"title":@"footer"};
100 | section.footerHeight = 100;
101 |
102 | NSMutableArray *rows = [NSMutableArray new];
103 | for (NSDictionary *dict in self.modelArray) {
104 | HoloTableRow *row = [HoloTableRow new];
105 | row.cell = HoloExampleTableViewCell.class;
106 | row.model = dict;
107 | [rows addObject:row];
108 | }
109 | section.rows = rows;
110 |
111 | self.tableView.holo_sections = @[section];
112 | [self.tableView reloadData];
113 | }
114 |
115 |
116 | #pragma mark - buttonAction
117 |
118 | - (void)_addButtonAction:(UIButton *)sender {
119 | [self insertRowToSectionWithReloadAnimation];
120 | }
121 |
122 |
123 | #pragma mark - getter
124 |
125 | - (UIButton *)addButton {
126 | if (!_addButton) {
127 | _addButton = [UIButton buttonWithType:UIButtonTypeSystem];
128 | _addButton.frame = CGRectMake(50, 44, HOLO_SCREEN_WIDTH - 100, 44);
129 | [_addButton setTitle:@"add a cell" forState:UIControlStateNormal];
130 | [_addButton addTarget:self action:@selector(_addButtonAction:) forControlEvents:UIControlEventTouchUpInside];
131 | }
132 | return _addButton;
133 | }
134 |
135 | - (UITableView *)tableView {
136 | if (!_tableView) {
137 | CGRect frame = CGRectMake(0, 100, HOLO_SCREEN_WIDTH, HOLO_SCREEN_HEIGHT - 100);
138 | _tableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain];
139 | _tableView.tableFooterView = [UIView new];
140 | _tableView.estimatedRowHeight = 0;
141 | _tableView.estimatedSectionHeaderHeight = 0;
142 | _tableView.estimatedSectionFooterHeight = 0;
143 | }
144 | return _tableView;
145 | }
146 |
147 | - (NSArray *)modelArray {
148 | if (!_modelArray) {
149 | _modelArray = @[
150 | @{@"bgColor": [UIColor yellowColor], @"text": @"cell-1", @"height": @66},
151 | @{@"bgColor": [UIColor cyanColor], @"text": @"cell-2", @"height": @66},
152 | @{@"bgColor": [UIColor orangeColor], @"text": @"cell-3", @"height": @66},
153 | ];
154 | }
155 | return _modelArray;
156 | }
157 |
158 | @end
159 |
--------------------------------------------------------------------------------
/Example/HoloTableView/Images.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 | }
99 |
--------------------------------------------------------------------------------
/Example/HoloTableView/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/HoloTableView/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // HoloTableView
4 | //
5 | // Created by gonghonglou on 07/28/2019.
6 | // Copyright (c) 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 | #import "HoloAppDelegate.h"
11 |
12 | int main(int argc, char * argv[])
13 | {
14 | @autoreleasepool {
15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([HoloAppDelegate class]));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | #use_frameworks!
2 |
3 | platform :ios, '8.0'
4 |
5 | target 'HoloTableView_Example' do
6 | pod 'HoloTableView', :path => '../'
7 |
8 | target 'HoloTableView_Tests' do
9 | inherit! :search_paths
10 |
11 |
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - HoloTableView (3.1.2)
3 |
4 | DEPENDENCIES:
5 | - HoloTableView (from `../`)
6 |
7 | EXTERNAL SOURCES:
8 | HoloTableView:
9 | :path: "../"
10 |
11 | SPEC CHECKSUMS:
12 | HoloTableView: 0bb60eaded87d266df87e48aa7a1e58055ed29d2
13 |
14 | PODFILE CHECKSUM: 4a04413c8d8cb6d0e0045bb58a41b9b63e9ba415
15 |
16 | COCOAPODS: 1.10.1
17 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableRowInsterTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowInsterTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableRowInsterTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableRowInsterTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 |
23 | self.tableView = [UITableView new];
24 |
25 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
26 | make.row(UITableViewCell.class).tag(TAG);
27 | }];
28 |
29 |
30 | // insert rows in section
31 |
32 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
33 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
34 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
35 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
36 | });
37 |
38 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
39 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
40 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
41 | });
42 | }];
43 | }
44 |
45 | - (void)tearDown {
46 | // Put teardown code here. This method is called after the invocation of each test method in the class.
47 | }
48 |
49 |
50 | #pragma mark - insert rows
51 |
52 | - (void)testInsertRows {
53 | [self.tableView holo_insertRowsAtIndex:0 block:^(HoloTableViewRowMaker * _Nonnull make) {
54 | make.row(UITableViewCell.class).tag(@"0").height(0);
55 | make.row(UITableViewCell.class).tag(@"1").height(1);
56 | }];
57 |
58 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
59 |
60 | HoloTableSection *section = self.tableView.holo_sections[0];
61 |
62 | XCTAssertEqual(section.rows.count, 3);
63 |
64 |
65 | HoloTableRow *row0 = section.rows[0];
66 | HoloTableRow *row1 = section.rows[1];
67 | HoloTableRow *row2 = section.rows[2];
68 |
69 | XCTAssertEqual(row0.tag, @"0");
70 | XCTAssertEqual(row1.tag, @"1");
71 | XCTAssertEqual(row2.tag, TAG);
72 |
73 | XCTAssertEqual(row0.height, 0);
74 | XCTAssertEqual(row1.height, 1);
75 | XCTAssertEqual(row2.height, CGFLOAT_MIN);
76 |
77 | [self.tableView holo_insertRowsAtIndex:3 block:^(HoloTableViewRowMaker * _Nonnull make) {
78 | make.row(UITableViewCell.class).tag(@"3").height(3);
79 | make.row(UITableViewCell.class).tag(@"4").height(4);
80 | }];
81 |
82 | XCTAssertEqual(section.rows.count, 5);
83 |
84 | HoloTableRow *row3 = section.rows[3];
85 | HoloTableRow *row4 = section.rows[4];
86 |
87 | XCTAssertEqual(row3.tag, @"3");
88 | XCTAssertEqual(row3.height, 3);
89 |
90 | XCTAssertEqual(row4.tag, @"4");
91 | XCTAssertEqual(row4.height, 4);
92 | }
93 |
94 |
95 | #pragma mark - insert rows in section
96 |
97 | - (void)testInsertRowsInSection {
98 | [self.tableView holo_insertRowsAtIndex:2 inSection:@"section-1" block:^(HoloTableViewRowMaker * _Nonnull make) {
99 | make.row(UITableViewCell.class).tag(@"2").model(@"2").height(2);
100 | }];
101 |
102 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
103 |
104 | HoloTableSection *section0 = self.tableView.holo_sections[0];
105 | HoloTableSection *section1 = self.tableView.holo_sections[1];
106 | HoloTableSection *section2 = self.tableView.holo_sections[2];
107 |
108 | XCTAssertEqual(section0.rows.count, 1);
109 | XCTAssertEqual(section1.rows.count, 3); // changed
110 | XCTAssertEqual(section2.rows.count, 2);
111 |
112 |
113 | // when you insert some rows to a section that doesn't already exist, will automatically create a new section.
114 |
115 | [self.tableView holo_insertRowsAtIndex:2 inSection:@"section-1000" block:^(HoloTableViewRowMaker * _Nonnull make) {
116 | make.row(UITableViewCell.class).tag(@"2").model(@"2").height(2);
117 | }];
118 |
119 | XCTAssertEqual(self.tableView.holo_sections.count, 4);
120 |
121 | HoloTableSection *section3 = self.tableView.holo_sections[3];
122 | XCTAssertEqual(section3.rows.count, 1);
123 | }
124 |
125 | - (void)testPerformanceExample {
126 | // This is an example of a performance test case.
127 | [self measureBlock:^{
128 | // Put the code you want to measure the time of here.
129 | }];
130 | }
131 |
132 | @end
133 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableRowMakerTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowMakerTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/20.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableRowMakerTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableRowMakerTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 |
23 | self.tableView = [UITableView new];
24 |
25 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
26 | make.row(UITableViewCell.class)
27 | .model(@"model")
28 | .modelHandler(^id _Nonnull{
29 | return @"modelHandler";
30 | })
31 |
32 | .style(UITableViewCellStyleValue1)
33 | .styleHandler(^UITableViewCellStyle(id _Nullable model) {
34 | return UITableViewCellStyleValue2;
35 | })
36 |
37 | .reuseId(@"reuseId")
38 | .reuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
39 | return @"reuseIdHandler";
40 | })
41 |
42 | .tag(TAG)
43 |
44 | .height(10)
45 | .heightHandler(^CGFloat(id _Nullable model) {
46 | return 11;
47 | })
48 |
49 | .estimatedHeight(100)
50 | .estimatedHeightHandler(^CGFloat(id _Nullable model) {
51 | return 101;
52 | })
53 |
54 | .shouldHighlight(NO)
55 | .shouldHighlightHandler(^BOOL(id _Nullable model) {
56 | return NO;
57 | })
58 |
59 | .canEdit(YES)
60 | .canEditHandler(^BOOL(id _Nullable model) {
61 | return YES;
62 | })
63 |
64 | .canMove(YES)
65 | .canMoveHandler(^BOOL(id _Nullable model) {
66 | return YES;
67 | })
68 |
69 | .leadingSwipeActions(@[[HoloTableViewRowSwipeAction new]])
70 | .trailingSwipeActions(@[[HoloTableViewRowSwipeAction new]])
71 |
72 | .editingDeleteTitle(@"editingDeleteTitle")
73 | .editingDeleteTitleHandler(^NSString * _Nonnull(id _Nullable model) {
74 | return @"editingDeleteTitleHandler";
75 | })
76 |
77 | .editingStyle(UITableViewCellEditingStyleDelete)
78 | .editingStyleHandler(^UITableViewCellEditingStyle(id _Nullable model) {
79 | return UITableViewCellEditingStyleInsert;
80 | });
81 | }];
82 |
83 |
84 | // make rows in section
85 |
86 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
87 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
88 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
89 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
90 | });
91 |
92 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
93 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
94 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
95 | });
96 | }];
97 | }
98 |
99 | - (void)tearDown {
100 | // Put teardown code here. This method is called after the invocation of each test method in the class.
101 | }
102 |
103 | #pragma mark - make rows
104 |
105 | - (void)testMakeRows {
106 | // This is an example of a functional test case.
107 | // Use XCTAssert and related functions to verify your tests produce the correct results.
108 |
109 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
110 |
111 | HoloTableSection *section = self.tableView.holo_sections[0];
112 |
113 | XCTAssertEqual(section.rows.count, 1);
114 |
115 | HoloTableRow *row = section.rows[0];
116 |
117 | XCTAssertEqual(row.cell, UITableViewCell.class);
118 | XCTAssertEqual(row.model, @"model");
119 | XCTAssertEqual(row.style, UITableViewCellStyleValue1);
120 | XCTAssertEqual(row.reuseId, @"reuseId");
121 | XCTAssertEqual(row.tag, TAG);
122 | XCTAssertEqual(row.height, 10);
123 | XCTAssertEqual(row.estimatedHeight, 100);
124 | XCTAssertEqual(row.shouldHighlight, NO);
125 | XCTAssertEqual(row.canEdit, YES);
126 | XCTAssertEqual(row.canMove, YES);
127 | XCTAssertEqual(row.leadingSwipeActions.count, 1);
128 | XCTAssertEqual(row.trailingSwipeActions.count, 1);
129 | XCTAssertEqual(row.editingDeleteTitle, @"editingDeleteTitle");
130 | XCTAssertEqual(row.editingStyle, UITableViewCellEditingStyleDelete);
131 | }
132 |
133 |
134 | #pragma mark - make rows in section
135 |
136 | - (void)testMakeRowsInSection {
137 | // This is an example of a functional test case.
138 | // Use XCTAssert and related functions to verify your tests produce the correct results.
139 |
140 | [self.tableView holo_makeRowsInSection:@"section-1" block:^(HoloTableViewRowMaker * _Nonnull make) {
141 | make.row(UITableViewCell.class).tag(@"2").model(@"2").height(2);
142 | }];
143 |
144 | // section(TAG)
145 | // section(@"section-1")
146 | // section(@"section-1")
147 |
148 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
149 |
150 | HoloTableSection *section0 = self.tableView.holo_sections[0];
151 | HoloTableSection *section1 = self.tableView.holo_sections[1];
152 | HoloTableSection *section2 = self.tableView.holo_sections[2];
153 |
154 | XCTAssertEqual(section0.rows.count, 1);
155 | XCTAssertEqual(section1.rows.count, 3); // changed
156 | XCTAssertEqual(section2.rows.count, 2);
157 |
158 |
159 | // when you make some rows to a section that doesn't already exist, will automatically create a new section.
160 |
161 | [self.tableView holo_makeRowsInSection:@"section-1000" block:^(HoloTableViewRowMaker * _Nonnull make) {
162 | make.row(UITableViewCell.class).tag(@"2").model(@"2").height(2);
163 | }];
164 |
165 | // section(TAG)
166 | // section(@"section-1")
167 | // section(@"section-1")
168 | // section(@"section-1000")
169 |
170 | XCTAssertEqual(self.tableView.holo_sections.count, 4);
171 |
172 | HoloTableSection *section3 = self.tableView.holo_sections[3];
173 | XCTAssertEqual(section3.rows.count, 1);
174 | }
175 |
176 | - (void)testPerformanceExample {
177 | // This is an example of a performance test case.
178 | [self measureBlock:^{
179 | // Put the code you want to measure the time of here.
180 | }];
181 | }
182 |
183 | @end
184 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableRowRemakerTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowRemakerTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface TestTableViewCell2 : UITableViewCell
13 | @end
14 | @implementation TestTableViewCell2
15 | @end
16 |
17 |
18 | @interface HoloTableRowRemakerTest : XCTestCase
19 |
20 | @property (nonatomic, strong) UITableView *tableView;
21 |
22 | @end
23 |
24 | @implementation HoloTableRowRemakerTest
25 |
26 | - (void)setUp {
27 | // Put setup code here. This method is called before the invocation of each test method in the class.
28 |
29 | self.tableView = [UITableView new];
30 |
31 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
32 | make.row(UITableViewCell.class)
33 | .model(@"model")
34 | .modelHandler(^id _Nonnull{
35 | return @"modelHandler";
36 | })
37 |
38 | .style(UITableViewCellStyleValue1)
39 | .styleHandler(^UITableViewCellStyle(id _Nullable model) {
40 | return UITableViewCellStyleValue2;
41 | })
42 |
43 | .reuseId(@"reuseId")
44 | .reuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
45 | return @"reuseIdHandler";
46 | })
47 |
48 | .tag(TAG)
49 |
50 | .height(10)
51 | .heightHandler(^CGFloat(id _Nullable model) {
52 | return 11;
53 | })
54 |
55 | .estimatedHeight(100)
56 | .estimatedHeightHandler(^CGFloat(id _Nullable model) {
57 | return 101;
58 | })
59 |
60 | .shouldHighlight(NO)
61 | .shouldHighlightHandler(^BOOL(id _Nullable model) {
62 | return NO;
63 | })
64 |
65 | .canEdit(YES)
66 | .canEditHandler(^BOOL(id _Nullable model) {
67 | return YES;
68 | })
69 |
70 | .canMove(YES)
71 | .canMoveHandler(^BOOL(id _Nullable model) {
72 | return YES;
73 | })
74 |
75 | .leadingSwipeActions(@[[HoloTableViewRowSwipeAction new]])
76 | .trailingSwipeActions(@[[HoloTableViewRowSwipeAction new]])
77 |
78 | .editingDeleteTitle(@"editingDeleteTitle")
79 | .editingDeleteTitleHandler(^NSString * _Nonnull(id _Nullable model) {
80 | return @"editingDeleteTitleHandler";
81 | })
82 |
83 | .editingStyle(UITableViewCellEditingStyleDelete)
84 | .editingStyleHandler(^UITableViewCellEditingStyle(id _Nullable model) {
85 | return UITableViewCellEditingStyleInsert;
86 | });
87 | }];
88 |
89 |
90 | // remake rows in section
91 |
92 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
93 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
94 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
95 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
96 | });
97 |
98 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
99 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
100 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
101 | });
102 | }];
103 | }
104 |
105 | - (void)tearDown {
106 | // Put teardown code here. This method is called after the invocation of each test method in the class.
107 | }
108 |
109 |
110 | #pragma mark - remake rows
111 |
112 | - (void)testRemakeRows {
113 | [self.tableView holo_remakeRows:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
114 | make.tag(TAG).row(TestTableViewCell2.class);
115 | }];
116 |
117 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
118 |
119 | HoloTableSection *section = self.tableView.holo_sections[0];
120 |
121 | XCTAssertEqual(section.rows.count, 1);
122 |
123 | HoloTableRow *row = section.rows[0];
124 |
125 |
126 | XCTAssertEqual(row.cell, TestTableViewCell2.class);
127 | XCTAssertNil(row.model);
128 | XCTAssertEqual(row.style, UITableViewCellStyleDefault);
129 | XCTAssertNil(row.reuseId);
130 | XCTAssertEqual(row.height, CGFLOAT_MIN);
131 | XCTAssertEqual(row.estimatedHeight, CGFLOAT_MIN);
132 | XCTAssertEqual(row.shouldHighlight, YES);
133 | XCTAssertEqual(row.canEdit, NO);
134 | XCTAssertEqual(row.canMove, NO);
135 | XCTAssertEqual(row.leadingSwipeActions.count, 0);
136 | XCTAssertEqual(row.trailingSwipeActions.count, 0);
137 | XCTAssertNil(row.editingDeleteTitle);
138 | XCTAssertEqual(row.editingStyle, UITableViewCellEditingStyleNone);
139 |
140 |
141 | // multiple rows with the same tag
142 |
143 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
144 | make.row(UITableViewCell.class).tag(@"1");
145 | make.row(UITableViewCell.class).tag(@"1");
146 | }];
147 |
148 | HoloTableRow *row1 = section.rows[1];
149 | HoloTableRow *row2 = section.rows[2];
150 |
151 | XCTAssertEqual(row1.cell, UITableViewCell.class);
152 | XCTAssertEqual(row2.cell, UITableViewCell.class);
153 |
154 | [self.tableView holo_remakeRows:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
155 | make.tag(@"1").row(TestTableViewCell2.class);
156 | make.tag(@"1").row(TestTableViewCell2.class);
157 | }];
158 |
159 | HoloTableRow *rowNew1 = section.rows[1];
160 | HoloTableRow *rowNew2 = section.rows[2];
161 | XCTAssertEqual(rowNew1.cell, TestTableViewCell2.class);
162 | XCTAssertEqual(rowNew2.cell, UITableViewCell.class);
163 | }
164 |
165 |
166 | #pragma mark - remake rows in section
167 |
168 | - (void)testRemakeRowsInSection {
169 | [self.tableView holo_remakeRowsInSection:@"section-1" block:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
170 | make.tag(@"0").row(UITableViewCell.class);
171 | }];
172 |
173 | // section(TAG)
174 | // section(@"section-1")
175 | // section(@"section-1")
176 |
177 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
178 |
179 | HoloTableSection *section0 = self.tableView.holo_sections[0];
180 | HoloTableSection *section1 = self.tableView.holo_sections[1];
181 | HoloTableSection *section2 = self.tableView.holo_sections[2];
182 |
183 | XCTAssertEqual(section0.rows.count, 1);
184 | XCTAssertEqual(section1.rows.count, 2);
185 | XCTAssertEqual(section2.rows.count, 2);
186 |
187 | HoloTableRow *row0InSection1 = section1.rows[0];
188 | HoloTableRow *row1InSection1 = section1.rows[1];
189 |
190 | XCTAssertEqual(row0InSection1.height, CGFLOAT_MIN); // changed
191 | XCTAssertNil(row0InSection1.model); // changed
192 | XCTAssertEqual(row1InSection1.height, 1);
193 |
194 | HoloTableRow *row0InSection2 = section2.rows[0];
195 | HoloTableRow *row1InSection2 = section2.rows[1];
196 |
197 | XCTAssertEqual(row0InSection2.height, 0);
198 | XCTAssertEqual(row1InSection2.height, 1);
199 |
200 |
201 | // when you remake some rows to a section that doesn't already exist, then ignore it.
202 |
203 | [self.tableView holo_remakeRowsInSection:@"section-1000" block:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
204 | make.tag(@"0").row(UITableViewCell.class);
205 | }];
206 |
207 | // section(TAG)
208 | // section(@"section-1")
209 | // section(@"section-1")
210 |
211 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
212 | }
213 |
214 | - (void)testPerformanceExample {
215 | // This is an example of a performance test case.
216 | [self measureBlock:^{
217 | // Put the code you want to measure the time of here.
218 | }];
219 | }
220 |
221 | @end
222 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableRowRemoverTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowRemoverTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableRowRemoverTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableRowRemoverTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 |
23 | self.tableView = [UITableView new];
24 |
25 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
26 | make.row(UITableViewCell.class).tag(TAG);
27 | }];
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | }
33 |
34 | - (void)testRemoveRows {
35 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
36 | make.row(UITableViewCell.class).tag(@"1");
37 | make.row(UITableViewCell.class).tag(@"2");
38 | make.row(UITableViewCell.class).tag(@"2");
39 | make.row(UITableViewCell.class).tag(@"3");
40 | }];
41 | XCTAssertEqual(self.tableView.holo_sections.firstObject.rows.count, 5);
42 |
43 | [self.tableView holo_removeRows:@[@"1", @"2"]];
44 |
45 | XCTAssertEqual(self.tableView.holo_sections.firstObject.rows.count, 2);
46 |
47 | HoloTableRow *lastRow = self.tableView.holo_sections.firstObject.rows[1];
48 | XCTAssertEqual(lastRow.tag, @"3");
49 |
50 | [self.tableView holo_removeAllSections];
51 | XCTAssertEqual(self.tableView.holo_sections.firstObject.rows.count, 0);
52 | }
53 |
54 | - (void)testPerformanceExample {
55 | // This is an example of a performance test case.
56 | [self measureBlock:^{
57 | // Put the code you want to measure the time of here.
58 | }];
59 | }
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableRowUpdaterTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowUpdaterTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface TestTableViewCell : UITableViewCell
13 | @end
14 | @implementation TestTableViewCell
15 | @end
16 |
17 |
18 | @interface HoloTableRowUpdaterTest : XCTestCase
19 |
20 | @property (nonatomic, strong) UITableView *tableView;
21 |
22 | @end
23 |
24 | @implementation HoloTableRowUpdaterTest
25 |
26 | - (void)setUp {
27 | // Put setup code here. This method is called before the invocation of each test method in the class.
28 |
29 | self.tableView = [UITableView new];
30 |
31 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
32 | make.row(UITableViewCell.class)
33 | .model(@"model")
34 | .modelHandler(^id _Nonnull{
35 | return @"modelHandler";
36 | })
37 |
38 | .style(UITableViewCellStyleValue1)
39 | .styleHandler(^UITableViewCellStyle(id _Nullable model) {
40 | return UITableViewCellStyleValue2;
41 | })
42 |
43 | .reuseId(@"reuseId")
44 | .reuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
45 | return @"reuseIdHandler";
46 | })
47 |
48 | .tag(TAG)
49 |
50 | .height(10)
51 | .heightHandler(^CGFloat(id _Nullable model) {
52 | return 11;
53 | })
54 |
55 | .estimatedHeight(100)
56 | .estimatedHeightHandler(^CGFloat(id _Nullable model) {
57 | return 101;
58 | })
59 |
60 | .shouldHighlight(NO)
61 | .shouldHighlightHandler(^BOOL(id _Nullable model) {
62 | return NO;
63 | })
64 |
65 | .canEdit(YES)
66 | .canEditHandler(^BOOL(id _Nullable model) {
67 | return YES;
68 | })
69 |
70 | .canMove(YES)
71 | .canMoveHandler(^BOOL(id _Nullable model) {
72 | return YES;
73 | })
74 |
75 | .leadingSwipeActions(@[[HoloTableViewRowSwipeAction new]])
76 | .trailingSwipeActions(@[[HoloTableViewRowSwipeAction new]])
77 |
78 | .editingDeleteTitle(@"editingDeleteTitle")
79 | .editingDeleteTitleHandler(^NSString * _Nonnull(id _Nullable model) {
80 | return @"editingDeleteTitleHandler";
81 | })
82 |
83 | .editingStyle(UITableViewCellEditingStyleDelete)
84 | .editingStyleHandler(^UITableViewCellEditingStyle(id _Nullable model) {
85 | return UITableViewCellEditingStyleInsert;
86 | });
87 | }];
88 |
89 |
90 | // update rows in section
91 |
92 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
93 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
94 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
95 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
96 | });
97 |
98 | make.section(@"section-1").headerHeight(100).makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
99 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
100 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
101 | });
102 | }];
103 | }
104 |
105 | - (void)tearDown {
106 | // Put teardown code here. This method is called after the invocation of each test method in the class.
107 | }
108 |
109 | #pragma mark - update rows
110 |
111 | - (void)testUpdateRows {
112 | [self.tableView holo_updateRows:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
113 | make.tag(TAG)
114 | .row(TestTableViewCell.class)
115 | .model(@"model-new")
116 | .style(UITableViewCellStyleValue2)
117 | .reuseId(@"reuseId-new")
118 | .height(101)
119 | .estimatedHeight(1001)
120 | .shouldHighlight(YES)
121 | .canEdit(NO)
122 | .canMove(NO)
123 | .leadingSwipeActions(@[])
124 | .trailingSwipeActions(@[])
125 | .editingDeleteTitle(@"editingDeleteTitle-new")
126 | .editingStyle(UITableViewCellEditingStyleInsert);
127 | }];
128 |
129 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
130 |
131 | HoloTableSection *section = self.tableView.holo_sections[0];
132 |
133 | XCTAssertEqual(section.rows.count, 1);
134 |
135 | HoloTableRow *row = section.rows[0];
136 |
137 |
138 | XCTAssertEqual(row.cell, TestTableViewCell.class);
139 | XCTAssertEqual(row.model, @"model-new");
140 | XCTAssertEqual(row.style, UITableViewCellStyleValue2);
141 | XCTAssertEqual(row.reuseId, @"reuseId-new");
142 | XCTAssertEqual(row.height, 101);
143 | XCTAssertEqual(row.estimatedHeight, 1001);
144 | XCTAssertEqual(row.shouldHighlight, YES);
145 | XCTAssertEqual(row.canEdit, NO);
146 | XCTAssertEqual(row.canMove, NO);
147 | XCTAssertEqual(row.leadingSwipeActions.count, 0);
148 | XCTAssertEqual(row.trailingSwipeActions.count, 0);
149 | XCTAssertEqual(row.editingDeleteTitle, @"editingDeleteTitle-new");
150 | XCTAssertEqual(row.editingStyle, UITableViewCellEditingStyleInsert);
151 |
152 |
153 | // multiple rows with the same tag
154 |
155 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
156 | make.row(UITableViewCell.class).tag(@"1").height(1);
157 | make.row(UITableViewCell.class).tag(@"1").height(10);
158 | }];
159 |
160 | HoloTableRow *row1 = section.rows[1];
161 | HoloTableRow *row2 = section.rows[2];
162 |
163 | XCTAssertEqual(row1.height, 1);
164 | XCTAssertEqual(row2.height, 10);
165 |
166 | [self.tableView holo_updateRows:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
167 | make.tag(@"1").height(100);
168 | make.tag(@"1").height(101);
169 | }];
170 |
171 | HoloTableRow *rowNew1 = section.rows[1];
172 | HoloTableRow *rowNew2 = section.rows[2];
173 |
174 | XCTAssertEqual(rowNew1.height, 101);
175 | XCTAssertEqual(rowNew2.height, 10);
176 | }
177 |
178 | #pragma mark - update rows in section
179 |
180 | - (void)testUpdateRowsInSection {
181 | [self.tableView holo_updateRowsInSection:@"section-1" block:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
182 | make.tag(@"0").height(1000);
183 | }];
184 |
185 | // section(TAG)
186 | // section(@"section-1")
187 | // section(@"section-1")
188 |
189 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
190 |
191 | HoloTableSection *section0 = self.tableView.holo_sections[0];
192 | HoloTableSection *section1 = self.tableView.holo_sections[1];
193 | HoloTableSection *section2 = self.tableView.holo_sections[2];
194 |
195 | XCTAssertEqual(section0.rows.count, 1);
196 | XCTAssertEqual(section1.rows.count, 2);
197 | XCTAssertEqual(section2.rows.count, 2);
198 |
199 | HoloTableRow *row0InSection1 = section1.rows[0];
200 | HoloTableRow *row1InSection1 = section1.rows[1];
201 |
202 | XCTAssertEqual(row0InSection1.height, 1000); // changed
203 | XCTAssertEqual(row1InSection1.height, 1);
204 |
205 | HoloTableRow *row0InSection2 = section2.rows[0];
206 | HoloTableRow *row1InSection2 = section2.rows[1];
207 |
208 | XCTAssertEqual(row0InSection2.height, 0);
209 | XCTAssertEqual(row1InSection2.height, 1);
210 |
211 |
212 | // when you update some rows to a section that doesn't already exist, then ignore it.
213 |
214 | [self.tableView holo_updateRowsInSection:@"section-1000" block:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
215 | make.tag(@"1").height(1000);
216 | }];
217 |
218 | // section(TAG)
219 | // section(@"section-1")
220 | // section(@"section-1")
221 |
222 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
223 | }
224 |
225 |
226 | - (void)testPerformanceExample {
227 | // This is an example of a performance test case.
228 | [self measureBlock:^{
229 | // Put the code you want to measure the time of here.
230 | }];
231 | }
232 |
233 | @end
234 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableSectionInsterTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSectionInsterTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableSectionInsterTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableSectionInsterTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 | self.tableView = [UITableView new];
23 |
24 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
25 | make.section(TAG);
26 | }];
27 | }
28 |
29 | - (void)tearDown {
30 | // Put teardown code here. This method is called after the invocation of each test method in the class.
31 | }
32 |
33 | - (void)testInsertSections {
34 | [self.tableView holo_insertSectionsAtIndex:0 block:^(HoloTableViewSectionMaker * _Nonnull make) {
35 | make.section(@"0").headerHeight(0);
36 | make.section(@"1").headerHeight(1);
37 | }];
38 |
39 | // section(@"0")
40 | // section(@"1")
41 | // section(TAG)
42 |
43 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
44 |
45 | HoloTableSection *section0 = self.tableView.holo_sections[0];
46 | HoloTableSection *section1 = self.tableView.holo_sections[1];
47 | HoloTableSection *section2 = self.tableView.holo_sections[2];
48 |
49 | XCTAssertEqual(section0.tag, @"0");
50 | XCTAssertEqual(section1.tag, @"1");
51 | XCTAssertEqual(section2.tag, TAG);
52 |
53 | XCTAssertEqual(section0.headerHeight, 0);
54 | XCTAssertEqual(section1.headerHeight, 1);
55 | XCTAssertEqual(section2.headerHeight, CGFLOAT_MIN);
56 |
57 |
58 | [self.tableView holo_insertSectionsAtIndex:3 block:^(HoloTableViewSectionMaker * _Nonnull make) {
59 | make.section(@"3").headerHeight(3);
60 | make.section(@"4").headerHeight(4);
61 | }];
62 |
63 | // section(@"0")
64 | // section(@"1")
65 | // section(TAG)
66 | // section(@"2")
67 | // section(@"3")
68 |
69 | XCTAssertEqual(self.tableView.holo_sections.count, 5);
70 |
71 | HoloTableSection *section3 = self.tableView.holo_sections[3];
72 | HoloTableSection *section4 = self.tableView.holo_sections[4];
73 |
74 | XCTAssertEqual(section3.tag, @"3");
75 | XCTAssertEqual(section3.headerHeight, 3);
76 |
77 | XCTAssertEqual(section4.tag, @"4");
78 | XCTAssertEqual(section4.headerHeight, 4);
79 | }
80 |
81 | - (void)testPerformanceExample {
82 | // This is an example of a performance test case.
83 | [self measureBlock:^{
84 | // Put the code you want to measure the time of here.
85 | }];
86 | }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableSectionMakerTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSectionMakerTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/20.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableSectionMakerTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableSectionMakerTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 | self.tableView = [UITableView new];
23 |
24 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
25 | make.section(TAG)
26 | .header(UITableViewHeaderFooterView.class)
27 | .footer(UITableViewHeaderFooterView.class)
28 |
29 | .headerReuseId(@"headerReuseId")
30 | .headerReuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
31 | return @"headerReuseIdHandler";
32 | })
33 | .footerReuseId(@"footerReuseId")
34 | .footerReuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
35 | return @"footerReuseIdHandler";
36 | })
37 |
38 | .headerTitle(@"headerTitle")
39 | .headerTitleHandler(^NSString * _Nonnull{
40 | return @"headerTitleHandler";
41 | })
42 | .footerTitle(@"footerTitle")
43 | .footerTitleHandler(^NSString * _Nonnull{
44 | return @"footerTitleHandler";
45 | })
46 |
47 | .headerModel(@"headerModel")
48 | .headerModelHandler(^id _Nonnull{
49 | return @"headerModelHandler";
50 | })
51 | .footerModel(@"footerModel")
52 | .footerModelHandler(^id _Nonnull{
53 | return @"footerModelHandler";
54 | })
55 |
56 | .headerHeight(10)
57 | .headerHeightHandler(^CGFloat(id _Nullable model) {
58 | return 11;
59 | })
60 | .footerHeight(20)
61 | .footerHeightHandler(^CGFloat(id _Nullable model) {
62 | return 21;
63 | })
64 |
65 | .headerEstimatedHeight(100)
66 | .headerEstimatedHeightHandler(^CGFloat(id _Nullable model) {
67 | return 101;
68 | })
69 | .footerEstimatedHeight(200)
70 | .footerEstimatedHeightHandler(^CGFloat(id _Nullable model) {
71 | return 201;
72 | });
73 | }];
74 |
75 |
76 | // makeSections with rows
77 |
78 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
79 | make.section(@"section-1").makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
80 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
81 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
82 | });
83 | }];
84 | }
85 |
86 | - (void)tearDown {
87 | // Put teardown code here. This method is called after the invocation of each test method in the class.
88 | }
89 |
90 |
91 | #pragma mark - makeSections
92 |
93 | - (void)testMakeSections {
94 | // This is an example of a functional test case.
95 | // Use XCTAssert and related functions to verify your tests produce the correct results.
96 |
97 | XCTAssertEqual(self.tableView.holo_sections.count, 2);
98 |
99 | HoloTableSection *section = self.tableView.holo_sections[0];
100 |
101 | XCTAssertEqual(section.tag, TAG);
102 |
103 | XCTAssertEqual(section.header, UITableViewHeaderFooterView.class);
104 | XCTAssertEqual(section.footer, UITableViewHeaderFooterView.class);
105 |
106 | XCTAssertEqual(section.headerReuseId, @"headerReuseId");
107 | XCTAssertEqual(section.footerReuseId, @"footerReuseId");
108 |
109 | XCTAssertEqual(section.headerTitle, @"headerTitle");
110 | XCTAssertEqual(section.footerTitle, @"footerTitle");
111 |
112 | XCTAssertEqual(section.headerModel, @"headerModel");
113 | XCTAssertEqual(section.footerModel, @"footerModel");
114 |
115 | XCTAssertEqual(section.headerHeight, 10);
116 | XCTAssertEqual(section.footerHeight, 20);
117 |
118 | XCTAssertEqual(section.headerEstimatedHeight, 100);
119 | XCTAssertEqual(section.footerEstimatedHeight, 200);
120 | }
121 |
122 |
123 | #pragma mark - makeSections with rows
124 |
125 | - (void)testMakeSectionsMakeRows {
126 | // This is an example of a functional test case.
127 | // Use XCTAssert and related functions to verify your tests produce the correct results.
128 |
129 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
130 | make.section(@"section-1").makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
131 | make.row(UITableViewCell.class).model(@"0").height(0);
132 | make.row(UITableViewCell.class).model(@"1").height(1);
133 | });
134 | }];
135 |
136 | // section(TAG)
137 | // section(@"section-1")
138 | // section(@"section-1")
139 |
140 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
141 |
142 | HoloTableSection *section = self.tableView.holo_sections[2];
143 |
144 | XCTAssertEqual(section.rows.count, 2);
145 |
146 | HoloTableRow *row0 = section.rows[0];
147 | HoloTableRow *row1 = section.rows[1];
148 |
149 | XCTAssertEqual(row0.cell, UITableViewCell.class);
150 | XCTAssertEqual(row0.model, @"0");
151 | XCTAssertEqual(row0.height, 0);
152 |
153 | XCTAssertEqual(row1.cell, UITableViewCell.class);
154 | XCTAssertEqual(row1.model, @"1");
155 | XCTAssertEqual(row1.height, 1);
156 | }
157 |
158 | - (void)testMakeSectionsUpdateRows {
159 | // This is an example of a functional test case.
160 | // Use XCTAssert and related functions to verify your tests produce the correct results.
161 |
162 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
163 | make.section(@"section-1").updateRows(^(HoloTableViewUpdateRowMaker * _Nonnull make) {
164 | make.tag(@"0").height(0);
165 | make.tag(@"1").height(1);
166 | });
167 | }];
168 |
169 | // section(TAG)
170 | // section(@"section-1")
171 | // section(@"section-1")
172 |
173 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
174 |
175 | HoloTableSection *section = self.tableView.holo_sections[2];
176 |
177 | XCTAssertEqual(section.rows.count, 0);
178 | }
179 |
180 | - (void)testMakeSectionsRemakeRows {
181 | // This is an example of a functional test case.
182 | // Use XCTAssert and related functions to verify your tests produce the correct results.
183 |
184 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
185 | make.section(@"section-1").remakeRows(^(HoloTableViewUpdateRowMaker * _Nonnull make) {
186 | make.tag(@"0").height(0);
187 | make.tag(@"1").height(1);
188 | });
189 | }];
190 |
191 | // section(TAG)
192 | // section(@"section-1")
193 | // section(@"section-1")
194 |
195 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
196 |
197 | HoloTableSection *section = self.tableView.holo_sections[2];
198 |
199 | XCTAssertEqual(section.rows.count, 0);
200 | }
201 |
202 | - (void)testPerformanceExample {
203 | // This is an example of a performance test case.
204 | [self measureBlock:^{
205 | // Put the code you want to measure the time of here.
206 | }];
207 | }
208 |
209 | @end
210 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableSectionRemakerTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSectionRemakerTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableSectionRemakerTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableSectionRemakerTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 | self.tableView = [UITableView new];
23 |
24 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
25 | make.section(TAG)
26 | .header(UITableViewHeaderFooterView.class)
27 | .footer(UITableViewHeaderFooterView.class)
28 |
29 | .headerReuseId(@"headerReuseId")
30 | .headerReuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
31 | return @"headerReuseIdHandler";
32 | })
33 | .footerReuseId(@"footerReuseId")
34 | .footerReuseIdHandler(^NSString * _Nonnull(id _Nullable model) {
35 | return @"footerReuseIdHandler";
36 | })
37 |
38 | .headerTitle(@"headerTitle")
39 | .headerTitleHandler(^NSString * _Nonnull{
40 | return @"headerTitleHandler";
41 | })
42 | .footerTitle(@"footerTitle")
43 | .footerTitleHandler(^NSString * _Nonnull{
44 | return @"footerTitleHandler";
45 | })
46 |
47 | .headerModel(@"headerModel")
48 | .headerModelHandler(^id _Nonnull{
49 | return @"headerModelHandler";
50 | })
51 | .footerModel(@"footerModel")
52 | .footerModelHandler(^id _Nonnull{
53 | return @"footerModelHandler";
54 | })
55 |
56 | .headerHeight(10)
57 | .headerHeightHandler(^CGFloat(id _Nullable model) {
58 | return 11;
59 | })
60 | .footerHeight(20)
61 | .footerHeightHandler(^CGFloat(id _Nullable model) {
62 | return 21;
63 | })
64 |
65 | .headerEstimatedHeight(100)
66 | .headerEstimatedHeightHandler(^CGFloat(id _Nullable model) {
67 | return 101;
68 | })
69 | .footerEstimatedHeight(200)
70 | .footerEstimatedHeightHandler(^CGFloat(id _Nullable model) {
71 | return 201;
72 | });
73 | }];
74 |
75 |
76 | // remakeSections with rows
77 |
78 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
79 | make.section(@"section-1").makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
80 | make.row(UITableViewCell.class).tag(@"0").model(@"0").height(0);
81 | make.row(UITableViewCell.class).tag(@"1").model(@"1").height(1);
82 | });
83 | }];
84 | }
85 |
86 | - (void)tearDown {
87 | // Put teardown code here. This method is called after the invocation of each test method in the class.
88 | }
89 |
90 | #pragma mark - remakeSections
91 |
92 | - (void)testRemakeSections {
93 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
94 | make.section(TAG);
95 | }];
96 | HoloTableSection *section = self.tableView.holo_sections.firstObject;
97 |
98 | XCTAssertEqual(section.header, UITableViewHeaderFooterView.class);
99 | XCTAssertEqual(section.footer, UITableViewHeaderFooterView.class);
100 |
101 | XCTAssertNil(section.headerReuseId);
102 | XCTAssertNil(section.footerReuseId);
103 |
104 | XCTAssertNil(section.headerTitle);
105 | XCTAssertNil(section.footerTitle);
106 |
107 | XCTAssertNil(section.headerModel);
108 | XCTAssertNil(section.footerModel);
109 |
110 | XCTAssertEqual(section.headerHeight, CGFLOAT_MIN);
111 | XCTAssertEqual(section.footerHeight, CGFLOAT_MIN);
112 |
113 | XCTAssertEqual(section.headerEstimatedHeight, CGFLOAT_MIN);
114 | XCTAssertEqual(section.footerEstimatedHeight, CGFLOAT_MIN);
115 |
116 |
117 | // multiple sections with the same tag
118 |
119 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
120 | make.section(@"section-1").headerHeight(1);
121 | }];
122 |
123 | // section(TAG)
124 | // section(@"section-1")
125 | // section(@"section-1")
126 |
127 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
128 |
129 | HoloTableSection *section1 = self.tableView.holo_sections[1];
130 | HoloTableSection *section2 = self.tableView.holo_sections[2];
131 |
132 | XCTAssertEqual(section1.headerHeight, CGFLOAT_MIN);
133 | XCTAssertEqual(section2.headerHeight, 1);
134 |
135 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
136 | make.section(@"section-1");
137 | make.section(@"section-1");
138 | }];
139 |
140 | HoloTableSection *sectionNew1 = self.tableView.holo_sections[1];
141 | HoloTableSection *sectionNew2 = self.tableView.holo_sections[2];
142 | XCTAssertEqual(sectionNew1.headerHeight, CGFLOAT_MIN); // changed
143 | XCTAssertEqual(sectionNew2.headerHeight, 1); // not changed
144 | }
145 |
146 |
147 | #pragma mark - remakeSections with rows
148 |
149 | - (void)testRemakeSectionsMakeRows {
150 | // This is an example of a functional test case.
151 | // Use XCTAssert and related functions to verify your tests produce the correct results.
152 |
153 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
154 | make.section(@"section-1").makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
155 | make.row(UITableViewCell.class).model(@"0").height(0);
156 | make.row(UITableViewCell.class).model(@"1").height(1);
157 | });
158 | }];
159 |
160 | // section(TAG)
161 | // section(@"section-1")
162 | // section(@"section-1")
163 |
164 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
165 |
166 | // not found a section with the tag
167 |
168 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
169 | make.section(@"section-2").makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
170 | make.row(UITableViewCell.class).model(@"0").height(0);
171 | make.row(UITableViewCell.class).model(@"1").height(1);
172 | make.row(UITableViewCell.class).model(@"2").height(2);
173 | });
174 | }];
175 |
176 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
177 |
178 | HoloTableSection *section1 = self.tableView.holo_sections[1];
179 | HoloTableSection *section2 = self.tableView.holo_sections[2];
180 |
181 | XCTAssertEqual(section1.rows.count, 2);
182 | XCTAssertEqual(section2.rows.count, 2);
183 |
184 |
185 | // found a section with the tag
186 |
187 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
188 | make.section(@"section-1").makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
189 | make.row(UITableViewCell.class).model(@"0").height(0);
190 | make.row(UITableViewCell.class).model(@"1").height(1);
191 | make.row(UITableViewCell.class).model(@"2").height(2);
192 | });
193 | }];
194 |
195 | XCTAssertEqual(self.tableView.holo_sections.count, 3);
196 |
197 | HoloTableSection *section1_new = self.tableView.holo_sections[1];
198 | HoloTableSection *section2_old = self.tableView.holo_sections[2];
199 |
200 | XCTAssertEqual(section1_new.rows.count, 3);
201 | XCTAssertEqual(section2_old.rows.count, 2);
202 |
203 | HoloTableRow *row0 = section1_new.rows[0];
204 | HoloTableRow *row1 = section1_new.rows[1];
205 |
206 | XCTAssertEqual(row0.cell, UITableViewCell.class);
207 | XCTAssertEqual(row0.model, @"0");
208 | XCTAssertEqual(row0.height, 0);
209 |
210 | XCTAssertEqual(row1.cell, UITableViewCell.class);
211 | XCTAssertEqual(row1.model, @"1");
212 | XCTAssertEqual(row1.height, 1);
213 | }
214 |
215 | - (void)testRemakeSectionsUpdateRows {
216 | // This is an example of a functional test case.
217 | // Use XCTAssert and related functions to verify your tests produce the correct results.
218 |
219 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
220 | make.section(@"section-1").updateRows(^(HoloTableViewUpdateRowMaker * _Nonnull make) {
221 | make.tag(@"1").height(1000);
222 | make.tag(@"2").height(2000);
223 | });
224 | }];
225 |
226 | // section(TAG)
227 | // section(@"section-1")
228 |
229 | XCTAssertEqual(self.tableView.holo_sections.count, 2);
230 |
231 | HoloTableSection *section1 = self.tableView.holo_sections[1];
232 |
233 | XCTAssertEqual(section1.rows.count, 0);
234 | }
235 |
236 | - (void)testRemakeSectionsRemakeRows {
237 | // This is an example of a functional test case.
238 | // Use XCTAssert and related functions to verify your tests produce the correct results.
239 |
240 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
241 | make.section(@"section-1").remakeRows(^(HoloTableViewUpdateRowMaker * _Nonnull make) {
242 | make.tag(@"1").height(1000);
243 | make.tag(@"2").height(2000);
244 | });
245 | }];
246 |
247 | // section(TAG)
248 | // section(@"section-1")
249 |
250 | XCTAssertEqual(self.tableView.holo_sections.count, 2);
251 |
252 | HoloTableSection *section1 = self.tableView.holo_sections[1];
253 |
254 | XCTAssertEqual(section1.rows.count, 0);
255 | }
256 |
257 | - (void)testPerformanceExample {
258 | // This is an example of a performance test case.
259 | [self measureBlock:^{
260 | // Put the code you want to measure the time of here.
261 | }];
262 | }
263 |
264 | @end
265 |
--------------------------------------------------------------------------------
/Example/Tests/HoloTableSectionRemoverTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSectionRemoverTest.m
3 | // HoloTableView_Tests
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | // Copyright © 2021 gonghonglou. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HoloTableSectionRemoverTest : XCTestCase
13 |
14 | @property (nonatomic, strong) UITableView *tableView;
15 |
16 | @end
17 |
18 | @implementation HoloTableSectionRemoverTest
19 |
20 | - (void)setUp {
21 | // Put setup code here. This method is called before the invocation of each test method in the class.
22 | self.tableView = [UITableView new];
23 |
24 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
25 | make.section(TAG);
26 | }];
27 | }
28 |
29 | - (void)tearDown {
30 | // Put teardown code here. This method is called after the invocation of each test method in the class.
31 | }
32 |
33 | - (void)testRemoveSections {
34 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
35 | make.section(@"1");
36 | make.section(@"2");
37 | make.section(@"2");
38 | make.section(@"3");
39 | }];
40 |
41 | XCTAssertEqual(self.tableView.holo_sections.count, 5);
42 |
43 | [self.tableView holo_removeSections:@[@"1", @"2"]];
44 |
45 | XCTAssertEqual(self.tableView.holo_sections.count, 2);
46 |
47 | HoloTableSection *lastSection = self.tableView.holo_sections[1];
48 | XCTAssertEqual(lastSection.tag, @"3");
49 |
50 | [self.tableView holo_removeAllSections];
51 | XCTAssertEqual(self.tableView.holo_sections.count, 0);
52 | }
53 |
54 | - (void)testPerformanceExample {
55 | // This is an example of a performance test case.
56 | [self measureBlock:^{
57 | // Put the code you want to measure the time of here.
58 | }];
59 | }
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Prefix.pch:
--------------------------------------------------------------------------------
1 | // The contents of this file are implicitly included at the beginning of every test case source file.
2 |
3 | #ifdef __OBJC__
4 |
5 |
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Example/Tests/Tests.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewTests.m
3 | // HoloTableViewTests
4 | //
5 | // Created by gonghonglou on 07/28/2019.
6 | // Copyright (c) 2019 gonghonglou. All rights reserved.
7 | //
8 |
9 | @import XCTest;
10 |
11 | @interface Tests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation Tests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
36 |
--------------------------------------------------------------------------------
/Example/Tests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/HoloTableView.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint HoloTableView.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 https://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = 'HoloTableView'
11 | s.version = '3.1.2'
12 | s.summary = 'Harness the power of UITableView with a simplified, chainable and expressive syntax.'
13 |
14 | # This description is used to generate tags and improve search results.
15 | # * Think: What does it do? Why did you write it? What is the focus?
16 | # * Try to keep it short, snappy and to the point.
17 | # * Write the description between the DESC delimiters below.
18 | # * Finally, don't worry about the indent, CocoaPods strips it!
19 |
20 | s.description = 'HoloTableView is a light-weight extension for UITableView. Harness the power of UITableView with a simplified, chainable and expressive syntax.'
21 |
22 | s.homepage = 'https://github.com/HoloFoundation/HoloTableView'
23 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
24 | s.license = { :type => 'MIT', :file => 'LICENSE' }
25 | s.author = { 'gonghonglou' => 'gonghonglou@icloud.com' }
26 | s.source = { :git => 'https://github.com/HoloFoundation/HoloTableView.git', :tag => s.version.to_s }
27 | # s.social_media_url = 'https://twitter.com/'
28 |
29 | s.ios.deployment_target = '8.0'
30 |
31 | s.source_files = 'HoloTableView/Classes/**/*'
32 |
33 | # s.resource_bundles = {
34 | # 'HoloTableView' => ['HoloTableView/Assets/*.png']
35 | # }
36 |
37 | # s.public_header_files = 'Pod/Classes/**/*.h'
38 | # s.frameworks = 'UIKit', 'MapKit'
39 | # s.dependency 'AFNetworking', '~> 2.3'
40 | end
41 |
--------------------------------------------------------------------------------
/HoloTableView/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HoloFoundation/HoloTableView/35eb14a22954264f0243bfac3abd934b06db5c18/HoloTableView/Assets/.gitkeep
--------------------------------------------------------------------------------
/HoloTableView/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HoloFoundation/HoloTableView/35eb14a22954264f0243bfac3abd934b06db5c18/HoloTableView/Classes/.gitkeep
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/HoloTableViewProxy.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewProxy.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/27.
6 | //
7 |
8 | #import
9 | #import "HoloTableViewProtocol.h"
10 | @class HoloTableViewProxyData;
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface HoloTableViewProxy : NSObject
15 |
16 | /**
17 | * Proxy data.
18 | */
19 | @property (nonatomic, strong) HoloTableViewProxyData *proxyData;
20 |
21 | /**
22 | * The delegate of the scroll-view object.
23 | */
24 | @property (nonatomic, weak, nullable) id scrollDelegate;
25 |
26 | @property (nonatomic, weak, nullable) id dataSource;
27 |
28 | @property (nonatomic, weak, nullable) id delegate;
29 |
30 | @end
31 |
32 | NS_ASSUME_NONNULL_END
33 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/HoloTableViewProxyData.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewProxyData.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/29.
6 | //
7 |
8 | #import
9 | @class HoloTableSection;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloTableViewProxyData : NSObject
14 |
15 | /**
16 | * Datasource of current UITableView.
17 | */
18 | @property (nonatomic, copy) NSArray *sections;
19 |
20 | /**
21 | * Return list of section titles to display in section index view (e.g. "ABCD...Z#").
22 | */
23 | @property (nonatomic, copy, nullable) NSArray *sectionIndexTitles;
24 |
25 | /**
26 | * Tell table which section corresponds to section title/index (e.g. "B",1)).
27 | */
28 | @property (nonatomic, copy, nullable) NSInteger (^sectionForSectionIndexTitleHandler)(NSString *title, NSInteger index);
29 |
30 |
31 | //@property (nonatomic, copy) NSDictionary *rowsMap;
32 | //
33 | //@property (nonatomic, copy) NSDictionary *headersMap;
34 | //
35 | //@property (nonatomic, copy) NSDictionary *footersMap;
36 |
37 | @end
38 |
39 | NS_ASSUME_NONNULL_END
40 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/HoloTableViewProxyData.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewProxyData.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/29.
6 | //
7 |
8 | #import "HoloTableViewProxyData.h"
9 |
10 | @implementation HoloTableViewProxyData
11 |
12 | #pragma mark - getter
13 | - (NSArray *)sections {
14 | if (!_sections) {
15 | _sections = [NSArray new];
16 | }
17 | return _sections;
18 | }
19 |
20 | //- (NSDictionary *)rowsMap {
21 | // if (!_rowsMap) {
22 | // _rowsMap = [NSDictionary new];
23 | // }
24 | // return _rowsMap;
25 | //}
26 | //
27 | //- (NSDictionary *)headersMap {
28 | // if (!_headersMap) {
29 | // _headersMap = [NSDictionary new];
30 | // }
31 | // return _headersMap;
32 | //}
33 | //
34 | //- (NSDictionary *)footersMap {
35 | // if (!_footersMap) {
36 | // _footersMap = [NSDictionary new];
37 | // }
38 | // return _footersMap;
39 | //}
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Protocol/HoloTableViewCellProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewCellProtocol.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @protocol HoloTableViewCellProtocol
13 |
14 | @required
15 |
16 | /**
17 | * Your cell must implement this method in order for the HoloTableView to pass the externally-set model.
18 | */
19 | - (void)holo_configureCellWithModel:(id _Nullable)model;
20 |
21 |
22 | @optional
23 |
24 | /**
25 | * If your cell implements this method, the HolotableView will set the height of the current cell from the return value of this method.
26 | *
27 | * Note that if your cell implements this method, the `heightHandler` and `height` properties set externally will be invalidated.
28 | */
29 | + (CGFloat)holo_heightForCellWithModel:(id _Nullable)model;
30 |
31 | /**
32 | * If your cell implements this method, the HolotableView will set the estimated height of the current cell from the return value of this method.
33 | *
34 | * Note that if your cell implements this method, the `estimatedHeightHandler` and `estimatedHeight` properties set externally will be invalidated.
35 | */
36 | + (CGFloat)holo_estimatedHeightForCellWithModel:(id _Nullable)model;
37 |
38 | /**
39 | * If your cell implements this method, the HolotableView will set the should highlight or not of the current cell from the return value of this method.
40 | *
41 | * Note that if your cell implements this method, the `shouldHighlightHandler` and `shouldHighlight` properties set externally will be invalidated.
42 | */
43 | - (BOOL)holo_shouldHighlightForCellWithModel:(id _Nullable)model;
44 |
45 | /**
46 | * If your cell implements this method, this method will be called when the cell will select.
47 | *
48 | * Note that if your cell implements this method, the `willSelectHandler` property set externally will be invalidated.
49 | */
50 | - (void)holo_willSelectCellWithModel:(id _Nullable)model;
51 |
52 | /**
53 | * If your cell implements this method, this method will be called when the cell will deselect.
54 | *
55 | * Note that if your cell implements this method, the `willDeselectHandler` property set externally will be invalidated.
56 | */
57 | - (void)holo_willDeselectCellWithModel:(id _Nullable)model;
58 |
59 | /**
60 | * If your cell implements this method, this method will be called when the cell did deselect.
61 | *
62 | * Note that if your cell implements this method, the `didDeselectHandler` property set externally will be invalidated.
63 | */
64 | - (void)holo_didDeselectCellWithModel:(id _Nullable)model;
65 |
66 | /**
67 | * If your cell implements this method, this method will be called when the cell did select.
68 | *
69 | * Note that if your cell implements this method, the `didSelectHandler` property set externally will be invalidated.
70 | */
71 | - (void)holo_didSelectCellWithModel:(id _Nullable)model;
72 |
73 | /**
74 | * If your cell implements this method, this method will be called when the cell will display.
75 | *
76 | * Note that if your cell implements this method, the `willDisplayHandler` property set externally will be invalidated.
77 | */
78 | - (void)holo_willDisplayCellWithModel:(id _Nullable)model;
79 |
80 | /**
81 | * If your cell implements this method, this method will be called when the cell did end displaying.
82 | *
83 | * Note that if your cell implements this method, the `didEndDisplayingHandler` property set externally will be invalidated.
84 | */
85 | - (void)holo_didEndDisplayingCellWithModel:(id _Nullable)model;
86 |
87 | /**
88 | * If your cell implements this method, this method will be called when the cell did highlight.
89 | *
90 | * Note that if your cell implements this method, the `didHighlightHandler` property set externally will be invalidated.
91 | */
92 | - (void)holo_didHighlightCellWithModel:(id _Nullable)model;
93 |
94 | /**
95 | * If your cell implements this method, this method will be called when the cell did un highlight.
96 | *
97 | * Note that if your cell implements this method, the `didUnHighlightHandler` property set externally will be invalidated.
98 | */
99 | - (void)holo_didUnHighlightCellWithModel:(id _Nullable)model;
100 |
101 | /**
102 | * If your cell implements this method, this method will be called when the cell accessory button tapped.
103 | *
104 | * Note that if your cell implements this method, the `accessoryButtonTappedHandler` property set externally will be invalidated.
105 | */
106 | - (void)holo_accessoryButtonTappedCellWithModel:(id _Nullable)model;
107 |
108 | /**
109 | * If your cell implements this method, this method will be called when the cell will begin editing.
110 | *
111 | * Note that if your cell implements this method, the `willBeginEditingHandler` property set externally will be invalidated.
112 | */
113 | - (void)holo_willBeginEditingCellWithModel:(id _Nullable)model;
114 |
115 | /**
116 | * If your cell implements this method, this method will be called when the cell did end editing.
117 | *
118 | * Note that if your cell implements this method, the `didEndEditingHandler` property set externally will be invalidated.
119 | */
120 | - (void)holo_didEndEditingCellWithModel:(id _Nullable)model;
121 |
122 | @end
123 |
124 | NS_ASSUME_NONNULL_END
125 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Protocol/HoloTableViewFooterProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewFooterProtocol.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @protocol HoloTableViewFooterProtocol
13 |
14 | @required
15 |
16 | /**
17 | * Your section footer must implement this method in order for the HoloTableView to pass the externally-set model to the current section footer.
18 | */
19 | - (void)holo_configureFooterWithModel:(id _Nullable)model;
20 |
21 |
22 | @optional
23 |
24 | /**
25 | * If your section footer implements this method, the HolotableView will set the height of the current section footer from the return value of this method.
26 | *
27 | * Note that if your section footer implements this method, the `footerHeightHandler` and `footerHeight` properties set externally will be invalidated.
28 | */
29 | + (CGFloat)holo_heightForFooterWithModel:(id _Nullable)model;
30 |
31 | /**
32 | * If your section footer implements this method, the HolotableView will set the estimated height of the current section footer from the return value of this method.
33 | *
34 | * Note that if your section footer implements this method, the `estimatedFooterHeightHandler` and `estimatedFooterHeight` properties set externally will be invalidated.
35 | */
36 | + (CGFloat)holo_estimatedHeightForFooterWithModel:(id _Nullable)model;
37 |
38 | /**
39 | * If your section footer implements this method, this method will be called when the section footer will display.
40 | *
41 | * Note that if your section footer implements this method, the `willDisplayHandler` property set externally will be invalidated.
42 | */
43 | - (void)holo_willDisplayFooterWithModel:(id _Nullable)model;
44 |
45 | /**
46 | * If your section footer implements this method, this method will be called when the section footer did end displaying.
47 | *
48 | * Note that if your section footer implements this method, the `didEndDisplayingHandler` property set externally will be invalidated.
49 | */
50 | - (void)holo_didEndDisplayingFooterWithModel:(id _Nullable)model;
51 |
52 | @end
53 |
54 | NS_ASSUME_NONNULL_END
55 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Protocol/HoloTableViewHeaderProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewHeaderProtocol.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @protocol HoloTableViewHeaderProtocol
13 |
14 | @required
15 |
16 | /**
17 | * Your section header must implement this method in order for the HoloTableView to pass the externally-set model to the current section header.
18 | */
19 | - (void)holo_configureHeaderWithModel:(id _Nullable)model;
20 |
21 |
22 | @optional
23 |
24 | /**
25 | * If your section header implements this method, the HolotableView will set the height of the current section header from the return value of this method.
26 | *
27 | * Note that if your section header implements this method, the `headerHeightHandler` and `headerHeight` properties set externally will be invalidated.
28 | */
29 | + (CGFloat)holo_heightForHeaderWithModel:(id _Nullable)model;
30 |
31 | /**
32 | * If your section header implements this method, the HolotableView will set the estimated height of the current section header from the return value of this method.
33 | *
34 | * Note that if your section header implements this method, the `estimatedHeaderHeightHandler` and `estimatedHeaderHeight` properties set externally will be invalidated.
35 | */
36 | + (CGFloat)holo_estimatedHeightForHeaderWithModel:(id _Nullable)model;
37 |
38 | /**
39 | * If your section header implements this method, this method will be called when the section header will display.
40 | *
41 | * Note that if your section header implements this method, the `willDisplayHandler` property set externally will be invalidated.
42 | */
43 | - (void)holo_willDisplayHeaderWithModel:(id _Nullable)model;
44 |
45 | /**
46 | * If your section header implements this method, this method will be called when the section header did end displaying.
47 | *
48 | * Note that if your section header implements this method, the `didEndDisplayingHandler` property set externally will be invalidated.
49 | */
50 | - (void)holo_didEndDisplayingHeaderWithModel:(id _Nullable)model;
51 |
52 | @end
53 |
54 | NS_ASSUME_NONNULL_END
55 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Protocol/HoloTableViewProtocol.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewProtocol.h
3 | // Pods
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | //
7 |
8 | #ifndef HoloTableViewProtocol_h
9 | #define HoloTableViewProtocol_h
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @protocol HoloTableViewDelegate
14 |
15 | @end
16 |
17 |
18 | @protocol HoloTableViewDataSource
19 |
20 | @optional
21 |
22 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
23 |
24 | // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
25 | // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
26 |
27 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
28 |
29 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented
30 |
31 | - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different
32 | - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
33 |
34 | // Editing
35 |
36 | // Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable.
37 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
38 |
39 | // Moving/reordering
40 |
41 | // Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
42 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
43 |
44 | // Index
45 |
46 | - (nullable NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; // return list of section titles to display in section index view (e.g. "ABCD...Z#")
47 | - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))
48 |
49 | // Data manipulation - insert and delete support
50 |
51 | // After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
52 | // Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead
53 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
54 |
55 | // Data manipulation - reorder / moving support
56 |
57 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
58 |
59 | @end
60 |
61 | NS_ASSUME_NONNULL_END
62 |
63 | #endif /* HoloTableViewProtocol_h */
64 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Row/HoloTableRow.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRow.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/1.
6 | //
7 |
8 | #import
9 | @class HoloTableViewRowSwipeAction;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloTableRow : NSObject
14 |
15 | /**
16 | * Cell class.
17 | */
18 | @property (nonatomic, assign) Class cell;
19 |
20 | /**
21 | * Set the data for the cell using the `model` property.
22 | *
23 | * If the `modelHandler` property is nil, then use the `model` property.
24 | */
25 | @property (nonatomic, strong, nullable) id model;
26 | @property (nonatomic, copy, nullable) id (^modelHandler)(void);
27 |
28 | /**
29 | * The cell must implement the `configSEL` property setting method in order for the HoloTableView to pass the model for the cell.
30 | */
31 | @property (nonatomic, assign) SEL configSEL;
32 |
33 | /**
34 | * Performed before `configSEL`.
35 | */
36 | @property (nonatomic, copy, nullable) void (^beforeConfigureHandler)(UITableViewCell *cell, id _Nullable model);
37 |
38 | /**
39 | * Performed after `configSEL`.
40 | */
41 | @property (nonatomic, copy, nullable) void (^afterConfigureHandler)(UITableViewCell *cell, id _Nullable model);
42 |
43 |
44 | /**
45 | * Set the style for the cell using the `style` property.
46 | *
47 | * If the `styleHandler` property is nil, then use the `style` property.
48 | */
49 | @property (nonatomic, assign) UITableViewCellStyle style;
50 | @property (nonatomic, copy, nullable) UITableViewCellStyle (^styleHandler)(id _Nullable model);
51 |
52 | /**
53 | * Set the reuse identifier for the cell using the `reuseId` property.
54 | *
55 | * If the `reuseIdHandler` property is nil, then use the `reuseId` property.
56 | */
57 | @property (nonatomic, copy, nullable) NSString *reuseId;
58 | @property (nonatomic, copy, nullable) NSString *(^reuseIdHandler)(id _Nullable model);
59 |
60 | /**
61 | * Set the tag for the cell using the `tag` property.
62 | */
63 | @property (nonatomic, copy, nullable) NSString *tag;
64 |
65 | /**
66 | * Set the height for the cell using the `height` property.
67 | *
68 | * If the `heightSEL` property is nil or the cell don't implement the `heightSEL` property setting method, then use the `heightHandler` property.
69 | * If the `heightHandler` property is nil, then use the `height` property.
70 | */
71 | @property (nonatomic, assign) CGFloat height;
72 | @property (nonatomic, copy, nullable) CGFloat (^heightHandler)(id _Nullable model);
73 | @property (nonatomic, assign) SEL heightSEL;
74 |
75 | /**
76 | * Set the estimated height for the cell using the `estimatedHeight` property.
77 | *
78 | * If the `estimatedHeightSEL` property is nil or the cell don't implement the `estimatedHeightSEL` property setting method, then use the `estimatedHeightHandler` property.
79 | * If the `estimatedHeightHandler` property is nil, then use the `estimatedHeight` property.
80 | */
81 | @property (nonatomic, assign) CGFloat estimatedHeight;
82 | @property (nonatomic, copy, nullable) CGFloat (^estimatedHeightHandler)(id _Nullable model);
83 | @property (nonatomic, assign) SEL estimatedHeightSEL;
84 |
85 | /**
86 | * Set the should highlight or not for the cell using the `shouldHighlight` property.
87 | *
88 | * If the `shouldHighlightSEL` property is nil or the cell don't implement the `shouldHighlightSEL` property setting method, then use the `shouldHighlightHandler` property.
89 | * If the `shouldHighlightHandler` property is nil, then use the `shouldHighlight` property.
90 | */
91 | @property (nonatomic, assign) BOOL shouldHighlight;
92 | @property (nonatomic, copy, nullable) BOOL (^shouldHighlightHandler)(id _Nullable model);
93 | @property (nonatomic, assign) SEL shouldHighlightSEL;
94 |
95 | /**
96 | * Set the can edit or not for the cell using the `canEdit` property.
97 | *
98 | * If the `canEditHandler` property is nil, then use the `canEdit` property.
99 | */
100 | @property (nonatomic, assign) BOOL canEdit;
101 | @property (nonatomic, copy, nullable) BOOL (^canEditHandler)(id _Nullable model);
102 | //@property (nonatomic, assign) SEL canEditSEL;
103 |
104 | /**
105 | * Set the can move or not for the cell using the `canMove` property.
106 | *
107 | * If the `canMoveHandler` property is nil, then use the `canEdit` property.
108 | */
109 | @property (nonatomic, assign) BOOL canMove;
110 | @property (nonatomic, copy, nullable) BOOL (^canMoveHandler)(id _Nullable model);
111 | //@property (nonatomic, assign) SEL canMoveSEL;
112 |
113 | /**
114 | * Set the leading swipe actions for the cell using the `leadingSwipeActions` property.
115 | *
116 | * If the `leadingSwipeActionsHandler` property is nil, then use the `leadingSwipeActions` property.
117 | */
118 | @property (nonatomic, copy, nullable) NSArray *leadingSwipeActions API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
119 | @property (nonatomic, copy, nullable) NSArray *(^leadingSwipeActionsHandler)(id _Nullable model) API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
120 | //@property (nonatomic, assign) SEL leadingSwipeActionsSEL;
121 |
122 | /**
123 | * Set the leading swipe for the cell using the `leadingSwipeHandler` property.
124 | */
125 | @property (nonatomic, copy, nullable) void (^leadingSwipeHandler)(id action, NSInteger index, void(^completionHandler)(BOOL actionPerformed)) API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
126 | //@property (nonatomic, assign) SEL leadingSwipeSEL API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
127 |
128 | /**
129 | * Set the trailing swipe actions for the cell using the `trailingSwipeActions` property.
130 | *
131 | * If the `trailingSwipeActionsHandler` property is nil, then use the `trailingSwipeActions` property.
132 | */
133 | @property (nonatomic, copy, nullable) NSArray *trailingSwipeActions;
134 | @property (nonatomic, copy, nullable) NSArray *(^trailingSwipeActionsHandler)(id _Nullable model);
135 | //@property (nonatomic, assign) SEL trailingSwipeActionsSEL;
136 |
137 | /**
138 | * Set the trailing swipe for the cell using the `trailingSwipeHandler` property.
139 | */
140 | @property (nonatomic, copy, nullable) void (^trailingSwipeHandler)(id action, NSInteger index, void(^completionHandler)(BOOL actionPerformed));
141 | //@property (nonatomic, assign) SEL trailingSwipeSEL;
142 |
143 | /**
144 | * Set the editing delete title for the cell using the `editingDeleteTitle` property.
145 | *
146 | * If the `editingDeleteTitleHandler` property is nil, then use the `editingDeleteTitle` property.
147 | */
148 | @property (nonatomic, copy, nullable) NSString *editingDeleteTitle;
149 | @property (nonatomic, copy, nullable) NSString *(^editingDeleteTitleHandler)(id _Nullable model);
150 | //@property (nonatomic, assign) SEL editingDeleteTitleSEL;
151 |
152 | /**
153 | * Set the editing style for the cell using the `editingStyle` property.
154 | *
155 | * If the `editingStyleHandler` property is nil, then use the `editingStyle` property.
156 | */
157 | @property (nonatomic, assign) UITableViewCellEditingStyle editingStyle;
158 | @property (nonatomic, copy, nullable) UITableViewCellEditingStyle(^editingStyleHandler)(id _Nullable model);
159 | //@property (nonatomic, assign) SEL editingStyleSEL;
160 |
161 | /**
162 | * If the cell will select, the `willSelectHandler` will be called.
163 | *
164 | * If the `willSelectSEL` property is nil or the cell don't implement the `willSelectSEL` property setting method, then use the `willSelectHandler` property.
165 | */
166 | @property (nonatomic, copy, nullable) void (^willSelectHandler)(id _Nullable model);
167 | @property (nonatomic, assign) SEL willSelectSEL;
168 |
169 | /**
170 | * If the cell will deselect, the `willDeselectHandler` will be called.
171 | *
172 | * If the `willDeselectSEL` property is nil or the cell don't implement the `willDeselectSEL` property setting method, then use the `willDeselectHandler` property.
173 | */
174 | @property (nonatomic, copy, nullable) void (^willDeselectHandler)(id _Nullable model);
175 | @property (nonatomic, assign) SEL willDeselectSEL;
176 |
177 | /**
178 | * If the cell did select, the `didSelectHandler` will be called.
179 | *
180 | * If the `didSelectSEL` property is nil or the cell don't implement the `didSelectSEL` property setting method, then use the `didSelectHandler` property.
181 | */
182 | @property (nonatomic, copy, nullable) void (^didSelectHandler)(id _Nullable model);
183 | @property (nonatomic, assign) SEL didSelectSEL;
184 |
185 | /**
186 | * If the cell did deselect, the `didDeselectHandler` will be called.
187 | *
188 | * If the `didDeselectSEL` property is nil or the cell don't implement the `didDeselectSEL` property setting method, then use the `didDeselectHandler` property.
189 | */
190 | @property (nonatomic, copy, nullable) void (^didDeselectHandler)(id _Nullable model);
191 | @property (nonatomic, assign) SEL didDeselectSEL;
192 |
193 | /**
194 | * If the cell will display, the `willDisplayHandler` will be called.
195 | *
196 | * If the `willDisplaySEL` property is nil or the cell don't implement the `willDisplaySEL` property setting method, then use the `willDisplayHandler` property.
197 | */
198 | @property (nonatomic, copy, nullable) void (^willDisplayHandler)(UITableViewCell *cell, id _Nullable model);
199 | @property (nonatomic, assign) SEL willDisplaySEL;
200 |
201 | /**
202 | * If the cell did end displaying, the `didEndDisplayingHandler` will be called.
203 | *
204 | * If the `didEndDisplayingSEL` property is nil or the cell don't implement the `didEndDisplayingSEL` property setting method, then use the `didEndDisplayingHandler` property.
205 | */
206 | @property (nonatomic, copy, nullable) void (^didEndDisplayingHandler)(UITableViewCell *cell, id _Nullable model);
207 | @property (nonatomic, assign) SEL didEndDisplayingSEL;
208 |
209 | /**
210 | * If the cell did highlight, the `didHighlightHandler` will be called.
211 | *
212 | * If the `didHighlightSEL` property is nil or the cell don't implement the `didHighlightSEL` property setting method, then use the `didHighlightHandler` property.
213 | */
214 | @property (nonatomic, copy, nullable) void (^didHighlightHandler)(id _Nullable model);
215 | @property (nonatomic, assign) SEL didHighlightSEL;
216 |
217 | /**
218 | * If the cell did unhighlight, the `didUnHighlightHandler` will be called.
219 | *
220 | * If the `didUnHighlightSEL` property is nil or the cell don't implement the `didUnHighlightSEL` property setting method, then use the `didUnHighlightHandler` property.
221 | */
222 | @property (nonatomic, copy, nullable) void (^didUnHighlightHandler)(id _Nullable model);
223 | @property (nonatomic, assign) SEL didUnHighlightSEL;
224 |
225 | /**
226 | * If the cell accessory button tapped, the `accessoryButtonTappedHandler` will be called.
227 | *
228 | * If the `accessoryButtonTappedSEL` property is nil or the cell don't implement the `accessoryButtonTappedSEL` property setting method, then use the `accessoryButtonTappedHandler` property.
229 | */
230 | @property (nonatomic, copy, nullable) void (^accessoryButtonTappedHandler)(id _Nullable model);
231 | @property (nonatomic, assign) SEL accessoryButtonTappedSEL;
232 |
233 | /**
234 | * If the cell will begin editing, the `willBeginEditingHandler` will be called.
235 | *
236 | * If the `willBeginEditingSEL` property is nil or the cell don't implement the `willBeginEditingSEL` property setting method, then use the `willBeginEditingHandler` property.
237 | */
238 | @property (nonatomic, copy, nullable) void (^willBeginEditingHandler)(id _Nullable model);
239 | @property (nonatomic, assign) SEL willBeginEditingSEL;
240 |
241 | /**
242 | * If the cell did end editing, the `didEndEditingHandler` will be called.
243 | *
244 | * If the `didEndEditingSEL` property is nil or the cell don't implement the `didEndEditingSEL` property setting method, then use the `didEndEditingHandler` property.
245 | */
246 | @property (nonatomic, copy, nullable) void (^didEndEditingHandler)(id _Nullable model);
247 | @property (nonatomic, assign) SEL didEndEditingSEL;
248 |
249 | /**
250 | * Set the target move index for the cell using the `targetMoveHandler` property.
251 | */
252 | @property (nonatomic, copy, nullable) NSIndexPath *(^targetMoveHandler)(NSIndexPath *atIndexPath, NSIndexPath *toIndexPath);
253 | //@property (nonatomic, assign) SEL targetMoveSEL;
254 |
255 | /**
256 | * If the cell is moved, the `moveHandler` will be called.
257 | */
258 | @property (nonatomic, copy, nullable) void (^moveHandler)(NSIndexPath *atIndexPath, NSIndexPath *toIndexPath, void(^completionHandler)(BOOL actionPerformed));
259 | //@property (nonatomic, assign) SEL moveSEL;
260 |
261 | /**
262 | * If the cell is editing delete, the `editingDeleteHandler` will be called.
263 | */
264 | @property (nonatomic, copy, nullable) void (^editingDeleteHandler)(id _Nullable model, void(^completionHandler)(BOOL actionPerformed));
265 | //@property (nonatomic, assign) SEL editingDeleteSEL;
266 |
267 | /**
268 | * If the cell is editing Insert, the `editingInsertHandler` will be called.
269 | */
270 | @property (nonatomic, copy, nullable) void (^editingInsertHandler)(id _Nullable model);
271 | //@property (nonatomic, assign) SEL editingInsertSEL;
272 |
273 |
274 | /**
275 | * Set the delegate for the cell using the `delegate` property.
276 | *
277 | * If the `delegateSEL` property is nil or the cell don't implement the `delegateSEL` property setting method, then use the `delegate` property.
278 | */
279 | @property (nonatomic, weak, nullable) id delegate;
280 | @property (nonatomic, assign) SEL delegateSEL;
281 |
282 | @end
283 |
284 | NS_ASSUME_NONNULL_END
285 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Row/HoloTableRow.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRow.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/1.
6 | //
7 |
8 | #import "HoloTableRow.h"
9 |
10 | @implementation HoloTableRow
11 |
12 | - (instancetype)init {
13 | self = [super init];
14 | if (self) {
15 | _cell = UITableViewCell.class;
16 | _height = CGFLOAT_MIN;
17 | _estimatedHeight = CGFLOAT_MIN;
18 | _shouldHighlight = YES;
19 | _style = UITableViewCellStyleDefault;
20 | _canEdit = NO;
21 | _canMove = NO;
22 | _editingStyle = UITableViewCellEditingStyleNone;
23 | #pragma clang diagnostic push
24 | #pragma clang diagnostic ignored "-Wundeclared-selector"
25 | _configSEL = @selector(holo_configureCellWithModel:);
26 | _heightSEL = @selector(holo_heightForCellWithModel:);
27 | _estimatedHeightSEL = @selector(holo_estimatedHeightForCellWithModel:);
28 | _shouldHighlightSEL = @selector(holo_shouldHighlightForCellWithModel:);
29 | _willSelectSEL = @selector(holo_willSelectCellWithModel:);
30 | _willDeselectSEL = @selector(holo_willDeselectCellWithModel:);
31 | _didDeselectSEL = @selector(holo_didDeselectCellWithModel:);
32 | _didSelectSEL = @selector(holo_didSelectCellWithModel:);
33 | _willDisplaySEL = @selector(holo_willDisplayCellWithModel:);
34 | _didEndDisplayingSEL = @selector(holo_didEndDisplayingCellWithModel:);
35 | _didHighlightSEL = @selector(holo_didHighlightCellWithModel:);
36 | _didUnHighlightSEL = @selector(holo_didUnHighlightCellWithModel:);
37 | _accessoryButtonTappedSEL = @selector(holo_accessoryButtonTappedCellWithModel:);
38 | _willBeginEditingSEL = @selector(holo_willBeginEditingCellWithModel:);
39 | _didEndEditingSEL = @selector(holo_didEndEditingCellWithModel:);
40 |
41 | // support set a delegate for cell
42 | _delegateSEL = @selector(holo_configureCellDelegate:);
43 | #pragma clang diagnostic pop
44 | }
45 |
46 | return self;
47 | }
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Section/HoloTableSection.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSection.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import
9 | @class HoloTableRow;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloTableSection : NSObject
14 |
15 | /**
16 | * Set the rows for the section using the `rows` property.
17 | */
18 | @property (nonatomic, copy) NSArray *rows;
19 |
20 | /**
21 | * Set the tag for the section using the `tag` property.
22 | */
23 | @property (nonatomic, copy, nullable) NSString *tag;
24 |
25 | /**
26 | * Header class.
27 | */
28 | @property (nonatomic, assign) Class header;
29 |
30 | /**
31 | * Footer class.
32 | */
33 | @property (nonatomic, assign) Class footer;
34 |
35 | /**
36 | * Set the header title for the section using the `headerTitle` property.
37 | *
38 | * If you set 'header', the `headerTitleHandler` property and `headerTitle` property will be invalid.
39 | *
40 | * If the `headerTitleHandler` property is nil, then use the `headerTitle` property.
41 | */
42 | @property (nonatomic, copy, nullable) NSString *headerTitle;
43 | @property (nonatomic, copy, nullable) NSString *(^headerTitleHandler)(void);
44 |
45 | /**
46 | * Set the footer title for the section using the `footerTitle` property.
47 | *
48 | * If you set 'footer', the `footerTitleHandler` property and `footerTitle` property will be invalid.
49 | *
50 | * If the `footerTitleHandler` property is nil, then use the `footerTitle` property.
51 | */
52 | @property (nonatomic, copy, nullable) NSString *footerTitle;
53 | @property (nonatomic, copy, nullable) NSString *(^footerTitleHandler)(void);
54 |
55 | /**
56 | * Set the data for the header using the `headerModel` property.
57 | *
58 | * If the `headerModelHandler` property is nil, then use the `headerModel` property.
59 | */
60 | @property (nonatomic, strong, nullable) id headerModel;
61 | @property (nonatomic, copy, nullable) id (^headerModelHandler)(void);
62 |
63 | /**
64 | * Set the data for the footer using the `footerModel` property.
65 | *
66 | * If the `footerModelHandler` property is nil, then use the `footerModel` property.
67 | */
68 | @property (nonatomic, strong, nullable) id footerModel;
69 | @property (nonatomic, copy, nullable) id (^footerModelHandler)(void);
70 |
71 | /**
72 | * The header must implement the `headerConfigSEL` property setting method in order for the HoloTableView to pass the model for the header.
73 | */
74 | @property (nonatomic, assign) SEL headerConfigSEL;
75 |
76 | /**
77 | * The footer must implement the `footerConfigSEL` property setting method in order for the HoloTableView to pass the model for the footer.
78 | */
79 | @property (nonatomic, assign) SEL footerConfigSEL;
80 |
81 | /**
82 | * Set the reuse identifier for the header using the `headerReuseId` property.
83 | *
84 | * If the `headerReuseIdHandler` property is nil, then use the `headerReuseId` property.
85 | */
86 | @property (nonatomic, copy, nullable) NSString *headerReuseId;
87 | @property (nonatomic, copy, nullable) NSString *(^headerReuseIdHandler)(id _Nullable model);
88 |
89 | /**
90 | * Set the reuse identifier for the footer using the `footerReuseId` property.
91 | *
92 | * If the `footerReuseIdHandler` property is nil, then use the `footerReuseId` property.
93 | */
94 | @property (nonatomic, copy, nullable) NSString *footerReuseId;
95 | @property (nonatomic, copy, nullable) NSString *(^footerReuseIdHandler)(id _Nullable model);
96 |
97 | /**
98 | * Set the height for the header using the `headerHeight` property.
99 | *
100 | * If the `headerHeightSEL` property is nil or the header don't implement the `headerHeightSEL` property setting method, then use the `headerHeightHandler` property.
101 | * If the `headerHeightHandler` property is nil, then use the `headerHeight` property.
102 | */
103 | @property (nonatomic, assign) CGFloat headerHeight;
104 | @property (nonatomic, copy, nullable) CGFloat (^headerHeightHandler)(id _Nullable model);
105 | @property (nonatomic, assign) SEL headerHeightSEL;
106 |
107 | /**
108 | * Set the height for the footer using the `footerHeight` property.
109 | *
110 | * If the `footerHeightSEL` property is nil or the footer don't implement the `footerHeightSEL` property setting method, then use the `footerHeightHandler` property.
111 | * If the `footerHeightHandler` property is nil, then use the `footerHeight` property.
112 | */
113 | @property (nonatomic, assign) CGFloat footerHeight;
114 | @property (nonatomic, copy, nullable) CGFloat (^footerHeightHandler)(id _Nullable model);
115 | @property (nonatomic, assign) SEL footerHeightSEL;
116 |
117 | /**
118 | * Set the estimated height for the header using the `headerEstimatedHeight` property.
119 | *
120 | * If the `headerEstimatedHeightSEL` property is nil or the header don't implement the `headerEstimatedHeightSEL` property setting method, then use the `headerEstimatedHeightHandler` property.
121 | * If the `headerEstimatedHeightHandler` property is nil, then use the `headerEstimatedHeight` property.
122 | */
123 | @property (nonatomic, assign) CGFloat headerEstimatedHeight;
124 | @property (nonatomic, copy, nullable) CGFloat (^headerEstimatedHeightHandler)(id _Nullable model);
125 | @property (nonatomic, assign) SEL headerEstimatedHeightSEL;
126 |
127 | /**
128 | * Set the estimated height for the footer using the `footerEstimatedHeight` property.
129 | *
130 | * If the `footerEstimatedHeightSEL` property is nil or the footer don't implement the `footerEstimatedHeightSEL` property setting method, then use the `footerEstimatedHeightHandler` property.
131 | * If the `footerEstimatedHeightHandler` property is nil, then use the `footerEstimatedHeight` property.
132 | */
133 | @property (nonatomic, assign) CGFloat footerEstimatedHeight;
134 | @property (nonatomic, copy, nullable) CGFloat (^footerEstimatedHeightHandler)(id _Nullable model);
135 | @property (nonatomic, assign) SEL footerEstimatedHeightSEL;
136 |
137 | /**
138 | * If the header will display, the `willDisplayHeaderHandler` will be called.
139 | *
140 | * If the `willDisplayHeaderSEL` property is nil or the header don't implement the `willDisplayHeaderSEL` property setting method, then use the `willDisplayHeaderHandler` property.
141 | */
142 | @property (nonatomic, copy, nullable) void (^willDisplayHeaderHandler)(UIView *header, id _Nullable model);
143 | @property (nonatomic, assign) SEL willDisplayHeaderSEL;
144 |
145 | /**
146 | * If the footer will display, the `willDisplayFooterSEL` will be called.
147 | *
148 | * If the `willDisplayFooterSEL` property is nil or the footer don't implement the `willDisplayFooterSEL` property setting method, then use the `willDisplayFooterHandler` property.
149 | */
150 | @property (nonatomic, copy, nullable) void (^willDisplayFooterHandler)(UIView *footer, id _Nullable model);
151 | @property (nonatomic, assign) SEL willDisplayFooterSEL;
152 |
153 | /**
154 | * If the header did end displaying, the `didEndDisplayingHeaderHandler` will be called.
155 | *
156 | * If the `didEndDisplayingHeaderSEL` property is nil or the header don't implement the `didEndDisplayingHeaderSEL` property setting method, then use the `didEndDisplayingHeaderHandler` property.
157 | */
158 | @property (nonatomic, copy, nullable) void (^didEndDisplayingHeaderHandler)(UIView *header, id _Nullable model);
159 | @property (nonatomic, assign) SEL didEndDisplayingHeaderSEL;
160 |
161 | /**
162 | * If the footer did end displaying, the `didEndDisplayingFooterHandler` will be called.
163 | *
164 | * If the `didEndDisplayingFooterSEL` property is nil or the footer don't implement the `didEndDisplayingFooterSEL` property setting method, then use the `didEndDisplayingFooterHandler` property.
165 | */
166 | @property (nonatomic, copy, nullable) void (^didEndDisplayingFooterHandler)(UIView *footer, id _Nullable model);
167 | @property (nonatomic, assign) SEL didEndDisplayingFooterSEL;
168 |
169 |
170 | /**
171 | * Add a row to current section.
172 | */
173 | - (void)addRow:(HoloTableRow *)row;
174 |
175 | /**
176 | * remove a row from current section.
177 | */
178 | - (void)removeRow:(HoloTableRow *)row;
179 |
180 | /**
181 | * Remove all rows of current section.
182 | */
183 | - (void)removeAllRows;
184 |
185 | /**
186 | * Insert a row to current section somewhere.
187 | */
188 | - (void)insertRow:(HoloTableRow *)row atIndex:(NSInteger)index;
189 |
190 | @end
191 |
192 |
193 | NS_ASSUME_NONNULL_END
194 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/Section/HoloTableSection.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSection.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import "HoloTableSection.h"
9 |
10 | @implementation HoloTableSection
11 |
12 | - (instancetype)init {
13 | self = [super init];
14 | if (self) {
15 | _rows = [NSArray new];
16 | _header = UITableViewHeaderFooterView.class;
17 | _footer = UITableViewHeaderFooterView.class;
18 | _headerHeight = CGFLOAT_MIN;
19 | _footerHeight = CGFLOAT_MIN;
20 | _headerEstimatedHeight = CGFLOAT_MIN;
21 | _footerEstimatedHeight = CGFLOAT_MIN;
22 | #pragma clang diagnostic push
23 | #pragma clang diagnostic ignored "-Wundeclared-selector"
24 | _headerConfigSEL = @selector(holo_configureHeaderWithModel:);
25 | _footerConfigSEL = @selector(holo_configureFooterWithModel:);
26 | _headerHeightSEL = @selector(holo_heightForHeaderWithModel:);
27 | _footerHeightSEL = @selector(holo_heightForFooterWithModel:);
28 | _headerEstimatedHeightSEL = @selector(holo_estimatedHeightForHeaderWithModel:);
29 | _footerEstimatedHeightSEL = @selector(holo_estimatedHeightForFooterWithModel:);
30 |
31 | _willDisplayHeaderSEL = @selector(holo_willDisplayHeaderWithModel:);
32 | _willDisplayFooterSEL = @selector(holo_willDisplayFooterWithModel:);
33 | _didEndDisplayingHeaderSEL = @selector(holo_didEndDisplayingHeaderWithModel:);
34 | _didEndDisplayingFooterSEL = @selector(holo_didEndDisplayingFooterWithModel:);
35 | #pragma clang diagnostic pop
36 | }
37 | return self;
38 | }
39 |
40 |
41 | - (void)addRow:(HoloTableRow *)row {
42 | if (!row) return;
43 |
44 | NSMutableArray *array = [NSMutableArray arrayWithArray:self.rows];
45 | [array addObject:row];
46 | self.rows = array.copy;
47 | }
48 |
49 | - (void)removeRow:(HoloTableRow *)row {
50 | if (!row) return;
51 |
52 | NSMutableArray *array = [NSMutableArray arrayWithArray:self.rows];
53 | [array removeObject:row];
54 | self.rows = array.copy;
55 | }
56 |
57 | - (void)removeAllRows {
58 | self.rows = [NSArray new];
59 | }
60 |
61 | - (void)insertRow:(HoloTableRow *)row atIndex:(NSInteger)index {
62 | if (!row) return;
63 |
64 | if (index < 0) index = 0;
65 | if (index > self.rows.count) index = self.rows.count;
66 |
67 | NSMutableArray *array = [NSMutableArray arrayWithArray:self.rows];
68 | [array insertObject:row atIndex:index];
69 | self.rows = array.copy;
70 | }
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/SwipeAction/HoloTableViewRowSwipeAction.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewRowSwipeAction.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/8/5.
6 | //
7 |
8 | #import
9 | @class HoloTableViewRowSwipeAction;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | typedef void (^HoloTableViewRowSwipeActionHandler)(id action, NSInteger index, void(^completionHandler)(BOOL actionPerformed));
14 |
15 | typedef NS_ENUM(NSInteger, HoloTableViewRowSwipeActionStyle) {
16 | HoloTableViewRowSwipeActionStyleNormal,
17 | HoloTableViewRowSwipeActionStyleDestructive
18 | };
19 |
20 | @interface HoloTableViewRowSwipeAction : NSObject
21 |
22 | + (instancetype)rowSwipeActionWithStyle:(HoloTableViewRowSwipeActionStyle)style title:(nullable NSString *)title;
23 |
24 | + (instancetype)rowSwipeActionWithStyle:(HoloTableViewRowSwipeActionStyle)style title:(nullable NSString *)title handler:(HoloTableViewRowSwipeActionHandler)handler;
25 |
26 | @property (nonatomic, copy, nullable) NSString *title;;
27 |
28 | @property (nonatomic, assign) HoloTableViewRowSwipeActionStyle style;
29 |
30 | @property (nonatomic, copy, nullable) UIColor *backgroundColor;
31 |
32 | @property (nonatomic, copy, nullable) UIVisualEffect *backgroundEffect NS_DEPRECATED_IOS(8_0, 10_0);
33 |
34 | @property (nonatomic, copy, nullable) UIImage *image API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
35 |
36 | @property (nonatomic, copy, nullable) HoloTableViewRowSwipeActionHandler handler;
37 |
38 | @end
39 |
40 | NS_ASSUME_NONNULL_END
41 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/SwipeAction/HoloTableViewRowSwipeAction.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewRowSwipeAction.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/8/5.
6 | //
7 |
8 | #import "HoloTableViewRowSwipeAction.h"
9 |
10 | @implementation HoloTableViewRowSwipeAction
11 |
12 | + (instancetype)rowSwipeActionWithStyle:(HoloTableViewRowSwipeActionStyle)style title:(nullable NSString *)title {
13 | HoloTableViewRowSwipeAction *action = [HoloTableViewRowSwipeAction new];
14 | action.style = style;
15 | action.title = title;
16 | return action;
17 | }
18 |
19 | + (instancetype)rowSwipeActionWithStyle:(HoloTableViewRowSwipeActionStyle)style title:(NSString *)title handler:(HoloTableViewRowSwipeActionHandler)handler {
20 | HoloTableViewRowSwipeAction *action = [HoloTableViewRowSwipeAction new];
21 | action.style = style;
22 | action.title = title;
23 | action.handler = handler;
24 | return action;
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/UITableView+HoloTableViewProxy.h:
--------------------------------------------------------------------------------
1 | //
2 | // UITableView+HoloTableViewProxy.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/27.
6 | //
7 |
8 | #import
9 | @class HoloTableSection, HoloTableViewProxy;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface UITableView (HoloTableViewProxy)
14 |
15 | /**
16 | * Datasource of current UITableView.
17 | */
18 | @property (nonatomic, copy) NSArray *holo_sections;
19 |
20 | /**
21 | * Return list of section titles to display in section index view (e.g. "ABCD...Z#").
22 | */
23 | @property (nonatomic, copy, nullable) NSArray *holo_sectionIndexTitles;
24 |
25 | /**
26 | * Tell table which section corresponds to section title/index (e.g. "B",1)).
27 | */
28 | @property (nonatomic, copy, nullable) NSInteger (^holo_sectionForSectionIndexTitleHandler)(NSString *title, NSInteger index);
29 |
30 | /**
31 | * The delegate of the scroll-view object.
32 | */
33 | @property (nonatomic, weak, nullable) id holo_scrollDelegate;
34 |
35 | /**
36 | * Proxy of current UITableView.
37 | */
38 | @property (nonatomic, strong, readonly) HoloTableViewProxy *holo_proxy;
39 |
40 | @end
41 |
42 | NS_ASSUME_NONNULL_END
43 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Core/UITableView+HoloTableViewProxy.m:
--------------------------------------------------------------------------------
1 | //
2 | // UITableView+HoloTableViewProxy.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/27.
6 | //
7 |
8 | #import "UITableView+HoloTableViewProxy.h"
9 | #import
10 | #import "HoloTableViewProxy.h"
11 | #import "HoloTableViewProxyData.h"
12 |
13 | static char kHoloTableViewProxyKey;
14 |
15 | @implementation UITableView (HoloTableViewProxy)
16 |
17 | - (NSArray *)holo_sections {
18 | return self.holo_proxy.proxyData.sections;
19 | }
20 |
21 | - (void)setHolo_sections:(NSArray *)holo_sections {
22 | self.holo_proxy.proxyData.sections = holo_sections;
23 | }
24 |
25 | - (NSArray *)holo_sectionIndexTitles {
26 | return self.holo_proxy.proxyData.sectionIndexTitles;
27 | }
28 |
29 | - (void)setHolo_sectionIndexTitles:(NSArray *)holo_sectionIndexTitles {
30 | self.holo_proxy.proxyData.sectionIndexTitles = holo_sectionIndexTitles;
31 | }
32 |
33 | - (NSInteger (^)(NSString * _Nonnull, NSInteger))holo_sectionForSectionIndexTitleHandler {
34 | return self.holo_proxy.proxyData.sectionForSectionIndexTitleHandler;
35 | }
36 |
37 | - (void)setHolo_sectionForSectionIndexTitleHandler:(NSInteger (^)(NSString * _Nonnull, NSInteger))holo_sectionForSectionIndexTitleHandler {
38 | self.holo_proxy.proxyData.sectionForSectionIndexTitleHandler = holo_sectionForSectionIndexTitleHandler;
39 | }
40 |
41 | - (id)holo_scrollDelegate {
42 | return self.holo_proxy.scrollDelegate;
43 | }
44 |
45 | - (void)setHolo_scrollDelegate:(id)holo_scrollDelegate {
46 | self.holo_proxy.scrollDelegate = holo_scrollDelegate;
47 | }
48 |
49 | - (HoloTableViewProxy *)holo_proxy {
50 | HoloTableViewProxy *tableViewProxy = objc_getAssociatedObject(self, &kHoloTableViewProxyKey);
51 | if (!tableViewProxy) {
52 | tableViewProxy = [HoloTableViewProxy new];
53 | objc_setAssociatedObject(self, &kHoloTableViewProxyKey, tableViewProxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
54 | self.dataSource = tableViewProxy;
55 | self.delegate = tableViewProxy;
56 | }
57 | return tableViewProxy;
58 | }
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/HoloTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableView.h
3 | // Pods
4 | //
5 | // Created by 与佳期 on 2019/7/27.
6 | //
7 |
8 | #ifndef HoloTableView_h
9 | #define HoloTableView_h
10 |
11 | // Maker
12 | #import
13 | #import
14 |
15 | // Maker (Row)
16 | #import
17 | #import
18 |
19 | // Maker (Section)
20 | #import
21 | #import
22 |
23 | // Maker (TableView)
24 | #import
25 |
26 | // Maker (Update)
27 | #import
28 |
29 | // Core
30 | #import
31 | #import
32 | #import
33 | #import
34 |
35 | // Core (Object)
36 | #import
37 | #import
38 |
39 | // Core (Protocol)
40 | #import
41 | #import
42 | #import
43 |
44 | // Core (SwipeAction)
45 | #import
46 |
47 | // Macro
48 | #import
49 |
50 | // Responder Event
51 | #import
52 |
53 | #endif /* HoloTableView_h */
54 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Macro/HoloTableViewMacro.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewMacro.h
3 | // Pods
4 | //
5 | // Created by 与佳期 on 2019/8/1.
6 | //
7 |
8 | #ifndef HoloTableViewMacro_h
9 | #define HoloTableViewMacro_h
10 |
11 | #if !defined(TAG)
12 | #define TAG @"HOLO_DEFAULT_TAG"
13 | #endif
14 |
15 | #if !defined(HoloLog)
16 | #ifdef DEBUG
17 | #define HoloLog(...) NSLog(__VA_ARGS__)
18 | #else
19 | #define HoloLog(...)
20 | #endif
21 | #endif
22 |
23 | #endif /* HoloTableViewMacro_h */
24 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Deprecated/UITableView+HoloDeprecated.h:
--------------------------------------------------------------------------------
1 | //
2 | // UITableView+HoloDeprecated.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | //
7 |
8 | #import
9 | @class HoloTableViewUpdateRowMaker;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface UITableView (HoloDeprecated)
14 |
15 | /**
16 | * Creates a HoloTableViewUpdateRowMaker in the callee for current UITableView.
17 | * Update these rows in the callee for the section according to the tag.
18 | * If the section according to the tag don't contain these rows, ignore them.
19 | *
20 | * @param block Scope within which you can update some rows which you wish to apply to the section according to the tag.
21 | * @param tag The tag of section which you wish to update rows.
22 | */
23 | - (void)holo_updateRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
24 | inSection:(NSString *)tag DEPRECATED_MSG_ATTRIBUTE("Please use `holo_updateRowsInSection:block:` api instead.");
25 |
26 | /**
27 | * Creates a HoloTableViewUpdateRowMaker in the callee for current UITableView.
28 | * Update these rows in the callee for the section according to the tag.
29 | * If the section according to the tag don't contain these rows, ignore them.
30 | *
31 | * Refresh current UITableView automatically.
32 | *
33 | * @param block Scope within which you can update some rows which you wish to apply to the section according to the tag.
34 | * @param tag The tag of section which you wish to update rows.
35 | * @param animation A constant that indicates how the reloading is to be animated, for example, fade out or slide out from the bottom. See UITableViewRowAnimation for descriptions of these constants. The animation constant affects the direction in which both the old and the new rows slide. For example, if the animation constant is UITableViewRowAnimationRight, the old rows slide out to the right and the new cells slide in from the right.
36 | */
37 | - (void)holo_updateRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
38 | inSection:(NSString *)tag
39 | withReloadAnimation:(UITableViewRowAnimation)animation DEPRECATED_MSG_ATTRIBUTE("Please use `holo_updateRowsInSection:block:withReloadAnimation:` api instead.");
40 |
41 | /**
42 | * Creates a HoloTableViewUpdateRowMaker in the callee for current UITableView.
43 | * Re-create these rows in the callee for the section according to the tag.
44 | * If the section according to the tag don't contain these rows, ignore them.
45 | *
46 | * @param block Scope within which you can re-create some rows which you wish to apply to the section according to the tag.
47 | * @param tag The tag of section which you wish to remake rows.
48 | */
49 | - (void)holo_remakeRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
50 | inSection:(NSString *)tag DEPRECATED_MSG_ATTRIBUTE("Please use `holo_remakeRows:block:` api instead.");
51 |
52 | /**
53 | * Creates a HoloTableViewUpdateRowMaker in the callee for current UITableView.
54 | * Re-create these rows in the callee for the section according to the tag.
55 | * If the section according to the tag don't contain these rows, ignore them.
56 | *
57 | * Refresh current UITableView automatically.
58 | *
59 | * @param block Scope within which you can re-create some rows which you wish to apply to the section according to the tag.
60 | * @param tag The tag of section which you wish to remake rows.
61 | * @param animation A constant that indicates how the reloading is to be animated, for example, fade out or slide out from the bottom. See UITableViewRowAnimation for descriptions of these constants. The animation constant affects the direction in which both the old and the new rows slide. For example, if the animation constant is UITableViewRowAnimationRight, the old rows slide out to the right and the new cells slide in from the right.
62 | */
63 | - (void)holo_remakeRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
64 | inSection:(NSString *)tag
65 | withReloadAnimation:(UITableViewRowAnimation)animation DEPRECATED_MSG_ATTRIBUTE("Please use `holo_remakeRows:block:withReloadAnimation:` api instead.");
66 |
67 | @end
68 |
69 | NS_ASSUME_NONNULL_END
70 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Deprecated/UITableView+HoloDeprecated.m:
--------------------------------------------------------------------------------
1 | //
2 | // UITableView+HoloDeprecated.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2021/5/22.
6 | //
7 |
8 | #import "UITableView+HoloDeprecated.h"
9 | #import "HoloTableViewUpdateRowMaker.h"
10 | #import "UITableView+HoloTableView.h"
11 |
12 | @implementation UITableView (HoloDeprecated)
13 |
14 | - (void)holo_updateRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
15 | inSection:(NSString *)tag {
16 | [self holo_updateRowsInSection:tag block:block];
17 | }
18 |
19 | - (void)holo_updateRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
20 | inSection:(NSString *)tag
21 | withReloadAnimation:(UITableViewRowAnimation)animation {
22 | [self holo_updateRowsInSection:tag block:block withReloadAnimation:animation];
23 | }
24 |
25 | - (void)holo_remakeRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
26 | inSection:(NSString *)tag {
27 | [self holo_remakeRowsInSection:tag block:block];
28 | }
29 |
30 | - (void)holo_remakeRows:(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make))block
31 | inSection:(NSString *)tag
32 | withReloadAnimation:(UITableViewRowAnimation)animation {
33 | [self holo_remakeRowsInSection:tag block:block withReloadAnimation:animation];
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Row/HoloTableRowMaker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowMaker.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/1.
6 | //
7 |
8 | #import
9 | @class HoloTableRow, HoloTableViewRowSwipeAction;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloTableRowMaker : NSObject
14 |
15 | /**
16 | * Make a cell with class.
17 | */
18 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^row)(Class row);
19 |
20 | /**
21 | * Set the data for current row using the `model` property.
22 | *
23 | * If the `modelHandler` property is nil, then use the `model` property.
24 | */
25 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^model)(id model);
26 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^modelHandler)(id (^)(void));
27 |
28 | /**
29 | * current row must implement the `configSEL` property setting method in order for the HoloTableView to pass the model for current row.
30 | */
31 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^configSEL)(SEL configSEL);
32 |
33 | /**
34 | * Performed before `configSEL`.
35 | */
36 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^beforeConfigureHandler)(void(^)(UITableViewCell *cell, id _Nullable model));
37 |
38 | /**
39 | * Performed after `configSEL`.
40 | */
41 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^afterConfigureHandler)(void(^)(UITableViewCell *cell, id _Nullable model));
42 |
43 | /**
44 | * Set the style for current row using the `style` property.
45 | *
46 | * If the `styleHandler` property is nil, then use the `style` property.
47 | */
48 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^style)(UITableViewCellStyle style);
49 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^styleHandler)(UITableViewCellStyle (^)(id _Nullable model));
50 |
51 | /**
52 | * Set the reuse identifier for current row using the `reuseId` property.
53 | *
54 | * If the `reuseIdHandler` property is nil, then use the `reuseId` property.
55 | */
56 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^reuseId)(NSString *reuseId);
57 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^reuseIdHandler)(NSString *(^)(id _Nullable model));
58 |
59 | /**
60 | * Set the tag for current row using the `tag` property.
61 | */
62 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^tag)(NSString *tag);
63 |
64 | /**
65 | * Set the height for current row using the `height` property.
66 | *
67 | * If the `heightSEL` property is nil or current row don't implement the `heightSEL` property setting method, then use the `heightHandler` property.
68 | * If the `heightHandler` property is nil, then use the `height` property.
69 | */
70 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^height)(CGFloat height);
71 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^heightHandler)(CGFloat (^)(id _Nullable model));
72 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^heightSEL)(SEL heightSEL);
73 |
74 | /**
75 | * Set the estimated height for current row using the `estimatedHeight` property.
76 | *
77 | * If the `estimatedHeightSEL` property is nil or current row don't implement the `estimatedHeightSEL` property setting method, then use the `estimatedHeightHandler` property.
78 | * If the `estimatedHeightHandler` property is nil, then use the `estimatedHeight` property.
79 | */
80 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^estimatedHeight)(CGFloat estimatedHeight);
81 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^estimatedHeightHandler)(CGFloat (^)(id _Nullable model));
82 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^estimatedHeightSEL)(SEL estimatedHeightSEL);
83 |
84 | /**
85 | * Set the should highlight or not for current row using the `estimatedHeight` property.
86 | *
87 | * If the `shouldHighlightSEL` property is nil or current row don't implement the `shouldHighlightSEL` property setting method, then use the `shouldHighlightHandler` property.
88 | * If the `shouldHighlightHandler` property is nil, then use the `shouldHighlight` property.
89 | */
90 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^shouldHighlight)(BOOL shouldHighlight);
91 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^shouldHighlightHandler)(BOOL (^)(id _Nullable model));
92 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^shouldHighlightSEL)(SEL shouldHighlightSEL);
93 |
94 | /**
95 | * Set the can edit or not for current row using the `canEdit` property.
96 | *
97 | * If the `canEditHandler` property is nil, then use the `canEdit` property.
98 | */
99 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^canEdit)(BOOL canEdit);
100 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^canEditHandler)(BOOL (^)(id _Nullable model));
101 |
102 | /**
103 | * Set the can move or not for current row using the `canMove` property.
104 | *
105 | * If the `canMoveHandler` property is nil, then use the `canEdit` property.
106 | */
107 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^canMove)(BOOL canMove);
108 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^canMoveHandler)(BOOL (^)(id _Nullable model));
109 |
110 | /**
111 | * Set the leading swipe actions for current row using the `leadingSwipeActions` property.
112 | *
113 | * If the `leadingSwipeActionsHandler` property is nil, then use the `leadingSwipeActions` property.
114 | */
115 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^leadingSwipeActions)(NSArray *leadingSwipeActions) API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
116 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^leadingSwipeActionsHandler)(NSArray *(^)(id _Nullable model)) API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
117 |
118 | /**
119 | * Set the leading swipe for current row using the `leadingSwipeHandler` property.
120 | */
121 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^leadingSwipeHandler)(void(^)(id action, NSInteger index, void(^completionHandler)(BOOL actionPerformed))) API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
122 |
123 | /**
124 | * Set the trailing swipe actions for current row using the `trailingSwipeActions` property.
125 | *
126 | * If the `trailingSwipeActionsHandler` property is nil, then use the `trailingSwipeActions` property.
127 | */
128 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^trailingSwipeActions)(NSArray *trailingSwipeActions);
129 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^trailingSwipeActionsHandler)(NSArray *(^)(id _Nullable model));
130 |
131 | /**
132 | * Set the trailing swipe for current row using the `trailingSwipeHandler` property.
133 | */
134 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^trailingSwipeHandler)(void(^)(id action, NSInteger index, void(^completionHandler)(BOOL actionPerformed)));
135 |
136 | /**
137 | * Set the editing delete title for current row using the `editingDeleteTitle` property.
138 | *
139 | * If the `editingDeleteTitleHandler` property is nil, then use the `editingDeleteTitle` property.
140 | */
141 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^editingDeleteTitle)(NSString *title);
142 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^editingDeleteTitleHandler)(NSString *(^)(id _Nullable model));
143 |
144 | /**
145 | * Set the editing style for current row using the `editingStyle` property.
146 | *
147 | * If the `editingStyleHandler` property is nil, then use the `editingStyle` property.
148 | */
149 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^editingStyle)(UITableViewCellEditingStyle editingStyle);
150 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^editingStyleHandler)(UITableViewCellEditingStyle(^)(id _Nullable model));
151 |
152 | /**
153 | * If current row will select, the `willSelectHandler` will be called.
154 | *
155 | * If the `willSelectSEL` property is nil or current row don't implement the `willSelectSEL` property setting method, then use the `willSelectHandler` property.
156 | */
157 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willSelectHandler)(void(^)(id _Nullable model));
158 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willSelectSEL)(SEL willSelectSEL);
159 |
160 | /**
161 | * If current row will deselect, the `willDeselectHandler` will be called.
162 | *
163 | * If the `willDeselectSEL` property is nil or current row don't implement the `willDeselectSEL` property setting method, then use the `willDeselectHandler` property.
164 | */
165 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willDeselectHandler)(void(^)(id _Nullable model));
166 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willDeselectSEL)(SEL willDeselectSEL);
167 |
168 | /**
169 | * If current row did deselect, the `didDeselectHandler` will be called.
170 | *
171 | * If the `didDeselectSEL` property is nil or current row don't implement the `didDeselectSEL` property setting method, then use the `didDeselectHandler` property.
172 | */
173 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didDeselectHandler)(void(^)(id _Nullable model));
174 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didDeselectSEL)(SEL didDeselectSEL);
175 |
176 | /**
177 | * If current row did select, the `didSelectHandler` will be called.
178 | *
179 | * If the `didSelectSEL` property is nil or current row don't implement the `didSelectSEL` property setting method, then use the `didSelectHandler` property.
180 | */
181 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didSelectHandler)(void(^)(id _Nullable model));
182 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didSelectSEL)(SEL didSelectSEL);
183 |
184 | /**
185 | * If current row will display, the `willDisplayHandler` will be called.
186 | *
187 | * If the `willDisplaySEL` property is nil or current row don't implement the `willDisplaySEL` property setting method, then use the `willDisplayHandler` property.
188 | */
189 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willDisplayHandler)(void(^)(UITableViewCell *cell, id _Nullable model));
190 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willDisplaySEL)(SEL willDisplaySEL);
191 |
192 | /**
193 | * If current row did end displaying, the `didEndDisplayingHandler` will be called.
194 | *
195 | * If the `didEndDisplayingSEL` property is nil or current row don't implement the `didEndDisplayingSEL` property setting method, then use the `didEndDisplayingHandler` property.
196 | */
197 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didEndDisplayingHandler)(void(^)(UITableViewCell *cell, id _Nullable model));
198 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didEndDisplayingSEL)(SEL didEndDisplayingSEL);
199 |
200 | /**
201 | * If current row did highlight, the `didHighlightHandler` will be called.
202 | *
203 | * If the `didHighlightSEL` property is nil or current row don't implement the `didHighlightSEL` property setting method, then use the `didHighlightHandler` property.
204 | */
205 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didHighlightHandler)(void(^)(id _Nullable model));
206 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didHighlightSEL)(SEL didHighlightSEL);
207 |
208 | /**
209 | * If current row did unhighlight, the `didUnHighlightHandler` will be called.
210 | *
211 | * If the `didUnHighlightSEL` property is nil or current row don't implement the `didUnHighlightSEL` property setting method, then use the `didUnHighlightHandler` property.
212 | */
213 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didUnHighlightHandler)(void(^)(id _Nullable model));
214 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didUnHighlightSEL)(SEL didUnHighlightSEL);
215 |
216 | /**
217 | * If current row accessory button tapped, the `accessoryButtonTappedHandler` will be called.
218 | *
219 | * If the `accessoryButtonTappedSEL` property is nil or current row don't implement the `accessoryButtonTappedSEL` property setting method, then use the `accessoryButtonTappedHandler` property.
220 | */
221 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^accessoryButtonTappedHandler)(void(^)(id _Nullable model));
222 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^accessoryButtonTappedSEL)(SEL accessoryButtonTappedSEL);
223 |
224 | /**
225 | * If current row will begin editing, the `willBeginEditingHandler` will be called.
226 | *
227 | * If the `willBeginEditingSEL` property is nil or current row don't implement the `willBeginEditingSEL` property setting method, then use the `willBeginEditingHandler` property.
228 | */
229 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willBeginEditingHandler)(void(^)(id _Nullable model));
230 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^willBeginEditingSEL)(SEL willBeginEditingSEL);
231 |
232 | /**
233 | * If current row did end editing, the `didEndEditingHandler` will be called.
234 | *
235 | * If the `didEndEditingSEL` property is nil or current row don't implement the `didEndEditingSEL` property setting method, then use the `didEndEditingHandler` property.
236 | */
237 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didEndEditingHandler)(void(^)(id _Nullable model));
238 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^didEndEditingSEL)(SEL didEndEditingSEL);
239 |
240 | /**
241 | * Set the target move index for current row using the `targetMoveHandler` property.
242 | */
243 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^targetMoveHandler)(NSIndexPath *(^targetIndexPath)(NSIndexPath *atIndexPath, NSIndexPath *toIndexPath));
244 |
245 | /**
246 | * If current row is moved, the `moveHandler` will be called.
247 | */
248 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^moveHandler)(void(^)(NSIndexPath *atIndexPath, NSIndexPath *toIndexPath, void(^completionHandler)(BOOL actionPerformed)));
249 |
250 | /**
251 | * If current row is editing delete, the `editingDeleteHandler` will be called.
252 | */
253 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^editingDeleteHandler)(void(^)(id _Nullable model, void(^completionHandler)(BOOL actionPerformed)));
254 |
255 | /**
256 | * If current row is editing Insert, the `editingInsertHandler` will be called.
257 | */
258 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^editingInsertHandler)(void(^)(id _Nullable model));
259 |
260 |
261 | - (HoloTableRow *)fetchTableRow;
262 |
263 | - (void)giveTableRow:(HoloTableRow *)tableRow;
264 |
265 | @end
266 |
267 | NS_ASSUME_NONNULL_END
268 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Row/HoloTableRowMaker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableRowMaker.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/1.
6 | //
7 |
8 | #import "HoloTableRowMaker.h"
9 | #import "HoloTableRow.h"
10 | #import "HoloTableViewRowSwipeAction.h"
11 |
12 | @interface HoloTableRowMaker ()
13 |
14 | @property (nonatomic, strong) HoloTableRow *tableRow;
15 |
16 | @end
17 |
18 | @implementation HoloTableRowMaker
19 |
20 | - (HoloTableRowMaker * (^)(Class))row {
21 | return ^id(Class cls) {
22 | self.tableRow.cell = cls;
23 | return self;
24 | };
25 | }
26 |
27 | - (HoloTableRowMaker *(^)(id))model {
28 | return ^id(id obj) {
29 | self.tableRow.model = obj;
30 | return self;
31 | };
32 | }
33 | - (HoloTableRowMaker * (^)(id (^)(void)))modelHandler {
34 | return ^id(id obj) {
35 | self.tableRow.modelHandler = obj;
36 | return self;
37 | };
38 | }
39 |
40 | - (HoloTableRowMaker *(^)(SEL))configSEL {
41 | return ^id(SEL s) {
42 | self.tableRow.configSEL = s;
43 | return self;
44 | };
45 | }
46 | - (HoloTableRowMaker * (^)(void (^)(UITableViewCell *, id)))beforeConfigureHandler {
47 | return ^id(id obj) {
48 | self.tableRow.beforeConfigureHandler = obj;
49 | return self;
50 | };
51 | }
52 | - (HoloTableRowMaker * (^)(void (^)(UITableViewCell *, id)))afterConfigureHandler {
53 | return ^id(id obj) {
54 | self.tableRow.afterConfigureHandler = obj;
55 | return self;
56 | };
57 | }
58 |
59 | - (HoloTableRowMaker * (^)(UITableViewCellStyle))style {
60 | return ^id(UITableViewCellStyle style) {
61 | self.tableRow.style = style;
62 | return self;
63 | };
64 | }
65 | - (HoloTableRowMaker * (^)(UITableViewCellStyle (^)(id)))styleHandler {
66 | return ^id(id obj) {
67 | self.tableRow.styleHandler = obj;
68 | return self;
69 | };
70 | }
71 |
72 | - (HoloTableRowMaker * (^)(NSString *))reuseId {
73 | return ^id(id obj) {
74 | self.tableRow.reuseId = obj;
75 | return self;
76 | };
77 | }
78 | - (HoloTableRowMaker * (^)(NSString * (^)(id)))reuseIdHandler {
79 | return ^id(id obj) {
80 | self.tableRow.reuseIdHandler = obj;
81 | return self;
82 | };
83 | }
84 |
85 | - (HoloTableRowMaker *(^)(NSString *))tag {
86 | return ^id(id obj) {
87 | self.tableRow.tag = obj;
88 | return self;
89 | };
90 | }
91 |
92 | - (HoloTableRowMaker *(^)(CGFloat))height {
93 | return ^id(CGFloat f) {
94 | self.tableRow.height = f;
95 | return self;
96 | };
97 | }
98 | - (HoloTableRowMaker * (^)(CGFloat (^)(id)))heightHandler {
99 | return ^id(id obj) {
100 | self.tableRow.heightHandler = obj;
101 | return self;
102 | };
103 | }
104 | - (HoloTableRowMaker *(^)(SEL))heightSEL {
105 | return ^id(SEL s) {
106 | self.tableRow.heightSEL = s;
107 | return self;
108 | };
109 | }
110 |
111 |
112 | - (HoloTableRowMaker *(^)(CGFloat))estimatedHeight {
113 | return ^id(CGFloat f) {
114 | self.tableRow.estimatedHeight = f;
115 | return self;
116 | };
117 | }
118 | - (HoloTableRowMaker * (^)(CGFloat (^)(id)))estimatedHeightHandler {
119 | return ^id(id obj) {
120 | self.tableRow.estimatedHeightHandler = obj;
121 | return self;
122 | };
123 | }
124 | - (HoloTableRowMaker *(^)(SEL))estimatedHeightSEL {
125 | return ^id(SEL s) {
126 | self.tableRow.estimatedHeightSEL = s;
127 | return self;
128 | };
129 | }
130 |
131 | - (HoloTableRowMaker *(^)(BOOL))shouldHighlight {
132 | return ^id(BOOL b) {
133 | self.tableRow.shouldHighlight = b;
134 | return self;
135 | };
136 | }
137 | - (HoloTableRowMaker * (^)(BOOL (^)(id)))shouldHighlightHandler {
138 | return ^id(id obj) {
139 | self.tableRow.shouldHighlightHandler = obj;
140 | return self;
141 | };
142 | }
143 | - (HoloTableRowMaker *(^)(SEL))shouldHighlightSEL {
144 | return ^id(SEL s) {
145 | self.tableRow.shouldHighlightSEL = s;
146 | return self;
147 | };
148 | }
149 |
150 | - (HoloTableRowMaker *(^)(BOOL))canEdit {
151 | return ^id(BOOL b) {
152 | self.tableRow.canEdit = b;
153 | return self;
154 | };
155 | }
156 | - (HoloTableRowMaker * (^)(BOOL (^)(id)))canEditHandler {
157 | return ^id(id obj) {
158 | self.tableRow.canEditHandler = obj;
159 | return self;
160 | };
161 | }
162 |
163 | - (HoloTableRowMaker *(^)(BOOL))canMove {
164 | return ^id(BOOL b) {
165 | if (b) self.tableRow.canEdit = YES;
166 | self.tableRow.canMove = b;
167 | return self;
168 | };
169 | }
170 | - (HoloTableRowMaker * (^)(BOOL (^)(id)))canMoveHandler {
171 | return ^id(id obj) {
172 | self.tableRow.canMoveHandler = obj;
173 | return self;
174 | };
175 | }
176 |
177 | - (HoloTableRowMaker *(^)(NSArray *))leadingSwipeActions {
178 | return ^id(NSArray *a) {
179 | if (a.count > 0) self.tableRow.canEdit = YES;
180 | if (@available(iOS 11.0, *)) {
181 | self.tableRow.leadingSwipeActions = a;
182 | }
183 | return self;
184 | };
185 | }
186 | - (HoloTableRowMaker * (^)(NSArray *(^)(id)))leadingSwipeActionsHandler {
187 | return ^id(id obj) {
188 | if (@available(iOS 11.0, *)) {
189 | self.tableRow.leadingSwipeActionsHandler = obj;
190 | }
191 | return self;
192 | };
193 | }
194 |
195 | - (HoloTableRowMaker *(^)(void (^)(id, NSInteger, void(^)(BOOL))))leadingSwipeHandler {
196 | return ^id(id obj) {
197 | self.tableRow.leadingSwipeHandler = obj;
198 | return self;
199 | };
200 | }
201 |
202 | - (HoloTableRowMaker *(^)(NSArray *))trailingSwipeActions {
203 | return ^id(NSArray *a) {
204 | if (a.count > 0) self.tableRow.canEdit = YES;
205 | self.tableRow.trailingSwipeActions = a;
206 | return self;
207 | };
208 | }
209 | - (HoloTableRowMaker * (^)(NSArray *(^)(id)))trailingSwipeActionsHandler {
210 | return ^id(id obj) {
211 | self.tableRow.trailingSwipeActionsHandler = obj;
212 | return self;
213 | };
214 | }
215 |
216 | - (HoloTableRowMaker *(^)(void (^)(id, NSInteger, void(^)(BOOL))))trailingSwipeHandler {
217 | return ^id(id obj) {
218 | self.tableRow.trailingSwipeHandler = obj;
219 | return self;
220 | };
221 | }
222 |
223 | - (HoloTableRowMaker *(^)(NSString *))editingDeleteTitle {
224 | return ^id(id obj) {
225 | self.tableRow.editingDeleteTitle = obj;
226 | return self;
227 | };
228 | }
229 | - (HoloTableRowMaker * (^)(NSString * (^)(id)))editingDeleteTitleHandler {
230 | return ^id(id obj) {
231 | self.tableRow.editingDeleteTitleHandler = obj;
232 | return self;
233 | };
234 | }
235 |
236 | - (HoloTableRowMaker * (^)(UITableViewCellEditingStyle))editingStyle {
237 | return ^id(UITableViewCellEditingStyle editingStyle) {
238 | self.tableRow.editingStyle = editingStyle;
239 | return self;
240 | };
241 | }
242 | - (HoloTableRowMaker * (^)(UITableViewCellEditingStyle (^)(id)))editingStyleHandler {
243 | return ^id(id obj) {
244 | self.tableRow.editingStyleHandler = obj;
245 | return self;
246 | };
247 | }
248 |
249 | - (HoloTableRowMaker * (^)(void (^)(id)))willSelectHandler {
250 | return ^id(id obj) {
251 | self.tableRow.willSelectHandler = obj;
252 | return self;
253 | };
254 | }
255 | - (HoloTableRowMaker *(^)(SEL))willSelectSEL {
256 | return ^id(SEL s) {
257 | self.tableRow.willSelectSEL = s;
258 | return self;
259 | };
260 | }
261 |
262 | - (HoloTableRowMaker * (^)(void (^)(id)))willDeselectHandler {
263 | return ^id(id obj) {
264 | self.tableRow.willDeselectHandler = obj;
265 | return self;
266 | };
267 | }
268 | - (HoloTableRowMaker *(^)(SEL))willDeselectSEL {
269 | return ^id(SEL s) {
270 | self.tableRow.willDeselectSEL = s;
271 | return self;
272 | };
273 | }
274 |
275 | - (HoloTableRowMaker * (^)(void (^)(id)))didDeselectHandler {
276 | return ^id(id obj) {
277 | self.tableRow.didDeselectHandler = obj;
278 | return self;
279 | };
280 | }
281 | - (HoloTableRowMaker *(^)(SEL))didDeselectSEL {
282 | return ^id(SEL s) {
283 | self.tableRow.didDeselectSEL = s;
284 | return self;
285 | };
286 | }
287 |
288 | - (HoloTableRowMaker * (^)(void (^)(id)))didSelectHandler {
289 | return ^id(id obj) {
290 | self.tableRow.didSelectHandler = obj;
291 | return self;
292 | };
293 | }
294 | - (HoloTableRowMaker *(^)(SEL))didSelectSEL {
295 | return ^id(SEL s) {
296 | self.tableRow.didSelectSEL = s;
297 | return self;
298 | };
299 | }
300 |
301 | - (HoloTableRowMaker *(^)(void (^)(UITableViewCell *, id)))willDisplayHandler {
302 | return ^id(id obj) {
303 | self.tableRow.willDisplayHandler = obj;
304 | return self;
305 | };
306 | }
307 | - (HoloTableRowMaker *(^)(SEL))willDisplaySEL {
308 | return ^id(SEL s) {
309 | self.tableRow.willDisplaySEL = s;
310 | return self;
311 | };
312 | }
313 |
314 | - (HoloTableRowMaker *(^)(void (^)(UITableViewCell *, id)))didEndDisplayingHandler {
315 | return ^id(id obj) {
316 | self.tableRow.didEndDisplayingHandler = obj;
317 | return self;
318 | };
319 | }
320 | - (HoloTableRowMaker *(^)(SEL))didEndDisplayingSEL {
321 | return ^id(SEL s) {
322 | self.tableRow.didEndDisplayingSEL = s;
323 | return self;
324 | };
325 | }
326 |
327 | - (HoloTableRowMaker *(^)(void (^)(id)))didHighlightHandler {
328 | return ^id(id obj) {
329 | self.tableRow.didHighlightHandler = obj;
330 | return self;
331 | };
332 | }
333 | - (HoloTableRowMaker *(^)(SEL))didHighlightSEL {
334 | return ^id(SEL s) {
335 | self.tableRow.didHighlightSEL = s;
336 | return self;
337 | };
338 | }
339 |
340 | - (HoloTableRowMaker *(^)(void (^)(id)))didUnHighlightHandler {
341 | return ^id(id obj) {
342 | self.tableRow.didUnHighlightHandler = obj;
343 | return self;
344 | };
345 | }
346 | - (HoloTableRowMaker *(^)(SEL))didUnHighlightSEL {
347 | return ^id(SEL s) {
348 | self.tableRow.didUnHighlightSEL = s;
349 | return self;
350 | };
351 | }
352 |
353 | - (HoloTableRowMaker *(^)(void (^)(id)))accessoryButtonTappedHandler {
354 | return ^id(id obj) {
355 | self.tableRow.accessoryButtonTappedHandler = obj;
356 | return self;
357 | };
358 | }
359 | - (HoloTableRowMaker *(^)(SEL))accessoryButtonTappedSEL {
360 | return ^id(SEL s) {
361 | self.tableRow.accessoryButtonTappedSEL = s;
362 | return self;
363 | };
364 | }
365 |
366 | - (HoloTableRowMaker *(^)(void (^)(id)))willBeginEditingHandler {
367 | return ^id(id obj) {
368 | self.tableRow.willBeginEditingHandler = obj;
369 | return self;
370 | };
371 | }
372 | - (HoloTableRowMaker *(^)(SEL))willBeginEditingSEL {
373 | return ^id(SEL s) {
374 | self.tableRow.willBeginEditingSEL = s;
375 | return self;
376 | };
377 | }
378 |
379 | - (HoloTableRowMaker *(^)(void (^)(id)))didEndEditingHandler {
380 | return ^id(id obj) {
381 | self.tableRow.didEndEditingHandler = obj;
382 | return self;
383 | };
384 | }
385 | - (HoloTableRowMaker *(^)(SEL))didEndEditingSEL {
386 | return ^id(SEL s) {
387 | self.tableRow.didEndEditingSEL = s;
388 | return self;
389 | };
390 | }
391 |
392 | - (HoloTableRowMaker *(^)(NSIndexPath *(^)(NSIndexPath *, NSIndexPath *)))targetMoveHandler {
393 | return ^id(id obj) {
394 | self.tableRow.targetMoveHandler = obj;
395 | return self;
396 | };
397 | }
398 |
399 | - (HoloTableRowMaker *(^)(void (^)(NSIndexPath *, NSIndexPath *, void(^)(BOOL))))moveHandler {
400 | return ^id(id obj) {
401 | if (obj) {
402 | self.tableRow.canEdit = YES;
403 | self.tableRow.canMove = YES;
404 | }
405 | self.tableRow.moveHandler = obj;
406 | return self;
407 | };
408 | }
409 |
410 | - (HoloTableRowMaker * (^)(void (^)(id, void (^)(BOOL))))editingDeleteHandler {
411 | return ^id(id obj) {
412 | if (obj) {
413 | self.tableRow.canEdit = YES;
414 | self.tableRow.editingStyle = UITableViewCellEditingStyleDelete;
415 | }
416 | self.tableRow.editingDeleteHandler = obj;
417 | return self;
418 | };
419 | }
420 |
421 | - (HoloTableRowMaker *(^)(void (^)(id)))editingInsertHandler {
422 | return ^id(id obj) {
423 | if (obj) {
424 | self.tableRow.canEdit = YES;
425 | self.tableRow.editingStyle = UITableViewCellEditingStyleInsert;
426 | }
427 | self.tableRow.editingInsertHandler = obj;
428 | return self;
429 | };
430 | }
431 |
432 | - (HoloTableRow *)fetchTableRow {
433 | return self.tableRow;
434 | }
435 |
436 | - (void)giveTableRow:(HoloTableRow *)tableRow {
437 | self.tableRow = tableRow;
438 | }
439 |
440 | #pragma mark - getter
441 | - (HoloTableRow *)tableRow {
442 | if (!_tableRow) {
443 | _tableRow = [HoloTableRow new];
444 | }
445 | return _tableRow;
446 | }
447 |
448 | @end
449 |
450 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Row/HoloTableViewRowMaker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewRowMaker.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | //
7 |
8 | #import
9 | @class HoloTableRow, HoloTableRowMaker;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloTableViewRowMaker : NSObject
14 |
15 | /**
16 | * Make a HoloTableRow object and set the cell class.
17 | */
18 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^row)(Class row);
19 |
20 | - (NSArray *)install;
21 |
22 | @end
23 |
24 | NS_ASSUME_NONNULL_END
25 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Row/HoloTableViewRowMaker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewRowMaker.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | //
7 |
8 | #import "HoloTableViewRowMaker.h"
9 | #import "HoloTableRow.h"
10 | #import "HoloTableRowMaker.h"
11 |
12 | @interface HoloTableViewRowMaker ()
13 |
14 | @property (nonatomic, strong) NSMutableArray *holoRows;
15 |
16 | @end
17 |
18 | @implementation HoloTableViewRowMaker
19 |
20 | - (HoloTableRowMaker * (^)(Class))row {
21 | return ^id(Class cls) {
22 | HoloTableRowMaker *rowMaker = [HoloTableRowMaker new];
23 | HoloTableRow *tableRow = [rowMaker fetchTableRow];
24 | tableRow.cell = cls;
25 |
26 | [self.holoRows addObject:tableRow];
27 | return rowMaker;
28 | };
29 | }
30 |
31 | - (NSArray *)install {
32 | return self.holoRows;
33 | }
34 |
35 | #pragma mark - getter
36 | - (NSMutableArray *)holoRows {
37 | if (!_holoRows) {
38 | _holoRows = [NSMutableArray new];
39 | }
40 | return _holoRows;
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Section/HoloTableSectionMaker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSectionMaker.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import
9 | @class HoloTableSection, HoloTableViewRowMaker, HoloTableViewUpdateRowMaker;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface HoloTableSectionMaker : NSObject
14 |
15 | /**
16 | * Make a headerwith class.
17 | */
18 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^header)(Class header);
19 |
20 | /**
21 | * Make a footer with class.
22 | */
23 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footer)(Class footer);
24 |
25 | /**
26 | * Set the reuse identifier for the header using the `headerReuseId` property.
27 | *
28 | * If the `headerReuseIdHandler` property is nil, then use the `headerReuseId` property.
29 | */
30 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerReuseId)(NSString *headerReuseId);
31 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerReuseIdHandler)(NSString *(^)(id _Nullable model));
32 |
33 | /**
34 | * Set the reuse identifier for the footer using the `footerReuseId` property.
35 | *
36 | * If the `footerReuseIdHandler` property is nil, then use the `footerReuseId` property.
37 | */
38 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerReuseId)(NSString *footerReuseId);
39 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerReuseIdHandler)(NSString *(^)(id _Nullable model));
40 |
41 | /**
42 | * Set the header title for the section using the `headerTitle` property.
43 | *
44 | * If you set 'header', the `headerTitleHandler` property and `headerTitle` property will be invalid.
45 | *
46 | * If the `headerTitleHandler` property is nil, then use the `headerTitle` property.
47 | */
48 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerTitle)(NSString *headerTitle);
49 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerTitleHandler)(NSString *(^)(void));
50 |
51 | /**
52 | * Set the footer title for the section using the `footerTitle` property.
53 | *
54 | * If you set 'footer', the `footerTitleHandler` property and `footerTitle` property will be invalid.
55 | *
56 | * If the `footerTitleHandler` property is nil, then use the `footerTitle` property.
57 | */
58 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerTitle)(NSString *footerTitle);
59 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerTitleHandler)(NSString *(^)(void));
60 |
61 | /**
62 | * Set the data for the header using the `headerModel` property.
63 | *
64 | * If the `headerModelHandler` property is nil, then use the `headerModel` property.
65 | */
66 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerModel)(id headerModel);
67 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerModelHandler)(id (^)(void));
68 |
69 | /**
70 | * Set the data for the footer using the `footerModel` property.
71 | *
72 | * If the `footerModelHandler` property is nil, then use the `footerModel` property.
73 | */
74 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerModel)(id footerModel);
75 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerModelHandler)(id (^)(void));
76 |
77 | /**
78 | * The header must implement the `headerConfigSEL` property setting method in order for the HoloTableView to pass the model for the header.
79 | */
80 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerConfigSEL)(SEL headerConfigSEL);
81 |
82 | /**
83 | * The footer must implement the `footerConfigSEL` property setting method in order for the HoloTableView to pass the model for the footer.
84 | */
85 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerConfigSEL)(SEL footerConfigSEL);
86 |
87 | /**
88 | * Set the height for the header using the `headerHeight` property.
89 | *
90 | * If the `headerHeightSEL` property is nil or the header don't implement the `headerHeightSEL` property setting method, then use the `headerHeightHandler` property.
91 | * If the `headerHeightHandler` property is nil, then use the `headerHeight` property.
92 | */
93 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerHeight)(CGFloat headerHeight);
94 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerHeightHandler)(CGFloat (^)(id _Nullable model));
95 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerHeightSEL)(SEL headerHeightSEL);
96 |
97 | /**
98 | * Set the height for the footer using the `footerHeight` property.
99 | *
100 | * If the `footerHeightSEL` property is nil or the footer don't implement the `footerHeightSEL` property setting method, then use the `footerHeightHandler` property.
101 | * If the `footerHeightHandler` property is nil, then use the `footerHeight` property.
102 | */
103 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerHeight)(CGFloat footerHeight);
104 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerHeightHandler)(CGFloat (^)(id _Nullable model));
105 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerHeightSEL)(SEL footerHeightSEL);
106 |
107 | /**
108 | * Set the estimated height for the header using the `headerEstimatedHeight` property.
109 | *
110 | * If the `headerEstimatedHeightSEL` property is nil or the header don't implement the `headerEstimatedHeightSEL` property setting method, then use the `headerEstimatedHeightHandler` property.
111 | * If the `headerEstimatedHeightHandler` property is nil, then use the `headerEstimatedHeight` property.
112 | */
113 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerEstimatedHeight)(CGFloat headerEstimatedHeight);
114 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerEstimatedHeightHandler)(CGFloat (^)(id _Nullable model));
115 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^headerEstimatedHeightSEL)(SEL headerEstimatedHeightSEL);
116 |
117 | /**
118 | * Set the estimated height for the footer using the `footerEstimatedHeight` property.
119 | *
120 | * If the `footerEstimatedHeightSEL` property is nil or the footer don't implement the `footerEstimatedHeightSEL` property setting method, then use the `footerEstimatedHeightHandler` property.
121 | * If the `footerEstimatedHeightHandler` property is nil, then use the `footerEstimatedHeight` property.
122 | */
123 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerEstimatedHeight)(CGFloat footerEstimatedHeight);
124 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerEstimatedHeightHandler)(CGFloat (^)(id _Nullable model));
125 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^footerEstimatedHeightSEL)(SEL footerEstimatedHeightSEL);
126 |
127 | /**
128 | * If the header will display, the `willDisplayHeaderHandler` will be called.
129 | *
130 | * If the `willDisplayHeaderSEL` property is nil or the header don't implement the `willDisplayHeaderSEL` property setting method, then use the `willDisplayHeaderHandler` property.
131 | */
132 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^willDisplayHeaderHandler)(void(^)(UIView *header, id _Nullable model));
133 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^willDisplayHeaderSEL)(SEL willDisplayHeaderSEL);
134 |
135 | /**
136 | * If the footer will display, the `willDisplayFooterSEL` will be called.
137 | *
138 | * If the `willDisplayFooterSEL` property is nil or the footer don't implement the `willDisplayFooterSEL` property setting method, then use the `willDisplayFooterHandler` property.
139 | */
140 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^willDisplayFooterHandler)(void(^)(UIView *footer, id _Nullable model));
141 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^willDisplayFooterSEL)(SEL willDisplayFooterSEL);
142 |
143 | /**
144 | * If the header did end displaying, the `didEndDisplayingHeaderHandler` will be called.
145 | *
146 | * If the `didEndDisplayingHeaderSEL` property is nil or the header don't implement the `didEndDisplayingHeaderSEL` property setting method, then use the `didEndDisplayingHeaderHandler` property.
147 | */
148 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^didEndDisplayingHeaderHandler)(void(^)(UIView *header, id _Nullable model));
149 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^didEndDisplayingHeaderSEL)(SEL didEndDisplayingHeaderSEL);
150 |
151 | /**
152 | * If the footer did end displaying, the `didEndDisplayingFooterHandler` will be called.
153 | *
154 | * If the `didEndDisplayingFooterSEL` property is nil or the footer don't implement the `didEndDisplayingFooterSEL` property setting method, then use the `didEndDisplayingFooterHandler` property.
155 | */
156 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^didEndDisplayingFooterHandler)(void(^)(UIView *footer, id _Nullable model));
157 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^didEndDisplayingFooterSEL)(SEL didEndDisplayingFooterSEL);
158 |
159 | /**
160 | * Creates a HoloTableViewRowMaker in the callee for current UITableView.
161 | * Append these rows in the callee to current section.
162 | *
163 | * @param block Scope within which you can create some rows which you wish to apply to current UITableView.
164 | */
165 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^makeRows)(void(NS_NOESCAPE ^)(HoloTableViewRowMaker *make));
166 |
167 | /**
168 | * Creates a HoloTableViewUpdateRowMaker in the callee for current UITableView.
169 | * Update these rows in the callee for current section.
170 | * If current section don't contain these rows, ignore them.
171 | *
172 | * @param block Scope within which you can update some rows which you wish to apply to current UITableView.
173 | */
174 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^updateRows)(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make));
175 |
176 | /**
177 | * Creates a HoloTableViewUpdateRowMaker in the callee for current UITableView.
178 | * Re-create these rows in the callee for current section.
179 | * If current section don't contain these rows, ignore them.
180 | *
181 | * @param block Scope within which you can re-create some rows which you wish to apply to current UITableView.
182 | */
183 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^remakeRows)(void(NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *make));
184 |
185 |
186 | - (HoloTableSection *)fetchTableSection;
187 |
188 | - (void)giveTableSection:(HoloTableSection *)section;
189 |
190 | @end
191 |
192 | NS_ASSUME_NONNULL_END
193 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Section/HoloTableSectionMaker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableSectionMaker.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/6/2.
6 | //
7 |
8 | #import "HoloTableSectionMaker.h"
9 | #import "HoloTableSection.h"
10 | #import "HoloTableViewRowMaker.h"
11 | #import "HoloTableViewUpdateRowMaker.h"
12 |
13 | @interface HoloTableSectionMaker ()
14 |
15 | @property (nonatomic, strong) HoloTableSection *section;
16 |
17 | @end
18 |
19 | @implementation HoloTableSectionMaker
20 |
21 | - (HoloTableSectionMaker * (^)(Class))header {
22 | return ^id(Class cls) {
23 | self.section.header = cls;
24 | return self;
25 | };
26 | }
27 |
28 | - (HoloTableSectionMaker * (^)(Class))footer {
29 | return ^id(Class cls) {
30 | self.section.footer = cls;
31 | return self;
32 | };
33 | }
34 |
35 | - (HoloTableSectionMaker *(^)(NSString *))headerReuseId {
36 | return ^id(id obj) {
37 | self.section.headerReuseId = obj;
38 | return self;
39 | };
40 | }
41 | - (HoloTableSectionMaker * (^)(NSString * (^)(id)))headerReuseIdHandler {
42 | return ^id(id obj) {
43 | self.section.headerReuseIdHandler = obj;
44 | return self;
45 | };
46 | }
47 |
48 | - (HoloTableSectionMaker *(^)(NSString *))footerReuseId {
49 | return ^id(id obj) {
50 | self.section.footerReuseId = obj;
51 | return self;
52 | };
53 | }
54 | - (HoloTableSectionMaker * (^)(NSString * (^)(id)))footerReuseIdHandler {
55 | return ^id(id obj) {
56 | self.section.footerReuseIdHandler = obj;
57 | return self;
58 | };
59 | }
60 |
61 | - (HoloTableSectionMaker *(^)(NSString *))headerTitle {
62 | return ^id(id obj) {
63 | self.section.headerTitle = obj;
64 | return self;
65 | };
66 | }
67 | - (HoloTableSectionMaker * (^)(NSString * (^)(void)))headerTitleHandler {
68 | return ^id(id obj) {
69 | self.section.headerTitleHandler = obj;
70 | return self;
71 | };
72 | }
73 |
74 | - (HoloTableSectionMaker *(^)(NSString *))footerTitle {
75 | return ^id(id obj) {
76 | self.section.footerTitle = obj;
77 | return self;
78 | };
79 | }
80 | - (HoloTableSectionMaker * (^)(NSString * (^)(void)))footerTitleHandler {
81 | return ^id(id obj) {
82 | self.section.footerTitleHandler = obj;
83 | return self;
84 | };
85 | }
86 |
87 | - (HoloTableSectionMaker * (^)(id))headerModel {
88 | return ^id(id obj) {
89 | self.section.headerModel = obj;
90 | return self;
91 | };
92 | }
93 | - (HoloTableSectionMaker * (^)(id (^)(void)))headerModelHandler {
94 | return ^id(id obj) {
95 | self.section.headerModelHandler = obj;
96 | return self;
97 | };
98 | }
99 |
100 | - (HoloTableSectionMaker * (^)(id))footerModel {
101 | return ^id(id obj) {
102 | self.section.footerModel = obj;
103 | return self;
104 | };
105 | }
106 | - (HoloTableSectionMaker * (^)(id (^)(void)))footerModelHandler {
107 | return ^id(id obj) {
108 | self.section.footerModelHandler = obj;
109 | return self;
110 | };
111 | }
112 |
113 | - (HoloTableSectionMaker *(^)(SEL))headerConfigSEL {
114 | return ^id(SEL s) {
115 | self.section.headerConfigSEL = s;
116 | return self;
117 | };
118 | }
119 |
120 | - (HoloTableSectionMaker *(^)(SEL))footerConfigSEL {
121 | return ^id(SEL s) {
122 | self.section.footerConfigSEL = s;
123 | return self;
124 | };
125 | }
126 |
127 | - (HoloTableSectionMaker *(^)(CGFloat))headerHeight {
128 | return ^id(CGFloat f) {
129 | self.section.headerHeight = f;
130 | return self;
131 | };
132 | }
133 | - (HoloTableSectionMaker * (^)(CGFloat (^)(id)))headerHeightHandler {
134 | return ^id(id obj) {
135 | self.section.headerHeightHandler = obj;
136 | return self;
137 | };
138 | }
139 | - (HoloTableSectionMaker *(^)(SEL))headerHeightSEL {
140 | return ^id(SEL s) {
141 | self.section.headerHeightSEL = s;
142 | return self;
143 | };
144 | }
145 |
146 | - (HoloTableSectionMaker *(^)(CGFloat))footerHeight {
147 | return ^id(CGFloat f) {
148 | self.section.footerHeight = f;
149 | return self;
150 | };
151 | }
152 | - (HoloTableSectionMaker * (^)(CGFloat (^)(id)))footerHeightHandler {
153 | return ^id(id obj) {
154 | self.section.footerHeightHandler = obj;
155 | return self;
156 | };
157 | }
158 | - (HoloTableSectionMaker *(^)(SEL))footerHeightSEL {
159 | return ^id(SEL s) {
160 | self.section.footerHeightSEL = s;
161 | return self;
162 | };
163 | }
164 |
165 | - (HoloTableSectionMaker *(^)(CGFloat))headerEstimatedHeight {
166 | return ^id(CGFloat f) {
167 | self.section.headerEstimatedHeight = f;
168 | return self;
169 | };
170 | }
171 | - (HoloTableSectionMaker * (^)(CGFloat (^)(id)))headerEstimatedHeightHandler {
172 | return ^id(id obj) {
173 | self.section.headerEstimatedHeightHandler = obj;
174 | return self;
175 | };
176 | }
177 | - (HoloTableSectionMaker *(^)(SEL))headerEstimatedHeightSEL {
178 | return ^id(SEL s) {
179 | self.section.headerEstimatedHeightSEL = s;
180 | return self;
181 | };
182 | }
183 |
184 | - (HoloTableSectionMaker *(^)(CGFloat))footerEstimatedHeight {
185 | return ^id(CGFloat f) {
186 | self.section.footerEstimatedHeight = f;
187 | return self;
188 | };
189 | }
190 | - (HoloTableSectionMaker * (^)(CGFloat (^)(id)))footerEstimatedHeightHandler {
191 | return ^id(id obj) {
192 | self.section.footerEstimatedHeightHandler = obj;
193 | return self;
194 | };
195 | }
196 | - (HoloTableSectionMaker *(^)(SEL))footerEstimatedHeightSEL {
197 | return ^id(SEL s) {
198 | self.section.footerEstimatedHeightSEL = s;
199 | return self;
200 | };
201 | }
202 |
203 | - (HoloTableSectionMaker *(^)(void (^)(UIView *, id)))willDisplayHeaderHandler {
204 | return ^id(id obj) {
205 | self.section.willDisplayHeaderHandler = obj;
206 | return self;
207 | };
208 | }
209 | - (HoloTableSectionMaker *(^)(SEL))willDisplayHeaderSEL {
210 | return ^id(SEL s) {
211 | self.section.willDisplayHeaderSEL = s;
212 | return self;
213 | };
214 | }
215 |
216 | - (HoloTableSectionMaker *(^)(void (^)(UIView *, id)))willDisplayFooterHandler {
217 | return ^id(id obj) {
218 | self.section.willDisplayFooterHandler = obj;
219 | return self;
220 | };
221 | }
222 | - (HoloTableSectionMaker *(^)(SEL))willDisplayFooterSEL {
223 | return ^id(SEL s) {
224 | self.section.willDisplayFooterSEL = s;
225 | return self;
226 | };
227 | }
228 |
229 | - (HoloTableSectionMaker *(^)(void (^)(UIView *, id)))didEndDisplayingHeaderHandler {
230 | return ^id(id obj) {
231 | self.section.didEndDisplayingHeaderHandler = obj;
232 | return self;
233 | };
234 | }
235 | - (HoloTableSectionMaker *(^)(SEL))didEndDisplayingHeaderSEL {
236 | return ^id(SEL s) {
237 | self.section.didEndDisplayingHeaderSEL = s;
238 | return self;
239 | };
240 | }
241 |
242 | - (HoloTableSectionMaker *(^)(void (^)(UIView *, id)))didEndDisplayingFooterHandler {
243 | return ^id(id obj) {
244 | self.section.didEndDisplayingFooterHandler = obj;
245 | return self;
246 | };
247 | }
248 | - (HoloTableSectionMaker *(^)(SEL))didEndDisplayingFooterSEL {
249 | return ^id(SEL s) {
250 | self.section.didEndDisplayingFooterSEL = s;
251 | return self;
252 | };
253 | }
254 |
255 |
256 | - (HoloTableSectionMaker * (^)(void (NS_NOESCAPE ^)(HoloTableViewRowMaker *)))makeRows {
257 | return ^id(void(^block)(HoloTableViewRowMaker *make)) {
258 | HoloTableViewRowMaker *maker = [HoloTableViewRowMaker new];
259 | if (block) block(maker);
260 |
261 | NSMutableArray *array = [NSMutableArray arrayWithArray:self.section.rows];
262 | [array addObjectsFromArray:[maker install]];
263 | self.section.rows = array.copy;
264 | return self;
265 | };
266 | }
267 |
268 | - (HoloTableSectionMaker * (^)(void (NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *)))updateRows {
269 | return ^id(void(^block)(HoloTableViewUpdateRowMaker *make)) {
270 | HoloTableViewUpdateRowMaker *maker = [[HoloTableViewUpdateRowMaker alloc] initWithProxyDataSections:@[self.section]
271 | makerType:HoloTableViewUpdateRowMakerTypeUpdate
272 | targetSection:NO
273 | sectionTag:nil];
274 | if (block) block(maker);
275 |
276 | return self;
277 | };
278 | }
279 |
280 | - (HoloTableSectionMaker * (^)(void (NS_NOESCAPE ^)(HoloTableViewUpdateRowMaker *)))remakeRows {
281 | return ^id(void(^block)(HoloTableViewUpdateRowMaker *make)) {
282 | HoloTableViewUpdateRowMaker *maker = [[HoloTableViewUpdateRowMaker alloc] initWithProxyDataSections:@[self.section]
283 | makerType:HoloTableViewUpdateRowMakerTypeRemake
284 | targetSection:NO
285 | sectionTag:nil];
286 | if (block) block(maker);
287 |
288 | return self;
289 | };
290 | }
291 |
292 |
293 | - (HoloTableSection *)fetchTableSection {
294 | return self.section;
295 | }
296 |
297 | - (void)giveTableSection:(HoloTableSection *)section {
298 | self.section = section;
299 | }
300 |
301 | #pragma mark - getter
302 | - (HoloTableSection *)section {
303 | if (!_section) {
304 | _section = [HoloTableSection new];
305 | }
306 | return _section;
307 | }
308 |
309 | @end
310 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Section/HoloTableViewSectionMaker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewSectionMaker.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | //
7 |
8 | #import
9 | @class HoloTableSection, HoloTableSectionMaker;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | typedef NS_ENUM(NSInteger, HoloTableViewSectionMakerType) {
14 | HoloTableViewSectionMakerTypeMake,
15 | HoloTableViewSectionMakerTypeInsert,
16 | HoloTableViewSectionMakerTypeUpdate,
17 | HoloTableViewSectionMakerTypeRemake
18 | };
19 |
20 |
21 | @interface HoloTableViewSectionMakerModel : NSObject
22 |
23 | @property (nonatomic, strong, nullable) HoloTableSection *operateSection;
24 |
25 | @property (nonatomic, strong, nullable) NSNumber *operateIndex;
26 |
27 | @end
28 |
29 |
30 | @interface HoloTableViewSectionMaker : NSObject
31 |
32 | /**
33 | * Make a HoloTableSection object and set the section tag.
34 | */
35 | @property (nonatomic, copy, readonly) HoloTableSectionMaker *(^section)(NSString *tag);
36 |
37 | - (instancetype)initWithProxyDataSections:(NSArray *)sections
38 | makerType:(HoloTableViewSectionMakerType)makerType;
39 |
40 | - (NSArray *)install;
41 |
42 | @end
43 |
44 | NS_ASSUME_NONNULL_END
45 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Section/HoloTableViewSectionMaker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewSectionMaker.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/28.
6 | //
7 |
8 | #import "HoloTableViewSectionMaker.h"
9 | #import "HoloTableSection.h"
10 | #import "HoloTableSectionMaker.h"
11 |
12 | @implementation HoloTableViewSectionMakerModel
13 |
14 | @end
15 |
16 |
17 | @interface HoloTableViewSectionMaker ()
18 |
19 | @property (nonatomic, copy) NSArray *dataSections;
20 |
21 | @property (nonatomic, assign) HoloTableViewSectionMakerType makerType;
22 |
23 | @property (nonatomic, strong) NSMutableArray *makerModels;
24 |
25 | @end
26 |
27 | @implementation HoloTableViewSectionMaker
28 |
29 | - (instancetype)initWithProxyDataSections:(NSArray *)sections
30 | makerType:(HoloTableViewSectionMakerType)makerType {
31 | self = [super init];
32 | if (self) {
33 | _dataSections = sections;
34 | _makerType = makerType;
35 | }
36 | return self;
37 | }
38 |
39 | - (HoloTableSectionMaker *(^)(NSString *))section {
40 | return ^id(NSString *tag) {
41 | HoloTableSectionMaker *sectionMaker = [HoloTableSectionMaker new];
42 | HoloTableSection *makerSection = [sectionMaker fetchTableSection];
43 | makerSection.tag = tag;
44 |
45 | __block NSNumber *operateIndex = nil;
46 | if (self.makerType == HoloTableViewSectionMakerTypeUpdate || self.makerType == HoloTableViewSectionMakerTypeRemake) {
47 | [self.dataSections enumerateObjectsUsingBlock:^(HoloTableSection * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) {
48 | if ([section.tag isEqualToString:tag] || (!section.tag && !tag)) {
49 | operateIndex = @(idx);
50 |
51 | if (self.makerType == HoloTableViewSectionMakerTypeUpdate) {
52 | // update: set the row object to maker from datasource
53 | [sectionMaker giveTableSection:section];
54 | }
55 |
56 | *stop = YES;
57 | }
58 | }];
59 | }
60 |
61 | HoloTableViewSectionMakerModel *makerModel = [HoloTableViewSectionMakerModel new];
62 | makerModel.operateSection = [sectionMaker fetchTableSection];
63 | makerModel.operateIndex = operateIndex;
64 | [self.makerModels addObject:makerModel];
65 |
66 | return sectionMaker;
67 | };
68 | }
69 |
70 | - (NSArray *)install {
71 | return self.makerModels.copy;
72 | }
73 |
74 | #pragma mark - getter
75 | - (NSMutableArray *)makerModels {
76 | if (!_makerModels) {
77 | _makerModels = [NSMutableArray new];
78 | }
79 | return _makerModels;
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/TableView/HoloTableViewMaker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewMaker.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/1/30.
6 | //
7 |
8 | #import
9 | #import "HoloTableViewProtocol.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | typedef NSInteger (^HoloTableViewSectionForSectionIndexTitleHandler)(NSString *title, NSInteger index);
14 |
15 |
16 | @interface HoloTableViewModel : NSObject
17 |
18 | @property (nonatomic, copy, nullable) NSArray *indexTitles;
19 |
20 | @property (nonatomic, copy, nullable) HoloTableViewSectionForSectionIndexTitleHandler indexTitlesHandler;
21 |
22 | @property (nonatomic, weak, nullable) id delegate;
23 |
24 | @property (nonatomic, weak, nullable) id dataSource;
25 |
26 | @property (nonatomic, weak, nullable) id scrollDelegate;
27 |
28 | @end
29 |
30 |
31 | @interface HoloTableViewMaker : NSObject
32 |
33 | /**
34 | * Return list of section titles to display in section index view (e.g. "ABCD...Z#").
35 | */
36 | @property (nonatomic, copy, readonly) HoloTableViewMaker *(^sectionIndexTitles)(NSArray *sectionIndexTitles);
37 |
38 | /**
39 | * Tell table which section corresponds to section title/index (e.g. "B",1)).
40 | */
41 | @property (nonatomic, copy, readonly) HoloTableViewMaker *(^sectionForSectionIndexTitleHandler)(NSInteger (^handler)(NSString *title, NSInteger index));
42 |
43 | /**
44 | * The delegate of the scroll-view object.
45 | */
46 | @property (nonatomic, copy, readonly) HoloTableViewMaker *(^scrollDelegate)(id scrollDelegate);
47 |
48 | @property (nonatomic, copy, readonly) HoloTableViewMaker *(^delegate)(id delegate);
49 |
50 | @property (nonatomic, copy, readonly) HoloTableViewMaker *(^dataSource)(id dataSource);
51 |
52 | - (HoloTableViewModel *)install;
53 |
54 | @end
55 |
56 | NS_ASSUME_NONNULL_END
57 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/TableView/HoloTableViewMaker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewMaker.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2020/1/30.
6 | //
7 |
8 | #import "HoloTableViewMaker.h"
9 |
10 | @implementation HoloTableViewModel
11 |
12 | @end
13 |
14 |
15 | @interface HoloTableViewMaker ()
16 |
17 | @property (nonatomic, strong) HoloTableViewModel *tableViewModel;
18 |
19 | @end
20 |
21 | @implementation HoloTableViewMaker
22 |
23 | - (HoloTableViewMaker * (^)(NSArray *))sectionIndexTitles {
24 | return ^id(id obj) {
25 | self.tableViewModel.indexTitles = obj;
26 | return self;
27 | };
28 | }
29 |
30 | - (HoloTableViewMaker * (^)(NSInteger (^)(NSString *, NSInteger)))sectionForSectionIndexTitleHandler {
31 | return ^id(id obj) {
32 | self.tableViewModel.indexTitlesHandler = obj;
33 | return self;
34 | };
35 | }
36 |
37 | - (HoloTableViewMaker * (^)(id))scrollDelegate {
38 | return ^id(id obj) {
39 | self.tableViewModel.scrollDelegate = obj;
40 | return self;
41 | };
42 | }
43 |
44 | - (HoloTableViewMaker * (^)(id))delegate {
45 | return ^id(id obj) {
46 | self.tableViewModel.delegate = obj;
47 | return self;
48 | };
49 | }
50 |
51 | - (HoloTableViewMaker * (^)(id))dataSource {
52 | return ^id(id obj) {
53 | self.tableViewModel.dataSource = obj;
54 | return self;
55 | };
56 | }
57 |
58 | - (HoloTableViewModel *)install {
59 | return self.tableViewModel;
60 | }
61 |
62 | #pragma mark - getter
63 | - (HoloTableViewModel *)tableViewModel {
64 | if (!_tableViewModel) {
65 | _tableViewModel = [HoloTableViewModel new];
66 | }
67 | return _tableViewModel;
68 | }
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Update/HoloTableViewUpdateRowMaker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewUpdateRowMaker.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/29.
6 | //
7 |
8 | #import
9 | @class HoloTableRow, HoloTableRowMaker, HoloTableSection;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | typedef NS_ENUM(NSInteger, HoloTableViewUpdateRowMakerType) {
14 | HoloTableViewUpdateRowMakerTypeUpdate,
15 | HoloTableViewUpdateRowMakerTypeRemake
16 | };
17 |
18 | @interface HoloTableViewUpdateRowMaker : NSObject
19 |
20 | /**
21 | * Fetch a HoloTableRow object with the tag.
22 | */
23 | @property (nonatomic, copy, readonly) HoloTableRowMaker *(^tag)(NSString *tag);
24 |
25 | - (instancetype)initWithProxyDataSections:(NSArray *)sections
26 | makerType:(HoloTableViewUpdateRowMakerType)makerType
27 | targetSection:(BOOL)targetSection
28 | sectionTag:(NSString * _Nullable)sectionTag;
29 |
30 | - (NSArray *)install;
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
35 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Maker/Update/HoloTableViewUpdateRowMaker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HoloTableViewUpdateRowMaker.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/7/29.
6 | //
7 |
8 | #import "HoloTableViewUpdateRowMaker.h"
9 | #import "HoloTableRow.h"
10 | #import "HoloTableRowMaker.h"
11 | #import "HoloTableSection.h"
12 | #import "HoloTableViewMacro.h"
13 |
14 | @interface HoloTableViewUpdateRowMaker ()
15 |
16 | @property (nonatomic, copy) NSArray *dataSections;
17 |
18 | @property (nonatomic, assign) HoloTableViewUpdateRowMakerType makerType;
19 |
20 | @property (nonatomic, strong) NSMutableArray *updateIndexPaths;
21 |
22 | // has target section or not
23 | @property (nonatomic, assign) BOOL targetSection;
24 | // target section tag
25 | @property (nonatomic, copy) NSString *sectionTag;
26 |
27 | @end
28 |
29 | @implementation HoloTableViewUpdateRowMaker
30 |
31 | - (instancetype)initWithProxyDataSections:(NSArray *)sections
32 | makerType:(HoloTableViewUpdateRowMakerType)makerType
33 | targetSection:(BOOL)targetSection
34 | sectionTag:(NSString * _Nullable)sectionTag {
35 | self = [super init];
36 | if (self) {
37 | _dataSections = sections;
38 | _makerType = makerType;
39 | _targetSection = targetSection;
40 | _sectionTag = sectionTag;
41 | }
42 | return self;
43 | }
44 |
45 | - (HoloTableRowMaker *(^)(NSString *))tag {
46 | return ^id(NSString *tag) {
47 | HoloTableRowMaker *rowMaker = [HoloTableRowMaker new];
48 | HoloTableRow *makerRow = [rowMaker fetchTableRow];
49 | makerRow.tag = tag;
50 |
51 | __block NSIndexPath *operateIndexPath = nil;
52 | [self.dataSections enumerateObjectsUsingBlock:^(HoloTableSection * _Nonnull section, NSUInteger sectionIdx, BOOL * _Nonnull sectionStop) {
53 | if (self.targetSection && !([section.tag isEqualToString:self.sectionTag] || (!section.tag && !self.sectionTag))) {
54 | return;
55 | }
56 | [section.rows enumerateObjectsUsingBlock:^(HoloTableRow * _Nonnull row, NSUInteger rowIdx, BOOL * _Nonnull rowStop) {
57 | if ([row.tag isEqualToString:tag] || (!row.tag && !tag)) {
58 | operateIndexPath = [NSIndexPath indexPathForRow:rowIdx inSection:sectionIdx];
59 |
60 | if (self.makerType == HoloTableViewUpdateRowMakerTypeUpdate) {
61 | // update: set the row object to maker from datasource
62 | [rowMaker giveTableRow:row];
63 | } else if (self.makerType == HoloTableViewUpdateRowMakerTypeRemake) {
64 | // remake: set the row object to datasource from maker
65 | NSMutableArray *rows = [NSMutableArray arrayWithArray:section.rows];
66 | [rows replaceObjectAtIndex:operateIndexPath.row withObject:makerRow];
67 | section.rows = rows.copy;
68 | }
69 |
70 | *rowStop = YES;
71 | *sectionStop = YES;
72 | }
73 | }];
74 | }];
75 |
76 | if (operateIndexPath) {
77 | [self.updateIndexPaths addObject:operateIndexPath];
78 | } else {
79 | HoloLog(@"[HoloTableView] No row found with the tag: `%@`.", tag);
80 | }
81 |
82 | return rowMaker;
83 | };
84 | }
85 |
86 | - (NSArray *)install {
87 | return self.updateIndexPaths.copy;
88 | }
89 |
90 | #pragma mark - getter
91 | - (NSMutableArray *)updateIndexPaths {
92 | if (!_updateIndexPaths) {
93 | _updateIndexPaths = [NSMutableArray new];
94 | }
95 | return _updateIndexPaths;
96 | }
97 |
98 | @end
99 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Responder Event/UIResponder+HoloEvent.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIResponder+HoloEvent.h
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/8/24.
6 | //
7 |
8 | #import
9 |
10 | @interface UIResponder (HoloEvent)
11 |
12 | - (void)holo_event:(NSString *)event params:(NSDictionary *)params;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/HoloTableView/Classes/Responder Event/UIResponder+HoloEvent.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIResponder+HoloEvent.m
3 | // HoloTableView
4 | //
5 | // Created by 与佳期 on 2019/8/24.
6 | //
7 |
8 | #import "UIResponder+HoloEvent.h"
9 |
10 | @implementation UIResponder (HoloEvent)
11 |
12 | - (void)holo_event:(NSString *)event params:(NSDictionary *)params {
13 | [self.nextResponder holo_event:event params:params];
14 | }
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 gonghonglou
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HoloTableView
2 |
3 | [](https://travis-ci.org/HoloFoundation/HoloTableView)
4 | [](https://cocoapods.org/pods/HoloTableView)
5 | [](https://cocoapods.org/pods/HoloTableView)
6 | [](https://cocoapods.org/pods/HoloTableView)
7 |
8 |
9 | `HoloTableView` provides chained syntax calls that encapsulate delegate methods for `UITableView`. The delegate methods for `UITableView` are distributed to each `cell`, each `cell` having its own method for setting Class, model, height, and click event, etc.
10 |
11 |
12 | ## Features
13 |
14 | - [x] Provide section and row maker to handle proxy events of `UITableVIew`.
15 | - [x] Provide protocols, implemented in cells, headers and footers to handle proxy events of `UITableVIew`.
16 | - [x] Provide left-slide and right-slide actions for `cell`.
17 | - [x] Passing events through the responder chain.
18 | - [x] [HoloTableViewMGPlugin](https://github.com/HoloFoundation/HoloTableViewMGPlugin) to support `MGSwipeTableCell`, add swip actions for `cell`.
19 | - [x] Diff reload data. [HoloTableViewDiffPlugin](https://github.com/HoloFoundation/HoloTableViewDiffPlugin) to support `DeepDiff`
20 | - [x] Support to reload a table view by setting datasource with `HoloTableSection` and `HoloTableRow`.
21 | - [ ] Modern Objective-C and better Swift support.
22 |
23 |
24 | ## Example
25 |
26 | To run the example project, clone the repo, and run `pod install` from the Example directory first.
27 |
28 |
29 | ## Integration with 3rd party libraries
30 |
31 | - [HoloTableViewMGPlugin](https://github.com/HoloFoundation/HoloTableViewMGPlugin) - plugin to support [MGSwipeTableCell](https://github.com/MortimerGoro/MGSwipeTableCell), add swip actions for `cell`. `MGSwipeTableCell` is an easy to use `UITableViewCell` subclass that allows to display swipeable buttons with a variety of transitions.
32 | - [HoloTableViewDiffPlugin](https://github.com/HoloFoundation/HoloTableViewDiffPlugin) - plugin to support [DeepDiff](https://github.com/onmyway133/DeepDiff), diff reload a section of `UITableView`. `DeepDiff` tells the difference between 2 collections and the changes as edit steps.
33 |
34 | ## Usage
35 |
36 | [中文介绍](https://github.com/HoloFoundation/HoloTableView/blob/master/README_CN.md)、[文章介绍](http://gonghonglou.com/2020/08/10/HoloTableView-HoloCollectionView/)
37 |
38 | ### 1. Make a simple cell list
39 |
40 | ```objc
41 | UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
42 | [self.view addSubview:tableView];
43 |
44 | [tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
45 | // make a cell
46 | make.row(ExampleTableViewCell.class).model(NSDictionary.new).height(44);
47 |
48 | // make a list
49 | for (NSObject *obj in NSArray.new) {
50 | make.row(ExampleTableViewCell.class).model(obj).didSelectHandler(^(id _Nullable model) {
51 | NSLog(@"did select row : %@", model);
52 | });
53 | }
54 | }];
55 |
56 | [tableView reloadData];
57 |
58 | // etc.
59 | ```
60 |
61 | The `holo_makeRows:` method is used to create a list of rows **with a default section**. Each `row` is a `cell`. **More properties provided for row see: [HoloTableViewRowMaker.h](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/Row/HoloTableViewRowMaker.h) and [HoloTableRowMaker.h](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/Row/HoloTableRowMaker.h)**
62 |
63 |
64 | #### Requirements for cell
65 |
66 | Conforms to protocol `HoloTableViewCellProtocol`, `HoloTableView` will automatically identify `cell` whether implement these methods and calls, the commonly used two methods:
67 |
68 | ```objc
69 | @required
70 |
71 | // set the model to cell
72 | // the model is the object passed in by make.model()
73 | - (void)holo_configureCellWithModel:(id)model;
74 |
75 |
76 | @optional
77 |
78 | // return cell height( Priority is higher than: 'heightHandler' and 'height' of maker)
79 | // the model is the object passed in by make.model()
80 | + (CGFloat)holo_heightForCellWithModel:(id)model;
81 | ```
82 |
83 | **See `HoloTableViewCellProtocol` more methods: [HoloTableViewCellProtocol](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Core/Protocol/HoloTableViewCellProtocol.h)**
84 |
85 | You can also call your own methods by configuring properties such as `configSEL`, `heightSEL`, etc. More properties can find in [HoloTableRowMaker.h](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/Row/HoloTableRowMaker.h).
86 |
87 | Note that attributes such as `height`, `estimatedHeight`, etc. that exist `SEL` have priority:
88 | 1. First judge whether `cell` implements `heightSEL` method
89 | 2. Secondly, verify the implementation of the `heightHandler` block
90 | 3. Finally, determine whether the property `height` is assigned
91 |
92 |
93 | ### 2. Make a section list (contain header, footer, row)
94 |
95 | ```objc
96 | UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
97 | [self.view addSubview:tableView];
98 |
99 | [tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
100 | make.section(TAG)
101 | .header(ExampleHeaderView.class)
102 | .headerModel(NSDictionary.new)
103 | .footer(ExampleFooterView.class)
104 | .footerModel(NSDictionary.new)
105 | .makeRows(^(HoloTableViewRowMaker * _Nonnull make) {
106 | // make a cell
107 | make.row(ExampleTableViewCell.class).model(NSDictionary.new).height(44);
108 |
109 | // make a list
110 | for (NSObject *obj in NSArray.new) {
111 | make.row(ExampleTableViewCell.class).model(obj).didSelectHandler(^(id _Nullable model) {
112 | NSLog(@"did select row : %@", model);
113 | });
114 | }
115 | });
116 | }];
117 |
118 | [tableView reloadData];
119 | ```
120 |
121 | The `holo_makeSections:` method is used to create a list of `section`. **More properties provided for section see: [HoloTableViewSectionMaker.h](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/Section/HoloTableViewSectionMaker.h) and [HoloTableSectionMaker.h](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/Section/HoloTableSectionMaker.h)**
122 |
123 |
124 | #### Requirements for header and footer
125 |
126 | 1. header: conforms to protocol `HoloTableViewHeaderProtocol` , implement these methods, the commonly used two methods:
127 |
128 | ```objc
129 | @required
130 |
131 | // set the model to header
132 | // the model is the object passed in by make.headerModel()
133 | - (void)holo_configureHeaderWithModel:(id)model;
134 |
135 | @optional
136 |
137 | // return header height( Priority is higher than: 'headerHeightHandler' and 'headerHeight' of maker)
138 | // the model is the object passed in by make.headerModel()
139 | + (CGFloat)holo_heightForHeaderWithModel:(id)model;
140 | ```
141 |
142 | 2. Footer: conforms to protocol `HoloTableViewFooterProtocol` , implement these methods, the commonly used two methods:
143 |
144 | ```objc
145 | @required
146 |
147 | // set the model to footer
148 | // the model is the object passed in by make.footerModel()
149 | - (void)holo_configureFooterWithModel:(id)model;
150 |
151 | @optional
152 |
153 | // return footer height( Priority is higher than: 'footerHeightHandler' and 'footerHeight' of maker)
154 | // the model is the object passed in by make.footerModel()
155 | + (CGFloat)holo_heightForFooterWithModel:(id)model;
156 | ```
157 |
158 | **See `HoloTableViewHeaderProtocol` and `HoloTableViewFooterProtocol` more methods: [HoloTableViewHeaderProtocol](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Core/Protocol/HoloTableViewHeaderProtocol.h) and [HoloTableViewFooterProtocol](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Core/Protocol/HoloTableViewFooterProtocol.h)**
159 |
160 | You can also call your own methods by configuring properties such as `headerConfigSEL`, `footerConfigSEL`, etc. More properties can find in [HoloTableSectionMaker.h](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/Section/HoloTableSectionMaker.h).
161 |
162 | Like `cell`, properties that contain `SEL` also have a priority.
163 |
164 |
165 | ### 3. Methods for section
166 |
167 | ```objc
168 | // adding
169 | [self.tableView holo_makeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
170 | make.section(TAG);
171 | }];
172 |
173 | // inserting at index
174 | [self.tableView holo_insertSectionsAtIndex:0 block:^(HoloTableViewSectionMaker * _Nonnull make) {
175 | make.section(TAG);
176 | }];
177 |
178 | // updating with tag value by maker
179 | [self.tableView holo_updateSections:^(HoloTableViewSectionMaker * _Nonnull make) {
180 | make.section(TAG);
181 | }];
182 |
183 | // resetting with tag value by maker
184 | [self.tableView holo_remakeSections:^(HoloTableViewSectionMaker * _Nonnull make) {
185 | make.section(TAG);
186 | }];
187 |
188 | // deleting
189 | [self.tableView holo_removeAllSections];
190 |
191 | // deleting with tag value
192 | [self.tableView holo_removeSections:@[TAG]];
193 |
194 |
195 | // reloadData
196 | [self.tableView reloadData];
197 | ```
198 |
199 | `UITableView+HoloTableView.h` provides a series of methods for manipulating `sections`, including adding, inserting, updating, resetting, deleting, etc.
200 | **More methods provided for section see: [UITableView+HoloTableView.h (about section)](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/UITableView%2BHoloTableView.h#L24-L144)**
201 |
202 |
203 | ### 4. Methods for row
204 |
205 | ```objc
206 | // adding
207 | [self.tableView holo_makeRows:^(HoloTableViewRowMaker * _Nonnull make) {
208 | make.row(ExampleTableViewCell.class);
209 | }];
210 |
211 | // adding to section with tag value
212 | [self.tableView holo_makeRowsInSection:TAG block:^(HoloTableViewRowMaker * _Nonnull make) {
213 | make.row(ExampleTableViewCell.class);
214 | }];
215 |
216 | // inserting at index
217 | [self.tableView holo_insertRowsAtIndex:0 block:^(HoloTableViewRowMaker * _Nonnull make) {
218 | make.row(ExampleTableViewCell.class);
219 | }];
220 |
221 | // inserting at index to section with tag value
222 | [self.tableView holo_insertRowsAtIndex:0 inSection:TAG block:^(HoloTableViewRowMaker * _Nonnull make) {
223 | make.row(ExampleTableViewCell.class);
224 | }];
225 |
226 | // updating
227 | [self.tableView holo_updateRows:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
228 | make.tag(TAG).height(120);
229 | }];
230 |
231 | // resetting
232 | [self.tableView holo_remakeRows:^(HoloTableViewUpdateRowMaker * _Nonnull make) {
233 | make.tag(TAG).model(NSDictionary.new).height(120);
234 | }];
235 |
236 | // deleting
237 | [self.tableView holo_removeAllRowsInSections:@[TAG]];
238 |
239 | // deleting
240 | [self.tableView holo_removeRows:@[TAG]];
241 |
242 |
243 | // reloadData
244 | [self.tableView reloadData];
245 | ```
246 |
247 | `UITableView+HoloTableView.h` provides a series of methods for manipulating rows, including adding, inserting, updating, resetting, deleting, etc.
248 | **More methods provided for row see: [UITableView+HoloTableView.h (about row)](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Maker/UITableView%2BHoloTableView.h#L146-L328)**
249 |
250 |
251 | ### 5. Retrieve Delegate
252 |
253 | You can retrieve the delegate of `UITableView` at any time, such as:
254 |
255 | ```objc
256 | // first way
257 | self.tableView.holo_proxy.dataSource = self;
258 | self.tableView.holo_proxy.delegate = self;
259 | self.tableView.holo_proxy.scrollDelegate = self;
260 |
261 | // second way
262 | [self.tableView holo_makeTableView:^(HoloTableViewMaker * _Nonnull make) {
263 | make.dataSource(self).delegate(self).scrollDelegate(self);
264 | }];
265 | ```
266 |
267 | Once you set up `dataSource`, `delegate`, `scrollDelegate` and implement some of their methods, `HoloTableView` will use your methods and return values first. For specific logic, please refer to: [HoloTableViewProxy.m](https://github.com/HoloFoundation/HoloTableView/blob/master/HoloTableView/Classes/Core/HoloTableViewProxy.m)
268 |
269 | ### 6. Reload a table view by setting datasource with `HoloTableSection` and `HoloTableRow`
270 |
271 | Make a section list with `HoloTableSection` and `HoloTableRow`:
272 |
273 | ```objc
274 | HoloTableSection *section = [HoloTableSection new];
275 | section.tag = TAG;
276 |
277 | section.header = ExampleHeaderView.class;
278 | section.headerModel = @{@"title":@"header"};
279 |
280 | section.footer = ExampleFooterView.class;
281 | section.footerModel = @{@"title":@"footer"};
282 | section.footerHeight = 100;
283 |
284 | NSMutableArray *rows = [NSMutableArray new];
285 | for (NSDictionary *dict in self.modelArray) {
286 | HoloTableRow *row = [HoloTableRow new];
287 | row.cell = ExampleTableViewCell.class;
288 | row.model = dict;
289 | [rows addObject:row];
290 | }
291 | section.rows = rows;
292 |
293 | self.tableView.holo_sections = @[section];
294 | [self.tableView reloadData];
295 | ```
296 |
297 |
298 | ## Installation
299 |
300 | HoloTableView is available through [CocoaPods](https://cocoapods.org). To install
301 | it, simply add the following line to your Podfile:
302 |
303 | ```ruby
304 | pod 'HoloTableView'
305 | ```
306 |
307 | ## Author
308 |
309 | gonghonglou, gonghonglou@icloud.com
310 |
311 | ## License
312 |
313 | HoloTableView is available under the MIT license. See the LICENSE file for more info.
314 |
315 |
316 |
--------------------------------------------------------------------------------