Commit 1b583525 authored by 谢卓城's avatar 谢卓城

完善:组件二进制化

parent 31fd98d7
This diff is collapsed.
//
// AppDelegate+Network.h
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#import "AppDelegate.h"
NS_ASSUME_NONNULL_BEGIN
@interface AppDelegate (Network)
- (void)networkApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
@end
NS_ASSUME_NONNULL_END
//
// AppDelegate+Network.m
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#import "AppDelegate+Network.h"
#import <NMNetwork/NMNetwork.h>
@implementation AppDelegate (Network)
- (void)networkApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NetworkManager updateBaseUrl:API_HOST];
}
@end
//
// AppDelegate+Theme.h
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#import "AppDelegate.h"
NS_ASSUME_NONNULL_BEGIN
@interface AppDelegate (Theme)
- (void)themeApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
@end
NS_ASSUME_NONNULL_END
//
// AppDelegate+Theme.m
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#import "AppDelegate+Theme.h"
#import <NMTheme/NMTheme.h>
@implementation AppDelegate (Theme)
- (void)themeApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NMThemeManager theme_application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
//
// AppDelegate+UIViewController.h
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#import "AppDelegate.h"
NS_ASSUME_NONNULL_BEGIN
@interface AppDelegate (UIViewController)
- (void)viewControllerApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
@end
NS_ASSUME_NONNULL_END
//
// AppDelegate+UIViewController.m
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#import "AppDelegate+UIViewController.h"
#import <NMCategories/NMCategories.h>
#import <QMUIKit/QMUIKit.h>
#import <NMTheme/NMTheme.h>
#import "NMRouter+CartModuleActions.h"
#import "NMRouter+HomeModuleActions.h"
@implementation AppDelegate (UIViewController)
- (void)viewControllerApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self initViewController];
[self initStyle];
[self startLaunchingAnimation];
}
- (void)initStyle {
[[UIButton appearance] setExclusiveTouch:YES];
if (@available(iOS 11.0, *)){
//[UITableView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
[UITableView appearance].estimatedRowHeight = 0;
[UITableView appearance].estimatedSectionHeaderHeight = 0;
[UITableView appearance].estimatedSectionFooterHeight = 0;
[UITableView appearance].backgroundColor = UIColor.nm_backgroundColor;
}else {
self.window.rootViewController.automaticallyAdjustsScrollViewInsets = NO;
}
}
- (void)initViewController {
UITabBarController *tab = [[UITabBarController alloc] init];
UIViewController *home = [[NMRouter sharedInstance] jyMediatorHomeViewController];
UIViewController *shopping = [[NMRouter sharedInstance] jyMediatorCartViewController];
tab.viewControllers = @[home,shopping];
self.window.rootViewController = tab;
[self.window makeKeyAndVisible];
}
- (void)startLaunchingAnimation {
UIWindow *window = self.window;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:[NSBundle mainBundle]];
UIViewController *rootVC = [storyboard instantiateInitialViewController];
UIView *launchScreenView = rootVC.view;
launchScreenView.backgroundColor = UIColor.clearColor;
//launchScreenView.frame = window.bounds;
[window addSubview:launchScreenView];
UIImageView *backgroundImageView = launchScreenView.subviews.firstObject;
backgroundImageView.clipsToBounds = YES;
/**
UIImageView *logoImageView = launchScreenView.subviews[1];
UILabel *copyrightLabel = launchScreenView.subviews.lastObject;
*/
UIView *maskView = [[UIView alloc] initWithFrame:launchScreenView.bounds];
maskView.backgroundColor = UIColor.nm_tintColor;
[launchScreenView insertSubview:maskView belowSubview:backgroundImageView];
[launchScreenView layoutIfNeeded];
[launchScreenView.constraints enumerateObjectsUsingBlock:^(__kindof NSLayoutConstraint * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@",obj.identifier);
if ([obj.identifier isEqualToString:@"bottomAlign"]) {
obj.active = NO;
[NSLayoutConstraint constraintWithItem:backgroundImageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:launchScreenView attribute:NSLayoutAttributeTop multiplier:1 constant:NavigationContentTop].active = YES;
*stop = YES;
}
}];
[UIView animateWithDuration:.15 delay:0.9 options:QMUIViewAnimationOptionsCurveOut animations:^{
[launchScreenView layoutIfNeeded];
//logoImageView.alpha = 0.0;
//copyrightLabel.alpha = 0;
} completion:nil];
[UIView animateWithDuration:1.2 delay:0.9 options:UIViewAnimationOptionCurveEaseOut animations:^{
maskView.alpha = 0;
backgroundImageView.alpha = 0;
} completion:^(BOOL finished) {
[launchScreenView removeFromSuperview];
}];
}
@end
......@@ -6,13 +6,13 @@
//
#import "AppDelegate.h"
#import "HomeViewController.h"
#import "ShoppingCartViewController.h"
#import "MacroDefinition.h"
#import "AppDelegate+Theme.h"
#import "AppDelegate+Network.h"
#import "AppDelegate+UIViewController.h"
#import <NMRouter/NMRouter.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
......@@ -21,33 +21,22 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UITabBarController *tab = [[UITabBarController alloc] init];
HomeViewController *home = [[HomeViewController alloc] init];
home.title = @"主页";
home.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"主页"
image:[UIImage imageNamed:@"index"]
selectedImage:[UIImage imageNamed:@"index_s"]];
UINavigationController* homeNav = [[UINavigationController alloc] initWithRootViewController:home];
[NMRouter setNMRouterPrefixKey:@"JY"];
ShoppingCartViewController *shopping = [[ShoppingCartViewController alloc] init];
shopping.title = @"购物车";
shopping.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"购物车"
image:[UIImage imageNamed:@"shoppingCart"]
selectedImage:[UIImage imageNamed:@"shoppingCart_s"]];
/// 网络处理
[self networkApplication:application didFinishLaunchingWithOptions:launchOptions];
[[UITabBar appearance] setTintColor:[UIColor colorWithRed:163.0f/255.0f green:46.0f/255.0f blue:46.0f/255.0f alpha:1.0f]];
/// 主题处理
[self themeApplication:application didFinishLaunchingWithOptions:launchOptions];
UINavigationController* shoppingNav = [[UINavigationController alloc] initWithRootViewController:shopping];
tab.viewControllers = @[homeNav,shoppingNav];
tab.selectedIndex = 1;
self.window.rootViewController = tab;
[self.window makeKeyAndVisible];
/// 界面
[self viewControllerApplication:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
#pragma mark - UISceneSession lifecycle
/**
......@@ -64,9 +53,4 @@
}
*/
@end
......@@ -8,7 +8,6 @@
#import "SceneDelegate.h"
#import "HomeViewController.h"
#import "ShoppingCartViewController.h"
#import "MacroDefinition.h"
@interface SceneDelegate ()
......
//
// ShoppingCartCell.h
// Mall-iOS
//
// Created by Nemo on 2020/10/13.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class GoodsModel;
@interface ShoppingCartCell : UITableViewCell
/// 商品选择
@property (nonatomic, copy) void(^selectBlock)(BOOL select);
/// 商品数量改变
@property (nonatomic, copy) void(^goodsCountChangeBlock)(NSInteger count);
@property (nonatomic, strong) GoodsModel *model;
@end
NS_ASSUME_NONNULL_END
//
// ShoppingCartCell.m
// Mall-iOS
//
// Created by Nemo on 2020/10/13.
//
#import "ShoppingCartCell.h"
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import "CounterView.h"
#import "GoodsModel.h"
@interface ShoppingCartCell ()
@property (nonatomic, strong) UIImageView *selectIv;
@property (nonatomic, strong) UIImageView *goodsIv;
@property (nonatomic, strong) UILabel *goodsNameLb;
@property (nonatomic, strong) UILabel *goodsSpecLb;
@property (nonatomic, strong) UILabel *goodsPriceLb;
@property (nonatomic, strong) CounterView *goodsCounterView;
@end
@implementation ShoppingCartCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setupUI];
}
return self;
}
- (void)setupUI {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.goodsIv.backgroundColor = [UIColor whiteColor];
self.selectIv.backgroundColor = [UIColor whiteColor];
self.goodsNameLb.text = @"";
self.goodsSpecLb.text = @"";
self.goodsPriceLb.text = @"";
self.goodsCounterView.count = 1;
}
-(void)setGoodsCountChangeBlock:(void (^)(NSInteger))goodsCountChangeBlock {
_goodsCountChangeBlock = goodsCountChangeBlock;
self.goodsCounterView.countChangeAction = goodsCountChangeBlock;
}
- (void)setModel:(GoodsModel *)model {
_model = model;
self.goodsNameLb.text = model.goodsName;
self.goodsSpecLb.text = model.goodsSpec;
self.goodsPriceLb.text = [NSString stringWithFormat:@"¥%.f",model.goodsPrice];
self.goodsCounterView.count = model.goodsCount;
self.selectIv.highlighted = model.isSelect;
}
#pragma mark -- business logic
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches]; //返回与当前接收者有关的所有的触摸对象
UITouch *touch = [allTouches anyObject]; //视图中的所有对象
CGPoint point = [touch locationInView:self];
if (CGRectContainsPoint(CGRectMake(0, 0, 35,self.bounds.size.height), point)) {
[self selectAction];
}else {
[super touchesBegan:touches withEvent:event];
}
}
- (void)selectAction {
self.selectIv.highlighted = !self.selectIv.highlighted;
!self.selectBlock ?: self.selectBlock(self.selectIv.highlighted);
}
#pragma --mark lazy load
- (CounterView *)goodsCounterView {
if (_goodsCounterView == nil) {
_goodsCounterView = [[CounterView alloc] init];
[self.contentView addSubview:_goodsCounterView];
[_goodsCounterView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.goodsIv);
make.right.equalTo(self.contentView).inset(27);
make.size.mas_equalTo(CGSizeMake(94, 30));
}];
}
return _goodsCounterView;
}
- (UILabel *)goodsPriceLb {
if (_goodsPriceLb == nil) {
_goodsPriceLb = [[UILabel alloc] init];
_goodsPriceLb.font = FONTSIZE(12);
_goodsPriceLb.textColor = RGBCOLOR(40, 40, 40);
[self.contentView addSubview:_goodsPriceLb];
[_goodsPriceLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.goodsNameLb);
make.bottom.equalTo(self.goodsIv.mas_bottom).inset(9);
}];
}
return _goodsPriceLb;
}
- (UILabel *)goodsSpecLb {
if (_goodsSpecLb == nil) {
_goodsSpecLb = [[UILabel alloc] init];
_goodsSpecLb.font = FONTSIZE(12);
_goodsSpecLb.textColor = RGBCOLOR(153, 153, 153);
[self.contentView addSubview:_goodsSpecLb];
[_goodsSpecLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.goodsNameLb);
make.top.equalTo(self.goodsNameLb.mas_bottom).offset(7);
}];
}
return _goodsSpecLb;
}
- (UILabel *)goodsNameLb {
if (_goodsNameLb == nil) {
_goodsNameLb = [[UILabel alloc] init];
_goodsNameLb.font = FONTSIZE(13);
_goodsNameLb.textColor = RGBCOLOR(33, 33, 33);
[self.contentView addSubview:_goodsNameLb];
[_goodsNameLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.goodsIv.mas_right).offset(8);
make.top.equalTo(self.goodsIv);
}];
}
return _goodsNameLb;
}
- (UIImageView *)goodsIv {
if (_goodsIv == nil) {
_goodsIv = [[UIImageView alloc] init];
_goodsIv.image = [UIImage imageNamed:@"group_portrait"];
[self.contentView addSubview:_goodsIv];
[_goodsIv mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self).inset(19);
make.left.equalTo(self.selectIv.mas_right).inset(7);
make.width.equalTo(self.goodsIv.mas_height).multipliedBy(1);
}];
}
return _goodsIv;
}
- (UIImageView *)selectIv {
if (_selectIv == nil) {
_selectIv = [[UIImageView alloc] init];
_selectIv.image = [UIImage imageNamed:@"check_f"];
_selectIv.highlightedImage = [UIImage imageNamed:@"check_t"];
[self.contentView addSubview:_selectIv];
[_selectIv mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(18);
make.centerY.equalTo(self);
make.left.mas_equalTo(11);
}];
}
return _selectIv;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//
// GoodsModel.h
// Mall-iOS
//
// Created by Nemo on 2020/10/14.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface GoodsModel : NSObject
@property (nonatomic, assign) BOOL isSelect;
/// 价格
@property (nonatomic, assign) CGFloat goodsPrice;
/// 数量
@property (nonatomic, assign) CGFloat goodsCount;
/// 图片
@property (nonatomic, copy) NSString *goodsUrl;
/// 名字
@property (nonatomic, copy) NSString *goodsName;
/// 规格
@property (nonatomic, copy) NSString *goodsSpec;
@end
NS_ASSUME_NONNULL_END
//
// GoodsModel.m
// Mall-iOS
//
// Created by Nemo on 2020/10/14.
//
#import "GoodsModel.h"
@implementation GoodsModel
@end
//
// JYTargetCartModule.h
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface JYTargetCartModule : NSObject
- (UIViewController *)jyNativeCartViewController;
@end
NS_ASSUME_NONNULL_END
//
// JYTargetCartModule.m
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#import "JYTargetCartModule.h"
#import "ShoppingCartViewController.h"
@implementation JYTargetCartModule
- (UIViewController *)jyNativeCartViewController {
ShoppingCartViewController *shopping = [[ShoppingCartViewController alloc] init];
shopping.title = @"购物车";
shopping.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"购物车"
image:[UIImage imageNamed:@"shoppingCart"]
selectedImage:[UIImage imageNamed:@"shoppingCart_s"]];
UINavigationController* shoppingNav = [[UINavigationController alloc] initWithRootViewController:shopping];
return shoppingNav;
}
@end
//
// NMRouter+CartModuleActions.h
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#if __has_include(<NMRouter/NMRouter.h>)
#import <NMRouter/NMRouter.h>
#else
#import "NMRouter.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@interface NMRouter (CartModuleActions)
- (UIViewController *)jyMediatorCartViewController;
@end
NS_ASSUME_NONNULL_END
//
// NMRouter+CartModuleActions.m
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#import "NMRouter+CartModuleActions.h"
@implementation NMRouter (CartModuleActions)
// 1. 字符串 是类名 JYXxx.h 中的 xxx 部分
NSString * const kNMMediatorCartTargetCourse = @"TargetCartModule";
// 2. 字符串是 JYxxx.h 中 定义的 jyXxx 函数名的 xxx 部分
NSString * const kNMMediatorCartActionNativToNativeCourse = @"NativeCartViewController";
- (UIViewController *)jyMediatorCartViewController {
UIViewController *viewController = [self performTarget:kNMMediatorCartTargetCourse
action:kNMMediatorCartActionNativToNativeCourse
params:nil
shouldCacheTarget:NO
];
if ([viewController isKindOfClass:[UIViewController class]]) {
// view controller 交付出去之后,可以由外界选择是push还是present
return viewController;
} else {
// 这里处理异常场景,具体如何处理取决于产品
NSLog(@"%@ 未能实例化页面", NSStringFromSelector(_cmd));
return [[UIViewController alloc] init];
}
}
@end
//
// CounterView.h
// Mall-iOS
//
// Created by Nemo on 2020/10/13.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CounterView : UIView
@property (nonatomic, assign) NSInteger count;
@property (nonatomic, copy) void(^countChangeAction)(NSInteger count);
@end
NS_ASSUME_NONNULL_END
//
// CounterView.m
// Mall-iOS
//
// Created by Nemo on 2020/10/13.
//
#import "CounterView.h"
#import <NMCategories/NMCategories.h>
#import <Masonry/Masonry.h>
#import <QMUIKit.h>
@interface CounterView()<UITextFieldDelegate>
@property (nonatomic, strong) UITextField *countTF;
@property (nonatomic, strong) UIView *keyboardConfirmView;
@property (nonatomic, strong) UIView *keyboardBackgroundView;
@property (nonatomic, strong) UIButton *confirmBtn;
@property (nonatomic, strong) UIButton *moreBtn;
@property (nonatomic, strong) UIButton *lessBtn;
@end
@implementation CounterView
- (instancetype)init
{
self = [super init];
if (self) {
[self setupUI];
}
return self;
}
- (void)setupUI {
[self.moreBtn setImage:[UIImage imageNamed:@"goods_detail_more"] forState:UIControlStateNormal];
[self.lessBtn setImage:[UIImage imageNamed:@"goods_detail_less"] forState:UIControlStateNormal];
}
- (void)keyboardWillChangeFrame:(NSNotification *)notification{
NSDictionary *userInfo = notification.userInfo;
CGFloat duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSLog(@"%f %@",duration,NSStringFromCGRect(endFrame));
if (!_keyboardBackgroundView.hidden) {
[kGetLastWindow() addSubview:self.keyboardBackgroundView];
}else{
self.keyboardBackgroundView.hidden = NO;
}
[self keyboardToolViewAnimationDistance:SCREEN_HEIGHT-44-endFrame.size.height];
}
#pragma mark -- business logic
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[KNOTE() addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillShowNotification object:nil];
return YES;;
}
- (void)inputFinishAction {
NSInteger count = [self.countTF.text integerValue];
_count = count;
!self.countChangeAction ?: self.countChangeAction(_count);
[self keyboardTapAction];
}
- (void)keyboardTapAction {
self.keyboardBackgroundView.hidden = YES;
[self.countTF resignFirstResponder];
[self keyboardToolViewAnimationDistance:SCREEN_HEIGHT-44];
[KNOTE() removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardToolViewAnimationDistance:(CGFloat)distance {
NSLog(@"%f",distance);
[UIView animateWithDuration:0.25 animations:^{
self.keyboardConfirmView.qmui_top = distance;
} completion:^(BOOL finished) { }];
}
#pragma --mark set data
- (void)setCount:(NSInteger)count {
_count = count;
self.countTF.text = [NSString stringWithFormat:@"%ld",count];
}
- (void)lessAction:(UIButton *)sender {
if (_count == 1) { return; }
_count --;
self.count = _count;
!self.countChangeAction ?: self.countChangeAction(_count);
}
- (void)moreAction:(UIButton *)sender {
_count ++;
self.count = _count;
!self.countChangeAction ?: self.countChangeAction(_count);
}
- (void)drawRect:(CGRect)rect {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(3, 3)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = rect;
maskLayer.borderWidth = 2;
maskLayer.borderColor = RGBCOLOR(221, 221, 221).CGColor;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
/**
UIBezierPath *path = [UIBezierPath qmui_bezierPathWithRoundedRect:rect cornerRadiusArray:@[@3,@3,@3,@3] lineWidth:0];
[[UIColor lightGrayColor] setFill];
[path fill];
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
layer.frame = rect;
layer.path = path.CGPath;
self.layer.mask = layer;
*/
}
#pragma mark lazy load
- (UIButton *)confirmBtn {
if (_confirmBtn == nil) {
_confirmBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[_confirmBtn setTitle:@"完成" forState:UIControlStateNormal];
[_confirmBtn addTarget:self action:@selector(inputFinishAction) forControlEvents:UIControlEventTouchUpInside];
}
return _confirmBtn;
}
- (UIView *)keyboardConfirmView {
if (_keyboardConfirmView == nil) {
_keyboardConfirmView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-44, SCREEN_WIDTH, 44)];
_keyboardConfirmView.backgroundColor = RGBCOLOR(153, 153, 153);
[self.keyboardBackgroundView addSubview:_keyboardConfirmView];
[_keyboardConfirmView addSubview:self.confirmBtn];
[_confirmBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self->_keyboardConfirmView);
make.right.equalTo(self->_keyboardConfirmView).inset(31);
}];
}
return _keyboardConfirmView;
}
- (UIView *)keyboardBackgroundView {
if (_keyboardBackgroundView == nil) {
_keyboardBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
UITapGestureRecognizer *tag =[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(keyboardTapAction)];
[_keyboardBackgroundView addGestureRecognizer:tag];
}
return _keyboardBackgroundView;
}
- (UITextField *)countTF {
if (_countTF == nil) {
_countTF = [[UITextField alloc] init];
_countTF.font = FONTSIZE(12);
_countTF.textColor = RGBCOLOR(51, 51, 51);
_countTF.textAlignment = NSTextAlignmentCenter;
_countTF.keyboardType = UIKeyboardTypeNumberPad;
_countTF.delegate = self;
[self addSubview:_countTF];
[_countTF mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.moreBtn.mas_left);
make.left.equalTo(self.lessBtn.mas_right);
make.top.bottom.equalTo(self);
}];
}
return _countTF;
}
- (UIButton *)moreBtn {
if (_moreBtn == nil) {
_moreBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_moreBtn addTarget:self action:@selector(moreAction:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_moreBtn];
[_moreBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(30);
make.right.top.equalTo(self);
}];
}
return _moreBtn;
}
- (UIButton *)lessBtn {
if (_lessBtn == nil) {
_lessBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_lessBtn addTarget:self action:@selector(lessAction:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_lessBtn];
[_lessBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(30);
make.left.top.equalTo(self);
}];
}
return _lessBtn;
}
- (void)dealloc {
self.countTF.delegate = nil;
}
@end
//
// ShoppingCartCounterView.h
// Mall-iOS
//
// Created by Nemo on 2020/10/13.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ShoppingCartCounterView : UIView
@property (nonatomic, assign) BOOL isSelectAll;
@property (nonatomic, assign) NSInteger selectCount;
@property (nonatomic, assign) CGFloat totalPrice;
@property (nonatomic, copy) void(^selectAllBlock)(BOOL isSelectAll);
@property (nonatomic, copy) void(^orderAction)(void);
@end
NS_ASSUME_NONNULL_END
//
// ShoppingCartCounterView.m
// Mall-iOS
//
// Created by Nemo on 2020/10/13.
//
#import "ShoppingCartCounterView.h"
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import <QMUIKit.h>
@interface ShoppingCartCounterView()
@property (nonatomic, strong) UIImageView *selectAllIv;
@property (nonatomic, strong) UILabel *selectCountLb;
@property (nonatomic, strong) UILabel *totalPriceLb;
@property (nonatomic, strong) UIButton *paymentBtn;
@end
@implementation ShoppingCartCounterView
- (void)setTotalPrice:(CGFloat)totalPrice {
_totalPrice = totalPrice;
self.totalPriceLb.text = [NSString stringWithFormat:@"合计:¥%.f",totalPrice];
}
- (void)setSelectCount:(NSInteger)selectCount {
_selectCount = selectCount;
NSString *count = (selectCount == 0)?@"全选":[NSString stringWithFormat:@"已选(%ld)",selectCount];
self.selectCountLb.text = count;
NSString *paymentStr = (selectCount == 0)?@"结算":[NSString stringWithFormat:@"结算(%ld)",selectCount];
[self.paymentBtn setTitle:paymentStr forState:UIControlStateNormal];
}
#pragma mark -- business logic
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches]; //返回与当前接收者有关的所有的触摸对象
UITouch *touch = [allTouches anyObject]; //视图中的所有对象
CGPoint point = [touch locationInView:self];
if (CGRectContainsPoint(CGRectMake(0, 0, 37,self.qmui_height), point)) {
[self selectAllAction];
}else {
[super touchesBegan:touches withEvent:event];
}
}
- (void)selectAllAction {
self.selectAllIv.highlighted = !self.selectAllIv.highlighted;
!self.selectAllBlock ?: self.selectAllBlock(self.selectAllIv.highlighted);
}
- (void)setIsSelectAll:(BOOL)isSelectAll {
_isSelectAll = isSelectAll;
self.selectAllIv.highlighted = isSelectAll;
}
- (void)paymentAction {
!self.orderAction ?: self.orderAction();
}
#pragma --mark lazy load
- (UILabel *)totalPriceLb {
if (_totalPriceLb == nil) {
_totalPriceLb = [[UILabel alloc] init];
_totalPriceLb.textColor = RGBCOLOR(178,37,46);
[self addSubview:_totalPriceLb];
[_totalPriceLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.paymentBtn.mas_left).inset(14);
make.centerY.equalTo(self);
}];
}
return _totalPriceLb;
}
- (UIButton *)paymentBtn {
if (_paymentBtn == nil) {
_paymentBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_paymentBtn setTitle:@"结算" forState:UIControlStateNormal];
[_paymentBtn setBackgroundColor:RGBCOLOR(178,37,46)];
[_paymentBtn setTitleColor:QMUICMI.whiteColor forState:UIControlStateNormal];
[_paymentBtn setTitleColor:QMUICMI.whiteColor forState:UIControlStateHighlighted];
[_paymentBtn addTarget:self action:@selector(paymentAction) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_paymentBtn];
[_paymentBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(49);
make.width.mas_equalTo(110);
make.right.bottom.equalTo(self);
}];
}
return _paymentBtn;
}
- (UILabel *)selectCountLb {
if (_selectCountLb == nil) {
_selectCountLb = [[UILabel alloc] init];
_selectCountLb.font = FONTSIZE(15);
[self addSubview:_selectCountLb];
[_selectCountLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.selectAllIv.mas_right).offset(10);
make.centerY.equalTo(self.selectAllIv);
}];
}
return _selectCountLb;
}
- (UIImageView *)selectAllIv {
if (_selectAllIv == nil) {
_selectAllIv = [[UIImageView alloc] init];
_selectAllIv.image = [UIImage imageNamed:@"check_f"];
_selectAllIv.highlightedImage = [UIImage imageNamed:@"check_t"];
[self addSubview:_selectAllIv];
[_selectAllIv mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(18);
make.centerY.equalTo(self);
make.left.mas_equalTo(11);
}];
}
return _selectAllIv;
}
@end
......@@ -6,8 +6,24 @@
//
#import "ShoppingCartViewController.h"
#import "ShoppingCartCounterView.h"
#import <NMReactiveCocoa/ReactiveObjC.h>
#import <QMUIKit/QMUIKit.h>
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import <NMUIChainKit/NMUIChainKit.h>
#import "ShoppingCartCell.h"
#import "GoodsModel.h"
@interface ShoppingCartViewController ()
@interface ShoppingCartViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) ShoppingCartCounterView *shoppingCounterView;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataSource;
/// 已选择的商品数组
@property (nonatomic, strong) NSMutableArray *selectGoodsSource;
@property (nonatomic, assign) CGFloat totalPrice;
@end
......@@ -16,14 +32,252 @@
- (void)viewDidLoad {
[super viewDidLoad];
[self setUp];
[self setupUI];
[self requstNewData];
}
-(void)setUp {
-(void)setupUI {
self.view.backgroundColor = [UIColor whiteColor];
self.shoppingCounterView.selectCount = 0;
self.shoppingCounterView.totalPrice = 0;
self.shoppingCounterView.isSelectAll = NO;
// [self.tableView reloadData];
}
- (void)requstNewData {
for (int i = 0; i < 7; i ++) {
GoodsModel *model = [[GoodsModel alloc] init];
model.isSelect = (i % 2) && (i < 6);
model.goodsName = [NSString stringWithFormat:@"90分户外休闲中长厚款鹅绒羽绒服 %d",i];
model.goodsSpec = [NSString stringWithFormat:@"XL;黑色 %d",i];
model.goodsUrl = @"";
model.goodsCount = i+1;
model.goodsPrice = (i + 1) * (arc4random() % 100);
[self.dataSource addObject:model];
if (model.isSelect) {
self.totalPrice += (model.goodsPrice*model.goodsCount);
[self.selectGoodsSource addObject:model];
}
}
self.title = [NSString stringWithFormat:@"购物车(%ld)",self.dataSource.count];
[self goodsChangeAction];
[self.tableView reloadData];
}
#pragma mark -- business logic
- (void)orderAction {
NSMutableString *info = [NSMutableString string];
CGFloat totalPrice = 0;
for (GoodsModel *model in self.selectGoodsSource) {
[info appendFormat:@"商品名:%@\n商品数量 :%.f\n商品价:%.f\n",model.goodsName,model.goodsCount,model.goodsPrice];
totalPrice += (model.goodsCount*model.goodsPrice);
}
[info appendFormat:@"总价:%f",totalPrice];
[QMUITips showInfo:info inView:self.view hideAfterDelay:6];
}
- (void)selectAllGood:(BOOL)isSelect {
if (!isSelect) {
[self.selectGoodsSource removeAllObjects];
self.totalPrice = 0;
for (GoodsModel *model in self.dataSource) {
model.isSelect = isSelect;
}
}else{
NSPredicate *pre = [NSPredicate predicateWithFormat:@"self.isSelect = %d",!isSelect];
NSArray *unSelectGoods = [self.dataSource filteredArrayUsingPredicate:pre];
for (GoodsModel *model in unSelectGoods) {
model.isSelect = isSelect;
self.totalPrice += (model.goodsPrice*model.goodsCount);
[self.selectGoodsSource addObject:model];
}
}
[self.tableView reloadData];
[self goodsChangeAction];
}
- (void)goodsChangeAction {
self.shoppingCounterView.selectCount = self.selectGoodsSource.count;
self.shoppingCounterView.isSelectAll = (self.dataSource.count == self.selectGoodsSource.count);
self.shoppingCounterView.totalPrice = self.totalPrice;
}
- (void)changeGoodsCount:(GoodsModel *)model count:(NSInteger)count {
if (count > 99) {
[QMUITips showError:[NSString stringWithFormat:@"超出商品:%@的库存",model.goodsName] inView:self.view hideAfterDelay:2];
NSInteger row = [self.dataSource indexOfObject:model];
if (row < self.dataSource.count) {
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationNone];
}else{
[self.tableView reloadData];
}
return;
}
if (model.isSelect) {
if (model.goodsCount > count) {
self.totalPrice -= (model.goodsPrice*(model.goodsCount - count));
}else{
self.totalPrice += (model.goodsPrice*(count - model.goodsCount));
}
self.shoppingCounterView.totalPrice = self.totalPrice;
}
model.goodsCount = count;
NSLog(@"总价:%.f",self.totalPrice);
}
- (void)selectGoods:(GoodsModel *)model isSelect:(BOOL)select{
//NSLog(@"indexPath:%ld",indexPath.row);
//GoodsModel *model = self.dataSource[indexPath.row];
model.isSelect = select;
if (select) {
self.totalPrice += (model.goodsPrice*model.goodsCount);
[self.selectGoodsSource addObject:model];
}else{
self.totalPrice -= (model.goodsPrice*model.goodsCount);
[self.selectGoodsSource removeObject:model];
}
[self goodsChangeAction];
}
- (void)deleteIndex:(GoodsModel *)model {
QMUIAlertAction *cancel = [QMUIAlertAction actionWithTitle:@"取消" style:QMUIAlertActionStyleCancel handler:NULL];
@weakify(self);
QMUIAlertAction *delete = [QMUIAlertAction actionWithTitle:@"删除" style:QMUIAlertActionStyleDestructive handler:^(__kindof QMUIAlertController * _Nonnull aAlertController, QMUIAlertAction * _Nonnull action) {
@strongify(self);
self.title = [NSString stringWithFormat:@"购物车(%ld)",self.dataSource.count];
if (model.isSelect) {
[self selectGoods:model isSelect:NO];
}
NSInteger row = [self.dataSource indexOfObject:model];
[self.dataSource removeObject:model];
if (row < self.dataSource.count) {
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView deleteRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationFade];
}else{
[self.tableView reloadData];
}
}];
QMUIAlertController *alertController = [QMUIAlertController alertControllerWithTitle:@"确定删除?" message:[NSString stringWithFormat:@"确定删除商品\n%@",model.goodsName] preferredStyle:QMUIAlertControllerStyleAlert];
[alertController addAction:cancel];
[alertController addAction:delete];
[alertController showWithAnimated:YES];
}
#pragma --mark delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ShoppingCartCell *cell = [tableView dequeueReusableCellWithIdentifier:NMUIChainModelIdentifier(ShoppingCartCell.class) forIndexPath:indexPath];
GoodsModel *model = self.dataSource[indexPath.row];
cell.model = model;
@weakify(self);
cell.selectBlock = ^(BOOL select) {
@strongify(self);
[self selectGoods:model isSelect:select];
};
cell.goodsCountChangeBlock = ^(NSInteger count) {
@strongify(self);
[self changeGoodsCount:model count:count];
};
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
GoodsModel *model = self.dataSource[indexPath.row];
[QMUITips showInfo:[NSString stringWithFormat:@"商品信息:%@",model.goodsName] inView:self.view hideAfterDelay:2];
NSLog(@"%s",__func__);
}
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
GoodsModel *model = self.dataSource[indexPath.row];
@weakify(self);
UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
@strongify(self);
[self deleteIndex:model];
}];
//修改RowAction的颜色
deleteRowAction.backgroundColor = QMUICMI.redColor;
return @[deleteRowAction];
}
#pragma --mark lazy load
- (UITableView *)tableView {
if (_tableView == nil) {
UITableViewModelCreate()
.delegate(self)
.dataSource(self)
.addToSuperView(self.view)
.rowHeight(113.0/375.0*SCREEN_WIDTH)
.registerCellClass(ShoppingCartCell.class, NMUIChainModelIdentifier(ShoppingCartCell.class))
.makeMasonry(^(MASConstraintMaker * _Nonnull make) {
make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(0, 0, TabBarHeight+49, 0));
})
.assignTo(^(__kindof UIView * _Nonnull view) {
self->_tableView = view;
});
}
return _tableView;
}
- (NSMutableArray *)selectGoodsSource {
if (_selectGoodsSource == nil) {
_selectGoodsSource = [[NSMutableArray alloc] init];
}
return _selectGoodsSource;
}
- (NSMutableArray *)dataSource {
if (_dataSource == nil) {
_dataSource = [[NSMutableArray alloc] init];
}
return _dataSource;
}
- (ShoppingCartCounterView *)shoppingCounterView {
if (_shoppingCounterView == nil) {
_shoppingCounterView = [[ShoppingCartCounterView alloc] init];
[self.view addSubview:_shoppingCounterView];
@weakify(self);
_shoppingCounterView.selectAllBlock = ^(BOOL isSelectAll) {
@strongify(self);
[self selectAllGood:isSelectAll];
};
_shoppingCounterView.orderAction = ^{
@strongify(self);
[self orderAction];
};
[_shoppingCounterView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.height.mas_equalTo(49);
make.bottom.inset(TabBarHeight);
}];
}
return _shoppingCounterView;
}
@end
......@@ -6,8 +6,9 @@
//
#import "ActivityCollectionCell.h"
#import <Masonry.h>
#import "MacroDefinition.h"
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import <NMTheme/NMTheme.h>
@interface ActivityCollectionCell()
@property (nonatomic, strong) UIImageView *iconIv;
......@@ -26,7 +27,9 @@
}
- (void)setup {
self.backgroundColor = RGBCOLOR(247, 247, 247);
// self.backgroundColor = RGBCOLOR(247, 247, 247);
self.backgroundColor = UIColor.nm_backgroundColor;
[self.contentView addSubview:self.iconIv];
[self.iconIv mas_makeConstraints:^(MASConstraintMaker *make) {
......
......@@ -6,8 +6,8 @@
//
#import "HomeClassficationCell.h"
#import "MacroDefinition.h"
#import <Masonry.h>
#import <NMCategories/NMCategories.h>
#import <Masonry/Masonry.h>
@interface HomeClassficationCell()
@property (nonatomic, strong) UIImageView *iconIv;
......
......@@ -6,8 +6,8 @@
//
#import "HomeGoodsCell.h"
#import <Masonry.h>
#import "MacroDefinition.h"
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import "AttributLabel.h"
#import "HomeGoodsModel.h"
......
//
// HomeCarouselModel.h
// Mall-iOS
//
// Created by Nemo on 2020/10/16.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeCarouselModel : NSObject
/// icon Url
@property (nonatomic, copy) NSString *picture;
/// icon name
@property (nonatomic, copy) NSString *name;
+ (instancetype)homeCarouselModelWithDict:(NSDictionary *)dict;
@end
NS_ASSUME_NONNULL_END
//
// HomeCarouselModel.m
// Mall-iOS
//
// Created by Nemo on 2020/10/16.
//
#import "HomeCarouselModel.h"
@implementation HomeCarouselModel
+ (instancetype)homeCarouselModelWithDict:(NSDictionary *)dict {
HomeCarouselModel *model = [[HomeCarouselModel alloc] init];
model.picture = [NSString stringWithFormat:@"%@/%@",API_HOST,dict[@"picture"]];
model.name = dict[@"name"];
return model;
}
@end
//
// HomeClassificationModel.h
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeClassificationModel : NSObject
/// icon Url
@property (nonatomic, copy) NSString *iconUrl;
/// icon name
@property (nonatomic, copy) NSString *iconName;
+ (instancetype)homeClassificationModelWithDict:(NSDictionary *)dict;
@end
NS_ASSUME_NONNULL_END
//
// HomeClassificationModel.m
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import "HomeClassificationModel.h"
@implementation HomeClassificationModel
+ (instancetype)homeClassificationModelWithDict:(NSDictionary *)dict {
HomeClassificationModel *model = [[HomeClassificationModel alloc] init];
model.iconUrl = [NSString stringWithFormat:@"%@/%@",API_HOST,dict[@"picture"]];
model.iconName = dict[@"name"];
return model;
}
@end
//
// HomeModel.h
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class HomeGoodsModel,HomeClassificationModel,HomeCarouselModel;
@interface HomeModel : NSObject
@property (nonatomic, strong) NSMutableArray <HomeCarouselModel *>*carouselAraay;
@property (nonatomic, strong) NSMutableArray <HomeClassificationModel *>*classificaAraay;
@property (nonatomic, strong) NSMutableArray <HomeGoodsModel *>*goodsArray;
@end
NS_ASSUME_NONNULL_END
//
// HomeModel.m
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import "HomeModel.h"
@implementation HomeModel
@end
//
// JYTargetHomeModule.h
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface JYTargetHomeModule : NSObject
- (UIViewController *)jyNativeHomeViewController;
@end
NS_ASSUME_NONNULL_END
//
// JYTargetHomeModule.m
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#import "JYTargetHomeModule.h"
#import "HomeViewController.h"
@implementation JYTargetHomeModule
- (UIViewController *)jyNativeHomeViewController {
HomeViewController *home = [HomeViewController homeViewController];
home.title = @"主页";
home.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"主页"
image:[UIImage imageNamed:@"index"]
selectedImage:[UIImage imageNamed:@"index_s"]];
UINavigationController* homeNav = [[UINavigationController alloc] initWithRootViewController:home];
return homeNav;
}
@end
//
// NMRouter+HomeModuleActions.h
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#if __has_include(<NMRouter/NMRouter.h>)
#import <NMRouter/NMRouter.h>
#else
#import "NMRouter.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@interface NMRouter (HomeModuleActions)
- (UIViewController *)jyMediatorHomeViewController;
@end
NS_ASSUME_NONNULL_END
//
// NMRouter+HomeModuleActions.m
// Mall-iOS
//
// Created by purewin on 2020/12/12.
//
#import "NMRouter+HomeModuleActions.h"
@implementation NMRouter (HomeModuleActions)
// 1. 字符串 是类名 JYXxx.h 中的 xxx 部分
NSString * const kNMMediatorHomeTargetCourse = @"TargetHomeModule";
// 2. 字符串是 JYxxx.h 中 定义的 jyXxx 函数名的 xxx 部分
NSString * const kNMMediatorHomeActionNativToNativeCourse = @"NativeHomeViewController";
- (UIViewController *)jyMediatorHomeViewController {
UIViewController *viewController = [self performTarget:kNMMediatorHomeTargetCourse
action:kNMMediatorHomeActionNativToNativeCourse
params:nil
shouldCacheTarget:NO
];
if ([viewController isKindOfClass:[UIViewController class]]) {
// view controller 交付出去之后,可以由外界选择是push还是present
return viewController;
} else {
// 这里处理异常场景,具体如何处理取决于产品
NSLog(@"%@ 未能实例化页面", NSStringFromSelector(_cmd));
return [[UIViewController alloc] init];
}
}
@end
//
// HomeServices.h
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import <Foundation/Foundation.h>
#import <NMReactiveCocoa/ReactiveObjC.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeServices : NSObject
- (RACSignal *)carouselSignal;
@end
NS_ASSUME_NONNULL_END
//
// HomeServices.m
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import "HomeServices.h"
#import <NMNetwork/NMNetwork.h>
@implementation HomeServices
- (RACSignal *)carouselSignal {
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSURLSessionDataTask *task = [NetworkManager POST:URLShopping() parameters:nil success:^(id _Nullable responseObject) {
[subscriber sendNext:responseObject];
[subscriber sendCompleted];
} failure:^(id _Nullable obj, NSError * _Nullable error) {
[subscriber sendError:error];
}];
return [RACDisposable disposableWithBlock:^{
//完成后清理不需要的资源
[task cancel];
}];
}];
}
@end
//
// HomeViewModel.h
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import <Foundation/Foundation.h>
#import "HomeServices.h"
#import "HomeModel.h"
NS_ASSUME_NONNULL_BEGIN
@class RACCommand;
@interface HomeViewModel : NSObject
@property (nonatomic, strong) HomeModel *model;
@property (strong, nonatomic) RACCommand *homeCommand;
@property (nonatomic, strong) RACSubject *errSubject;
- (instancetype)initServices:(HomeServices *)services;
@end
NS_ASSUME_NONNULL_END
//
// HomeViewModel.m
// Mall-iOS
//
// Created by Nemo on 2020/10/15.
//
#import "HomeViewModel.h"
#import <NMReactiveCocoa/ReactiveObjC.h>
#import "HomeCarouselModel.h"
@interface HomeViewModel()
@property (nonatomic, strong) HomeServices *services;
@end
@implementation HomeViewModel
- (instancetype)initServices:(HomeServices *)services
{
self = [super init];
if (self) {
_services = services;
_model = [[HomeModel alloc] init];
_errSubject = [RACSubject subject];
[self initCommand];
}
return self;
}
- (void)initCommand {
@weakify(self);
self.homeCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
@strongify(self);
return [[self.services carouselSignal] logAll];
}];
[self.homeCommand.executionSignals subscribeNext:^(RACSignal* innerSignal) {
[innerSignal subscribeNext:^(NSArray *x) {
@strongify(self);
NSMutableArray *datas = [[NSMutableArray alloc] initWithCapacity:x.count];
for (NSDictionary *dict in x) {
HomeCarouselModel *homeCarouselModel = [HomeCarouselModel homeCarouselModelWithDict:dict];
[datas addObject:homeCarouselModel];
}
self.model.carouselAraay = datas;
}];
}];
[[RACSubject merge:@[self.homeCommand.errors]] subscribe:self.errSubject];
}
-(void)requestData{
//网络请求1
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"网络请求1");
[subscriber sendNext:@"网络请求1"];
return nil;
}];
//网络请求2
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"网络请求2");
[subscriber sendNext:@"网络请求2"];
return nil;
}];
//网络请求3
RACSignal *signal3 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"网络请求3");
[subscriber sendNext:@"网络请求3"];
return nil;
}];
[self rac_liftSelector:@selector(dealDataData1:data2:data3:) withSignals:signal1,signal2,signal3, nil];
}
-(void)dealDataData1:(id)data1 data2:(id)data2 data3:(id)data3 {
}
@end
......@@ -6,9 +6,10 @@
//
#import "ActivityView.h"
#import "UICollectionViewCell+Extension.h"
#import <Masonry/Masonry.h>
#import <NMTheme/NMTheme.h>
#import <NMUIChainKit/NMUIChainKit.h>
#import "ActivityCollectionCell.h"
#import <Masonry.h>
#import <QMUIKit.h>
@interface ActivityView()<UICollectionViewDelegate,UICollectionViewDataSource>
......@@ -30,9 +31,7 @@
-(void)setupUI {
self.backgroundColor = [UIColor whiteColor];
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.collectionView reloadData];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
......@@ -41,7 +40,7 @@
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ActivityCollectionCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:[ActivityCollectionCell identifier] forIndexPath:indexPath];
ActivityCollectionCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:NMUIChainModelIdentifier(ActivityCollectionCell.class) forIndexPath:indexPath];
return cell;
}
......@@ -59,15 +58,20 @@
layout.itemSize = CGSizeMake(width, height);
layout.sectionInset = UIEdgeInsetsMake(0, 5, 0, 0);
_collectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.showsVerticalScrollIndicator = NO;
_collectionView.backgroundColor = [UIColor whiteColor];
[self addSubview:_collectionView];
[ActivityCollectionCell registerClassForCollectionView:_collectionView];
UICollectionViewCreateWithLayout(layout).makeChain
.addToSuperView(self)
.delegate(self)
.dataSource(self)
.showsHorizontalScrollIndicator(NO)
.showsHorizontalScrollIndicator(NO)
.backgroundColor(UIColor.nm_backgroundColor)
.registerCellClass(ActivityCollectionCell.class, NMUIChainModelIdentifier(ActivityCollectionCell.class))
.assignTo(^(__kindof UIView * _Nonnull view) {
self->_collectionView = view;
})
.makeMasonry(^(MASConstraintMaker * _Nonnull make) {
make.edges.equalTo(self);
});
}
return _collectionView;
......
......@@ -16,15 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) NSArray <HomeClassificationModel *>*dataSource;
@end
@interface HomeClassificationModel : NSObject
/// icon Url
@property (nonatomic, copy) NSString *iconUrl;
/// icon name
@property (nonatomic, copy) NSString *iconName;
@property (nonatomic, copy) void(^cellClickAction)(HomeClassificationModel *model);
@end
......
......@@ -6,10 +6,11 @@
//
#import "HomeClassificationView.h"
#import <QMUIKit.h>
#import <NMCategories/NMCategories.h>
#import <NMUIChainKit/NMUIChainKit.h>
#import <NMTheme/NMTheme.h>
#import "HomeClassficationCell.h"
#import "UICollectionViewCell+Extension.h"
#import <Masonry.h>
#import "HomeClassificationModel.h"
@interface HomeClassificationView()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView *collectionView;
......@@ -27,15 +28,11 @@
}
-(void)setupUI {
self.backgroundColor = [UIColor whiteColor];
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
self.backgroundColor = UIColor.nm_backgroundColor;
}
- (void)setDataSource:(NSArray<HomeClassificationModel *> *)dataSource {
_dataSource = dataSource;
[self.collectionView reloadData];
}
......@@ -48,7 +45,7 @@
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
HomeClassficationCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:[HomeClassficationCell identifier] forIndexPath:indexPath];
HomeClassficationCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:NMUIChainModelIdentifier(HomeClassficationCell.class) forIndexPath:indexPath];
HomeClassificationModel *model = self.dataSource[indexPath.row];
cell.iconName = model.iconName;
......@@ -58,7 +55,9 @@
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
HomeClassificationModel *model = self.dataSource[indexPath.row];
[QMUITips showSucceed:model.iconName inView:QMUIHelper.visibleViewController.view hideAfterDelay:2];
!self.cellClickAction ?: self.cellClickAction(model);
//[QMUITips showSucceed:model.iconName inView:QMUIHelper.visibleViewController.view hideAfterDelay:2];
}
......@@ -66,7 +65,7 @@
if (_collectionView == nil) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
CGFloat lineSpacing = (SCREEN_WIDTH -45*5)/6.0;
CGFloat lineSpacing = (NMScreenWidth() -45*5)/6.0;
// 上下的距离
layout.minimumLineSpacing = lineSpacing;
layout.minimumInteritemSpacing = 20;
......@@ -75,16 +74,20 @@
layout.itemSize = CGSizeMake(45, 72);
layout.sectionInset = UIEdgeInsetsMake(30, lineSpacing, 30, 0);
_collectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.decelerationRate = 0.8;
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.showsVerticalScrollIndicator = NO;
_collectionView.backgroundColor = [UIColor whiteColor];
[self addSubview:_collectionView];
[HomeClassficationCell registerClassForCollectionView:_collectionView];
UICollectionViewCreateWithLayout(layout).makeChain
.dataSource(self)
.delegate(self)
.showsVerticalScrollIndicator(NO)
.showsHorizontalScrollIndicator(NO)
.backgroundColor(UIColor.nm_backgroundColor)
.addToSuperView(self)
.registerCellClass(HomeClassficationCell.class, NMUIChainModelIdentifier(HomeClassficationCell.class))
.assignTo(^(__kindof UIView * _Nonnull view) {
self->_collectionView = view;
})
.makeMasonry(^(MASConstraintMaker * _Nonnull make) {
make.edges.equalTo(self);
});
}
return _collectionView;
......@@ -92,7 +95,3 @@
@end
@implementation HomeClassificationModel
@end
......@@ -9,10 +9,16 @@
NS_ASSUME_NONNULL_BEGIN
@class HomeClassificationModel;
@interface HomeCollectionHeaderView : UICollectionReusableView
@property (nonatomic, strong) NSDictionary *headerDict;
@property (nonatomic, copy) void(^searchActionBlcok)(void);
@property (nonatomic, copy) void(^cellAction)(HomeClassificationModel *model);
@end
NS_ASSUME_NONNULL_END
......@@ -6,16 +6,16 @@
//
#import "HomeCollectionHeaderView.h"
#import <Masonry.h>
#import "MacroDefinition.h"
#import <SDCycleScrollView.h>
#import "UIImage+Extension.h"
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import <NMCycleScrollView/SDCycleScrollView.h>
#import "HomeCarouselModel.h"
#import "HomeClassificationView.h"
#import "ActivityView.h"
#import <SDWebImage.h>
#import <QMUIKit.h>
#import <SDWebImage/SDWebImage.h>
@interface HomeCollectionHeaderView()<SDCycleScrollViewDelegate>
@interface HomeCollectionHeaderView()
@property (nonatomic, strong) UIButton *searchBtn;
@property (nonatomic, strong) SDCycleScrollView *cycleView;
@property (nonatomic, strong) HomeClassificationView *homeClassficationView;
......@@ -78,36 +78,35 @@
[self.layer addSublayer:bottomLine];
}
- (void)setCellAction:(void (^)(HomeClassificationModel * _Nonnull))cellAction {
_cellAction = cellAction;
self.homeClassficationView.cellClickAction = cellAction;
}
- (void)setHeaderDict:(NSDictionary *)headerDict {
_headerDict = headerDict;
NSArray *ary = @[@"居家",@"鞋包配饰",@"服装",
@"电器",@"婴童",@"饮食",
@"特色区",@"洗护",@"餐厨",@"文体"];
@autoreleasepool {
NSMutableArray <HomeClassificationModel *>*list = [[NSMutableArray alloc] init];
for (int i = 0; i < ary.count; i ++) {
HomeClassificationModel *model = [[HomeClassificationModel alloc] init];
model.iconUrl = @"";
model.iconName = ary[i];
[list addObject:model];
NSArray *classificaAry = headerDict[@"Classifica"];
if (classificaAry.count > 0) {
self.homeClassficationView.dataSource = classificaAry;
}
self.homeClassficationView.dataSource = list;
NSArray *carouselsAry = headerDict[@"Carousels"];
if (carouselsAry.count > 0) {
NSMutableArray *carouselsURLs = [[NSMutableArray alloc] initWithCapacity:carouselsAry.count];
for (HomeCarouselModel *model in carouselsAry) {
[carouselsURLs addObject:model.picture];
}
// self.cycleView.imageURLStringsGroup = carouselsURLs;
}
}
-(void)searchAction {
NSLog(@"======test");
[QMUITips showSucceed:@"搜索被点击!" inView:kAppWindow() hideAfterDelay:2];
!self.searchActionBlcok ?: self.searchActionBlcok();
}
- (UIImageView *)recommendIv {
if (_recommendIv == nil) {
_recommendIv = [[UIImageView alloc] init];
[self addSubview:_recommendIv];
CGFloat height = 100.0/360.0*SCREEN_WIDTH;
CGFloat height = 100.0/360.0*NMScreenWidth();
[_recommendIv mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(height);
make.top.equalTo(self.homeClassficationView.mas_bottom);
......@@ -120,7 +119,7 @@
if (_activityView == nil) {
_activityView = [[ActivityView alloc] init];
[self addSubview:_activityView];
CGFloat width = (SCREEN_WIDTH-15)/2.0;
CGFloat width = (NMScreenWidth()-15)/2.0;
CGFloat height = 135.0/180.0*width;
[_activityView mas_makeConstraints:^(MASConstraintMaker *make) {
......@@ -135,7 +134,7 @@
if (_homeClassficationView == nil) {
_homeClassficationView = [[HomeClassificationView alloc] init];
[self addSubview:_homeClassficationView];
CGFloat height = 231.0/375.0*SCREEN_WIDTH;
CGFloat height = 231.0/375.0*NMScreenWidth();
[_homeClassficationView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(height);
make.top.equalTo(self.cycleView.mas_bottom);
......@@ -146,8 +145,8 @@
}
- (SDCycleScrollView *)cycleView {
if (_cycleView == nil) {
CGFloat height = 170.0/SCREEN_WIDTH*375.0;
_cycleView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectMake(0, 43, SCREEN_WIDTH, height) delegate:self placeholderImage:[UIImage imageWithColor:[UIColor grayColor]]];
CGFloat height = 170.0/NMScreenWidth()*375.0;
_cycleView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectMake(0, 43, NMScreenWidth(), height) imageURLStringsGroup:@[]];
_cycleView.backgroundColor = [UIColor whiteColor];
[self addSubview:_cycleView];
}
......
......@@ -8,9 +8,10 @@
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeViewController : UIViewController
+ (instancetype)homeViewController;
@end
NS_ASSUME_NONNULL_END
......@@ -6,17 +6,23 @@
//
#import "HomeViewController.h"
#import <Masonry.h>
#import <Masonry/Masonry.h>
#import <NMCategories/NMCategories.h>
#import <QMUIKit.h>
#import <MJRefresh.h>
#import "HomeCollectionHeaderView.h"
#import "UICollectionViewCell+Extension.h"
#import "UICollectionReusableView+Extension.h"
#import <NMRouter.h>
#import "HomeGoodsCell.h"
#import "MacroDefinition.h"
#import "HomeGoodsModel.h"
#import "HomeViewModel.h"
#import "HomeClassificationModel.h"
#import "HomeCollectionHeaderView.h"
#import <NMUIChainKit/NMUIChainKit.h>
//#import <JYSearchModule/JYSearchModule.h>
#import <JYSearchModule.h>
@interface HomeViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, strong) HomeViewModel *viewModel;
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, assign) CGFloat collectionViewHeaderHeight;
@property (nonatomic, strong) NSMutableArray *dataSource;
......@@ -24,11 +30,26 @@
@implementation HomeViewController
+ (instancetype)homeViewController {
HomeViewModel *viewModel = [[HomeViewModel alloc] initServices:[[HomeServices alloc] init]];
return [[self alloc] initWithViewModel:viewModel];
}
- (instancetype)initWithViewModel:(HomeViewModel *)viewModel {
if (self = [super init]) {
self.viewModel = viewModel;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setUp];
[self bindViewModel];
[self requestNewData];
}
......@@ -45,8 +66,24 @@
model.goodsType = (i%2)?HomeGoodsModelTypeNone:HomeGoodsModelTypeCom;
[self.dataSource addObject:model];
}
NSArray *ary = @[@"居家",@"鞋包配饰",@"服装",
@"电器",@"婴童",@"饮食",
@"特色区",@"洗护",@"餐厨",@"文体"];
NSMutableArray <HomeClassificationModel *>*list = [[NSMutableArray alloc] initWithCapacity:ary.count];
for (int i = 0; i < ary.count; i ++) {
HomeClassificationModel *model = [[HomeClassificationModel alloc] init];
model.iconUrl = @"";
model.iconName = ary[i];
[list addObject:model];
}
self.viewModel.model.classificaAraay = list;
[self.collectionView reloadData];
[self.collectionView.mj_header endRefreshing];
}
- (void)requestMoreData {
......@@ -69,26 +106,44 @@
self.collectionViewHeaderHeight = 926.0/375*SCREEN_WIDTH;
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.collectionView];
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
_dataSource = [[NSMutableArray alloc] init];
WeakSelf
MJRefreshBackNormalFooter *footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
[weakSelf requestMoreData];
@weakify(self);
[self.collectionView footerWithRefreshingBlock:^{
@strongify(self);
[self requestMoreData];
}];
footer.automaticallyChangeAlpha = YES;
self.collectionView.mj_footer = footer;
self.collectionView.mj_header = [MJRefreshStateHeader headerWithRefreshingBlock:^{
[weakSelf requestNewData];
[self.collectionView headerWithRefreshingBlock:^{
@strongify(self);
[self requestNewData];
}];
}
- (void)searchAction {
UIViewController *search = [[NMRouter sharedInstance] jyMediatorViewController];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:search];
if(@available(iOS 13.0, *)) {
nav.modalPresentationStyle = UIModalPresentationFullScreen;
}
[self presentViewController:nav animated:NO completion:nil];
}
- (void)bindViewModel {
[self.viewModel.homeCommand execute:@"aaaa"];
@weakify(self);
[[RACObserve(self.viewModel.model, carouselAraay) skip:1] subscribeNext:^(id _Nullable x) {
@strongify(self);
[self.collectionView reloadData];
}];
[[self.viewModel.errSubject distinctUntilChanged] subscribeNext:^(NSError *err) {
@strongify(self);
[self.collectionView endRefresh];
[self showFailToast:[NSString stringWithFormat:@"%@",err.userInfo[NSLocalizedDescriptionKey]]];
}];
}
#pragma mark - UICollectionViewDelegate
......@@ -97,7 +152,17 @@
if ([kind isEqualToString:UICollectionElementKindSectionHeader]){
HomeCollectionHeaderView *header = [HomeCollectionHeaderView dequeueReusableSupplementaryHeaderViewOfKind:collectionView index:indexPath];
header.headerDict = @{};
header.headerDict = @{@"Carousels":self.viewModel.model.carouselAraay?:@[],
@"Classifica":self.viewModel.model.classificaAraay?:@[]};
@weakify(self);
header.searchActionBlcok = ^{
@strongify(self);
[self searchAction];
};
header.cellAction = ^(HomeClassificationModel * _Nonnull model) {
@strongify(self);
[self showWarningToast:model.iconName];
};
return header;
}
return [UICollectionReusableView new];
......@@ -112,7 +177,7 @@
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
HomeGoodsCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:[HomeGoodsCell identifier] forIndexPath:indexPath];
HomeGoodsCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:NMUIChainModelIdentifier(HomeGoodsCell.class) forIndexPath:indexPath];
cell.model = self.dataSource[indexPath.row];
return cell;
......@@ -129,18 +194,21 @@
layout.itemSize = CGSizeMake(width, height);
layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
_collectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.decelerationRate = 0.8;
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.showsVerticalScrollIndicator = NO;
_collectionView.backgroundColor = RGBCOLOR(238, 238, 238);
[self.view addSubview:_collectionView];
[HomeGoodsCell registerClassForCollectionView:_collectionView];
[HomeCollectionHeaderView registerClassHeaderForCollectionView:_collectionView];
UICollectionViewCreateWithLayout(layout).makeChain
.addToSuperView(self.view)
.delegate(self)
.dataSource(self)
.showsHorizontalScrollIndicator(NO)
.showsHorizontalScrollIndicator(NO)
.backgroundColor(RGBCOLOR(238, 238, 238))
.registerHeaderViewClass(HomeCollectionHeaderView.class, NMUIChainModelIdentifier(HomeCollectionHeaderView.class))
.registerCellClass(HomeGoodsCell.class, NMUIChainModelIdentifier(HomeGoodsCell.class))
.assignTo(^(__kindof UIView * _Nonnull view) {
self->_collectionView = view;
})
.makeMasonry(^(MASConstraintMaker * _Nonnull make) {
make.edges.equalTo(self.view);
});
}
return _collectionView;
}
......
//
// UITableViewCell+Extension.h
// SearchTagViewCell.h
// xiangwan
//
// Created by mac on 2019/8/17.
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "NMTagView.h"
NS_ASSUME_NONNULL_BEGIN
@interface UITableViewCell (Extension)
/// cell Class注册方法
+ (void)registerClassForTableView:(UITableView *)tableView;
/// cell Nib注册方法
+ (void)registerNibForTableView:(UITableView *)tableView;
+ (NSString *)identifier;
@interface SearchTagViewCell : UITableViewCell
@property (nonatomic, weak) UILabel *headerLb;
@property (weak, nonatomic) NMTagView *tagView;
@property (nonatomic, assign) BOOL showClearBtn;
@property (nonatomic, copy) void(^clearAction)(void);
@end
NS_ASSUME_NONNULL_END
//
// SearchTagViewCell.m
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import "SearchTagViewCell.h"
@interface SearchTagViewCell()
@property (nonatomic, weak) UIButton *clearBtn;
@end
@implementation SearchTagViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
UILabel *headerLb = [[UILabel alloc] init];
headerLb.font = [UIFont systemFontOfSize:16];
[self.contentView addSubview:headerLb];
self.headerLb = headerLb;
[headerLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(16);
make.top.mas_equalTo(24);
make.height.mas_equalTo(21);
}];
UIButton *clearBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[clearBtn setTitle:@"清空" forState:UIControlStateNormal];
[clearBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
clearBtn.titleLabel.font = [UIFont systemFontOfSize:16];
[clearBtn addTarget:self action:@selector(clearBtnAction) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:clearBtn];
self.clearBtn = clearBtn;
[clearBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(headerLb);
make.right.inset(16);
}];
NMTagView *tagView = [[NMTagView alloc] init];
[self.contentView addSubview:tagView];
self.tagView = tagView;
[tagView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.contentView);
make.left.right.inset(16);
make.top.equalTo(headerLb.mas_bottom).offset(16);
}];
}
-(void)setShowClearBtn:(BOOL)showClearBtn {
_showClearBtn = showClearBtn;
self.clearBtn.hidden = !showClearBtn;
}
- (void)clearBtnAction {
!self.clearAction ?: self.clearAction();
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//
// JYSearchModule.h
// JYSearchModule
//
// Created by Nemo on 2020/10/16.
// Copyright © 2020 AgoniNemo. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for JYSearchModule.
FOUNDATION_EXPORT double JYSearchModuleVersionNumber;
//! Project version string for JYSearchModule.
FOUNDATION_EXPORT const unsigned char JYSearchModuleVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <JYSearchModule/PublicHeader.h>
#import "NMRouter+SearchModuleActions.h"
//
// SearchTagHeaderModel.h
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class SearchTagModel;
@interface SearchTagHeaderModel : NSObject
@property (nonatomic, strong) NSString *headerText;
@property (nonatomic, strong) NSArray <SearchTagModel *>*tagModels;
@end
NS_ASSUME_NONNULL_END
//
// SearchTagHeaderModel.m
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import "SearchTagHeaderModel.h"
@implementation SearchTagHeaderModel
@end
//
// SearchTagModel.h
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SearchTagModel : NSObject
@property (nonatomic, strong) NSString *tagText;
@end
NS_ASSUME_NONNULL_END
//
// SearchTagModel.m
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import "SearchTagModel.h"
@implementation SearchTagModel
@end
//
// JYSearchTargetModule.h
// JYSearchModule_Example
//
// Created by Nemo on 2020/10/16.
// Copyright © 2020 AgoniNemo. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface JYSearchTargetModule : NSObject
- (UIViewController *)jyNativeSearchViewController;
@end
NS_ASSUME_NONNULL_END
//
// JYSearchTargetModule.m
// JYSearchModule_Example
//
// Created by Nemo on 2020/10/16.
// Copyright © 2020 AgoniNemo. All rights reserved.
//
#import "JYSearchTargetModule.h"
#import "JYSearchViewController.h"
@implementation JYSearchTargetModule
- (UIViewController *)jyNativeSearchViewController {
JYSearchViewController *viewController = [JYSearchViewController jySearchViewController];
return viewController;
}
@end
//
// NMRouter+SearchModuleActions.h
// Mall-iOS
//
// Created by Nemo on 2020/10/16.
//
#import "NMRouter.h"
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NMRouter (SearchModuleActions)
// 外部调用的方法
- (UIViewController *)jyMediatorViewController;
@end
NS_ASSUME_NONNULL_END
//
// NMRouter+SearchModuleActions.m
// Mall-iOS
//
// Created by Nemo on 2020/10/16.
//
#import "NMRouter+SearchModuleActions.h"
// 1. 字符串 是类名 JYXxx.h 中的 xxx 部分
NSString * const kCTMediatorTargetCourse = @"SearchTargetModule";
// 2. 字符串是 JYxxx.h 中 定义的 jyXxx 函数名的 xxx 部分
NSString * const kCTMediatorActionNativToNativeCourse = @"NativeSearchViewController";
@implementation NMRouter (SearchModuleActions)
- (UIViewController *)jyMediatorViewController {
UIViewController *viewController = [self performTarget:kCTMediatorTargetCourse
action:kCTMediatorActionNativToNativeCourse
params:nil
shouldCacheTarget:NO
];
if ([viewController isKindOfClass:[UIViewController class]]) {
// view controller 交付出去之后,可以由外界选择是push还是present
return viewController;
} else {
// 这里处理异常场景,具体如何处理取决于产品
NSLog(@"%@ 未能实例化页面", NSStringFromSelector(_cmd));
return [[UIViewController alloc] init];
}
}
@end
//
// NMTag.h
// CQ_App
//
// Created by mac on 2019/4/9.
// Copyright © 2019年 mac. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NMTag : NSObject
@property (copy, nonatomic, nullable) NSString *text;
@property (copy, nonatomic, nullable) NSAttributedString *attributedText;
@property (strong, nonatomic, nullable) UIColor *textColor;
///backgound color
@property (strong, nonatomic, nullable) UIColor *bgColor;
@property (strong, nonatomic, nullable) UIColor *highlightedBgColor;
///background image
@property (strong, nonatomic, nullable) UIImage *bgImg;
@property (assign, nonatomic) CGFloat cornerRadius;
@property (strong, nonatomic, nullable) UIColor *borderColor;
@property (assign, nonatomic) CGFloat borderWidth;
///like padding in css
@property (assign, nonatomic) UIEdgeInsets padding;
@property (strong, nonatomic, nullable) UIFont *font;
///if no font is specified, system font with fontSize is used
@property (assign, nonatomic) CGFloat fontSize;
///default:YES
@property (assign, nonatomic) BOOL enable;
- (nonnull instancetype)initWithText: (nonnull NSString *)text;
+ (nonnull instancetype)tagWithText: (nonnull NSString *)text;
@end
NS_ASSUME_NONNULL_END
//
// NMTag.m
// CQ_App
//
// Created by mac on 2019/4/9.
// Copyright © 2019年 mac. All rights reserved.
//
#import "NMTag.h"
static const CGFloat kDefaultFontSize = 13.0;
@implementation NMTag
- (instancetype)init {
self = [super init];
if (self) {
_fontSize = kDefaultFontSize;
_textColor = [UIColor colorWithRed:34.0/255.0 green:34.0/255.0 blue:34.0/255.0 alpha:1];
_bgColor = [UIColor whiteColor];
_enable = YES;
}
return self;
}
- (instancetype)initWithText: (NSString *)text {
self = [self init];
if (self) {
_text = text;
}
return self;
}
+ (instancetype)tagWithText: (NSString *)text {
return [[self alloc] initWithText: text];
}
@end
//
// ViewControllerConfigure.h
// NMTagButton.h
// CQ_App
//
// Created by mac on 2019/3/22.
// Created by mac on 2019/4/9.
// Copyright © 2019年 mac. All rights reserved.
//
......@@ -10,8 +10,9 @@
NS_ASSUME_NONNULL_BEGIN
@interface ViewControllerConfigure : NSObject
@class NMTag;
@interface NMTagButton : UIButton
+ (nonnull instancetype)buttonWithTag: (nonnull NMTag *)tag;
@end
NS_ASSUME_NONNULL_END
//
// NMTagButton.m
// CQ_App
//
// Created by mac on 2019/4/9.
// Copyright © 2019年 mac. All rights reserved.
//
#import "NMTagButton.h"
#import "NMTag.h"
@implementation NMTagButton
+ (instancetype)buttonWithTag: (NMTag *)tag {
NMTagButton *btn = [super buttonWithType:UIButtonTypeCustom];
if (tag.attributedText) {
[btn setAttributedTitle: tag.attributedText forState: UIControlStateNormal];
} else {
[btn setTitle: tag.text forState:UIControlStateNormal];
[btn setTitleColor: tag.textColor forState: UIControlStateNormal];
btn.titleLabel.font = tag.font ?: [UIFont systemFontOfSize:tag.fontSize];
}
btn.backgroundColor = tag.bgColor;
btn.contentEdgeInsets = tag.padding;
btn.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
if (tag.bgImg) {
[btn setBackgroundImage: tag.bgImg forState: UIControlStateNormal];
}
if (tag.borderColor) {
btn.layer.borderColor = tag.borderColor.CGColor;
}
if (tag.borderWidth) {
btn.layer.borderWidth = tag.borderWidth;
}
btn.userInteractionEnabled = tag.enable;
if (tag.enable) {
UIColor *highlightedBgColor = tag.highlightedBgColor ?: [self darkerColor:btn.backgroundColor];
[btn setBackgroundImage:[self imageWithColor:highlightedBgColor] forState:UIControlStateHighlighted];
}
btn.layer.cornerRadius = tag.cornerRadius;
btn.layer.masksToBounds = YES;
return btn;
}
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
+ (UIColor *)darkerColor:(UIColor *)color {
CGFloat h, s, b, a;
if ([color getHue:&h saturation:&s brightness:&b alpha:&a])
return [UIColor colorWithHue:h
saturation:s
brightness:b * 0.85
alpha:a];
return color;
}
@end
//
// NMTagView.h
// CQ_App
//
// Created by mac on 2019/4/9.
// Copyright © 2019年 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "NMTag.h"
NS_ASSUME_NONNULL_BEGIN
@interface NMTagView : UIView
@property (assign, nonatomic) UIEdgeInsets padding; //内边距
@property (assign, nonatomic) CGFloat lineSpacing; //行间距
@property (assign, nonatomic) CGFloat interitemSpacing; //item间距
@property (assign, nonatomic) CGFloat preferredMaxLayoutWidth; //最大宽度
@property (assign, nonatomic) CGFloat regularWidth; //!< 固定宽度
@property (nonatomic,assign ) CGFloat regularHeight; //!< 固定高度
@property (assign, nonatomic) BOOL singleLine;
@property (nonatomic, assign) BOOL isTagBtnEnable; //标签按钮是否可点击 NO:可点击, YES: 不可点击
@property (copy, nonatomic, nullable) void (^didTapTagAtIndex)(NSUInteger index);
- (void)addTag: (nonnull NMTag *)tag;
- (void)insertTag: (nonnull NMTag *)tag atIndex:(NSUInteger)index;
- (void)removeTag: (nonnull NMTag *)tag;
- (void)removeTagAtIndex: (NSUInteger)index;
- (void)removeAllTags;
@end
NS_ASSUME_NONNULL_END
//
// NMTagView.m
// CQ_App
//
// Created by mac on 2019/4/9.
// Copyright © 2019年 mac. All rights reserved.
//
#import "NMTagView.h"
#import "NMTagButton.h"
@interface NMTagView ()
@property (strong, nonatomic, nullable) NSMutableArray *tags;
@property (assign, nonatomic) BOOL didSetup;
@property (nonatomic,assign) BOOL isIntrinsicWidth; //!<是否宽度固定
@property (nonatomic,assign) BOOL isIntrinsicHeight; //!<是否高度固定
@end
@implementation NMTagView
// 重写setter给bool赋值
- (void)setRegularWidth:(CGFloat)intrinsicWidth
{
if (_regularWidth != intrinsicWidth) {
_regularWidth = intrinsicWidth;
if (intrinsicWidth == 0) {
self.isIntrinsicWidth = NO;
}
else
{
self.isIntrinsicWidth = YES;
}
}
}
- (void)setRegularHeight:(CGFloat)intrinsicHeight
{
if (_regularHeight != intrinsicHeight) {
_regularHeight = intrinsicHeight;
if (intrinsicHeight == 0)
{
self.isIntrinsicHeight = NO;
}
else
{
self.isIntrinsicHeight = YES;
}
}
}
#pragma mark - Lifecycle
- (CGSize)intrinsicContentSize {
if (!self.tags.count) {
return CGSizeZero;
}
NSArray *subviews = self.subviews;
UIView *previousView = nil;
CGFloat topPadding = self.padding.top;
CGFloat bottomPadding = self.padding.bottom;
CGFloat leftPadding = self.padding.left;
CGFloat rightPadding = self.padding.right;
CGFloat itemSpacing = self.interitemSpacing;
CGFloat lineSpacing = self.lineSpacing;
CGFloat currentX = leftPadding;
CGFloat intrinsicHeight = topPadding; //初始固定高度
CGFloat intrinsicWidth = leftPadding; //初始固定宽度
if (!self.singleLine && self.preferredMaxLayoutWidth > 0) {
NSInteger lineCount = 0; //累加行数
for (UIView *view in subviews) {
CGSize size = view.intrinsicContentSize;
// 宽度和高度通过参数的0或者非0来进行赋值
CGFloat width = self.isIntrinsicWidth?self.regularWidth:size.width;
CGFloat height = self.isIntrinsicHeight?self.regularHeight:size.height;
if (previousView) { //上一个tagbutton是否存在
// CGFloat width = size.width;
currentX += itemSpacing;
if (currentX + width + rightPadding <= self.preferredMaxLayoutWidth) { //计算是否换行
currentX += width;
} else {
lineCount ++;
currentX = leftPadding + width;
intrinsicHeight += height;
}
} else {
lineCount ++;
intrinsicHeight += height;
currentX += width;
}
previousView = view;
intrinsicWidth = MAX(intrinsicWidth, currentX + rightPadding);
}
intrinsicHeight += bottomPadding + lineSpacing * (lineCount - 1);
} else {
for (UIView *view in subviews) {
CGSize size = view.intrinsicContentSize;
intrinsicWidth += self.isIntrinsicWidth?self.regularWidth:size.width;
}
intrinsicWidth += itemSpacing * (subviews.count - 1) + rightPadding;
intrinsicHeight += ((UIView *)subviews.firstObject).intrinsicContentSize.height + bottomPadding;
}
return CGSizeMake(intrinsicWidth, intrinsicHeight);
}
- (void)layoutSubviews {
if (!self.singleLine) {
self.preferredMaxLayoutWidth = self.frame.size.width;
}
[super layoutSubviews];
[self layoutTags];
}
#pragma mark - Custom accessors
- (NSMutableArray *)tags {
if(!_tags) {
_tags = [NSMutableArray array];
}
return _tags;
}
- (void)setPreferredMaxLayoutWidth: (CGFloat)preferredMaxLayoutWidth {
if (preferredMaxLayoutWidth != _preferredMaxLayoutWidth) {
_preferredMaxLayoutWidth = preferredMaxLayoutWidth;
_didSetup = NO;
[self invalidateIntrinsicContentSize];
}
}
#pragma mark - Private
- (void)layoutTags {
if (self.didSetup || !self.tags.count) {
return;
}
NSArray *subviews = self.subviews;
UIView *previousView = nil;
CGFloat topPadding = self.padding.top;
CGFloat leftPadding = self.padding.left;
CGFloat rightPadding = self.padding.right;
CGFloat itemSpacing = self.interitemSpacing;
CGFloat lineSpacing = self.lineSpacing;
CGFloat currentX = leftPadding;
if (!self.singleLine && self.preferredMaxLayoutWidth > 0) {
for (UIView *view in subviews) {
CGSize size = view.intrinsicContentSize;
CGFloat width1 = self.isIntrinsicWidth?self.regularWidth:size.width;
CGFloat height1 = self.isIntrinsicHeight?self.regularHeight:size.height;
if (previousView) {
// CGFloat width = size.width;
currentX += itemSpacing;
if (currentX + width1 + rightPadding <= self.preferredMaxLayoutWidth) {
view.frame = CGRectMake(currentX, CGRectGetMinY(previousView.frame), width1, height1);
currentX += width1;
} else {
CGFloat width = MIN(width1, self.preferredMaxLayoutWidth - leftPadding - rightPadding);
view.frame = CGRectMake(leftPadding, CGRectGetMaxY(previousView.frame) + lineSpacing, width, height1);
currentX = leftPadding + width;
}
} else {
CGFloat width = MIN(width1, self.preferredMaxLayoutWidth - leftPadding - rightPadding);
view.frame = CGRectMake(leftPadding, topPadding, width, height1);
currentX += width;
}
previousView = view;
}
} else {
for (UIView *view in subviews) {
CGSize size = view.intrinsicContentSize;
view.frame = CGRectMake(currentX, topPadding, self.isIntrinsicWidth?self.regularWidth:size.width, self.isIntrinsicHeight?self.regularHeight:size.height);
currentX += self.isIntrinsicWidth?self.regularWidth:size.width;
previousView = view;
}
}
self.didSetup = YES;
}
#pragma mark - IBActions
- (void)onTag: (UIButton *)btn {
if (self.didTapTagAtIndex) {
self.didTapTagAtIndex([self.subviews indexOfObject: btn]);
}
}
#pragma mark - Public
- (void)addTag: (NMTag *)tag {
NSParameterAssert(tag);
NMTagButton *btn = [NMTagButton buttonWithTag: tag];
btn.userInteractionEnabled = !self.isTagBtnEnable;
[btn addTarget: self action: @selector(onTag:) forControlEvents: UIControlEventTouchUpInside];
[self addSubview: btn];
[self.tags addObject: tag];
self.didSetup = NO;
[self invalidateIntrinsicContentSize];
}
- (void)insertTag: (NMTag *)tag atIndex: (NSUInteger)index {
NSParameterAssert(tag);
if (index + 1 > self.tags.count) {
[self addTag: tag];
} else {
NMTagButton *btn = [NMTagButton buttonWithTag: tag];
[btn addTarget: self action: @selector(onTag:) forControlEvents: UIControlEventTouchUpInside];
[self insertSubview: btn atIndex: index];
[self.tags insertObject: tag atIndex: index];
self.didSetup = NO;
[self invalidateIntrinsicContentSize];
}
}
- (void)removeTag: (NMTag *)tag {
NSParameterAssert(tag);
NSUInteger index = [self.tags indexOfObject: tag];
if (NSNotFound == index) {
return;
}
[self.tags removeObjectAtIndex: index];
if (self.subviews.count > index) {
[self.subviews[index] removeFromSuperview];
}
self.didSetup = NO;
[self invalidateIntrinsicContentSize];
}
- (void)removeTagAtIndex: (NSUInteger)index {
if (index + 1 > self.tags.count) {
return;
}
[self.tags removeObjectAtIndex: index];
if (self.subviews.count > index) {
[self.subviews[index] removeFromSuperview];
}
self.didSetup = NO;
[self invalidateIntrinsicContentSize];
}
- (void)removeAllTags {
[self.tags removeAllObjects];
for (UIView *view in self.subviews) {
[view removeFromSuperview];
}
self.didSetup = NO;
[self invalidateIntrinsicContentSize];
}
@end
//
// SKSearchBar.h
// xiangwan
//
// Created by cqmac on 2019/9/23.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface SKSearchBar : UITextField <UITextFieldDelegate>
/// 最大字数,emoji算两个字,中英文都算一个字。
@property(nonatomic, assign) NSInteger maxLength;
/// 如果需要自定义UITextField的delegate,请用textField.bridgeDelegate = self 代替 textField.delegate = self
@property(nonatomic, weak) id<UITextFieldDelegate> bridgeDelegate;
@end
NS_ASSUME_NONNULL_END
//
// SKSearchBar.m
// xiangwan
//
// Created by cqmac on 2019/9/23.
// Copyright © 2019 mac. All rights reserved.
//
#import "SKSearchBar.h"
@interface SKSearchBar()
@end
@implementation SKSearchBar
- (instancetype)init {
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if(self = [super initWithFrame:frame]){
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
if(self = [super initWithCoder:aDecoder]){
[self setup];
}
return self;
}
- (void)setup{
_maxLength = 0;
[self addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
self.delegate = self;
[self initLeftIcon:@"public_s_search"];
}
- (void)initLeftIcon:(NSString *)leftIcon {
UIView *view = [[UIView alloc] init];
UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:leftIcon]];
[view addSubview:iv];
self.leftViewMode = UITextFieldViewModeAlways;
self.leftView = iv;
self.layer.masksToBounds = YES;
self.layer.cornerRadius = 5;
}
- (CGRect)leftViewRectForBounds:(CGRect)bounds {
CGRect leftRect = [super leftViewRectForBounds:bounds];
leftRect.origin.x += 10; //右边偏10
return leftRect;
}
//UITextField 文字与输入框的距离
- (CGRect)textRectForBounds:(CGRect)bounds{
return CGRectInset(bounds, 33, 0);
}
//控制文本的位置
- (CGRect)editingRectForBounds:(CGRect)bounds{
return CGRectInset(bounds, 33, 0);
}
- (CGRect)rightViewRectForBounds:(CGRect)bounds {
CGRect rightRect = [super rightViewRectForBounds:bounds];
rightRect.origin.x -= 10; //左边偏10
return rightRect;
}
/**
主要是用于中文输入的场景
剩余的允许输入的字数较少时,限制拼音字符的输入,提升体验
*/
- (NSInteger)allowMaxMarkLength:(NSInteger)remainLength{
NSInteger length = 0;
if(remainLength > 2){
length = NSIntegerMax;
}else if(remainLength > 0){
length = remainLength * 6; //一个中文对应的拼音一般不超过6个
}
return length;
}
- (void)textFieldDidChange:(UITextField *)textField
{
if(_maxLength <= 0){
return;
}
NSString *text = textField.text;
UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
//没有高亮选择的字,则对已输入的文字进行字数统计和限制,防止中文/emoj被截断
if (!position){
if (text.length > _maxLength){
NSRange rangeIndex = [text rangeOfComposedCharacterSequenceAtIndex:_maxLength];
if (rangeIndex.length == 1){
textField.text = [text substringToIndex:_maxLength];
}else{
if(_maxLength == 1){
textField.text = @"";
}else{
NSRange rangeRange = [text rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, _maxLength - 1 )];
textField.text = [text substringWithRange:rangeRange];
}
}
}
}
}
#pragma mark -- UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if([_bridgeDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]){
return [_bridgeDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
}
// if(_maxLength <= 0){
// //输入钱的正则表达式,可输入正负,小数点前5位,小数点后2位,位数可控
// NSString *toString = [textField.text stringByReplacingCharactersInRange:range withString:string];
// if (toString.length > 0) {
// NSString *stringRegex = @"(\\+|\\-)?(([0]|(0[.]\\d{0,2}))|([1-9]\\d{0,4}(([.]\\d{0,2})?)))?";
// NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", stringRegex];
// BOOL flag = [phoneTest evaluateWithObject:toString];
// if (!flag) {
// return NO;
// }
// }
// return YES;
// }
UITextRange *selectedRange = [textField markedTextRange];//高亮选择的字
UITextPosition *startPos = [textField positionFromPosition:selectedRange.start offset:0];
UITextPosition *endPos = [textField positionFromPosition:selectedRange.end offset:0];
NSInteger markLength = [textField offsetFromPosition:startPos toPosition:endPos];
NSInteger confirmlength = textField.text.length - markLength - range.length;//已经确认输入的字符长度
if(confirmlength >= _maxLength ){
return NO;
}
NSInteger allowMaxMarkLength = [self allowMaxMarkLength:_maxLength - confirmlength];
if(markLength > allowMaxMarkLength ){// && string.length > 0){
return NO;
}
return YES;
}
// return NO to disallow editing.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if([_bridgeDelegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]){
return [_bridgeDelegate textFieldShouldBeginEditing:textField];
}else{
return YES;
}
}
// became first responder
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if([_bridgeDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]){
[_bridgeDelegate textFieldDidBeginEditing:textField];
}
}
// return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if([_bridgeDelegate respondsToSelector:@selector(textFieldShouldEndEditing:)]){
return [_bridgeDelegate textFieldShouldEndEditing:textField];
}else{
return YES;
}
}
// may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if([_bridgeDelegate respondsToSelector:@selector(textFieldDidEndEditing:)]){
[_bridgeDelegate textFieldDidEndEditing:textField];
}
}
// called when clear button pressed. return NO to ignore (no notifications)
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
if([_bridgeDelegate respondsToSelector:@selector(textFieldShouldClear:)]){
return [_bridgeDelegate textFieldShouldClear:textField];
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if([_bridgeDelegate respondsToSelector:@selector(textFieldShouldReturn:)]){
return [_bridgeDelegate textFieldShouldReturn:textField];
}
return NO;
}
@end
//
// SearchTagView.h
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SearchTagModel.h"
#import "SearchTagHeaderModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface SearchTagView : UIView
@property (nonatomic, copy) void(^tagClick)(NSString * text);
@property (nonatomic, copy) void(^clearAll)(void);
@property (nonatomic, strong) NSArray *datas;
- (void)insertSection:(SearchTagHeaderModel *)item;
- (NSInteger)insertRow:(SearchTagModel *)item;
@end
NS_ASSUME_NONNULL_END
//
// SearchTagView.m
// xiangwan
//
// Created by mac on 2019/8/23.
// Copyright © 2019 mac. All rights reserved.
//
#import "SearchTagView.h"
#import "SearchTagViewCell.h"
#import "SearchTagHeaderModel.h"
#import "NMTag.h"
#import <UITableView+FDTemplateLayoutCell.h>
#define nScreenWidth UIScreen.mainScreen.bounds.size.width
@interface SearchTagView()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataSource;
@end
@implementation SearchTagView
- (instancetype)init
{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
[self addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.tableView registerClass:[SearchTagViewCell class] forCellReuseIdentifier:[self identifier]];
}
- (NSString *)identifier {
return [NSString stringWithFormat:@"%@Id",[SearchTagViewCell class]];
}
-(void)setDatas:(NSArray *)datas {
_datas = datas;
self.dataSource = [[NSMutableArray alloc] initWithArray:datas];
[self.tableView reloadData];
}
- (void)insertSection:(SearchTagHeaderModel *)item {
[self.dataSource insertObject:item atIndex:0];
NSIndexPath *insert = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[insert] withRowAnimation:UITableViewRowAnimationNone];
}
- (NSInteger)insertRow:(SearchTagModel *)item {
NSInteger idx = [self checkRepeat:item.tagText];
if (idx == -1) {
SearchTagHeaderModel *model = self.dataSource.firstObject;
NSMutableArray *ary = [[NSMutableArray alloc] initWithArray:model.tagModels];
if (ary.count > 9) {
[ary removeLastObject];
}
[ary insertObject:item atIndex:0];
model.tagModels = ary;
}
NSIndexPath *insert = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView reloadRowsAtIndexPaths:@[insert] withRowAnimation:UITableViewRowAnimationNone];
return idx;
}
- (NSInteger)checkRepeat:(NSString *)text {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"tagText = %@",text];
SearchTagHeaderModel *model = self.dataSource.firstObject;
NSArray *result = [model.tagModels filteredArrayUsingPredicate:predicate];
SearchTagModel *item = result.firstObject;
NSInteger index = [model.tagModels indexOfObject:item];
if (index < model.tagModels.count && index != 0) {
NSMutableArray *ary = [[NSMutableArray alloc] initWithArray:model.tagModels];
[ary exchangeObjectAtIndex:0 withObjectAtIndex:index];
model.tagModels = ary;
}
return (result.count == 0)?-1:index;
}
- (void)clearRecord {
[self.dataSource removeObjectAtIndex:0];
NSIndexPath *insert = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:@[insert] withRowAnimation:UITableViewRowAnimationNone];
!self.clearAll ?: self.clearAll();
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataSource.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SearchTagViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[self identifier]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.showClearBtn = (indexPath.row == 0 && self.dataSource.count > 1);
[self configCell:cell indexPath:indexPath];
@weakify(self);
cell.clearAction = ^{
@strongify(self);
[self clearRecord];
};
return cell;
}
- (void)configCell:(SearchTagViewCell *)cell indexPath:(NSIndexPath *)indexPath
{
[cell.tagView removeAllTags];
cell.tagView.preferredMaxLayoutWidth = nScreenWidth-32;
//cell.tagView.padding = UIEdgeInsetsMake(0, 0, 0, 0);
cell.tagView.lineSpacing = 10;
cell.tagView.interitemSpacing = 10;
cell.tagView.singleLine = NO;
// 给出两个字段,如果给的是0,那么就是变化的,如果给的不是0,那么就是固定的
// cell.tagView.regularWidth = 80;
// cell.tagView.regularHeight = 30;
SearchTagHeaderModel *model = self.dataSource[indexPath.row];
cell.headerLb.text = model.headerText;
NSArray *arr = model.tagModels;
@weakify(self);
[arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
@strongify(self);
SearchTagModel *subModel = arr[idx];
NMTag *tag = [self createTag:subModel.tagText];
[cell.tagView addTag:tag];
}];
cell.tagView.didTapTagAtIndex = ^(NSUInteger index) {
@strongify(self);
SearchTagModel *subModel = arr[index];
[self cellAction:subModel];
};
}
- (void)cellAction:(SearchTagModel *)model {
if (self.tagClick) {
self.tagClick(model.tagText);
}
}
- (NMTag *)createTag:(NSString *)text {
NMTag *tag = [[NMTag alloc] initWithText:text];
tag.font = [UIFont systemFontOfSize:14];
tag.textColor = [UIColor colorWithRed:34.0/255 green:34.0/255 blue:34.0/255 alpha:1];
tag.bgColor = [UIColor colorWithRed:249.0/255 green:249.0/255 blue:249.0/255 alpha:1];
tag.cornerRadius = 8;
tag.enable = YES;
tag.padding = UIEdgeInsetsMake(6, 16, 6, 16);
return tag;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
@weakify(self);
return [tableView fd_heightForCellWithIdentifier:[self identifier] configuration:^(id cell) {
@strongify(self);
[self configCell:cell indexPath:indexPath];
}];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(UITableView *)tableView {
if (_tableView == nil) {
_tableView = [[UITableView alloc] init];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.tableFooterView = [UIView new];
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
return _tableView;
}
-(NSMutableArray *)dataSource {
if (_dataSource == nil) {
_dataSource = [[NSMutableArray alloc] init];
}
return _dataSource;
}
@end
//
// JYSearchViewController.h
// Mall-iOS
//
// Created by Nemo on 2020/10/16.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface JYSearchViewController : UIViewController
+ (instancetype)jySearchViewController;
@end
NS_ASSUME_NONNULL_END
//
// JYSearchViewController.m
// Mall-iOS
//
// Created by Nemo on 2020/10/16.
//
#import "JYSearchViewController.h"
#import "SearchTagView.h"
#import "SKSearchBar.h"
#import <QMUIKit.h>
@interface JYSearchViewController ()
@property (nonatomic, weak) SKSearchBar *search;
@property (nonatomic, weak) SearchTagView *tagView;
@property (nonatomic, weak) UIButton *searchBtn;
@property (nonatomic, strong) NSMutableArray *historys;
@property (nonatomic, strong) NSMutableArray *searchDataSource;
@property (nonatomic, assign) NSInteger index;
@end
@implementation JYSearchViewController
+ (instancetype)jySearchViewController {
//HomeViewModel *viewModel = [[HomeViewModel alloc] initServices:[[HomeServices alloc] init]];
return [[self alloc] init];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
}
- (void)createTagView {
SearchTagView *tagView = [[SearchTagView alloc] init];
[self.view addSubview:tagView];
self.tagView = tagView;
@weakify(self);
tagView.tagClick = ^(NSString * _Nonnull text) {
@strongify(self);
self.search.text = text;
//[self searchAction];
};
tagView.clearAll = ^{
@strongify(self);
[self.historys removeAllObjects];
[self.searchDataSource removeObjectAtIndex:0];
//[[DatabaseCenter sharedDatabaseCenter].historyDBMager deleteAllConditions:nil];
};
/**
[tagView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithActionBlock:^(id _Nonnull sender) {
@strongify(self);
[self.search resignFirstResponder];
}]];
*/
[tagView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.mas_equalTo(0);
make.bottom.inset(291);
}];
}
- (void)initData {
self.historys = [[NSMutableArray alloc] initWithArray:@[]];
NSArray *hotWords = @[];
if (hotWords.count == 0) {
hotWords = @[@{@"text":@"吃饭"},@{@"text":@"喝东西"},@{@"text":@"唱歌"}];
}
self.searchDataSource = [[NSMutableArray alloc] init];
if (self.historys.count > 0) {
[self.searchDataSource addObject:@{@"data":self.historys,@"title":@"历史记录"}];
}
[self.searchDataSource addObject:@{@"data":hotWords,@"title":@"热搜"}];
NSMutableArray *arry = [[NSMutableArray alloc] init];
for (int i = 0; i < self.searchDataSource.count; i ++) {
NSDictionary *dict = self.searchDataSource[i];
SearchTagHeaderModel *model = [[SearchTagHeaderModel alloc] init];
model.headerText = dict[@"title"];
NSMutableArray *ary = [[NSMutableArray alloc] init];
NSArray *datas = dict[@"data"];
for (int j = 0; j < datas.count; j ++) {
NSDictionary *dt = datas[j];
SearchTagModel *subMdl = [[SearchTagModel alloc] init];
subMdl.tagText = dt[@"text"];
[ary addObject:subMdl];
}
model.tagModels = ary;
[arry addObject:model];
}
self.tagView.datas = arry;
}
@end
//
// HomeMainMacro.h
// Mall-iOS
//
// Created by Nemo on 2020/10/21.
//
#ifndef HomeMainMacro_h
#define HomeMainMacro_h
#ifdef DEBUG
#define NSLog(format, ...) printf("[%s] %s [第%d行] %s\n", __TIME__, __FUNCTION__, __LINE__, [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String]);
#else
#define NSLog(format, ...)
#endif
#endif /* HomeMainMacro_h */
//
// Interface.h
//
#ifndef Interface_h
#define Interface_h
#import <UIKit/UIKit.h>
#pragma mark ****** 接口信息 ******
#if DevelopMent ==0
/*********正式环境*********/ // 119.23.50.171
//域名 app.xwattendit.com
#define API_HOST @"https://dev.changein.cn/pw-weapp-api"
#elif DevelopMent ==1
/*********开发环境*********/
#define API_HOST @"https://dev.changein.cn/pw-weapp-api"
#else
/*********测试环境*********/
#define API_HOST @"https://dev.changein.cn/pw-weapp-api"
#endif
#pragma mark - ——————— 详细接口地址 ————————
//测试接口
CG_INLINE NSString * URLTest() {
return @"/api/";
}
#pragma mark - ——————— 1.首页相关 ————————
//首页接口
CG_INLINE NSString * URLShopping() {
return @"/shoppingMall/index/shoppingMallIndexAdv";
}
//获取热门关键词列表
CG_INLINE NSString * URLHotWordList() {
return @"/pw-weapp-api/search/getHotWordList";
}
#pragma mark - ——————— 其他相关 ————————
#endif /* Interface_h */
//
// MacroDefinition.h
// CQ_App
//
// Created by mac on 2019/3/20.
// Copyright © 2019年 mac. All rights reserved.
//
#ifndef MacroDefinition_h
#define MacroDefinition_h
#pragma mark ****** 宏方法 ******
//iOS 11.0 配置
#define AdjustsScrollViewInsetNever(controller,view) if(@available(iOS 11.0, *)) {view.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;} else if([controller isKindOfClass:[UIViewController class]]) {controller.automaticallyAdjustsScrollViewInsets = false;}
#define kStatusBarAndNavigationBarHeight (nScreenHeight() >= 812.0 ? 88.f : 64.f)
#define kSafeAreaBottomHeight (nScreenHeight() >= 812.0 ? 34.0f : 0.0)
#define kTabbarHeight (nScreenHeight() >= 812.0 ? 83.f : 49.f)
//数据验证
#define StrValid(f) (f!=nil && [f isKindOfClass:[NSString class]] && ![f isEqualToString:@""])
#define SafeStr(f) (StrValid(f) ? f:@"")
#define HasString(str,key) ([str rangeOfString:key].location!=NSNotFound)
#define ValidStr(f) StrValid(f)
#define ValidDict(f) (f!=nil && [f isKindOfClass:[NSDictionary class]] && [f count]>0)
#define ValidArray(f) (f!=nil && [f isKindOfClass:[NSArray class]] && [f count]>0)
#define ValidNum(f) (f!=nil && [f isKindOfClass:[NSNumber class]])
#define ValidClass(f,cls) (f!=nil && [f isKindOfClass:[cls class]])
#define ValidData(f) (f!=nil && [f isKindOfClass:[NSData class]])
//单例化一个类
#define SINGLETON_FOR_HEADER(className) \
\
+ (className *)shared##className;
#define SINGLETON_FOR_CLASS(className) \
static className *shared##className = nil;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
if (shared##className == nil) {\
shared##className = [super allocWithZone:zone];\
}\
});\
return shared##className;\
}\
+(instancetype)shared##className\
{\
return [[self alloc] init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return shared##className;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return shared##className;\
}
#pragma mark ————— 获取系统对象内联方法 —————
CG_INLINE UIWindow *kGetLastWindow() {
UIWindow *lastWindow = [UIApplication sharedApplication].keyWindow;
if (!lastWindow) {
lastWindow = [UIApplication sharedApplication].windows.lastObject;
}
return lastWindow;
}
CG_INLINE UIApplication *kApplication() {
return [UIApplication sharedApplication];
}
CG_INLINE UIView *kAppWindow() {
return [UIApplication sharedApplication].delegate.window;
}
CG_INLINE UIViewController *kRootViewController() {
return [UIApplication sharedApplication].delegate.window.rootViewController;
}
/**
CG_INLINE CGFloat nScreenWidth() {
return SCREEN_WIDTH;
}
CG_INLINE CGFloat nScreenHeight() {
return YYScreenSize().height;
}
*/
CG_INLINE CGFloat kSafeAreaTopHeight() {
return [[UIApplication sharedApplication] statusBarFrame].size.height;
}
/**
CG_INLINE CGFloat tabBarHeight() {
return 40+(nScreenHeight() >= 812.0 ? 34.0f : 5.0);
}
CG_INLINE CGFloat kKeyboardHeight() {
if(nScreenHeight() == 812 && nScreenWidth() == 375){
return 291.f;
}else if(nScreenHeight() == 736 && nScreenWidth() == 414){
return 216.f;
}else if(nScreenHeight() == 667 && nScreenWidth() == 375){
return 216.f;
}else if(nScreenHeight() == 568 && nScreenWidth() == 320){
return 253.f;
}else{
return 216.f;
}
}
*/
#pragma mark - ——————— 字体内联方法 ————————
CG_INLINE UIFont *FONTSIZE(CGFloat a) {
return [UIFont fontWithName:@"PingFangSC-Regular" size:a];
}
CG_INLINE UIFont *FONTBOLDSIZE(CGFloat a) {
return [UIFont fontWithName:@"PingFangSC-Semibold" size:a];
}
#pragma mark ————— UICOLOR内联方法 —————
/**
* 输入RGBA值获取颜色
*
* @param r RED值
* @param g GREEN值
* @param b BLUE值
* @param a 透明度
*
* @return UIColor
*/
CG_INLINE UIColor * RGBACOLOR(CGFloat r,CGFloat g,CGFloat b,CGFloat a) {
return [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:(a)];
}
/**
输入RGB值获取颜色
@param r RED值
@param g GREEN值
@param b BLUE值
@return UIColor
*/
CG_INLINE UIColor * RGBCOLOR(CGFloat r,CGFloat g,CGFloat b) {
return [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1];
}
/**
* 输入16进制值获取颜色
*
* @param rgbValue 16进制值
*
* @return UIColor
*/
CG_INLINE UIColor * HEXCOLOR(NSUInteger rgbValue) {
return [UIColor colorWithRed:(((float)((rgbValue & 0xFF0000) >> 16))) / 255.0f green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0f blue:((float)(rgbValue & 0xFF)) / 255.0f alpha:1];
}
/**
随机颜色
@return 随机颜色
*/
CG_INLINE UIColor * RandomColor() {
return [UIColor colorWithRed:arc4random_uniform(256) / 255.0f green:arc4random_uniform(256) / 255.0f blue:arc4random_uniform(256) / 255.0f alpha:1];
}
#pragma mark ————— 通知中心 —————
/**
通知中心
@return NSNotificationCenter
*/
CG_INLINE NSNotificationCenter * KNOTE() {
return [NSNotificationCenter defaultCenter];
}
/**
通知中心发送通知
@param name 通知名称
@param obj 通知参数
*/
CG_INLINE void KNOTEPost(NSString *name,id obj) {
[[NSNotificationCenter defaultCenter] postNotificationName:name object:obj];
}
/**
通知中心发送通知
@param name 通知名称
@param obj 通知参数
@param userInfo 传递参数
*/
CG_INLINE void KNOTEPostUserInfo(NSString *name,id obj, NSDictionary *userInfo) {
[[NSNotificationCenter defaultCenter] postNotificationName:name object:obj userInfo:userInfo];
}
/**
移除通知监听
@param name 通知名称
*/
CG_INLINE void KNOTERemoveObserver(NSString *name,id _self) {
[[NSNotificationCenter defaultCenter] removeObserver:_self name:name object:nil];
}
/**
添加通知观察者
@param observer 观察对象
@param selector 相应事件
@param name 通知名称
*/
CG_INLINE void KNOTEAddObserver(NSString *name,NSString *selector,id observer) {
[[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(selector) name:name object:nil];
}
#pragma mark ————— 偏好设置UserDefault —————
/**
用户设置偏好设置
@param keyName 偏好名称
@param object 值
*/
CG_INLINE void UserDefaults_Set_WithKey(NSString *keyName,id object) {
[[NSUserDefaults standardUserDefaults] setObject:object forKey:keyName];
[[NSUserDefaults standardUserDefaults] synchronize];
}
/**
用户设置偏好获取
@param keyName 偏好名称
*/
CG_INLINE id UserDefaults_Get_WithKey(NSString *keyName) {
return [[NSUserDefaults standardUserDefaults] objectForKey:keyName];
}
/**
用户设置偏好删除
@param keyName 偏好名称
*/
CG_INLINE void UserDefaults_Del_WithKey(NSString *keyName) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:keyName];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark ————— 多线程内联函数 —————
//GCD - 一次性执行
CG_INLINE void kDISPATCH_ONCE_BLOCK(dispatch_block_t onceBlock) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, onceBlock);
}
//GCD - 在Main线程上运行
CG_INLINE void kDISPATCH_MAIN_THREAD(dispatch_block_t block) {
dispatch_async(dispatch_get_main_queue(), block);
}
//GCD - 开启异步线程
CG_INLINE void kDISPATCH_GLOBAL_QUEUE_DEFAULT(dispatch_block_t block) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
}
//GCD - 延时
CG_INLINE void kDISPATCH_AFTER(CGFloat seconds,dispatch_block_t block) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(seconds * NSEC_PER_SEC)), dispatch_get_main_queue(), block);
}
//基础数据转字符串
CG_INLINE NSString *IntegerString(NSInteger integer) {
return [NSString stringWithFormat:@"%li",integer];
}
//CGFloat转字符串
CG_INLINE NSString *FloatString(CGFloat f) {
return [NSString stringWithFormat:@"%.f",f];
}
//弱引用
#define WeakSelf __weak typeof(self) weakSelf = self;
#define StrongSelf __strong typeof(weakSelf) strongSelf = weakSelf;
#ifdef DEBUG
#define NSLog(format, ...) printf("[%s] %s [第%d行] %s\n", __TIME__, __FUNCTION__, __LINE__, [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String]);
#else
#define NSLog(format, ...)
#endif
#endif /* MacroDefinition_h */
//
// PrefixHeader.pch
// CQ_App
//
// Created by mac on 2019/3/20.
// Copyright © 2019年 mac. All rights reserved.
//
#ifndef PrefixHeader_pch
#define PrefixHeader_pch
#pragma mark -----界面相关-----
#import "HomeMainMacro.h"
#pragma mark -----网络相关-----
#import "Interface.h"
#pragma mark -----其他-----
#endif /* PrefixHeader_pch */
//
// UICollectionReusableView+Extension.h
// xiangwan
//
// Created by mac on 2019/8/27.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UICollectionReusableView (Extension)
/// Footer Class注册方法
+ (void)registerClassFooterForCollectionView:(UICollectionView *)collectionView;
/// Header Class注册方法
+ (void)registerClassHeaderForCollectionView:(UICollectionView *)collectionView;
/// Footer Nib注册方法
+ (void)registerNibFooterForCollectionView:(UICollectionView *)collectionView;
/// Header Nib注册方法
+ (void)registerNibHeaderForCollectionView:(UICollectionView *)collectionView;
+(instancetype)dequeueReusableSupplementaryHeaderViewOfKind:(UICollectionView *)collectionView index:(NSIndexPath *)indexPath;
+(instancetype)dequeueReusableSupplementaryFooterViewOfKind:(UICollectionView *)collectionView index:(NSIndexPath *)indexPath;
@end
NS_ASSUME_NONNULL_END
//
// UICollectionReusableView+Extension.m
// xiangwan
//
// Created by mac on 2019/8/27.
// Copyright © 2019 mac. All rights reserved.
//
#import "UICollectionReusableView+Extension.h"
@implementation UICollectionReusableView (Extension)
+ (void)registerClassFooterForCollectionView:(UICollectionView *)collectionView {
[collectionView registerClass:self forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:[self identifier]];
}
+ (void)registerNibFooterForCollectionView:(UICollectionView *)collectionView {
[collectionView registerNib:[UINib nibWithNibName:[self className]
bundle:[NSBundle mainBundle]] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:[self identifier]];
}
+ (void)registerNibHeaderForCollectionView:(UICollectionView *)collectionView {
[collectionView registerNib:[UINib nibWithNibName:[self className]
bundle:[NSBundle mainBundle]] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[self identifier]];
}
+ (void)registerClassHeaderForCollectionView:(UICollectionView *)collectionView {
[collectionView registerClass:self forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[self identifier]];
}
+ (instancetype)dequeueReusableSupplementaryHeaderViewOfKind:(UICollectionView *)collectionView index:(NSIndexPath *)indexPath{
return [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[self identifier] forIndexPath:indexPath];
}
+ (instancetype)dequeueReusableSupplementaryFooterViewOfKind:(UICollectionView *)collectionView index:(NSIndexPath *)indexPath {
return [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:[self identifier] forIndexPath:indexPath];
}
+ (NSString *)identifier {
return [NSString stringWithFormat:@"%@Id",[self className]];
}
+ (NSString *)className {
return NSStringFromClass(self);
}
@end
//
// UICollectionViewCell+Extension.h
// xiangwan
//
// Created by mac on 2019/8/17.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UICollectionViewCell (Extension)
/// cell Class注册方法
+ (void)registerClassForCollectionView:(UICollectionView *)collectionView;
/// cell Nib注册方法
+ (void)registerNibForCollectionView:(UICollectionView *)collectionView;
+ (NSString *)identifier;
@end
NS_ASSUME_NONNULL_END
//
// UICollectionViewCell+Extension.m
// xiangwan
//
// Created by mac on 2019/8/17.
// Copyright © 2019 mac. All rights reserved.
//
#import "UICollectionViewCell+Extension.h"
@implementation UICollectionViewCell (Extension)
+ (void)registerClassForCollectionView:(UICollectionView *)collectionView {
[collectionView registerClass:self forCellWithReuseIdentifier:[self identifier]];
}
+ (void)registerNibForCollectionView:(UICollectionView *)collectionView {
[collectionView registerNib:[UINib nibWithNibName:[self className]
bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:[self identifier]];
}
+ (NSString *)identifier {
return [NSString stringWithFormat:@"%@Id",[self className]];
}
+ (NSString *)className {
return NSStringFromClass(self);
}
@end
//
// UITableViewCell+Extension.m
// xiangwan
//
// Created by mac on 2019/8/17.
// Copyright © 2019 mac. All rights reserved.
//
#import "UITableViewCell+Extension.h"
@implementation UITableViewCell (Extension)
+ (void)registerClassForTableView:(UITableView *)tableView {
[tableView registerClass:self forCellReuseIdentifier:[self identifier]];
}
+ (void)registerNibForTableView:(UITableView *)tableView {
[tableView registerNib:[UINib nibWithNibName:[self className]
bundle:[NSBundle mainBundle]] forCellReuseIdentifier:[self identifier]];
}
+ (NSString *)identifier {
return [NSString stringWithFormat:@"%@Id",[self className]];
}
+ (NSString *)className {
return NSStringFromClass(self);
}
@end
//
// UITableViewHeaderFooterView+Extension.h
// xiangwan
//
// Created by mac on 2019/10/8.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITableViewHeaderFooterView (Extension)
/// Class注册方法
+ (void)registerClassHeaderFooterForTableView:(UITableView *)tableView;
/// Nib注册方法
+ (void)registerNibHeaderFooterForTableView:(UITableView *)tableView;
+ (NSString *)identifier;
@end
NS_ASSUME_NONNULL_END
//
// UITableViewHeaderFooterView+Extension.m
// xiangwan
//
// Created by mac on 2019/10/8.
// Copyright © 2019 mac. All rights reserved.
//
#import "UITableViewHeaderFooterView+Extension.h"
@implementation UITableViewHeaderFooterView (Extension)
+ (void)registerClassHeaderFooterForTableView:(UITableView *)tableView {
[tableView registerClass:self forHeaderFooterViewReuseIdentifier:[self identifier]];
}
+ (void)registerNibHeaderFooterForTableView:(UITableView *)tableView {
[tableView registerNib:[UINib nibWithNibName:[self className]
bundle:[NSBundle mainBundle]] forHeaderFooterViewReuseIdentifier:[self identifier]];
}
+ (NSString *)identifier {
return [NSString stringWithFormat:@"%@Id",[self className]];
}
+ (NSString *)className {
return NSStringFromClass(self);
}
@end
//
// UIImage+Extension.h
// xiangwan
//
// Created by mac on 2019/8/5.
// Copyright © 2019 mac. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (Extension)
+ (UIImage *)imageWithColor:(UIColor *)color;
// 生成二维码
+ (UIImage *)generateQRCode:(NSString *)code size:(CGSize)size;
//生成一个圆角图片
- (UIImage *)circleImage;
///毛玻璃
- (UIImage *)blurryImage:(UIImage *)image withBlurLevel:(CGFloat)blur;
///根据颜色和圆的半径来创建一个圆形图片
+ (UIImage *)createImageWithColor:(UIColor *)color radius:(CGFloat)radius;
///根据一个view来创建一个 Image
+ (UIImage*)creatImageWithView:(UIView *)theView;
/**
图片组 本地
@param array 原生image arr
@param bgColor 新生成image 背景色
@return image 组合
*/
+ (UIImage *)groupIconWith:(NSArray *)array bgColor:(UIColor *)bgColor;
/**
图片组 本地
@param corner 新生成组合图片背景圆角
@param array 原生image arr
@param bgColor 新生成image 背景色
@return image 组合
*/
+ (UIImage *)groupIconWith:(NSArray *)array corner:(CGFloat)corner bgColor:(UIColor *)bgColor;
/**
图片组合 网络请求,使用SD缓存到本地磁盘,请求前先去缓存中哈希查找是否有缓存
@param URLArray 图片url 数组
@param corner 新生成组合图片背景圆角
@param bgColor 新生成组合图片背景颜色
@param Success 组合成功回调
@param Failed 组合失败回调
*/
+ (void )groupIconWithURLArray:(NSArray *)URLArray
corner:(CGFloat)corner
bgColor:(UIColor *)bgColor
Success:(void(^)(UIImage *image))Success
Failed:(void(^)(NSString *fail))Failed;
/**
图片组合 网络请求,使用SD缓存到本地磁盘,请求前先去缓存中哈希查找是否有缓存
@param URLArray 图片url 数组
@param bgColor 新生成组合图片背景颜色
@param Success 组合成功回调
@param Failed 组合失败回调
*/
+ (void)groupIconWithURLArray:(NSArray *)URLArray
bgColor:(UIColor *)bgColor
Success:(void(^)(UIImage *image))Success
Failed:(void(^)(NSString *fail))Failed;
/// 旋转90度
- (UIImage *)normalizedImage;
/// 压缩图片使图片文件小于指定大小
- (NSData *)compressWithMaxLength:(NSUInteger)maxLength;
/**
缓存图片到SDWebImage
@param url 图片url(如:files/activityPic/xxxx/xxx.jpg)
*/
- (void)cacheImageWithUrl:(NSString *)url;
@end
NS_ASSUME_NONNULL_END
//
// AttributLabel.h
// CQ_App
//
// Created by mac on 2019/6/25.
// Copyright © 2019 mac. All rights reserved.
......
//
// AttributLabel.m
// CQ_App
//
// Created by mac on 2019/6/25.
// Copyright © 2019 mac. All rights reserved.
//
#import "AttributLabel.h"
#import "MacroDefinition.h"
#import <NMCategories/NMCategories.h>
@implementation AttributLabel
-(void)setSolidString:(NSString *)solidString {
_solidString = solidString;
NSAttributedString *attrStr = [[NSAttributedString alloc]initWithString:solidString attributes: @{NSFontAttributeName:FONTSIZE(12.0f),NSForegroundColorAttributeName:[UIColor redColor],NSStrikethroughStyleAttributeName:@(NSUnderlineStyleSingle|NSUnderlinePatternSolid),NSStrikethroughColorAttributeName:[UIColor redColor]}];
NSAttributedString *attrStr = [[NSAttributedString alloc]initWithString:solidString attributes: @{NSFontAttributeName:FONTSIZE(14),NSForegroundColorAttributeName:[UIColor redColor],NSStrikethroughStyleAttributeName:@(NSUnderlineStyleSingle|NSUnderlinePatternSolid),NSStrikethroughColorAttributeName:[UIColor redColor]}];
self.attributedText = attrStr;
}
......
//
// QMUIConfigurationTemplate.h
//
// Created by QMUI Team on 15/3/29.
// Copyright (c) 2015年 QMUI Team. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <QMUIKit/QMUIKit.h>
#import <NMTheme/NMThemeProtocol.h>
/**
* QMUIConfigurationTemplate 是一份配置表,用于配合 QMUIConfiguration 来管理整个 App 的全局样式,使用方式:
* 在 QMUI 项目代码的文件夹里找到 QMUIConfigurationTemplate 目录,把里面所有文件复制到自己项目里,保证能被编译到即可,不需要在某些地方 import,也不需要手动运行。
*
* @warning 更新 QMUIKit 的版本时,请留意 Release Log 里是否有提醒更新配置表,请尽量保持自己项目里的配置表与 QMUIKit 里的配置表一致,避免遗漏新的属性。
* @warning 配置表的 class 名必须以 QMUIConfigurationTemplate 开头,并且实现 <QMUIConfigurationTemplateProtocol>,因为这两者是 QMUI 识别该 NSObject 是否为一份配置表的条件。
* @warning QMUI 2.3.0 之后,配置表改为自动运行,不需要再在某个地方手动运行了。
*/
@interface QMUIConfigurationTemplate : NSObject<NMThemeProtocol>
@end
This diff is collapsed.
//
// QMUIConfigurationTemplate.h
//
// Created by QMUI Team on 15/3/29.
// Copyright (c) 2015年 QMUI Team. All rights reserved.
//
#import "QMUIConfigurationTemplate.h"
@interface QMUIConfigurationTemplateDark : QMUIConfigurationTemplate
@end
//
// QMUIConfigurationTemplate.m
// qmui
//
// Created by QMUI Team on 15/3/29.
// Copyright (c) 2015年 QMUI Team. All rights reserved.
//
#import "QMUIConfigurationTemplateDark.h"
#import <NMTheme/NMCommonUI.h>
@implementation QMUIConfigurationTemplateDark
#pragma mark - <QMUIConfigurationTemplateProtocol>
- (void)applyConfigurationTemplate {
[super applyConfigurationTemplate];
QMUICMI.keyboardAppearance = UIKeyboardAppearanceDark;
//QMUICMI.navBarBackgroundImage = nil;
QMUICMI.navBarStyle = UIBarStyleBlack;
QMUICMI.navBarBarTintColor = UIColorBlack;
QMUICMI.tabBarBackgroundImage = nil;
QMUICMI.tabBarStyle = UIBarStyleBlack;
QMUICMI.toolBarStyle = UIBarStyleBlack;
}
// QMUI 2.3.0 版本里,配置表新增这个方法,返回 YES 表示在 App 启动时要自动应用这份配置表。仅当你的 App 里存在多份配置表时,才需要把除默认配置表之外的其他配置表的返回值改为 NO。
- (BOOL)shouldApplyTemplateAutomatically {
[QMUIThemeManagerCenter.defaultThemeManager addThemeIdentifier:self.themeName theme:self];
NSString *selectedThemeIdentifier = [[NSUserDefaults standardUserDefaults] stringForKey:NMSelectedThemeIdentifier];
BOOL result = [selectedThemeIdentifier isEqualToString:self.themeName];
if (result) {
QMUIThemeManagerCenter.defaultThemeManager.currentTheme = self;
}
return result;
}
#pragma mark - <QDThemeProtocol>
- (UIColor *)themeBackgroundColor {
return UIColorBlack;
}
- (UIColor *)themeBackgroundColorLighten {
return UIColorMake(28, 28, 30);
}
- (UIColor *)themeBackgroundColorHighlighted {
return UIColorMake(48, 49, 51);
}
- (UIColor *)themeTintColor {
return UIColorTheme10;
}
- (UIColor *)themeTitleTextColor {
return UIColorDarkGray1;
}
- (UIColor *)themeMainTextColor {
return UIColorDarkGray3;
}
- (UIColor *)themeDescriptionTextColor {
return UIColorDarkGray6;
}
- (UIColor *)themePlaceholderColor {
return UIColorDarkGray8;
}
- (UIColor *)themeCodeColor {
return self.themeTintColor;
}
- (UIColor *)themeSeparatorColor {
return UIColorMake(46, 50, 54);
}
- (NSString *)themeName {
return NMThemeIdentifierDark;
}
@end
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "check_f.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "check_t.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment