Files
keyboard/keyBoard/Class/AiTalk/VC/AIReportVC.m
2026-02-02 17:07:46 +08:00

645 lines
24 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// AIReportVC.m
// keyBoard
//
// Created by Mac on 2026/1/29.
//
#import "AIReportVC.h"
#import "AiVM.h"
#pragma mark - AIReportOptionCell
@interface AIReportOptionCell : UITableViewCell
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *selectButton;
@property (nonatomic, assign) BOOL isSelectedOption;
@end
@implementation AIReportOptionCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.backgroundColor = [UIColor clearColor];
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self setupUI];
}
return self;
}
- (void)setupUI {
[self.contentView addSubview:self.titleLabel];
[self.contentView addSubview:self.selectButton];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).offset(16);
make.centerY.equalTo(self.contentView);
make.right.lessThanOrEqualTo(self.selectButton.mas_left).offset(-10);
}];
[self.selectButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.contentView).offset(-16);
make.centerY.equalTo(self.contentView);
make.width.height.mas_equalTo(24);
}];
}
- (void)setIsSelectedOption:(BOOL)isSelectedOption {
_isSelectedOption = isSelectedOption;
self.selectButton.selected = isSelectedOption;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = [UIFont systemFontOfSize:14];
_titleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
}
return _titleLabel;
}
- (UIButton *)selectButton {
if (!_selectButton) {
_selectButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_selectButton setImage:[UIImage imageNamed:@"report_nor_icon"] forState:UIControlStateNormal];
[_selectButton setImage:[UIImage imageNamed:@"report_sel_icon"] forState:UIControlStateSelected];
_selectButton.userInteractionEnabled = NO;
}
return _selectButton;
}
@end
#pragma mark - AIReportVC
@interface AIReportVC () <UITableViewDelegate, UITableViewDataSource, UITextViewDelegate>
/// 滚动容器
@property (nonatomic, strong) UIScrollView *scrollView;
/// 内容容器
@property (nonatomic, strong) UIView *contentView;
/// 举报原因卡片
@property (nonatomic, strong) UIView *reasonCardView;
/// 举报原因标题
@property (nonatomic, strong) UILabel *reasonTitleLabel;
/// 举报原因列表
@property (nonatomic, strong) UITableView *reasonTableView;
/// 举报原因数据
@property (nonatomic, strong) NSArray<NSString *> *reportReasons;
/// 选中的举报原因索引集合
@property (nonatomic, strong) NSMutableSet<NSNumber *> *selectedReasonIndexes;
/// 选择内容卡片
@property (nonatomic, strong) UIView *contentCardView;
/// 选择内容标题
@property (nonatomic, strong) UILabel *contentTitleLabel;
/// 选择内容列表
@property (nonatomic, strong) UITableView *contentTableView;
/// 选择内容数据
@property (nonatomic, strong) NSArray<NSString *> *contentOptions;
/// 选中的内容索引集合
@property (nonatomic, strong) NSMutableSet<NSNumber *> *selectedContentIndexes;
/// 举报描述卡片
@property (nonatomic, strong) UIView *descriptionCardView;
/// 举报描述标题
@property (nonatomic, strong) UILabel *descriptionTitleLabel;
/// 举报描述输入框
@property (nonatomic, strong) UITextView *descriptionTextView;
/// 占位符标签
@property (nonatomic, strong) UILabel *placeholderLabel;
/// 字数统计标签
@property (nonatomic, strong) UILabel *countLabel;
/// 提交按钮
@property (nonatomic, strong) UIButton *submitButton;
@property (nonatomic, strong) AiVM *viewModel;
@end
@implementation AIReportVC
#pragma mark - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
self.kb_titleLabel.text = KBLocalized(@"Report");
/// 1初始化数据
[self initData];
/// 2控件初始化
[self setupUI];
/// 3绑定事件
[self bindActions];
/// 4其他通知/键盘等)
[self bindKeyboardNotifications];
}
#pragma mark - 1初始化数据
- (void)initData {
self.reportReasons = @[
KBLocalized(@"Pornographic And Vulgar"),
KBLocalized(@"Politically Sensitive"),
KBLocalized(@"Insult Attacks"),
KBLocalized(@"Bloody Violence"),
KBLocalized(@"Suicide And Self Harm"),
KBLocalized(@"Plagiarism Infringement"),
KBLocalized(@"Invasion Of Privacy"),
KBLocalized(@"False Rumor"),
KBLocalized(@"Other Harmful Information")
];
self.contentOptions = @[
KBLocalized(@"Character Name And Description"),
KBLocalized(@"Picture"),
KBLocalized(@"Timbre")
];
self.selectedReasonIndexes = [NSMutableSet set];
self.selectedContentIndexes = [NSMutableSet set];
}
#pragma mark - 2控件初始化
- (void)setupUI {
// 先添加提交按钮(因为 scrollView 的约束依赖它)
[self.view addSubview:self.submitButton];
[self.submitButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(40);
make.right.equalTo(self.view).offset(-40);
make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM - 20);
make.height.mas_equalTo(50);
}];
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.contentView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.kb_navView.mas_bottom);
make.left.right.equalTo(self.view);
make.bottom.equalTo(self.submitButton.mas_top).offset(-10);
}];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
make.width.equalTo(self.scrollView);
}];
// 举报原因卡片
[self.contentView addSubview:self.reasonCardView];
[self.reasonCardView addSubview:self.reasonTitleLabel];
[self.reasonCardView addSubview:self.reasonTableView];
[self.reasonCardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView).offset(16);
make.left.equalTo(self.contentView).offset(16);
make.right.equalTo(self.contentView).offset(-16);
}];
[self.reasonTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.reasonCardView).offset(16);
make.centerX.equalTo(self.reasonCardView);
}];
CGFloat reasonTableHeight = self.reportReasons.count * 44;
[self.reasonTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.reasonTitleLabel.mas_bottom).offset(8);
make.left.right.equalTo(self.reasonCardView);
make.height.mas_equalTo(reasonTableHeight);
make.bottom.equalTo(self.reasonCardView).offset(-8);
}];
// 选择内容卡片
[self.contentView addSubview:self.contentCardView];
[self.contentCardView addSubview:self.contentTitleLabel];
[self.contentCardView addSubview:self.contentTableView];
[self.contentCardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.reasonCardView.mas_bottom).offset(16);
make.left.equalTo(self.contentView).offset(16);
make.right.equalTo(self.contentView).offset(-16);
}];
[self.contentTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentCardView).offset(16);
make.centerX.equalTo(self.contentCardView);
}];
CGFloat contentTableHeight = self.contentOptions.count * 44;
[self.contentTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentTitleLabel.mas_bottom).offset(8);
make.left.right.equalTo(self.contentCardView);
make.height.mas_equalTo(contentTableHeight);
make.bottom.equalTo(self.contentCardView).offset(-8);
}];
// 举报描述卡片
[self.contentView addSubview:self.descriptionCardView];
[self.descriptionCardView addSubview:self.descriptionTitleLabel];
[self.descriptionCardView addSubview:self.descriptionTextView];
[self.descriptionCardView addSubview:self.placeholderLabel];
[self.descriptionCardView addSubview:self.countLabel];
[self.descriptionCardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentCardView.mas_bottom).offset(16);
make.left.equalTo(self.contentView).offset(16);
make.right.equalTo(self.contentView).offset(-16);
make.bottom.equalTo(self.contentView).offset(-16);
}];
[self.descriptionTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.descriptionCardView).offset(16);
make.centerX.equalTo(self.descriptionCardView);
}];
[self.descriptionTextView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.descriptionTitleLabel.mas_bottom).offset(12);
make.left.equalTo(self.descriptionCardView).offset(12);
make.right.equalTo(self.descriptionCardView).offset(-12);
make.height.mas_equalTo(100);
make.bottom.equalTo(self.descriptionCardView).offset(-30);
}];
[self.placeholderLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.descriptionTextView).offset(8);
make.left.equalTo(self.descriptionTextView).offset(5);
make.right.equalTo(self.descriptionTextView).offset(-5);
}];
[self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.descriptionCardView).offset(-16);
make.bottom.equalTo(self.descriptionCardView).offset(-8);
}];
}
#pragma mark - 3绑定事件
- (void)bindActions {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
tap.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tap];
}
- (void)dismissKeyboard {
[self.view endEditing:YES];
}
#pragma mark - 4键盘处理
- (void)bindKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleKeyboardWillChange:)
name:UIKeyboardWillChangeFrameNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleKeyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)handleKeyboardWillChange:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo ?: @{};
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
NSInteger curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGRect endFrameInView = [self.view convertRect:endFrame fromView:nil];
CGFloat keyboardHeight = MAX(0, CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(endFrameInView));
UIEdgeInsets inset = self.scrollView.contentInset;
inset.bottom = keyboardHeight;
UIViewAnimationOptions options = (UIViewAnimationOptions)(curve << 16);
[UIView animateWithDuration:duration delay:0 options:options animations:^{
self.scrollView.contentInset = inset;
self.scrollView.scrollIndicatorInsets = inset;
if ([self.descriptionTextView isFirstResponder]) {
CGRect rect = [self.descriptionTextView convertRect:self.descriptionTextView.bounds toView:self.scrollView];
rect = CGRectInset(rect, 0, -12);
[self.scrollView scrollRectToVisible:rect animated:NO];
}
} completion:nil];
}
- (void)handleKeyboardWillHide:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo ?: @{};
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
NSInteger curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIViewAnimationOptions options = (UIViewAnimationOptions)(curve << 16);
[UIView animateWithDuration:duration delay:0 options:options animations:^{
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
} completion:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.reasonTableView) {
return self.reportReasons.count;
} else {
return self.contentOptions.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AIReportOptionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AIReportOptionCell" forIndexPath:indexPath];
if (tableView == self.reasonTableView) {
cell.titleLabel.text = self.reportReasons[indexPath.row];
cell.isSelectedOption = [self.selectedReasonIndexes containsObject:@(indexPath.row)];
} else {
cell.titleLabel.text = self.contentOptions[indexPath.row];
cell.isSelectedOption = [self.selectedContentIndexes containsObject:@(indexPath.row)];
}
return cell;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableSet *selectedSet;
if (tableView == self.reasonTableView) {
selectedSet = self.selectedReasonIndexes;
} else {
selectedSet = self.selectedContentIndexes;
}
NSNumber *indexNum = @(indexPath.row);
if ([selectedSet containsObject:indexNum]) {
[selectedSet removeObject:indexNum];
} else {
[selectedSet addObject:indexNum];
}
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 44;
}
#pragma mark - UITextViewDelegate
- (void)textViewDidChange:(UITextView *)textView {
self.placeholderLabel.hidden = textView.text.length > 0;
// 限制 200 字
if (textView.text.length > 200) {
textView.text = [textView.text substringToIndex:200];
}
self.countLabel.text = [NSString stringWithFormat:@"%ld/200", (long)textView.text.length];
}
#pragma mark - Actions
- (void)submitButtonTapped {
if (self.personaId <= 0) {
[KBHUD showError:KBLocalized(@"Invalid parameter")];
return;
}
if (self.selectedReasonIndexes.count == 0) {
[KBHUD showError:KBLocalized(@"Please select at least one report reason")];
return;
}
if (self.selectedContentIndexes.count == 0) {
[KBHUD showError:KBLocalized(@"Please select at least one content type")];
return;
}
// 收集选中的举报原因
NSMutableArray *selectedReasons = [NSMutableArray array];
for (NSNumber *index in self.selectedReasonIndexes) {
[selectedReasons addObject:self.reportReasons[index.integerValue]];
}
// 收集选中的内容类型
NSMutableArray *selectedContents = [NSMutableArray array];
for (NSNumber *index in self.selectedContentIndexes) {
[selectedContents addObject:self.contentOptions[index.integerValue]];
}
NSString *reportDesc = [self.descriptionTextView.text ?: @"" stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(@"[AIReportVC] 举报人设 ID: %ld", (long)self.personaId);
NSLog(@"[AIReportVC] 举报原因: %@", selectedReasons);
NSLog(@"[AIReportVC] 内容类型: %@", selectedContents);
NSLog(@"[AIReportVC] 描述: %@", reportDesc);
// 组装举报类型(从上到下 1-12举报原因 1-9内容类型 10-12
NSMutableArray<NSNumber *> *reportTypes = [NSMutableArray array];
NSArray<NSNumber *> *sortedReasonIndexes = [[self.selectedReasonIndexes allObjects]
sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]]];
for (NSNumber *index in sortedReasonIndexes) {
NSInteger type = index.integerValue + 1;
if (type > 0) {
[reportTypes addObject:@(type)];
}
}
NSArray<NSNumber *> *sortedContentIndexes = [[self.selectedContentIndexes allObjects]
sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]]];
for (NSNumber *index in sortedContentIndexes) {
NSInteger type = self.reportReasons.count + index.integerValue + 1;
if (type > 0) {
[reportTypes addObject:@(type)];
}
}
[KBHUD show];
__weak typeof(self) weakSelf = self;
[self.viewModel reportCompanionWithCompanionId:self.personaId
reportTypes:reportTypes
reportDesc:reportDesc
chatContext:nil
evidenceImageUrl:nil
completion:^(BOOL success, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
[KBHUD dismiss];
if (!success) {
NSString *msg = error.localizedDescription ?: KBLocalized(@"Network error");
[KBHUD showError:msg];
return;
}
[KBHUD showSuccess:KBLocalized(@"Report submitted")];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.navigationController popViewControllerAnimated:YES];
});
});
}];
}
#pragma mark - Lazy Load
- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] init];
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.alwaysBounceVertical = YES;
_scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
}
return _scrollView;
}
- (UIView *)contentView {
if (!_contentView) {
_contentView = [[UIView alloc] init];
}
return _contentView;
}
- (UIView *)reasonCardView {
if (!_reasonCardView) {
_reasonCardView = [[UIView alloc] init];
_reasonCardView.backgroundColor = [UIColor whiteColor];
_reasonCardView.layer.cornerRadius = 12;
}
return _reasonCardView;
}
- (UILabel *)reasonTitleLabel {
if (!_reasonTitleLabel) {
_reasonTitleLabel = [[UILabel alloc] init];
_reasonTitleLabel.text = KBLocalized(@"Report reason");
_reasonTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
_reasonTitleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
}
return _reasonTitleLabel;
}
- (UITableView *)reasonTableView {
if (!_reasonTableView) {
_reasonTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_reasonTableView.backgroundColor = [UIColor clearColor];
_reasonTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_reasonTableView.scrollEnabled = NO;
_reasonTableView.delegate = self;
_reasonTableView.dataSource = self;
[_reasonTableView registerClass:[AIReportOptionCell class] forCellReuseIdentifier:@"AIReportOptionCell"];
}
return _reasonTableView;
}
- (UIView *)contentCardView {
if (!_contentCardView) {
_contentCardView = [[UIView alloc] init];
_contentCardView.backgroundColor = [UIColor whiteColor];
_contentCardView.layer.cornerRadius = 12;
}
return _contentCardView;
}
- (UILabel *)contentTitleLabel {
if (!_contentTitleLabel) {
_contentTitleLabel = [[UILabel alloc] init];
_contentTitleLabel.text = KBLocalized(@"selection content");
_contentTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
_contentTitleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
}
return _contentTitleLabel;
}
- (UITableView *)contentTableView {
if (!_contentTableView) {
_contentTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_contentTableView.backgroundColor = [UIColor clearColor];
_contentTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_contentTableView.scrollEnabled = NO;
_contentTableView.delegate = self;
_contentTableView.dataSource = self;
[_contentTableView registerClass:[AIReportOptionCell class] forCellReuseIdentifier:@"AIReportOptionCell"];
}
return _contentTableView;
}
- (UIView *)descriptionCardView {
if (!_descriptionCardView) {
_descriptionCardView = [[UIView alloc] init];
_descriptionCardView.backgroundColor = [UIColor whiteColor];
_descriptionCardView.layer.cornerRadius = 12;
}
return _descriptionCardView;
}
- (UILabel *)descriptionTitleLabel {
if (!_descriptionTitleLabel) {
_descriptionTitleLabel = [[UILabel alloc] init];
_descriptionTitleLabel.text = KBLocalized(@"Report description");
_descriptionTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
_descriptionTitleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
}
return _descriptionTitleLabel;
}
- (UITextView *)descriptionTextView {
if (!_descriptionTextView) {
_descriptionTextView = [[UITextView alloc] init];
_descriptionTextView.font = [UIFont systemFontOfSize:14];
_descriptionTextView.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0];
_descriptionTextView.backgroundColor = [UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0];
_descriptionTextView.layer.cornerRadius = 8;
_descriptionTextView.delegate = self;
_descriptionTextView.textContainerInset = UIEdgeInsetsMake(8, 4, 8, 4);
}
return _descriptionTextView;
}
- (UILabel *)placeholderLabel {
if (!_placeholderLabel) {
_placeholderLabel = [[UILabel alloc] init];
_placeholderLabel.text = KBLocalized(@"Please describe the specific reason for your report.");
_placeholderLabel.font = [UIFont systemFontOfSize:14];
_placeholderLabel.textColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0];
_placeholderLabel.numberOfLines = 0;
}
return _placeholderLabel;
}
- (UILabel *)countLabel {
if (!_countLabel) {
_countLabel = [[UILabel alloc] init];
_countLabel.text = @"0/200";
_countLabel.font = [UIFont systemFontOfSize:12];
_countLabel.textColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0];
}
return _countLabel;
}
- (UIButton *)submitButton {
if (!_submitButton) {
_submitButton = [UIButton buttonWithType:UIButtonTypeCustom];
_submitButton.backgroundColor = [UIColor colorWithRed:0.0 green:0.75 blue:0.67 alpha:1.0];
_submitButton.layer.cornerRadius = 25;
[_submitButton setTitle:KBLocalized(@"Submit") forState:UIControlStateNormal];
[_submitButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_submitButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
[_submitButton addTarget:self action:@selector(submitButtonTapped) forControlEvents:UIControlEventTouchUpInside];
}
return _submitButton;
}
- (AiVM *)viewModel {
if (!_viewModel) {
_viewModel = [[AiVM alloc] init];
}
return _viewModel;
}
@end