MTZTableViewManager is a powerful framework that allows you to create table views in a descriptive way, by specifying rows and sections without having to bother with indexes. It also provides a set of tools for creating forms and handling their input, applying masks, performing validations and converting to and from complex objects.
- Make sure to pick the right tag (
1.2.0at the moment). - Drop the file
MTZTableViewManager.xcodeprojinside your Xcode project. - Make sure your submodules are up-to-date.
- Drag the
MTZTableViewManager.framework(underProducts) to your targetLinked Frameworks and Librariesarea.
You can also declare the following on your Podfile:
pod 'MTZTableViewManager', '~> 1.2.0'Note that this will also add MTZExpirationDatePicker as a pod dependency.
Getting started is fairly simple. Just declare a strongly-held MTZTableManager somewhere:
@property (nonatomic) MTZTableManager *tableManager;Then declare your rows, sections and finally the data. Using a custom UITableViewCell subclass is recommended.
MTZTableRow *row = [[MTZTableRow alloc] initWithClass:[MyCustomCell class]
action:^(NSIndexPath * _Nonnull indexPath, id<MTZModel> model) {
NSLog(@"Tap!");
}];
MTZTableSection *section = [[MTZTableSection alloc] initWithTableRows:@[row]];
MTZTableData *data = [[MTZTableData alloc] initWithTableSections:@[section]];
self.tableManager = [[MTZTableManager alloc] initWithTableView:self.tableView tableData:data];And you're good to go! Please note you cannot be the tableViews delegate or data source while using MTZTableManager.
- You can also provide a regular and/or expanded height to a row, and it will toggle between them upon selection.
- You can also hide rows or sections dinamically, just set the
hiddenproperty. - You can instantiate cells using
nibs as well. Likewise you can provide custom headers and footers classes for every section.
To declare an object as a possible model, just conform it to MTZModel:
@interface MyCustomCellModel: NSObject <MTZModel>
@property (nonatomic) NSString *text;
@endCells can then be configured to display information. Simply conform the cell you want to MTZModelDisplaying and implement the required method:
@interface MyCustomCell: UITableViewCell <MTZModelDisplaying>
@end
@implementation MyCustomCell
- (void)configureWithModel:(id<MTZModel>)model {
self.textLabel.text = ((MyCustomCellModel *)model).text;
}
@end- Sections can also have models, and they're provided to custom headers/footers, if any, as long as their classes also conform to
MTZModelDisplaying.
Form objects are objects that can be manipulated by a form generated by MTZTableViewManager. Ideally, you want to make all of its properties read-only to avoid external mutation, since the form elements will modify the values directly via KVO. If you're using Swift. Don't forget the dynamic keyword for that! Make sure the object conforms to MTZFormObject:
@interface MyCustomFormObject: NSObject <MTZFormObject>
@property (nonatomic, readonly) NSString *title;
@property (nonatomic, readonly) NSDate *date;
@property (nonatomic, readonly) MyCustomUser *user;
@endFor a cell to be compatible with a form, it needs to conform with MTZFormEditing and implement the required method:
@interface MyCustomTextFieldCell: UITableViewCell <MTZFormEditing>
@property (nonatomic) UITextField *textField;
@end
@implementation MyCustomTextFieldCell
// ...
- (UIControl<MTZFormField> *)fieldForFormObject {
return self.textField;
}
@end- Note that the form fields must conform to
MTZFormField. The framework already provides a default implementation forUITextField,UITextView,UISwitchandUIStepper.
Form fields automatically provide you with inputAccessoryView for jumping between other fields within the same section. To localise the buttons on the framework-provided input accessory view, simply add the following entries to your Localizable.strings, replacing the translations to whatever fits your needs:
"mtz_prev" = "Prev";
"mtz_next" = "Next";
"mtz_done" = "Done";- If the keyboard provides a return button, the "Done" button is ommitted.
Dates are a special topic. Due to that, if you want to interact with a NSDate key path, use MTZTableFormDateRow instead:
MTZTableFormDateRow *dateRow = [[MTZTableFormDateRow alloc] initWithClass:[MyCustomTextFieldCell class]
formObject:self.formObject
keyPath:CLASSKEY(MyCustomFormObject, date)];
dateRow.minimumDate = [NSDate date];
dateRow.maximumDate = [[NSDate date] dateByAddingTimeInterval:60*60*24*15];
dateRow.datePickerMode = MTZDatePickerModeDateAndTime;MTZTableFormDateRowmust also useUITextFieldas a form field, as we replace theinputViewwith the adequate picker.- You can also use
MTZDatePickerModeExpirationDateas a picker mode, and it will use theMTZExpirationDatePickerasinputView.
If you want to provide a set of options, do so by conforming the type of object you want to provide as an option to MTZFormOption:
@interface MyCustomUser: NSObject <MTZFormOption>
@property (nonatomic) NSInteger ID;
@property (nonatomic) NSString *email;
- (instancetype)initWithID:(NSInteger)ID email:(NSString *)email;
@end
@implementation MyCustomUser
// ...
- (NSString *)optionDescription {
return self.email;
}
- (BOOL)isEqual:(MyCustomUser *)object {
return self.ID == object.ID;
}
@endThen set the availableOptions property on the MTZTableFormOptionRow:
NSArray *allUsers = @[[[MyCustomUser alloc] initWithID:1 email:@"a@b.com"],
[[MyCustomUser alloc] initWithID:2 email:@"b@c.com"],
[[MyCustomUser alloc] initWithID:3 email:@"c@d.com"]];
MTZTableFormOptionRow *userRow = [[MTZTableFormOptionRow alloc] initWithClass:[MyCustomTextFieldCell class]
formObject:self.formObject
keyPath:CLASSKEY(MyCustomFormObject, user)];
userRow.availableOptions = allUsers;- If you set available options, you must also use
UITextFieldas a form field, as we replace theinputViewwith the adequate picker. - Make sure you provide a valid implementation of
isEqual:to yourMTZFormOptionobject.
TBA
TBA
Maskers allow UITextFields to have their input:
- limited to an specific amount of characters;
- limited to an specific set of characters;
- appended with placeholders in specific indexes (i.e.: Dots every 4 digits: 1234.1234.1234.1234).
Simply subclass MTZTextFieldMasker and implement the desired methods:
@interface MyMasker : MTZTextFieldMasker
@end
// .m
@implementation MyMasker
- (NSCharacterSet *)allowedCharacterSet {
return [NSCharacterSet decimalDigitCharacterSet]; // only digits
}
- (NSInteger)maximumInputLength {
return 21; // i.e.: card number + spaces
}
- (NSString *)stringToAppendAtIndex:(NSInteger)index
ofString:(NSString *)currentString {
if (index % 4 == 0) {
return @" "; // add space every 4 digits.
}
return nil;
}
@endThen set the masker property to a MTZTableFormRow that uses an UITextField:
MTZTableFormRow *cardNumberRow = [[MTZTableFormRow alloc] initWithNib:myTextFieldCellNib
formObject:myFormObject
keyPath:CLASSKEY(MyFormObjectClass, cardNumber)];
cardNumberRow.masker = [MyMasker new];- All masker methods are optional.
- As mentioned, this requires an
UITextFieldto work properly.
TBA
MTZTableViewManager is released under the MIT license. See LICENSE for details.
