diff --git a/CustomKeyboard/Info.plist b/CustomKeyboard/Info.plist index c25c1ec..6b0b101 100644 --- a/CustomKeyboard/Info.plist +++ b/CustomKeyboard/Info.plist @@ -2,6 +2,10 @@ + LSApplicationQueriesSchemes + + kbkeyboardAppExtension + NSExtension NSExtensionAttributes diff --git a/CustomKeyboard/KeyboardViewController.m b/CustomKeyboard/KeyboardViewController.m index 320d2bf..e27dcff 100644 --- a/CustomKeyboard/KeyboardViewController.m +++ b/CustomKeyboard/KeyboardViewController.m @@ -14,6 +14,7 @@ #import "Masonry.h" #import "KBAuthManager.h" #import "KBFullAccessManager.h" +#import "KBSkinManager.h" static CGFloat KEYBOARDHEIGHT = 256 + 20; @@ -22,6 +23,7 @@ static CGFloat KEYBOARDHEIGHT = 256 + 20; @property (nonatomic, strong) KBKeyBoardMainView *keyBoardMainView; // 功能面板视图(点击工具栏第0个时显示) @property (nonatomic, strong) KBFunctionView *functionView; // 功能面板视图(点击工具栏第0个时显示) @property (nonatomic, strong) KBSettingView *settingView; // 设置页 +@property (nonatomic, strong) UIImageView *bgImageView; // 背景图(在底层) @end @implementation KeyboardViewController @@ -40,12 +42,32 @@ static CGFloat KEYBOARDHEIGHT = 256 + 20; __unused id token = [[NSNotificationCenter defaultCenter] addObserverForName:KBFullAccessChangedNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(__unused NSNotification * _Nonnull note) { // 如需,可在此刷新与完全访问相关的 UI }]; + + // 皮肤变化时,立即应用 + __unused id token2 = [[NSNotificationCenter defaultCenter] addObserverForName:KBSkinDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(__unused NSNotification * _Nonnull note) { + [self kb_applyTheme]; + }]; + [self kb_applyTheme]; } - (void)setupUI { - // 固定键盘整体高度 - [self.view.heightAnchor constraintEqualToConstant:KEYBOARDHEIGHT].active = YES; + // 固定键盘整体高度;为减少与系统自调整高度产生的告警,将优先级设置为 High + NSLayoutConstraint *h = [self.view.heightAnchor constraintEqualToConstant:KEYBOARDHEIGHT]; + h.priority = UILayoutPriorityDefaultHigh; // 750 + h.active = YES; + // 关闭 UIInputView 自适应(某些系统版本会尝试放大为全屏高度导致冲突) + if ([self.view isKindOfClass:[UIInputView class]]) { + UIInputView *iv = (UIInputView *)self.view; + if ([iv respondsToSelector:@selector(setAllowsSelfSizing:)]) { + iv.allowsSelfSizing = NO; + } + } + // 背景图铺底 + [self.view addSubview:self.bgImageView]; + [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; // 预置功能面板(默认隐藏),与键盘区域共享相同布局 self.functionView.hidden = YES; [self.view addSubview:self.functionView]; @@ -209,7 +231,8 @@ static CGFloat KEYBOARDHEIGHT = 256 + 20; } - (void)kb_tryOpenContainerForLoginIfNeeded { - NSURL *url = [NSURL URLWithString:@"kbkeyboard://login?src=keyboard"]; + // 使用与主 App 一致的自定义 Scheme + NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@@//login?src=keyboard", KB_APP_SCHEME]]; if (!url) return; __weak typeof(self) weakSelf = self; [self.extensionContext openURL:url completionHandler:^(__unused BOOL success) { @@ -217,4 +240,40 @@ static CGFloat KEYBOARDHEIGHT = 256 + 20; __unused typeof(weakSelf) selfStrong = weakSelf; }]; } + +#pragma mark - Theme + +- (void)kb_applyTheme { + KBSkinTheme *t = [KBSkinManager shared].current; + UIImage *img = [[KBSkinManager shared] currentBackgroundImage]; + self.bgImageView.image = img; + BOOL hasImg = (img != nil); + self.view.backgroundColor = hasImg ? [UIColor clearColor] : t.keyboardBackground; + self.keyBoardMainView.backgroundColor = hasImg ? [UIColor clearColor] : t.keyboardBackground; + // 触发键区按主题重绘 + if ([self.keyBoardMainView respondsToSelector:@selector(kb_applyTheme)]) { + // method declared in KBKeyBoardMainView.h + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [self.keyBoardMainView performSelector:@selector(kb_applyTheme)]; + #pragma clang diagnostic pop + } + if ([self.functionView respondsToSelector:@selector(kb_applyTheme)]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [self.functionView performSelector:@selector(kb_applyTheme)]; +#pragma clang diagnostic pop + } +} + +#pragma mark - Lazy + +- (UIImageView *)bgImageView { + if (!_bgImageView) { + _bgImageView = [[UIImageView alloc] init]; + _bgImageView.contentMode = UIViewContentModeScaleAspectFill; + _bgImageView.clipsToBounds = YES; + } + return _bgImageView; +} @end diff --git a/CustomKeyboard/PrefixHeader.pch b/CustomKeyboard/PrefixHeader.pch index 5d96a48..4623ba0 100644 --- a/CustomKeyboard/PrefixHeader.pch +++ b/CustomKeyboard/PrefixHeader.pch @@ -23,9 +23,15 @@ // 通用链接(Universal Links)统一配置 // 配置好 AASA 与 Associated Domains 后,只需修改这里即可切换域名/path。 -#define KB_UL_BASE @"https://your.domain/ul" // 替换为你的真实域名与前缀路径 +#define KB_UL_BASE @"https://app.tknb.net/ul" // 与 Associated Domains 一致 #define KB_UL_LOGIN KB_UL_BASE @"/login" #define KB_UL_SETTINGS KB_UL_BASE @"/settings" +// 在扩展内,启用 URL Bridge(仅在显式的用户点击动作中使用) +// 这样即便宿主 App(如备忘录)拒绝 extensionContext 的 openURL,仍可通过响应链兜底拉起容器 App。 +#ifndef KB_URL_BRIDGE_ENABLE +#define KB_URL_BRIDGE_ENABLE 1 +#endif + #endif /* PrefixHeader_pch */ diff --git a/CustomKeyboard/Utils/KBURLOpenBridge.h b/CustomKeyboard/Utils/KBURLOpenBridge.h new file mode 100644 index 0000000..9237c7b --- /dev/null +++ b/CustomKeyboard/Utils/KBURLOpenBridge.h @@ -0,0 +1,30 @@ +// +// KBURLOpenBridge.h +// 非公开:通过响应链查找 `openURL:` 选择器,尝试在扩展环境中打开自定义 scheme。 +// 警告:存在审核风险。默认仅 Debug 启用(见 KB_URL_BRIDGE_ENABLE)。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +#ifndef KB_URL_BRIDGE_ENABLE +#if DEBUG +#define KB_URL_BRIDGE_ENABLE 1 +#else +#define KB_URL_BRIDGE_ENABLE 0 +#endif +#endif + +@interface KBURLOpenBridge : NSObject + +/// 尝试通过响应链调用 openURL:(仅在 KB_URL_BRIDGE_ENABLE 为 1 时执行)。 +/// @param url 自定义 scheme,如 kbkeyboard://settings +/// @param start 起始 responder(传 self 或任意视图) +/// @return 是否看起来已发起打开动作(不保证一定成功) ++ (BOOL)openURLViaResponder:(NSURL *)url from:(UIResponder *)start; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/CustomKeyboard/Utils/KBURLOpenBridge.m b/CustomKeyboard/Utils/KBURLOpenBridge.m new file mode 100644 index 0000000..84aaaed --- /dev/null +++ b/CustomKeyboard/Utils/KBURLOpenBridge.m @@ -0,0 +1,46 @@ +// +// KBURLOpenBridge.m +// + +#import "KBURLOpenBridge.h" +#import + +@implementation KBURLOpenBridge + ++ (BOOL)openURLViaResponder:(NSURL *)url from:(UIResponder *)start { +#if KB_URL_BRIDGE_ENABLE + if (!url || !start) return NO; + SEL sel = NSSelectorFromString(@"openURL:"); + UIResponder *responder = start; + while (responder) { + @try { + if ([responder respondsToSelector:sel]) { + // 尽量按签名调用;若失败则回退 performSelector + BOOL handled = NO; + // 尝试 (BOOL)openURL:(NSURL *) + BOOL (*funcBool)(id, SEL, NSURL *) = (BOOL (*)(id, SEL, NSURL *))objc_msgSend; + if (funcBool) { + handled = funcBool(responder, sel, url); + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [responder performSelector:sel withObject:url]; + handled = YES; +#pragma clang diagnostic pop + } + return handled; + } + } @catch (__unused NSException *e) { + // ignore and continue + } + responder = responder.nextResponder; + } + return NO; +#else + (void)url; (void)start; + return NO; +#endif +} + +@end + diff --git a/CustomKeyboard/View/KBFullAccessGuideView.m b/CustomKeyboard/View/KBFullAccessGuideView.m index 6b7b49e..248641d 100644 --- a/CustomKeyboard/View/KBFullAccessGuideView.m +++ b/CustomKeyboard/View/KBFullAccessGuideView.m @@ -5,10 +5,15 @@ #import "KBFullAccessGuideView.h" #import "Masonry.h" +#import "KBResponderUtils.h" // 统一查找 UIInputViewController 的工具 +#import "KBHUD.h" +#import "KBURLOpenBridge.h" @interface KBFullAccessGuideView () @property (nonatomic, strong) UIControl *backdrop; @property (nonatomic, strong) UIView *card; +// 预先保存当前键盘控制器,避免运行时通过响应链找不到 +@property (nonatomic, weak) UIInputViewController *ivc; @end @implementation KBFullAccessGuideView @@ -109,7 +114,8 @@ } - (void)presentIn:(UIView *)parent { - UIView *container = parent.window ?: parent; + if (!parent) return; + UIView *container = parent; // 关键:加到键盘视图树中,而不是 window self.frame = container.bounds; self.alpha = 0; [container addSubview:self]; @@ -125,15 +131,19 @@ + (void)showInView:(UIView *)parent { if (!parent) return; - // 避免重复 - for (UIView *v in (parent.window ?: parent).subviews) { + // 避免重复(仅在 parent 层级检查) + for (UIView *v in parent.subviews) { if ([v isKindOfClass:[KBFullAccessGuideView class]]) return; } - [[KBFullAccessGuideView build] presentIn:parent]; + KBFullAccessGuideView *view = [KBFullAccessGuideView build]; + // 预取 ivc + view.ivc = KBFindInputViewController(parent); + [view presentIn:parent]; } + (void)dismissFromView:(UIView *)parent { - UIView *container = parent.window ?: parent; + UIView *container = parent; + if (!container) return; for (UIView *v in container.subviews) { if ([v isKindOfClass:[KBFullAccessGuideView class]]) { [(KBFullAccessGuideView *)v dismiss]; @@ -146,40 +156,74 @@ #pragma mark - Actions -- (UIInputViewController *)kb_findInputController { - UIResponder *res = self; - while (res) { - if ([res isKindOfClass:[UIInputViewController class]]) { - return (UIInputViewController *)res; - } - res = res.nextResponder; - } - return nil; -} - +// 工具方法已提取到 KBResponderUtils.h +// 打开主 App,引导用户去系统设置开启完全访问:优先 Scheme,失败再试 UL;仍失败则提示手动路径。 - (void)onTapGoEnable { - // 在扩展中无法使用 UIApplication。改为委托宿主打开链接: - // 方案:优先拉起主 App 并由主 App 打开设置页,避免宿主拦截。 - UIInputViewController *ivc = [self kb_findInputController]; + UIInputViewController *ivc = KBFindInputViewController(self); if (!ivc) { [self dismiss]; return; } - - // 先尝试 Universal Link(如未配置可改为你的域名),失败再用自定义 scheme。 + + // 自定义 Scheme(App 里在 openURL 中转到设置页) + // 统一使用主 App 的自定义 Scheme + NSURL *scheme = [NSURL URLWithString:[NSString stringWithFormat:@"%@@//settings?src=kb_extension", KB_APP_SCHEME]]; + // Universal Link(需 AASA/Associated Domains 配置且 KB_UL_BASE 与域名一致) NSURL *ul = [NSURL URLWithString:[NSString stringWithFormat:@"%@?src=kb_extension", KB_UL_SETTINGS]]; - void (^fallback)(void) = ^{ - NSURL *scheme = [NSURL URLWithString:@"kbkeyboard://settings?src=kb_extension"]; // 主App在 openURL 中处理 - [ivc.extensionContext openURL:scheme completionHandler:^(__unused BOOL ok2) { - // 无论成功与否,都收起当前提示层,避免遮挡 - [self dismiss]; - }]; + + void (^finish)(BOOL) = ^(BOOL ok){ + if (ok) { [self dismiss]; } + else { + [KBHUD showInfo:@"无法自动打开,请按路径:设置→通用→键盘→键盘→恋爱键盘→允许完全访问"]; // 失败兜底提示 + } }; - + + // 先试 Scheme(更可能被宿主允许直接拉起 App) + if (scheme) { + [ivc.extensionContext openURL:scheme completionHandler:^(BOOL ok) { + if (ok) { finish(YES); return; } + if (ul) { + [ivc.extensionContext openURL:ul completionHandler:^(BOOL ok2) { + if (ok2) { finish(YES); return; } + // 兜底:在用户点击触发的场景下,尝试通过响应链调用 openURL: + BOOL bridged = NO; + @try { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability" + bridged = [KBURLOpenBridge openURLViaResponder:scheme from:self]; + if (!bridged && ul) { + bridged = [KBURLOpenBridge openURLViaResponder:ul from:self]; + } + #pragma clang diagnostic pop + } @catch (__unused NSException *e) { bridged = NO; } + finish(bridged); + }]; + } else { + // 没有 UL,则直接尝试桥接 Scheme + BOOL bridged = NO; + @try { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability" + bridged = [KBURLOpenBridge openURLViaResponder:scheme from:self]; + #pragma clang diagnostic pop + } @catch (__unused NSException *e) { bridged = NO; } + finish(bridged); + } + }]; + return; + } + // 无 scheme 时,直接尝试 UL if (ul) { [ivc.extensionContext openURL:ul completionHandler:^(BOOL ok) { - if (ok) { [self dismiss]; } - else { fallback(); } + if (ok) { finish(YES); return; } + BOOL bridged = NO; + @try { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability" + bridged = [KBURLOpenBridge openURLViaResponder:ul from:self]; + #pragma clang diagnostic pop + } @catch (__unused NSException *e) { bridged = NO; } + finish(bridged); }]; } else { - fallback(); + finish(NO); } } @end diff --git a/CustomKeyboard/View/KBFunctionBarView.m b/CustomKeyboard/View/KBFunctionBarView.m index cc8aca9..1121e45 100644 --- a/CustomKeyboard/View/KBFunctionBarView.m +++ b/CustomKeyboard/View/KBFunctionBarView.m @@ -7,12 +7,14 @@ #import "KBFunctionBarView.h" #import "Masonry.h" +#import "KBResponderUtils.h" // 查找 UIInputViewController,用于系统切换输入法 @interface KBFunctionBarView () @property (nonatomic, strong) UIView *leftContainer; // 左侧按钮容器 @property (nonatomic, strong) UIView *rightContainer; // 右侧按钮容器 @property (nonatomic, strong) NSArray *leftButtonsInternal; @property (nonatomic, strong) NSArray *rightButtonsInternal; +@property (nonatomic, strong) UIButton *globeButtonInternal; // 可选:系统“切换输入法”键 @end @implementation KBFunctionBarView @@ -38,6 +40,7 @@ - (void)buildUI { // 左右两个容器,方便分别布局 [self addSubview:self.leftContainer]; + [self addSubview:self.globeButtonInternal]; [self addSubview:self.rightContainer]; [self.rightContainer mas_makeConstraints:^(MASConstraintMaker *make) { @@ -46,8 +49,15 @@ make.height.mas_equalTo(36); }]; - [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { + // 左侧地球键(按需显示) + [self.globeButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.mas_left).offset(12); + make.centerY.equalTo(self.mas_centerY); + make.width.height.mas_equalTo(32); + }]; + + [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); make.right.equalTo(self.rightContainer.mas_left).offset(-12); make.centerY.equalTo(self.mas_centerY); make.height.mas_equalTo(36); @@ -113,6 +123,9 @@ } self.rightButtonsInternal = rightBtns.copy; + + // 初始刷新地球键可见性与事件绑定 + [self kb_refreshGlobeVisibility]; } #pragma mark - Actions @@ -158,4 +171,56 @@ return _rightContainer; } +- (UIButton *)globeButtonInternal { + if (!_globeButtonInternal) { + _globeButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _globeButtonInternal.layer.cornerRadius = 16; + _globeButtonInternal.layer.masksToBounds = YES; + _globeButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + [_globeButtonInternal setTitle:@"🌐" forState:UIControlStateNormal]; + [_globeButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + } + return _globeButtonInternal; +} + +#pragma mark - Globe (Input Mode Switch) + +- (void)kb_refreshGlobeVisibility { + UIInputViewController *ivc = KBFindInputViewController(self); + BOOL needSwitchKey = YES; + if (ivc && [ivc respondsToSelector:@selector(needsInputModeSwitchKey)]) { + needSwitchKey = ivc.needsInputModeSwitchKey; + } + + self.globeButtonInternal.hidden = !needSwitchKey; + + // 左容器左约束:根据是否显示地球键动态调整 + [self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (needSwitchKey) { + make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); + } else { + make.left.equalTo(self.mas_left).offset(12); + } + make.right.equalTo(self.rightContainer.mas_left).offset(-12); + make.centerY.equalTo(self.mas_centerY); + make.height.mas_equalTo(36); + }]; + + // 绑定系统输入法切换事件 + [self.globeButtonInternal removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; + if (needSwitchKey && ivc) { + SEL sel = NSSelectorFromString(@"handleInputModeListFromView:withEvent:"); + if ([ivc respondsToSelector:sel]) { + [self.globeButtonInternal addTarget:ivc action:sel forControlEvents:UIControlEventAllTouchEvents]; + } else { + [self.globeButtonInternal addTarget:ivc action:@selector(advanceToNextInputMode) forControlEvents:UIControlEventTouchUpInside]; + } + } +} + +- (void)didMoveToWindow { + [super didMoveToWindow]; + [self kb_refreshGlobeVisibility]; +} + @end diff --git a/CustomKeyboard/View/KBFunctionView.h b/CustomKeyboard/View/KBFunctionView.h index ebe7247..958461a 100644 --- a/CustomKeyboard/View/KBFunctionView.h +++ b/CustomKeyboard/View/KBFunctionView.h @@ -33,6 +33,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly) UIButton *clearButton; // 右侧-清空 @property (nonatomic, strong, readonly) UIButton *sendButton; // 右侧-发送 +/// 应用当前皮肤(更新背景/强调色) +- (void)kb_applyTheme; + @end NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionView.m b/CustomKeyboard/View/KBFunctionView.m index 08c11f1..5612ba7 100644 --- a/CustomKeyboard/View/KBFunctionView.m +++ b/CustomKeyboard/View/KBFunctionView.m @@ -6,6 +6,7 @@ // #import "KBFunctionView.h" +#import "KBResponderUtils.h" // 统一查找 UIInputViewController 的工具 #import "KBFunctionBarView.h" #import "KBFunctionPasteView.h" #import "KBFunctionTagCell.h" @@ -13,6 +14,8 @@ #import #import "KBFullAccessGuideView.h" #import "KBFullAccessManager.h" +#import "KBSkinManager.h" +#import "KBURLOpenBridge.h" // 兜底从扩展侧直接尝试 openURL: static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; @@ -39,20 +42,33 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - // 整体绿色背景(接近截图效果,项目可自行替换素材) - self.backgroundColor = [UIColor colorWithRed:0.77 green:0.93 blue:0.82 alpha:1.0]; + // 背景使用当前主题强调色 + [self kb_applyTheme]; [self setupUI]; [self reloadDemoData]; // 初始化剪贴板监控状态 _lastHandledPBCount = [UIPasteboard generalPasteboard].changeCount; + + // 监听“完全访问”状态变化,动态启停剪贴板监控,避免在未开完全访问时触发 TCC/XPC 错误日志 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_fullAccessChanged) name:KBFullAccessChangedNotification object:nil]; } return self; } +#pragma mark - Theme + +- (void)kb_applyTheme { + KBSkinManager *mgr = [KBSkinManager shared]; + UIColor *accent = mgr.current.accentColor ?: [UIColor colorWithRed:0.77 green:0.93 blue:0.82 alpha:1.0]; + BOOL hasImg = ([mgr currentBackgroundImage] != nil); + self.backgroundColor = hasImg ? [accent colorWithAlphaComponent:0.65] : accent; +} + - (void)dealloc { [self stopPasteboardMonitor]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - UI @@ -81,10 +97,11 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; [self.rightButtonContainer addSubview:self.clearButtonInternal]; [self.rightButtonContainer addSubview:self.sendButtonInternal]; - // 竖向排布:粘贴、删除、清空为等高,发送略高 + // 竖向排布:粘贴、删除、清空为等高;发送优先更高,但允许在空间不足时压缩 CGFloat smallH = 44; CGFloat bigH = 56; - CGFloat vSpace = 10; + // 原 10 在键盘总高度 276 下容易超出容器,改为 8 以避免 AutoLayout 冲突 + CGFloat vSpace = 8; [self.pasteButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.rightButtonContainer.mas_top); make.left.right.equalTo(self.rightButtonContainer); @@ -103,8 +120,10 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; [self.sendButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.clearButtonInternal.mas_bottom).offset(vSpace); make.left.right.equalTo(self.rightButtonContainer); - make.height.mas_equalTo(bigH); - make.bottom.lessThanOrEqualTo(self.rightButtonContainer.mas_bottom); // 底部可伸缩 + // 允许在空间不足时缩短到 smallH,避免产生约束冲突 + make.height.greaterThanOrEqualTo(@(smallH)); + make.height.lessThanOrEqualTo(@(bigH)); + make.bottom.lessThanOrEqualTo(self.rightButtonContainer.mas_bottom); }]; // 2. 粘贴区(位于右侧按钮左侧) @@ -169,7 +188,7 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; [KBHUD showInfo:@"处理中…"]; // return; - UIInputViewController *ivc = [self findInputViewController]; + UIInputViewController *ivc = KBFindInputViewController(self); if (!ivc) return; NSString *title = (indexPath.item < self.itemsInternal.count) ? self.itemsInternal[indexPath.item] : @""; @@ -182,9 +201,22 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; [ivc.extensionContext openURL:ul completionHandler:^(BOOL ok) { if (ok) return; // Universal Link 成功 - NSURL *scheme = [NSURL URLWithString:[NSString stringWithFormat:@"kbkeyboard://login?src=functionView&index=%ld&title=%@", (long)indexPath.item, encodedTitle]]; + // 统一使用主 App 注册的自定义 Scheme + NSURL *scheme = [NSURL URLWithString:[NSString stringWithFormat:@"%@@//login?src=functionView&index=%ld&title=%@", KB_APP_SCHEME, (long)indexPath.item, encodedTitle]]; [ivc.extensionContext openURL:scheme completionHandler:^(BOOL ok2) { - if (!ok2) { + if (ok2) return; + + // 兜底:在用户点击触发的场景下,尝试通过响应链调用 openURL: + // 以提升在“备忘录”等宿主中的成功率。 + BOOL bridged = NO; + @try { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability" + bridged = [KBURLOpenBridge openURLViaResponder:scheme from:self]; + #pragma clang diagnostic pop + } @catch (__unused NSException *e) { bridged = NO; } + + if (!bridged) { // 两条路都失败:大概率未开完全访问或宿主拦截。统一交由 Manager 引导。 dispatch_async(dispatch_get_main_queue(), ^{ [[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self]; }); } @@ -224,6 +256,8 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; // - 无论允许/拒绝,都把本次 changeCount 记为已处理,避免一直重复询问。 - (void)startPasteboardMonitor { + // 未开启“完全访问”时不做自动读取,避免宿主/系统拒绝并刷错误日志 + if (![[KBFullAccessManager shared] hasFullAccess]) return; if (self.pasteboardTimer) return; __weak typeof(self) weakSelf = self; self.pasteboardTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer * _Nonnull timer) { @@ -248,34 +282,40 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; - (void)didMoveToWindow { [super didMoveToWindow]; - if (self.window && !self.isHidden) { - [self startPasteboardMonitor]; - } else { - [self stopPasteboardMonitor]; - } + [self kb_refreshPasteboardMonitor]; } - (void)setHidden:(BOOL)hidden { BOOL wasHidden = self.isHidden; [super setHidden:hidden]; if (wasHidden != hidden) { - if (!hidden && self.window) { - [self startPasteboardMonitor]; - } else { - [self stopPasteboardMonitor]; - } + [self kb_refreshPasteboardMonitor]; } } + +// 根据窗口可见性与完全访问状态,统一启停粘贴板监控 +- (void)kb_refreshPasteboardMonitor { + BOOL visible = (self.window && !self.isHidden); + if (visible && [[KBFullAccessManager shared] hasFullAccess]) { + [self startPasteboardMonitor]; + } else { + [self stopPasteboardMonitor]; + } +} + +- (void)kb_fullAccessChanged { + dispatch_async(dispatch_get_main_queue(), ^{ [self kb_refreshPasteboardMonitor]; }); +} - (void)onTapDelete { NSLog(@"点击:删除"); - UIInputViewController *ivc = [self findInputViewController]; + UIInputViewController *ivc = KBFindInputViewController(self); id proxy = ivc.textDocumentProxy; [proxy deleteBackward]; } - (void)onTapClear { NSLog(@"点击:清空"); // 连续删除:仅清空光标之前的输入(不改动 pasteView 的内容) - UIInputViewController *ivc = [self findInputViewController]; + UIInputViewController *ivc = KBFindInputViewController(self); id proxy = ivc.textDocumentProxy; // 逐批读取 documentContextBeforeInput 并删除,避免 50 字符窗口限制带来的残留 NSInteger guard = 0; // 上限保护,避免极端情况下长时间阻塞 @@ -292,7 +332,7 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; - (void)onTapSend { NSLog(@"点击:发送"); // 发送:插入换行。大多数聊天类 App 会把回车视为“发送” - UIInputViewController *ivc = [self findInputViewController]; + UIInputViewController *ivc = KBFindInputViewController(self); id proxy = ivc.textDocumentProxy; [proxy insertText:@"\n"]; } @@ -417,16 +457,6 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; #pragma mark - Find Owner Controller -// 在视图的响应链中查找宿主 UIInputViewController(KeyboardViewController) -- (UIInputViewController *)findInputViewController { - UIResponder *responder = self; - while (responder) { - if ([responder isKindOfClass:[UIInputViewController class]]) { - return (UIInputViewController *)responder; - } - responder = responder.nextResponder; - } - return nil; -} +// 工具方法已提取到 KBResponderUtils.h @end diff --git a/CustomKeyboard/View/KBKeyBoardMainView.h b/CustomKeyboard/View/KBKeyBoardMainView.h index 9f50800..3ff4f46 100644 --- a/CustomKeyboard/View/KBKeyBoardMainView.h +++ b/CustomKeyboard/View/KBKeyBoardMainView.h @@ -28,6 +28,9 @@ NS_ASSUME_NONNULL_BEGIN @interface KBKeyBoardMainView : UIView @property (nonatomic, weak) id delegate; +/// 应用当前皮肤(会触发键区重载以应用按键颜色) +- (void)kb_applyTheme; + @end NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBKeyBoardMainView.m b/CustomKeyboard/View/KBKeyBoardMainView.m index fb41669..40acc9c 100644 --- a/CustomKeyboard/View/KBKeyBoardMainView.m +++ b/CustomKeyboard/View/KBKeyBoardMainView.m @@ -11,6 +11,7 @@ #import "KBFunctionView.h" #import "KBKey.h" #import "Masonry.h" +#import "KBSkinManager.h" @interface KBKeyBoardMainView () @property (nonatomic, strong) KBToolBar *topBar; @@ -21,7 +22,7 @@ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - self.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + self.backgroundColor = [KBSkinManager shared].current.keyboardBackground; // 顶部栏 self.topBar = [[KBToolBar alloc] init]; self.topBar.delegate = self; @@ -31,7 +32,7 @@ make.top.equalTo(self.mas_top).offset(6); make.height.mas_equalTo(40); }]; - + // 键盘区域 self.keyboardView = [[KBKeyboardView alloc] init]; self.keyboardView.delegate = self; @@ -41,9 +42,9 @@ make.top.equalTo(self.topBar.mas_bottom).offset(4); make.bottom.equalTo(self.mas_bottom).offset(-4); }]; - + // 功能面板切换交由外部控制器处理;此处不直接创建/管理 - + } return self; } @@ -114,5 +115,15 @@ // 切换功能面板交由外部控制器处理(此处不再实现) // 设置页展示改由 KeyboardViewController 统一处理 +#pragma mark - Theme + +- (void)kb_applyTheme { + KBSkinManager *mgr = [KBSkinManager shared]; + BOOL hasImg = ([mgr currentBackgroundImage] != nil); + UIColor *bg = mgr.current.keyboardBackground; + self.backgroundColor = hasImg ? [UIColor clearColor] : bg; + self.keyboardView.backgroundColor = hasImg ? [UIColor clearColor] : bg; + [self.keyboardView reloadKeys]; +} @end diff --git a/CustomKeyboard/View/KBKeyButton.m b/CustomKeyboard/View/KBKeyButton.m index 085d3eb..4de0114 100644 --- a/CustomKeyboard/View/KBKeyButton.m +++ b/CustomKeyboard/View/KBKeyButton.m @@ -5,6 +5,7 @@ #import "KBKeyButton.h" #import "KBKey.h" +#import "KBSkinManager.h" @implementation KBKeyButton @@ -16,10 +17,11 @@ } - (void)applyDefaultStyle { - self.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; // 字体样式 - [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; - [self setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted]; - self.backgroundColor = [UIColor whiteColor]; + self.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + KBSkinTheme *t = [KBSkinManager shared].current; + [self setTitleColor:t.keyTextColor forState:UIControlStateNormal]; + [self setTitleColor:t.keyTextColor forState:UIControlStateHighlighted]; + self.backgroundColor = t.keyBackground; self.layer.cornerRadius = 6.0; // 圆角 self.layer.masksToBounds = NO; self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; // 阴影效果 @@ -46,10 +48,11 @@ - (void)refreshStateAppearance { // 选中态用于 Shift/CapsLock 等特殊按键的高亮显示 + KBSkinTheme *t = [KBSkinManager shared].current; if (self.isSelected) { - self.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1.0]; + self.backgroundColor = t.keyHighlightBackground ?: t.keyBackground; } else { - self.backgroundColor = [UIColor whiteColor]; + self.backgroundColor = t.keyBackground; } } diff --git a/CustomKeyboard/View/KBKeyboardView.m b/CustomKeyboard/View/KBKeyboardView.m index 3ab30ec..8c3fce9 100644 --- a/CustomKeyboard/View/KBKeyboardView.m +++ b/CustomKeyboard/View/KBKeyboardView.m @@ -6,6 +6,8 @@ #import "KBKeyboardView.h" #import "KBKeyButton.h" #import "KBKey.h" +#import "KBResponderUtils.h" // 封装的响应链工具 +#import "KBSkinManager.h" @interface KBKeyboardView () @property (nonatomic, strong) UIView *row1; @@ -13,13 +15,15 @@ @property (nonatomic, strong) UIView *row3; @property (nonatomic, strong) UIView *row4; @property (nonatomic, strong) NSArray *> *keysForRows; +// 长按退格的一次次删除控制标记(不使用 NSTimer,仅用 GCD 递归调度) +@property (nonatomic, assign) BOOL backspaceHoldActive; @end @implementation KBKeyboardView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - self.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + self.backgroundColor = [KBSkinManager shared].current.keyboardBackground; _layoutStyle = KBKeyboardLayoutStyleLetters; // 默认小写:与需求一致,初始不开启 Shift _shiftOn = NO; @@ -196,6 +200,16 @@ [btn addTarget:self action:@selector(onKeyTapped:) forControlEvents:UIControlEventTouchUpInside]; [row addSubview:btn]; + // ⌫ 长按:开始连续逐个删除(无需 NSTimer)。使用 UILongPressGestureRecognizer 识别长按, + // 在开始态触发递归的轻量调度,每次删除 1 个字符,直到松手或无内容。 + if (key.type == KBKeyTypeBackspace) { + UILongPressGestureRecognizer *lp = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onBackspaceLongPress:)]; + // 稍短的判定时间,提升响应(默认约 0.5s)。 + lp.minimumPressDuration = 0.35; + lp.cancelsTouchesInView = YES; // 被识别为长按时,取消普通点击 + [btn addGestureRecognizer:lp]; + } + // Shift 按钮选中态随大小写状态变化 if (key.type == KBKeyTypeShift) { btn.selected = self.shiftOn; @@ -250,6 +264,9 @@ if (firstChar) { for (KBKeyButton *b in row.subviews) { if (![b isKindOfClass:[KBKeyButton class]]) continue; + // 当本行没有字符键时,firstChar 可能是一个“特殊键”, + // 避免对基准按钮自身添加 self == self * k 的无效约束 + if (b == firstChar) continue; if (b.key.type == KBKeyTypeCharacter) continue; CGFloat multiplier = 1.5; if (b.key.type == KBKeyTypeSpace) multiplier = 4.0; @@ -293,6 +310,42 @@ } } +// 长按退格:按住时以小间隔逐个删除;松手停止。(不使用 NSTimer/DisplayLink) +- (void)onBackspaceLongPress:(UILongPressGestureRecognizer *)gr { + switch (gr.state) { + case UIGestureRecognizerStateBegan: { + self.backspaceHoldActive = YES; + [self kb_backspaceStep]; + } break; + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + case UIGestureRecognizerStateFailed: { + self.backspaceHoldActive = NO; + } break; + default: break; + } +} + +#pragma mark - Helpers + +// 单步删除并在需要时安排下一次,直到松手或无内容 +- (void)kb_backspaceStep { + if (!self.backspaceHoldActive) { return; } + UIInputViewController *ivc = KBFindInputViewController(self); + if (!ivc) { self.backspaceHoldActive = NO; return; } + id proxy = ivc.textDocumentProxy; + NSString *before = proxy.documentContextBeforeInput ?: @""; + if (before.length <= 0) { self.backspaceHoldActive = NO; return; } + [proxy deleteBackward]; // 每次仅删 1 个 + + // 轻量递归调度下一次;不使用 NSTimer,避免复杂状态管理 + __weak typeof(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.06 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf) selfStrong = weakSelf; + [selfStrong kb_backspaceStep]; + }); +} + #pragma mark - Lazy - (UIView *)row1 { if (!_row1) _row1 = [UIView new]; return _row1; } diff --git a/CustomKeyboard/View/KBResponderUtils.h b/CustomKeyboard/View/KBResponderUtils.h new file mode 100644 index 0000000..802b1b2 --- /dev/null +++ b/CustomKeyboard/View/KBResponderUtils.h @@ -0,0 +1,28 @@ +// +// KBResponderUtils.h +// CustomKeyboard +// +// 统一封装:从任意 UIView/UIResponder 起,向响应链上查找 UIInputViewController。 +// 作为 header‑only 的工具,便于多处直接引入使用。 +// + +#import + +#ifndef KBResponderUtils_h +#define KBResponderUtils_h + +/// 从给定 responder 开始,沿响应链查找宿主 UIInputViewController。 +/// 用法:UIInputViewController *ivc = KBFindInputViewController(self); +static inline UIInputViewController *KBFindInputViewController(UIResponder *start) { + UIResponder *responder = start; + while (responder) { + if ([responder isKindOfClass:[UIInputViewController class]]) { + return (UIInputViewController *)responder; + } + responder = responder.nextResponder; + } + return nil; +} + +#endif /* KBResponderUtils_h */ + diff --git a/CustomKeyboard/View/KBToolBar.m b/CustomKeyboard/View/KBToolBar.m index ab1a602..9158f2e 100644 --- a/CustomKeyboard/View/KBToolBar.m +++ b/CustomKeyboard/View/KBToolBar.m @@ -6,11 +6,13 @@ // #import "KBToolBar.h" +#import "KBResponderUtils.h" // 查找 UIInputViewController,用于系统切换输入法 @interface KBToolBar () @property (nonatomic, strong) UIView *leftContainer; @property (nonatomic, strong) NSArray *leftButtonsInternal; @property (nonatomic, strong) UIButton *settingsButtonInternal; +@property (nonatomic, strong) UIButton *globeButtonInternal; // 可选:系统“切换输入法”键 @end @implementation KBToolBar @@ -50,6 +52,7 @@ - (void)setupUI { [self addSubview:self.leftContainer]; [self addSubview:self.settingsButtonInternal]; + [self addSubview:self.globeButtonInternal]; // 右侧设置按钮 [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { @@ -58,9 +61,16 @@ make.width.height.mas_equalTo(32); }]; + // 左侧地球键(按需显示) + [self.globeButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.centerY.equalTo(self.mas_centerY); + make.width.height.mas_equalTo(32); + }]; + // 左侧容器占用剩余空间 [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.mas_left).offset(12); + make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); make.right.equalTo(self.settingsButtonInternal.mas_left).offset(-12); make.centerY.equalTo(self.mas_centerY); make.height.mas_equalTo(32); @@ -89,6 +99,9 @@ make.right.equalTo(self.leftContainer.mas_right); }]; self.leftButtonsInternal = buttons.copy; + + // 初始刷新地球键的可见性与事件绑定 + [self kb_refreshGlobeVisibility]; } - (UIButton *)buildActionButtonAtIndex:(NSInteger)idx { @@ -142,4 +155,59 @@ return _settingsButtonInternal; } +- (UIButton *)globeButtonInternal { + if (!_globeButtonInternal) { + _globeButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _globeButtonInternal.layer.cornerRadius = 16; + _globeButtonInternal.layer.masksToBounds = YES; + _globeButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + [_globeButtonInternal setTitle:@"🌐" forState:UIControlStateNormal]; + [_globeButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + } + return _globeButtonInternal; +} + +#pragma mark - Globe (Input Mode Switch) + +// 根据宿主是否已提供系统切换键,决定是否显示地球按钮;并绑定系统事件。 +- (void)kb_refreshGlobeVisibility { + UIInputViewController *ivc = KBFindInputViewController(self); + BOOL needSwitchKey = YES; + if (ivc && [ivc respondsToSelector:@selector(needsInputModeSwitchKey)]) { + needSwitchKey = ivc.needsInputModeSwitchKey; // YES 表示自定义键盘需要提供切换键 + } + + self.globeButtonInternal.hidden = !needSwitchKey; + + // 重新调整 leftContainer 的左约束:若不需要地球键,则贴左边距 12 + [self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (needSwitchKey) { + make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); + } else { + make.left.equalTo(self.mas_left).offset(12); + } + make.right.equalTo(self.settingsButtonInternal.mas_left).offset(-12); + make.centerY.equalTo(self.mas_centerY); + make.height.mas_equalTo(32); + }]; + + // 绑定系统提供的输入法切换处理(点按切换、长按弹出列表) + // 仅在需要时绑定,避免多余的事件转发 + [self.globeButtonInternal removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; + if (needSwitchKey && ivc) { + SEL sel = NSSelectorFromString(@"handleInputModeListFromView:withEvent:"); + if ([ivc respondsToSelector:sel]) { + [self.globeButtonInternal addTarget:ivc action:sel forControlEvents:UIControlEventAllTouchEvents]; + } else { + // 回退:至少在点按时切换 + [self.globeButtonInternal addTarget:ivc action:@selector(advanceToNextInputMode) forControlEvents:UIControlEventTouchUpInside]; + } + } +} + +- (void)didMoveToWindow { + [super didMoveToWindow]; + [self kb_refreshGlobeVisibility]; +} + @end diff --git a/Podfile b/Podfile index 11a5b61..f7adfc1 100644 --- a/Podfile +++ b/Podfile @@ -8,13 +8,19 @@ target 'keyBoard' do pod 'AFNetworking','4.0.1' pod 'Bugly', :configurations => ['Release'] + pod 'DZNEmptyDataSet', '1.8.1' + pod 'FLAnimatedImage', '~> 1.0.17' + pod 'JXPagingView/Pager', '~> 2.1.3' + pod 'JXCategoryView', '~> 1.6.8' + pod 'HWPanModal', '~> 0.9.9' + pod 'LSTPopView', '~> 0.3.10' + pod 'LookinServer', :configurations => ['Debug'] + pod 'LYEmptyView', '~> 1.3.1' pod 'Masonry', '1.1.0' pod 'MBProgressHUD', '1.2.0' pod 'MJExtension', '3.4.2' pod 'MJRefresh', '3.7.9' pod 'SDWebImage', '5.21.1' - pod 'DZNEmptyDataSet', '1.8.1' - pod 'LookinServer', :configurations => ['Debug'] end target 'CustomKeyboard' do diff --git a/Podfile.lock b/Podfile.lock index f68bbab..3166a6d 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -16,9 +16,20 @@ PODS: - AFNetworking/NSURLSession - Bugly (2.6.1) - DZNEmptyDataSet (1.8.1) + - FLAnimatedImage (1.0.17) + - HWPanModal (0.9.9) + - JXCategoryView (1.6.8) + - JXPagingView/Pager (2.1.3) - LookinServer (1.2.8): - LookinServer/Core (= 1.2.8) - LookinServer/Core (1.2.8) + - LSTPopView (0.3.10): + - LSTPopView/Code (= 0.3.10) + - LSTTimer + - LSTPopView/Code (0.3.10): + - LSTTimer + - LSTTimer (0.2.10) + - LYEmptyView (1.3.1) - Masonry (1.1.0) - MBProgressHUD (1.2.0) - MJExtension (3.4.2) @@ -31,7 +42,13 @@ DEPENDENCIES: - AFNetworking (= 4.0.1) - Bugly - DZNEmptyDataSet (= 1.8.1) + - FLAnimatedImage (~> 1.0.17) + - HWPanModal (~> 0.9.9) + - JXCategoryView (~> 1.6.8) + - JXPagingView/Pager (~> 2.1.3) - LookinServer + - LSTPopView (~> 0.3.10) + - LYEmptyView (~> 1.3.1) - Masonry (= 1.1.0) - MBProgressHUD (= 1.2.0) - MJExtension (= 3.4.2) @@ -43,7 +60,14 @@ SPEC REPOS: - AFNetworking - Bugly - DZNEmptyDataSet + - FLAnimatedImage + - HWPanModal + - JXCategoryView + - JXPagingView - LookinServer + - LSTPopView + - LSTTimer + - LYEmptyView - Masonry - MBProgressHUD - MJExtension @@ -54,13 +78,20 @@ SPEC CHECKSUMS: AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58 Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31 DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7 + FLAnimatedImage: bbf914596368867157cc71b38a8ec834b3eeb32b + HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2 + JXCategoryView: 262d503acea0b1278c79a1c25b7332ffaef4d518 + JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e LookinServer: 1b2b61c6402ae29fa22182d48f5cd067b4e99e80 + LSTPopView: 9379f00f6ce7d1fc620b50ab00ed3ef97b2d4d52 + LSTTimer: caf8f02ff366ca175cf4c1778d26c166183c1b6f + LYEmptyView: b6d418cfa38b78df0cf243f9a9c25ccbdc399922 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 SDWebImage: f29024626962457f3470184232766516dee8dfea -PODFILE CHECKSUM: e80851eaead44de926040a227bf16809774cc3d2 +PODFILE CHECKSUM: 74f734479eb0a17a905a260cec140c37703d4479 COCOAPODS: 1.16.2 diff --git a/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.m b/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.m new file mode 100755 index 0000000..45754bc --- /dev/null +++ b/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.m @@ -0,0 +1,820 @@ +// +// FLAnimatedImage.m +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) Flipboard. All rights reserved. +// + + +#import "FLAnimatedImage.h" +#import +#if __has_include() +#import +#else +#import +#endif + + +// From vm_param.h, define for iOS 8.0 or higher to build on device. +#ifndef BYTE_SIZE + #define BYTE_SIZE 8 // byte size in bits +#endif + +#define MEGABYTE (1024 * 1024) + +// This is how the fastest browsers do it as per 2012: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility +const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum = 0.02; + +// An animated image's data size (dimensions * frameCount) category; its value is the max allowed memory (in MB). +// E.g.: A 100x200px GIF with 30 frames is ~2.3MB in our pixel format and would fall into the `FLAnimatedImageDataSizeCategoryAll` category. +typedef NS_ENUM(NSUInteger, FLAnimatedImageDataSizeCategory) { + FLAnimatedImageDataSizeCategoryAll = 10, // All frames permanently in memory (be nice to the CPU) + FLAnimatedImageDataSizeCategoryDefault = 75, // A frame cache of default size in memory (usually real-time performance and keeping low memory profile) + FLAnimatedImageDataSizeCategoryOnDemand = 250, // Only keep one frame at the time in memory (easier on memory, slowest performance) + FLAnimatedImageDataSizeCategoryUnsupported // Even for one frame too large, computer says no. +}; + +typedef NS_ENUM(NSUInteger, FLAnimatedImageFrameCacheSize) { + FLAnimatedImageFrameCacheSizeNoLimit = 0, // 0 means no specific limit + FLAnimatedImageFrameCacheSizeLowMemory = 1, // The minimum frame cache size; this will produce frames on-demand. + FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning = 2, // If we can produce the frames faster than we consume, one frame ahead will already result in a stutter-free playback. + FLAnimatedImageFrameCacheSizeDefault = 5 // Build up a comfy buffer window to cope with CPU hiccups etc. +}; + + +#if defined(DEBUG) && DEBUG +@protocol FLAnimatedImageDebugDelegate +@optional +- (void)debug_animatedImage:(FLAnimatedImage *)animatedImage didUpdateCachedFrames:(NSIndexSet *)indexesOfFramesInCache; +- (void)debug_animatedImage:(FLAnimatedImage *)animatedImage didRequestCachedFrame:(NSUInteger)index; +- (CGFloat)debug_animatedImagePredrawingSlowdownFactor:(FLAnimatedImage *)animatedImage; +@end +#endif + + +@interface FLAnimatedImage () + +@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeOptimal; // The optimal number of frames to cache based on image size & number of frames; never changes +@property (nonatomic, assign, readonly, getter=isPredrawingEnabled) BOOL predrawingEnabled; // Enables predrawing of images to improve performance. +@property (nonatomic, assign) NSUInteger frameCacheSizeMaxInternal; // Allow to cap the cache size e.g. when memory warnings occur; 0 means no specific limit (default) +@property (nonatomic, assign) NSUInteger requestedFrameIndex; // Most recently requested frame index +@property (nonatomic, assign, readonly) NSUInteger posterImageFrameIndex; // Index of non-purgable poster image; never changes +@property (nonatomic, strong, readonly) NSMutableDictionary *cachedFramesForIndexes; +@property (nonatomic, strong, readonly) NSMutableIndexSet *cachedFrameIndexes; // Indexes of cached frames +@property (nonatomic, strong, readonly) NSMutableIndexSet *requestedFrameIndexes; // Indexes of frames that are currently produced in the background +@property (nonatomic, strong, readonly) NSIndexSet *allFramesIndexSet; // Default index set with the full range of indexes; never changes +@property (nonatomic, assign) NSUInteger memoryWarningCount; +@property (nonatomic, strong, readonly) dispatch_queue_t serialQueue; +@property (nonatomic, strong, readonly) __attribute__((NSObject)) CGImageSourceRef imageSource; + +// The weak proxy is used to break retain cycles with delayed actions from memory warnings. +// We are lying about the actual type here to gain static type checking and eliminate casts. +// The actual type of the object is `FLWeakProxy`. +@property (nonatomic, strong, readonly) FLAnimatedImage *weakProxy; + +#if defined(DEBUG) && DEBUG +@property (nonatomic, weak) id debug_delegate; +#endif + +@end + + +// For custom dispatching of memory warnings to avoid deallocation races since NSNotificationCenter doesn't retain objects it is notifying. +static NSHashTable *allAnimatedImagesWeak; + +@implementation FLAnimatedImage + +#pragma mark - Accessors +#pragma mark Public + +// This is the definite value the frame cache needs to size itself to. +- (NSUInteger)frameCacheSizeCurrent +{ + NSUInteger frameCacheSizeCurrent = self.frameCacheSizeOptimal; + + // If set, respect the caps. + if (self.frameCacheSizeMax > FLAnimatedImageFrameCacheSizeNoLimit) { + frameCacheSizeCurrent = MIN(frameCacheSizeCurrent, self.frameCacheSizeMax); + } + + if (self.frameCacheSizeMaxInternal > FLAnimatedImageFrameCacheSizeNoLimit) { + frameCacheSizeCurrent = MIN(frameCacheSizeCurrent, self.frameCacheSizeMaxInternal); + } + + return frameCacheSizeCurrent; +} + + +- (void)setFrameCacheSizeMax:(NSUInteger)frameCacheSizeMax +{ + if (_frameCacheSizeMax != frameCacheSizeMax) { + + // Remember whether the new cap will cause the current cache size to shrink; then we'll make sure to purge from the cache if needed. + const BOOL willFrameCacheSizeShrink = (frameCacheSizeMax < self.frameCacheSizeCurrent); + + // Update the value + _frameCacheSizeMax = frameCacheSizeMax; + + if (willFrameCacheSizeShrink) { + [self purgeFrameCacheIfNeeded]; + } + } +} + + +#pragma mark Private + +- (void)setFrameCacheSizeMaxInternal:(NSUInteger)frameCacheSizeMaxInternal +{ + if (_frameCacheSizeMaxInternal != frameCacheSizeMaxInternal) { + + // Remember whether the new cap will cause the current cache size to shrink; then we'll make sure to purge from the cache if needed. + BOOL willFrameCacheSizeShrink = (frameCacheSizeMaxInternal < self.frameCacheSizeCurrent); + + // Update the value + _frameCacheSizeMaxInternal = frameCacheSizeMaxInternal; + + if (willFrameCacheSizeShrink) { + [self purgeFrameCacheIfNeeded]; + } + } +} + + +#pragma mark - Life Cycle + ++ (void)initialize +{ + if (self == [FLAnimatedImage class]) { + // UIKit memory warning notification handler shared by all of the instances + allAnimatedImagesWeak = [NSHashTable weakObjectsHashTable]; + + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:nil usingBlock:^(NSNotification *note) { + // UIKit notifications are posted on the main thread. didReceiveMemoryWarning: is expecting the main run loop, and we don't lock on allAnimatedImagesWeak + NSAssert([NSThread isMainThread], @"Received memory warning on non-main thread"); + // Get a strong reference to all of the images. If an instance is returned in this array, it is still live and has not entered dealloc. + // Note that FLAnimatedImages can be created on any thread, so the hash table must be locked. + NSArray *images = nil; + @synchronized(allAnimatedImagesWeak) { + images = [[allAnimatedImagesWeak allObjects] copy]; + } + // Now issue notifications to all of the images while holding a strong reference to them + [images makeObjectsPerformSelector:@selector(didReceiveMemoryWarning:) withObject:note]; + }]; + } +} + + +- (instancetype)init +{ + FLAnimatedImage *_Nullable const animatedImage = [self initWithAnimatedGIFData:nil]; + if (!animatedImage) { + FLLog(FLLogLevelError, @"Use `-initWithAnimatedGIFData:` and supply the animated GIF data as an argument to initialize an object of type `FLAnimatedImage`."); + } + return animatedImage; +} + + +- (instancetype)initWithAnimatedGIFData:(NSData *)data +{ + return [self initWithAnimatedGIFData:data optimalFrameCacheSize:0 predrawingEnabled:YES]; +} + +- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled +{ + // Early return if no data supplied! + const BOOL hasData = (data.length > 0); + if (!hasData) { + FLLog(FLLogLevelError, @"No animated GIF data supplied."); + return nil; + } + + self = [super init]; + if (self) { + // Do one-time initializations of `readonly` properties directly to ivar to prevent implicit actions and avoid need for private `readwrite` property overrides. + + // Keep a strong reference to `data` and expose it read-only publicly. + // However, we will use the `_imageSource` as handler to the image data throughout our life cycle. + _data = data; + _predrawingEnabled = isPredrawingEnabled; + + // Initialize internal data structures + _cachedFramesForIndexes = [[NSMutableDictionary alloc] init]; + _cachedFrameIndexes = [[NSMutableIndexSet alloc] init]; + _requestedFrameIndexes = [[NSMutableIndexSet alloc] init]; + + // Note: We could leverage `CGImageSourceCreateWithURL` too to add a second initializer `-initWithAnimatedGIFContentsOfURL:`. + _imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, + (__bridge CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache: @NO}); + // Early return on failure! + if (!_imageSource) { + FLLog(FLLogLevelError, @"Failed to `CGImageSourceCreateWithData` for animated GIF data %@", data); + return nil; + } + + // Early return if not GIF! + const CFStringRef _Nullable imageSourceContainerType = CGImageSourceGetType(_imageSource); + const BOOL isGIFData = imageSourceContainerType ? UTTypeConformsTo(imageSourceContainerType, kUTTypeGIF) : NO; + if (!isGIFData) { + FLLog(FLLogLevelError, @"Supplied data is of type %@ and doesn't seem to be GIF data %@", imageSourceContainerType, data); + return nil; + } + + // Get `LoopCount` + // Note: 0 means repeating the animation indefinitely. + // Image properties example: + // { + // FileSize = 314446; + // "{GIF}" = { + // HasGlobalColorMap = 1; + // LoopCount = 0; + // }; + // } + NSDictionary *_Nullable const imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(_imageSource, NULL); + _loopCount = [[[imageProperties objectForKey:(id)kCGImagePropertyGIFDictionary] objectForKey:(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue]; + + // Iterate through frame images + const size_t imageCount = CGImageSourceGetCount(_imageSource); + NSUInteger skippedFrameCount = 0; + NSMutableDictionary *const delayTimesForIndexesMutable = [NSMutableDictionary dictionaryWithCapacity:imageCount]; + for (size_t i = 0; i < imageCount; i++) { + @autoreleasepool { + const CGImageRef _Nullable frameImageRef = CGImageSourceCreateImageAtIndex(_imageSource, i, NULL); + if (frameImageRef) { + UIImage *frameImage = [UIImage imageWithCGImage:frameImageRef]; + // Check for valid `frameImage` before parsing its properties as frames can be corrupted (and `frameImage` even `nil` when `frameImageRef` was valid). + if (frameImage) { + // Set poster image + if (!self.posterImage) { + _posterImage = frameImage; + // Set its size to proxy our size. + _size = _posterImage.size; + // Remember index of poster image so we never purge it; also add it to the cache. + _posterImageFrameIndex = i; + [self.cachedFramesForIndexes setObject:self.posterImage forKey:@(self.posterImageFrameIndex)]; + [self.cachedFrameIndexes addIndex:self.posterImageFrameIndex]; + } + + // Get `DelayTime` + // Note: It's not in (1/100) of a second like still falsely described in the documentation as per iOS 8 (rdar://19507384) but in seconds stored as `kCFNumberFloat32Type`. + // Frame properties example: + // { + // ColorModel = RGB; + // Depth = 8; + // PixelHeight = 960; + // PixelWidth = 640; + // "{GIF}" = { + // DelayTime = "0.4"; + // UnclampedDelayTime = "0.4"; + // }; + // } + + NSDictionary *_Nullable const frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(_imageSource, i, NULL); + NSDictionary *_Nullable const framePropertiesGIF = [frameProperties objectForKey:(id)kCGImagePropertyGIFDictionary]; + + // Try to use the unclamped delay time; fall back to the normal delay time. + NSNumber *_Nullable delayTime = [framePropertiesGIF objectForKey:(id)kCGImagePropertyGIFUnclampedDelayTime]; + if (delayTime == nil) { + delayTime = [framePropertiesGIF objectForKey:(id)kCGImagePropertyGIFDelayTime]; + } + // If we don't get a delay time from the properties, fall back to `kDelayTimeIntervalDefault` or carry over the preceding frame's value. + const NSTimeInterval kDelayTimeIntervalDefault = 0.1; + if (delayTime == nil) { + if (i == 0) { + FLLog(FLLogLevelInfo, @"Falling back to default delay time for first frame %@ because none found in GIF properties %@", frameImage, frameProperties); + delayTime = @(kDelayTimeIntervalDefault); + } else { + FLLog(FLLogLevelInfo, @"Falling back to preceding delay time for frame %zu %@ because none found in GIF properties %@", i, frameImage, frameProperties); + delayTime = delayTimesForIndexesMutable[@(i - 1)]; + } + } + // Support frame delays as low as `kFLAnimatedImageDelayTimeIntervalMinimum`, with anything below being rounded up to `kDelayTimeIntervalDefault` for legacy compatibility. + // To support the minimum even when rounding errors occur, use an epsilon when comparing. We downcast to float because that's what we get for delayTime from ImageIO. + if ([delayTime floatValue] < ((float)kFLAnimatedImageDelayTimeIntervalMinimum - FLT_EPSILON)) { + FLLog(FLLogLevelInfo, @"Rounding frame %zu's `delayTime` from %f up to default %f (minimum supported: %f).", i, [delayTime floatValue], kDelayTimeIntervalDefault, kFLAnimatedImageDelayTimeIntervalMinimum); + delayTime = @(kDelayTimeIntervalDefault); + } + delayTimesForIndexesMutable[@(i)] = delayTime; + } else { + skippedFrameCount++; + FLLog(FLLogLevelInfo, @"Dropping frame %zu because valid `CGImageRef` %@ did result in `nil`-`UIImage`.", i, frameImageRef); + } + CFRelease(frameImageRef); + } else { + skippedFrameCount++; + FLLog(FLLogLevelInfo, @"Dropping frame %zu because failed to `CGImageSourceCreateImageAtIndex` with image source %@", i, self->_imageSource); + } + } + } + _delayTimesForIndexes = [delayTimesForIndexesMutable copy]; + _frameCount = imageCount; + + if (self.frameCount == 0) { + FLLog(FLLogLevelInfo, @"Failed to create any valid frames for GIF with properties %@", imageProperties); + return nil; + } else if (self.frameCount == 1) { + // Warn when we only have a single frame but return a valid GIF. + FLLog(FLLogLevelInfo, @"Created valid GIF but with only a single frame. Image properties: %@", imageProperties); + } else { + // We have multiple frames, rock on! + } + + // If no value is provided, select a default based on the GIF. + if (optimalFrameCacheSize == 0) { + // Calculate the optimal frame cache size: try choosing a larger buffer window depending on the predicted image size. + // It's only dependent on the image size & number of frames and never changes. + const CGFloat animatedImageDataSize = (CGFloat)CGImageGetBytesPerRow(self.posterImage.CGImage) * self.size.height * (CGFloat)(self.frameCount - skippedFrameCount) / (CGFloat)MEGABYTE; + if (animatedImageDataSize <= FLAnimatedImageDataSizeCategoryAll) { + _frameCacheSizeOptimal = self.frameCount; + } else if (animatedImageDataSize <= FLAnimatedImageDataSizeCategoryDefault) { + // This value doesn't depend on device memory much because if we're not keeping all frames in memory we will always be decoding 1 frame up ahead per 1 frame that gets played and at this point we might as well just keep a small buffer just large enough to keep from running out of frames. + _frameCacheSizeOptimal = FLAnimatedImageFrameCacheSizeDefault; + } else { + // The predicted size exceeds the limits to build up a cache and we go into low memory mode from the beginning. + _frameCacheSizeOptimal = FLAnimatedImageFrameCacheSizeLowMemory; + } + } else { + // Use the provided value. + _frameCacheSizeOptimal = optimalFrameCacheSize; + } + // In any case, cap the optimal cache size at the frame count. + _frameCacheSizeOptimal = MIN(_frameCacheSizeOptimal, self.frameCount); + + // Convenience/minor performance optimization; keep an index set handy with the full range to return in `-frameIndexesToCache`. + _allFramesIndexSet = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, self.frameCount)]; + + // See the property declarations for descriptions. + _weakProxy = (id)[FLWeakProxy weakProxyForObject:self]; + + // Register this instance in the weak table for memory notifications. The NSHashTable will clean up after itself when we're gone. + // Note that FLAnimatedImages can be created on any thread, so the hash table must be locked. + @synchronized(allAnimatedImagesWeak) { + [allAnimatedImagesWeak addObject:self]; + } + } + return self; +} + + ++ (instancetype)animatedImageWithGIFData:(NSData *)data +{ + FLAnimatedImage *const animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:data]; + return animatedImage; +} + + +- (void)dealloc +{ + if (_weakProxy) { + [NSObject cancelPreviousPerformRequestsWithTarget:_weakProxy]; + } + + if (_imageSource) { + CFRelease(_imageSource); + } +} + + +#pragma mark - Public Methods + +// See header for more details. +// Note: both consumer and producer are throttled: consumer by frame timings and producer by the available memory (max buffer window size). +- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index +{ + // Early return if the requested index is beyond bounds. + // Note: We're comparing an index with a count and need to bail on greater than or equal to. + if (index >= self.frameCount) { + FLLog(FLLogLevelWarn, @"Skipping requested frame %lu beyond bounds (total frame count: %lu) for animated image: %@", (unsigned long)index, (unsigned long)self.frameCount, self); + return nil; + } + + // Remember requested frame index, this influences what we should cache next. + self.requestedFrameIndex = index; +#if defined(DEBUG) && DEBUG + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImage:didRequestCachedFrame:)]) { + [self.debug_delegate debug_animatedImage:self didRequestCachedFrame:index]; + } +#endif + + // Quick check to avoid doing any work if we already have all possible frames cached, a common case. + if ([self.cachedFrameIndexes count] < self.frameCount) { + // If we have frames that should be cached but aren't and aren't requested yet, request them. + // Exclude existing cached frames, frames already requested, and specially cached poster image. + NSMutableIndexSet *frameIndexesToAddToCacheMutable = [self frameIndexesToCache]; + [frameIndexesToAddToCacheMutable removeIndexes:self.cachedFrameIndexes]; + [frameIndexesToAddToCacheMutable removeIndexes:self.requestedFrameIndexes]; + [frameIndexesToAddToCacheMutable removeIndex:self.posterImageFrameIndex]; + NSIndexSet *frameIndexesToAddToCache = [frameIndexesToAddToCacheMutable copy]; + + // Asynchronously add frames to our cache. + if ([frameIndexesToAddToCache count] > 0) { + [self addFrameIndexesToCache:frameIndexesToAddToCache]; + } + } + + // Get the specified image. + UIImage *const image = self.cachedFramesForIndexes[@(index)]; + + // Purge if needed based on the current playhead position. + [self purgeFrameCacheIfNeeded]; + + return image; +} + + +// Only called once from `-imageLazilyCachedAtIndex` but factored into its own method for logical grouping. +- (void)addFrameIndexesToCache:(NSIndexSet *)frameIndexesToAddToCache +{ + // Order matters. First, iterate over the indexes starting from the requested frame index. + // Then, if there are any indexes before the requested frame index, do those. + const NSRange firstRange = NSMakeRange(self.requestedFrameIndex, self.frameCount - self.requestedFrameIndex); + const NSRange secondRange = NSMakeRange(0, self.requestedFrameIndex); + if (firstRange.length + secondRange.length != self.frameCount) { + FLLog(FLLogLevelWarn, @"Two-part frame cache range doesn't equal full range."); + } + + // Add to the requested list before we actually kick them off, so they don't get into the queue twice. + [self.requestedFrameIndexes addIndexes:frameIndexesToAddToCache]; + + // Lazily create dedicated isolation queue. + if (!self.serialQueue) { + _serialQueue = dispatch_queue_create("com.flipboard.framecachingqueue", DISPATCH_QUEUE_SERIAL); + } + + // Start streaming requested frames in the background into the cache. + // Avoid capturing self in the block as there's no reason to keep doing work if the animated image went away. + __weak __typeof(self) weakSelf = self; + dispatch_async(self.serialQueue, ^{ + // Produce and cache next needed frame. + void (^frameRangeBlock)(NSRange, BOOL *) = ^(NSRange range, BOOL *stop) { + // Iterate through contiguous indexes; can be faster than `enumerateIndexesInRange:options:usingBlock:`. + for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { +#if defined(DEBUG) && DEBUG + const CFTimeInterval predrawBeginTime = CACurrentMediaTime(); +#endif + UIImage *const image = [weakSelf imageAtIndex:i]; +#if defined(DEBUG) && DEBUG + const CFTimeInterval predrawDuration = CACurrentMediaTime() - predrawBeginTime; + CFTimeInterval slowdownDuration = 0.0; + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImagePredrawingSlowdownFactor:)]) { + CGFloat predrawingSlowdownFactor = [self.debug_delegate debug_animatedImagePredrawingSlowdownFactor:self]; + slowdownDuration = predrawDuration * predrawingSlowdownFactor - predrawDuration; + [NSThread sleepForTimeInterval:slowdownDuration]; + } + FLLog(FLLogLevelVerbose, @"Predrew frame %lu in %f ms for animated image: %@", (unsigned long)i, (predrawDuration + slowdownDuration) * 1000, self); +#endif + // The results get returned one by one as soon as they're ready (and not in batch). + // The benefits of having the first frames as quick as possible outweigh building up a buffer to cope with potential hiccups when the CPU suddenly gets busy. + if (image && weakSelf) { + dispatch_async(dispatch_get_main_queue(), ^{ + weakSelf.cachedFramesForIndexes[@(i)] = image; + [weakSelf.cachedFrameIndexes addIndex:i]; + [weakSelf.requestedFrameIndexes removeIndex:i]; +#if defined(DEBUG) && DEBUG + if ([weakSelf.debug_delegate respondsToSelector:@selector(debug_animatedImage:didUpdateCachedFrames:)]) { + [weakSelf.debug_delegate debug_animatedImage:weakSelf didUpdateCachedFrames:weakSelf.cachedFrameIndexes]; + } +#endif + }); + } + } + }; + + [frameIndexesToAddToCache enumerateRangesInRange:firstRange options:0 usingBlock:frameRangeBlock]; + [frameIndexesToAddToCache enumerateRangesInRange:secondRange options:0 usingBlock:frameRangeBlock]; + }); +} + + ++ (CGSize)sizeForImage:(id)image +{ + CGSize imageSize = CGSizeZero; + + // Early return for nil + if (!image) { + return imageSize; + } + + if ([image isKindOfClass:[UIImage class]]) { + UIImage *const uiImage = (UIImage *)image; + imageSize = uiImage.size; + } else if ([image isKindOfClass:[FLAnimatedImage class]]) { + FLAnimatedImage *const animatedImage = (FLAnimatedImage *)image; + imageSize = animatedImage.size; + } else { + // Bear trap to capture bad images; we have seen crashers cropping up on iOS 7. + FLLog(FLLogLevelError, @"`image` isn't of expected types `UIImage` or `FLAnimatedImage`: %@", image); + } + + return imageSize; +} + + +#pragma mark - Private Methods +#pragma mark Frame Loading + +- (UIImage *)imageAtIndex:(NSUInteger)index +{ + // It's very important to use the cached `_imageSource` since the random access to a frame with `CGImageSourceCreateImageAtIndex` turns from an O(1) into an O(n) operation when re-initializing the image source every time. + const CGImageRef _Nullable imageRef = CGImageSourceCreateImageAtIndex(_imageSource, index, NULL); + + // Early return for nil + if (!imageRef) { + return nil; + } + + UIImage *image = [UIImage imageWithCGImage:imageRef]; + CFRelease(imageRef); + + // Loading in the image object is only half the work, the displaying image view would still have to synchronosly wait and decode the image, so we go ahead and do that here on the background thread. + if (self.isPredrawingEnabled) { + image = [[self class] predrawnImageFromImage:image]; + } + + return image; +} + + +#pragma mark Frame Caching + +- (NSMutableIndexSet *)frameIndexesToCache +{ + NSMutableIndexSet *indexesToCache = nil; + // Quick check to avoid building the index set if the number of frames to cache equals the total frame count. + if (self.frameCacheSizeCurrent == self.frameCount) { + indexesToCache = [self.allFramesIndexSet mutableCopy]; + } else { + indexesToCache = [[NSMutableIndexSet alloc] init]; + + // Add indexes to the set in two separate blocks- the first starting from the requested frame index, up to the limit or the end. + // The second, if needed, the remaining number of frames beginning at index zero. + const NSUInteger firstLength = MIN(self.frameCacheSizeCurrent, self.frameCount - self.requestedFrameIndex); + const NSRange firstRange = NSMakeRange(self.requestedFrameIndex, firstLength); + [indexesToCache addIndexesInRange:firstRange]; + const NSUInteger secondLength = self.frameCacheSizeCurrent - firstLength; + if (secondLength > 0) { + NSRange secondRange = NSMakeRange(0, secondLength); + [indexesToCache addIndexesInRange:secondRange]; + } + // Double check our math, before we add the poster image index which may increase it by one. + if ([indexesToCache count] != self.frameCacheSizeCurrent) { + FLLog(FLLogLevelWarn, @"Number of frames to cache doesn't equal expected cache size."); + } + + [indexesToCache addIndex:self.posterImageFrameIndex]; + } + + return indexesToCache; +} + + +- (void)purgeFrameCacheIfNeeded +{ + // Purge frames that are currently cached but don't need to be. + // But not if we're still under the number of frames to cache. + // This way, if all frames are allowed to be cached (the common case), we can skip all the `NSIndexSet` math below. + if ([self.cachedFrameIndexes count] > self.frameCacheSizeCurrent) { + NSMutableIndexSet *indexesToPurge = [self.cachedFrameIndexes mutableCopy]; + [indexesToPurge removeIndexes:[self frameIndexesToCache]]; + [indexesToPurge enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) { + // Iterate through contiguous indexes; can be faster than `enumerateIndexesInRange:options:usingBlock:`. + for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { + [self.cachedFrameIndexes removeIndex:i]; + [self.cachedFramesForIndexes removeObjectForKey:@(i)]; + // Note: Don't `CGImageSourceRemoveCacheAtIndex` on the image source for frames that we don't want cached any longer to maintain O(1) time access. +#if defined(DEBUG) && DEBUG + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImage:didUpdateCachedFrames:)]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.debug_delegate debug_animatedImage:self didUpdateCachedFrames:self.cachedFrameIndexes]; + }); + } +#endif + } + }]; + } +} + + +- (void)growFrameCacheSizeAfterMemoryWarning:(NSNumber *)frameCacheSize +{ + self.frameCacheSizeMaxInternal = [frameCacheSize unsignedIntegerValue]; + FLLog(FLLogLevelDebug, @"Grew frame cache size max to %lu after memory warning for animated image: %@", (unsigned long)self.frameCacheSizeMaxInternal, self); + + // Schedule resetting the frame cache size max completely after a while. + const NSTimeInterval kResetDelay = 3.0; + [self.weakProxy performSelector:@selector(resetFrameCacheSizeMaxInternal) withObject:nil afterDelay:kResetDelay]; +} + + +- (void)resetFrameCacheSizeMaxInternal +{ + self.frameCacheSizeMaxInternal = FLAnimatedImageFrameCacheSizeNoLimit; + FLLog(FLLogLevelDebug, @"Reset frame cache size max (current frame cache size: %lu) for animated image: %@", (unsigned long)self.frameCacheSizeCurrent, self); +} + + +#pragma mark System Memory Warnings Notification Handler + +- (void)didReceiveMemoryWarning:(NSNotification *)notification +{ + self.memoryWarningCount++; + + // If we were about to grow larger, but got rapped on our knuckles by the system again, cancel. + [NSObject cancelPreviousPerformRequestsWithTarget:self.weakProxy selector:@selector(growFrameCacheSizeAfterMemoryWarning:) object:@(FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning)]; + [NSObject cancelPreviousPerformRequestsWithTarget:self.weakProxy selector:@selector(resetFrameCacheSizeMaxInternal) object:nil]; + + // Go down to the minimum and by that implicitly immediately purge from the cache if needed to not get jettisoned by the system and start producing frames on-demand. + FLLog(FLLogLevelDebug, @"Attempt setting frame cache size max to %lu (previous was %lu) after memory warning #%lu for animated image: %@", (unsigned long)FLAnimatedImageFrameCacheSizeLowMemory, (unsigned long)self.frameCacheSizeMaxInternal, (unsigned long)self.memoryWarningCount, self); + self.frameCacheSizeMaxInternal = FLAnimatedImageFrameCacheSizeLowMemory; + + // Schedule growing larger again after a while, but cap our attempts to prevent a periodic sawtooth wave (ramps upward and then sharply drops) of memory usage. + // + // [mem]^ (2) (5) (6) 1) Loading frames for the first time + // (*)| , , , 2) Mem warning #1; purge cache + // | /| (4)/| /| 3) Grow cache size a bit after a while, if no mem warning occurs + // | / | _/ | _/ | 4) Try to grow cache size back to optimum after a while, if no mem warning occurs + // |(1)/ |_/ |/ |__(7) 5) Mem warning #2; purge cache + // |__/ (3) 6) After repetition of (3) and (4), mem warning #3; purge cache + // +----------------------> 7) After 3 mem warnings, stay at minimum cache size + // [t] + // *) The mem high water mark before we get warned might change for every cycle. + // + const NSUInteger kGrowAttemptsMax = 2; + const NSTimeInterval kGrowDelay = 2.0; + if ((self.memoryWarningCount - 1) <= kGrowAttemptsMax) { + [self.weakProxy performSelector:@selector(growFrameCacheSizeAfterMemoryWarning:) withObject:@(FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning) afterDelay:kGrowDelay]; + } + + // Note: It's not possible to get the level of a memory warning with a public API: http://stackoverflow.com/questions/2915247/iphone-os-memory-warnings-what-do-the-different-levels-mean/2915477#2915477 +} + + +#pragma mark Image Decoding + +// Decodes the image's data and draws it off-screen fully in memory; it's thread-safe and hence can be called on a background thread. +// On success, the returned object is a new `UIImage` instance with the same content as the one passed in. +// On failure, the returned object is the unchanged passed in one; the data will not be predrawn in memory though and an error will be logged. +// First inspired by & good Karma to: https://gist.github.com/steipete/1144242 ++ (UIImage *)predrawnImageFromImage:(UIImage *)imageToPredraw +{ + // Always use a device RGB color space for simplicity and predictability what will be going on. + const CGColorSpaceRef _Nullable colorSpaceDeviceRGBRef = CGColorSpaceCreateDeviceRGB(); + // Early return on failure! + if (!colorSpaceDeviceRGBRef) { + FLLog(FLLogLevelError, @"Failed to `CGColorSpaceCreateDeviceRGB` for image %@", imageToPredraw); + return imageToPredraw; + } + + // Even when the image doesn't have transparency, we have to add the extra channel because Quartz doesn't support other pixel formats than 32 bpp/8 bpc for RGB: + // kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst, kCGImageAlphaPremultipliedLast + // (source: docs "Quartz 2D Programming Guide > Graphics Contexts > Table 2-1 Pixel formats supported for bitmap graphics contexts") + const size_t numberOfComponents = CGColorSpaceGetNumberOfComponents(colorSpaceDeviceRGBRef) + 1; // 4: RGB + A + + // "In iOS 4.0 and later, and OS X v10.6 and later, you can pass NULL if you want Quartz to allocate memory for the bitmap." (source: docs) + void *_Nullable data = NULL; + const size_t width = imageToPredraw.size.width; + const size_t height = imageToPredraw.size.height; + const size_t bitsPerComponent = CHAR_BIT; + + const size_t bitsPerPixel = (bitsPerComponent * numberOfComponents); + const size_t bytesPerPixel = (bitsPerPixel / BYTE_SIZE); + const size_t bytesPerRow = (bytesPerPixel * width); + + CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; + + CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageToPredraw.CGImage); + // If the alpha info doesn't match to one of the supported formats (see above), pick a reasonable supported one. + // "For bitmaps created in iOS 3.2 and later, the drawing environment uses the premultiplied ARGB format to store the bitmap data." (source: docs) + if (alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaOnly) { + alphaInfo = kCGImageAlphaNoneSkipFirst; + } else if (alphaInfo == kCGImageAlphaFirst) { + alphaInfo = kCGImageAlphaPremultipliedFirst; + } else if (alphaInfo == kCGImageAlphaLast) { + alphaInfo = kCGImageAlphaPremultipliedLast; + } + // "The constants for specifying the alpha channel information are declared with the `CGImageAlphaInfo` type but can be passed to this parameter safely." (source: docs) + bitmapInfo |= alphaInfo; + + // Create our own graphics context to draw to; `UIGraphicsGetCurrentContext`/`UIGraphicsBeginImageContextWithOptions` doesn't create a new context but returns the current one which isn't thread-safe (e.g. main thread could use it at the same time). + // Note: It's not worth caching the bitmap context for multiple frames ("unique key" would be `width`, `height` and `hasAlpha`), it's ~50% slower. Time spent in libRIP's `CGSBlendBGRA8888toARGB8888` suddenly shoots up -- not sure why. + const CGContextRef _Nullable bitmapContextRef = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpaceDeviceRGBRef, bitmapInfo); + CGColorSpaceRelease(colorSpaceDeviceRGBRef); + // Early return on failure! + if (!bitmapContextRef) { + FLLog(FLLogLevelError, @"Failed to `CGBitmapContextCreate` with color space %@ and parameters (width: %zu height: %zu bitsPerComponent: %zu bytesPerRow: %zu) for image %@", colorSpaceDeviceRGBRef, width, height, bitsPerComponent, bytesPerRow, imageToPredraw); + return imageToPredraw; + } + + // Draw image in bitmap context and create image by preserving receiver's properties. + CGContextDrawImage(bitmapContextRef, CGRectMake(0.0, 0.0, imageToPredraw.size.width, imageToPredraw.size.height), imageToPredraw.CGImage); + const CGImageRef _Nullable predrawnImageRef = CGBitmapContextCreateImage(bitmapContextRef); + UIImage *_Nullable predrawnImage = predrawnImageRef ? [UIImage imageWithCGImage:predrawnImageRef scale:imageToPredraw.scale orientation:imageToPredraw.imageOrientation] : nil; + CGImageRelease(predrawnImageRef); + CGContextRelease(bitmapContextRef); + + // Early return on failure! + if (!predrawnImage) { + FLLog(FLLogLevelError, @"Failed to `imageWithCGImage:scale:orientation:` with image ref %@ created with color space %@ and bitmap context %@ and properties and properties (scale: %f orientation: %ld) for image %@", predrawnImageRef, colorSpaceDeviceRGBRef, bitmapContextRef, imageToPredraw.scale, (long)imageToPredraw.imageOrientation, imageToPredraw); + return imageToPredraw; + } + + return predrawnImage; +} + + +#pragma mark - Description + +- (NSString *)description +{ + NSString *description = [super description]; + + description = [description stringByAppendingFormat:@" size=%@", NSStringFromCGSize(self.size)]; + description = [description stringByAppendingFormat:@" frameCount=%lu", (unsigned long)self.frameCount]; + + return description; +} + + +@end + +#pragma mark - Logging + +@implementation FLAnimatedImage (Logging) + +static void (^_logBlock)(NSString *logString, FLLogLevel logLevel) = nil; +static FLLogLevel _logLevel; + ++ (void)setLogBlock:(void (^_Nullable)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel +{ + _logBlock = [logBlock copy]; + _logLevel = logLevel; +} + ++ (void)logStringFromBlock:(NSString *(^_Nullable)(void))stringBlock withLevel:(FLLogLevel)level +{ + if (level <= _logLevel && _logBlock && stringBlock) { + _logBlock(stringBlock(), level); + } +} + +@end + + +#pragma mark - FLWeakProxy + +@interface FLWeakProxy () + +@property (nonatomic, weak) id target; + +@end + + +@implementation FLWeakProxy + +#pragma mark Life Cycle + +// This is the designated creation method of an `FLWeakProxy` and +// as a subclass of `NSProxy` it doesn't respond to or need `-init`. ++ (instancetype)weakProxyForObject:(id)targetObject +{ + FLWeakProxy *weakProxy = [FLWeakProxy alloc]; + weakProxy.target = targetObject; + return weakProxy; +} + + +#pragma mark Forwarding Messages + +- (id)forwardingTargetForSelector:(SEL)selector +{ + // Keep it lightweight: access the ivar directly + return _target; +} + + +#pragma mark - NSWeakProxy Method Overrides +#pragma mark Handling Unimplemented Methods + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + // Fallback for when target is nil. Don't do anything, just return 0/NULL/nil. + // The method signature we've received to get here is just a dummy to keep `doesNotRecognizeSelector:` from firing. + // We can't really handle struct return types here because we don't know the length. + void *_Nullable nullPointer = NULL; + [invocation setReturnValue:&nullPointer]; +} + + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector +{ + // We only get here if `forwardingTargetForSelector:` returns nil. + // In that case, our weak target has been reclaimed. Return a dummy method signature to keep `doesNotRecognizeSelector:` from firing. + // We'll emulate the Obj-c messaging nil behavior by setting the return value to nil in `forwardInvocation:`, but we'll assume that the return value is `sizeof(void *)`. + // Other libraries handle this situation by making use of a global method signature cache, but that seems heavier than necessary and has issues as well. + // See https://www.mikeash.com/pyblog/friday-qa-2010-02-26-futures.html and https://github.com/steipete/PSTDelegateProxy/issues/1 for examples of using a method signature cache. + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} + + +@end diff --git a/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.m b/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.m new file mode 100755 index 0000000..34178ef --- /dev/null +++ b/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.m @@ -0,0 +1,460 @@ +// +// FLAnimatedImageView.h +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) Flipboard. All rights reserved. +// + + +#import "FLAnimatedImageView.h" +#import "FLAnimatedImage.h" +#import + + +#if defined(DEBUG) && DEBUG +@protocol FLAnimatedImageViewDebugDelegate +@optional +- (void)debug_animatedImageView:(FLAnimatedImageView *)animatedImageView waitingForFrame:(NSUInteger)index duration:(NSTimeInterval)duration; +@end +#endif + + +@interface FLAnimatedImageView () + +// Override of public `readonly` properties as private `readwrite` +@property (nonatomic, strong, readwrite) UIImage *currentFrame; +@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex; + +@property (nonatomic, assign) NSUInteger loopCountdown; +@property (nonatomic, assign) NSTimeInterval accumulator; +@property (nonatomic, strong) CADisplayLink *displayLink; + +@property (nonatomic, assign) BOOL shouldAnimate; // Before checking this value, call `-updateShouldAnimate` whenever the animated image or visibility (window, superview, hidden, alpha) has changed. +@property (nonatomic, assign) BOOL needsDisplayWhenImageBecomesAvailable; + +#if defined(DEBUG) && DEBUG +@property (nonatomic, weak) id debug_delegate; +#endif + +@end + + +@implementation FLAnimatedImageView +@synthesize runLoopMode = _runLoopMode; + +#pragma mark - Initializers + +// -initWithImage: isn't documented as a designated initializer of UIImageView, but it actually seems to be. +// Using -initWithImage: doesn't call any of the other designated initializers. +- (instancetype)initWithImage:(UIImage *)image +{ + self = [super initWithImage:image]; + if (self) { + [self commonInit]; + } + return self; +} + +// -initWithImage:highlightedImage: also isn't documented as a designated initializer of UIImageView, but it doesn't call any other designated initializers. +- (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage +{ + self = [super initWithImage:image highlightedImage:highlightedImage]; + if (self) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit +{ + self.runLoopMode = [[self class] defaultRunLoopMode]; + + if (@available(iOS 11.0, *)) { + self.accessibilityIgnoresInvertColors = YES; + } +} + + +#pragma mark - Accessors +#pragma mark Public + +- (void)setAnimatedImage:(FLAnimatedImage *)animatedImage +{ + if (![_animatedImage isEqual:animatedImage]) { + if (animatedImage) { + if (super.image) { + // UIImageView's `setImage:` will internally call its layer's `setContentsTransform:` based on the `image.imageOrientation`. + // The `contentsTransform` will affect layer rendering rotation because the CGImage's bitmap buffer does not actually take rotation. + // However, when calling `setImage:nil`, this `contentsTransform` will not be reset to identity. + // Further animation frame will be rendered as rotated. So we must set it to the poster image to clear the previous state. + // See more here: https://github.com/Flipboard/FLAnimatedImage/issues/100 + super.image = animatedImage.posterImage; + // Clear out the image. + super.image = nil; + } + // Ensure disabled highlighting; it's not supported (see `-setHighlighted:`). + super.highlighted = NO; + // UIImageView seems to bypass some accessors when calculating its intrinsic content size, so this ensures its intrinsic content size comes from the animated image. + [self invalidateIntrinsicContentSize]; + } else { + // Stop animating before the animated image gets cleared out. + [self stopAnimating]; + } + + _animatedImage = animatedImage; + + self.currentFrame = animatedImage.posterImage; + self.currentFrameIndex = 0; + if (animatedImage.loopCount > 0) { + self.loopCountdown = animatedImage.loopCount; + } else { + self.loopCountdown = NSUIntegerMax; + } + self.accumulator = 0.0; + + // Start animating after the new animated image has been set. + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } + + [self.layer setNeedsDisplay]; + } +} + + +#pragma mark - Life Cycle + +- (void)dealloc +{ + // Removes the display link from all run loop modes. + [_displayLink invalidate]; +} + + +#pragma mark - UIView Method Overrides +#pragma mark Observing View-Related Changes + +- (void)didMoveToSuperview +{ + [super didMoveToSuperview]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + + +- (void)didMoveToWindow +{ + [super didMoveToWindow]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + +- (void)setAlpha:(CGFloat)alpha +{ + [super setAlpha:alpha]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + +- (void)setHidden:(BOOL)hidden +{ + [super setHidden:hidden]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + + +#pragma mark Auto Layout + +- (CGSize)intrinsicContentSize +{ + // Default to let UIImageView handle the sizing of its image, and anything else it might consider. + CGSize intrinsicContentSize = [super intrinsicContentSize]; + + // If we have have an animated image, use its image size. + // UIImageView's intrinsic content size seems to be the size of its image. The obvious approach, simply calling `-invalidateIntrinsicContentSize` when setting an animated image, results in UIImageView steadfastly returning `{UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric}` for its intrinsicContentSize. + // (Perhaps UIImageView bypasses its `-image` getter in its implementation of `-intrinsicContentSize`, as `-image` is not called after calling `-invalidateIntrinsicContentSize`.) + if (self.animatedImage) { + intrinsicContentSize = self.image.size; + } + + return intrinsicContentSize; +} + + +#pragma mark - UIImageView Method Overrides +#pragma mark Image Data + +- (UIImage *)image +{ + UIImage *image = nil; + if (self.animatedImage) { + // Initially set to the poster image. + image = self.currentFrame; + } else { + image = super.image; + } + return image; +} + + +- (void)setImage:(UIImage *)image +{ + if (image) { + // Clear out the animated image and implicitly pause animation playback. + self.animatedImage = nil; + } + + super.image = image; +} + + +#pragma mark Animating Images + +- (NSTimeInterval)frameDelayGreatestCommonDivisor +{ + // Presision is set to half of the `kFLAnimatedImageDelayTimeIntervalMinimum` in order to minimize frame dropping. + const NSTimeInterval kGreatestCommonDivisorPrecision = 2.0 / kFLAnimatedImageDelayTimeIntervalMinimum; + + NSArray *const delays = self.animatedImage.delayTimesForIndexes.allValues; + + // Scales the frame delays by `kGreatestCommonDivisorPrecision` + // then converts it to an UInteger for in order to calculate the GCD. + NSUInteger scaledGCD = lrint([delays.firstObject floatValue] * kGreatestCommonDivisorPrecision); + for (NSNumber *value in delays) { + scaledGCD = gcd(lrint([value floatValue] * kGreatestCommonDivisorPrecision), scaledGCD); + } + + // Reverse to scale to get the value back into seconds. + return (double)scaledGCD / kGreatestCommonDivisorPrecision; +} + + +static NSUInteger gcd(NSUInteger a, NSUInteger b) +{ + // http://en.wikipedia.org/wiki/Greatest_common_divisor + if (a < b) { + return gcd(b, a); + } else if (a == b) { + return b; + } + + while (true) { + const NSUInteger remainder = a % b; + if (remainder == 0) { + return b; + } + a = b; + b = remainder; + } +} + + +- (void)startAnimating +{ + if (self.animatedImage) { + // Lazily create the display link. + if (!self.displayLink) { + // It is important to note the use of a weak proxy here to avoid a retain cycle. `-displayLinkWithTarget:selector:` + // will retain its target until it is invalidated. We use a weak proxy so that the image view will get deallocated + // independent of the display link's lifetime. Upon image view deallocation, we invalidate the display + // link which will lead to the deallocation of both the display link and the weak proxy. + FLWeakProxy *weakProxy = [FLWeakProxy weakProxyForObject:self]; + self.displayLink = [CADisplayLink displayLinkWithTarget:weakProxy selector:@selector(displayDidRefresh:)]; + + [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:self.runLoopMode]; + } + + if (@available(iOS 10, *)) { + // Adjusting preferredFramesPerSecond allows us to skip unnecessary calls to displayDidRefresh: when showing GIFs + // that don't animate quickly. Use ceil to err on the side of too many FPS so we don't miss a frame transition moment. + self.displayLink.preferredFramesPerSecond = ceil(1.0 / [self frameDelayGreatestCommonDivisor]); + } else { + const NSTimeInterval kDisplayRefreshRate = 60.0; // 60Hz + self.displayLink.frameInterval = MAX([self frameDelayGreatestCommonDivisor] * kDisplayRefreshRate, 1); + } + self.displayLink.paused = NO; + } else { + [super startAnimating]; + } +} + +- (void)setRunLoopMode:(NSRunLoopMode)runLoopMode +{ + if (![@[NSDefaultRunLoopMode, NSRunLoopCommonModes] containsObject:runLoopMode]) { + NSAssert(NO, @"Invalid run loop mode: %@", runLoopMode); + _runLoopMode = [[self class] defaultRunLoopMode]; + } else { + _runLoopMode = runLoopMode; + } +} + +- (void)stopAnimating +{ + if (self.animatedImage) { + self.displayLink.paused = YES; + } else { + [super stopAnimating]; + } +} + + +- (BOOL)isAnimating +{ + BOOL isAnimating = NO; + if (self.animatedImage) { + isAnimating = self.displayLink && !self.displayLink.isPaused; + } else { + isAnimating = [super isAnimating]; + } + return isAnimating; +} + + +#pragma mark Highlighted Image Unsupport + +- (void)setHighlighted:(BOOL)highlighted +{ + // Highlighted image is unsupported for animated images, but implementing it breaks the image view when embedded in a UICollectionViewCell. + if (!self.animatedImage) { + [super setHighlighted:highlighted]; + } +} + + +#pragma mark - Private Methods +#pragma mark Animation + +// Don't repeatedly check our window & superview in `-displayDidRefresh:` for performance reasons. +// Just update our cached value whenever the animated image or visibility (window, superview, hidden, alpha) is changed. +- (void)updateShouldAnimate +{ + const BOOL isVisible = self.window && self.superview && ![self isHidden] && self.alpha > 0.0; + self.shouldAnimate = self.animatedImage && isVisible; +} + + +- (void)displayDidRefresh:(CADisplayLink *)displayLink +{ + // If for some reason a wild call makes it through when we shouldn't be animating, bail. + // Early return! + if (!self.shouldAnimate) { + FLLog(FLLogLevelWarn, @"Trying to animate image when we shouldn't: %@", self); + return; + } + + NSNumber *_Nullable const delayTimeNumber = [self.animatedImage.delayTimesForIndexes objectForKey:@(self.currentFrameIndex)]; + // If we don't have a frame delay (e.g. corrupt frame), don't update the view but skip the playhead to the next frame (in else-block). + if (delayTimeNumber != nil) { + const NSTimeInterval delayTime = [delayTimeNumber floatValue]; + // If we have a nil image (e.g. waiting for frame), don't update the view nor playhead. + UIImage *_Nullable const image = [self.animatedImage imageLazilyCachedAtIndex:self.currentFrameIndex]; + if (image) { + FLLog(FLLogLevelVerbose, @"Showing frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage); + self.currentFrame = image; + if (self.needsDisplayWhenImageBecomesAvailable) { + [self.layer setNeedsDisplay]; + self.needsDisplayWhenImageBecomesAvailable = NO; + } + + if (@available(iOS 10, *)) { + self.accumulator += displayLink.targetTimestamp - CACurrentMediaTime(); + } else { + self.accumulator += displayLink.duration * (NSTimeInterval)displayLink.frameInterval; + } + + // While-loop first inspired by & good Karma to: https://github.com/ondalabs/OLImageView/blob/master/OLImageView.m + while (self.accumulator >= delayTime) { + self.accumulator -= delayTime; + self.currentFrameIndex++; + if (self.currentFrameIndex >= self.animatedImage.frameCount) { + // If we've looped the number of times that this animated image describes, stop looping. + self.loopCountdown--; + if (self.loopCompletionBlock) { + self.loopCompletionBlock(self.loopCountdown); + } + + if (self.loopCountdown == 0) { + [self stopAnimating]; + return; + } + self.currentFrameIndex = 0; + } + // Calling `-setNeedsDisplay` will just paint the current frame, not the new frame that we may have moved to. + // Instead, set `needsDisplayWhenImageBecomesAvailable` to `YES` -- this will paint the new image once loaded. + self.needsDisplayWhenImageBecomesAvailable = YES; + } + } else { + FLLog(FLLogLevelDebug, @"Waiting for frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage); +#if defined(DEBUG) && DEBUG + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImageView:waitingForFrame:duration:)]) { + if (@available(iOS 10, *)) { + [self.debug_delegate debug_animatedImageView:self waitingForFrame:self.currentFrameIndex duration:displayLink.targetTimestamp - CACurrentMediaTime()]; + } else { + [self.debug_delegate debug_animatedImageView:self waitingForFrame:self.currentFrameIndex duration:displayLink.duration * (NSTimeInterval)displayLink.frameInterval]; + } + } +#endif + } + } else { + self.currentFrameIndex++; + } +} + ++ (NSRunLoopMode)defaultRunLoopMode +{ + // Key off `activeProcessorCount` (as opposed to `processorCount`) since the system could shut down cores in certain situations. + return [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode; +} + + +#pragma mark - CALayerDelegate (Informal) +#pragma mark Providing the Layer's Content + +- (void)displayLayer:(CALayer *)layer +{ + layer.contents = (__bridge id)self.image.CGImage; +} + + +@end diff --git a/Pods/FLAnimatedImage/FLAnimatedImage/include/FLAnimatedImage.h b/Pods/FLAnimatedImage/FLAnimatedImage/include/FLAnimatedImage.h new file mode 100644 index 0000000..0dd731c --- /dev/null +++ b/Pods/FLAnimatedImage/FLAnimatedImage/include/FLAnimatedImage.h @@ -0,0 +1,83 @@ +// +// FLAnimatedImage.h +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) Flipboard. All rights reserved. +// + + +#import + +// Allow user classes conveniently just importing one header. +#import "FLAnimatedImageView.h" + +#ifndef NS_DESIGNATED_INITIALIZER + #if __has_attribute(objc_designated_initializer) + #define NS_DESIGNATED_INITIALIZER __attribute((objc_designated_initializer)) + #else + #define NS_DESIGNATED_INITIALIZER + #endif +#endif + +extern const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum; + +// +// An `FLAnimatedImage`'s job is to deliver frames in a highly performant way and works in conjunction with `FLAnimatedImageView`. +// It subclasses `NSObject` and not `UIImage` because it's only an "image" in the sense that a sea lion is a lion. +// It tries to intelligently choose the frame cache size depending on the image and memory situation with the goal to lower CPU usage for smaller ones, lower memory usage for larger ones and always deliver frames for high performant play-back. +// Note: `posterImage`, `size`, `loopCount`, `delayTimes` and `frameCount` don't change after successful initialization. +// +@interface FLAnimatedImage : NSObject + +@property (nonatomic, strong, readonly) UIImage *posterImage; // Guaranteed to be loaded; usually equivalent to `-imageLazilyCachedAtIndex:0` +@property (nonatomic, assign, readonly) CGSize size; // The `.posterImage`'s `.size` + +@property (nonatomic, assign, readonly) NSUInteger loopCount; // "The number of times to repeat an animated sequence." according to ImageIO (note the slightly different definition to Netscape 2.0 Loop Extension); 0 means repeating the animation forever +@property (nonatomic, strong, readonly) NSDictionary *delayTimesForIndexes; // Of type `NSTimeInterval` boxed in `NSNumber`s +@property (nonatomic, assign, readonly) NSUInteger frameCount; // Number of valid frames; equal to `[.delayTimes count]` + +@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeCurrent; // Current size of intelligently chosen buffer window; can range in the interval [1..frameCount] +@property (nonatomic, assign) NSUInteger frameCacheSizeMax; // Allow to cap the cache size; 0 means no specific limit (default) + +// Intended to be called from main thread synchronously; will return immediately. +// If the result isn't cached, will return `nil`; the caller should then pause playback, not increment frame counter and keep polling. +// After an initial loading time, depending on `frameCacheSize`, frames should be available immediately from the cache. +- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index; + +// Pass either a `UIImage` or an `FLAnimatedImage` and get back its size ++ (CGSize)sizeForImage:(id)image; + +// On success, the initializers return an `FLAnimatedImage` with all fields initialized, on failure they return `nil` and an error will be logged. +- (instancetype)initWithAnimatedGIFData:(NSData *)data; +// Pass 0 for optimalFrameCacheSize to get the default, predrawing is enabled by default. +- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled NS_DESIGNATED_INITIALIZER; ++ (instancetype)animatedImageWithGIFData:(NSData *)data; + +@property (nonatomic, strong, readonly) NSData *data; // The data the receiver was initialized with; read-only + +@end + +typedef NS_ENUM(NSUInteger, FLLogLevel) { + FLLogLevelNone = 0, + FLLogLevelError, + FLLogLevelWarn, + FLLogLevelInfo, + FLLogLevelDebug, + FLLogLevelVerbose +}; + +@interface FLAnimatedImage (Logging) + ++ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel; ++ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level; + +@end + +#define FLLog(logLevel, format, ...) [FLAnimatedImage logStringFromBlock:^NSString *{ return [NSString stringWithFormat:(format), ## __VA_ARGS__]; } withLevel:(logLevel)] + +@interface FLWeakProxy : NSProxy + ++ (instancetype)weakProxyForObject:(id)targetObject; + +@end diff --git a/Pods/FLAnimatedImage/FLAnimatedImage/include/FLAnimatedImageView.h b/Pods/FLAnimatedImage/FLAnimatedImage/include/FLAnimatedImageView.h new file mode 100644 index 0000000..8884e53 --- /dev/null +++ b/Pods/FLAnimatedImage/FLAnimatedImage/include/FLAnimatedImageView.h @@ -0,0 +1,36 @@ +// +// FLAnimatedImageView.h +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) Flipboard. All rights reserved. +// + + +#import + +@class FLAnimatedImage; +@protocol FLAnimatedImageViewDebugDelegate; + + +// +// An `FLAnimatedImageView` can take an `FLAnimatedImage` and plays it automatically when in view hierarchy and stops when removed. +// The animation can also be controlled with the `UIImageView` methods `-start/stop/isAnimating`. +// It is a fully compatible `UIImageView` subclass and can be used as a drop-in component to work with existing code paths expecting to display a `UIImage`. +// Under the hood it uses a `CADisplayLink` for playback, which can be inspected with `currentFrame` & `currentFrameIndex`. +// +@interface FLAnimatedImageView : UIImageView + +// Setting `[UIImageView.image]` to a non-`nil` value clears out existing `animatedImage`. +// And vice versa, setting `animatedImage` will initially populate the `[UIImageView.image]` to its `posterImage` and then start animating and hold `currentFrame`. +@property (nonatomic, strong) FLAnimatedImage *animatedImage; +@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining); + +@property (nonatomic, strong, readonly) UIImage *currentFrame; +@property (nonatomic, assign, readonly) NSUInteger currentFrameIndex; + +// The animation runloop mode. Enables playback during scrolling by allowing timer events (i.e. animation) with NSRunLoopCommonModes. +// To keep scrolling smooth on single-core devices such as iPhone 3GS/4 and iPod Touch 4th gen, the default run loop mode is NSDefaultRunLoopMode. Otherwise, the default is NSDefaultRunLoopMode. +@property (nonatomic, copy) NSRunLoopMode runLoopMode; + +@end diff --git a/Pods/FLAnimatedImage/LICENSE b/Pods/FLAnimatedImage/LICENSE new file mode 100644 index 0000000..632653f --- /dev/null +++ b/Pods/FLAnimatedImage/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016 Flipboard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/FLAnimatedImage/README.md b/Pods/FLAnimatedImage/README.md new file mode 100644 index 0000000..79c1d85 --- /dev/null +++ b/Pods/FLAnimatedImage/README.md @@ -0,0 +1,122 @@ +# [FLAnimatedImage](https://github.com/Flipboard/FLAnimatedImage) · [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Flipboard/FLAnimatedImage/blob/master/LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Flipboard/FLAnimatedImage/pulls) + +FLAnimatedImage is a performant animated GIF engine for iOS: + +- Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers +- Honors variable frame delays +- Behaves gracefully under memory pressure +- Eliminates delays or blocking during the first playback loop +- Interprets the frame delays of fast GIFs the same way modern browsers do + +It's a well-tested [component that powers all GIFs in Flipboard](http://engineering.flipboard.com/2014/05/animated-gif). To understand its behavior it comes with an interactive demo: + +![Flipboard playing multiple GIFs](https://github.com/Flipboard/FLAnimatedImage/raw/master/images/flanimatedimage-demo-player.gif) + +## Who is this for? + +- Apps that don't support animated GIFs yet +- Apps that already support animated GIFs but want a higher performance solution +- People who want to tinker with the code ([the corresponding blog post](http://engineering.flipboard.com/2014/05/animated-gif/) is a great place to start; also see the *To Do* section below) + +## Installation & Usage + +FLAnimatedImage is a well-encapsulated drop-in component. Simply replace your `UIImageView` instances with instances of `FLAnimatedImageView` to get animated GIF support. There is no central cache or state to manage. + +If using CocoaPods, the quickest way to try it out is to type this on the command line: + +```shell +$ pod try FLAnimatedImage +``` + +To add it to your app, copy the two classes `FLAnimatedImage.h/.m` and `FLAnimatedImageView.h/.m` into your Xcode project or add via [CocoaPods](http://cocoapods.org) by adding this to your Podfile: + +```ruby +pod 'FLAnimatedImage', '~> 1.0' +``` + +If using [Carthage](https://github.com/Carthage/Carthage), add the following line into your `Cartfile` + +``` +github "Flipboard/FLAnimatedImage" +``` + +If using [Swift Package Manager](https://github.com/apple/swift-package-manager), add the following to your `Package.swift` or add via XCode: + +```swift +dependencies: [ + .package(url: "https://github.com/Flipboard/FLAnimatedImage.git", .upToNextMajor(from: "1.0.16")) +], +targets: [ + .target(name: "TestProject", dependencies: ["FLAnimatedImage""]) +] +``` + +In your code, `#import "FLAnimatedImage.h"`, create an image from an animated GIF, and setup the image view to display it: + +```objective-c +FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]]]; +FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init]; +imageView.animatedImage = image; +imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0); +[self.view addSubview:imageView]; +``` + +It's flexible to integrate in your custom image loading stack and backwards compatible to iOS 9. + +It uses ARC and the Apple frameworks `QuartzCore`, `ImageIO`, `MobileCoreServices`, and `CoreGraphics`. + +It is capable of fine-grained logging. A block can be set on `FLAnimatedImage` that's invoked when logging occurs with various log levels via the `+setLogBlock:logLevel:` method. For example: + +```objective-c +// Set up FLAnimatedImage logging. +[FLAnimatedImage setLogBlock:^(NSString *logString, FLLogLevel logLevel) { + // Using NSLog + NSLog(@"%@", logString); + + // ...or CocoaLumberjackLogger only logging warnings and errors + if (logLevel == FLLogLevelError) { + DDLogError(@"%@", logString); + } else if (logLevel == FLLogLevelWarn) { + DDLogWarn(@"%@", logString); + } +} logLevel:FLLogLevelWarn]; +``` + +Since FLAnimatedImage is licensed under MIT, it's compatible with the terms of using it for any app on the App Store. + +## Release process +1. Bump version in `FLAnimatedImage.podspec`, update CHANGES, and commit. +2. Tag commit with `> git tag -a -m ""` and `> git push --tags`. +3. [Submit Podspec to Trunk with](https://guides.cocoapods.org/making/specs-and-specs-repo.html#how-do-i-update-an-existing-pod) `> pod trunk push FLAnimatedImage.podspec` ([ensure you're auth'ed](https://guides.cocoapods.org/making/getting-setup-with-trunk.html#getting-started)). +## To Do +- Support other animated image formats such as APNG or WebP (WebP support implemented [here](https://github.com/Flipboard/FLAnimatedImage/pull/86)) +- Integration into network libraries and image caches +- Investigate whether `FLAnimatedImage` should become a `UIImage` subclass +- Smarter buffering +- Bring demo app to iPhone + +This code has successfully shipped to many people as is, but please do come with your questions, issues and pull requests! + +## Select apps using FLAnimatedImage +(alphabetically) + +- [Close-up](http://closeu.pe) +- [Design Shots](https://itunes.apple.com/app/id792517951) +- [Dropbox](https://www.dropbox.com) +- [Dumpert](http://dumpert.nl) +- [Ello](https://ello.co/) +- [Facebook](https://facebook.com) +- [Flipboard](https://flipboard.com) +- [getGIF](https://itunes.apple.com/app/id964784701) +- [Gifalicious](https://itunes.apple.com/us/app/gifalicious-see-your-gifs/id965346708?mt=8) +- [HashPhotos](https://itunes.apple.com/app/id685784609) +- [Instagram](https://www.instagram.com/) +- [LiveBooth](http://www.liveboothapp.com) +- [lWlVl Festival](http://lwlvl.com) +- [Medium](https://medium.com) +- [Pinterest](https://pinterest.com) +- [Slack](https://slack.com/) +- [Telegram](https://telegram.org/) +- [Zip Code Finder](https://itunes.apple.com/app/id893031254) + +If you're using FLAnimatedImage in your app, please open a PR to add it to this list! diff --git a/Pods/HWPanModal/LICENSE b/Pods/HWPanModal/LICENSE new file mode 100644 index 0000000..2d7cb4e --- /dev/null +++ b/Pods/HWPanModal/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Heath Wang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/HWPanModal/README-CN.md b/Pods/HWPanModal/README-CN.md new file mode 100644 index 0000000..e44e914 --- /dev/null +++ b/Pods/HWPanModal/README-CN.md @@ -0,0 +1,330 @@ + +# HWPanModal 👍 +

+ + + + + + + + + + + + + + + + + codebeat badge + +

+ + +HWPanModal 用于从底部弹出控制器(UIViewController),并用拖拽手势来关闭控制器。提供了自定义视图大小和位置,高度自定义弹出视图的各个属性。 + +APP中常见的从底部弹出视图,可以通过该框架快速实现,只需专注于相应的视图编写。常规热门app的UI示例: +1. 知乎APP的查看评论 +2. 抖音的评论查看 +3. 微信,网易音乐等app弹出分享 +4. 嘀嗒出行行程进行页(地图上的浮层view效果) +5. iOS13 默认模态(present)效果 +6. And more... + +## 特别感谢 + +Special Thanks to JetBrains! I use AppCode IDE to develop my open source project. +

+ + + +

+ +## 截图 + +
+ + + + + + + + + + + + + +
BasicBlur backgroundKeyboard handleApp demo
+ + + + + + + +
+
+ +## 功能 +1. 支持任意类型的 `UIViewController` +2. 支持继承自 `HWPanModalContentView` 的view +3. 平滑的转场动画 +4. 支持2种类型的手势dismiss视图 + 1. 上下方向拖动关闭视图。 + 2. 侧滑关闭视图,支持全屏侧滑。 +5. 支持为presenting VC编写自定义动画。 +6. 支持配置动画时间,动画options,弹性spring值 +7. 支持配置背景alpha,或者高斯模糊背景。注意:动态调整模糊效果仅工作于iOS9.0+。 +8. 支持显示隐藏指示器,修改圆角 +9. 自动处理键盘弹出消失事件。 +10. 自定义指示器indicator view。 +11. 事件可以穿透到下层presenting VC。 +12. 可配置presented content 阴影。 + +更多配置信息请参阅 [_HWPanModalPresentable.h_](https://github.com/HeathWang/HWPanModal/blob/master/Sources/Presentable/HWPanModalPresentable.h) 声明。 + +## 特别注意 + +1. 任何情况下,内部嵌套scrollable(UIScrollView,UITableView,UIWebView,UICollectionView),如果scrollable的contentSize变化了,务必调用`- (void)hw_panModalSetNeedsLayoutUpdate`刷新UI!!! +2. 如果需要弹出浮层后push到下一层,使用`HWPanModalContentView`或者present vc用navigation 包一层。 +3. 请仔细阅读md,编译run示例代码,95%的功能在示例中都有展示,不要什么都不看就来问问题!!! + + +### 支持UIViewController和继承自HWPanModalContentView弹出视图 + +从0.6.0版本后, 该框架支持使用 `HWPanModalContentView` 从底部弹出视图, 即实现了present ViewController同样的交互和动画。 + +不同点是 `HWPanModalContentView` 只是一个view视图, 通过添加一些动画实现了原本的功能。不像present ViewController的模式,你可以获得controller的整个生命周期,并且可以使用navigation栈来push VC。 + +`HWPanModalContentView` 目前的限制: +* 不支持转屏。 +* 不支持屏幕边缘横向拖拽来dismiss。 +* 不支持自定义presenting VC动画。(因为是view,没有presenting VC) + + +## 适配 +**iOS 8.0+**, support Objective-C & Swift. + +## 安装 + +### [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) + +```ruby +pod 'HWPanModal', '~> 0.9.4' +``` + +## 如何使用 + +### 如何从底部弹出控制器 +只需要视图控制器适配 `HWPanModalPresentable` 协议即可. 默认情况下,不用重写适配的各个方法,如果需要自定义,请实现协议方法。 + +更多的自定义UI配置,请参见`HWPanModalPresentable`协议中每个方法的说明。 + +```Objective-C +#import +@interface HWBaseViewController () + +@end + +@implementation HWBaseViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +#pragma mark - HWPanModalPresentable +- (PanModalHeight)longFormHeight { + return PanModalHeightMake(PanModalHeightTypeMaxTopInset, 44); +} +@end +``` + +弹出控制器: + +```Objective-C +#import +[self presentPanModal:[HWBaseViewController new]]; +``` + +就是这么简单。 + +### 如何主动更新控制器UI +请查阅 `UIViewController+Presentation.h`,里面有详细说明。 +* Change the state between short and long form. call `- (void)hw_panModalTransitionTo:(PresentationState)state;` +* Change ScrollView ContentOffset. call `- (void)hw_panModalSetContentOffset:(CGPoint)offset;` +* Reload layout. call `- (void)hw_panModalSetNeedsLayoutUpdate;` + * 注意:如果scrollable view的contentSize改变了,你必须调用改reload方法来更新UI。 + +### 自定义presenting VC动画编写 + +1. Create object conforms `HWPresentingViewControllerAnimatedTransitioning` . + + ```Objective-C + + @interface HWMyCustomAnimation : NSObject + + @end + + @implementation HWMyCustomAnimation + + + - (void)presentAnimateTransition:(id)transitionContext { + NSTimeInterval duration = [transitionContext transitionDuration]; + UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; + // replace it. + [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + fromVC.view.transform = CGAffineTransformMakeScale(0.95, 0.95); + } completion:^(BOOL finished) { + + }]; + } + + - (void)dismissAnimateTransition:(id)transitionContext { + NSTimeInterval duration = [transitionContext transitionDuration]; + UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; + // replace it. + [UIView animateWithDuration:duration animations:^{ + toVC.view.transform = CGAffineTransformIdentity; + }]; + } + + @end + ``` +1. Overwrite below two method. + + ```Objective-C + - (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle { + return PresentingViewControllerAnimationStyleCustom; + } + + - (id)customPresentingVCAnimation { + return self.customAnimation; + } + + - (HWMyCustomAnimation *)customAnimation { + if (!_customAnimation) { + _customAnimation = [HWMyCustomAnimation new]; + } + return _customAnimation; + } + ``` + +### 自定义指示器indicator view + +You just need to create your own UIView, then adopt `HWPanModalIndicatorProtocol`. + +In your presented controller, return it: + +```Objective-C +- (nullable UIView *)customIndicatorView { + HWTextIndicatorView *textIndicatorView = [HWTextIndicatorView new]; + return textIndicatorView; +} +``` + +Here is `HWTextIndicatorView` code: + +```Objective-C +@interface HWTextIndicatorView : UIView + +@end + +@interface HWTextIndicatorView () +@property (nonatomic, strong) UILabel *stateLabel; +@end + +@implementation HWTextIndicatorView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // init the _stateLabel + [self addSubview:_stateLabel]; + } + return self; +} + + +- (void)didChangeToState:(HWIndicatorState)state { + switch (state) { + case HWIndicatorStateNormal: { + self.stateLabel.text = @"Please pull down to dismiss"; + self.stateLabel.textColor = [UIColor whiteColor]; + } + break; + case HWIndicatorStatePullDown: { + self.stateLabel.text = @"Keep pull down to dismiss"; + self.stateLabel.textColor = [UIColor colorWithRed:1.000 green:0.200 blue:0.000 alpha:1.00]; + } + break; + } +} + +- (CGSize)indicatorSize { + return CGSizeMake(200, 18); +} + +- (void)setupSubviews { + self.stateLabel.frame = self.bounds; +} + +@end + +``` + +### 如何使用HWPanModalContentView + +你必须继承自 `HWPanModalContentView`. `HWPanModalContentView` 适配 `HWPanModalPresentable` 协议,就像你可用该协议来present一样。 + +```Objective-C +@interface HWSimplePanModalView : HWPanModalContentView + +@end + +@implementation HWSimplePanModalView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // add view and layout. + } + + return self; +} + +// present it. +HWSimplePanModalView *simplePanModalView = [HWSimplePanModalView new]; +[simplePanModalView presentInView:nil]; +``` + + +## 例子 + +1. 克隆项目 +2. 然后执行 `pod install` +3. 打开 HWPanModal.xcworkspace, 选择OC或者Swift项目运行 + +###### 我分别编写了纯`Objective-C` & `Swift`例子,基本涵盖了该framework的所有API使用。 + +## 联系我 + +Heath Wang +yishu.jay@gmail.com + +## WX + +

+ + + +

+ +## License + +HWPanModal is released under a MIT License. See LICENSE file for details. + + diff --git a/Pods/HWPanModal/Sources/Animator/HWPanModalAnimator.h b/Pods/HWPanModal/Sources/Animator/HWPanModalAnimator.h new file mode 100644 index 0000000..e80d3f5 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPanModalAnimator.h @@ -0,0 +1,27 @@ +// +// HWPanModalAnimator.h +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^AnimationBlockType)(void); +typedef void(^AnimationCompletionType)(BOOL completion); + +static NSTimeInterval kTransitionDuration = 0.5; + +@interface HWPanModalAnimator : NSObject + ++ (void)animate:(AnimationBlockType)animations config:(nullable id )config completion:(nullable AnimationCompletionType)completion; + ++ (void)dismissAnimate:(AnimationBlockType)animations config:(nullable id )config completion:(AnimationCompletionType)completion; + ++ (void)smoothAnimate:(AnimationBlockType)animations duration:(NSTimeInterval)duration completion:(nullable AnimationCompletionType)completion; +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Animator/HWPanModalAnimator.m b/Pods/HWPanModal/Sources/Animator/HWPanModalAnimator.m new file mode 100644 index 0000000..37dc498 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPanModalAnimator.m @@ -0,0 +1,40 @@ +// +// HWPanModalAnimator.m +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import "HWPanModalAnimator.h" + +@implementation HWPanModalAnimator + ++ (void)animate:(AnimationBlockType)animations config:(nullable id)config completion:(AnimationCompletionType)completion { + [HWPanModalAnimator animate:animations config:config startingFromPercent:1 isPresentation:YES completion:completion]; +} + ++ (void)dismissAnimate:(AnimationBlockType)animations config:(nullable id)config completion:(AnimationCompletionType)completion { + [HWPanModalAnimator animate:animations config:config startingFromPercent:1 isPresentation:NO completion:completion]; +} + ++ (void)animate:(AnimationBlockType)animations config:(nullable id )config startingFromPercent:(CGFloat)animationPercent isPresentation:(BOOL)flag completion:(AnimationCompletionType)completion { + + NSTimeInterval duration; + if (flag) { + duration = config ? [config transitionDuration] : kTransitionDuration; + } else { + duration = config ? [config dismissalDuration] : kTransitionDuration; + } + + duration = duration * MAX(animationPercent, 0); + CGFloat springDamping = config ? [config springDamping] : 1.0; + UIViewAnimationOptions options = config ? [config transitionAnimationOptions] : UIViewAnimationOptionPreferredFramesPerSecondDefault; + + [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:springDamping initialSpringVelocity:0 options:options animations:animations completion:completion]; +} + ++ (void)smoothAnimate:(AnimationBlockType)animations duration:(NSTimeInterval)duration completion:(nullable AnimationCompletionType)completion { + [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:animations completion:completion]; +} + +@end diff --git a/Pods/HWPanModal/Sources/Animator/HWPanModalInteractiveAnimator.h b/Pods/HWPanModal/Sources/Animator/HWPanModalInteractiveAnimator.h new file mode 100644 index 0000000..f31a1b0 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPanModalInteractiveAnimator.h @@ -0,0 +1,17 @@ +// +// HWPanModalInteractiveAnimator.h +// HWPanModal +// +// Created by heath wang on 2019/5/14. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanModalInteractiveAnimator : UIPercentDrivenInteractiveTransition + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Animator/HWPanModalInteractiveAnimator.m b/Pods/HWPanModal/Sources/Animator/HWPanModalInteractiveAnimator.m new file mode 100644 index 0000000..f5c4bf5 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPanModalInteractiveAnimator.m @@ -0,0 +1,16 @@ +// +// HWPanModalInteractiveAnimator.m +// HWPanModal +// +// Created by heath wang on 2019/5/14. +// + +#import "HWPanModalInteractiveAnimator.h" + +@implementation HWPanModalInteractiveAnimator + +- (CGFloat)completionSpeed { + return 0.618; +} + +@end diff --git a/Pods/HWPanModal/Sources/Animator/HWPanModalPresentationAnimator.h b/Pods/HWPanModal/Sources/Animator/HWPanModalPresentationAnimator.h new file mode 100644 index 0000000..d98398d --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPanModalPresentationAnimator.h @@ -0,0 +1,28 @@ +// +// HWPanModalPresentationAnimator.h +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import +#import +#import "HWPanModalPresentationDelegate.h" + +typedef NS_ENUM(NSInteger, TransitionStyle) { + TransitionStylePresentation, + TransitionStyleDismissal, +}; + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanModalPresentationAnimator : NSObject + +- (instancetype)initWithTransitionStyle:(TransitionStyle)transitionStyle interactiveMode:(PanModalInteractiveMode)mode; + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Animator/HWPanModalPresentationAnimator.m b/Pods/HWPanModal/Sources/Animator/HWPanModalPresentationAnimator.m new file mode 100644 index 0000000..522141b --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPanModalPresentationAnimator.m @@ -0,0 +1,314 @@ +// +// HWPanModalPresentationAnimator.m +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import "HWPanModalPresentationAnimator.h" +#import "HWPanModalAnimator.h" +#import "UIViewController+LayoutHelper.h" +#import "HWPanContainerView.h" +#import "UIView+HW_Frame.h" +#import "HWPageSheetPresentingAnimation.h" +#import "HWShoppingCartPresentingAnimation.h" + +@interface HWPresentingVCTransitionContext : NSObject + +@property (nonatomic, weak) UIViewController *fromVC; +@property (nonatomic, weak) UIViewController *toVC; +@property (nonatomic, assign) NSTimeInterval duration; +@property (nonatomic, strong) UIView *containerView; + +- (instancetype)initWithFromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC duration:(NSTimeInterval)duration containerView:(UIView *)containerView; + +@end + +@interface HWPanModalPresentationAnimator () + +@property (nonatomic, assign) TransitionStyle transitionStyle; + +@property (nullable, nonatomic, strong) UISelectionFeedbackGenerator *feedbackGenerator API_AVAILABLE(ios(10.0)); +@property (nonatomic, strong) HWPresentingVCTransitionContext *presentingVCTransitionContext; +@property (nonatomic, assign) PanModalInteractiveMode interactiveMode; + +@end + +@implementation HWPanModalPresentationAnimator + +- (instancetype)initWithTransitionStyle:(TransitionStyle)transitionStyle interactiveMode:(PanModalInteractiveMode)mode { + self = [super init]; + if (self) { + _transitionStyle = transitionStyle; + _interactiveMode = mode; + if (transitionStyle == TransitionStylePresentation) { + if (@available(iOS 10.0, *)) { + _feedbackGenerator = [UISelectionFeedbackGenerator new]; + [_feedbackGenerator prepare]; + } else { + // Fallback on earlier versions + } + } + } + + return self; +} + +/** + * 弹出controller动画 + */ +- (void)animatePresentation:(id)context { + + UIViewController *toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey]; + UIViewController *fromVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey]; + if (!toVC && !fromVC) + return; + + UIViewController *presentable = [self panModalViewController:context]; + + if ([presentable shouldEnableAppearanceTransition]) { + // If you are implementing a custom container controller, use this method to tell the child that its views are about to appear or disappear. + [fromVC beginAppearanceTransition:NO animated:YES]; + [self beginAppearanceTransitionForController:toVC isAppearing:YES animated:YES]; + } + + + CGFloat yPos = presentable.shortFormYPos; + if ([presentable originPresentationState] == PresentationStateLong) { + yPos = presentable.longFormYPos; + } else if ([presentable originPresentationState] == PresentationStateMedium) { + yPos = presentable.mediumFormYPos; + } + + UIView *panView = context.containerView.panContainerView ?: toVC.view; + panView.frame = [context finalFrameForViewController:toVC]; + panView.hw_top = context.containerView.frame.size.height; + + if ([presentable isHapticFeedbackEnabled]) { + if (@available(iOS 10.0, *)) { + [self.feedbackGenerator selectionChanged]; + } + } + + [HWPanModalAnimator animate:^{ + panView.hw_top = yPos; + } config:presentable completion:^(BOOL completion) { + + if ([presentable shouldEnableAppearanceTransition]) { + [fromVC endAppearanceTransition]; + [self endAppearanceTransitionForController:toVC]; + } + + if (@available(iOS 10.0, *)) { + self.feedbackGenerator = nil; + } + + [context completeTransition:completion]; + }]; + + self.presentingVCTransitionContext = [[HWPresentingVCTransitionContext alloc] initWithFromVC:fromVC toVC:toVC duration:[presentable transitionDuration] containerView:context.containerView]; + [self presentAnimationForPresentingVC:presentable]; +} + +/** + * 使弹出controller消失动画 + */ +- (void)animateDismissal:(id)context { + + UIViewController *fromVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey]; + UIViewController *toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey]; + if (!fromVC && !toVC) + return; + + UIViewController *presentable = [self panModalViewController:context]; + + + if ([presentable shouldEnableAppearanceTransition]) { + [self beginAppearanceTransitionForController:fromVC isAppearing:NO animated:YES]; + [toVC beginAppearanceTransition:YES animated:YES]; + } + + UIView *panView = context.containerView.panContainerView ?: fromVC.view; + self.presentingVCTransitionContext = [[HWPresentingVCTransitionContext alloc] initWithFromVC:fromVC toVC:toVC duration:[presentable transitionDuration] containerView:context.containerView]; + + // user toggle pan gesture to dismiss. + if ([context isInteractive]) { + [self interactionDismiss:context fromVC:fromVC toVC:toVC presentable:presentable panView:panView]; + } else { + [self springDismiss:context fromVC:fromVC toVC:toVC presentable:presentable panView:panView]; + } +} + +- (void)springDismiss:(id )context fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC presentable:(UIViewController *)presentable panView:(UIView *)panView { + CGFloat offsetY = 0; + HWPanModalShadow *shadowConfig = [presentable contentShadow]; + if (shadowConfig.shadowColor) { + // we should make the panView move further to hide the shadow effect. + offsetY = offsetY + shadowConfig.shadowRadius + shadowConfig.shadowOffset.height; + if ([presentable showDragIndicator]) { + offsetY += [presentable customIndicatorView] ? [presentable customIndicatorView].indicatorSize.height : 13; + } + } + + [HWPanModalAnimator dismissAnimate:^{ + [self dismissAnimationForPresentingVC:presentable]; + panView.hw_top = (context.containerView.frame.size.height + offsetY); + } config:presentable completion:^(BOOL completion) { + [fromVC.view removeFromSuperview]; + + if ([presentable shouldEnableAppearanceTransition]) { + [self endAppearanceTransitionForController:fromVC]; + [toVC endAppearanceTransition]; + } + + [context completeTransition:completion]; + }]; +} + +- (void)interactionDismiss:(id )context fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC presentable:(UIViewController *)presentable panView:(UIView *)panView { + [HWPanModalAnimator smoothAnimate:^{ + if (self.interactiveMode == PanModalInteractiveModeSideslip) { + panView.hw_left = panView.hw_width; + } + + [self dismissAnimationForPresentingVC:presentable]; + } duration:[presentable dismissalDuration] completion:^(BOOL completion) { + // 因为会有手势交互,所以需要判断transitions是否cancel + BOOL finished = ![context transitionWasCancelled]; + + if (finished) { + [fromVC.view removeFromSuperview]; + + if ([presentable shouldEnableAppearanceTransition]) { + [self endAppearanceTransitionForController:fromVC]; + [toVC endAppearanceTransition]; + } + + context.containerView.userInteractionEnabled = YES; + } + [context completeTransition:finished]; + }]; +} + +#pragma mark - presenting VC animation + +- (void)presentAnimationForPresentingVC:(UIViewController *)presentable { + id presentingAnimation = [self presentingVCAnimation:presentable]; + if (presentingAnimation) { + [presentingAnimation presentAnimateTransition:self.presentingVCTransitionContext]; + } +} + +- (void)dismissAnimationForPresentingVC:(UIViewController *)presentable { + id presentingAnimation = [self presentingVCAnimation:presentable]; + if (presentingAnimation) { + [presentingAnimation dismissAnimateTransition:self.presentingVCTransitionContext]; + } +} + +- (UIViewController *)panModalViewController:(id )context { + switch (self.transitionStyle) { + case TransitionStylePresentation: { + UIViewController *controller = [context viewControllerForKey:UITransitionContextToViewControllerKey]; + if ([controller conformsToProtocol:@protocol(HWPanModalPresentable)]) { + return (UIViewController *) controller; + } else { + return nil; + } + } + case TransitionStyleDismissal: { + UIViewController *controller = [context viewControllerForKey:UITransitionContextFromViewControllerKey]; + if ([controller conformsToProtocol:@protocol(HWPanModalPresentable)]) { + return (UIViewController *) controller; + } else { + return nil; + } + } + } +} + +#pragma mark - UIViewControllerAnimatedTransitioning + +- (void)animateTransition:(nonnull id)transitionContext { + switch (self.transitionStyle) { + case TransitionStylePresentation: { + [self animatePresentation:transitionContext]; + } + break; + case TransitionStyleDismissal: { + [self animateDismissal:transitionContext]; + } + default: + break; + } +} + +- (NSTimeInterval)transitionDuration:(nullable id)transitionContext { + if (transitionContext && [self panModalViewController:transitionContext]) { + UIViewController *controller = [self panModalViewController:transitionContext]; + return [controller transitionDuration]; + } + return kTransitionDuration; +} + +#pragma mark - presenting animated transition + +- (id)presentingVCAnimation:(UIViewController *)presentable { + switch ([presentable presentingVCAnimationStyle]) { + case PresentingViewControllerAnimationStylePageSheet: + return [HWPageSheetPresentingAnimation new]; + case PresentingViewControllerAnimationStyleShoppingCart: + return [HWShoppingCartPresentingAnimation new]; + case PresentingViewControllerAnimationStyleCustom: + return [presentable customPresentingVCAnimation]; + default: + return nil; + } +} + +#pragma mark - private method + +- (void)beginAppearanceTransitionForController:(UIViewController *)viewController isAppearing:(BOOL)isAppearing animated:(BOOL)animated { + // Fix `The unbalanced calls to begin/end appearance transitions` warning. + if (![viewController isKindOfClass:UINavigationController.class]) { + [viewController beginAppearanceTransition:isAppearing animated:animated]; + } +} + +- (void)endAppearanceTransitionForController:(UIViewController *)viewController { + if (![viewController isKindOfClass:UINavigationController.class]) { + [viewController endAppearanceTransition]; + } +} + +@end + +@implementation HWPresentingVCTransitionContext + +- (instancetype)initWithFromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC duration:(NSTimeInterval)duration containerView:(UIView *)containerView { + self = [super init]; + if (self) { + _fromVC = fromVC; + _toVC = toVC; + _duration = duration; + _containerView = containerView; + } + + return self; +} + + +- (__kindof UIViewController *)viewControllerForKey:(UITransitionContextViewControllerKey)key { + if ([key isEqualToString:UITransitionContextFromViewControllerKey]) { + return self.fromVC; + } else if ([key isEqualToString:UITransitionContextToViewControllerKey]) { + return self.toVC; + } + return nil; +} + +- (NSTimeInterval)transitionDuration { + return self.duration; +} + +@end diff --git a/Pods/HWPanModal/Sources/Animator/HWPresentingVCAnimatedTransitioning.h b/Pods/HWPanModal/Sources/Animator/HWPresentingVCAnimatedTransitioning.h new file mode 100644 index 0000000..e726688 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/HWPresentingVCAnimatedTransitioning.h @@ -0,0 +1,51 @@ +// +// HWCustomPresentingVCAnimatedTransitioning.h +// HWPanModal +// +// Created by heath wang on 2019/6/12. +// + +#ifndef HWCustomPresentingVCAnimatedTransitioning_h +#define HWCustomPresentingVCAnimatedTransitioning_h + +NS_SWIFT_NAME(PanModalPresentingViewControllerContextTransitioning) +@protocol HWPresentingViewControllerContextTransitioning + +/** + * Returns a view controller involved in the transition. + * @return The view controller object for the specified key or nil if the view controller could not be found. + */ +- (__kindof UIViewController * _Nullable )viewControllerForKey:(nonnull UITransitionContextViewControllerKey)key; + +/** + * The Animation duration gets from ViewController which conforms HWPanModalPresentable + * - (NSTimeInterval)transitionDuration; + */ +- (NSTimeInterval)transitionDuration; + +/** + * Transition container, from UIViewControllerContextTransitioning protocol + */ +@property(nonnull, nonatomic, readonly) UIView *containerView; + +@end + +NS_SWIFT_NAME(PanModalPresentingViewControllerAnimatedTransitioning) +@protocol HWPresentingViewControllerAnimatedTransitioning + +/** + * Write you custom animation when present. + */ +- (void)presentAnimateTransition:(nonnull id)context NS_SWIFT_NAME(presentTransition(context:)); +/** + * Write you custom animation when dismiss. + */ +- (void)dismissAnimateTransition:(nonnull id)context NS_SWIFT_NAME(dismissTransition(context:)); + +@end + + +#endif /* HWCustomPresentingVCAnimatedTransitioning_h */ + + + diff --git a/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.h b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.h new file mode 100644 index 0000000..da90548 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.h @@ -0,0 +1,17 @@ +// +// HWPageSheetPresentingAnimation.h +// HWPanModal-iOS10.0 +// +// Created by heath wang on 2019/9/5. +// + +#import +#import "HWPresentingVCAnimatedTransitioning.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPageSheetPresentingAnimation : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.m b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.m new file mode 100644 index 0000000..82bbd1e --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.m @@ -0,0 +1,29 @@ +// +// HWPageSheetPresentingAnimation.m +// HWPanModal-iOS10.0 +// +// Created by heath wang on 2019/9/5. +// + +#import "HWPageSheetPresentingAnimation.h" + +@implementation HWPageSheetPresentingAnimation + +- (void)presentAnimateTransition:(nonnull id )context { + NSTimeInterval duration = [context transitionDuration]; + UIViewController *fromVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey]; + [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.9 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height; + CGFloat scale = 1 - statusBarHeight * 2 / CGRectGetHeight(fromVC.view.bounds); + fromVC.view.transform = CGAffineTransformMakeScale(scale, scale); + } completion:^(BOOL finished) { + + }]; +} + +- (void)dismissAnimateTransition:(nonnull id )context { + UIViewController *toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey]; + toVC.view.transform = CGAffineTransformIdentity; +} + +@end diff --git a/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.h b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.h new file mode 100644 index 0000000..373a8a0 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.h @@ -0,0 +1,17 @@ +// +// HWShoppingCartPresentingAnimation.h +// HWPanModal-iOS10.0 +// +// Created by heath wang on 2019/9/5. +// + +#import +#import "HWPresentingVCAnimatedTransitioning.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface HWShoppingCartPresentingAnimation : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.m b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.m new file mode 100644 index 0000000..228d9b5 --- /dev/null +++ b/Pods/HWPanModal/Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.m @@ -0,0 +1,39 @@ +// +// HWShoppingCartPresentingAnimation.m +// HWPanModal-iOS10.0 +// +// Created by heath wang on 2019/9/5. +// + +#import "HWShoppingCartPresentingAnimation.h" + +@implementation HWShoppingCartPresentingAnimation + +- (void)presentAnimateTransition:(nonnull id )context { + + NSTimeInterval duration = [context transitionDuration]; + UIViewController *fromVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey]; + CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height; + CGFloat scale = 1 - statusBarHeight * 2 / CGRectGetHeight(fromVC.view.bounds); + [UIView animateWithDuration:duration * 0.4 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ + CATransform3D tran = CATransform3DIdentity; + tran.m34 = -1 / 1000.0f; + tran = CATransform3DRotate(tran, M_PI / 16, 1, 0, 0); + tran = CATransform3DTranslate(tran, 0, 0, -100); + fromVC.view.layer.transform = tran; + } completion:^(BOOL finished) { + + [UIView animateWithDuration:duration * 0.6 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ + fromVC.view.layer.transform = CATransform3DMakeScale(scale, scale, 1); + } completion:^(BOOL finished) { + + }]; + }]; +} + +- (void)dismissAnimateTransition:(nonnull id )context { + UIViewController *toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey]; + toVC.view.layer.transform = CATransform3DIdentity; +} + +@end diff --git a/Pods/HWPanModal/Sources/Category/UIScrollView+Helper.h b/Pods/HWPanModal/Sources/Category/UIScrollView+Helper.h new file mode 100644 index 0000000..73b8c8e --- /dev/null +++ b/Pods/HWPanModal/Sources/Category/UIScrollView+Helper.h @@ -0,0 +1,18 @@ +// +// UIScrollView+Helper.h +// Pods +// +// Created by heath wang on 2019/10/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIScrollView (Helper) + +@property (nonatomic, assign, readonly) BOOL isScrolling; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Category/UIScrollView+Helper.m b/Pods/HWPanModal/Sources/Category/UIScrollView+Helper.m new file mode 100644 index 0000000..fa9214c --- /dev/null +++ b/Pods/HWPanModal/Sources/Category/UIScrollView+Helper.m @@ -0,0 +1,16 @@ +// +// UIScrollView+Helper.m +// Pods +// +// Created by heath wang on 2019/10/15. +// + +#import "UIScrollView+Helper.h" + +@implementation UIScrollView (Helper) + +- (BOOL)isScrolling { + return (self.isDragging && !self.isDecelerating) || self.isTracking; +} + +@end diff --git a/Pods/HWPanModal/Sources/Category/UIView+HW_Frame.h b/Pods/HWPanModal/Sources/Category/UIView+HW_Frame.h new file mode 100644 index 0000000..9c81d2b --- /dev/null +++ b/Pods/HWPanModal/Sources/Category/UIView+HW_Frame.h @@ -0,0 +1,28 @@ +// +// UIView+HW_Frame.h +// HWPanModal +// +// Created by heath wang on 2019/5/20. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (HW_Frame) + +@property (nonatomic, assign) CGFloat hw_left; ///< Shortcut for frame.origin.x. +@property (nonatomic, assign) CGFloat hw_top; ///< Shortcut for frame.origin.y +@property (nonatomic, assign) CGFloat hw_right; ///< Shortcut for frame.origin.x + frame.size.width +@property (nonatomic, assign) CGFloat hw_bottom; ///< Shortcut for frame.origin.y + frame.size.height +@property (nonatomic, assign) CGFloat hw_width; ///< Shortcut for frame.size.width. +@property (nonatomic, assign) CGFloat hw_height; ///< Shortcut for frame.size.height. +@property (nonatomic, assign) CGFloat hw_centerX; ///< Shortcut for center.x +@property (nonatomic, assign) CGFloat hw_centerY; ///< Shortcut for center.y +@property (nonatomic, assign) CGPoint hw_origin; ///< Shortcut for frame.origin. +@property (nonatomic, assign) CGSize hw_size; ///< Shortcut for frame.size. + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Category/UIView+HW_Frame.m b/Pods/HWPanModal/Sources/Category/UIView+HW_Frame.m new file mode 100644 index 0000000..6cea736 --- /dev/null +++ b/Pods/HWPanModal/Sources/Category/UIView+HW_Frame.m @@ -0,0 +1,109 @@ +// +// UIView+HW_Frame.m +// HWPanModal +// +// Created by heath wang on 2019/5/20. +// + +#import "UIView+HW_Frame.h" + +@implementation UIView (HW_Frame) + +- (CGFloat)hw_left { + return self.frame.origin.x; +} + +- (void)setHw_left:(CGFloat)hwLeft { + CGRect frame = self.frame; + frame.origin.x = hwLeft; + self.frame = frame; +} + +- (CGFloat)hw_top { + return self.frame.origin.y; +} + +- (void)setHw_top:(CGFloat)hwTop { + CGRect frame = self.frame; + frame.origin.y = hwTop; + self.frame = frame; +} + +- (CGFloat)hw_right { + return self.frame.origin.x + self.frame.size.width; +} + +- (void)setHw_right:(CGFloat)hwRight { + CGRect frame = self.frame; + frame.origin.x = hwRight - self.frame.size.width; + self.frame = frame; +} + +- (CGFloat)hw_bottom { + return self.frame.origin.y + self.frame.size.height; +} + +- (void)setHw_bottom:(CGFloat)hwBottom { + CGRect frame = self.frame; + frame.origin.y = hwBottom - self.frame.size.height; + self.frame = frame; +} + +- (CGFloat)hw_width { + return self.frame.size.width; +} + +- (void)setHw_width:(CGFloat)hwWidth { + CGRect frame = self.frame; + frame.size.width = hwWidth; + self.frame = frame; +} + +- (CGFloat)hw_height { + return self.frame.size.height; +} + +- (void)setHw_height:(CGFloat)hwHeight { + CGRect frame = self.frame; + frame.size.height = hwHeight; + self.frame = frame; +} + +- (CGFloat)hw_centerX { + return self.center.x; +} + +- (void)setHw_centerX:(CGFloat)hwCenterX { + self.center = CGPointMake(hwCenterX, self.center.y); +} + +- (CGFloat)hw_centerY { + return self.center.y; +} + +- (void)setHw_centerY:(CGFloat)hwCenterY { + self.center = CGPointMake(self.center.x, hwCenterY); +} + +- (CGPoint)hw_origin { + return self.frame.origin; +} + +- (void)setHw_origin:(CGPoint)hwOrigin { + CGRect frame = self.frame; + frame.origin = hwOrigin; + self.frame = frame; +} + +- (CGSize)hw_size { + return self.frame.size; +} + +- (void)setHw_size:(CGSize)hwSize { + CGRect frame = self.frame; + frame.size = hwSize; + self.frame = frame; +} + + +@end diff --git a/Pods/HWPanModal/Sources/Controller/HWPanModalPresentationController.h b/Pods/HWPanModal/Sources/Controller/HWPanModalPresentationController.h new file mode 100644 index 0000000..d25a430 --- /dev/null +++ b/Pods/HWPanModal/Sources/Controller/HWPanModalPresentationController.h @@ -0,0 +1,32 @@ +// +// HWPanModalPresentationController.h +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import +#import +@class HWDimmedView; + +NS_ASSUME_NONNULL_BEGIN + + +@interface HWPanModalPresentationController : UIPresentationController + +@property (nonatomic, readonly) HWDimmedView *backgroundView; +@property (nonatomic, readonly) PresentationState currentPresentationState; + +- (void)setNeedsLayoutUpdate; + +- (void)updateUserHitBehavior; + +- (void)transitionToState:(PresentationState)state animated:(BOOL)animated; + +- (void)setScrollableContentOffset:(CGPoint)offset animated:(BOOL)animated; + +- (void)dismissAnimated:(BOOL)animated completion:(void (^)(void))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Controller/HWPanModalPresentationController.m b/Pods/HWPanModal/Sources/Controller/HWPanModalPresentationController.m new file mode 100644 index 0000000..338cfb4 --- /dev/null +++ b/Pods/HWPanModal/Sources/Controller/HWPanModalPresentationController.m @@ -0,0 +1,599 @@ +// +// HWPanModalPresentationController.m +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import "HWPanModalPresentationController.h" +#import "HWDimmedView.h" +#import "HWPanContainerView.h" +#import "UIViewController+LayoutHelper.h" +#import "HWPanModalAnimator.h" +#import "HWPanModalInteractiveAnimator.h" +#import "HWPanModalPresentationDelegate.h" +#import "UIViewController+PanModalPresenter.h" +#import "HWPanIndicatorView.h" +#import "UIView+HW_Frame.h" +#import "HWPanModalPresentableHandler.h" + +@interface HWPanModalPresentationController () + +// 判断弹出的view是否在做动画 +@property (nonatomic, assign) BOOL isPresentedViewAnimating; +@property (nonatomic, assign) PresentationState currentPresentationState; + +@property (nonatomic, strong) id presentable; + +// view +@property (nonatomic, strong) HWDimmedView *backgroundView; +@property (nonatomic, strong) HWPanContainerView *panContainerView; +@property (nonatomic, strong) UIView *dragIndicatorView; + +@property (nonatomic, strong) HWPanModalPresentableHandler *handler; + +@end + +@implementation HWPanModalPresentationController + +- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(nullable UIViewController *)presentingViewController { + self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController]; + if (self) { + _handler = [[HWPanModalPresentableHandler alloc] initWithPresentable:[self presentable]]; + _handler.delegate = self; + _handler.dataSource = self; + } + + return self; +} + +#pragma mark - overridden + +- (UIView *)presentedView { + return self.panContainerView; +} + +- (void)containerViewWillLayoutSubviews { + [super containerViewWillLayoutSubviews]; + [self configureViewLayout]; +} + +#pragma mark - Tracking the Transition Start and End + +- (void)presentationTransitionWillBegin { + [[self presentable] panModalTransitionWillBegin]; + + if (!self.containerView) + return; + + [self layoutBackgroundView:self.containerView]; + + if ([[self presentable] originPresentationState] == PresentationStateLong) { + self.currentPresentationState = PresentationStateLong; + } else if ([[self presentable] originPresentationState] == PresentationStateMedium) { + self.currentPresentationState = PresentationStateMedium; + } + + [self layoutPresentedView:self.containerView]; + [self.handler configureScrollViewInsets]; + + if (!self.presentedViewController.transitionCoordinator) { + self.backgroundView.dimState = DimStateMax; + return; + } + + __weak typeof(self) wkSelf = self; + __block BOOL isAnimated = NO; + [self.presentedViewController.transitionCoordinator animateAlongsideTransition:^(id context) { + wkSelf.backgroundView.dimState = DimStateMax; + [wkSelf.presentedViewController setNeedsStatusBarAppearanceUpdate]; + isAnimated = YES; + } completion:^(id _Nonnull context) { + if (!isAnimated) { + /// In some cases, for example, present a `hw` when a navigation controller is pushing a new vc, `animateAlongsideTransition` will not call. + /// If not called, call it here. + wkSelf.backgroundView.dimState = DimStateMax; + [wkSelf.presentedViewController setNeedsStatusBarAppearanceUpdate]; + } + if ([[wkSelf presentable] allowsTouchEventsPassingThroughTransitionView]) { + // hack TransitionView + [wkSelf.containerView setValue:@(YES) forKey:@"ignoreDirectTouchEvents"]; + } + }]; + +} + +- (void)presentationTransitionDidEnd:(BOOL)completed { + [[self presentable] panModalTransitionDidFinish]; + if (completed) + return; + + [self.backgroundView removeFromSuperview]; + [self.presentedView endEditing:YES]; +} + +- (void)dismissalTransitionWillBegin { + id transitionCoordinator = self.presentedViewController.transitionCoordinator; + if (!transitionCoordinator) { + self.backgroundView.dimState = DimStateOff; + return; + } + + __weak typeof(self) wkSelf = self; + [transitionCoordinator animateAlongsideTransition:^(id context) { + wkSelf.dragIndicatorView.alpha = 0; + wkSelf.backgroundView.dimState = DimStateOff; + [wkSelf.presentedViewController setNeedsStatusBarAppearanceUpdate]; + } completion:^(id context) { + + }]; +} + +- (void)dismissalTransitionDidEnd:(BOOL)completed { + if (completed) { + // break the delegate + self.delegate = nil; + } +} + +#pragma mark - UIContentContainer protocol + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id )coordinator { + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + + [coordinator animateAlongsideTransition:^(id context) { + if (self && [self presentable]) { + [self adjustPresentedViewFrame]; + + if ([self.presentable shouldRoundTopCorners]) { + [self addRoundedCornersToView:self.panContainerView.contentView]; + } + [self updateDragIndicatorView]; + } + } completion:^(id context) { + [self transitionToState:self.currentPresentationState animated:NO]; + }]; +} + +#pragma mark - public method + +- (void)setNeedsLayoutUpdate { + [self configureViewLayout]; + [self adjustPresentedViewFrame]; + + [self updateBackgroundColor]; + [self updateContainerViewShadow]; + [self updateDragIndicatorView]; + [self updateRoundedCorners]; + + [self.handler observeScrollable]; + [self.handler configureScrollViewInsets]; + [self checkEdgeInteractive]; +} + +- (void)transitionToState:(PresentationState)state animated:(BOOL)animated { + + if (![self.presentable shouldTransitionToState:state]) + return; + + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + [self.presentable willTransitionToState:state]; + + switch (state) { + case PresentationStateLong: { + [self snapToYPos:self.handler.longFormYPosition animated:animated]; + } + break; + case PresentationStateMedium: { + [self snapToYPos:self.handler.mediumFormYPosition animated:animated]; + } + break; + case PresentationStateShort: { + [self snapToYPos:self.handler.shortFormYPosition animated:animated]; + } + break; + } + self.currentPresentationState = state; + [[self presentable] didChangeTransitionToState:state]; +} + +- (void)setScrollableContentOffset:(CGPoint)offset animated:(BOOL)animated { + [self.handler setScrollableContentOffset:offset animated:animated]; +} + +- (void)updateUserHitBehavior { + [self checkVCContainerEventPass]; + [self checkBackgroundViewEventPass]; +} + +#pragma mark - layout + +- (void)adjustPresentedViewFrame { + + if (!self.containerView) + return; + + CGRect frame = self.containerView.frame; + CGSize size = CGSizeMake(CGRectGetWidth(frame), CGRectGetHeight(frame) - self.handler.anchoredYPosition); + + self.presentedView.hw_size = frame.size; + self.panContainerView.contentView.frame = CGRectMake(0, 0, size.width, size.height); + self.presentedViewController.view.frame = self.panContainerView.contentView.bounds; + [self.presentedViewController.view setNeedsLayout]; + [self.presentedViewController.view layoutIfNeeded]; +} + +/** + * add backGroundView并设置约束 + */ +- (void)layoutBackgroundView:(UIView *)containerView { + [containerView addSubview:self.backgroundView]; + [self updateBackgroundColor]; + self.backgroundView.translatesAutoresizingMaskIntoConstraints = NO; + + NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[backgroundView]|" options:0 metrics:nil views:@{@"backgroundView": self.backgroundView}]; + NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[backgroundView]|" options:0 metrics:nil views:@{@"backgroundView": self.backgroundView}]; + [NSLayoutConstraint activateConstraints:hCons]; + [NSLayoutConstraint activateConstraints:vCons]; +} + +- (void)updateBackgroundColor { + self.backgroundView.blurTintColor = [self.presentable backgroundConfig].blurTintColor; +} + +- (void)layoutPresentedView:(UIView *)containerView { + if (!self.presentable) + return; + + self.handler.presentedView = self.presentedView; + + [containerView addSubview:self.presentedView]; + [containerView addGestureRecognizer:self.handler.panGestureRecognizer]; + + if ([self.presentable allowScreenEdgeInteractive]) { + [containerView addGestureRecognizer:self.handler.screenEdgeGestureRecognizer]; + [self.handler.screenEdgeGestureRecognizer addTarget:self action:@selector(screenEdgeInteractiveAction:)]; + } + + [self setNeedsLayoutUpdate]; + [self adjustPanContainerBackgroundColor]; + + [[self presentable] presentedViewDidMoveToSuperView]; +} + +- (void)adjustPanContainerBackgroundColor { + self.panContainerView.contentView.backgroundColor = self.presentedViewController.view.backgroundColor ? : [self.presentable panScrollable].backgroundColor; +} + +- (void)updateDragIndicatorView { + if ([self.presentable showDragIndicator]) { + [self addDragIndicatorViewToView:self.panContainerView]; + } else { + self.dragIndicatorView.hidden = YES; + } +} + +- (void)addDragIndicatorViewToView:(UIView *)view { + // if has been add, won't update it. + self.dragIndicatorView.hidden = NO; + + CGSize indicatorSize = [self.dragIndicatorView indicatorSize]; + + if (self.dragIndicatorView.superview == view) { + self.dragIndicatorView.frame = CGRectMake((view.hw_width - indicatorSize.width) / 2, -kIndicatorYOffset - indicatorSize.height, indicatorSize.width, indicatorSize.height); + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + return; + } + + self.handler.dragIndicatorView = self.dragIndicatorView; + [view addSubview:self.dragIndicatorView]; + + self.dragIndicatorView.frame = CGRectMake((view.hw_width - indicatorSize.width) / 2, -kIndicatorYOffset - indicatorSize.height, indicatorSize.width, indicatorSize.height); + [self.dragIndicatorView setupSubviews]; + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; +} + +- (void)updateRoundedCorners { + if ([self.presentable shouldRoundTopCorners]) { + [self addRoundedCornersToView:self.panContainerView.contentView]; + } else { + [self resetRoundedCornersToView:self.panContainerView.contentView]; + } +} + +- (void)addRoundedCornersToView:(UIView *)view { + CGFloat radius = [self.presentable cornerRadius]; + + UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopRight | UIRectCornerTopLeft cornerRadii:CGSizeMake(radius, radius)]; + + CAShapeLayer *mask = [CAShapeLayer new]; + mask.path = bezierPath.CGPath; + view.layer.mask = mask; + + // 提高性能 + view.layer.shouldRasterize = YES; + view.layer.rasterizationScale = [UIScreen mainScreen].scale; +} + +- (void)resetRoundedCornersToView:(UIView *)view { + view.layer.mask = nil; + view.layer.shouldRasterize = NO; +} + +- (void)updateContainerViewShadow { + HWPanModalShadow *shadow = [[self presentable] contentShadow]; + if (shadow.shadowColor) { + [self.panContainerView updateShadow:shadow.shadowColor shadowRadius:shadow.shadowRadius shadowOffset:shadow.shadowOffset shadowOpacity:shadow.shadowOpacity]; + } else { + [self.panContainerView clearShadow]; + } +} + + +/** + * Calculates & stores the layout anchor points & options + */ +- (void)configureViewLayout { + + [self.handler configureViewLayout]; + self.containerView.userInteractionEnabled = [[self presentable] isUserInteractionEnabled]; +} + +#pragma mark - event passing through + +- (void)checkVCContainerEventPass { + BOOL eventPassValue = [[self presentable] allowsTouchEventsPassingThroughTransitionView]; + // hack TransitionView + [self.containerView setValue:@(eventPassValue) forKey:@"ignoreDirectTouchEvents"]; +} + +- (void)checkBackgroundViewEventPass { + if ([[self presentable] allowsTouchEventsPassingThroughTransitionView]) { + self.backgroundView.userInteractionEnabled = NO; + self.backgroundView.tapBlock = nil; + } else { + self.backgroundView.userInteractionEnabled = YES; + __weak typeof(self) wkSelf = self; + self.backgroundView.tapBlock = ^(UITapGestureRecognizer *recognizer) { + if ([[wkSelf presentable] allowsTapBackgroundToDismiss]) { + [wkSelf dismiss:NO mode:PanModalInteractiveModeNone]; + } + }; + } +} + +#pragma mark - y position update + +- (void)snapToYPos:(CGFloat)yPos animated:(BOOL)animated { + + if (animated) { + [HWPanModalAnimator animate:^{ + self.isPresentedViewAnimating = YES; + [self adjustToYPos:yPos]; + } config:self.presentable completion:^(BOOL completion) { + self.isPresentedViewAnimating = NO; + }]; + } else { + [self adjustToYPos:yPos]; + } +} + +- (void)adjustToYPos:(CGFloat)yPos { + self.presentedView.hw_top = MAX(yPos, self.handler.anchoredYPosition); + + // change dim background starting from shortFormYPosition. + if (self.presentedView.frame.origin.y >= self.handler.shortFormYPosition) { + + CGFloat yDistanceFromShortForm = self.presentedView.frame.origin.y - self.handler.shortFormYPosition; + CGFloat bottomHeight = self.containerView.hw_height - self.handler.shortFormYPosition; + CGFloat percent = yDistanceFromShortForm / bottomHeight; + self.backgroundView.dimState = DimStatePercent; + self.backgroundView.percent = 1 - percent; + + [self.presentable panModalGestureRecognizer:self.handler.panGestureRecognizer dismissPercent:MIN(percent, 1)]; + if (self.presentedViewController.isBeingDismissed) { + [[self interactiveAnimator] updateInteractiveTransition:MIN(percent, 1)]; + } + } else { + self.backgroundView.dimState = DimStateMax; + } +} + +#pragma mark - HWPanModalPresentableHandlerDelegate + +- (void)adjustPresentableYPos:(CGFloat)yPos { + [self adjustToYPos:yPos]; +} + +- (void)dismiss:(BOOL)isInteractive mode:(PanModalInteractiveMode)mode { + [self dismiss:isInteractive mode:mode animated:YES completion:nil]; +} + +- (void)dismiss:(BOOL)isInteractive mode:(PanModalInteractiveMode)mode animated:(BOOL)animated completion:(void (^)(void))completion { + self.presentedViewController.hw_panModalPresentationDelegate.interactive = isInteractive; + self.presentedViewController.hw_panModalPresentationDelegate.interactiveMode = mode; + [self.presentable panModalWillDismiss]; + [self.presentedViewController dismissViewControllerAnimated:animated completion:^{ + if (completion) completion(); + [self.presentable panModalDidDismissed]; + }]; +} + +- (void)dismissAnimated:(BOOL)animated completion:(nonnull void (^)(void))completion { + [self dismiss:NO mode:PanModalInteractiveModeNone animated:animated completion:completion]; +} + +- (void)presentableTransitionToState:(PresentationState)state { + [self transitionToState:state animated:YES]; +} + +- (PresentationState)getCurrentPresentationState { + return self.currentPresentationState; +} + +#pragma mark - interactive handle + +- (void)finishInteractiveTransition { + if (self.presentedViewController.isBeingDismissed) { + // make the containerView can not response event action. + self.containerView.userInteractionEnabled = NO; + [[self interactiveAnimator] finishInteractiveTransition]; + + if (self.presentedViewController.hw_panModalPresentationDelegate.interactiveMode != PanModalInteractiveModeDragDown) + return; + + if ([[self presentable] presentingVCAnimationStyle] > PresentingViewControllerAnimationStyleNone) { + [HWPanModalAnimator animate:^{ + [self presentedView].hw_top = self.containerView.frame.size.height; + self.dragIndicatorView.alpha = 0; + self.backgroundView.dimState = DimStateOff; + } config:[self presentable] completion:^(BOOL completion) { + + }]; + } + } +} + +- (void)cancelInteractiveTransition { + if (self.presentedViewController.isBeingDismissed) { + [[self interactiveAnimator] cancelInteractiveTransition]; + self.presentedViewController.hw_panModalPresentationDelegate.interactiveMode = PanModalInteractiveModeNone; + self.presentedViewController.hw_panModalPresentationDelegate.interactive = NO; + } +} + +#pragma mark - HWPanModalPresentableHandlerDataSource + +- (CGSize)containerSize { + return self.containerView.bounds.size; +} + +- (BOOL)isBeingDismissed { + return self.presentedViewController.isBeingDismissed; +} + +- (BOOL)isBeingPresented { + return self.presentedViewController.isBeingPresented; +} + +- (BOOL)isPresentedViewAnchored { + + if (![[self presentable] shouldRespondToPanModalGestureRecognizer:self.handler.panGestureRecognizer]) { + return YES; + } + + if (!self.isPresentedViewAnimating && self.handler.extendsPanScrolling && (CGRectGetMinY(self.presentedView.frame) <= self.handler.anchoredYPosition || HW_TWO_FLOAT_IS_EQUAL(CGRectGetMinY(self.presentedView.frame), self.handler.anchoredYPosition))) { + return YES; + } + return NO; +} + +- (BOOL)isPresentedControllerInteractive { + return self.presentedViewController.hw_panModalPresentationDelegate.interactive; +} + +- (BOOL)isFormPositionAnimating { + return self.isPresentedViewAnimating; +} + +#pragma mark - Screen Gesture enevt + +- (void)screenEdgeInteractiveAction:(UIPanGestureRecognizer *)recognizer { + CGPoint translation = [recognizer translationInView:recognizer.view]; + CGFloat percent = translation.x / CGRectGetWidth(recognizer.view.bounds); + CGPoint velocity = [recognizer velocityInView:recognizer.view]; + + switch (recognizer.state) { + case UIGestureRecognizerStateBegan: { + [self dismiss:YES mode:PanModalInteractiveModeSideslip]; + } + break; + case UIGestureRecognizerStateCancelled: + case UIGestureRecognizerStateEnded: { + if (percent > 0.5 || velocity.x >= [[self presentable] minHorizontalVelocityToTriggerScreenEdgeDismiss]) { + [self finishInteractiveTransition]; + } else { + [self cancelInteractiveTransition]; + } + + } + break; + case UIGestureRecognizerStateChanged: { + + [[self interactiveAnimator] updateInteractiveTransition:percent]; + } + break; + default: + break; + } +} + +- (void)checkEdgeInteractive { + //TODO: changed the user interactive, if someone else has different requirements, change it. + self.handler.screenEdgeGestureRecognizer.enabled = [[self presentable] allowScreenEdgeInteractive]; +} + +#pragma mark - Getter + +- (id )presentable { + if ([self.presentedViewController conformsToProtocol:@protocol(HWPanModalPresentable)]) { + return (id ) self.presentedViewController; + } + return nil; +} + +- (HWPanModalInteractiveAnimator *)interactiveAnimator { + HWPanModalPresentationDelegate *presentationDelegate = self.presentedViewController.hw_panModalPresentationDelegate; + return presentationDelegate.interactiveDismissalAnimator; +} + +- (HWDimmedView *)backgroundView { + if (!_backgroundView) { + if (self.presentable) { + _backgroundView = [[HWDimmedView alloc] initWithBackgroundConfig:[self.presentable backgroundConfig]]; + } else { + _backgroundView = [[HWDimmedView alloc] init]; + } + + if ([[self presentable] allowsTouchEventsPassingThroughTransitionView]) { + _backgroundView.userInteractionEnabled = NO; + } else { + __weak typeof(self) wkSelf = self; + _backgroundView.tapBlock = ^(UITapGestureRecognizer *recognizer) { + if ([[wkSelf presentable] allowsTapBackgroundToDismiss]) { + [wkSelf dismiss:NO mode:PanModalInteractiveModeNone]; + } + }; + } + + } + + return _backgroundView; +} + +- (HWPanContainerView *)panContainerView { + if (!_panContainerView) { + _panContainerView = [[HWPanContainerView alloc] initWithPresentedView:self.presentedViewController.view frame:self.containerView.frame]; + } + + return _panContainerView; +} + +- (UIView *)dragIndicatorView { + + if (!_dragIndicatorView) { + if ([self presentable] && + [[self presentable] respondsToSelector:@selector(customIndicatorView)] && + [[self presentable] customIndicatorView] != nil) { + _dragIndicatorView = [[self presentable] customIndicatorView]; + // set the indicator size first in case `setupSubviews` can Not get the right size. + _dragIndicatorView.hw_size = [[[self presentable] customIndicatorView] indicatorSize]; + } else { + _dragIndicatorView = [HWPanIndicatorView new]; + } + } + + return _dragIndicatorView; +} + +@end diff --git a/Pods/HWPanModal/Sources/Delegate/HWPanModalPresentationDelegate.h b/Pods/HWPanModal/Sources/Delegate/HWPanModalPresentationDelegate.h new file mode 100644 index 0000000..ea12ce9 --- /dev/null +++ b/Pods/HWPanModal/Sources/Delegate/HWPanModalPresentationDelegate.h @@ -0,0 +1,29 @@ +// +// HWPanModalPresentationDelegate.h +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import +#import + +@class HWPanModalInteractiveAnimator; + +typedef NS_ENUM(NSInteger, PanModalInteractiveMode) { + PanModalInteractiveModeNone, + PanModalInteractiveModeSideslip, // 侧滑返回 + PanModalInteractiveModeDragDown, // 向下拖拽返回 +}; + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanModalPresentationDelegate : NSObject + +@property (nonatomic, assign) BOOL interactive; +@property (nonatomic, assign) PanModalInteractiveMode interactiveMode; +@property (nonnull, nonatomic, strong, readonly) HWPanModalInteractiveAnimator *interactiveDismissalAnimator; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Delegate/HWPanModalPresentationDelegate.m b/Pods/HWPanModal/Sources/Delegate/HWPanModalPresentationDelegate.m new file mode 100644 index 0000000..d2f5037 --- /dev/null +++ b/Pods/HWPanModal/Sources/Delegate/HWPanModalPresentationDelegate.m @@ -0,0 +1,66 @@ +// +// HWPanModalPresentationDelegate.m +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import "HWPanModalPresentationDelegate.h" +#import "HWPanModalPresentationAnimator.h" +#import "HWPanModalPresentationController.h" +#import "HWPanModalInteractiveAnimator.h" + +@interface HWPanModalPresentationDelegate () + +@property (nonatomic, strong) HWPanModalInteractiveAnimator *interactiveDismissalAnimator; + +@end + +@implementation HWPanModalPresentationDelegate + +- (nullable id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { + return [[HWPanModalPresentationAnimator alloc] initWithTransitionStyle:TransitionStylePresentation interactiveMode:PanModalInteractiveModeNone]; +} + +- (nullable id )animationControllerForDismissedController:(UIViewController *)dismissed { + return [[HWPanModalPresentationAnimator alloc] initWithTransitionStyle:TransitionStyleDismissal interactiveMode:self.interactiveMode]; +} + +- (nullable id )interactionControllerForDismissal:(id )animator { + if (self.interactive) { + return self.interactiveDismissalAnimator; + } + + return nil; +} + +- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(nullable UIViewController *)presenting sourceViewController:(UIViewController *)source { + UIPresentationController *controller = [[HWPanModalPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting]; + controller.delegate = self; + return controller; +} + +#pragma mark - UIAdaptivePresentationControllerDelegate + +- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { + return UIModalPresentationNone; +} + +#pragma mark - Getter + +- (HWPanModalInteractiveAnimator *)interactiveDismissalAnimator { + if (!_interactiveDismissalAnimator) { + _interactiveDismissalAnimator = [[HWPanModalInteractiveAnimator alloc] init]; + } + return _interactiveDismissalAnimator; +} + +#ifdef DEBUG + +- (void)dealloc { + NSLog(@"%s", __PRETTY_FUNCTION__); +} + +#endif + +@end diff --git a/Pods/HWPanModal/Sources/HWPanModal.h b/Pods/HWPanModal/Sources/HWPanModal.h new file mode 100644 index 0000000..c02c81d --- /dev/null +++ b/Pods/HWPanModal/Sources/HWPanModal.h @@ -0,0 +1,36 @@ +// +// HWPanModal.h +// Pods +// +// Created by heath wang on 2019/4/30. +// +#import + +//! Project version number for HWPanModal. +FOUNDATION_EXPORT double HWPanModalVersionNumber; + +//! Project version string for JYHitchModule. +FOUNDATION_EXPORT const unsigned char HWPanModalVersionString[]; + +// protocol +#import +#import +#import + +#import + +// category +#import +#import +#import + +// custom animation +#import + +// view +#import +#import +#import + +// panModal view +#import diff --git a/Pods/HWPanModal/Sources/KVO/KeyValueObserver.h b/Pods/HWPanModal/Sources/KVO/KeyValueObserver.h new file mode 100644 index 0000000..d2280ca --- /dev/null +++ b/Pods/HWPanModal/Sources/KVO/KeyValueObserver.h @@ -0,0 +1,52 @@ +// +// KeyValueObserver.h +// Lab Color Space Explorer +// +// Created by Daniel Eggert on 01/12/2013. +// Copyright (c) 2013 objc.io. All rights reserved. +// + +#import + + + +@interface KeyValueObserver : NSObject + +@property (nonatomic, weak) id target; +@property (nonatomic) SEL selector; + +/// Create a Key-Value Observing helper object. +/// +/// As long as the returned token object is retained, the KVO notifications of the @c object +/// and @c keyPath will cause the given @c selector to be called on @c target. +/// @a object and @a target are weak references. +/// Once the token object gets dealloc'ed, the observer gets removed. +/// +/// The @c selector should conform to +/// @code +/// - (void)nameDidChange:(NSDictionary *)change; +/// @endcode +/// The passed in dictionary is the KVO change dictionary (c.f. @c NSKeyValueChangeKindKey, @c NSKeyValueChangeNewKey etc.) +/// +/// @returns the opaque token object to be stored in a property +/// +/// Example: +/// +/// @code +/// self.nameObserveToken = [KeyValueObserver observeObject:user +/// keyPath:@"name" +/// target:self +/// selector:@selector(nameDidChange:)]; +/// @endcode ++ (NSObject *)observeObject:(id)object keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector __attribute__((warn_unused_result)); + +/// Create a key-value-observer with the given KVO options ++ (NSObject *)observeObject:(id)object keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector options:(NSKeyValueObservingOptions)options __attribute__((warn_unused_result)); + +/** + * When you call this method, observer will not work. + * Please call observer method again. + */ +- (void)unObserver; + +@end diff --git a/Pods/HWPanModal/Sources/KVO/KeyValueObserver.m b/Pods/HWPanModal/Sources/KVO/KeyValueObserver.m new file mode 100644 index 0000000..7d2d8c5 --- /dev/null +++ b/Pods/HWPanModal/Sources/KVO/KeyValueObserver.m @@ -0,0 +1,85 @@ +// +// KeyValueObserver.m +// Lab Color Space Explorer +// +// Created by Daniel Eggert on 01/12/2013. +// Copyright (c) 2013 objc.io. All rights reserved. +// + +#import "KeyValueObserver.h" + +// +// Created by chris on 7/24/13. +// + +#import "KeyValueObserver.h" + +@interface KeyValueObserver () +@property (nonatomic, weak) id observedObject; +@property (nonatomic, copy) NSString* keyPath; +@property (nonatomic, assign) BOOL shouldObserver; +@end + +@implementation KeyValueObserver + +- (id)initWithObject:(id)object keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector options:(NSKeyValueObservingOptions)options; +{ + if (object == nil) { + return nil; + } + NSParameterAssert(target != nil); + NSParameterAssert([target respondsToSelector:selector]); + self = [super init]; + if (self) { + _shouldObserver = YES; + self.target = target; + self.selector = selector; + self.observedObject = object; + self.keyPath = keyPath; + [object addObserver:self forKeyPath:keyPath options:options context:(__bridge void *)(self)]; + } + return self; +} + ++ (NSObject *)observeObject:(id)object keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector __attribute__((warn_unused_result)); +{ + return [self observeObject:object keyPath:keyPath target:target selector:selector options:0]; +} + ++ (NSObject *)observeObject:(id)object keyPath:(NSString*)keyPath target:(id)target selector:(SEL)selector options:(NSKeyValueObservingOptions)options __attribute__((warn_unused_result)); +{ + return [[self alloc] initWithObject:object keyPath:keyPath target:target selector:selector options:options]; +} + +- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context +{ + if (context == (__bridge void *)(self)) { + [self didChange:change]; + } +} + +- (void)didChange:(NSDictionary *)change { + + if (!self.shouldObserver) { + return; + } + + id strongTarget = self.target; + + if ([strongTarget respondsToSelector:self.selector]) { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [strongTarget performSelector:self.selector withObject:change]; + #pragma clang diagnostic pop + } +} + +- (void)dealloc { + [self.observedObject removeObserver:self forKeyPath:self.keyPath]; +} + +- (void)unObserver { + self.shouldObserver = NO; +} + +@end diff --git a/Pods/HWPanModal/Sources/Mediator/HWPanModalPresentableHandler.h b/Pods/HWPanModal/Sources/Mediator/HWPanModalPresentableHandler.h new file mode 100644 index 0000000..a06d062 --- /dev/null +++ b/Pods/HWPanModal/Sources/Mediator/HWPanModalPresentableHandler.h @@ -0,0 +1,102 @@ +// +// HWPanModalPresentableHandler.h +// HWPanModal +// +// Created by heath wang on 2019/10/15. +// Copyright © 2019 Heath Wang. All rights reserved. +// + +#import +#import +#import +#import "HWPanModalPresentationDelegate.h" + +typedef NS_ENUM(NSUInteger, HWPanModalPresentableHandlerMode) { + HWPanModalPresentableHandlerModeViewController, // used for UIViewController + HWPanModalPresentableHandlerModeView, // used for view +}; + +NS_ASSUME_NONNULL_BEGIN + +@protocol HWPanModalPresentableHandlerDelegate + +/** + * tell the delegate the presentable is about to update origin y + */ +- (void)adjustPresentableYPos:(CGFloat)yPos; + +/** + * tell the delegate presentable is about to change the form state + * @param state short,medium, long + */ +- (void)presentableTransitionToState:(PresentationState)state; + + +/** +* get current CurrentPresentationState of the delegate +*/ +- (PresentationState)getCurrentPresentationState; + +/** + * dismiss Controller/UIView + * @param isInteractive only for UIViewController, pop view will ignore it. + * @param mode only for UIViewController, pop view will ignore it. + */ +- (void)dismiss:(BOOL)isInteractive mode:(PanModalInteractiveMode)mode; + +@optional +- (void)cancelInteractiveTransition; +- (void)finishInteractiveTransition; + +@end + +@protocol HWPanModalPresentableHandlerDataSource + +- (CGSize)containerSize; +- (BOOL)isBeingDismissed; +- (BOOL)isBeingPresented; +- (BOOL)isFormPositionAnimating; + +@optional +- (BOOL)isPresentedViewAnchored; +- (BOOL)isPresentedControllerInteractive; + +@end + +@interface HWPanModalPresentableHandler : NSObject + +@property (nonatomic, assign, readonly) CGFloat shortFormYPosition; +@property (nonatomic, assign, readonly) CGFloat mediumFormYPosition; +@property (nonatomic, assign, readonly) CGFloat longFormYPosition; +@property (nonatomic, assign, readonly) BOOL extendsPanScrolling; +@property (nonatomic, assign, readonly) BOOL anchorModalToLongForm; +@property (nonatomic, assign, readonly) CGFloat anchoredYPosition; + +@property (nonatomic, strong, readonly) UIPanGestureRecognizer *panGestureRecognizer; +// make controller or view to deal with the gesture action +@property (nonatomic, strong, readonly) UIPanGestureRecognizer *screenEdgeGestureRecognizer; + +@property (nonatomic, assign) HWPanModalPresentableHandlerMode mode; +@property (nonatomic, weak) UIView *dragIndicatorView; +@property (nonatomic, weak) UIView *presentedView; // which used to present. + +@property(nonatomic, weak) id delegate; +@property(nonatomic, weak) id dataSource; + +- (instancetype)initWithPresentable:(id )presentable; ++ (instancetype)handlerWithPresentable:(id )presentable; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +- (void)observeScrollable; + +- (void)configureScrollViewInsets; + +- (void)setScrollableContentOffset:(CGPoint)offset animated:(BOOL)animated; + +- (void)configureViewLayout; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Mediator/HWPanModalPresentableHandler.m b/Pods/HWPanModal/Sources/Mediator/HWPanModalPresentableHandler.m new file mode 100644 index 0000000..648c63a --- /dev/null +++ b/Pods/HWPanModal/Sources/Mediator/HWPanModalPresentableHandler.m @@ -0,0 +1,769 @@ +// +// HWPanModalPresentableHandler.m +// HWPanModal +// +// Created by heath wang on 2019/10/15. +// Copyright © 2019 Heath Wang. All rights reserved. +// + +#import "HWPanModalPresentableHandler.h" +#import "UIScrollView+Helper.h" +#import "UIViewController+LayoutHelper.h" +#import "UIView+HW_Frame.h" +#import "KeyValueObserver.h" +#import "HWPanModalContentView.h" + +static NSString *const kScrollViewKVOContentOffsetKey = @"contentOffset"; + +@interface HWPanModalPresentableHandler () + +@property (nonatomic, assign) CGFloat shortFormYPosition; + +@property (nonatomic, assign) CGFloat mediumFormYPosition; + +@property (nonatomic, assign) CGFloat longFormYPosition; + +@property (nonatomic, assign) BOOL extendsPanScrolling; + +@property (nonatomic, assign) BOOL anchorModalToLongForm; + +@property (nonatomic, assign) CGFloat anchoredYPosition; + +@property (nonatomic, strong) id presentable; + +// keyboard handle +@property (nonatomic, copy) NSDictionary *keyboardInfo; + +@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer; +@property (nonatomic, strong) UIPanGestureRecognizer *screenEdgeGestureRecognizer; + +// kvo +@property (nonatomic, strong) id observerToken; +@property (nonatomic, assign) CGFloat scrollViewYOffset; + +@end + +@implementation HWPanModalPresentableHandler + +- (instancetype)initWithPresentable:(id )presentable { + self = [super init]; + if (self) { + _presentable = presentable; + _extendsPanScrolling = YES; + _anchorModalToLongForm = YES; + [self addKeyboardObserver]; + } + + return self; +} + ++ (instancetype)handlerWithPresentable:(id )presentable { + return [[self alloc] initWithPresentable:presentable]; +} + +#pragma mark - Pan Gesture Event Handler + +- (void)didPanOnView:(UIPanGestureRecognizer *)panGestureRecognizer { + + if ([self shouldResponseToPanGestureRecognizer:panGestureRecognizer] && !self.keyboardInfo) { + + switch (panGestureRecognizer.state) { + + case UIGestureRecognizerStateBegan: + case UIGestureRecognizerStateChanged: { + [self handlePanGestureBeginOrChanged:panGestureRecognizer]; + } + break; + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + case UIGestureRecognizerStateFailed: { + [self handlePanGestureEnded:panGestureRecognizer]; + } + break; + default: break; + } + } else { + [self handlePanGestureDidNotResponse:panGestureRecognizer]; + } + [self.presentable didRespondToPanModalGestureRecognizer:panGestureRecognizer]; +} + +- (BOOL)shouldResponseToPanGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + if ([self.presentable shouldRespondToPanModalGestureRecognizer:panGestureRecognizer] || + !(panGestureRecognizer.state == UIGestureRecognizerStateBegan || panGestureRecognizer.state == UIGestureRecognizerStateCancelled)) { + + return ![self shouldFailPanGestureRecognizer:panGestureRecognizer]; + } else { + // stop pan gesture working. + panGestureRecognizer.enabled = NO; + panGestureRecognizer.enabled = YES; + return NO; + } +} + +- (BOOL)shouldFailPanGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + + if ([self shouldPrioritizePanGestureRecognizer:panGestureRecognizer]) { + // high priority than scroll view gesture, disable scrollView gesture. + [self.presentable panScrollable].panGestureRecognizer.enabled = NO; + [self.presentable panScrollable].panGestureRecognizer.enabled = YES; + return NO; + } + + if ([self shouldHandleShortStatePullDownWithRecognizer:panGestureRecognizer]) { +// panGestureRecognizer.enabled = NO; +// panGestureRecognizer.enabled = YES; + return YES; + } + + BOOL shouldFail = NO; + UIScrollView *scrollView = [self.presentable panScrollable]; + if (scrollView) { + shouldFail = scrollView.contentOffset.y > -MAX(scrollView.contentInset.top, 0); + + // we want scroll the panScrollable, not the presentedView + if (self.isPresentedViewAnchored && shouldFail) { + CGPoint location = [panGestureRecognizer locationInView:self.presentedView]; + BOOL flag = CGRectContainsPoint(scrollView.frame, location) || scrollView.isScrolling; + if (flag) { + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + } + return flag; + } else { + return NO; + } + + } else { + return NO; + } + +} + +- (BOOL)shouldHandleShortStatePullDownWithRecognizer:(UIPanGestureRecognizer *)recognizer { + if ([self.presentable allowsPullDownWhenShortState]) return NO; + + CGPoint location = [recognizer translationInView:self.presentedView]; + if ([self.delegate getCurrentPresentationState] == PresentationStateShort && recognizer.state == UIGestureRecognizerStateBegan) { + return YES; + } + + if ((self.presentedView.frame.origin.y >= self.shortFormYPosition || HW_TWO_FLOAT_IS_EQUAL(self.presentedView.frame.origin.y, self.shortFormYPosition)) && location.y > 0) { + return YES; + } + + return NO; +} + +- (BOOL)shouldPrioritizePanGestureRecognizer:(UIPanGestureRecognizer *)recognizer { + return recognizer.state == UIGestureRecognizerStateBegan && [[self presentable] shouldPrioritizePanModalGestureRecognizer:recognizer]; +} + +- (void)respondToPanGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + [self.presentable willRespondToPanModalGestureRecognizer:panGestureRecognizer]; + + CGFloat yDisplacement = [panGestureRecognizer translationInView:self.presentedView].y; + + if (self.presentedView.frame.origin.y < self.longFormYPosition) { + yDisplacement = yDisplacement / 2; + } + + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(adjustPresentableYPos:)]) { + [delegate adjustPresentableYPos:self.presentedView.frame.origin.y + yDisplacement]; + } + + [panGestureRecognizer setTranslation:CGPointZero inView:self.presentedView]; +} + +- (BOOL)isVelocityWithinSensitivityRange:(CGFloat)velocity { + return (fabs(velocity) - [self.presentable minVerticalVelocityToTriggerDismiss]) > 0; +} + +- (CGFloat)nearestDistance:(CGFloat)position inDistances:(NSArray *)distances { + + if (distances.count <= 0) { + return position; + } + + // TODO: need refine this sort code. + NSMutableArray *tmpArr = [NSMutableArray arrayWithCapacity:distances.count]; + NSMutableDictionary *tmpDict = [NSMutableDictionary dictionaryWithCapacity:distances.count]; + + [distances enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSNumber *number = obj; + NSNumber *absValue = @(fabs(number.floatValue - position)); + [tmpArr addObject:absValue]; + tmpDict[absValue] = number; + + }]; + + [tmpArr sortUsingSelector:@selector(compare:)]; + + NSNumber *result = tmpDict[tmpArr.firstObject]; + return result.floatValue; +} + +- (void)screenEdgeInteractiveAction:(UIPanGestureRecognizer *)gestureRecognizer { + // +} + +#pragma mark - handle did Pan gesture events + +- (void)handlePanGestureDidNotResponse:(UIPanGestureRecognizer *)panGestureRecognizer { + switch (panGestureRecognizer.state) { + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + case UIGestureRecognizerStateFailed: { + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + [self cancelInteractiveTransition]; + } + break; + default: + break; + } + [panGestureRecognizer setTranslation:CGPointZero inView:panGestureRecognizer.view]; +} + +- (void)handlePanGestureBeginOrChanged:(UIPanGestureRecognizer *)panGestureRecognizer { + CGPoint velocity = [panGestureRecognizer velocityInView:self.presentedView]; + [self respondToPanGestureRecognizer:panGestureRecognizer]; + + if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) { + // check if toggle dismiss action + if ([[self presentable] presentingVCAnimationStyle] > PresentingViewControllerAnimationStyleNone && + velocity.y > 0 && + (self.presentedView.frame.origin.y > self.shortFormYPosition || HW_TWO_FLOAT_IS_EQUAL(self.presentedView.frame.origin.y, self.shortFormYPosition))) { + [self dismissPresentable:YES mode:PanModalInteractiveModeDragDown]; + } + } + + if (HW_TWO_FLOAT_IS_EQUAL(self.presentedView.frame.origin.y, self.anchoredYPosition) && self.extendsPanScrolling) { + [self.presentable willTransitionToState:PresentationStateLong]; + } + + // update drag indicator + if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) { + if (velocity.y > 0) { + [self.dragIndicatorView didChangeToState:HWIndicatorStatePullDown]; + } else if (velocity.y < 0 && self.presentedView.frame.origin.y <= self.anchoredYPosition && !self.extendsPanScrolling) { + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + } + } +} + +- (void)handlePanGestureEnded:(UIPanGestureRecognizer *)panGestureRecognizer { + CGPoint velocity = [panGestureRecognizer velocityInView:self.presentedView]; + /** + * pan recognizer结束 + * 根据velocity(速度),当velocity.y < 0,说明用户在向上拖拽view;当velocity.y > 0,向下拖拽 + * 根据拖拽的速度,处理不同的情况: + * 1.超过拖拽速度阈值时并且向下拖拽,dismiss controller + * 2.向上拖拽永远不会dismiss,回弹至相应的状态 + */ + + if ([self isVelocityWithinSensitivityRange:velocity.y]) { + + id delegate = self.delegate; + PresentationState currentState = [delegate getCurrentPresentationState]; + + if (velocity.y < 0) { + [self handleDragUpState:currentState]; + } else { + [self handleDragDownState:currentState]; + } + } else { + CGFloat position = [self nearestDistance:CGRectGetMinY(self.presentedView.frame) inDistances:@[@([self containerSize].height), @(self.shortFormYPosition), @(self.longFormYPosition), @(self.mediumFormYPosition)]]; + if (HW_TWO_FLOAT_IS_EQUAL(position, self.longFormYPosition)) { + [self transitionToState:PresentationStateLong]; + [self cancelInteractiveTransition]; + } else if (HW_TWO_FLOAT_IS_EQUAL(position, self.mediumFormYPosition)) { + [self transitionToState:PresentationStateMedium]; + [self cancelInteractiveTransition]; + } else if (HW_TWO_FLOAT_IS_EQUAL(position, self.shortFormYPosition) || ![self.presentable allowsDragToDismiss]) { + [self transitionToState:PresentationStateShort]; + [self cancelInteractiveTransition]; + } else { + if ([self isBeingDismissed]) { + [self finishInteractiveTransition]; + } else { + [self dismissPresentable:NO mode:PanModalInteractiveModeNone]; + } + } + } + [self.presentable didEndRespondToPanModalGestureRecognizer:panGestureRecognizer]; +} + +- (void)handleDragUpState:(PresentationState)state { + switch (state) { + case PresentationStateLong: + [self transitionToState:PresentationStateLong]; + [self cancelInteractiveTransition]; + break; + case PresentationStateMedium: + [self transitionToState:PresentationStateLong]; + [self cancelInteractiveTransition]; + break; + case PresentationStateShort: + [self transitionToState:PresentationStateMedium]; + [self cancelInteractiveTransition]; + break; + default: + break; + } +} + +- (void)handleDragDownState:(PresentationState)state { + switch (state) { + case PresentationStateLong: + [self transitionToState:PresentationStateMedium]; + [self cancelInteractiveTransition]; + break; + case PresentationStateMedium: + [self transitionToState:PresentationStateShort]; + [self cancelInteractiveTransition]; + break; + case PresentationStateShort: + if (![self.presentable allowsDragToDismiss]) { + [self transitionToState:PresentationStateShort]; + [self cancelInteractiveTransition]; + } else { + if ([self isBeingDismissed]) { + [self finishInteractiveTransition]; + } else { + [self dismissPresentable:NO mode:PanModalInteractiveModeNone]; + } + } + break; + default: + break; + } +} + +#pragma mark - UIScrollView kvo + +- (void)observeScrollable { + UIScrollView *scrollView = [[self presentable] panScrollable]; + if (!scrollView) { + // force set observerToken to nil, make sure to callback. + self.observerToken = nil; + return; + } + + self.scrollViewYOffset = MAX(scrollView.contentOffset.y, -(MAX(scrollView.contentInset.top, 0))); + self.observerToken = [KeyValueObserver observeObject:scrollView keyPath:kScrollViewKVOContentOffsetKey target:self selector:@selector(didPanOnScrollViewChanged:) options:NSKeyValueObservingOptionOld]; +} + +/** + As the user scrolls, track & save the scroll view y offset. + This helps halt scrolling when we want to hold the scroll view in place. +*/ +- (void)trackScrolling:(UIScrollView *)scrollView { + self.scrollViewYOffset = MAX(scrollView.contentOffset.y, -(MAX(scrollView.contentInset.top, 0))); + scrollView.showsVerticalScrollIndicator = [[self presentable] showsScrollableVerticalScrollIndicator]; +} + +/** + * Halts the scroll of a given scroll view & anchors it at the `scrollViewYOffset` + */ +- (void)haltScrolling:(UIScrollView *)scrollView { + + // + // Fix bug: the app will crash after the table view reloads data via calling [tableView reloadData] if the user scrolls to the bottom. + // + // We remove some element and reload data, for example, [self.dataSource removeLastObject], the previous saved scrollViewYOffset value + // will be great than or equal to the current actual offset(i.e. scrollView.contentOffset.y). At this time, if the method + // [scrollView setContentOffset:CGPointMake(0, self.scrollViewYOffset) animated:NO] is called, which will trigger KVO recursively. + // So scrollViewYOffset must be less than or equal to the actual offset here. + // See issues: https://github.com/HeathWang/HWPanModal/issues/107 and https://github.com/HeathWang/HWPanModal/issues/103 + + if (scrollView.contentOffset.y <= 0 || self.scrollViewYOffset <= scrollView.contentOffset.y) { + [scrollView setContentOffset:CGPointMake(0, self.scrollViewYOffset) animated:NO]; + scrollView.showsVerticalScrollIndicator = NO; + } +} + +- (void)didPanOnScrollViewChanged:(NSDictionary *)change { + + UIScrollView *scrollView = [[self presentable] panScrollable]; + if (!scrollView) return; + + if ((![self isBeingDismissed] && ![self isBeingPresented]) || + ([self isBeingDismissed] && [self isPresentedViewControllerInteractive])) { + + if (![self isPresentedViewAnchored] && scrollView.contentOffset.y > 0) { + [self haltScrolling:scrollView]; + } else if ([scrollView isScrolling] || [self isPresentedViewAnimating]) { + + // While we're scrolling upwards on the scrollView, store the last content offset position + if ([self isPresentedViewAnchored]) { + [self trackScrolling:scrollView]; + } else { + /** + * Keep scroll view in place while we're panning on main view + */ + [self haltScrolling:scrollView]; + } + } else { + [self trackScrolling:scrollView]; + } + + } else { + /** + * 当present Controller,而且动画没有结束的时候,用户可能会对scrollView设置contentOffset + * 首次用户滑动scrollView时,会因为scrollViewYOffset = 0而出现错位 + */ + if ([self isBeingPresented]) { + [self setScrollableContentOffset:scrollView.contentOffset animated:YES]; + } + } +} + +#pragma mark - UIScrollView update + +- (void)configureScrollViewInsets { + + // when scrolling, return + if ([self.presentable panScrollable] && ![self.presentable panScrollable].isScrolling) { + UIScrollView *scrollView = [self.presentable panScrollable]; + // 禁用scrollView indicator除非用户开始滑动scrollView + scrollView.showsVerticalScrollIndicator = [self.presentable showsScrollableVerticalScrollIndicator]; + scrollView.scrollEnabled = [self.presentable isPanScrollEnabled]; + scrollView.scrollIndicatorInsets = [self.presentable scrollIndicatorInsets]; + + if (![self.presentable shouldAutoSetPanScrollContentInset]) return; + + UIEdgeInsets insets1 = scrollView.contentInset; + CGFloat bottomLayoutOffset = [UIApplication sharedApplication].keyWindow.rootViewController.bottomLayoutGuide.length; + /* + * If scrollView has been set contentInset, and bottom is NOT zero, we won't change it. + * If contentInset.bottom is zero, set bottom = bottomLayoutOffset + * If scrollView has been set contentInset, BUT the bottom < bottomLayoutOffset, set bottom = bottomLayoutOffset + */ + if (HW_FLOAT_IS_ZERO(insets1.bottom) || insets1.bottom < bottomLayoutOffset) { + + insets1.bottom = bottomLayoutOffset; + scrollView.contentInset = insets1; + } + + if (@available(iOS 11.0, *)) { + scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + // Fallback on earlier versions + } + } +} + +- (void)setScrollableContentOffset:(CGPoint)offset animated:(BOOL)animated { + if (![self.presentable panScrollable]) return; + + UIScrollView *scrollView = [self.presentable panScrollable]; + [self.observerToken unObserver]; + + [scrollView setContentOffset:offset animated:animated]; + // wait for animation finished. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) ((animated ? 0.30 : 0.1) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + [self trackScrolling:scrollView]; + [self observeScrollable]; + }); + +} + +#pragma mark - layout + +- (void)configureViewLayout { + + if ([self.presentable isKindOfClass:UIViewController.class]) { + UIViewController *layoutPresentable = (UIViewController *) self.presentable; + self.shortFormYPosition = layoutPresentable.shortFormYPos; + self.mediumFormYPosition = layoutPresentable.mediumFormYPos; + self.longFormYPosition = layoutPresentable.longFormYPos; + self.anchorModalToLongForm = [layoutPresentable anchorModalToLongForm]; + self.extendsPanScrolling = [layoutPresentable allowsExtendedPanScrolling]; + } else if ([self.presentable isKindOfClass:HWPanModalContentView.class]) { + HWPanModalContentView *layoutPresentable = (HWPanModalContentView *) self.presentable; + self.shortFormYPosition = layoutPresentable.shortFormYPos; + self.mediumFormYPosition = layoutPresentable.mediumFormYPos; + self.longFormYPosition = layoutPresentable.longFormYPos; + self.anchorModalToLongForm = [layoutPresentable anchorModalToLongForm]; + self.extendsPanScrolling = [layoutPresentable allowsExtendedPanScrolling]; + } + +} + +#pragma mark - UIGestureRecognizerDelegate + +/** + * ONLY When otherGestureRecognizer is panGestureRecognizer, and target gestureRecognizer is panGestureRecognizer, return YES. + */ +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + + if ([self.presentable respondsToSelector:@selector(hw_gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) { + return [self.presentable hw_gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; + } + + if ([gestureRecognizer isKindOfClass:UIPanGestureRecognizer.class]) { + return [otherGestureRecognizer isKindOfClass:UIPanGestureRecognizer.class]; + } + return NO; +} + +/** + * 当前手势为screenGestureRecognizer时,其他pan recognizer都应该fail + */ +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + + if ([self.presentable respondsToSelector:@selector(hw_gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:)]) { + return [self.presentable hw_gestureRecognizer:gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:otherGestureRecognizer]; + } + + + if (gestureRecognizer == self.screenEdgeGestureRecognizer && [otherGestureRecognizer isKindOfClass:UIPanGestureRecognizer.class]) { + return YES; + } + return NO; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + if ([self.presentable respondsToSelector:@selector(hw_gestureRecognizer:shouldRequireFailureOfGestureRecognizer:)]) { + return [self.presentable hw_gestureRecognizer:gestureRecognizer shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer]; + } + + return NO; +} + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + + if ([self.presentable respondsToSelector:@selector(hw_gestureRecognizerShouldBegin:)]) { + return [self.presentable hw_gestureRecognizerShouldBegin:gestureRecognizer]; + } + + if (gestureRecognizer == self.screenEdgeGestureRecognizer) { + CGPoint velocity = [self.screenEdgeGestureRecognizer velocityInView:self.screenEdgeGestureRecognizer.view]; + + if (velocity.x <= 0 || HW_TWO_FLOAT_IS_EQUAL(velocity.x, 0)) { + return NO; + } + + // check the distance to left edge + CGPoint location = [self.screenEdgeGestureRecognizer locationInView:self.screenEdgeGestureRecognizer.view]; + CGFloat thresholdDistance = [[self presentable] maxAllowedDistanceToLeftScreenEdgeForPanInteraction]; + if (thresholdDistance > 0 && location.x > thresholdDistance) { + return NO; + } + + if (velocity.x > 0 && HW_TWO_FLOAT_IS_EQUAL(velocity.y, 0)) { + return YES; + } + + //TODO: this logic can be updated later. + if (velocity.x > 0 && velocity.x / fabs(velocity.y) > 2) { + return YES; + } + return NO; + } + + return YES; +} + +#pragma mark - UIKeyboard Handle + +- (void)addKeyboardObserver { + if ([self.presentable isAutoHandleKeyboardEnabled]) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + } +} + +- (void)removeKeyboardObserver { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)keyboardWillShow:(NSNotification *)notification { + UIView *currentInput = [self findCurrentTextInputInView:self.presentedView]; + + if (!currentInput) + return; + + self.keyboardInfo = notification.userInfo; + [self updatePanContainerFrameForKeyboard]; +} + +- (void)keyboardWillHide:(NSNotification *)notification { + self.keyboardInfo = nil; + + NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + UIViewAnimationCurve curve = (UIViewAnimationCurve) [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; + + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationCurve:curve]; + [UIView setAnimationDuration:duration]; + + self.presentedView.transform = CGAffineTransformIdentity; + + [UIView commitAnimations]; +} + +- (void)updatePanContainerFrameForKeyboard { + if (!self.keyboardInfo) + return; + + UIView *textInput = [self findCurrentTextInputInView:self.presentedView]; + if (!textInput) + return; + + CGAffineTransform lastTransform = self.presentedView.transform; + self.presentedView.transform = CGAffineTransformIdentity; + + CGFloat textViewBottomY = [textInput convertRect:textInput.bounds toView:self.presentedView].origin.y + textInput.hw_height; + CGFloat keyboardHeight = [self.keyboardInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; + + CGFloat offsetY = 0; + CGFloat top = [self.presentable keyboardOffsetFromInputView]; + offsetY = self.presentedView.hw_height - (keyboardHeight + top + textViewBottomY + self.presentedView.hw_top); + + NSTimeInterval duration = [self.keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + UIViewAnimationCurve curve = (UIViewAnimationCurve) [self.keyboardInfo[UIKeyboardAnimationCurveUserInfoKey] intValue]; + + self.presentedView.transform = lastTransform; + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationCurve:curve]; + [UIView setAnimationDuration:duration]; + + self.presentedView.transform = CGAffineTransformMakeTranslation(0, offsetY); + + [UIView commitAnimations]; +} + +- (UIView *)findCurrentTextInputInView:(UIView *)view { + if ([view conformsToProtocol:@protocol(UIKeyInput)] && view.isFirstResponder) { + // Quick fix for web view issue + if ([view isKindOfClass:NSClassFromString(@"UIWebBrowserView")] || [view isKindOfClass:NSClassFromString(@"WKContentView")]) { + return nil; + } + return (UIView *) view; + } + + for (UIView *subview in view.subviews) { + UIView *inputInView = [self findCurrentTextInputInView:subview]; + if (inputInView) { + return inputInView; + } + } + return nil; +} + +#pragma mark - delegate throw + +- (void)transitionToState:(PresentationState)state { + + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(presentableTransitionToState:)]) { + [delegate presentableTransitionToState:state]; + } +} + +- (void)cancelInteractiveTransition { + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(cancelInteractiveTransition)]) { + [delegate cancelInteractiveTransition]; + } +} + +- (void)finishInteractiveTransition { + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(finishInteractiveTransition)]) { + [delegate finishInteractiveTransition]; + } +} + +- (void)dismissPresentable:(BOOL)isInteractive mode:(PanModalInteractiveMode)mode { + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(dismiss:mode:)]) { + [delegate dismiss:isInteractive mode:mode]; + } +} + +#pragma mark - dataSource handle + +- (BOOL)isPresentedViewAnchored { + if (self.dataSource && [self.dataSource respondsToSelector:@selector(isPresentedViewAnchored)]) { + return [self.dataSource isPresentedViewAnchored]; + } + + return NO; +} + +- (BOOL)isBeingDismissed { + if (self.dataSource && [self.dataSource respondsToSelector:@selector(isBeingDismissed)]) { + return [self.dataSource isBeingDismissed]; + } + return NO; +} + +- (BOOL)isBeingPresented { + if (self.dataSource && [self.dataSource respondsToSelector:@selector(isBeingPresented)]) { + return [self.dataSource isBeingPresented]; + } + return NO; +} + +- (BOOL)isPresentedViewControllerInteractive { + if (self.dataSource && [self.dataSource respondsToSelector:@selector(isPresentedControllerInteractive)]) { + return [self.dataSource isPresentedControllerInteractive]; + } + return NO; +} + +- (BOOL)isPresentedViewAnimating { + if (self.dataSource && [self.dataSource respondsToSelector:@selector(isFormPositionAnimating)]) { + [self.dataSource isFormPositionAnimating]; + } + return NO; +} + +- (CGSize)containerSize { + if (self.dataSource && [self.dataSource respondsToSelector:@selector(containerSize)]) { + return [self.dataSource containerSize]; + } + + return CGSizeZero; +} + +#pragma mark - Getter + +- (UIPanGestureRecognizer *)panGestureRecognizer { + if (!_panGestureRecognizer) { + _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPanOnView:)]; + _panGestureRecognizer.minimumNumberOfTouches = 1; + _panGestureRecognizer.maximumNumberOfTouches = 1; + _panGestureRecognizer.delegate = self; + } + return _panGestureRecognizer; +} + +- (UIPanGestureRecognizer *)screenEdgeGestureRecognizer { + if (!_screenEdgeGestureRecognizer) { + _screenEdgeGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(screenEdgeInteractiveAction:)]; + _screenEdgeGestureRecognizer.minimumNumberOfTouches = 1; + _screenEdgeGestureRecognizer.maximumNumberOfTouches = 1; + _screenEdgeGestureRecognizer.delegate = self; + } + + return _screenEdgeGestureRecognizer; +} + +- (CGFloat)anchoredYPosition { + CGFloat defaultTopOffset = [self.presentable topOffset]; + return self.anchorModalToLongForm ? self.longFormYPosition : defaultTopOffset; +} + +#pragma mark - Dealloc + +- (void)dealloc { + [self removeKeyboardObserver]; +} + +@end diff --git a/Pods/HWPanModal/Sources/Presentable/HWPanModalHeight.h b/Pods/HWPanModal/Sources/Presentable/HWPanModalHeight.h new file mode 100644 index 0000000..998b8d9 --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/HWPanModalHeight.h @@ -0,0 +1,48 @@ +// +// HWPanModalHeight.h +// Pods +// +// Created by heath wang on 2019/4/26. +// + +#import +#import + +typedef NS_ENUM(NSInteger, PanModalHeightType) { + PanModalHeightTypeMax NS_SWIFT_NAME(max), // from top max + PanModalHeightTypeMaxTopInset NS_SWIFT_NAME(topInset), // from top offset + PanModalHeightTypeContent NS_SWIFT_NAME(content), // from bottom + PanModalHeightTypeContentIgnoringSafeArea NS_SWIFT_NAME(contentIgnoringSafeArea), // from bottom ignore safeArea + PanModalHeightTypeIntrinsic NS_SWIFT_NAME(intrinsic), // auto get size, There is something wrong, DO NOT recommend to use. +}; + +struct PanModalHeight { + PanModalHeightType heightType NS_SWIFT_NAME(type); + CGFloat height; +}; + +typedef struct PanModalHeight PanModalHeight; + +/** + * When heightType is PanModalHeightTypeMax, PanModalHeightTypeIntrinsic, the height value will be ignored. + */ +CG_INLINE PanModalHeight PanModalHeightMake(PanModalHeightType heightType, CGFloat height) { + PanModalHeight modalHeight; + modalHeight.heightType = heightType; + modalHeight.height = height; + return modalHeight; +} + +static inline BOOL HW_FLOAT_IS_ZERO(CGFloat value) { + return (value > -FLT_EPSILON) && (value < FLT_EPSILON); +} + +static inline BOOL HW_TWO_FLOAT_IS_EQUAL(CGFloat x, CGFloat y) { + CGFloat minusValue = fabs(x - y); + CGFloat criticalValue = 0.0001; + if (minusValue < criticalValue || minusValue < FLT_MIN) { + return YES; + } + return NO; +} + diff --git a/Pods/HWPanModal/Sources/Presentable/HWPanModalPanGestureDelegate.h b/Pods/HWPanModal/Sources/Presentable/HWPanModalPanGestureDelegate.h new file mode 100644 index 0000000..908cbdb --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/HWPanModalPanGestureDelegate.h @@ -0,0 +1,31 @@ +// +// HWPanModalPanGestureDelegate.h +// Pods +// +// Created by heath wang on 2022/8/1. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * In this framewok, we use UIPanGestureRecognizer to control user drags behavior. + * The internal logic, there are two panGestureRecognizers delegate will response below delegate: the main panGesture used to control darg down, another panGesture used to control screen edge dismiss. + * Implement this delegate and custom user drag behavior. + * WARNING: BE CAREFUL, AND KNOW WHAT YOU ARE DOING! + */ +@protocol HWPanModalPanGestureDelegate + +- (BOOL)hw_gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer; +- (BOOL)hw_gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; + +- (BOOL)hw_gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; +- (BOOL)hw_gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; + + +@end + +NS_ASSUME_NONNULL_END + diff --git a/Pods/HWPanModal/Sources/Presentable/HWPanModalPresentable.h b/Pods/HWPanModal/Sources/Presentable/HWPanModalPresentable.h new file mode 100644 index 0000000..2e9bc85 --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/HWPanModalPresentable.h @@ -0,0 +1,451 @@ +// +// HWPanModalPresentable.h +// Pods +// +// Created by heath wang on 2019/4/26. +// + +#import +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, PresentationState) { + PresentationStateShort NS_SWIFT_NAME(short), + PresentationStateMedium NS_SWIFT_NAME(medium), + PresentationStateLong NS_SWIFT_NAME(long), +}; + +typedef NS_ENUM(NSInteger, PresentingViewControllerAnimationStyle) { + // no animation for presentingVC + PresentingViewControllerAnimationStyleNone NS_SWIFT_NAME(none), + // page sheet animation, like iOS13 default modalPresentation style + PresentingViewControllerAnimationStylePageSheet NS_SWIFT_NAME(pageSheet), + // shopping cart animation, like jd/taobao shopping cart animation + PresentingViewControllerAnimationStyleShoppingCart NS_SWIFT_NAME(shoppingCart), + // make your own custom animation + PresentingViewControllerAnimationStyleCustom NS_SWIFT_NAME(custom), +}; + +/** + * HWPanModalPresentable为present配置协议 + * 默认情况下无需实现,只需Controller/View适配该协议 + * 通过category来默认实现以下所有方法,避免继承类 + * + * This Protocol is the core of HWPanModal, we use it to config presentation. + * Default, you don't need to conform all of these methods, just implement what you want to customize. + * All the config has default value, we use a `UIViewController` category to conform `HWPanModalPresentable` protocol. + */ +@protocol HWPanModalPresentable + +#pragma mark - ScrollView Config + +/** + * 支持同步拖拽的scrollView + * 如果ViewController中包含scrollView并且你想scrollView滑动和拖拽手势同时存在,请返回此scrollView + * + * If your ViewController has a scrollable view(UIScrollView and subclass), and you want pan gesture and scrollable both work, return it. + */ +- (nullable UIScrollView *)panScrollable; + +/** + * determine ScrollView scrollEnabled + * default is YES + */ +- (BOOL)isPanScrollEnabled; + +/** + * scrollView指示器insets + * Use `panModalSetNeedsLayoutUpdate()` when updating insets. + */ +- (UIEdgeInsets)scrollIndicatorInsets; + +/** + * A Boolean value that controls whether the scrollable vertical scroll indicator is visible. + * default is YES. + */ +- (BOOL)showsScrollableVerticalScrollIndicator; + +/** + * default is YES. + */ +- (BOOL)shouldAutoSetPanScrollContentInset; + +/** + * 是否允许拖动额外拖动,如果panScrollable存在,且scrollView contentSize > (size + bottomLayoutOffset),返回YES + * 其余情况返回NO + * + * If panScrollable exists, and scrollView contentSize > (size + bottomLayoutOffset), auto return YES, otherwise return NO. + * You can make your own logic if you want, and you know what you are doing. + */ +- (BOOL)allowsExtendedPanScrolling; + +#pragma mark - Offset/position + +/** + * Screen top offset from presented viewController + * Default is topLayoutGuide.length + 21.0. + */ +- (CGFloat)topOffset; + +/** + * 当pan状态为short时候的高度 + * default: shortFormHeight = longFormHeight + */ +- (PanModalHeight)shortFormHeight; + +/** + * default: mediumFormHeight = longFormHeight + */ +- (PanModalHeight)mediumFormHeight; + +/** + * 当pan状态为long的高度 + */ +- (PanModalHeight)longFormHeight; + +/** + * 初始弹出高度状态,默认为`shortFormHeight` + * + * Origin presentation height state, if you have special requirement, change it. + * Default is `shortFormHeight` + */ +- (PresentationState)originPresentationState; + +#pragma mark - Animation config + +/** + * spring弹性动画数值 + * Default is 0.9 + */ +- (CGFloat)springDamping; + +/** + * 转场动画时间 + * Default is 0.5 second + */ +- (NSTimeInterval)transitionDuration; + +/** + * starting from version 0.6.5, Only works when dismiss + * Default is same as `- (NSTimeInterval)transitionDuration;` + */ +- (NSTimeInterval)dismissalDuration; + +/** + * 转场动画options + * Default is UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState + */ +- (UIViewAnimationOptions)transitionAnimationOptions; + +#pragma mark - AppearanceTransition + +/** + * If enabled, the presenting VC will invoke viewWillAppear:, viewWillDisappear: + * Default is YES + */ +- (BOOL)shouldEnableAppearanceTransition; + +#pragma mark - Background config + +/** + * use this object to config background alpha or blur effect + * @return background config object + */ +- (HWBackgroundConfig *)backgroundConfig; + +#pragma mark - User Interaction + +/** + * 该bool值控制当pan View状态为long的情况下,是否可以继续拖拽到PanModalHeight = MAX的情况 + * 默认为YES,即当已经拖拽到long的情况下不能再继续拖动 + */ +- (BOOL)anchorModalToLongForm; + +/** + * 是否允许点击背景处dismiss presented Controller + * 默认为YES + */ +- (BOOL)allowsTapBackgroundToDismiss; + + +/** + * 是否允许drag操作dismiss presented Controller + * Default is YES + */ +- (BOOL)allowsDragToDismiss; + +/// Default is YES, When return NO, and you did set shortForm, user CAN NOT pull down the view. +- (BOOL)allowsPullDownWhenShortState; + +/** + min Velocity from Vertical direction that trigger dismiss action. + Default is 300.0 + */ +- (CGFloat)minVerticalVelocityToTriggerDismiss; + +/** + * 是否允许用户操作 + * Default is YES + */ +- (BOOL)isUserInteractionEnabled; + +/** + * 是否允许触觉反馈 + * Default is YES + */ +- (BOOL)isHapticFeedbackEnabled; + +/** + * 是否允许触摸事件透传到presenting ViewController/View。如果你有特殊需求的话(比如弹出一个底部视图,但是你想操作弹出视图下面的view,即presenting VC/View),可开启此功能 + * + * Whether allows touch events passing through the transition container view. + * In some situations, you present the bottom VC/View, and you want to operate the presenting VC/View(mapView, scrollView and etc), enable this func. + * + * Note: You SHOULD MUST dismiss the presented VC in the right time. + */ +- (BOOL)allowsTouchEventsPassingThroughTransitionView; + +#pragma mark - Screen left egde interaction + +/** + * 是否允许屏幕边缘侧滑手势 + * Default is NO,not allowed this user interaction. + * + * Note: Currently only works on UIViewController. + */ +- (BOOL)allowScreenEdgeInteractive; + +/** + * Max allowed distance to screen left edge when you want to make screen edge pan interaction + * Default is 0, means it will ignore this limit, full screen left edge pan will work. + * @return distance to left screen edge + */ +- (CGFloat)maxAllowedDistanceToLeftScreenEdgeForPanInteraction; + +/** + * When you enabled `- (BOOL)allowScreenEdgeInteractive`, this can work. + * min horizontal velocity to trigger screen edge dismiss if the drag didn't reach 0.5 screen width. + * Default is 500 + */ +- (CGFloat)minHorizontalVelocityToTriggerScreenEdgeDismiss; + +#pragma mark - Customize presentingViewController animation + +/** + * Config presentingViewController animation style, this animations will work for present & dismiss. + * Default is `PresentingViewControllerAnimationStyleNone`. + * @return The animation style. + */ +- (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle; + +/** + * 自定义presenting ViewController转场动画,默认为nil + * 注意:如果实现该方法并返回非空示例,要使该方法生效,`- (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle`必须返回PresentingViewControllerAnimationStyleCustom + * + * custom presenting ViewController transition animation, default is nil + * Note: If you implement this method and return non nil value, You must implement `- (PresentingViewControllerAnimationStyle) + * presentingVCAnimationStyle` and return PresentingViewControllerAnimationStyleCustom + */ +- (nullable id)customPresentingVCAnimation; + +#pragma mark - Content UI config + +/** + * 是否顶部圆角 + * Default is YES + */ +- (BOOL)shouldRoundTopCorners; + +/** + * 顶部圆角数值 + * Default is 8.0 + */ +- (CGFloat)cornerRadius; + +/** +* presented content shadow +* Default is None config +*/ +- (HWPanModalShadow *)contentShadow; + +#pragma mark - Indicator config + +/** + * 是否显示drag指示view + * Default is YES,Default this method depend on `- (BOOL)shouldRoundTopCorners` + */ +- (BOOL)showDragIndicator; + +/** + * You can make the indicator customized. Just adopt `HWPanModalIndicatorProtocol` + * Default this method return nil, Then the default indicator will be used. + */ +- (__kindof UIView * _Nullable)customIndicatorView; + +#pragma mark - Keyboard handle + +/** + * When there is text input view exists and becomeFirstResponder, will auto handle keyboard height. + * Default is YES. You can disable it, handle it by yourself. + */ +- (BOOL)isAutoHandleKeyboardEnabled; + +/** + The offset that keyboard show from input view's bottom. It works when + `isAutoHandleKeyboardEnabled` return YES. + + @return offset, default is 5. + */ +- (CGFloat)keyboardOffsetFromInputView; + +#pragma mark - Delegate + +#pragma mark - Pan Gesture delegate + +/** + * 询问delegate是否需要使拖拽手势生效 + * 若返回NO,则禁用拖拽手势操作,即不能拖拽dismiss + * 默认为YES + */ +- (BOOL)shouldRespondToPanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer; + +/** + * 当pan recognizer状态为begin/changed时,通知delegate回调。 + * 当拖动presented View时,该方法会持续的回调 + * 默认实现为空 + */ +- (void)willRespondToPanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer; + +/** + * 内部处理完成拖动操作后触发此回调,此时view frame可能已经变化。 + * Framework has did finish logic for GestureRecognizer delegate. It will call many times when you darg. + */ +- (void)didRespondToPanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer; + +/** + * 内部处理完成拖动操作后触发此回调,此时view frame可能已经变化。 + * Framework has did finish logic for GestureRecognizer delegate. It will call many times when you darg. + */ +- (void)didEndRespondToPanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer; + +/** + * 是否优先执行dismiss拖拽手势,当存在panScrollable的情况下,如果此方法返回YES,则 + * dismiss手势生效,scrollView本身的滑动则不再生效。也就是说可以拖动Controller view,而scrollView没法拖动了。 + * + * 例子:controller view上添加一个TableView,并铺满全屏,然后在controller view 顶部添加一个一定大小的viewA, + * 这个时候会发现viewA有时候无法拖动,可以实现此delegate方法来解决 + ``` + - (BOOL)shouldPrioritizePanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + CGPoint loc = [panGestureRecognizer locationInView:self.view]; + // check whether user pan action in viewA + if (CGRectContainsPoint(self.viewA.frame, loc)) { + return YES; + } + + return NO; +} + ``` + * 默认为NO + * + * This delegate is useful when you want panGestureRecognizer has a high prioritize and + * make scrollable does NOT scroll. + * Example: You controller add a full size tableView, then add viewA on top of your controller view. + * Now you find you can not drag the viewA, use this delegate to resolve problem. + * Please refer to code above this comment. + * + * Default is NO + */ +- (BOOL)shouldPrioritizePanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer; + +/** + * When you pan present controller to dismiss, and the view's y <= shortFormYPos, + * this delegate method will be called. + * @param percent 0 ~ 1, 1 means has dismissed + */ +- (void)panModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer dismissPercent:(CGFloat)percent; + +#pragma mark - PresentationState change delegate +/** + * 是否应该变更panModal状态 + */ +- (BOOL)shouldTransitionToState:(PresentationState)state; + +/** + * called when the Transition State will change. + * 通知回调即将变更状态 + */ +- (void)willTransitionToState:(PresentationState)state; + +/** + * PresentationState did change callback + */ +- (void)didChangeTransitionToState:(PresentationState)state; + +#pragma mark - present delegate + +/** + * call when present transition will begin. + */ +- (void)panModalTransitionWillBegin; + +/** + * call when present transition did finish. + */ +- (void)panModalTransitionDidFinish; + +/** + * call when your custom presented vc has been added to the presentation container. + */ +- (void)presentedViewDidMoveToSuperView; + +#pragma mark - Dismiss delegate +/** + * will dismiss + */ +- (void)panModalWillDismiss; + +/** + * Did finish dismissing + */ +- (void)panModalDidDismissed; + +#pragma mark - DEPRECATED DECLARE + +/** + * 是否对presentingViewController做动画效果,默认该效果类似淘宝/京东购物车凹陷效果 + * 默认为NO + */ +- (BOOL)shouldAnimatePresentingVC DEPRECATED_MSG_ATTRIBUTE("This api has been marked as DEPRECATED on version 0.3.6, please use `- (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle` replaced."); + +/** + * 背景透明度 + * Default is 0.7 + */ +- (CGFloat)backgroundAlpha DEPRECATED_MSG_ATTRIBUTE("This api has been marked as DEPRECATED on version 0.7.0, please use `- (HWBackgroundConfig *)backgroundConfig` replaced."); + +/** + * Blur background + * This function can NOT coexist with backgroundAlpha + * Default use backgroundAlpha, Once you set backgroundBlurRadius > 0, blur will work. + * Recommend set the value 10 ~ 20. + * @return blur radius + */ +- (CGFloat)backgroundBlurRadius DEPRECATED_MSG_ATTRIBUTE("This api has been marked as DEPRECATED on version 0.7.0, please use `- (HWBackgroundConfig *)backgroundConfig` replaced."); + +/** + * blur background color + * @return color, default is White Color. + */ +- (nonnull UIColor *)backgroundBlurColor DEPRECATED_MSG_ATTRIBUTE("This api has been marked as DEPRECATED on version 0.7.0, please use `- (HWBackgroundConfig *)backgroundConfig` replaced."); + +@end + + +NS_ASSUME_NONNULL_END + diff --git a/Pods/HWPanModal/Sources/Presentable/HWPanModalPresentationUpdateProtocol.h b/Pods/HWPanModal/Sources/Presentable/HWPanModalPresentationUpdateProtocol.h new file mode 100644 index 0000000..809f74f --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/HWPanModalPresentationUpdateProtocol.h @@ -0,0 +1,63 @@ +// +// HWPanModalPresentationUpdateProtocol.h +// Pods +// +// Created by heath wang on 2019/10/17. +// + +#import +@class HWDimmedView; + +@protocol HWPanModalPresentationUpdateProtocol +/// background view, you can call `reloadConfig:` to update the UI. +@property (nonatomic, readonly) HWDimmedView *hw_dimmedView; +/// the root container which your custom VC's view to be added. +@property (nonatomic, readonly) UIView *hw_rootContainerView; +/// which view that your presented viewController's view has been added. +@property (nonatomic, readonly) UIView *hw_contentView; +/// current presentation State +@property (nonatomic, readonly) PresentationState hw_presentationState; +/** + * force update pan modal State, short/long + */ +- (void)hw_panModalTransitionTo:(PresentationState)state NS_SWIFT_NAME(panModalTransitionTo(state:)); + +/** + * force update pan modal State, short/long + * @param state transition state + * @param animated whether animate when set state + */ +- (void)hw_panModalTransitionTo:(PresentationState)state animated:(BOOL)animated NS_SWIFT_NAME(panModalTransitionTo(state:animated:)); + +/** + * When presented ViewController has a UIScrollView, Use This method to update UIScrollView contentOffset + * Default it has animation + */ +- (void)hw_panModalSetContentOffset:(CGPoint)offset NS_SWIFT_NAME(panModalSetContentOffset(offset:)); + +/** + * When presented ViewController has a UIScrollView, Use This method to update UIScrollView contentOffset + * @param offset scrollView offset value + * @param animated whether animate + */ +- (void)hw_panModalSetContentOffset:(CGPoint)offset animated:(BOOL)animated NS_SWIFT_NAME(panModalSetContentOffset(offset:animated:)); + +/** + * Note:if we present a NavigationController, and we want to pan screen edge to dismiss. + * We MUST call this method when we PUSH/POP viewController. + * + */ +- (void)hw_panModalSetNeedsLayoutUpdate NS_SWIFT_NAME(panModalSetNeedsLayoutUpdate()); + +/** + * When you change the user touch event, like `allowsTouchEventsPassingThroughTransitionView`, you should call this method to make it work. + * 更新用户行为,比如事件穿透 + */ +- (void)hw_panModalUpdateUserHitBehavior NS_SWIFT_NAME(panModalUpdateUserHitBehavior()); + +/** + * call this method to dismiss your presented VC directly + */ +- (void)hw_dismissAnimated:(BOOL)animated completion:(void (^)(void))completion NS_SWIFT_NAME(panModalDismissAnimated(animated:completion:)); + +@end diff --git a/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.h b/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.h new file mode 100644 index 0000000..cc64c3b --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.h @@ -0,0 +1,38 @@ +// +// UIViewController+LayoutHelper.h +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import +@class HWPanModalPresentationController; + +NS_ASSUME_NONNULL_BEGIN + +@protocol HWPanModalPresentableLayoutProtocol + +@property (nonatomic, assign, readonly) CGFloat topLayoutOffset; + +@property (nonatomic, assign, readonly) CGFloat bottomLayoutOffset; + +@property (nonatomic, assign, readonly) CGFloat shortFormYPos; + +@property (nonatomic, assign, readonly) CGFloat mediumFormYPos; + +@property (nonatomic, assign, readonly) CGFloat longFormYPos; + +@property (nonatomic, assign, readonly) CGFloat bottomYPos; + +@end + +/** + * Help presentedViewController/presented View to layout. + */ +@interface UIViewController (LayoutHelper) + +@property (nullable, nonatomic, strong, readonly) HWPanModalPresentationController *hw_presentedVC; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.m b/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.m new file mode 100644 index 0000000..0208fda --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.m @@ -0,0 +1,130 @@ +// +// UIViewController+LayoutHelper.m +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import "UIViewController+LayoutHelper.h" +#import "HWPanModalPresentationController.h" +#import "UIViewController+PanModalDefault.h" + +@implementation UIViewController (LayoutHelper) + +- (CGFloat)topLayoutOffset { + if (@available(iOS 11, *)) { + return [UIApplication sharedApplication].keyWindow.safeAreaInsets.top; + } else { + return [UIApplication sharedApplication].keyWindow.rootViewController.topLayoutGuide.length; + } + +} + +- (CGFloat)bottomLayoutOffset { + if (@available(iOS 11, *)) { + return [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom; + } else { + return [UIApplication sharedApplication].keyWindow.rootViewController.bottomLayoutGuide.length; + } +} + +- (HWPanModalPresentationController *)hw_presentedVC { + /* + * Fix iOS13 bug: if we access presentationController before present VC, this will lead `modalPresentationStyle` not working. + * refer to: https://github.com/HeathWang/HWPanModal/issues/27 + * Apple Doc: If you have not yet presented the current view controller, accessing this property creates a presentation controller based on the current value in the modalPresentationStyle property. + */ + + /** + * fix bug: https://github.com/HeathWang/HWPanModal/issues/37 + */ + if (self.presentingViewController) { + return [self hw_getPanModalPresentationController]; + } else { + return nil; + } +} + +- (HWPanModalPresentationController *)hw_getPanModalPresentationController { + UIViewController *ancestorsVC; + + // seeking for the root presentation VC. + if (self.splitViewController) { + ancestorsVC = self.splitViewController; + } else if (self.navigationController) { + ancestorsVC = self.navigationController; + } else if (self.tabBarController) { + ancestorsVC = self.tabBarController; + } else { + ancestorsVC = self; + } + + if ([ancestorsVC.presentationController isMemberOfClass:HWPanModalPresentationController.class]) { + return (HWPanModalPresentationController *) ancestorsVC.presentationController; + } + return nil; +} + +/** + Returns the short form Y postion + + - Note: If voiceover is on, the `longFormYPos` is returned. + We do not support short form when voiceover is on as it would make it difficult for user to navigate. +*/ +- (CGFloat)shortFormYPos { + if (UIAccessibilityIsVoiceOverRunning()) { + return self.longFormYPos; + } else { + CGFloat shortFormYPos = [self topMarginFromPanModalHeight:[self shortFormHeight]] + [self topOffset]; + return MAX(shortFormYPos, self.longFormYPos); + } +} + +- (CGFloat)mediumFormYPos { + if (UIAccessibilityIsVoiceOverRunning()) { + return self.longFormYPos; + } else { + CGFloat mediumFormYPos = [self topMarginFromPanModalHeight:[self mediumFormHeight]] + [self topOffset]; + return MAX(mediumFormYPos, self.longFormYPos); + } +} + +- (CGFloat)longFormYPos { + return MAX([self topMarginFromPanModalHeight:[self longFormHeight]], [self topMarginFromPanModalHeight:PanModalHeightMake(PanModalHeightTypeMax, 0)]) + [self topOffset]; +} + +/** + * Use the container view for relative positioning as this view's frame + is adjusted in PanModalPresentationController + */ +- (CGFloat)bottomYPos { + if (self.hw_presentedVC.containerView) { + return self.hw_presentedVC.containerView.bounds.size.height - [self topOffset]; + } + return self.view.bounds.size.height; +} + +- (CGFloat)topMarginFromPanModalHeight:(PanModalHeight)panModalHeight { + switch (panModalHeight.heightType) { + case PanModalHeightTypeMax: + return 0.0f; + case PanModalHeightTypeMaxTopInset: + return panModalHeight.height; + case PanModalHeightTypeContent: + return self.bottomYPos - (panModalHeight.height + self.bottomLayoutOffset); + case PanModalHeightTypeContentIgnoringSafeArea: + return self.bottomYPos - panModalHeight.height; + case PanModalHeightTypeIntrinsic: + { + [self.view layoutIfNeeded]; + + CGSize targetSize = CGSizeMake(self.hw_presentedVC.containerView ? self.hw_presentedVC.containerView.bounds.size.width : [UIScreen mainScreen].bounds.size.width, UILayoutFittingCompressedSize.height); + CGFloat intrinsicHeight = [self.view systemLayoutSizeFittingSize:targetSize].height; + return self.bottomYPos - (intrinsicHeight + self.bottomLayoutOffset); + } + default: + return 0; + } +} + +@end diff --git a/Pods/HWPanModal/Sources/Presentable/UIViewController+PanModalDefault.h b/Pods/HWPanModal/Sources/Presentable/UIViewController+PanModalDefault.h new file mode 100644 index 0000000..bef8afe --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/UIViewController+PanModalDefault.h @@ -0,0 +1,18 @@ +// +// UIViewController+PanModalDefault.h +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIViewController (PanModalDefault) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Presentable/UIViewController+PanModalDefault.m b/Pods/HWPanModal/Sources/Presentable/UIViewController+PanModalDefault.m new file mode 100644 index 0000000..04d33bd --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/UIViewController+PanModalDefault.m @@ -0,0 +1,253 @@ +// +// UIViewController+PanModalDefault.m +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import "UIViewController+PanModalDefault.h" +#import "UIViewController+LayoutHelper.h" + +@implementation UIViewController (PanModalDefault) + +- (UIScrollView *)panScrollable { + return nil; +} + +- (CGFloat)topOffset { + return self.topLayoutOffset + 21.f; +} + +- (PanModalHeight)shortFormHeight { + return [self longFormHeight]; +} + +- (PanModalHeight)mediumFormHeight { + return [self longFormHeight]; +} + +- (PanModalHeight)longFormHeight { + if ([self panScrollable]) { + [[self panScrollable] layoutIfNeeded]; + return PanModalHeightMake(PanModalHeightTypeContent, MAX([self panScrollable].contentSize.height, [self panScrollable].bounds.size.height)); + } else { + return PanModalHeightMake(PanModalHeightTypeMax, 0); + } +} + +- (PresentationState)originPresentationState { + return PresentationStateShort; +} + +- (CGFloat)springDamping { + return 0.8; +} + +- (NSTimeInterval)transitionDuration { + return 0.5; +} + +- (NSTimeInterval)dismissalDuration { + return [self transitionDuration]; +} + +- (UIViewAnimationOptions)transitionAnimationOptions { + return UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState; +} + +- (CGFloat)backgroundAlpha { + return 0.7; +} + +- (CGFloat)backgroundBlurRadius { + return 0; +} + +- (nonnull UIColor *)backgroundBlurColor { + return [UIColor whiteColor]; +} + +- (HWBackgroundConfig *)backgroundConfig { + return [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault]; +} + +- (UIEdgeInsets)scrollIndicatorInsets { + CGFloat top = [self shouldRoundTopCorners] ? [self cornerRadius] : 0; + return UIEdgeInsetsMake(top, 0, self.bottomLayoutOffset, 0); +} + +- (BOOL)showsScrollableVerticalScrollIndicator { + return YES; +} + +- (BOOL)shouldAutoSetPanScrollContentInset { + return YES; +} + +- (BOOL)anchorModalToLongForm { + return YES; +} + +- (BOOL)allowsExtendedPanScrolling { + if ([self panScrollable]) { + UIScrollView *scrollable = [self panScrollable]; + + /* + [TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. + */ + if (!scrollable.superview || !scrollable.window) return NO; + + [scrollable layoutIfNeeded]; + return scrollable.contentSize.height > (scrollable.frame.size.height - self.bottomLayoutOffset); + } + + return NO; +} + +- (BOOL)allowsDragToDismiss { + return YES; +} + +- (CGFloat)minVerticalVelocityToTriggerDismiss { + return 300; +} + +- (BOOL)allowsTapBackgroundToDismiss { + return YES; +} + +- (BOOL)allowScreenEdgeInteractive { + return NO; +} + +- (CGFloat)maxAllowedDistanceToLeftScreenEdgeForPanInteraction { + return 0; +} + +- (CGFloat)minHorizontalVelocityToTriggerScreenEdgeDismiss { + return 500; +} + +- (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle { + return PresentingViewControllerAnimationStyleNone; +} + +- (BOOL)shouldEnableAppearanceTransition { + return YES; +} + +- (BOOL)shouldAnimatePresentingVC { + return NO; +} + +- (id )customPresentingVCAnimation { + return nil; +} + +- (BOOL)isPanScrollEnabled { + return YES; +} + +- (BOOL)isUserInteractionEnabled { + return YES; +} + +- (BOOL)allowsPullDownWhenShortState { + return YES; +} + +- (BOOL)isHapticFeedbackEnabled { + return YES; +} + +- (BOOL)allowsTouchEventsPassingThroughTransitionView { + return NO; +} + +- (BOOL)shouldRoundTopCorners { + return YES; +} + +- (CGFloat)cornerRadius { + return 8; +} + +- (HWPanModalShadow *)contentShadow { + return [HWPanModalShadow panModalShadowNil]; +} + +- (BOOL)showDragIndicator { + if ([self allowsTouchEventsPassingThroughTransitionView]) { + return NO; + } + return YES; +} + +- (nullable UIView *)customIndicatorView { + return nil; +} + +- (BOOL)isAutoHandleKeyboardEnabled { + return YES; +} + +- (CGFloat)keyboardOffsetFromInputView { + return 5; +} + +- (BOOL)shouldRespondToPanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + return YES; +} + +- (void)willRespondToPanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + +} + +- (void)didRespondToPanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + +} + +- (void)didEndRespondToPanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer { + +} + +- (BOOL)shouldPrioritizePanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + return NO; +} + +- (BOOL)shouldTransitionToState:(PresentationState)state { + return YES; +} + +- (void)willTransitionToState:(PresentationState)state { +} + +- (void)didChangeTransitionToState:(PresentationState)state { +} + +- (void)panModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer dismissPercent:(CGFloat)percent { + +} + +- (void)panModalWillDismiss { + +} + +- (void)panModalDidDismissed { + +} + +- (void)panModalTransitionWillBegin { + +} + +- (void)panModalTransitionDidFinish { + +} + +- (void)presentedViewDidMoveToSuperView { + +} + +@end + diff --git a/Pods/HWPanModal/Sources/Presentable/UIViewController+Presentation.h b/Pods/HWPanModal/Sources/Presentable/UIViewController+Presentation.h new file mode 100644 index 0000000..671fc21 --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/UIViewController+Presentation.h @@ -0,0 +1,21 @@ +// +// UIViewController+Presentation.h +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The presented Controller can use the category to update UIPresentationController container. + */ +@interface UIViewController (Presentation) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Presentable/UIViewController+Presentation.m b/Pods/HWPanModal/Sources/Presentable/UIViewController+Presentation.m new file mode 100644 index 0000000..bcbf3d4 --- /dev/null +++ b/Pods/HWPanModal/Sources/Presentable/UIViewController+Presentation.m @@ -0,0 +1,70 @@ +// +// UIViewController+Presentation.m +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import "UIViewController+Presentation.h" +#import "UIViewController+LayoutHelper.h" +#import "HWPanModalPresentationController.h" + +@interface UIViewController () + +@end + +@implementation UIViewController (Presentation) + +- (void)hw_panModalTransitionTo:(PresentationState)state { + if (!self.hw_presentedVC) return; + [self.hw_presentedVC transitionToState:state animated:YES]; +} + +- (void)hw_panModalTransitionTo:(PresentationState)state animated:(BOOL)animated { + if (!self.hw_presentedVC) return; + [self.hw_presentedVC transitionToState:state animated:animated]; +} + +- (void)hw_panModalSetContentOffset:(CGPoint)offset animated:(BOOL)animated { + if (!self.hw_presentedVC) return; + [self.hw_presentedVC setScrollableContentOffset:offset animated:animated]; +} + + +- (void)hw_panModalSetContentOffset:(CGPoint)offset { + if (!self.hw_presentedVC) return; + [self.hw_presentedVC setScrollableContentOffset:offset animated:YES]; +} + +- (void)hw_panModalSetNeedsLayoutUpdate { + if (!self.hw_presentedVC) return; + [self.hw_presentedVC setNeedsLayoutUpdate]; +} + +- (void)hw_panModalUpdateUserHitBehavior { + if (!self.hw_presentedVC) return; + [self.hw_presentedVC updateUserHitBehavior]; +} + +- (void)hw_dismissAnimated:(BOOL)animated completion:(void (^)(void))completion{ + if (!self.hw_presentedVC) return; + [self.hw_presentedVC dismissAnimated:animated completion:completion]; +} + +- (HWDimmedView *)hw_dimmedView { + return self.hw_presentedVC.backgroundView; +} + +- (UIView *)hw_rootContainerView { + return self.hw_presentedVC.containerView; +} + +- (UIView *)hw_contentView { + return self.hw_presentedVC.presentedView; +} + +- (PresentationState)hw_presentationState { + return self.hw_presentedVC.currentPresentationState; +} + +@end diff --git a/Pods/HWPanModal/Sources/Presenter/HWPanModalPresenterProtocol.h b/Pods/HWPanModal/Sources/Presenter/HWPanModalPresenterProtocol.h new file mode 100644 index 0000000..386f004 --- /dev/null +++ b/Pods/HWPanModal/Sources/Presenter/HWPanModalPresenterProtocol.h @@ -0,0 +1,47 @@ +// +// HWPanModalPresenterProtocol.h +// Pods +// +// Created by heath wang on 2019/4/29. +// + +#import +#import +#import +@class HWPanModalPresentationDelegate; + +NS_ASSUME_NONNULL_BEGIN + +@protocol HWPanModalPresenter + +@property (nonatomic, assign, readonly) BOOL isPanModalPresented; +/** + * 这里我们将实现UIViewControllerTransitioningDelegate协议的delegate通过runtime存入到viewControllerToPresent中。 + * use runtime to store this prop to hw_presentedVC + */ +@property (nonnull, nonatomic, strong) HWPanModalPresentationDelegate *hw_panModalPresentationDelegate; + +/** + * Note: This method ONLY for iPad, like UIPopoverPresentationController. + */ +- (void)presentPanModal:(UIViewController *)viewControllerToPresent + sourceView:(nullable UIView *)sourceView + sourceRect:(CGRect)rect; + +- (void)presentPanModal:(UIViewController *)viewControllerToPresent + sourceView:(nullable UIView *)sourceView + sourceRect:(CGRect)rect + completion:(void (^ __nullable)(void))completion; + +/** + * Present the Controller from bottom. + */ +- (void)presentPanModal:(UIViewController *)viewControllerToPresent; + +- (void)presentPanModal:(UIViewController *)viewControllerToPresent + completion:(void (^ __nullable)(void))completion; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/Pods/HWPanModal/Sources/Presenter/UIViewController+PanModalPresenter.h b/Pods/HWPanModal/Sources/Presenter/UIViewController+PanModalPresenter.h new file mode 100644 index 0000000..ce13542 --- /dev/null +++ b/Pods/HWPanModal/Sources/Presenter/UIViewController+PanModalPresenter.h @@ -0,0 +1,17 @@ +// +// UIViewController+PanModalPresenter.h +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import +#import "HWPanModalPresenterProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface UIViewController (PanModalPresenter) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/Presenter/UIViewController+PanModalPresenter.m b/Pods/HWPanModal/Sources/Presenter/UIViewController+PanModalPresenter.m new file mode 100644 index 0000000..9b41b9e --- /dev/null +++ b/Pods/HWPanModal/Sources/Presenter/UIViewController+PanModalPresenter.m @@ -0,0 +1,64 @@ +// +// UIViewController+PanModalPresenter.m +// HWPanModal +// +// Created by heath wang on 2019/4/29. +// + +#import "UIViewController+PanModalPresenter.h" +#import "HWPanModalPresentationDelegate.h" +#import + +@implementation UIViewController (PanModalPresenter) + +- (BOOL)isPanModalPresented { + return [self.transitioningDelegate isKindOfClass:HWPanModalPresentationDelegate.class]; +} + +- (void)presentPanModal:(UIViewController *)viewControllerToPresent sourceView:(UIView *)sourceView sourceRect:(CGRect)rect completion:(void (^)(void))completion { + + HWPanModalPresentationDelegate *delegate = [HWPanModalPresentationDelegate new]; + viewControllerToPresent.hw_panModalPresentationDelegate = delegate; + + if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad && + (sourceView && !CGRectEqualToRect(rect, CGRectZero))) { + viewControllerToPresent.modalPresentationStyle = UIModalPresentationPopover; + viewControllerToPresent.popoverPresentationController.sourceRect = rect; + viewControllerToPresent.popoverPresentationController.sourceView = sourceView; + viewControllerToPresent.popoverPresentationController.delegate = delegate; + } else { + + viewControllerToPresent.modalPresentationStyle = UIModalPresentationCustom; + viewControllerToPresent.modalPresentationCapturesStatusBarAppearance = YES; + viewControllerToPresent.transitioningDelegate = delegate; + } + + // fix for iOS 8 issue: the present action will delay. + dispatch_async(dispatch_get_main_queue(), ^{ + [self presentViewController:viewControllerToPresent animated:YES completion:completion]; + }); +} + +- (void)presentPanModal:(UIViewController *)viewControllerToPresent sourceView:(nullable UIView *)sourceView sourceRect:(CGRect)rect { + [self presentPanModal:viewControllerToPresent sourceView:sourceView sourceRect:rect completion:nil]; + +} + +- (void)presentPanModal:(UIViewController *)viewControllerToPresent { + [self presentPanModal:viewControllerToPresent sourceView:nil sourceRect:CGRectZero]; +} + +- (void)presentPanModal:(UIViewController *)viewControllerToPresent completion:(void (^)(void))completion { + [self presentPanModal:viewControllerToPresent sourceView:nil sourceRect:CGRectZero completion:completion]; +} + +- (HWPanModalPresentationDelegate *)hw_panModalPresentationDelegate { + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setHw_panModalPresentationDelegate:(HWPanModalPresentationDelegate *)hw_panModalPresentationDelegate { + objc_setAssociatedObject(self, @selector(hw_panModalPresentationDelegate), hw_panModalPresentationDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + + +@end diff --git a/Pods/HWPanModal/Sources/View/HWBackgroundConfig.h b/Pods/HWPanModal/Sources/View/HWBackgroundConfig.h new file mode 100644 index 0000000..7bce565 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWBackgroundConfig.h @@ -0,0 +1,37 @@ +// +// HWBackgroundConfig.h +// Pods +// +// Created by heath wang on 2020/4/17. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, HWBackgroundBehavior) { + HWBackgroundBehaviorDefault, // use background alpha + HWBackgroundBehaviorSystemVisualEffect, // use system UIVisualEffect object + HWBackgroundBehaviorCustomBlurEffect, // use custom blur +}; + +@interface HWBackgroundConfig : NSObject + +@property (nonatomic, assign) HWBackgroundBehavior backgroundBehavior; +// ONLY works for backgroundBehavior = HWBackgroundBehaviorDefault +@property (nonatomic, assign) CGFloat backgroundAlpha; // default is 0.7 +// ONLY works for backgroundBehavior = HWBackgroundBehaviorSystemVisualEffect +@property (nonatomic, strong) UIVisualEffect *visualEffect; // default is UIBlurEffectStyleLight + +// ONLY works for backgroundBehavior = HWBackgroundBehaviorCustomBlurEffect +@property (nonatomic, strong) UIColor *blurTintColor; // default is white color +@property (nonatomic, assign) CGFloat backgroundBlurRadius; // default is 10 + +- (instancetype)initWithBehavior:(HWBackgroundBehavior)backgroundBehavior; + ++ (instancetype)configWithBehavior:(HWBackgroundBehavior)backgroundBehavior; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/HWBackgroundConfig.m b/Pods/HWPanModal/Sources/View/HWBackgroundConfig.m new file mode 100644 index 0000000..7ea6ac5 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWBackgroundConfig.m @@ -0,0 +1,57 @@ +// +// HWBackgroundConfig.m +// Pods +// +// Created by heath wang on 2020/4/17. +// + +#import "HWBackgroundConfig.h" + +@implementation HWBackgroundConfig + +- (instancetype)init { + self = [super init]; + if (self) { + self.backgroundBehavior = HWBackgroundBehaviorDefault; + } + + return self; +} + +- (instancetype)initWithBehavior:(HWBackgroundBehavior)backgroundBehavior { + self = [super init]; + if (self) { + self.backgroundBehavior = backgroundBehavior; + } + + return self; +} + ++ (instancetype)configWithBehavior:(HWBackgroundBehavior)backgroundBehavior { + return [[self alloc] initWithBehavior:backgroundBehavior]; +} + +#pragma mark - Setter + +- (void)setBackgroundBehavior:(HWBackgroundBehavior)backgroundBehavior { + _backgroundBehavior = backgroundBehavior; + + switch (backgroundBehavior) { + case HWBackgroundBehaviorSystemVisualEffect: { + self.visualEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + } + break; + case HWBackgroundBehaviorCustomBlurEffect: { + self.backgroundBlurRadius = 10; + self.blurTintColor = [UIColor whiteColor]; + } + break; + default: { + self.backgroundAlpha = 0.7; + } + break; + } +} + + +@end diff --git a/Pods/HWPanModal/Sources/View/HWDimmedView.h b/Pods/HWPanModal/Sources/View/HWDimmedView.h new file mode 100644 index 0000000..1f2d3db --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWDimmedView.h @@ -0,0 +1,41 @@ +// +// HWDimmedView.h +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import +@class HWBackgroundConfig; + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, DimState) { + DimStateMax, + DimStateOff, + DimStatePercent, +}; + +typedef void(^didTap)(UITapGestureRecognizer *recognizer); + +@interface HWDimmedView : UIView + +@property (nonatomic, assign) DimState dimState; +@property (nonatomic, assign) CGFloat percent; +@property (nullable, nonatomic, copy) didTap tapBlock; +@property (nullable, nonatomic, strong) UIColor *blurTintColor; + +@property (nonatomic, readonly) HWBackgroundConfig *backgroundConfig; + +/** + * init with the max dim alpha & max blur radius. + */ +- (instancetype)initWithDimAlpha:(CGFloat)dimAlpha blurRadius:(CGFloat)blurRadius; + +- (instancetype)initWithBackgroundConfig:(HWBackgroundConfig *)backgroundConfig; + +- (void)reloadConfig:(HWBackgroundConfig *)backgroundConfig; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/HWDimmedView.m b/Pods/HWPanModal/Sources/View/HWDimmedView.m new file mode 100644 index 0000000..099214d --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWDimmedView.m @@ -0,0 +1,202 @@ +// +// HWDimmedView.m +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import "HWDimmedView.h" +#import "HWVisualEffectView.h" +#import "HWBackgroundConfig.h" + +@interface HWDimmedView () + +@property (nonatomic, strong) UIView *backgroundView; +@property (nonatomic, strong) HWVisualEffectView *blurView; +@property (nonatomic, strong) HWBackgroundConfig *backgroundConfig; + +@property (nonatomic, assign) CGFloat maxDimAlpha; +@property (nonatomic, assign) CGFloat maxBlurRadius; +@property (nonatomic, assign) CGFloat maxBlurTintAlpha; +@property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer; +@property (nonatomic, assign) BOOL isBlurMode; + +@end + +@implementation HWDimmedView + +- (instancetype)initWithDimAlpha:(CGFloat)dimAlpha blurRadius:(CGFloat)blurRadius { + self = [super initWithFrame:CGRectZero]; + if (self) { + _maxBlurRadius = blurRadius; + _maxDimAlpha = dimAlpha; + [self commonInit]; + } + + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _maxDimAlpha = 0.7; + [self commonInit]; + } + + return self; +} + +- (instancetype)initWithBackgroundConfig:(HWBackgroundConfig *)backgroundConfig { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.backgroundConfig = backgroundConfig; + _maxDimAlpha = backgroundConfig.backgroundAlpha; + _maxBlurRadius = backgroundConfig.backgroundBlurRadius; + _blurTintColor = backgroundConfig.blurTintColor; + + [self commonInit]; + } + + return self; +} + +- (void)commonInit { + _dimState = DimStateOff; + _maxBlurTintAlpha = 0.5; + // default, max alpha. + _percent = 1; + _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapView)]; + [self addGestureRecognizer:_tapGestureRecognizer]; + + [self setupView]; +} + +- (void)setupView { + self.isBlurMode = self.maxBlurRadius > 0 || self.backgroundConfig.visualEffect; + if (self.isBlurMode) { + [self addSubview:self.blurView]; + [self configBlurView]; + } else { + [self addSubview:self.backgroundView]; + } +} + +#pragma mark - layout + +- (void)layoutSubviews { + [super layoutSubviews]; + + // not call getter. + _blurView.frame = self.bounds; + _backgroundView.frame = self.bounds; +} + +#pragma mark - touch action + +- (void)didTapView { + self.tapBlock ? self.tapBlock(self.tapGestureRecognizer) : nil; +} + +#pragma mark - public method + +- (void)reloadConfig:(HWBackgroundConfig *)backgroundConfig { + + for (UIView *view in self.subviews) { + [view removeFromSuperview]; + } + + self.backgroundConfig = backgroundConfig; + _maxDimAlpha = backgroundConfig.backgroundAlpha; + _maxBlurRadius = backgroundConfig.backgroundBlurRadius; + _blurTintColor = backgroundConfig.blurTintColor; + + [self setupView]; + + DimState state = self.dimState; + self.dimState = state; +} + +#pragma mark - private method + +- (void)updateAlpha { + CGFloat alpha = 0; + CGFloat blurRadius = 0; + CGFloat blurTintAlpha = 0; + + switch (self.dimState) { + case DimStateMax:{ + alpha = self.maxDimAlpha; + blurRadius = self.maxBlurRadius; + blurTintAlpha = self.maxBlurTintAlpha; + } + break; + case DimStatePercent: { + CGFloat percent = MAX(0, MIN(1.0f, self.percent)); + alpha = self.maxDimAlpha * percent; + blurRadius = self.maxBlurRadius * percent; + blurTintAlpha = self.maxBlurTintAlpha * percent; + } + default: + break; + } + + if (self.isBlurMode) { + if (self.backgroundConfig.visualEffect) return; + + self.blurView.blurRadius = blurRadius; + self.blurView.colorTintAlpha = blurTintAlpha; + } else { + self.backgroundView.alpha = alpha; + } +} + +- (void)configBlurView { + if (self.backgroundConfig.visualEffect) { + [_blurView updateBlurEffect:self.backgroundConfig.visualEffect]; + } else { + _blurView.colorTint = [UIColor whiteColor]; + _blurView.colorTintAlpha = self.maxBlurTintAlpha; + _blurView.userInteractionEnabled = NO; + } +} + +#pragma mark - Setter + +- (void)setDimState:(DimState)dimState { + _dimState = dimState; + [self updateAlpha]; +} + +- (void)setPercent:(CGFloat)percent { + _percent = percent; + [self updateAlpha]; +} + +#pragma mark - Getter + +- (UIView *)backgroundView { + if (!_backgroundView) { + _backgroundView = [UIView new]; + _backgroundView.userInteractionEnabled = NO; + _backgroundView.alpha = 0; + _backgroundView.backgroundColor = [UIColor blackColor]; + } + return _backgroundView; +} + +- (HWVisualEffectView *)blurView { + if (!_blurView) { + _blurView = [HWVisualEffectView new]; + } + return _blurView; +} + +#pragma mark - Setter + +- (void)setBlurTintColor:(UIColor *)blurTintColor { + _blurTintColor = blurTintColor; + _blurView.colorTint = _blurTintColor; +} + + +@end diff --git a/Pods/HWPanModal/Sources/View/HWPanContainerView.h b/Pods/HWPanModal/Sources/View/HWPanContainerView.h new file mode 100644 index 0000000..82937d1 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanContainerView.h @@ -0,0 +1,34 @@ +// +// HWPanContainerView.h +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanContainerView : UIView + +/// the presented view should add to the content view. +@property (nonatomic, strong, readonly) UIView *contentView; + +- (instancetype)initWithPresentedView:(UIView *)presentedView frame:(CGRect)frame; + +- (void)updateShadow:(UIColor *)shadowColor + shadowRadius:(CGFloat)shadowRadius + shadowOffset:(CGSize)shadowOffset + shadowOpacity:(float)shadowOpacity; + +- (void)clearShadow; + +@end + +@interface UIView (PanContainer) + +@property (nullable, nonatomic, strong, readonly) HWPanContainerView *panContainerView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/HWPanContainerView.m b/Pods/HWPanModal/Sources/View/HWPanContainerView.m new file mode 100644 index 0000000..fadf43f --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanContainerView.m @@ -0,0 +1,60 @@ +// +// HWPanContainerView.m +// HWPanModal +// +// Created by heath wang on 2019/4/26. +// + +#import "HWPanContainerView.h" + +@interface HWPanContainerView () + +@property (nonatomic, strong) UIView *contentView; + +@end + +@implementation HWPanContainerView + +- (instancetype)initWithPresentedView:(UIView *)presentedView frame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _contentView = [UIView new]; + + _contentView.frame = self.bounds; + [self addSubview:_contentView]; + [_contentView addSubview:presentedView]; + } + + return self; +} + +- (void)updateShadow:(UIColor *)shadowColor shadowRadius:(CGFloat)shadowRadius shadowOffset:(CGSize)shadowOffset shadowOpacity:(float)shadowOpacity { + + self.layer.shadowColor = shadowColor.CGColor; + self.layer.shadowRadius = shadowRadius; + self.layer.shadowOffset = shadowOffset; + self.layer.shadowOpacity = shadowOpacity; +} + +- (void)clearShadow { + self.layer.shadowColor = nil; + self.layer.shadowRadius = 3.0; + self.layer.shadowOffset = CGSizeZero; + self.layer.shadowOpacity = 0.0; +} + +@end + +@implementation UIView (PanContainer) + +- (HWPanContainerView *)panContainerView { + for (UIView *subview in self.subviews) { + if ([subview isKindOfClass:HWPanContainerView.class]) { + return (HWPanContainerView *) subview; + } + } + return nil; +} + + +@end diff --git a/Pods/HWPanModal/Sources/View/HWPanIndicatorView.h b/Pods/HWPanModal/Sources/View/HWPanIndicatorView.h new file mode 100644 index 0000000..0fb8638 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanIndicatorView.h @@ -0,0 +1,19 @@ +// +// HWPanIndicatorView.h +// HWPanModal +// +// Created by heath wang on 2019/5/16. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanIndicatorView : UIView + +@property (nonnull, nonatomic, strong) UIColor *indicatorColor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/HWPanIndicatorView.m b/Pods/HWPanModal/Sources/View/HWPanIndicatorView.m new file mode 100644 index 0000000..9ce5fb8 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanIndicatorView.m @@ -0,0 +1,114 @@ +// +// HWPanIndicatorView.m +// HWPanModal +// +// Created by heath wang on 2019/5/16. +// + +#import "UIView+HW_Frame.h" +#import + +@interface HWPanIndicatorView () + +@property (nonatomic, strong) UIView *leftView; +@property (nonatomic, strong) UIView *rightView; + +@property (nonatomic, assign) HWIndicatorState state; + +@end + +@implementation HWPanIndicatorView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + [self addSubview:self.leftView]; + [self addSubview:self.rightView]; + self.indicatorColor = [UIColor colorWithRed:0.792 green:0.788 blue:0.812 alpha:1.00]; + } + + return self; +} + +- (void)animate:(void (^)(void))animations { + [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseOut animations:animations completion:^(BOOL finished) { + + }]; +} + +#pragma mark - HWPanModalIndicatorProtocol + +- (void)didChangeToState:(HWIndicatorState)state { + self.state = state; +} + +- (CGSize)indicatorSize { + return CGSizeMake(34, 13); +} + +- (void)setupSubviews { + CGSize size = [self indicatorSize]; + self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, size.width, size.height); + CGFloat height = 5; + CGFloat correction = height / 2; + + self.leftView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame) / 2 + correction, height); + self.leftView.hw_centerY = self.hw_height / 2; + self.leftView.layer.cornerRadius = MIN(self.leftView.hw_width, self.leftView.hw_height) / 2; + + self.rightView.frame = CGRectMake(CGRectGetWidth(self.frame) / 2 - correction, 0, CGRectGetWidth(self.frame) / 2 + correction, height); + self.rightView.hw_centerY = self.hw_height / 2; + self.rightView.layer.cornerRadius = MIN(self.rightView.hw_width, self.rightView.hw_height) / 2; + +} + +#pragma mark - Getter + +- (UIView *)leftView { + if (!_leftView) { + _leftView = [UIView new]; + } + return _leftView; +} + +- (UIView *)rightView { + if (!_rightView) { + _rightView = [UIView new]; + } + return _rightView; +} + + +#pragma mark - Setter + +- (void)setIndicatorColor:(UIColor *)indicatorColor { + _indicatorColor = indicatorColor; + self.leftView.backgroundColor = indicatorColor; + self.rightView.backgroundColor = indicatorColor; +} + +- (void)setState:(HWIndicatorState)state { + + _state = state; + + switch (state) { + case HWIndicatorStateNormal: { + CGFloat angle = 20 * M_PI / 180; + [self animate:^{ + self.leftView.transform = CGAffineTransformMakeRotation(angle); + self.rightView.transform = CGAffineTransformMakeRotation(-angle); + }]; + } + break; + case HWIndicatorStatePullDown: { + [self animate:^{ + self.leftView.transform = CGAffineTransformIdentity; + self.rightView.transform = CGAffineTransformIdentity; + }]; + } + break; + } +} + +@end diff --git a/Pods/HWPanModal/Sources/View/HWPanModalIndicatorProtocol.h b/Pods/HWPanModal/Sources/View/HWPanModalIndicatorProtocol.h new file mode 100644 index 0000000..67a5a29 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanModalIndicatorProtocol.h @@ -0,0 +1,36 @@ +// +// HWPanModalIndicatorProtocol.h +// HWPanModal +// +// Created by heath wang on 2019/8/9. +// + +typedef NS_ENUM(NSUInteger, HWIndicatorState) { + HWIndicatorStateNormal NS_SWIFT_NAME(normal), // origin state + HWIndicatorStatePullDown NS_SWIFT_NAME(pull), // drag down state +}; + +static CGFloat const kIndicatorYOffset = 5; + +@protocol HWPanModalIndicatorProtocol + +/** + * When user drags, the state will change. + * You can change your UI here. + * @param state The state when drag changed. + */ +- (void)didChangeToState:(HWIndicatorState)state; + +/** + * Tell the size of the indicator. + */ +- (CGSize)indicatorSize; + +/** + * You can layout your UI here if you need. + * This method called when indicator added to super view + */ +- (void)setupSubviews; + +@end + diff --git a/Pods/HWPanModal/Sources/View/HWPanModalShadow.h b/Pods/HWPanModal/Sources/View/HWPanModalShadow.h new file mode 100644 index 0000000..ab5604c --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanModalShadow.h @@ -0,0 +1,26 @@ +// +// HWPanModalShadow.h +// Pods +// +// Created by hb on 2023/8/3. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanModalShadow : NSObject + +@property (nonatomic, strong) UIColor *shadowColor; +@property (nonatomic, assign) CGFloat shadowRadius; +@property (nonatomic, assign) CGSize shadowOffset; +@property (nonatomic, assign) CGFloat shadowOpacity; + +- (instancetype)initWithColor:(UIColor *)shadowColor shadowRadius:(CGFloat)shadowRadius shadowOffset:(CGSize)shadowOffset shadowOpacity:(CGFloat)shadowOpacity; + ++ (instancetype)panModalShadowNil; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/HWPanModalShadow.m b/Pods/HWPanModal/Sources/View/HWPanModalShadow.m new file mode 100644 index 0000000..efbbbd8 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWPanModalShadow.m @@ -0,0 +1,28 @@ +// +// HWPanModalShadow.m +// Pods +// +// Created by hb on 2023/8/3. +// + +#import "HWPanModalShadow.h" + +@implementation HWPanModalShadow + +- (instancetype)initWithColor:(UIColor *)shadowColor shadowRadius:(CGFloat)shadowRadius shadowOffset:(CGSize)shadowOffset shadowOpacity:(CGFloat)shadowOpacity { + self = [super init]; + if (self) { + _shadowColor = shadowColor; + _shadowRadius = shadowRadius; + _shadowOffset = shadowOffset; + _shadowOpacity = shadowOpacity; + } + + return self; +} + ++ (instancetype)panModalShadowNil { + return [[HWPanModalShadow alloc] initWithColor:[UIColor clearColor] shadowRadius:0 shadowOffset:CGSizeZero shadowOpacity:0]; +} + +@end diff --git a/Pods/HWPanModal/Sources/View/HWVisualEffectView.h b/Pods/HWPanModal/Sources/View/HWVisualEffectView.h new file mode 100644 index 0000000..b730ae4 --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWVisualEffectView.h @@ -0,0 +1,39 @@ +// +// HWVisualEffectView.h +// HWPanModal +// +// Created by heath wang on 2019/6/14. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HWVisualEffectView : UIVisualEffectView + +/** + * tint color + * default is nil + */ +@property (nullable, nonatomic, strong) UIColor *colorTint; +/** + * tint color alpha + * default is 0.0 + */ +@property (nonatomic, assign) CGFloat colorTintAlpha; +/** + * blur radius, change it to make blur affect + * default is 0.0 + */ +@property (nonatomic, assign) CGFloat blurRadius; +/** + * scale factor. + * default is 1.0 + */ +@property (nonatomic, assign) CGFloat scale; + +- (void)updateBlurEffect:(UIVisualEffect *)effect; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/HWVisualEffectView.m b/Pods/HWPanModal/Sources/View/HWVisualEffectView.m new file mode 100644 index 0000000..2e9473d --- /dev/null +++ b/Pods/HWPanModal/Sources/View/HWVisualEffectView.m @@ -0,0 +1,111 @@ +// +// HWVisualEffectView.m +// HWPanModal +// +// Created by heath wang on 2019/6/14. +// + +#import "HWVisualEffectView.h" + +NSString * const kInternalCustomBlurEffect = @"_UICustomBlurEffect"; +NSString * const kHWBlurEffectColorTintKey = @"colorTint"; +NSString * const kHWBlurEffectColorTintAlphaKey = @"colorTintAlpha"; +NSString * const kHWBlurEffectBlurRadiusKey = @"blurRadius"; +NSString * const kHWBlurEffectScaleKey = @"scale"; + +@interface HWVisualEffectView () + +@property (nonatomic, strong) UIVisualEffect *blurEffect; + +@end + +@implementation HWVisualEffectView + +@synthesize colorTint = _colorTint; +@synthesize colorTintAlpha = _colorTintAlpha; +@synthesize blurRadius = _blurRadius; +@synthesize scale = _scale; + +#pragma mark - init + +- (instancetype)initWithEffect:(UIVisualEffect *)effect { + self = [super initWithEffect:effect]; + if (self) { + self.scale = 1; + } + return self; +} + +#pragma mark - public method + +- (void)updateBlurEffect:(UIVisualEffect *)effect { + self.blurEffect = effect; + self.effect = self.blurEffect; +} + +#pragma mark - private method + +- (nullable id)__valueForKey:(NSString *)key { + if (![NSStringFromClass(self.blurEffect.class) isEqualToString:kInternalCustomBlurEffect]) { + return @(0); + } + return [self.blurEffect valueForKey:key]; +} + +- (void)__setValue:(id)value forKey:(NSString *)key { + if (![NSStringFromClass(self.blurEffect.class) isEqualToString:kInternalCustomBlurEffect]) { + self.effect = self.blurEffect; + return; + } + [self.blurEffect setValue:value forKey:key]; + self.effect = self.blurEffect; +} + +#pragma mark - Getter & Setter + +- (UIVisualEffect *)blurEffect { + if (!_blurEffect) { + if (NSClassFromString(kInternalCustomBlurEffect)) { + _blurEffect = (UIBlurEffect *)[NSClassFromString(@"_UICustomBlurEffect") new]; + } else { + _blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + } + } + + return _blurEffect; +} + +- (UIColor *)colorTint { + return [self __valueForKey:kHWBlurEffectColorTintKey]; +} + +- (void)setColorTint:(UIColor *)colorTint { + [self __setValue:colorTint forKey:kHWBlurEffectColorTintKey]; +} + +- (CGFloat)colorTintAlpha { + return ((NSNumber *)[self __valueForKey:kHWBlurEffectColorTintAlphaKey]).floatValue; +} + +- (void)setColorTintAlpha:(CGFloat)colorTintAlpha { + [self __setValue:@(colorTintAlpha) forKey:kHWBlurEffectColorTintAlphaKey]; +} + +- (CGFloat)blurRadius { + return ((NSNumber *)[self __valueForKey:kHWBlurEffectBlurRadiusKey]).floatValue; +} + +- (void)setBlurRadius:(CGFloat)blurRadius { + [self __setValue:@(blurRadius) forKey:kHWBlurEffectBlurRadiusKey]; +} + +- (CGFloat)scale { + return ((NSNumber *)[self __valueForKey:kHWBlurEffectScaleKey]).floatValue; +} + +- (void)setScale:(CGFloat)scale { + [self __setValue:@(scale) forKey:kHWBlurEffectScaleKey]; +} + + +@end diff --git a/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.h b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.h new file mode 100644 index 0000000..312097f --- /dev/null +++ b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.h @@ -0,0 +1,39 @@ +// +// HWPanModalContainerView.h +// Pods +// +// Created by heath wang on 2019/10/17. +// + +#import +#import + +@class HWPanModalContentView; +@class HWDimmedView; +@class HWPanContainerView; + +NS_ASSUME_NONNULL_BEGIN + +@interface HWPanModalContainerView : UIView + +@property (nonatomic, readonly) HWDimmedView *backgroundView; +@property (readonly) HWPanContainerView *panContainerView; +@property (nonatomic, readonly) PresentationState currentPresentationState; + +- (instancetype)initWithPresentingView:(UIView *)presentingView contentView:(HWPanModalContentView *)contentView; + +- (void)show; + +- (void)dismissAnimated:(BOOL)flag completion:(void (^)(void))completion; + +- (void)setNeedsLayoutUpdate; + +- (void)updateUserHitBehavior; + +- (void)transitionToState:(PresentationState)state animated:(BOOL)animated; + +- (void)setScrollableContentOffset:(CGPoint)offset animated:(BOOL)animated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.m b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.m new file mode 100644 index 0000000..7fda9df --- /dev/null +++ b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.m @@ -0,0 +1,546 @@ +// +// HWPanModalContainerView.m +// Pods +// +// Created by heath wang on 2019/10/17. +// + +#import "HWPanModalContainerView.h" +#import "HWPanModalContentView.h" +#import "HWPanModalPresentableHandler.h" +#import "HWDimmedView.h" +#import "HWPanContainerView.h" +#import "UIView+HW_Frame.h" +#import "HWPanIndicatorView.h" +#import "HWPanModalAnimator.h" + +@interface HWPanModalContainerView () + +@property (nonatomic, strong) HWPanModalContentView *contentView; +@property (nonatomic, weak) UIView *presentingView; + +@property (nonatomic, strong) HWPanModalPresentableHandler *handler; + +// 判断弹出的view是否在做动画 +@property (nonatomic, assign) BOOL isPresentedViewAnimating; +@property (nonatomic, assign) PresentationState currentPresentationState; +@property (nonatomic, assign) BOOL isPresenting; +@property (nonatomic, assign) BOOL isDismissing; + +// view +@property (nonatomic, strong) HWDimmedView *backgroundView; +@property (nonatomic, strong) HWPanContainerView *panContainerView; +@property (nonatomic, strong) UIView *dragIndicatorView; + +@property (nonatomic, copy) void(^animationBlock)(void); + +@property (nullable, nonatomic, strong) UISelectionFeedbackGenerator *feedbackGenerator API_AVAILABLE(ios(10.0)); + +@end + +@implementation HWPanModalContainerView + +- (instancetype)initWithPresentingView:(UIView *)presentingView contentView:(HWPanModalContentView *)contentView { + self = [super init]; + if (self) { + _presentingView = presentingView; + _contentView = contentView; + } + + return self; +} + +- (void)show { + [self prepare]; + [self presentAnimationWillBegin]; + [self beginPresentAnimation]; +} + +- (void)dismissAnimated:(BOOL)flag completion:(void (^)(void))completion { + if (flag) { + self.animationBlock = completion; + [self dismiss:NO mode:PanModalInteractiveModeNone]; + } else { + self.isDismissing = YES; + [[self presentable] panModalWillDismiss]; + [self removeFromSuperview]; + [[self presentable] panModalDidDismissed]; + + completion ? completion() : nil; + self.isDismissing = NO; + } +} + +- (void)prepare { + [self.presentingView addSubview:self]; + self.frame = self.presentingView.bounds; + + _handler = [[HWPanModalPresentableHandler alloc] initWithPresentable:self.contentView]; + _handler.delegate = self; + _handler.dataSource = self; + + if (@available(iOS 10.0, *)) { + _feedbackGenerator = [UISelectionFeedbackGenerator new]; + [_feedbackGenerator prepare]; + } else { + // Fallback on earlier versions + } +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + [self.superview removeObserver:self forKeyPath:@"frame"]; + [newSuperview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil]; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if (object == self.presentingView && [keyPath isEqualToString:@"frame"]) { + self.frame = self.presentingView.bounds; + [self setNeedsLayoutUpdate]; + [self updateDragIndicatorViewFrame]; + [self.contentView hw_panModalTransitionTo:self.contentView.hw_presentationState animated:NO]; + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +- (void)presentAnimationWillBegin { + [[self presentable] panModalTransitionWillBegin]; + [self layoutBackgroundView]; + + if ([[self presentable] originPresentationState] == PresentationStateLong) { + self.currentPresentationState = PresentationStateLong; + } else if ([[self presentable] originPresentationState] == PresentationStateMedium) { + self.currentPresentationState = PresentationStateMedium; + } + + [self addSubview:self.panContainerView]; + [self layoutPresentedView]; + + [self.handler configureScrollViewInsets]; + [[self presentable] presentedViewDidMoveToSuperView]; +} + +- (void)beginPresentAnimation { + self.isPresenting = YES; + CGFloat yPos = self.contentView.shortFormYPos; + if ([[self presentable] originPresentationState] == PresentationStateLong) { + yPos = self.contentView.longFormYPos; + } else if ([[self presentable] originPresentationState] == PresentationStateMedium) { + yPos = self.contentView.mediumFormYPos; + } + + // refresh layout + [self configureViewLayout]; + [self adjustPresentedViewFrame]; + + self.panContainerView.hw_top = self.hw_height; + + if ([[self presentable] isHapticFeedbackEnabled]) { + if (@available(iOS 10.0, *)) { + [self.feedbackGenerator selectionChanged]; + } + } + + [HWPanModalAnimator animate:^{ + self.panContainerView.hw_top = yPos; + self.backgroundView.dimState = DimStateMax; + } config:[self presentable] completion:^(BOOL completion) { + self.isPresenting = NO; + [[self presentable] panModalTransitionDidFinish]; + + if (@available(iOS 10.0, *)) { + self.feedbackGenerator = nil; + } + }]; + +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self configureViewLayout]; +} + +#pragma mark - public method + +- (void)setNeedsLayoutUpdate { + + [self configureViewLayout]; + [self updateBackgroundColor]; + [self.handler observeScrollable]; + [self adjustPresentedViewFrame]; + [self.handler configureScrollViewInsets]; + + [self updateContainerViewShadow]; + [self updateDragIndicatorView]; + [self updateRoundedCorners]; +} + +- (void)updateUserHitBehavior { + [self checkBackgroundViewEventPass]; + [self checkPanGestureRecognizer]; +} + +- (void)transitionToState:(PresentationState)state animated:(BOOL)animated { + + if (![self.presentable shouldTransitionToState:state]) return; + + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + [self.presentable willTransitionToState:state]; + + switch (state) { + case PresentationStateLong: { + [self snapToYPos:self.handler.longFormYPosition animated:animated]; + } + break; + case PresentationStateMedium: { + [self snapToYPos:self.handler.mediumFormYPosition animated:animated]; + } + break; + case PresentationStateShort: { + [self snapToYPos:self.handler.shortFormYPosition animated:animated]; + } + break; + default: + break; + } + self.currentPresentationState = state; + [[self presentable] didChangeTransitionToState:state]; +} + +- (void)setScrollableContentOffset:(CGPoint)offset animated:(BOOL)animated { + [self.handler setScrollableContentOffset:offset animated:animated]; +} + +#pragma mark - layout + +- (void)adjustPresentedViewFrame { + CGRect frame = self.frame; + CGSize size = CGSizeMake(CGRectGetWidth(frame), CGRectGetHeight(frame) - self.handler.anchoredYPosition); + + self.panContainerView.hw_size = frame.size; + self.panContainerView.contentView.frame = CGRectMake(0, 0, size.width, size.height); + self.contentView.frame = self.panContainerView.contentView.bounds; + [self.contentView setNeedsLayout]; + [self.contentView layoutIfNeeded]; +} + +- (void)configureViewLayout { + + [self.handler configureViewLayout]; + self.userInteractionEnabled = [[self presentable] isUserInteractionEnabled]; +} + +- (void)layoutBackgroundView { + [self addSubview:self.backgroundView]; + [self updateBackgroundColor]; + self.backgroundView.translatesAutoresizingMaskIntoConstraints = NO; + + NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[backgroundView]|" options:0 metrics:nil views:@{@"backgroundView": self.backgroundView}]; + NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[backgroundView]|" options:0 metrics:nil views:@{@"backgroundView": self.backgroundView}]; + [NSLayoutConstraint activateConstraints:hCons]; + [NSLayoutConstraint activateConstraints:vCons]; +} + +- (void)updateBackgroundColor { + self.backgroundView.blurTintColor = [self.presentable backgroundConfig].blurTintColor; +} + +- (void)layoutPresentedView { + if (!self.presentable) + return; + + self.handler.presentedView = self.panContainerView; + + if ([[self presentable] allowsTouchEventsPassingThroughTransitionView]) { + [self.panContainerView addGestureRecognizer:self.handler.panGestureRecognizer]; + } else { + [self addGestureRecognizer:self.handler.panGestureRecognizer]; + } + + [self setNeedsLayoutUpdate]; + [self adjustPanContainerBackgroundColor]; +} + +- (void)adjustPanContainerBackgroundColor { + self.panContainerView.contentView.backgroundColor = self.contentView.backgroundColor ? : [self.presentable panScrollable].backgroundColor; +} + +- (void)updateDragIndicatorView { + if ([self.presentable showDragIndicator]) { + [self addDragIndicatorView]; + } else { + self.dragIndicatorView.hidden = YES; + } +} + +- (void)addDragIndicatorView { + // if has been add, won't update it. + self.dragIndicatorView.hidden = NO; + + if (self.dragIndicatorView.superview == self.panContainerView) { + [self updateDragIndicatorViewFrame]; + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; + return; + } + + self.handler.dragIndicatorView = self.dragIndicatorView; + [self.panContainerView addSubview:self.dragIndicatorView]; + [self updateDragIndicatorViewFrame]; + + [self.dragIndicatorView setupSubviews]; + [self.dragIndicatorView didChangeToState:HWIndicatorStateNormal]; +} + +- (void)updateDragIndicatorViewFrame { + CGSize indicatorSize = [self.dragIndicatorView indicatorSize]; + self.dragIndicatorView.frame = CGRectMake((self.panContainerView.hw_width - indicatorSize.width) / 2, -kIndicatorYOffset - indicatorSize.height, indicatorSize.width, indicatorSize.height); +} + +- (void)updateContainerViewShadow { + HWPanModalShadow *shadow = [[self presentable] contentShadow]; + if (shadow.shadowColor) { + [self.panContainerView updateShadow:shadow.shadowColor shadowRadius:shadow.shadowRadius shadowOffset:shadow.shadowOffset shadowOpacity:shadow.shadowOpacity]; + } else { + [self.panContainerView clearShadow]; + } +} + +- (void)updateRoundedCorners { + if ([self.presentable shouldRoundTopCorners]) { + [self addRoundedCornersToView:self.panContainerView.contentView]; + } else { + [self resetRoundedCornersToView:self.panContainerView.contentView]; + } +} + +- (void)addRoundedCornersToView:(UIView *)view { + CGFloat radius = [self.presentable cornerRadius]; + + UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopRight | UIRectCornerTopLeft cornerRadii:CGSizeMake(radius, radius)]; + + CAShapeLayer *mask = [CAShapeLayer new]; + mask.path = bezierPath.CGPath; + view.layer.mask = mask; + + // 提高性能 + view.layer.shouldRasterize = YES; + view.layer.rasterizationScale = [UIScreen mainScreen].scale; +} + +- (void)resetRoundedCornersToView:(UIView *)view { + view.layer.mask = nil; + view.layer.shouldRasterize = NO; +} + +- (void)snapToYPos:(CGFloat)yPos animated:(BOOL)animated { + + if (animated) { + [HWPanModalAnimator animate:^{ + self.isPresentedViewAnimating = YES; + [self adjustToYPos:yPos]; + } config:self.presentable completion:^(BOOL completion) { + self.isPresentedViewAnimating = NO; + }]; + } else { + [self adjustToYPos:yPos]; + } + +} + +- (void)adjustToYPos:(CGFloat)yPos { + self.panContainerView.hw_top = MAX(yPos, self.handler.anchoredYPosition); + + // change dim background starting from shortFormYPosition. + if (self.panContainerView.frame.origin.y >= self.handler.shortFormYPosition) { + + CGFloat yDistanceFromShortForm = self.panContainerView.frame.origin.y - self.handler.shortFormYPosition; + CGFloat bottomHeight = self.hw_height - self.handler.shortFormYPosition; + CGFloat percent = yDistanceFromShortForm / bottomHeight; + self.backgroundView.dimState = DimStatePercent; + self.backgroundView.percent = 1 - percent; + + [self.presentable panModalGestureRecognizer:self.handler.panGestureRecognizer dismissPercent:MIN(percent, 1)]; + + } else { + self.backgroundView.dimState = DimStateMax; + } +} + +#pragma mark - HWPanModalPresentableHandlerDelegate + +- (void)adjustPresentableYPos:(CGFloat)yPos { + [self adjustToYPos:yPos]; +} + +- (void)presentableTransitionToState:(PresentationState)state { + [self transitionToState:state animated:YES]; +} + +- (PresentationState)getCurrentPresentationState { + return self.currentPresentationState; +} + +- (void)dismiss:(BOOL)isInteractive mode:(PanModalInteractiveMode)mode { + self.handler.panGestureRecognizer.enabled = NO; + self.isDismissing = YES; + + [[self presentable] panModalWillDismiss]; + + [HWPanModalAnimator animate:^{ + self.panContainerView.hw_top = CGRectGetHeight(self.bounds); + self.backgroundView.dimState = DimStateOff; + self.dragIndicatorView.alpha = 0; + } config:[self presentable] completion:^(BOOL completion) { + [self removeFromSuperview]; + [[self presentable] panModalDidDismissed]; + self.animationBlock ? self.animationBlock() : nil; + self.isDismissing = NO; + }]; + +} + +#pragma mark - HWPanModalPresentableHandlerDataSource + +- (CGSize)containerSize { + return self.presentingView.bounds.size; +} + +- (BOOL)isBeingDismissed { + return self.isDismissing; +} + +- (BOOL)isBeingPresented { + return self.isPresenting; +} + +- (BOOL)isFormPositionAnimating { + return self.isPresentedViewAnimating; +} + +- (BOOL)isPresentedViewAnchored { + + if (![[self presentable] shouldRespondToPanModalGestureRecognizer:self.handler.panGestureRecognizer]) { + return YES; + } + + if (!self.isPresentedViewAnimating && self.handler.extendsPanScrolling && (CGRectGetMinY(self.panContainerView.frame) <= self.handler.anchoredYPosition || HW_TWO_FLOAT_IS_EQUAL(CGRectGetMinY(self.panContainerView.frame), self.handler.anchoredYPosition))) { + return YES; + } + return NO; +} + +#pragma mark - event handle + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + + if (!self.userInteractionEnabled || self.hidden || self.alpha < 0.01) { + return nil; + } + + if (![self pointInside:point withEvent:event]) { + return nil; + } + + BOOL eventThrough = [[self presentable] allowsTouchEventsPassingThroughTransitionView]; + if (eventThrough) { + CGPoint convertedPoint = [self.panContainerView convertPoint:point fromView:self]; + if (CGRectGetWidth(self.panContainerView.frame) >= convertedPoint.x && + convertedPoint.x > 0 && + CGRectGetHeight(self.panContainerView.frame) >= convertedPoint.y && + convertedPoint.y > 0) { + return [super hitTest:point withEvent:event]; + } else { + return nil; + } + } else { + return [super hitTest:point withEvent:event]; + } +} + +- (void)checkBackgroundViewEventPass { + if ([[self presentable] allowsTouchEventsPassingThroughTransitionView]) { + self.backgroundView.userInteractionEnabled = NO; + self.backgroundView.tapBlock = nil; + } else { + self.backgroundView.userInteractionEnabled = YES; + __weak typeof(self) wkSelf = self; + self.backgroundView.tapBlock = ^(UITapGestureRecognizer *recognizer) { + if ([[wkSelf presentable] allowsTapBackgroundToDismiss]) { + [wkSelf dismiss:NO mode:PanModalInteractiveModeNone]; + } + }; + } +} + +- (void)checkPanGestureRecognizer { + if ([[self presentable] allowsTouchEventsPassingThroughTransitionView]) { + [self removeGestureRecognizer:self.handler.panGestureRecognizer]; + [self.panContainerView addGestureRecognizer:self.handler.panGestureRecognizer]; + } else { + [self.panContainerView removeGestureRecognizer:self.handler.panGestureRecognizer]; + [self addGestureRecognizer:self.handler.panGestureRecognizer]; + } +} + +#pragma mark - getter + +- (id)presentable { + if ([self.contentView conformsToProtocol:@protocol(HWPanModalPresentable)]) { + return self.contentView; + } + return nil; +} + +- (HWDimmedView *)backgroundView { + if (!_backgroundView) { + if (self.presentable) { + _backgroundView = [[HWDimmedView alloc] initWithBackgroundConfig:[self.presentable backgroundConfig]]; + } else { + _backgroundView = [[HWDimmedView alloc] init]; + } + + if ([[self presentable] allowsTouchEventsPassingThroughTransitionView]) { + _backgroundView.userInteractionEnabled = NO; + } else { + __weak typeof(self) wkSelf = self; + _backgroundView.tapBlock = ^(UITapGestureRecognizer *recognizer) { + if ([[wkSelf presentable] allowsTapBackgroundToDismiss]) { + [wkSelf dismiss:NO mode:PanModalInteractiveModeNone]; + } + }; + } + + } + + return _backgroundView; +} + +- (HWPanContainerView *)panContainerView { + if (!_panContainerView) { + _panContainerView = [[HWPanContainerView alloc] initWithPresentedView:self.contentView frame:self.bounds]; + } + + return _panContainerView; +} + +- (UIView *)dragIndicatorView { + + if (!_dragIndicatorView) { + if ([self presentable] && + [[self presentable] respondsToSelector:@selector(customIndicatorView)] && + [[self presentable] customIndicatorView] != nil) { + _dragIndicatorView = [[self presentable] customIndicatorView]; + // set the indicator size first in case `setupSubviews` can Not get the right size. + _dragIndicatorView.hw_size = [[[self presentable] customIndicatorView] indicatorSize]; + } else { + _dragIndicatorView = [HWPanIndicatorView new]; + } + } + + return _dragIndicatorView; +} + +@end diff --git a/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContentView.h b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContentView.h new file mode 100644 index 0000000..be4fafe --- /dev/null +++ b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContentView.h @@ -0,0 +1,36 @@ +// +// HWPanModalContentView.h +// Pods +// +// Created by heath wang on 2019/10/17. +// + +#import +#import +#import +#import +#import + +@class HWPanModalContainerView; + +NS_ASSUME_NONNULL_BEGIN + +/// when use `HWPanModalContentView`, you should take care of the safe area by yourself. +@interface HWPanModalContentView : UIView + +/** + * present in the target view + * @param view The view which present to. If the view is nil, will use UIWindow's keyWindow. + */ +- (void)presentInView:(nullable UIView *)view; + +/** + * call this method to dismiss contentView directly. + * @param flag should animate flag + * @param completion dismiss completion block + */ +- (void)dismissAnimated:(BOOL)flag completion:(void (^)(void))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContentView.m b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContentView.m new file mode 100644 index 0000000..89200eb --- /dev/null +++ b/Pods/HWPanModal/Sources/View/PanModal/HWPanModalContentView.m @@ -0,0 +1,414 @@ +// +// HWPanModalContentView.m +// Pods +// +// Created by heath wang on 2019/10/17. +// + +#import "HWPanModalContentView.h" +#import "HWPanModalContainerView.h" + +@interface HWPanModalContentView () + +@property (nonatomic, weak) HWPanModalContainerView *containerView; + +@end + +@implementation HWPanModalContentView + +#pragma mark - public method + +- (void)presentInView:(UIView *)view { + if (!view) { + view = [self findKeyWindow]; + } + HWPanModalContainerView *containerView = [[HWPanModalContainerView alloc] initWithPresentingView:view contentView:self]; + [containerView show]; +} + +- (void)dismissAnimated:(BOOL)flag completion:(void (^)(void))completion { + [self.containerView dismissAnimated:flag completion:completion]; +} + +#pragma mark - HWPanModalPresentationUpdateProtocol + +- (void)hw_panModalTransitionTo:(PresentationState)state { + [self.containerView transitionToState:state animated:YES]; +} + +- (void)hw_panModalSetContentOffset:(CGPoint)offset { + [self.containerView setScrollableContentOffset:offset animated:YES]; +} + +- (void)hw_panModalSetNeedsLayoutUpdate { + [self.containerView setNeedsLayoutUpdate]; +} + +- (void)hw_panModalUpdateUserHitBehavior { + [self.containerView updateUserHitBehavior]; +} + +- (void)hw_panModalTransitionTo:(PresentationState)state animated:(BOOL)animated { + [self.containerView transitionToState:state animated:animated]; +} + +- (void)hw_panModalSetContentOffset:(CGPoint)offset animated:(BOOL)animated { + [self.containerView setScrollableContentOffset:offset animated:animated]; +} + +- (void)hw_dismissAnimated:(BOOL)animated completion:(void (^)(void))completion { + [self dismissAnimated:animated completion:completion]; +} + +- (HWDimmedView *)hw_dimmedView { + return self.containerView.backgroundView; +} + +- (UIView *)hw_rootContainerView { + return self.containerView; +} + +- (UIView *)hw_contentView { + return (UIView *)self.containerView.panContainerView; +} + +- (PresentationState)hw_presentationState { + return self.containerView.currentPresentationState; +} + +#pragma mark - HWPanModalPresentable + +- (UIScrollView *)panScrollable { + return nil; +} + +- (CGFloat)topOffset { + return self.topLayoutOffset + 21.f; +} + +- (PanModalHeight)shortFormHeight { + return [self longFormHeight]; +} + +- (PanModalHeight)mediumFormHeight { + return [self longFormHeight]; +} + +- (PanModalHeight)longFormHeight { + if ([self panScrollable]) { + [[self panScrollable] layoutIfNeeded]; + return PanModalHeightMake(PanModalHeightTypeContent, MAX([self panScrollable].contentSize.height, [self panScrollable].bounds.size.height)); + } else { + return PanModalHeightMake(PanModalHeightTypeMax, 0); + } +} + +- (PresentationState)originPresentationState { + return PresentationStateShort; +} + +- (CGFloat)springDamping { + return 0.8; +} + +- (NSTimeInterval)transitionDuration { + return 0.5; +} + +- (NSTimeInterval)dismissalDuration { + return [self transitionDuration]; +} + +- (UIViewAnimationOptions)transitionAnimationOptions { + return UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState; +} + +- (CGFloat)backgroundAlpha { + return 0.7; +} + +- (CGFloat)backgroundBlurRadius { + return 0; +} + +- (nonnull UIColor *)backgroundBlurColor { + return [UIColor whiteColor]; +} + +- (HWBackgroundConfig *)backgroundConfig { + return [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault]; +} + +- (UIEdgeInsets)scrollIndicatorInsets { + CGFloat top = [self shouldRoundTopCorners] ? [self cornerRadius] : 0; + return UIEdgeInsetsMake(top, 0, self.bottomLayoutOffset, 0); +} + +- (BOOL)showsScrollableVerticalScrollIndicator { + return YES; +} + +- (BOOL)shouldAutoSetPanScrollContentInset { + return YES; +} + +- (BOOL)anchorModalToLongForm { + return YES; +} + +- (BOOL)allowsExtendedPanScrolling { + if ([self panScrollable]) { + UIScrollView *scrollable = [self panScrollable]; + [scrollable layoutIfNeeded]; + return scrollable.contentSize.height > (scrollable.frame.size.height - self.bottomLayoutOffset); + } else { + return NO; + } +} + +- (BOOL)allowsDragToDismiss { + return YES; +} + +- (CGFloat)minVerticalVelocityToTriggerDismiss { + return 300; +} + +- (BOOL)allowsTapBackgroundToDismiss { + return YES; +} + +- (BOOL)allowsPullDownWhenShortState { + return YES; +} + +- (BOOL)allowScreenEdgeInteractive { + return NO; +} + +- (CGFloat)maxAllowedDistanceToLeftScreenEdgeForPanInteraction { + return 0; +} + +- (CGFloat)minHorizontalVelocityToTriggerScreenEdgeDismiss { + return 500; +} + +- (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle { + return PresentingViewControllerAnimationStyleNone; +} + +- (BOOL)shouldAnimatePresentingVC { + return NO; +} + +- (id )customPresentingVCAnimation { + return nil; +} + +- (BOOL)isPanScrollEnabled { + return YES; +} + +- (BOOL)isUserInteractionEnabled { + return YES; +} + +- (BOOL)isHapticFeedbackEnabled { + return YES; +} + +- (BOOL)allowsTouchEventsPassingThroughTransitionView { + return NO; +} + +- (BOOL)shouldRoundTopCorners { + return YES; +} + +- (CGFloat)cornerRadius { + return 8; +} + +- (HWPanModalShadow *)contentShadow { + return [HWPanModalShadow panModalShadowNil]; +} + +- (BOOL)showDragIndicator { + if ([self allowsTouchEventsPassingThroughTransitionView]) { + return NO; + } + return [self shouldRoundTopCorners]; +} + +- (nullable UIView *)customIndicatorView { + return nil; +} + +- (BOOL)isAutoHandleKeyboardEnabled { + return YES; +} + +- (CGFloat)keyboardOffsetFromInputView { + return 5; +} + +- (BOOL)shouldRespondToPanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + return YES; +} + +- (void)willRespondToPanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + +} + +- (void)didRespondToPanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + +} + +- (void)didEndRespondToPanModalGestureRecognizer:(nonnull UIPanGestureRecognizer *)panGestureRecognizer { + +} + +- (BOOL)shouldPrioritizePanModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer { + return NO; +} + +- (BOOL)shouldTransitionToState:(PresentationState)state { + return YES; +} + +- (void)willTransitionToState:(PresentationState)state { + +} + +- (void)didChangeTransitionToState:(PresentationState)state { + +} + +- (void)panModalGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer dismissPercent:(CGFloat)percent { + +} + +- (void)panModalWillDismiss { + +} + +- (void)panModalDidDismissed { + +} + +- (void)panModalTransitionWillBegin { + +} + +- (void)panModalTransitionDidFinish { + +} + +- (void)presentedViewDidMoveToSuperView { + +} + +- (BOOL)shouldEnableAppearanceTransition { + return YES; +} + +#pragma mark - HWPanModalPresentableLayoutProtocol + +- (CGFloat)topLayoutOffset { + return 0; +} + +- (CGFloat)bottomLayoutOffset { + return 0; +} + +- (CGFloat)shortFormYPos { + CGFloat shortFormYPos = [self topMarginFromPanModalHeight:[self shortFormHeight]] + [self topOffset]; + return MAX(shortFormYPos, self.longFormYPos); +} + +- (CGFloat)mediumFormYPos { + CGFloat mediumFormYPos = [self topMarginFromPanModalHeight:[self mediumFormHeight]] + [self topOffset]; + return MAX(mediumFormYPos, self.longFormYPos); +} + +- (CGFloat)longFormYPos { + CGFloat longFrom = MAX([self topMarginFromPanModalHeight:[self longFormHeight]], [self topMarginFromPanModalHeight:PanModalHeightMake(PanModalHeightTypeMax, 0)]) + [self topOffset]; + return longFrom; +} + +- (CGFloat)bottomYPos { + if (self.containerView) { + return self.containerView.bounds.size.height - [self topOffset]; + } + return self.bounds.size.height; +} + +- (CGFloat)topMarginFromPanModalHeight:(PanModalHeight)panModalHeight { + switch (panModalHeight.heightType) { + case PanModalHeightTypeMax: + return 0.0f; + case PanModalHeightTypeMaxTopInset: + return panModalHeight.height; + case PanModalHeightTypeContent: + return self.bottomYPos - (panModalHeight.height + self.bottomLayoutOffset); + case PanModalHeightTypeContentIgnoringSafeArea: + return self.bottomYPos - panModalHeight.height; + case PanModalHeightTypeIntrinsic: { + [self layoutIfNeeded]; + + CGSize targetSize = CGSizeMake(self.containerView ? self.containerView.bounds.size.width : [UIScreen mainScreen].bounds.size.width, UILayoutFittingCompressedSize.height); + CGFloat intrinsicHeight = [self systemLayoutSizeFittingSize:targetSize].height; + return self.bottomYPos - (intrinsicHeight + self.bottomLayoutOffset); + } + default: + return 0; + } +} + +#pragma mark - Getter + +- (HWPanModalContainerView *)containerView { + // we assume the container view will not change after we got it. + if (!_containerView) { + UIView *fatherView = self.superview; + while (fatherView) { + if ([fatherView isKindOfClass:HWPanModalContainerView.class]) { + _containerView = (HWPanModalContainerView *) fatherView; + break; + } + fatherView = fatherView.superview; + } + } + + return _containerView; +} + +- (UIView *)findKeyWindow { + + if (@available(iOS 13.0, *)) { + NSSet *connectedScenes = [UIApplication sharedApplication].connectedScenes; + for (UIScene *scene in connectedScenes) { + if ([scene isKindOfClass:UIWindowScene.class]) { + UIWindowScene *windowScene = (UIWindowScene *)scene; + for (UIWindow *tmpWindow in windowScene.windows) { + if ([tmpWindow isKeyWindow]) { + return tmpWindow; + } + } + } + } + + } else { + NSArray *windows = [UIApplication sharedApplication].windows; + for (UIWindow *window in windows) { + if ([window isKeyWindow]) { + return window; + } + } + } + return nil; +} + +@end diff --git a/Pods/JXCategoryView/LICENSE b/Pods/JXCategoryView/LICENSE new file mode 100644 index 0000000..0fdb1e7 --- /dev/null +++ b/Pods/JXCategoryView/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 暴走的鑫鑫 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/JXCategoryView/README.md b/Pods/JXCategoryView/README.md new file mode 100644 index 0000000..2fae2c3 --- /dev/null +++ b/Pods/JXCategoryView/README.md @@ -0,0 +1,296 @@ +
+ +[![platform](https://img.shields.io/badge/platform-iOS-blue.svg?style=plastic)](#) +[![languages](https://img.shields.io/badge/language-objective--c-blue.svg)](#) +[![cocoapods](https://img.shields.io/badge/cocoapods-supported-4BC51D.svg?style=plastic)](https://cocoapods.org/pods/JXCategoryView) +[![support](https://img.shields.io/badge/support-ios%208%2B-orange.svg)](#) + +A powerful and easy to use category view (segmentedcontrol, segmentview, pagingview, pagerview, pagecontrol) (腾讯新闻、今日头条、QQ 音乐、网易云音乐、京东、爱奇艺、腾讯视频、淘宝、天猫、简书、微博等所有主流 APP 分类切换滚动视图) + +与其他的同类三方库对比的优点: +- 使用协议封装指示器逻辑,可以随心所欲地自定义指示器效果; +- 提供更加全面丰富、高度自定义的效果; +- 使用子类化管理 cell 样式,逻辑更清晰,扩展更简单; +- 高度封装列表容器,使用便捷,完美支持列表的生命周期调用; + +## Swift版本 + +如果你在找 Swift 版本,请点击查看 [JXSegmentedView](https://github.com/pujiaxin33/JXSegmentedView)。 + +## 效果预览 + +### 指示器效果预览 + +说明 | Gif | +----|------| +LineView | | +LineView延长 | | +LineView延长+偏移 | | +LineView🌈彩虹风格 | | +DotLineView点线效果 | | +BallView QQ黏性红点 | | +TriangleView 三角形底部 | | +TriangleView 三角形顶部 | | +BackgroundView椭圆形 | | +BackgroundView椭圆形+阴影 | | +BackgroundView长方形 | | +BackgroundView遮罩有背景 | | +BackgroundView遮罩无背景 | | +BackgroundView渐变色 | | +ImageView底部(小船) | | +ImageView背景(最佳男歌手) | | +ImageView滚动效果(足球) | | +混合使用 | | + +以下均支持上下位置切换: +`JXCategoryIndicatorLineView`、`JXCategoryIndicatorImageView`、`JXCategoryIndicatorBallView`、`JXCategoryIndicatorTriangleView` + +### Cell样式效果预览 + +说明 | Gif | +----|------| +颜色渐变 | | +大小缩放 | | +大小缩放+底部锚点 | | +大小缩放+顶部锚点 | | +大小缩放+字体粗细 | | +大小缩放+点击动画 | | +大小缩放+cell宽度缩放 | | +TitleImage_Top | | +TitleImage_Left | | +TitleImage_Bottom | | +TitleImage_Right | | +cell图文混用 | | +Image | | +数字 | | +红点 | | +多行文本 | | +多行富文本 | | +Cell背景色渐变 | | +分割线 | | + +### 特殊效果预览 + +说明 | Gif | +----|------| +数据源过少
averageCellSpacingEnabled默认为YES | | +数据源过少
averageCellSpacingEnabled为NO | | +SegmentedControl
参考[`SegmentedControlViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/SegmentedControl/SegmentedControlViewController.m)类 | | +导航栏使用
参考[`NaviSegmentedControlViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/SegmentedControl/NaviSegmentedControlViewController.m)类 | | +嵌套使用
参考[`NestViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/Nest/NestViewController.m)类 | | +个人主页(上下左右滚动、header悬浮)
参考[`PagingViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/PagingView/Example/PagingViewController.m)类
更多样式请点击查看[JXPagingView库](https://github.com/pujiaxin33/JXPagingView) | | +垂直列表滚动
参考[`VerticalListViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/VerticalListView/VerticalListViewController.m)类
高仿腾讯视频
支持UITableView,参考[`VerticalListTableViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/VerticalListView/VerticalListTableViewController.m)
(背景色异常是录屏软件bug) | | +| 垂直缩放(仿网易圈圈、脉脉首页)
参考[`ScrollZoomViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/ScrollZoom/ScrollZoomViewController.m)类 | | +数据源刷新&列表数据加载
参考[`LoadDataListContainerViewController`](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/LoadData/LoadDataListContainerViewController.m)类 | | +上下滚动隐藏导航栏 | | +京东首页-滚动渐变变小 | | + +### 自定义效果预览 + +收录来自其他使用者的自定义示例,这些自定义类只在 Demo 项目里面,Pod 库并没有这些文件。所以,如果你需要使用这些自定义效果,请通过文件导入的方式。 + +目的: +- 参考学习如何自定义; +- 直接修改自定义示例类以快速实现自己的需求。 + +欢迎提 PullRequest 进行收录你的自定义效果。 + +| 说明 | Gif | +| ----|------| +| Spring动画指示器 | | +| 富文本数量cell | | +| 左右对齐指示器 | | +| 秒杀时间线cell | | +| 京东商品排序cell | | +| title背景块cell | | + +## 要求 + +- iOS 9.0+ +- Xcode 9+ +- Objective-C + +## 安装 + +### 手动 + +Clone 代码,把 Sources 文件夹拖入项目,`#import "JXCategoryView.h"` 就可以使用了。 + +### CocoaPods + +```ruby +target '' do + pod 'JXCategoryView' +end +``` +先执行 `pod repo update`,再执行 `pod install`。 + +## 结构图 + + + +## 使用 + +### JXCategoryTitleView 使用示例 + +1. 初始化 `JXCategoryTitleView`: +```Objective-C +self.categoryView = [[JXCategoryTitleView alloc] initWithFrame:CGRectMake(0, 0, WindowsSize.width, 50)]; +self.categoryView.delegate = self; +[self.view addSubview:self.categoryView]; +``` + +2. 配置 `JXCategoryTitleView` 的属性: +```Objective-C +self.categoryView.titles = @[@"螃蟹", @"麻辣小龙虾", @"苹果"...]; +self.categoryView.titleColorGradientEnabled = YES; +``` + +3. 添加指示器: +```Objective-C +JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init]; +lineView.indicatorColor = [UIColor redColor]; +lineView.indicatorWidth = JXCategoryViewAutomaticDimension; +self.categoryView.indicators = @[lineView]; +``` + +4. 实现 `JXCategoryViewDelegate` 代理(可选) +```Objective-C +// 点击选中或者滚动选中都会调用该方法。适用于只关心选中事件,不关心具体是点击还是滚动选中的。 +- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index; + +// 点击选中的情况才会调用该方法 +- (void)categoryView:(JXCategoryBaseView *)categoryView didClickSelectedItemAtIndex:(NSInteger)index; + +// 滚动选中的情况才会调用该方法 +- (void)categoryView:(JXCategoryBaseView *)categoryView didScrollSelectedItemAtIndex:(NSInteger)index; + +// 正在滚动中的回调 +- (void)categoryView:(JXCategoryBaseView *)categoryView scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio; +``` + +### 列表容器使用示例 + +#### `JXCategoryListContainerView` 封装类使用示例 + +`JXCategoryListContainerView` 是对列表视图高度封装的类,具有以下优点: + +- 相对于直接使用 `UIScrollView` 自定义,封装度高、代码集中、使用简单; +- 列表懒加载:当显示某个列表的时候,才进行列表初始化。而不是一次性加载全部列表,性能更优; +- 支持列表的 `willAppear`、`didAppear`、`willDisappear`、`didDisappear` 生命周期方法调用; + +1. 初始化 `JXCategoryListContainerView` 并关联到 `categoryView`: +```Objective-C +self.listContainerView = [[JXCategoryListContainerView alloc] initWithType:JXCategoryListContainerType_ScrollView delegate:self]; +[self.view addSubview:self.listContainerView]; +// 关联到 categoryView +self.categoryView.listContainer = self.listContainerView; +``` + +2. 实现 `JXCategoryListContainerViewDelegate` 代理方法: +```Objective-C +// 返回列表的数量 +- (NSInteger)numberOfListsInlistContainerView:(JXCategoryListContainerView *)listContainerView { + return self.titles.count; +} +// 根据下标 index 返回对应遵守并实现 `JXCategoryListContentViewDelegate` 协议的列表实例 +- (id)listContainerView:(JXCategoryListContainerView *)listContainerView initListForIndex:(NSInteger)index { + return [[ListViewController alloc] init]; +} +``` + +3. 列表实现 `JXCategoryListContentViewDelegate` 代理方法 +不管列表是 `UIView` 还是 `UIViewController` 都可以,提高使用灵活性,更便于现有的业务接入。 +```Objective-C +// 返回列表视图 +// 如果列表是 VC,就返回 VC.view +// 如果列表是 View,就返回 View 自己 +- (UIView *)listView { + return self.view; +} +``` + + +具体点击 [LoadDataListContainerViewController](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/LoadData/LoadDataListContainerViewController.m) 查看源代码了解 + +#### 直接使用 UIScrollView 自定义 + +因为代码量较多且分散,所有不推荐使用该方法。要正确使用需要注意的地方比较多,尤其对于刚接触 iOS 的同学来说不太友好。 + +不直接贴代码了,具体点击 [LoadDataListCustomViewController](https://github.com/pujiaxin33/JXCategoryView/tree/master/Example/Example/Examples/LoadData/LoadDataListCustomViewController.m) 查看源代码了解。 + + +## 常见问题和答案 + +❗️❗️❗️这里面包含了许多常见问题和答案,使用之前请务必浏览此文档,或者遇到问题先看此文档❗️❗️❗️ + +[常见问题和答案总文档](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md) + +- [个人主页效果更丰富的示例:JXPagingView](https://github.com/pujiaxin33/JXPagingView) +- [侧滑手势处理](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BE%A7%E6%BB%91%E6%89%8B%E5%8A%BF%E5%A4%84%E7%90%86.md) +- [列表的生命周期方法处理](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E5%88%97%E8%A1%A8%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%96%B9%E6%B3%95%E5%A4%84%E7%90%86.md) +- [`JXCategoryListContainerType`的`scrollView`和`collectionView`对比](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#jxcategorylistcontainertype%E7%9A%84scrollview%E5%92%8Ccollectionview%E5%AF%B9%E6%AF%94) +- [cell左滑删除](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#cell%E5%B7%A6%E6%BB%91%E5%88%A0%E9%99%A4) +- [`FDFullscreenPopGesture`等全屏手势处理](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E5%85%A8%E5%B1%8F%E6%89%8B%E5%8A%BF%E5%A4%84%E7%90%86.md) +- [JXCategoryView数据源刷新](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#jxcategoryview%E6%95%B0%E6%8D%AE%E6%BA%90%E5%88%B7%E6%96%B0) +- [`reloadDataWithoutListContainer`方法使用说明](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#reloaddatawithoutlistcontainer%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E) +- [listContainer或contentScrollView关联说明](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#listcontainer%E6%88%96contentscrollview%E5%85%B3%E8%81%94%E8%AF%B4%E6%98%8E) +- [点击切换列表的动画控制](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E7%82%B9%E5%87%BB%E5%88%87%E6%8D%A2%E5%88%97%E8%A1%A8%E7%9A%84%E5%8A%A8%E7%94%BB%E6%8E%A7%E5%88%B6) +- [列表cell点击跳转示例](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E5%88%97%E8%A1%A8cell%E7%82%B9%E5%87%BB%E8%B7%B3%E8%BD%AC%E7%A4%BA%E4%BE%8B) +- [列表调用`presentViewController`方法](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E5%88%97%E8%A1%A8%E8%B0%83%E7%94%A8presentviewcontroller%E6%96%B9%E6%B3%95) +- [代码选中指定index](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E4%BB%A3%E7%A0%81%E9%80%89%E4%B8%AD%E6%8C%87%E5%AE%9Aindex) +- [JXCategoryView.collectionView高度取整说明](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#jxcategoryviewcollectionview%E9%AB%98%E5%BA%A6%E5%8F%96%E6%95%B4%E8%AF%B4%E6%98%8E) +- [对父VC的automaticallyAdjustsScrollViewInsets属性设置为NO](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E5%AF%B9%E7%88%B6vc%E7%9A%84automaticallyadjustsscrollviewinsets%E5%B1%9E%E6%80%A7%E8%AE%BE%E7%BD%AE%E4%B8%BAno) +- [`JXCategoryListContainerView`内部使用`UIViewController`当做列表容器使用说明](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#jxcategorylistcontainerview%E5%86%85%E9%83%A8%E4%BD%BF%E7%94%A8uiviewcontroller%E5%BD%93%E5%81%9A%E5%88%97%E8%A1%A8%E5%AE%B9%E5%99%A8%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E) +- [使用多行文本](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E4%BD%BF%E7%94%A8%E5%A4%9A%E8%A1%8C%E6%96%87%E6%9C%AC) +- [列表容器禁止左右滑动](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E5%88%97%E8%A1%A8%E5%AE%B9%E5%99%A8%E7%A6%81%E6%AD%A2%E5%B7%A6%E5%8F%B3%E6%BB%91%E5%8A%A8) +- [单个cell刷新 ](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E5%8D%95%E4%B8%AAcell%E5%88%B7%E6%96%B0) +- [点击item时指示器和列表滚动时效果一致](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E7%82%B9%E5%87%BBitem%E6%97%B6%E6%8C%87%E7%A4%BA%E5%99%A8%E5%92%8C%E5%88%97%E8%A1%A8%E6%BB%9A%E5%8A%A8%E6%97%B6%E6%95%88%E6%9E%9C%E4%B8%80%E8%87%B4) +- [自定义建议](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BB%BA%E8%AE%AE) + +## 指示器样式自定义 + +- 需要继承 `JXCategoryIndicatorProtocol` 协议,点击参看 [JXCategoryIndicatorProtocol](https://github.com/pujiaxin33/JXCategoryView/blob/master/Sources/Common/JXCategoryIndicatorProtocol.h); +- 提供了继承 `JXCategoryIndicatorProtocol` 协议的基类 `JXCategoryIndicatorComponentView`,里面提供了许多基础属性。点击参看 [JXCategoryIndicatorComponentView](https://github.com/pujiaxin33/JXCategoryView/blob/master/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.m); +- 自定义指示器,请参考已实现的指示器视图,多尝试、多思考,再有问题请提 Issue 或加入反馈 QQ 群。 + +## Cell 自定义 + +- 任何子类化需求,view、cell、cellModel 三个都要子类化,即使某个子类 cell 什么事情都不做。用于维护继承链,以免以后子类化都不知道要继承谁了; +- 如果你想完全自定义 cell 里面的内容,那就继承 `JXCategoryIndicatorView`、`JXCategoryIndicatorCell、`JXCategoryIndicatorCellModel`,就像`JXCategoryTitleView`、`JXCategoryTitleCell、`JXCategoryTitleCellModel`那样去做; +- 如果你只是在父类进行一些微调,那就继承目标 view、cell、cellModel,对 cell 原有控件微调、或者加入新的控件皆可。就像 `JXCategoryTitleImageView` 系列、`JXCategoryTitleAttributeView` 系列那样去做; +- Cell 自定义,请参考已实现的 cell 样式,多尝试、多思考,再有问题请提 Issue 或加入反馈 QQ 群 + +## 常用属性说明 + +[常用属性说明文档地址](https://github.com/pujiaxin33/JXCategoryView/blob/master/Document/%E5%B8%B8%E7%94%A8%E5%B1%9E%E6%80%A7%E8%AF%B4%E6%98%8E.md) + +## 更新记录 + +- 2018.8.21 发布1.0.0版本,更新内容:使用POP(面向协议编程)重构指示器视图;[迁移指南](https://github.com/pujiaxin33/JXCategoryView/blob/master/Migration/1.0.0.md) +- 2018.8.22 发布1.0.1版本,更新内容:删除zoomEnabled,新增titleLabelZoomEnabled、imageZoomEnabled; +- 2018.8.23 发布1.0.2版本,更新内容:添加cellWidthZoomEnabled实现腾讯视频效果; +- 2018.8.24 发布1.0.3版本,更新内容:添加垂直列表滚动效果、指示器添加verticalMargin属性、JXCategoryViewDelegate代理方法优化; +- 2018.9.4 发布1.0.4版本,更新内容:修复bug、添加cell图文混用示例; +- 2018.12.19 发布1.1.7版本,更新内容:添加`JXCategoryListContainerView`,高度封装列表逻辑,支持懒加载列表,提升初始化性能; +- 2019.1.24 发布1.2.2版本,更新内容:非兼容更新接口`- (BOOL)selectCellAtIndex:(NSInteger)index selectedType:(JXCategoryCellSelectedType)selectedType`,自定义有用到该接口的请及时更新。 +- 2019.6.21 发布1.3.13版本,更新内容:将`JXCategoryListCollectionContainerView.dataSource`移动到m实现文件,添加`- (instancetype)initWithDataSource:(id)dataSource`初始化方法。 +- 2019.7.20 发布1.3.16版本,删除代理方法`- (void)categoryView:(JXCategoryBaseView *)categoryView didClickedItemContentScrollViewTransitionToIndex:(NSInteger)index;`,请使用`contentScrollViewClickTransitionAnimationEnabled`属性。`JXCategoryTitleVerticalZoomView`进行了重构,内容左边距只需要使用`contentEdgeLeft`属性即可。 +- 2019.9.11 发布1.4.0版本,删除一波被标记为弃用的属性和方法;完善列表的生命周期方法的调用;`JXCategoryListCollectionContainerView`类新增和必须要调用`- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex`和`- (void)didClickSelectedItemAtIndex:(NSInteger)index`两个方法。 +- 2019.9.19 发布1.5.0版本,重构列表容器,具体修改请参考[1.5.0版本迁移指南](https://github.com/pujiaxin33/JXCategoryView/blob/master/Migration/1.5.0%E7%89%88%E6%9C%AC%E8%BF%81%E7%A7%BB%E6%8C%87%E5%8D%97.md) + +## 补充 + +如果刚开始使用`JXCategoryView`,当开发过程中需要支持某种特性时,请务必先搜索使用文档或者源代码。确认是否已经实现支持了想要的特性。请别不要文档和源代码都没有看,就直接提问,这对于大家都是一种时间浪费。如果没有支持想要的特性,欢迎提Issue讨论,或者自己实现提一个PullRequest。 + +该仓库保持随时更新,对于主流新的分类选择效果会第一时间支持。使用过程中,有任何建议或问题,可以通过以下方式联系我:
+邮箱:317437084@qq.com
+QQ群: 112440473 + + + +喜欢就star❤️一下吧 + +## License + +JXCategoryView is released under the MIT license. diff --git a/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCell.h b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCell.h new file mode 100644 index 0000000..ba630f3 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCell.h @@ -0,0 +1,29 @@ +// +// JXCategoryBaseCell.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXCategoryBaseCellModel.h" +#import "JXCategoryViewAnimator.h" +#import "JXCategoryViewDefines.h" + +@interface JXCategoryBaseCell : UICollectionViewCell + +@property (nonatomic, strong, readonly) JXCategoryBaseCellModel *cellModel; +@property (nonatomic, strong, readonly) JXCategoryViewAnimator *animator; + +- (void)initializeViews NS_REQUIRES_SUPER; + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel NS_REQUIRES_SUPER; + +- (BOOL)checkCanStartSelectedAnimation:(JXCategoryBaseCellModel *)cellModel; + +- (void)addSelectedAnimationBlock:(JXCategoryCellSelectedAnimationBlock)block; + +- (void)startSelectedAnimationIfNeeded:(JXCategoryBaseCellModel *)cellModel; + +@end diff --git a/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCell.m b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCell.m new file mode 100644 index 0000000..ea63aac --- /dev/null +++ b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCell.m @@ -0,0 +1,98 @@ +// +// JXCategoryBaseCell.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryBaseCell.h" +#import "RTLManager.h" + +@interface JXCategoryBaseCell () +@property (nonatomic, strong) JXCategoryBaseCellModel *cellModel; +@property (nonatomic, strong) JXCategoryViewAnimator *animator; +@property (nonatomic, strong) NSMutableArray *animationBlockArray; +@end + +@implementation JXCategoryBaseCell + +#pragma mark - Initialize + +- (void)dealloc { + [self.animator stop]; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + + [self.animator stop]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initializeViews]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self initializeViews]; + } + return self; +} + +#pragma mark - Public + +- (void)initializeViews { + _animationBlockArray = [NSMutableArray array]; + + [RTLManager horizontalFlipViewIfNeeded:self]; + [RTLManager horizontalFlipViewIfNeeded:self.contentView]; +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + self.cellModel = cellModel; + + if (cellModel.isSelectedAnimationEnabled) { + [self.animationBlockArray removeLastObject]; + if ([self checkCanStartSelectedAnimation:cellModel]) { + self.animator = [[JXCategoryViewAnimator alloc] init]; + self.animator.duration = cellModel.selectedAnimationDuration; + } else { + [self.animator stop]; + } + } +} + +- (BOOL)checkCanStartSelectedAnimation:(JXCategoryBaseCellModel *)cellModel { + BOOL canStartSelectedAnimation = ((cellModel.selectedType == JXCategoryCellSelectedTypeCode) || (cellModel.selectedType == JXCategoryCellSelectedTypeClick)); + return canStartSelectedAnimation; +} + +- (void)addSelectedAnimationBlock:(JXCategoryCellSelectedAnimationBlock)block { + [self.animationBlockArray addObject:block]; +} + +- (void)startSelectedAnimationIfNeeded:(JXCategoryBaseCellModel *)cellModel { + if (cellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:cellModel]) { + // 需要更新 isTransitionAnimating,用于处理在过滤时,禁止响应点击,避免界面异常。 + cellModel.transitionAnimating = YES; + __weak typeof(self)weakSelf = self; + self.animator.progressCallback = ^(CGFloat percent) { + for (JXCategoryCellSelectedAnimationBlock block in weakSelf.animationBlockArray) { + block(percent); + } + }; + self.animator.completeCallback = ^{ + cellModel.transitionAnimating = NO; + [weakSelf.animationBlockArray removeAllObjects]; + }; + [self.animator start]; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCellModel.h b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCellModel.h new file mode 100644 index 0000000..af82301 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCellModel.h @@ -0,0 +1,31 @@ +// +// JXCategoryBaseCellModel.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import +#import "JXCategoryViewDefines.h" + +@interface JXCategoryBaseCellModel : NSObject + +@property (nonatomic, assign) NSUInteger index; +@property (nonatomic, assign) CGFloat cellWidth; +@property (nonatomic, assign) CGFloat cellSpacing; +@property (nonatomic, assign, getter=isSelected) BOOL selected; + +@property (nonatomic, assign, getter=isCellWidthZoomEnabled) BOOL cellWidthZoomEnabled; +@property (nonatomic, assign) CGFloat cellWidthNormalZoomScale; +@property (nonatomic, assign) CGFloat cellWidthCurrentZoomScale; +@property (nonatomic, assign) CGFloat cellWidthSelectedZoomScale; + +@property (nonatomic, assign, getter=isSelectedAnimationEnabled) BOOL selectedAnimationEnabled; +@property (nonatomic, assign) NSTimeInterval selectedAnimationDuration; +@property (nonatomic, assign) JXCategoryCellSelectedType selectedType; + +@property (nonatomic, assign, getter=isTransitionAnimating) BOOL transitionAnimating; + +@end diff --git a/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCellModel.m b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCellModel.m new file mode 100644 index 0000000..9b6e520 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseCellModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryBaseCellModel.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryBaseCellModel.h" + +@implementation JXCategoryBaseCellModel + +@end diff --git a/Pods/JXCategoryView/Sources/Base/JXCategoryBaseView.h b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseView.h new file mode 100644 index 0000000..27a54fe --- /dev/null +++ b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseView.h @@ -0,0 +1,222 @@ +// +// JXCategoryView.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXCategoryBaseCell.h" +#import "JXCategoryBaseCellModel.h" +#import "JXCategoryCollectionView.h" +#import "JXCategoryViewDefines.h" + +@class JXCategoryBaseView; + +@protocol JXCategoryViewListContainer +- (void)setDefaultSelectedIndex:(NSInteger)index; +- (UIScrollView *)contentScrollView; +- (void)reloadData; +- (void)didClickSelectedItemAtIndex:(NSInteger)index; +@end + +@protocol JXCategoryViewDelegate + +@optional + +//为什么会把选中代理分为三个,因为有时候只关心点击选中的,有时候只关心滚动选中的,有时候只关心选中。所以具体情况,使用对应方法。 +/** + 点击选中或者滚动选中都会调用该方法。适用于只关心选中事件,不关心具体是点击还是滚动选中的。 + + @param categoryView categoryView对象 + @param index 选中的index + */ +- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index; + +/** + 点击选中的情况才会调用该方法 + + @param categoryView categoryView对象 + @param index 选中的index + */ +- (void)categoryView:(JXCategoryBaseView *)categoryView didClickSelectedItemAtIndex:(NSInteger)index; + +/** + 滚动选中的情况才会调用该方法 + + @param categoryView categoryView对象 + @param index 选中的index + */ +- (void)categoryView:(JXCategoryBaseView *)categoryView didScrollSelectedItemAtIndex:(NSInteger)index; + +/** + 控制能否点击Item + + @param categoryView categoryView对象 + @param index 准备点击的index + @return 能否点击 + */ +- (BOOL)categoryView:(JXCategoryBaseView *)categoryView canClickItemAtIndex:(NSInteger)index; + +/** + 正在滚动中的回调 + + @param categoryView categoryView对象 + @param leftIndex 正在滚动中,相对位置处于左边的index + @param rightIndex 正在滚动中,相对位置处于右边的index + @param ratio 从左往右计算的百分比 + */ +- (void)categoryView:(JXCategoryBaseView *)categoryView scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio; + +@end + +@interface JXCategoryBaseView : UIView + +@property (nonatomic, strong, readonly) JXCategoryCollectionView *collectionView; + +@property (nonatomic, strong) NSArray *dataSource; + +@property (nonatomic, weak) id delegate; + +/** + 高封装度的列表容器,使用该类可以让列表拥有完成的生命周期、自动同步defaultSelectedIndex、自动调用reloadData。 + */ +@property (nonatomic, weak) id listContainer; + +/** + 推荐使用封装度更高的listContainer属性。如果使用contentScrollView请参考`LoadDataListCustomViewController`使用示例。 + */ +@property (nonatomic, strong) UIScrollView *contentScrollView; + +@property (nonatomic, assign) NSInteger defaultSelectedIndex; //修改初始化的时候默认选择的index + +@property (nonatomic, assign, readonly) NSInteger selectedIndex; + +@property (nonatomic, assign, getter=isContentScrollViewClickTransitionAnimationEnabled) BOOL contentScrollViewClickTransitionAnimationEnabled; //点击cell进行contentScrollView切换时是否需要动画。默认为YES + +@property (nonatomic, assign) CGFloat contentEdgeInsetLeft; //整体内容的左边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing) + +@property (nonatomic, assign) CGFloat contentEdgeInsetRight; //整体内容的右边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing) + +@property (nonatomic, assign) CGFloat cellWidth; //默认JXCategoryViewAutomaticDimension + +@property (nonatomic, assign) CGFloat cellWidthIncrement; //cell宽度补偿。默认:0 + +@property (nonatomic, assign) CGFloat cellSpacing; //cell之间的间距,默认20 + +@property (nonatomic, assign, getter=isAverageCellSpacingEnabled) BOOL averageCellSpacingEnabled; //当collectionView.contentSize.width小于JXCategoryBaseView的宽度,是否将cellSpacing均分。默认为YES。 + +//cell宽度是否缩放 +@property (nonatomic, assign, getter=isCellWidthZoomEnabled) BOOL cellWidthZoomEnabled; //默认为NO + +@property (nonatomic, assign, getter=isCellWidthZoomScrollGradientEnabled) BOOL cellWidthZoomScrollGradientEnabled; //手势滚动过程中,是否需要更新cell的宽度。默认为YES + +@property (nonatomic, assign) CGFloat cellWidthZoomScale; //默认1.2,cellWidthZoomEnabled为YES才生效 + +@property (nonatomic, assign, getter=isSelectedAnimationEnabled) BOOL selectedAnimationEnabled; //是否开启点击或代码选中动画。默认为NO。自定义的cell选中动画需要自己实现。(仅点击或调用selectItemAtIndex选中才有效,滚动选中无效) + +@property (nonatomic, assign) NSTimeInterval selectedAnimationDuration; //cell选中动画的时间。默认0.25 + +/** + 选中目标index的item + + @param index 目标index + */ +- (void)selectItemAtIndex:(NSInteger)index; + +/** + 初始化的时候无需调用。比如页面初始化之后,根据网络接口异步回调回来数据,重新配置categoryView,需要调用该方法进行刷新。 + */ +- (void)reloadData; + +/** + 重新配置categoryView但是不需要reload listContainer。特殊情况是该方法。 + */ +- (void)reloadDataWithoutListContainer; + +/** + 刷新指定的index的cell + 内部会触发`- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index`方法进行cellModel刷新 + + @param index 指定cell的index + */ +- (void)reloadCellAtIndex:(NSInteger)index; + +@end + + + +@interface JXCategoryBaseView (UISubclassingBaseHooks) + +/** + 获取目标cell当前的frame,反应当前真实的frame受到cellWidthSelectedZoomScale的影响。 + */ +- (CGRect)getTargetCellFrame:(NSInteger)targetIndex; + +/** + 获取目标cell的选中时的frame,其他cell的状态都当做普通状态处理。 + */ +- (CGRect)getTargetSelectedCellFrame:(NSInteger)targetIndex selectedType:(JXCategoryCellSelectedType)selectedType; +- (void)initializeData NS_REQUIRES_SUPER; +- (void)initializeViews NS_REQUIRES_SUPER; + +/** + reloadData方法调用,重新生成数据源赋值到self.dataSource + */ +- (void)refreshDataSource; + +/** + reloadData方法调用,根据数据源重新刷新状态; + */ +- (void)refreshState NS_REQUIRES_SUPER; + +/** + 选中某个item时,刷新将要选中与取消选中的cellModel + + @param selectedCellModel 将要选中的cellModel + @param unselectedCellModel 取消选中的cellModel + */ +- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel NS_REQUIRES_SUPER; + +/** + 关联的contentScrollView的contentOffset发生了改变 + + @param contentOffset 偏移量 + */ +- (void)contentOffsetOfContentScrollViewDidChanged:(CGPoint)contentOffset NS_REQUIRES_SUPER; + +/** + 选中某一个item的时候调用,该方法用于子类重载。 + 如果外部要选中某个index,请使用`- (void)selectItemAtIndex:(NSUInteger)index;` + + @param index 选中的index + @param selectedType JXCategoryCellSelectedType + @return 返回值为NO,表示触发内部某些判断(点击了同一个cell),子类无需后续操作。 + */ +- (BOOL)selectCellAtIndex:(NSInteger)index selectedType:(JXCategoryCellSelectedType)selectedType NS_REQUIRES_SUPER; + +/** + reloadData时,返回每个cell的宽度 + + @param index 目标index + @return cellWidth + */ +- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index; + +/** + 返回自定义cell的class + + @return cell class + */ +- (Class)preferredCellClass; + +/** + refreshState时调用,重置cellModel的状态 + + @param cellModel 待重置的cellModel + @param index cellModel在数组中的index + */ +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index NS_REQUIRES_SUPER; + +@end diff --git a/Pods/JXCategoryView/Sources/Base/JXCategoryBaseView.m b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseView.m new file mode 100644 index 0000000..4d0b7bd --- /dev/null +++ b/Pods/JXCategoryView/Sources/Base/JXCategoryBaseView.m @@ -0,0 +1,697 @@ +// +// JXCategoryBaseView.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryBaseView.h" +#import "JXCategoryFactory.h" +#import "JXCategoryViewAnimator.h" +#import "RTLManager.h" + +struct DelegateFlags { + unsigned int didSelectedItemAtIndexFlag : 1; + unsigned int didClickSelectedItemAtIndexFlag : 1; + unsigned int didScrollSelectedItemAtIndexFlag : 1; + unsigned int canClickItemAtIndexFlag : 1; + unsigned int scrollingFromLeftIndexToRightIndexFlag : 1; +}; + +@interface JXCategoryBaseView () + +@property (nonatomic, strong) JXCategoryCollectionView *collectionView; +@property (nonatomic, assign) struct DelegateFlags delegateFlags; +@property (nonatomic, assign) NSInteger selectedIndex; +@property (nonatomic, assign) CGFloat innerCellSpacing; +@property (nonatomic, assign) CGPoint lastContentViewContentOffset; +@property (nonatomic, strong) JXCategoryViewAnimator *animator; +// 正在滚动中的目标index。用于处理正在滚动列表的时候,立即点击item,会导致界面显示异常。 +@property (nonatomic, assign) NSInteger scrollingTargetIndex; +@property (nonatomic, assign, getter=isNeedReloadByBecomeActive) BOOL needReloadByBecomeActive; +@property (nonatomic, assign, getter=isFirstLayoutSubviews) BOOL firstLayoutSubviews; +@property (nonatomic, assign, getter=isNeedConfigAutomaticallyAdjustsScrollViewInsets) BOOL needConfigAutomaticallyAdjustsScrollViewInsets; + +@end + +@implementation JXCategoryBaseView + +- (void)dealloc { + if (self.contentScrollView) { + [self.contentScrollView removeObserver:self forKeyPath:@"contentOffset"]; + } + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [self.animator stop]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initializeData]; + [self initializeViews]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self initializeData]; + [self initializeViews]; + } + return self; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + + [self configAutomaticallyAdjustsScrollViewInsets:newSuperview]; +} + +- (void)reloadData { + [self reloadDataWithoutListContainer]; + [self.listContainer reloadData]; +} + +- (void)reloadDataWithoutListContainer { + [self refreshDataSource]; + [self refreshState]; + [self.collectionView.collectionViewLayout invalidateLayout]; + [self.collectionView reloadData]; +} + +- (void)reloadCellAtIndex:(NSInteger)index { + if (index < 0 || index >= self.dataSource.count) { + return; + } + JXCategoryBaseCellModel *cellModel = self.dataSource[index]; + cellModel.selectedType = JXCategoryCellSelectedTypeUnknown; + [self refreshCellModel:cellModel index:index]; + JXCategoryBaseCell *cell = (JXCategoryBaseCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + [cell reloadData:cellModel]; +} + +- (void)selectItemAtIndex:(NSInteger)index { + [self selectCellAtIndex:index selectedType:JXCategoryCellSelectedTypeCode]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + //部分使用者为了适配不同的手机屏幕尺寸,JXCategoryView的宽高比要求保持一样,所以它的高度就会因为不同宽度的屏幕而不一样。计算出来的高度,有时候会是位数很长的浮点数,如果把这个高度设置给UICollectionView就会触发内部的一个错误。所以,为了规避这个问题,在这里对高度统一向下取整。 + //如果向下取整导致了你的页面异常,请自己重新设置JXCategoryView的高度,保证为整数即可。 + CGRect targetFrame = CGRectMake(0, 0, self.bounds.size.width, floor(self.bounds.size.height)); + if (self.isFirstLayoutSubviews) { + if (self.bounds.size.width == 0 || self.bounds.size.height == 0) { + return; + } + if (self.isNeedConfigAutomaticallyAdjustsScrollViewInsets) { + [self configAutomaticallyAdjustsScrollViewInsets:self.superview]; + } + self.firstLayoutSubviews = NO; + self.collectionView.frame = targetFrame; + [self reloadDataWithoutListContainer]; + }else { + if (!CGRectEqualToRect(self.collectionView.frame, targetFrame)) { + self.collectionView.frame = targetFrame; + [self refreshState]; + [self.collectionView.collectionViewLayout invalidateLayout]; + [self.collectionView reloadData]; + } + } +} + +#pragma mark - Setter + +- (void)setDelegate:(id)delegate { + _delegate = delegate; + + _delegateFlags.didSelectedItemAtIndexFlag = [delegate respondsToSelector:@selector(categoryView:didSelectedItemAtIndex:)]; + _delegateFlags.didClickSelectedItemAtIndexFlag = [delegate respondsToSelector:@selector(categoryView:didClickSelectedItemAtIndex:)]; + _delegateFlags.didScrollSelectedItemAtIndexFlag = [delegate respondsToSelector:@selector(categoryView:didScrollSelectedItemAtIndex:)]; + _delegateFlags.canClickItemAtIndexFlag = [delegate respondsToSelector:@selector(categoryView:canClickItemAtIndex:)]; + _delegateFlags.scrollingFromLeftIndexToRightIndexFlag = [delegate respondsToSelector:@selector(categoryView:scrollingFromLeftIndex:toRightIndex:ratio:)]; +} + +- (void)setDefaultSelectedIndex:(NSInteger)defaultSelectedIndex { + _defaultSelectedIndex = defaultSelectedIndex; + + self.selectedIndex = defaultSelectedIndex; + [self.listContainer setDefaultSelectedIndex:defaultSelectedIndex]; +} + +- (void)setContentScrollView:(UIScrollView *)contentScrollView { + if (_contentScrollView != nil) { + [_contentScrollView removeObserver:self forKeyPath:@"contentOffset"]; + } + _contentScrollView = contentScrollView; + + self.contentScrollView.scrollsToTop = NO; + [self.contentScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; +} + +- (void)setListContainer:(id)listContainer { + _listContainer = listContainer; + [listContainer setDefaultSelectedIndex:self.defaultSelectedIndex]; + self.contentScrollView = [listContainer contentScrollView]; +} + +#pragma mark - + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 1; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.dataSource.count; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + return [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([self preferredCellClass]) forIndexPath:indexPath]; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + JXCategoryBaseCellModel *cellModel = self.dataSource[indexPath.item]; + cellModel.selectedType = JXCategoryCellSelectedTypeUnknown; + [(JXCategoryBaseCell *)cell reloadData:cellModel]; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + BOOL isTransitionAnimating = NO; + for (JXCategoryBaseCellModel *cellModel in self.dataSource) { + if (cellModel.isTransitionAnimating) { + isTransitionAnimating = YES; + break; + } + } + if (!isTransitionAnimating) { + //当前没有正在过渡的item,才允许点击选中 + [self clickSelectItemAtIndex:indexPath.row]; + } +} + +#pragma mark - + +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(0, [self getContentEdgeInsetLeft], 0, [self getContentEdgeInsetRight]); +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return CGSizeMake(self.dataSource[indexPath.item].cellWidth, self.collectionView.bounds.size.height); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return self.innerCellSpacing; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return self.innerCellSpacing; +} + +#pragma mark - KVO + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqualToString:@"contentOffset"]) { + CGPoint contentOffset = [change[NSKeyValueChangeNewKey] CGPointValue]; + if ((self.contentScrollView.isTracking || self.contentScrollView.isDecelerating)) { + //只处理用户滚动的情况 + [self contentOffsetOfContentScrollViewDidChanged:contentOffset]; + } + self.lastContentViewContentOffset = contentOffset; + } +} + +#pragma mark - Private + +- (void)configAutomaticallyAdjustsScrollViewInsets:(UIView *)view { + UIResponder *next = view; + while (next != nil) { + if ([next isKindOfClass:[UIViewController class]]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + ((UIViewController *)next).automaticallyAdjustsScrollViewInsets = NO; +#pragma clang diagnostic pop + self.needConfigAutomaticallyAdjustsScrollViewInsets = NO; + break; + } + next = next.nextResponder; + } +} + +- (CGFloat)getContentEdgeInsetLeft { + if (self.contentEdgeInsetLeft == JXCategoryViewAutomaticDimension) { + return self.innerCellSpacing; + } + return self.contentEdgeInsetLeft; +} + +- (CGFloat)getContentEdgeInsetRight { + if (self.contentEdgeInsetRight == JXCategoryViewAutomaticDimension) { + return self.innerCellSpacing; + } + return self.contentEdgeInsetRight; +} + +- (CGFloat)getCellWidthAtIndex:(NSInteger)index { + return [self preferredCellWidthAtIndex:index] + self.cellWidthIncrement; +} + +- (void)clickSelectItemAtIndex:(NSInteger)index { + if (self.delegateFlags.canClickItemAtIndexFlag && ![self.delegate categoryView:self canClickItemAtIndex:index]) { + return; + } + + [self selectCellAtIndex:index selectedType:JXCategoryCellSelectedTypeClick]; +} + +- (void)scrollSelectItemAtIndex:(NSInteger)index { + [self selectCellAtIndex:index selectedType:JXCategoryCellSelectedTypeScroll]; +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + if (self.isNeedReloadByBecomeActive) { + self.needReloadByBecomeActive = NO; + [self reloadData]; + } +} + +@end + +@implementation JXCategoryBaseView (UISubclassingBaseHooks) + +- (CGRect)getTargetCellFrame:(NSInteger)targetIndex { + CGFloat x = [self getContentEdgeInsetLeft]; + for (int i = 0; i < targetIndex; i ++) { + JXCategoryBaseCellModel *cellModel = self.dataSource[i]; + CGFloat cellWidth; + if (cellModel.isTransitionAnimating && cellModel.isCellWidthZoomEnabled) { + //正在进行动画的时候,cellWidthCurrentZoomScale是随着动画渐变的,而没有立即更新到目标值 + if (cellModel.isSelected) { + cellWidth = [self getCellWidthAtIndex:cellModel.index]*cellModel.cellWidthSelectedZoomScale; + }else { + cellWidth = [self getCellWidthAtIndex:cellModel.index]*cellModel.cellWidthNormalZoomScale; + } + }else { + cellWidth = cellModel.cellWidth; + } + x += cellWidth + self.innerCellSpacing; + } + CGFloat width; + JXCategoryBaseCellModel *selectedCellModel = self.dataSource[targetIndex]; + if (selectedCellModel.isTransitionAnimating && selectedCellModel.isCellWidthZoomEnabled) { + width = [self getCellWidthAtIndex:selectedCellModel.index]*selectedCellModel.cellWidthSelectedZoomScale; + }else { + width = selectedCellModel.cellWidth; + } + return CGRectMake(x, 0, width, self.bounds.size.height); +} + +- (CGRect)getTargetSelectedCellFrame:(NSInteger)targetIndex selectedType:(JXCategoryCellSelectedType)selectedType { + CGFloat x = [self getContentEdgeInsetLeft]; + for (int i = 0; i < targetIndex; i ++) { + JXCategoryBaseCellModel *cellModel = self.dataSource[i]; + x += [self getCellWidthAtIndex:cellModel.index] + self.innerCellSpacing; + } + CGFloat cellWidth = 0; + JXCategoryBaseCellModel *selectedCellModel = self.dataSource[targetIndex]; + if (selectedCellModel.cellWidthZoomEnabled) { + cellWidth = [self getCellWidthAtIndex:targetIndex]*selectedCellModel.cellWidthSelectedZoomScale; + }else { + cellWidth = [self getCellWidthAtIndex:targetIndex]; + } + return CGRectMake(x, 0, cellWidth, self.bounds.size.height); +} + +- (void)initializeData { + _firstLayoutSubviews = YES; + _dataSource = [NSMutableArray array]; + _selectedIndex = 0; + _cellWidth = JXCategoryViewAutomaticDimension; + _cellWidthIncrement = 0; + _cellSpacing = 20; + _averageCellSpacingEnabled = YES; + _cellWidthZoomEnabled = NO; + _cellWidthZoomScale = 1.2; + _cellWidthZoomScrollGradientEnabled = YES; + _contentEdgeInsetLeft = JXCategoryViewAutomaticDimension; + _contentEdgeInsetRight = JXCategoryViewAutomaticDimension; + _lastContentViewContentOffset = CGPointZero; + _selectedAnimationEnabled = NO; + _selectedAnimationDuration = 0.25; + _scrollingTargetIndex = -1; + _contentScrollViewClickTransitionAnimationEnabled = YES; + _needReloadByBecomeActive = NO; +} + +- (void)initializeViews { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + _collectionView = [[JXCategoryCollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout]; + self.collectionView.backgroundColor = [UIColor clearColor]; + self.collectionView.showsHorizontalScrollIndicator = NO; + self.collectionView.showsVerticalScrollIndicator = NO; + self.collectionView.scrollsToTop = NO; + self.collectionView.dataSource = self; + self.collectionView.delegate = self; + [self.collectionView registerClass:[self preferredCellClass] forCellWithReuseIdentifier:NSStringFromClass([self preferredCellClass])]; + if (@available(iOS 10.0, *)) { + self.collectionView.prefetchingEnabled = NO; + } + if (@available(iOS 11.0, *)) { + if ([self.collectionView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { + self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + } + if ([RTLManager supportRTL]) { + self.collectionView.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + [RTLManager horizontalFlipView:self.collectionView]; + } + [self addSubview:self.collectionView]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; +} + +- (void)refreshDataSource {} + +- (void)refreshState { + if (self.selectedIndex < 0 || self.selectedIndex >= self.dataSource.count) { + self.defaultSelectedIndex = 0; + } + + self.innerCellSpacing = self.cellSpacing; + //总的内容宽度(左边距+cell总宽度+总cellSpacing+右边距) + __block CGFloat totalItemWidth = [self getContentEdgeInsetLeft]; + //总的cell宽度 + CGFloat totalCellWidth = 0; + for (int i = 0; i < self.dataSource.count; i++) { + JXCategoryBaseCellModel *cellModel = self.dataSource[i]; + cellModel.index = i; + cellModel.cellWidthZoomEnabled = self.cellWidthZoomEnabled; + cellModel.cellWidthNormalZoomScale = 1; + cellModel.cellWidthSelectedZoomScale = self.cellWidthZoomScale; + cellModel.selectedAnimationEnabled = self.selectedAnimationEnabled; + cellModel.selectedAnimationDuration = self.selectedAnimationDuration; + cellModel.cellSpacing = self.innerCellSpacing; + if (i == self.selectedIndex) { + cellModel.selected = YES; + cellModel.cellWidthCurrentZoomScale = cellModel.cellWidthSelectedZoomScale; + }else { + cellModel.selected = NO; + cellModel.cellWidthCurrentZoomScale = cellModel.cellWidthNormalZoomScale; + } + if (self.isCellWidthZoomEnabled) { + cellModel.cellWidth = [self getCellWidthAtIndex:i]*cellModel.cellWidthCurrentZoomScale; + }else { + cellModel.cellWidth = [self getCellWidthAtIndex:i]; + } + totalCellWidth += cellModel.cellWidth; + if (i == self.dataSource.count - 1) { + totalItemWidth += cellModel.cellWidth + [self getContentEdgeInsetRight]; + }else { + totalItemWidth += cellModel.cellWidth + self.innerCellSpacing; + } + [self refreshCellModel:cellModel index:i]; + } + + if (self.isAverageCellSpacingEnabled && totalItemWidth < self.bounds.size.width) { + //如果总的内容宽度都没有超过视图宽度,就将cellSpacing等分 + NSInteger cellSpacingItemCount = self.dataSource.count - 1; + CGFloat totalCellSpacingWidth = self.bounds.size.width - totalCellWidth; + //如果内容左边距是Automatic,就加1 + if (self.contentEdgeInsetLeft == JXCategoryViewAutomaticDimension) { + cellSpacingItemCount += 1; + }else { + totalCellSpacingWidth -= self.contentEdgeInsetLeft; + } + //如果内容右边距是Automatic,就加1 + if (self.contentEdgeInsetRight == JXCategoryViewAutomaticDimension) { + cellSpacingItemCount += 1; + }else { + totalCellSpacingWidth -= self.contentEdgeInsetRight; + } + + CGFloat cellSpacing = 0; + if (cellSpacingItemCount > 0) { + cellSpacing = totalCellSpacingWidth/cellSpacingItemCount; + } + self.innerCellSpacing = cellSpacing; + [self.dataSource enumerateObjectsUsingBlock:^(JXCategoryBaseCellModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + obj.cellSpacing = self.innerCellSpacing; + }]; + } + + //---------------------定位collectionView到当前选中的位置---------------------- + //因为初始化的时候,collectionView并没有初始化完,cell都没有被加载出来。只有自己手动计算当前选中的index的位置,然后更新到contentOffset + __block CGFloat frameXOfSelectedCell = [self getContentEdgeInsetLeft]; + __block CGFloat selectedCellWidth = 0; + totalItemWidth = [self getContentEdgeInsetLeft]; + [self.dataSource enumerateObjectsUsingBlock:^(JXCategoryBaseCellModel * cellModel, NSUInteger idx, BOOL * _Nonnull stop) { + if (idx < self.selectedIndex) { + frameXOfSelectedCell += cellModel.cellWidth + self.innerCellSpacing; + }else if (idx == self.selectedIndex) { + selectedCellWidth = cellModel.cellWidth; + } + if (idx == self.dataSource.count - 1) { + totalItemWidth += cellModel.cellWidth + [self getContentEdgeInsetRight]; + }else { + totalItemWidth += cellModel.cellWidth + self.innerCellSpacing; + } + }]; + + CGFloat minX = 0; + CGFloat maxX = totalItemWidth - self.bounds.size.width; + CGFloat targetX = frameXOfSelectedCell - self.bounds.size.width/2.0 + selectedCellWidth/2.0; + CGPoint collectionViewContentOffset = self.collectionView.contentOffset; + collectionViewContentOffset.x = MAX(MIN(maxX, targetX), minX); + + [self.collectionView setContentOffset:collectionViewContentOffset + animated:NO]; + //---------------------定位collectionView到当前选中的位置---------------------- + + if (CGRectEqualToRect(self.contentScrollView.frame, CGRectZero) && self.contentScrollView.superview != nil) { + //某些情况系统会出现JXCategoryView先布局,contentScrollView后布局。就会导致下面指定defaultSelectedIndex失效,所以发现contentScrollView的frame为zero时,强行触发其父视图链里面已经有frame的一个父视图的layoutSubviews方法。 + //比如JXSegmentedListContainerView会将contentScrollView包裹起来使用,该情况需要JXSegmentedListContainerView.superView触发布局更新 + UIView *parentView = self.contentScrollView.superview; + while (parentView != nil && CGRectEqualToRect(parentView.frame, CGRectZero)) { + parentView = parentView.superview; + } + [parentView setNeedsLayout]; + [parentView layoutIfNeeded]; + } + //将contentScrollView的contentOffset定位到当前选中index的位置 + CGPoint contentScrollViewContentOffset = self.contentScrollView.contentOffset; + contentScrollViewContentOffset.x = self.selectedIndex*self.contentScrollView.bounds.size.width; + [self.contentScrollView setContentOffset:contentScrollViewContentOffset animated:NO]; +} + +- (BOOL)selectCellAtIndex:(NSInteger)targetIndex selectedType:(JXCategoryCellSelectedType)selectedType { + if (targetIndex < 0 || targetIndex >= self.dataSource.count) { + return NO; + } + + self.needReloadByBecomeActive = NO; + if (self.selectedIndex == targetIndex) { + //目标index和当前选中的index相等,就不需要处理后续的选中更新逻辑,只需要回调代理方法即可。 + if (selectedType == JXCategoryCellSelectedTypeCode) { + [self.listContainer didClickSelectedItemAtIndex:targetIndex]; + }else if (selectedType == JXCategoryCellSelectedTypeClick) { + [self.listContainer didClickSelectedItemAtIndex:targetIndex]; + if (self.delegateFlags.didClickSelectedItemAtIndexFlag) { + [self.delegate categoryView:self didClickSelectedItemAtIndex:targetIndex]; + } + }else if (selectedType == JXCategoryCellSelectedTypeScroll) { + if (self.delegateFlags.didScrollSelectedItemAtIndexFlag) { + [self.delegate categoryView:self didScrollSelectedItemAtIndex:targetIndex]; + } + } + if (self.delegateFlags.didSelectedItemAtIndexFlag) { + [self.delegate categoryView:self didSelectedItemAtIndex:targetIndex]; + } + self.scrollingTargetIndex = -1; + return NO; + } + + //通知子类刷新当前选中的和将要选中的cellModel + JXCategoryBaseCellModel *lastCellModel = self.dataSource[self.selectedIndex]; + lastCellModel.selectedType = selectedType; + JXCategoryBaseCellModel *selectedCellModel = self.dataSource[targetIndex]; + selectedCellModel.selectedType = selectedType; + [self refreshSelectedCellModel:selectedCellModel unselectedCellModel:lastCellModel]; + + //刷新当前选中的和将要选中的cell + JXCategoryBaseCell *lastCell = (JXCategoryBaseCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.selectedIndex inSection:0]]; + [lastCell reloadData:lastCellModel]; + JXCategoryBaseCell *selectedCell = (JXCategoryBaseCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0]]; + [selectedCell reloadData:selectedCellModel]; + + if (self.scrollingTargetIndex != -1 && self.scrollingTargetIndex != targetIndex) { + JXCategoryBaseCellModel *scrollingTargetCellModel = self.dataSource[self.scrollingTargetIndex]; + scrollingTargetCellModel.selected = NO; + scrollingTargetCellModel.selectedType = selectedType; + [self refreshSelectedCellModel:selectedCellModel unselectedCellModel:scrollingTargetCellModel]; + JXCategoryBaseCell *scrollingTargetCell = (JXCategoryBaseCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.scrollingTargetIndex inSection:0]]; + [scrollingTargetCell reloadData:scrollingTargetCellModel]; + } + + if (self.isCellWidthZoomEnabled) { + [self.collectionView.collectionViewLayout invalidateLayout]; + //延时为了解决cellwidth变化,点击最后几个cell,scrollToItem会出现位置偏移bu。需要等cellWidth动画渐变结束后再滚动到index的cell位置。 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.selectedAnimationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES]; + }); + } else { + [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES]; + } + + if (selectedType == JXCategoryCellSelectedTypeClick || + selectedType == JXCategoryCellSelectedTypeCode) { + CGPoint offset = self.contentScrollView.contentOffset; + offset.x = + targetIndex*self.contentScrollView.bounds.size.width; + [self.contentScrollView setContentOffset:offset + animated:self.isContentScrollViewClickTransitionAnimationEnabled]; + } + + self.selectedIndex = targetIndex; + if (selectedType == JXCategoryCellSelectedTypeCode) { + [self.listContainer didClickSelectedItemAtIndex:targetIndex]; + } else if (selectedType == JXCategoryCellSelectedTypeClick) { + [self.listContainer didClickSelectedItemAtIndex:targetIndex]; + if (self.delegateFlags.didClickSelectedItemAtIndexFlag) { + [self.delegate categoryView:self didClickSelectedItemAtIndex:targetIndex]; + } + } else if(selectedType == JXCategoryCellSelectedTypeScroll) { + if (self.delegateFlags.didScrollSelectedItemAtIndexFlag) { + [self.delegate categoryView:self didScrollSelectedItemAtIndex:targetIndex]; + } + } + if (self.delegateFlags.didSelectedItemAtIndexFlag) { + [self.delegate categoryView:self didSelectedItemAtIndex:targetIndex]; + } + self.scrollingTargetIndex = -1; + + return YES; +} + + +- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel { + selectedCellModel.selected = YES; + unselectedCellModel.selected = NO; + + if (self.isCellWidthZoomEnabled) { + if (selectedCellModel.selectedType == JXCategoryCellSelectedTypeCode || + selectedCellModel.selectedType == JXCategoryCellSelectedTypeClick) { + self.animator = [[JXCategoryViewAnimator alloc] init]; + self.animator.duration = self.selectedAnimationDuration; + __weak typeof(self) weakSelf = self; + self.animator.progressCallback = ^(CGFloat percent) { + selectedCellModel.transitionAnimating = YES; + unselectedCellModel.transitionAnimating = YES; + selectedCellModel.cellWidthCurrentZoomScale = [JXCategoryFactory interpolationFrom:selectedCellModel.cellWidthNormalZoomScale to:selectedCellModel.cellWidthSelectedZoomScale percent:percent]; + selectedCellModel.cellWidth = [weakSelf getCellWidthAtIndex:selectedCellModel.index] * selectedCellModel.cellWidthCurrentZoomScale; + unselectedCellModel.cellWidthCurrentZoomScale = [JXCategoryFactory interpolationFrom:unselectedCellModel.cellWidthSelectedZoomScale to:unselectedCellModel.cellWidthNormalZoomScale percent:percent]; + unselectedCellModel.cellWidth = [weakSelf getCellWidthAtIndex:unselectedCellModel.index] * unselectedCellModel.cellWidthCurrentZoomScale; + [weakSelf.collectionView.collectionViewLayout invalidateLayout]; + }; + self.animator.completeCallback = ^{ + selectedCellModel.transitionAnimating = NO; + unselectedCellModel.transitionAnimating = NO; + }; + [self.animator start]; + } else { + selectedCellModel.cellWidthCurrentZoomScale = selectedCellModel.cellWidthSelectedZoomScale; + selectedCellModel.cellWidth = [self getCellWidthAtIndex:selectedCellModel.index] * selectedCellModel.cellWidthCurrentZoomScale; + unselectedCellModel.cellWidthCurrentZoomScale = unselectedCellModel.cellWidthNormalZoomScale; + unselectedCellModel.cellWidth = [self getCellWidthAtIndex:unselectedCellModel.index] * unselectedCellModel.cellWidthCurrentZoomScale; + } + } +} + +- (void)contentOffsetOfContentScrollViewDidChanged:(CGPoint)contentOffset { + if (self.dataSource.count == 0) { + return; + } + CGFloat ratio = contentOffset.x/self.contentScrollView.bounds.size.width; + if (ratio > self.dataSource.count - 1 || ratio < 0) { + //超过了边界,不需要处理 + return; + } + if (contentOffset.x == 0 && self.selectedIndex == 0 && self.lastContentViewContentOffset.x == 0) { + //滚动到了最左边,且已经选中了第一个,且之前的contentOffset.x为0 + return; + } + CGFloat maxContentOffsetX = self.contentScrollView.contentSize.width - self.contentScrollView.bounds.size.width; + if (contentOffset.x == maxContentOffsetX && self.selectedIndex == self.dataSource.count - 1 && self.lastContentViewContentOffset.x == maxContentOffsetX) { + //滚动到了最右边,且已经选中了最后一个,且之前的contentOffset.x为maxContentOffsetX + return; + } + ratio = MAX(0, MIN(self.dataSource.count - 1, ratio)); + NSInteger baseIndex = floorf(ratio); + CGFloat remainderRatio = ratio - baseIndex; + + if (remainderRatio == 0) { + //快速滑动翻页,用户一直在拖拽contentScrollView,需要更新选中状态 + //滑动一小段距离,然后放开回到原位,contentOffset同样的值会回调多次。例如在index为1的情况,滑动放开回到原位,contentOffset会多次回调CGPoint(width, 0) + if (!(self.lastContentViewContentOffset.x == contentOffset.x && self.selectedIndex == baseIndex)) { + [self scrollSelectItemAtIndex:baseIndex]; + } + } else { + self.needReloadByBecomeActive = YES; + if (self.animator.isExecuting) { + [self.animator invalid]; + //需要重置之前animator.progessCallback为处理完的状态 + for (JXCategoryBaseCellModel *model in self.dataSource) { + if (model.isSelected) { + model.cellWidthCurrentZoomScale = model.cellWidthSelectedZoomScale; + model.cellWidth = [self getCellWidthAtIndex:model.index] * model.cellWidthCurrentZoomScale; + }else { + model.cellWidthCurrentZoomScale = model.cellWidthNormalZoomScale; + model.cellWidth = [self getCellWidthAtIndex:model.index] * model.cellWidthCurrentZoomScale; + } + } + } + //快速滑动翻页,当remainderRatio没有变成0,但是已经翻页了,需要通过下面的判断,触发选中 + if (fabs(ratio - self.selectedIndex) > 1) { + NSInteger targetIndex = baseIndex; + if (ratio < self.selectedIndex) { + targetIndex = baseIndex + 1; + } + [self scrollSelectItemAtIndex:targetIndex]; + } + + if (self.selectedIndex == baseIndex) { + self.scrollingTargetIndex = baseIndex + 1; + } else { + self.scrollingTargetIndex = baseIndex; + } + + if (self.isCellWidthZoomEnabled && self.isCellWidthZoomScrollGradientEnabled) { + JXCategoryBaseCellModel *leftCellModel = (JXCategoryBaseCellModel *)self.dataSource[baseIndex]; + JXCategoryBaseCellModel *rightCellModel = (JXCategoryBaseCellModel *)self.dataSource[baseIndex + 1]; + leftCellModel.cellWidthCurrentZoomScale = [JXCategoryFactory interpolationFrom:leftCellModel.cellWidthSelectedZoomScale to:leftCellModel.cellWidthNormalZoomScale percent:remainderRatio]; + leftCellModel.cellWidth = [self getCellWidthAtIndex:leftCellModel.index] * leftCellModel.cellWidthCurrentZoomScale; + rightCellModel.cellWidthCurrentZoomScale = [JXCategoryFactory interpolationFrom:rightCellModel.cellWidthNormalZoomScale to:rightCellModel.cellWidthSelectedZoomScale percent:remainderRatio]; + rightCellModel.cellWidth = [self getCellWidthAtIndex:rightCellModel.index] * rightCellModel.cellWidthCurrentZoomScale; + [self.collectionView.collectionViewLayout invalidateLayout]; + } + + if (self.delegateFlags.scrollingFromLeftIndexToRightIndexFlag) { + [self.delegate categoryView:self scrollingFromLeftIndex:baseIndex toRightIndex:baseIndex + 1 ratio:remainderRatio]; + } + } +} + +- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index { + return 0; +} + +- (Class)preferredCellClass { + return JXCategoryBaseCell.class; +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + +} + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryCollectionView.h b/Pods/JXCategoryView/Sources/Common/JXCategoryCollectionView.h new file mode 100644 index 0000000..dcf1ccb --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryCollectionView.h @@ -0,0 +1,24 @@ +// +// JXCategoryCollectionView.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/21. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXCategoryIndicatorProtocol.h" +@class JXCategoryCollectionView; + +@protocol JXCategoryCollectionViewGestureDelegate +@optional +- (BOOL)categoryCollectionView:(JXCategoryCollectionView *)collectionView gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer; +- (BOOL)categoryCollectionView:(JXCategoryCollectionView *)collectionView gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; +@end + +@interface JXCategoryCollectionView : UICollectionView + +@property (nonatomic, strong) NSArray *> *indicators; +@property (nonatomic, weak) id gestureDelegate; + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryCollectionView.m b/Pods/JXCategoryView/Sources/Common/JXCategoryCollectionView.m new file mode 100644 index 0000000..e8d4829 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryCollectionView.m @@ -0,0 +1,52 @@ +// +// JXCategoryCollectionView.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/21. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryCollectionView.h" + +@interface JXCategoryCollectionView () +@end + +@implementation JXCategoryCollectionView + +- (void)setIndicators:(NSArray *> *)indicators { + for (UIView *indicator in _indicators) { + //先移除之前的indicator + [indicator removeFromSuperview]; + } + + _indicators = indicators; + + for (UIView *indicator in indicators) { + [self addSubview:indicator]; + } +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + for (UIView *view in self.indicators) { + [self sendSubviewToBack:view]; + } +} + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + if (self.gestureDelegate && [self.gestureDelegate respondsToSelector:@selector(categoryCollectionView:gestureRecognizerShouldBegin:)]) { + return [self.gestureDelegate categoryCollectionView:self gestureRecognizerShouldBegin:gestureRecognizer]; + } + return YES; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + if (self.gestureDelegate && [self.gestureDelegate respondsToSelector:@selector(categoryCollectionView:gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) { + return [self.gestureDelegate categoryCollectionView:self gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; + } + return NO; +} + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryFactory.h b/Pods/JXCategoryView/Sources/Common/JXCategoryFactory.h new file mode 100644 index 0000000..ef28f7e --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryFactory.h @@ -0,0 +1,18 @@ +// +// JXCategoryFactory.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import + +@interface JXCategoryFactory : NSObject + ++ (CGFloat)interpolationFrom:(CGFloat)from to:(CGFloat)to percent:(CGFloat)percent; + ++ (UIColor *)interpolationColorFrom:(UIColor *)fromColor to:(UIColor *)toColor percent:(CGFloat)percent; + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryFactory.m b/Pods/JXCategoryView/Sources/Common/JXCategoryFactory.m new file mode 100644 index 0000000..c71451e --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryFactory.m @@ -0,0 +1,29 @@ +// +// JXCategoryFactory.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryFactory.h" +#import "UIColor+JXAdd.h" + +@implementation JXCategoryFactory + ++ (CGFloat)interpolationFrom:(CGFloat)from to:(CGFloat)to percent:(CGFloat)percent +{ + percent = MAX(0, MIN(1, percent)); + return from + (to - from)*percent; +} + ++ (UIColor *)interpolationColorFrom:(UIColor *)fromColor to:(UIColor *)toColor percent:(CGFloat)percent +{ + CGFloat red = [self interpolationFrom:fromColor.jx_red to:toColor.jx_red percent:percent]; + CGFloat green = [self interpolationFrom:fromColor.jx_green to:toColor.jx_green percent:percent]; + CGFloat blue = [self interpolationFrom:fromColor.jx_blue to:toColor.jx_blue percent:percent]; + CGFloat alpha = [self interpolationFrom:fromColor.jx_alpha to:toColor.jx_alpha percent:percent]; + return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +} + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorParamsModel.h b/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorParamsModel.h new file mode 100644 index 0000000..00da754 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorParamsModel.h @@ -0,0 +1,31 @@ +// +// JXCategoryIndicatorParamsModel.h +// JXCategoryView +// +// Created by jiaxin on 2018/12/13. +// Copyright © 2018 jiaxin. All rights reserved. +// + +#import +#import +#import "JXCategoryViewDefines.h" + +/** + 指示器不同情况处理时传递的数据模型,不同情况会对不同的属性赋值,根据不同情况的 api 说明确认。 + + FAQ: 为什么会通过 model 传递数据? + 因为指示器处理逻辑以后会扩展不同的使用场景,会新增参数,如果不通过 model 传递,就会在 api 新增参数,一旦修改 api 改的地方就特别多了,而且会影响到之前自定义实现的开发者。 + */ +@interface JXCategoryIndicatorParamsModel : NSObject + +@property (nonatomic, assign) NSInteger selectedIndex; // 当前选中的 index +@property (nonatomic, assign) CGRect selectedCellFrame; // 当前选中的 cellFrame +@property (nonatomic, assign) NSInteger leftIndex; // 正在过渡中的两个 cell,相对位置在左边的 cell 的 index +@property (nonatomic, assign) CGRect leftCellFrame; // 正在过渡中的两个 cell,相对位置在左边的 cell 的 frame +@property (nonatomic, assign) NSInteger rightIndex; // 正在过渡中的两个 cell,相对位置在右边的 cell 的 index +@property (nonatomic, assign) CGRect rightCellFrame; // 正在过渡中的两个 cell,相对位置在右边的 cell 的 frame +@property (nonatomic, assign) CGFloat percent; // 正在过渡中的两个 cell,从左到右的百分比 +@property (nonatomic, assign) NSInteger lastSelectedIndex; // 之前选中的 index +@property (nonatomic, assign) JXCategoryCellSelectedType selectedType; //cell 被选中类型 + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorParamsModel.m b/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorParamsModel.m new file mode 100644 index 0000000..8a0eff0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorParamsModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryIndicatorParamsModel.m +// JXCategoryView +// +// Created by jiaxin on 2018/12/13. +// Copyright © 2018 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorParamsModel.h" + +@implementation JXCategoryIndicatorParamsModel + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorProtocol.h b/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorProtocol.h new file mode 100644 index 0000000..b4f9ff0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryIndicatorProtocol.h @@ -0,0 +1,49 @@ +// +// JXCategoryIndicatorProtocol.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import +#import "JXCategoryViewDefines.h" +#import "JXCategoryIndicatorParamsModel.h" + +@protocol JXCategoryIndicatorProtocol + +/** + categoryView 重置状态时调用 + + param selectedIndex 当前选中的 index + param selectedCellFrame 当前选中的 cellFrame + @param model 数据模型 + */ +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model; + +/** + contentScrollView在进行手势滑动时,处理指示器跟随手势变化UI逻辑; + + param selectedIndex 当前选中的index + param leftIndex 正在过渡中的两个cell,相对位置在左边的cell的index + param leftCellFrame 正在过渡中的两个cell,相对位置在左边的cell的frame + param rightIndex 正在过渡中的两个cell,相对位置在右边的cell的index + param rightCellFrame 正在过渡中的两个cell,相对位置在右边的cell的frame + param percent 过渡百分比 + @param model 数据模型 + */ +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model; + +/** + 选中了某一个cell + + param lastSelectedIndex 之前选中的index + param selectedIndex 选中的index + param selectedCellFrame 选中的cellFrame + param selectedType cell被选中类型 + @param model 数据模型 + */ +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model; + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerRTLCell.h b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerRTLCell.h new file mode 100644 index 0000000..75243b4 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerRTLCell.h @@ -0,0 +1,16 @@ +// +// JXCategoryListContainerRTLCell.h +// JXCategoryView +// +// Created by jiaxin on 2020/7/3. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface JXCategoryListContainerRTLCell : UICollectionViewCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerRTLCell.m b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerRTLCell.m new file mode 100644 index 0000000..403efa9 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerRTLCell.m @@ -0,0 +1,23 @@ +// +// JXCategoryListContainerRTLCell.m +// JXCategoryView +// +// Created by jiaxin on 2020/7/3. +// + +#import "JXCategoryListContainerRTLCell.h" +#import "RTLManager.h" + +@implementation JXCategoryListContainerRTLCell + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [RTLManager horizontalFlipViewIfNeeded:self]; + [RTLManager horizontalFlipViewIfNeeded:self.contentView]; + } + return self; +} + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerView.h b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerView.h new file mode 100644 index 0000000..215b3a9 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerView.h @@ -0,0 +1,122 @@ +// +// JXCategoryListScrollView.h +// JXCategoryView +// +// Created by jiaxin on 2018/9/12. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXCategoryViewDefines.h" +#import "JXCategoryBaseView.h" +@class JXCategoryListContainerView; + +/** + 列表容器视图的类型 + + - ScrollView: UIScrollView。优势:没有其他副作用。劣势:视图内存占用相对大一点。 + - CollectionView: 使用UICollectionView。优势:因为列表被添加到cell上,视图的内存占用更少,适合内存要求特别高的场景。劣势:因为cell重用机制的问题,导致列表下拉刷新视图,会因为被removeFromSuperview而被隐藏。需要参考`LoadDataListCollectionListViewController`类做特殊处理。 + */ +typedef NS_ENUM(NSUInteger, JXCategoryListContainerType) { + JXCategoryListContainerType_ScrollView, + JXCategoryListContainerType_CollectionView, +}; + +@protocol JXCategoryListContentViewDelegate + +/** + 如果列表是VC,就返回VC.view + 如果列表是View,就返回View自己 + + @return 返回列表视图 + */ +- (UIView *)listView; + +@optional + +/** + 可选实现,列表将要显示的时候调用 + */ +- (void)listWillAppear; + +/** + 可选实现,列表显示的时候调用 + */ +- (void)listDidAppear; + +/** + 可选实现,列表将要消失的时候调用 + */ +- (void)listWillDisappear; + +/** + 可选实现,列表消失的时候调用 + */ +- (void)listDidDisappear; + +@end + +@protocol JXCategoryListContainerViewDelegate +/** + 返回list的数量 + + @param listContainerView 列表的容器视图 + @return list的数量 + */ +- (NSInteger)numberOfListsInlistContainerView:(JXCategoryListContainerView *)listContainerView; + +/** + 根据index返回一个对应列表实例,需要是遵从`JXCategoryListContentViewDelegate`协议的对象。 + 你可以代理方法调用的时候初始化对应列表,达到懒加载的效果。这也是默认推荐的初始化列表方法。你也可以提前创建好列表,等该代理方法回调的时候再返回也可以,达到预加载的效果。 + 如果列表是用自定义UIView封装的,就让自定义UIView遵从`JXCategoryListContentViewDelegate`协议,该方法返回自定义UIView即可。 + 如果列表是用自定义UIViewController封装的,就让自定义UIViewController遵从`JXCategoryListContentViewDelegate`协议,该方法返回自定义UIViewController即可。 + + @param listContainerView 列表的容器视图 + @param index 目标下标 + @return 遵从JXCategoryListContentViewDelegate协议的list实例 + */ +- (id)listContainerView:(JXCategoryListContainerView *)listContainerView initListForIndex:(NSInteger)index; + +@optional +/** + 返回自定义UIScrollView或UICollectionView的Class + 某些特殊情况需要自己处理UIScrollView内部逻辑。比如项目用了FDFullscreenPopGesture,需要处理手势相关代理。 + + @param listContainerView JXCategoryListContainerView + @return 自定义UIScrollView实例 + */ +- (Class)scrollViewClassInlistContainerView:(JXCategoryListContainerView *)listContainerView; + +/** + 控制能否初始化对应index的列表。有些业务需求,需要在某些情况才允许初始化某些列表,通过通过该代理实现控制。 + */ +- (BOOL)listContainerView:(JXCategoryListContainerView *)listContainerView canInitListAtIndex:(NSInteger)index; + +- (void)listContainerViewDidScroll:(UIScrollView *)scrollView; +- (void)listContainerViewWillBeginDragging:(UIScrollView *)scrollView; +- (void)listContainerViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; +- (void)listContainerViewWillBeginDecelerating:(UIScrollView *)scrollView; +- (void)listContainerViewDidEndDecelerating:(UIScrollView *)scrollView; + +@end + + +@interface JXCategoryListContainerView : UIView + +@property (nonatomic, assign, readonly) JXCategoryListContainerType containerType; +@property (nonatomic, strong, readonly) UIScrollView *scrollView; +@property (nonatomic, strong, readonly) NSDictionary > *validListDict; //已经加载过的列表字典。key是index,value是对应的列表 +@property (nonatomic, strong) UIColor *listCellBackgroundColor; //默认:[UIColor whiteColor] +/** + 滚动切换的时候,滚动距离超过一页的多少百分比,就触发列表的初始化。默认0.01(即列表显示了一点就触发加载)。范围0~1,开区间不包括0和1 + */ +@property (nonatomic, assign) CGFloat initListPercent; +@property (nonatomic, assign) BOOL bounces; //默认NO + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithType:(JXCategoryListContainerType)type delegate:(id)delegate NS_DESIGNATED_INITIALIZER; + +@end + diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerView.m b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerView.m new file mode 100644 index 0000000..42081b1 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryListContainerView.m @@ -0,0 +1,547 @@ +// +// JXCategoryListContainerView.m +// JXCategoryView +// +// Created by jiaxin on 2018/9/12. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryListContainerView.h" +#import +#import "RTLManager.h" + +@interface JXCategoryListContainerViewController : UIViewController +@property (copy) void(^viewWillAppearBlock)(void); +@property (copy) void(^viewDidAppearBlock)(void); +@property (copy) void(^viewWillDisappearBlock)(void); +@property (copy) void(^viewDidDisappearBlock)(void); +@end + +@implementation JXCategoryListContainerViewController +- (void)dealloc +{ + self.viewWillAppearBlock = nil; + self.viewDidAppearBlock = nil; + self.viewWillDisappearBlock = nil; + self.viewDidDisappearBlock = nil; +} +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + self.viewWillAppearBlock(); +} +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + self.viewDidAppearBlock(); +} +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + self.viewWillDisappearBlock(); +} +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + self.viewDidDisappearBlock(); +} +- (BOOL)shouldAutomaticallyForwardAppearanceMethods { return NO; } +@end + +@interface JXCategoryListContainerView () +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, assign) NSInteger currentIndex; +@property (nonatomic, strong) NSMutableDictionary > *validListDict; +@property (nonatomic, assign) NSInteger willAppearIndex; +@property (nonatomic, assign) NSInteger willDisappearIndex; +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) JXCategoryListContainerViewController *containerVC; +@end + +@implementation JXCategoryListContainerView + +- (instancetype)initWithType:(JXCategoryListContainerType)type delegate:(id)delegate{ + self = [super initWithFrame:CGRectZero]; + if (self) { + _containerType = type; + _delegate = delegate; + _validListDict = [NSMutableDictionary dictionary]; + _willAppearIndex = -1; + _willDisappearIndex = -1; + _initListPercent = 0.01; + [self initializeViews]; + } + return self; +} + +- (void)initializeViews { + _listCellBackgroundColor = [UIColor whiteColor]; + _containerVC = [[JXCategoryListContainerViewController alloc] init]; + self.containerVC.view.backgroundColor = [UIColor clearColor]; + [self addSubview:self.containerVC.view]; + __weak typeof(self) weakSelf = self; + self.containerVC.viewWillAppearBlock = ^{ + [weakSelf listWillAppear:weakSelf.currentIndex]; + }; + self.containerVC.viewDidAppearBlock = ^{ + [weakSelf listDidAppear:weakSelf.currentIndex]; + }; + self.containerVC.viewWillDisappearBlock = ^{ + [weakSelf listWillDisappear:weakSelf.currentIndex]; + }; + self.containerVC.viewDidDisappearBlock = ^{ + [weakSelf listDidDisappear:weakSelf.currentIndex]; + }; + if (self.containerType == JXCategoryListContainerType_ScrollView) { + if (self.delegate && + [self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerView:)] && + [[self.delegate scrollViewClassInlistContainerView:self] isKindOfClass:object_getClass([UIScrollView class])]) { + _scrollView = (UIScrollView *)[[[self.delegate scrollViewClassInlistContainerView:self] alloc] init]; + }else { + _scrollView = [[UIScrollView alloc] init]; + } + self.scrollView.delegate = self; + self.scrollView.pagingEnabled = YES; + self.scrollView.showsHorizontalScrollIndicator = NO; + self.scrollView.showsVerticalScrollIndicator = NO; + self.scrollView.scrollsToTop = NO; + self.scrollView.bounces = NO; + if (@available(iOS 11.0, *)) { + if ([self.scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { + self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + } + [RTLManager horizontalFlipViewIfNeeded:self.scrollView]; + [self.containerVC.view addSubview:self.scrollView]; + }else { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + layout.minimumLineSpacing = 0; + layout.minimumInteritemSpacing = 0; + if (self.delegate && + [self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerView:)] && + [[self.delegate scrollViewClassInlistContainerView:self] isKindOfClass:object_getClass([UICollectionView class])]) { + _collectionView = (UICollectionView *)[[[self.delegate scrollViewClassInlistContainerView:self] alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + }else { + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + } + self.collectionView.pagingEnabled = YES; + self.collectionView.showsHorizontalScrollIndicator = NO; + self.collectionView.showsVerticalScrollIndicator = NO; + self.collectionView.scrollsToTop = NO; + self.collectionView.bounces = NO; + self.collectionView.dataSource = self; + self.collectionView.delegate = self; + [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; + if (@available(iOS 10.0, *)) { + self.collectionView.prefetchingEnabled = NO; + } + if (@available(iOS 11.0, *)) { + if ([self.collectionView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { + self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + } + if ([RTLManager supportRTL]) { + self.collectionView.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; + [RTLManager horizontalFlipView:self.collectionView]; + } + [self.containerVC.view addSubview:self.collectionView]; + //让外部统一访问scrollView + _scrollView = _collectionView; + } +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + + UIResponder *next = newSuperview; + while (next != nil) { + if ([next isKindOfClass:[UIViewController class]]) { + [((UIViewController *)next) addChildViewController:self.containerVC]; + break; + } + next = next.nextResponder; + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + self.containerVC.view.frame = self.bounds; + if (self.containerType == JXCategoryListContainerType_ScrollView) { + if (CGRectEqualToRect(self.scrollView.frame, CGRectZero) || !CGSizeEqualToSize(self.scrollView.bounds.size, self.bounds.size)) { + self.scrollView.frame = self.bounds; + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height); + [_validListDict enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull index, id _Nonnull list, BOOL * _Nonnull stop) { + [list listView].frame = CGRectMake(index.intValue*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); + }]; + CGPoint scrollViewContentOffset = self.scrollView.contentOffset; + scrollViewContentOffset.x = self.currentIndex*self.scrollView.bounds.size.width; + self.scrollView.contentOffset = scrollViewContentOffset; + }else { + self.scrollView.frame = self.bounds; + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height); + } + }else { + if (CGRectEqualToRect(self.collectionView.frame, CGRectZero) || !CGSizeEqualToSize(self.collectionView.bounds.size, self.bounds.size)) { + [self.collectionView.collectionViewLayout invalidateLayout]; + self.collectionView.frame = self.bounds; + [self.collectionView reloadData]; + CGPoint collectionViewContentOffset = self.collectionView.contentOffset; + collectionViewContentOffset.x = + self.collectionView.bounds.size.width*self.currentIndex; + [self.collectionView setContentOffset:collectionViewContentOffset animated:NO]; + }else { + self.collectionView.frame = self.bounds; + } + } +} + + +- (void)setinitListPercent:(CGFloat)initListPercent { + _initListPercent = initListPercent; + if (initListPercent <= 0 || initListPercent >= 1) { + NSAssert(NO, @"initListPercent值范围为开区间(0,1),即不包括0和1"); + } +} + +- (void)setBounces:(BOOL)bounces { + _bounces = bounces; + self.scrollView.bounces = bounces; +} + +#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return [self.delegate numberOfListsInlistContainerView:self]; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; + cell.contentView.backgroundColor = self.listCellBackgroundColor; + + UIView* listView = nil; + id list = _validListDict[@(indexPath.item)]; + if (list != nil) { + //fixme:如果list是UIViewController,如果这里的frame修改是`[list listView].frame = cell.bounds;`。那么就必须给list vc添加如下代码: + //- (void)loadView { + // self.view = [[UIView alloc] init]; + //} + //所以,总感觉是把UIViewController当做普通view使用,导致了系统内部的bug。所以,缓兵之计就是用下面的方法,暂时解决问题。 + listView = [list listView]; + if ([list isKindOfClass:[UIViewController class]]) { + listView.frame = cell.contentView.bounds; + } else { + listView.frame = cell.bounds; + } + } + + BOOL isAdded = NO; + for (UIView *subview in cell.contentView.subviews) { + if( listView != subview ) { + [subview removeFromSuperview]; + } else { + isAdded = YES; + } + } + + if( !isAdded && listView ) { + [cell.contentView addSubview:listView]; + } + + // 针对 RTL 布局 + if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:self.semanticContentAttribute] + == UIUserInterfaceLayoutDirectionRightToLeft) { + cell.contentView.transform = CGAffineTransformMakeScale(-1, 1); + } + + return cell; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return self.bounds.size; +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewDidScroll:)]) { + [self.delegate listContainerViewDidScroll:scrollView]; + } + + if (!scrollView.isDragging && !scrollView.isTracking && !scrollView.isDecelerating) { + return; + } + CGFloat ratio = scrollView.contentOffset.x/scrollView.bounds.size.width; + NSInteger maxCount = round(scrollView.contentSize.width/scrollView.bounds.size.width); + NSInteger leftIndex = floorf(ratio); + leftIndex = MAX(0, MIN(maxCount - 1, leftIndex)); + NSInteger rightIndex = leftIndex + 1; + if (ratio < 0 || rightIndex >= maxCount) { + [self listDidAppearOrDisappear:scrollView]; + return; + } + CGFloat remainderRatio = ratio - leftIndex; + if (rightIndex == self.currentIndex) { + //当前选中的在右边,用户正在从右边往左边滑动 + if (self.validListDict[@(leftIndex)] == nil && remainderRatio < (1 - self.initListPercent)) { + [self initListIfNeededAtIndex:leftIndex]; + }else if (self.validListDict[@(leftIndex)] != nil) { + if (self.willAppearIndex == -1) { + self.willAppearIndex = leftIndex; + [self listWillAppear:self.willAppearIndex]; + } + } + if (self.willDisappearIndex == -1) { + self.willDisappearIndex = rightIndex; + [self listWillDisappear:self.willDisappearIndex]; + } + }else { + //当前选中的在左边,用户正在从左边往右边滑动 + if (self.validListDict[@(rightIndex)] == nil && remainderRatio > self.initListPercent) { + [self initListIfNeededAtIndex:rightIndex]; + }else if (self.validListDict[@(rightIndex)] != nil) { + if (self.willAppearIndex == -1) { + self.willAppearIndex = rightIndex; + [self listWillAppear:self.willAppearIndex]; + } + } + if (self.willDisappearIndex == -1) { + self.willDisappearIndex = leftIndex; + [self listWillDisappear:self.willDisappearIndex]; + } + } + [self listDidAppearOrDisappear:scrollView]; +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + //滑动到一半又取消滑动处理 + if (self.willDisappearIndex != -1) { + [self listWillAppear:self.willDisappearIndex]; + [self listWillDisappear:self.willAppearIndex]; + [self listDidAppear:self.willDisappearIndex]; + [self listDidDisappear:self.willAppearIndex]; + self.willDisappearIndex = -1; + self.willAppearIndex = -1; + } + + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewDidEndDecelerating:)]) { + [self.delegate listContainerViewDidEndDecelerating:scrollView]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWillBeginDragging:)]) { + [self.delegate listContainerViewWillBeginDragging:scrollView]; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate +{ + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewDidEndDragging:willDecelerate:)]) { + [self.delegate listContainerViewDidEndDragging:scrollView willDecelerate:decelerate]; + } +} + +- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView +{ + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWillBeginDecelerating:)]) { + [self.delegate listContainerViewWillBeginDecelerating:scrollView]; + } +} + +#pragma mark - JXCategoryViewListContainer + +- (UIScrollView *)contentScrollView { + return self.scrollView; +} + +- (void)setDefaultSelectedIndex:(NSInteger)index { + self.currentIndex = index; +} + +- (void)didClickSelectedItemAtIndex:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + self.willAppearIndex = -1; + self.willDisappearIndex = -1; + if (self.currentIndex != index) { + [self listWillDisappear:self.currentIndex]; + [self listDidDisappear:self.currentIndex]; + [self listWillAppear:index]; + [self listDidAppear:index]; + } +} + +- (void)reloadData { + for (id list in _validListDict.allValues) { + [[list listView] removeFromSuperview]; + if ([list isKindOfClass:[UIViewController class]]) { + [(UIViewController *)list removeFromParentViewController]; + } + } + [_validListDict removeAllObjects]; + + if (self.containerType == JXCategoryListContainerType_ScrollView) { + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height); + }else { + [self.collectionView reloadData]; + } + [self listWillAppear:self.currentIndex]; + [self listDidAppear:self.currentIndex]; +} + +#pragma mark - Private + +- (void)initListIfNeededAtIndex:(NSInteger)index { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:canInitListAtIndex:)]) { + BOOL canInitList = [self.delegate listContainerView:self canInitListAtIndex:index]; + if (!canInitList) { + return; + } + } + id list = _validListDict[@(index)]; + if (list != nil) { + //列表已经创建好了 + return; + } + list = [self.delegate listContainerView:self initListForIndex:index]; + if ([list isKindOfClass:[UIViewController class]]) { + [self.containerVC addChildViewController:(UIViewController *)list]; + } + _validListDict[@(index)] = list; + + if (self.containerType == JXCategoryListContainerType_ScrollView) { + [list listView].frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); + [self.scrollView addSubview:[list listView]]; + [RTLManager horizontalFlipViewIfNeeded:[list listView]]; + }else { + UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + [list listView].frame = cell.contentView.bounds; + [cell.contentView addSubview:[list listView]]; + } +} + +- (void)listWillAppear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + id list = _validListDict[@(index)]; + if (list == nil) { + //当前列表未被创建(页面初始化或通过点击触发的listWillAppear) + BOOL canInitList = YES; + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:canInitListAtIndex:)]) { + canInitList = [self.delegate listContainerView:self canInitListAtIndex:index]; + } + if (!canInitList) { + return; + } + list = [self.delegate listContainerView:self initListForIndex:index]; + if ([list isKindOfClass:[UIViewController class]]) { + [self.containerVC addChildViewController:(UIViewController *)list]; + } + _validListDict[@(index)] = list; + if (self.containerType == JXCategoryListContainerType_ScrollView) { + if ([list listView].superview == nil) { + [list listView].frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); + [self.scrollView addSubview:[list listView]]; + [RTLManager horizontalFlipViewIfNeeded:[list listView]]; + } + }else { + UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + [list listView].frame = cell.contentView.bounds; + [cell.contentView addSubview:[list listView]]; + } + } + + if (list && [list respondsToSelector:@selector(listWillAppear)]) { + [list listWillAppear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC beginAppearanceTransition:YES animated:NO]; + } +} + +- (void)listDidAppear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + self.currentIndex = index; + id list = _validListDict[@(index)]; + if (list && [list respondsToSelector:@selector(listDidAppear)]) { + [list listDidAppear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC endAppearanceTransition]; + } +} + +- (void)listWillDisappear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + id list = _validListDict[@(index)]; + if (list && [list respondsToSelector:@selector(listWillDisappear)]) { + [list listWillDisappear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC beginAppearanceTransition:NO animated:NO]; + } +} + +- (void)listDidDisappear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + id list = _validListDict[@(index)]; + if (list && [list respondsToSelector:@selector(listDidDisappear)]) { + [list listDidDisappear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC endAppearanceTransition]; + } +} + +- (BOOL)checkIndexValid:(NSInteger)index { + NSUInteger count = [self.delegate numberOfListsInlistContainerView:self]; + if (count <= 0 || index >= count) { + return NO; + } + return YES; +} + +- (void)listDidAppearOrDisappear:(UIScrollView *)scrollView { + CGFloat currentIndexPercent = scrollView.contentOffset.x/scrollView.bounds.size.width; + if (self.willAppearIndex != -1 || self.willDisappearIndex != -1) { + NSInteger disappearIndex = self.willDisappearIndex; + NSInteger appearIndex = self.willAppearIndex; + if (self.willAppearIndex > self.willDisappearIndex) { + //将要出现的列表在右边 + if (currentIndexPercent >= self.willAppearIndex) { + self.willDisappearIndex = -1; + self.willAppearIndex = -1; + [self listDidDisappear:disappearIndex]; + [self listDidAppear:appearIndex]; + } + }else { + //将要出现的列表在左边 + if (currentIndexPercent <= self.willAppearIndex) { + self.willDisappearIndex = -1; + self.willAppearIndex = -1; + [self listDidDisappear:disappearIndex]; + [self listDidAppear:appearIndex]; + } + } + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryViewAnimator.h b/Pods/JXCategoryView/Sources/Common/JXCategoryViewAnimator.h new file mode 100644 index 0000000..2c7acae --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryViewAnimator.h @@ -0,0 +1,24 @@ +// +// JXCategoryViewAnimator.h +// JXCategoryView +// +// Created by jiaxin on 2019/1/24. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import +#import + +@interface JXCategoryViewAnimator : NSObject + +@property (nonatomic, assign) NSTimeInterval duration; +@property (nonatomic, copy) void(^progressCallback)(CGFloat percent); +@property (nonatomic, copy) void(^completeCallback)(void); +@property (readonly, getter=isExecuting) BOOL executing; + +- (void)start; +- (void)stop; +- (void)invalid; + +@end + diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryViewAnimator.m b/Pods/JXCategoryView/Sources/Common/JXCategoryViewAnimator.m new file mode 100644 index 0000000..fc26144 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryViewAnimator.m @@ -0,0 +1,75 @@ +// +// JXCategoryViewAnimator.m +// JXCategoryView +// +// Created by jiaxin on 2019/1/24. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryViewAnimator.h" + +@interface JXCategoryViewAnimator () +@property (nonatomic, strong) CADisplayLink *displayLink; +@property (nonatomic, assign) CFTimeInterval firstTimestamp; +@property (readwrite, getter=isExecuting) BOOL executing; +@end + +@implementation JXCategoryViewAnimator + +#pragma mark - Initialize + +- (void)dealloc { + self.progressCallback = nil; + self.completeCallback = nil; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _executing = NO; + _duration = 0.25; + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(processDisplayLink:)]; + } + return self; +} + +#pragma mark - Public + +- (void)start { + [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + self.executing = YES; +} + +- (void)stop { + !self.progressCallback ?: self.progressCallback(1); + [self.displayLink invalidate]; + !self.completeCallback ?: self.completeCallback(); + self.executing = NO; +} + +- (void)invalid { + [self.displayLink invalidate]; + !self.completeCallback ?: self.completeCallback(); + self.executing = NO; +} + +#pragma mark - Actions + +- (void)processDisplayLink:(CADisplayLink *)sender { + if (self.firstTimestamp == 0) { + self.firstTimestamp = sender.timestamp; + return; + } + CGFloat percent = (sender.timestamp - self.firstTimestamp)/self.duration; + if (percent >= 1) { + !self.progressCallback ?: self.progressCallback(percent); + [self.displayLink invalidate]; + !self.completeCallback ?: self.completeCallback(); + self.executing = NO; + }else { + !self.progressCallback ?: self.progressCallback(percent); + self.executing = YES; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Common/JXCategoryViewDefines.h b/Pods/JXCategoryView/Sources/Common/JXCategoryViewDefines.h new file mode 100644 index 0000000..ec3a60c --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/JXCategoryViewDefines.h @@ -0,0 +1,43 @@ +// +// JXCategoryViewDefines.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import + +static const CGFloat JXCategoryViewAutomaticDimension = -1; + +typedef void(^JXCategoryCellSelectedAnimationBlock)(CGFloat percent); + +// 指示器的位置 +typedef NS_ENUM(NSUInteger, JXCategoryComponentPosition) { + JXCategoryComponentPosition_Bottom, + JXCategoryComponentPosition_Top +}; + +// cell 被选中的类型 +typedef NS_ENUM(NSUInteger, JXCategoryCellSelectedType) { + JXCategoryCellSelectedTypeUnknown, // 未知,不是选中(cellForRow方法里面、两个cell过渡时) + JXCategoryCellSelectedTypeClick, // 点击选中 + JXCategoryCellSelectedTypeCode, // 调用方法 selectItemAtIndex: 选中 + JXCategoryCellSelectedTypeScroll // 通过滚动到某个 cell 选中 +}; + +// cell 标题锚点位置 +typedef NS_ENUM(NSUInteger, JXCategoryTitleLabelAnchorPointStyle) { + JXCategoryTitleLabelAnchorPointStyleCenter, + JXCategoryTitleLabelAnchorPointStyleTop, + JXCategoryTitleLabelAnchorPointStyleBottom +}; + +// 指示器滚动样式 +typedef NS_ENUM(NSUInteger, JXCategoryIndicatorScrollStyle) { + JXCategoryIndicatorScrollStyleSimple, // 简单滚动,即从当前位置过渡到目标位置 + JXCategoryIndicatorScrollStyleSameAsUserScroll // 和用户左右滚动列表时的效果一样 +}; + +#define JXCategoryViewDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead) diff --git a/Pods/JXCategoryView/Sources/Common/UIColor+JXAdd.h b/Pods/JXCategoryView/Sources/Common/UIColor+JXAdd.h new file mode 100644 index 0000000..06e1c14 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/UIColor+JXAdd.h @@ -0,0 +1,18 @@ +// +// UIColor+JXAdd.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/21. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import + +@interface UIColor (JXAdd) + +@property (nonatomic, assign, readonly) CGFloat jx_red; +@property (nonatomic, assign, readonly) CGFloat jx_green; +@property (nonatomic, assign, readonly) CGFloat jx_blue; +@property (nonatomic, assign, readonly) CGFloat jx_alpha; + +@end diff --git a/Pods/JXCategoryView/Sources/Common/UIColor+JXAdd.m b/Pods/JXCategoryView/Sources/Common/UIColor+JXAdd.m new file mode 100644 index 0000000..f76c11b --- /dev/null +++ b/Pods/JXCategoryView/Sources/Common/UIColor+JXAdd.m @@ -0,0 +1,35 @@ +// +// UIColor+JXAdd.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/21. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "UIColor+JXAdd.h" + +@implementation UIColor (JXAdd) + +- (CGFloat)jx_red { + CGFloat r = 0, g, b, a; + [self getRed:&r green:&g blue:&b alpha:&a]; + return r; +} + +- (CGFloat)jx_green { + CGFloat r, g = 0, b, a; + [self getRed:&r green:&g blue:&b alpha:&a]; + return g; +} + +- (CGFloat)jx_blue { + CGFloat r, g, b = 0, a; + [self getRed:&r green:&g blue:&b alpha:&a]; + return b; +} + +- (CGFloat)jx_alpha { + return CGColorGetAlpha(self.CGColor); +} + +@end diff --git a/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCell.h b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCell.h new file mode 100644 index 0000000..14d3019 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCell.h @@ -0,0 +1,13 @@ +// +// JXCategoryDotCell.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCell.h" + +@interface JXCategoryDotCell : JXCategoryTitleCell + +@end diff --git a/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCell.m b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCell.m new file mode 100644 index 0000000..2022acd --- /dev/null +++ b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCell.m @@ -0,0 +1,64 @@ +// +// JXCategoryDotCell.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryDotCell.h" +#import "JXCategoryDotCellModel.h" + +@interface JXCategoryDotCell () +@property (nonatomic, strong) UIView *dot; +@end + +@implementation JXCategoryDotCell + +- (void)initializeViews { + [super initializeViews]; + + _dot = [[UIView alloc] init]; + [self.contentView addSubview:self.dot]; + self.dot.translatesAutoresizingMaskIntoConstraints = NO; +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryDotCellModel *myCellModel = (JXCategoryDotCellModel *)cellModel; + self.dot.hidden = !myCellModel.dotHidden; + self.dot.backgroundColor = myCellModel.dotColor; + self.dot.layer.cornerRadius = myCellModel.dotCornerRadius; + [NSLayoutConstraint deactivateConstraints:self.dot.constraints]; + [self.dot.widthAnchor constraintEqualToConstant:myCellModel.dotSize.width].active = YES; + [self.dot.heightAnchor constraintEqualToConstant:myCellModel.dotSize.height].active = YES; + switch (myCellModel.relativePosition) { + case JXCategoryDotRelativePosition_TopLeft: + { + [self.dot.centerXAnchor constraintEqualToAnchor:self.titleLabel.leadingAnchor constant:myCellModel.dotOffset.x].active = YES; + [self.dot.centerYAnchor constraintEqualToAnchor:self.titleLabel.topAnchor constant:myCellModel.dotOffset.y].active = YES; + } + break; + case JXCategoryDotRelativePosition_TopRight: + { + [self.dot.centerXAnchor constraintEqualToAnchor:self.titleLabel.trailingAnchor constant:myCellModel.dotOffset.x].active = YES; + [self.dot.centerYAnchor constraintEqualToAnchor:self.titleLabel.topAnchor constant:myCellModel.dotOffset.y].active = YES; + } + break; + case JXCategoryDotRelativePosition_BottomLeft: + { + [self.dot.centerXAnchor constraintEqualToAnchor:self.titleLabel.leadingAnchor constant:myCellModel.dotOffset.x].active = YES; + [self.dot.centerYAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:myCellModel.dotOffset.y].active = YES; + } + break; + case JXCategoryDotRelativePosition_BottomRight: + { + [self.dot.centerXAnchor constraintEqualToAnchor:self.titleLabel.trailingAnchor constant:myCellModel.dotOffset.x].active = YES; + [self.dot.centerYAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:myCellModel.dotOffset.y].active = YES; + } + break; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCellModel.h b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCellModel.h new file mode 100644 index 0000000..b0531a9 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCellModel.h @@ -0,0 +1,27 @@ +// +// JXCategoryDotCellModel.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCellModel.h" + +typedef NS_ENUM(NSUInteger, JXCategoryDotRelativePosition) { + JXCategoryDotRelativePosition_TopLeft = 0, + JXCategoryDotRelativePosition_TopRight, + JXCategoryDotRelativePosition_BottomLeft, + JXCategoryDotRelativePosition_BottomRight, +}; + +@interface JXCategoryDotCellModel : JXCategoryTitleCellModel + +@property (nonatomic, assign) BOOL dotHidden; +@property (nonatomic, assign) JXCategoryDotRelativePosition relativePosition; +@property (nonatomic, assign) CGSize dotSize; +@property (nonatomic, assign) CGFloat dotCornerRadius; +@property (nonatomic, strong) UIColor *dotColor; +@property (nonatomic, assign) CGPoint dotOffset; + +@end diff --git a/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCellModel.m b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCellModel.m new file mode 100644 index 0000000..054cbfc --- /dev/null +++ b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotCellModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryDotCellModel.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryDotCellModel.h" + +@implementation JXCategoryDotCellModel + +@end diff --git a/Pods/JXCategoryView/Sources/Dot/JXCategoryDotView.h b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotView.h new file mode 100644 index 0000000..1cc9ad9 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotView.h @@ -0,0 +1,30 @@ +// +// JXCategoryDotView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleView.h" +#import "JXCategoryDotCell.h" +#import "JXCategoryDotCellModel.h" + +@interface JXCategoryDotView : JXCategoryTitleView + +//相对于titleLabel的位置,默认:JXCategoryDotRelativePosition_TopRight +@property (nonatomic, assign) JXCategoryDotRelativePosition relativePosition; +//@[@(布尔值)]数组,控制红点是否显示 +@property (nonatomic, strong) NSArray *dotStates; +//红点的尺寸。默认:CGSizeMake(10, 10) +@property (nonatomic, assign) CGSize dotSize; +//红点的圆角值。默认:JXCategoryViewAutomaticDimension(self.dotSize.height/2) +@property (nonatomic, assign) CGFloat dotCornerRadius; +//红点的颜色。默认:[UIColor redColor] +@property (nonatomic, strong) UIColor *dotColor; +/** + 红点 x,y方向的偏移 (+值:水平方向向右,竖直方向向下) + */ +@property (nonatomic, assign) CGPoint dotOffset; + +@end diff --git a/Pods/JXCategoryView/Sources/Dot/JXCategoryDotView.m b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotView.m new file mode 100644 index 0000000..847aadb --- /dev/null +++ b/Pods/JXCategoryView/Sources/Dot/JXCategoryDotView.m @@ -0,0 +1,52 @@ +// +// JXCategoryDotView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryDotView.h" + +@implementation JXCategoryDotView + +- (void)initializeData { + [super initializeData]; + + _relativePosition = JXCategoryDotRelativePosition_TopRight; + _dotSize = CGSizeMake(10, 10); + _dotCornerRadius = JXCategoryViewAutomaticDimension; + _dotColor = [UIColor redColor]; + _dotOffset = CGPointZero; +} + +- (Class)preferredCellClass { + return [JXCategoryDotCell class]; +} + +- (void)refreshDataSource { + NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:self.titles.count]; + for (int i = 0; i < self.titles.count; i++) { + JXCategoryDotCellModel *cellModel = [[JXCategoryDotCellModel alloc] init]; + [tempArray addObject:cellModel]; + } + self.dataSource = [NSArray arrayWithArray:tempArray]; +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + [super refreshCellModel:cellModel index:index]; + + JXCategoryDotCellModel *myCellModel = (JXCategoryDotCellModel *)cellModel; + myCellModel.dotHidden = [self.dotStates[index] boolValue]; + myCellModel.relativePosition = self.relativePosition; + myCellModel.dotSize = self.dotSize; + myCellModel.dotColor = self.dotColor; + myCellModel.dotOffset = self.dotOffset; + if (self.dotCornerRadius == JXCategoryViewAutomaticDimension) { + myCellModel.dotCornerRadius = self.dotSize.height/2; + }else { + myCellModel.dotCornerRadius = self.dotCornerRadius; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Image/JXCategoryImageCell.h b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCell.h new file mode 100644 index 0000000..f0dc162 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCell.h @@ -0,0 +1,15 @@ +// +// JXCategoryImageCell.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorCell.h" + +@interface JXCategoryImageCell : JXCategoryIndicatorCell + +@property (nonatomic, strong) UIImageView *imageView; + +@end diff --git a/Pods/JXCategoryView/Sources/Image/JXCategoryImageCell.m b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCell.m new file mode 100644 index 0000000..7384759 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCell.m @@ -0,0 +1,97 @@ +// +// JXCategoryImageCell.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryImageCell.h" +#import "JXCategoryImageCellModel.h" + +@interface JXCategoryImageCell() +@property (nonatomic, strong) id currentImageInfo; +@property (nonatomic, strong) NSString *currentImageName; +@property (nonatomic, strong) NSURL *currentImageURL; +@end + +@implementation JXCategoryImageCell + +- (void)prepareForReuse { + [super prepareForReuse]; + + self.currentImageInfo = nil; + self.currentImageName = nil; + self.currentImageURL = nil; +} + +- (void)initializeViews { + [super initializeViews]; + + _imageView = [[UIImageView alloc] init]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + [self.contentView addSubview:_imageView]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + JXCategoryImageCellModel *myCellModel = (JXCategoryImageCellModel *)self.cellModel; + self.imageView.bounds = CGRectMake(0, 0, myCellModel.imageSize.width, myCellModel.imageSize.height); + self.imageView.center = self.contentView.center; + if (myCellModel.imageCornerRadius && (myCellModel.imageCornerRadius != 0)) { + self.imageView.layer.cornerRadius = myCellModel.imageCornerRadius; + self.imageView.layer.masksToBounds = YES; + } +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryImageCellModel *myCellModel = (JXCategoryImageCellModel *)cellModel; + //因为`- (void)reloadData:(JXCategoryBaseCellModel *)cellModel`方法会回调多次,尤其是左右滚动的时候会调用无数次,如果每次都触发图片加载,会非常消耗性能。所以只会在图片发生了变化的时候,才进行图片加载。 + if (myCellModel.loadImageBlock != nil) { + id currentImageInfo = myCellModel.imageInfo; + if (myCellModel.isSelected) { + currentImageInfo = myCellModel.selectedImageInfo; + } + if (currentImageInfo && ![currentImageInfo isEqual:self.currentImageInfo]) { + self.currentImageInfo = currentImageInfo; + if (myCellModel.loadImageBlock) { + myCellModel.loadImageBlock(self.imageView, currentImageInfo); + } + } + } else { + NSString *currentImageName; + NSURL *currentImageURL; + if (myCellModel.imageName) { + currentImageName = myCellModel.imageName; + } else if (myCellModel.imageURL) { + currentImageURL = myCellModel.imageURL; + } + if (myCellModel.isSelected) { + if (myCellModel.selectedImageName) { + currentImageName = myCellModel.selectedImageName; + } else if (myCellModel.selectedImageURL) { + currentImageURL = myCellModel.selectedImageURL; + } + } + if (currentImageName && ![currentImageName isEqualToString:self.currentImageName]) { + self.currentImageName = currentImageName; + self.imageView.image = [UIImage imageNamed:currentImageName]; + } else if (currentImageURL && ![currentImageURL.absoluteString isEqualToString:self.currentImageURL.absoluteString]) { + self.currentImageURL = currentImageURL; + if (myCellModel.loadImageCallback) { + myCellModel.loadImageCallback(self.imageView, currentImageURL); + } + } + } + + if (myCellModel.isImageZoomEnabled) { + self.imageView.transform = CGAffineTransformMakeScale(myCellModel.imageZoomScale, myCellModel.imageZoomScale); + }else { + self.imageView.transform = CGAffineTransformIdentity; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Image/JXCategoryImageCellModel.h b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCellModel.h new file mode 100644 index 0000000..0d79fdf --- /dev/null +++ b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCellModel.h @@ -0,0 +1,32 @@ +// +// JXCategoryImageCellModel.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorCellModel.h" + +@interface JXCategoryImageCellModel : JXCategoryIndicatorCellModel + +@property (nonatomic, strong) id imageInfo; +@property (nonatomic, strong) id selectedImageInfo; +@property (nonatomic, copy) void(^loadImageBlock)(UIImageView *imageView, id info); + +@property (nonatomic, assign) CGSize imageSize; + +@property (nonatomic, assign) CGFloat imageCornerRadius; + +@property (nonatomic, assign, getter=isImageZoomEnabled) BOOL imageZoomEnabled; + +@property (nonatomic, assign) CGFloat imageZoomScale; + +/// 以下属性将会被弃用 +@property (nonatomic, copy) NSString *imageName; //加载bundle内的图片 +@property (nonatomic, strong) NSURL *imageURL; //图片URL +@property (nonatomic, copy) NSString *selectedImageName; +@property (nonatomic, strong) NSURL *selectedImageURL; +@property (nonatomic, copy) void(^loadImageCallback)(UIImageView *imageView, NSURL *imageURL); + +@end diff --git a/Pods/JXCategoryView/Sources/Image/JXCategoryImageCellModel.m b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCellModel.m new file mode 100644 index 0000000..a7dbec7 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Image/JXCategoryImageCellModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryImageCellModel.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryImageCellModel.h" + +@implementation JXCategoryImageCellModel + +@end diff --git a/Pods/JXCategoryView/Sources/Image/JXCategoryImageView.h b/Pods/JXCategoryView/Sources/Image/JXCategoryImageView.h new file mode 100644 index 0000000..a4324d6 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Image/JXCategoryImageView.h @@ -0,0 +1,32 @@ +// +// JXCategoryImageView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorView.h" +#import "JXCategoryImageCell.h" +#import "JXCategoryImageCellModel.h" + +@interface JXCategoryImageView : JXCategoryIndicatorView + +//imageInfo数组可以传入imageName字符串或者image的URL地址等,然后会通过loadImageBlock透传回来,把imageView对于图片的加载过程完全交给使用者决定。 +@property (nonatomic, strong) NSArray *imageInfoArray; +@property (nonatomic, strong) NSArray *selectedImageInfoArray; +@property (nonatomic, copy) void(^loadImageBlock)(UIImageView *imageView, id info); + +@property (nonatomic, assign) CGSize imageSize; //默认值为 CGSizeMake(20, 20) +@property (nonatomic, assign) CGFloat imageCornerRadius; //图片圆角 +@property (nonatomic, assign, getter=isImageZoomEnabled) BOOL imageZoomEnabled; //默认值为 NO +@property (nonatomic, assign) CGFloat imageZoomScale; //默认值为 1.2,imageZoomEnabled 为 YES 时才生效 + +//下面的属性将会被弃用,请使用`imageInfoArray`、`selectedImageInfoArray`、`loadImageBlock`属性完成需求。 +@property (nonatomic, strong) NSArray *imageNames; +@property (nonatomic, strong) NSArray *imageURLs; +@property (nonatomic, strong) NSArray *selectedImageNames; +@property (nonatomic, strong) NSArray *selectedImageURLs; +@property (nonatomic, copy) void(^loadImageCallback)(UIImageView *imageView, NSURL *imageURL); //使用imageURL从远端下载图片进行加载,建议使用SDWebImage等第三方库进行下载。 + +@end diff --git a/Pods/JXCategoryView/Sources/Image/JXCategoryImageView.m b/Pods/JXCategoryView/Sources/Image/JXCategoryImageView.m new file mode 100644 index 0000000..9c39b02 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Image/JXCategoryImageView.m @@ -0,0 +1,104 @@ +// +// JXCategoryImageView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/20. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryImageView.h" +#import "JXCategoryFactory.h" + +@implementation JXCategoryImageView + +- (void)dealloc { + self.loadImageBlock = nil; + self.loadImageCallback = nil; +} + +- (void)initializeData { + [super initializeData]; + + _imageSize = CGSizeMake(20, 20); + _imageZoomEnabled = NO; + _imageZoomScale = 1.2; + _imageCornerRadius = 0; +} + +- (Class)preferredCellClass { + return [JXCategoryImageCell class]; +} + +- (void)refreshDataSource { + NSUInteger count = 0; + if (self.imageInfoArray.count > 0) { + count = self.imageInfoArray.count; + }else if (self.imageNames.count > 0) { + count = self.imageNames.count; + }else { + count = self.imageURLs.count; + } + NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:count]; + for (int i = 0; i < count; i++) { + JXCategoryImageCellModel *cellModel = [[JXCategoryImageCellModel alloc] init]; + [tempArray addObject:cellModel]; + } + self.dataSource = [NSArray arrayWithArray:tempArray]; +} + +- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel { + [super refreshSelectedCellModel:selectedCellModel unselectedCellModel:unselectedCellModel]; + + JXCategoryImageCellModel *myUnselectedCellModel = (JXCategoryImageCellModel *)unselectedCellModel; + myUnselectedCellModel.imageZoomScale = 1.0; + + JXCategoryImageCellModel *myselectedCellModel = (JXCategoryImageCellModel *)selectedCellModel; + myselectedCellModel.imageZoomScale = self.imageZoomScale; +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + [super refreshCellModel:cellModel index:index]; + + JXCategoryImageCellModel *myCellModel = (JXCategoryImageCellModel *)cellModel; + myCellModel.loadImageBlock = self.loadImageBlock; + myCellModel.loadImageCallback = self.loadImageCallback; + myCellModel.imageSize = self.imageSize; + myCellModel.imageCornerRadius = self.imageCornerRadius; + if (self.imageInfoArray && self.imageInfoArray.count != 0) { + myCellModel.imageInfo = self.imageInfoArray[index]; + }else if (self.imageNames && self.imageNames.count != 0) { + myCellModel.imageName = self.imageNames[index]; + }else if (self.imageURLs && self.imageURLs.count != 0) { + myCellModel.imageURL = self.imageURLs[index]; + } + if (self.selectedImageInfoArray && self.selectedImageInfoArray.count != 0) { + myCellModel.selectedImageInfo = self.selectedImageInfoArray[index]; + }else if (self.selectedImageNames && self.selectedImageNames.count != 0) { + myCellModel.selectedImageName = self.selectedImageNames[index]; + }else if (self.selectedImageURLs && self.selectedImageURLs.count != 0) { + myCellModel.selectedImageURL = self.selectedImageURLs[index]; + } + myCellModel.imageZoomEnabled = self.imageZoomEnabled; + myCellModel.imageZoomScale = ((index == self.selectedIndex) ? self.imageZoomScale : 1.0); +} + +- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratio { + [super refreshLeftCellModel:leftCellModel rightCellModel:rightCellModel ratio:ratio]; + + JXCategoryImageCellModel *leftModel = (JXCategoryImageCellModel *)leftCellModel; + JXCategoryImageCellModel *rightModel = (JXCategoryImageCellModel *)rightCellModel; + + if (self.isImageZoomEnabled) { + leftModel.imageZoomScale = [JXCategoryFactory interpolationFrom:self.imageZoomScale to:1.0 percent:ratio]; + rightModel.imageZoomScale = [JXCategoryFactory interpolationFrom:1.0 to:self.imageZoomScale percent:ratio]; + } +} + +- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index { + if (self.cellWidth == JXCategoryViewAutomaticDimension) { + return self.imageSize.width; + } + return self.cellWidth; +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.h new file mode 100644 index 0000000..e423efb --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.h @@ -0,0 +1,14 @@ +// +// JXCategoryIndicatorBackgroundView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +/// BackgroundView 样式的指示器 +@interface JXCategoryIndicatorBackgroundView : JXCategoryIndicatorComponentView + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.m new file mode 100644 index 0000000..4f4942f --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.m @@ -0,0 +1,101 @@ +// +// JXCategoryIndicatorBackgroundView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorBackgroundView.h" +#import "JXCategoryFactory.h" + +@implementation JXCategoryIndicatorBackgroundView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (void)configureDefaulteValue { + self.indicatorWidth = JXCategoryViewAutomaticDimension; + self.indicatorHeight = JXCategoryViewAutomaticDimension; + self.indicatorCornerRadius = JXCategoryViewAutomaticDimension; + self.indicatorColor = [UIColor lightGrayColor]; + self.indicatorWidthIncrement = 10; +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + self.layer.cornerRadius = [self indicatorCornerRadiusValue:model.selectedCellFrame]; + self.backgroundColor = self.indicatorColor; + + CGFloat width = [self indicatorWidthValue:model.selectedCellFrame]; + CGFloat height = [self indicatorHeightValue:model.selectedCellFrame]; + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - width)/2; + CGFloat y = (model.selectedCellFrame.size.height - height)/2 - self.verticalMargin; + self.frame = CGRectMake(x, y, width, height); +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + CGRect rightCellFrame = model.rightCellFrame; + CGRect leftCellFrame = model.leftCellFrame; + CGFloat percent = model.percent; + CGFloat targetX = 0; + CGFloat targetWidth = [self indicatorWidthValue:leftCellFrame]; + + if (percent == 0) { + targetX = leftCellFrame.origin.x + (leftCellFrame.size.width - targetWidth)/2.0; + }else { + CGFloat leftWidth = targetWidth; + CGFloat rightWidth = [self indicatorWidthValue:rightCellFrame]; + + CGFloat leftX = leftCellFrame.origin.x + (leftCellFrame.size.width - leftWidth)/2; + CGFloat rightX = rightCellFrame.origin.x + (rightCellFrame.size.width - rightWidth)/2; + + targetX = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:percent]; + + if (self.indicatorWidth == JXCategoryViewAutomaticDimension) { + targetWidth = [JXCategoryFactory interpolationFrom:leftWidth to:rightWidth percent:percent]; + } + } + + //允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了; + if (self.isScrollEnabled == YES || (self.isScrollEnabled == NO && percent == 0)) { + CGRect toFrame = self.frame; + toFrame.origin.x = targetX; + toFrame.size.width = targetWidth; + self.frame = toFrame; + } +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + CGFloat width = [self indicatorWidthValue:model.selectedCellFrame]; + CGRect toFrame = self.frame; + toFrame.origin.x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - width)/2; + toFrame.size.width = width; + + if (self.isScrollEnabled) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ + self.frame = toFrame; + } completion:^(BOOL finished) { + }]; + }else { + self.frame = toFrame; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.h new file mode 100644 index 0000000..777d8a3 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.h @@ -0,0 +1,17 @@ +// +// JXCategoryIndicatorBallView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/21. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +/// QQ 小红点样式的指示器 +@interface JXCategoryIndicatorBallView : JXCategoryIndicatorComponentView + +// 球沿的 X 轴方向上的偏移量。默认值为 20 +@property (nonatomic, assign) CGFloat ballScrollOffsetX; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.m new file mode 100644 index 0000000..afaeff0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.m @@ -0,0 +1,199 @@ +// +// JXCategoryIndicatorBallView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/21. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorBallView.h" +#import "JXCategoryFactory.h" + +@interface JXCategoryIndicatorBallView () +@property (nonatomic, strong) UIView *smallBall; +@property (nonatomic, strong) UIView *bigBall; +@property (nonatomic, strong) CAShapeLayer *shapeLayer; +@end + +@implementation JXCategoryIndicatorBallView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self configureIndicatorBall]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self configureIndicatorBall]; + } + return self; +} + +- (void)configureIndicatorBall { + self.indicatorWidth = 15; + self.indicatorHeight = 15; + _ballScrollOffsetX = 20; + + _smallBall = [[UIView alloc] init]; + [self addSubview:self.smallBall]; + + _bigBall = [[UIView alloc] init]; + [self addSubview:self.bigBall]; + + _shapeLayer = [CAShapeLayer layer]; + [self.layer addSublayer:self.shapeLayer]; +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + CGFloat ballWidth = [self indicatorWidthValue:model.selectedCellFrame]; + CGFloat ballHeight = [self indicatorHeightValue:model.selectedCellFrame]; + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + self.shapeLayer.fillColor = self.indicatorColor.CGColor; + [CATransaction commit]; + + self.smallBall.backgroundColor = self.indicatorColor; + self.smallBall.layer.cornerRadius = ballHeight/2; + self.bigBall.backgroundColor = self.indicatorColor; + self.bigBall.layer.cornerRadius = ballHeight/2; + + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - ballWidth)/2; + CGFloat y = self.superview.bounds.size.height - ballHeight - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + y = self.verticalMargin; + } + self.smallBall.frame = CGRectMake(x, y, ballWidth, ballHeight); + self.bigBall.frame = CGRectMake(x, y, ballWidth, ballHeight); +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + CGFloat ballWidth = [self indicatorWidthValue:model.leftCellFrame]; + CGFloat ballHeight = [self indicatorHeightValue:model.leftCellFrame]; + CGRect rightCellFrame = model.rightCellFrame; + CGRect leftCellFrame = model.leftCellFrame; + CGFloat percent = model.percent; + CGFloat targetXOfBigBall = 0; + CGFloat targetXOfSmallBall = leftCellFrame.origin.x + (leftCellFrame.size.width - ballWidth)/2; + CGFloat targetWidthOfSmallBall = ballWidth; + + if (percent == 0) { + targetXOfBigBall = leftCellFrame.origin.x + (leftCellFrame.size.width - ballWidth)/2.0; + targetXOfSmallBall = leftCellFrame.origin.x + (leftCellFrame.size.width - targetWidthOfSmallBall)/2.0; + }else { + CGFloat leftX = leftCellFrame.origin.x + (leftCellFrame.size.width - ballWidth)/2; + CGFloat rightX = rightCellFrame.origin.x + (rightCellFrame.size.width - ballWidth)/2; + + //前50%,移动bigBall的x,缩小smallBall;后50%,移动bigBall的x,缩小smallBall,移动smallBall的x + if (percent <= 0.5) { + targetXOfBigBall = [JXCategoryFactory interpolationFrom:leftX to:(rightX - self.ballScrollOffsetX) percent:percent*2]; + targetWidthOfSmallBall = [JXCategoryFactory interpolationFrom:ballWidth to:ballWidth/2 percent:percent*2]; + }else { + targetXOfBigBall = [JXCategoryFactory interpolationFrom:(rightX - self.ballScrollOffsetX) to:rightX percent:(percent - 0.5)*2]; + targetWidthOfSmallBall = [JXCategoryFactory interpolationFrom:ballWidth/2 to:0 percent:(percent - 0.5)*2]; + targetXOfSmallBall = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:(percent - 0.5)*2]; + } + } + + //允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了; + if (self.isScrollEnabled == YES || (self.isScrollEnabled == NO && percent == 0)) { + CGRect bigBallFrame = self.bigBall.frame; + bigBallFrame.origin.x = targetXOfBigBall; + self.bigBall.frame = bigBallFrame; + self.bigBall.layer.cornerRadius = bigBallFrame.size.height/2; + + CGFloat targetYOfSmallBall = self.superview.bounds.size.height - ballHeight/2 - targetWidthOfSmallBall/2 - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + targetYOfSmallBall = ballHeight/2 - targetWidthOfSmallBall/2 + self.verticalMargin; + } + self.smallBall.frame = CGRectMake(targetXOfSmallBall, targetYOfSmallBall, targetWidthOfSmallBall, targetWidthOfSmallBall); + self.smallBall.layer.cornerRadius = targetWidthOfSmallBall/2; + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + self.shapeLayer.path = [self getBezierPathWithSmallCir:self.smallBall andBigCir:self.bigBall].CGPath; + [CATransaction commit]; + } +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + CGFloat ballWidth = [self indicatorWidthValue:model.selectedCellFrame]; + CGFloat ballHeight = [self indicatorHeightValue:model.selectedCellFrame]; + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - ballWidth)/2; + CGFloat y = self.superview.bounds.size.height - ballHeight - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + y = self.verticalMargin; + } + CGRect toFrame = CGRectMake(x, y, ballWidth, ballHeight); + + if (self.isScrollEnabled) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.smallBall.frame = toFrame; + self.bigBall.frame = toFrame; + self.smallBall.layer.cornerRadius = ballHeight/2; + self.bigBall.layer.cornerRadius = ballHeight/2; + } completion:^(BOOL finished) { + + }]; + }else { + self.smallBall.frame = toFrame; + self.bigBall.frame = toFrame; + self.smallBall.layer.cornerRadius = ballHeight/2; + self.bigBall.layer.cornerRadius = ballHeight/2; + } +} + +- (UIBezierPath *)getBezierPathWithSmallCir:(UIView *)smallCir andBigCir:(UIView *)bigCir{ + // 获取最小的圆 + if (bigCir.frame.size.width < smallCir.frame.size.width) { + UIView *view = bigCir; + bigCir = smallCir; + smallCir = view; + } + // 获取小圆的信息 + CGFloat d = self.bigBall.center.x - self.smallBall.center.x; + if (d == 0) { + return nil; + } + CGFloat x1 = smallCir.center.x; + CGFloat y1 = smallCir.center.y; + CGFloat r1 = smallCir.bounds.size.width/2; + + // 获取大圆的信息 + CGFloat x2 = bigCir.center.x; + CGFloat y2 = bigCir.center.y; + CGFloat r2 = bigCir.bounds.size.width/2; + + // 获取三角函数 + CGFloat sinA = (y2 - y1)/d; + CGFloat cosA = (x2 - x1)/d; + + // 获取矩形四个点 + CGPoint pointA = CGPointMake(x1 - sinA*r1, y1 + cosA * r1); + CGPoint pointB = CGPointMake(x1 + sinA*r1, y1 - cosA * r1); + CGPoint pointC = CGPointMake(x2 + sinA*r2, y2 - cosA * r2); + CGPoint pointD = CGPointMake(x2 - sinA*r2, y2 + cosA * r2); + + // 获取控制点,以便画出曲线 + CGPoint pointO = CGPointMake(pointA.x + d / 2 * cosA , pointA.y + d / 2 * sinA); + CGPoint pointP = CGPointMake(pointB.x + d / 2 * cosA , pointB.y + d / 2 * sinA); + + // 创建路径 + UIBezierPath *path =[UIBezierPath bezierPath]; + [path moveToPoint:pointA]; + [path addLineToPoint:pointB]; + [path addQuadCurveToPoint:pointC controlPoint:pointP]; + [path addLineToPoint:pointD]; + [path addQuadCurveToPoint:pointA controlPoint:pointO]; + return path; +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.h new file mode 100644 index 0000000..6b2906e --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.h @@ -0,0 +1,113 @@ +// +// JXCategoryComponentBaseView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXCategoryIndicatorProtocol.h" +#import "JXCategoryViewDefines.h" + +@interface JXCategoryIndicatorComponentView : UIView + +/** + 指示器的位置 + + 可设置的枚举类型: + - 底部:JXCategoryComponentPosition_Bottom + - 顶部:JXCategoryComponentPosition_Top + */ +@property (nonatomic, assign) JXCategoryComponentPosition componentPosition; + +/** + 指示器的宽度 + + 默认值为 JXCategoryViewAutomaticDimension(表示与 cell 的宽度相等)。 + 内部通过 `- (CGFloat)indicatorWidthValue:(CGRect)cellFrame` 方法获取实际的值。 + */ +@property (nonatomic, assign) CGFloat indicatorWidth; + +/** + 指示器的宽度增量 + + 例如:需求是指示器宽度比 cell 宽度多 10pt。就可以将该属性赋值为 10。 + 最终指示器的宽度 = indicatorWidth + indicatorWidthIncrement。 + */ +@property (nonatomic, assign) CGFloat indicatorWidthIncrement; + +/** + 指示器的高度 + + 默认值为 3。 + 内部通过 `- (CGFloat)indicatorHeightValue:(CGRect)cellFrame` 方法获取实际的值。 + */ +@property (nonatomic, assign) CGFloat indicatorHeight; + +/** + 指示器的 CornerRadius 圆角半径 + + 默认值为 JXCategoryViewAutomaticDimension (等于 indicatorHeight/2)。 + 内部通过 `- (CGFloat)indicatorCornerRadiusValue:(CGRect)cellFrame` 方法获取实际的值。 + */ +@property (nonatomic, assign) CGFloat indicatorCornerRadius; + +/** + 指示器的颜色 + */ +@property (nonatomic, strong) UIColor *indicatorColor; + +/** + 指示器在垂直方向上的偏移量 + + 数值越大越靠近中心。默认值为 0。 + */ +@property (nonatomic, assign) CGFloat verticalMargin; + +/** + 是否允许手势滚动 + + 点击切换的时候,是否允许滚动,默认值为 YES。 + */ +@property (nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled; + +/** + 指示器滚动样式 + + 点击切换的时候,如果允许滚动,分为简单滚动和复杂滚动。 + 默认值为 JXCategoryIndicatorScrollStyleSimple + 目前仅JXCategoryIndicatorLineView、JXCategoryIndicatorDotLineView支持,其他子类暂不支持。 + */ +@property (nonatomic, assign) JXCategoryIndicatorScrollStyle scrollStyle; + +/** + 滚动动画的时间,默认值为 0.25s + */ +@property (nonatomic, assign) NSTimeInterval scrollAnimationDuration; + +/** + 传入 cellFrame 获取指示器的最终宽度 + + @param cellFrame cellFrame + @return 指示器的最终宽度 + */ +- (CGFloat)indicatorWidthValue:(CGRect)cellFrame; + +/** + 传入 cellFrame 获取指示器的最终高度 + + @param cellFrame cellFrame + @return 指示器的最终高度 + */ +- (CGFloat)indicatorHeightValue:(CGRect)cellFrame; + +/** + 传入 cellFrame 获取指示器的最终圆角 + + @param cellFrame cellFrame + @return 指示器的最终圆角 + */ +- (CGFloat)indicatorCornerRadiusValue:(CGRect)cellFrame; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.m new file mode 100644 index 0000000..f9111d3 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.m @@ -0,0 +1,81 @@ +// +// JXCategoryComponentBaseView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +@implementation JXCategoryIndicatorComponentView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self configureDefaultValue]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self configureDefaultValue]; + } + return self; +} + +- (void)configureDefaultValue { + _componentPosition = JXCategoryComponentPosition_Bottom; + _scrollEnabled = YES; + _verticalMargin = 0; + _scrollAnimationDuration = 0.25; + _indicatorWidth = JXCategoryViewAutomaticDimension; + _indicatorWidthIncrement = 0; + _indicatorHeight = 3; + _indicatorCornerRadius = JXCategoryViewAutomaticDimension; + _indicatorColor = [UIColor redColor]; + _scrollStyle = JXCategoryIndicatorScrollStyleSimple; +} + +#pragma mark - Public + +- (CGFloat)indicatorWidthValue:(CGRect)cellFrame { + if (self.indicatorWidth == JXCategoryViewAutomaticDimension) { + return cellFrame.size.width + self.indicatorWidthIncrement; + } + return self.indicatorWidth + self.indicatorWidthIncrement; +} + +- (CGFloat)indicatorHeightValue:(CGRect)cellFrame { + if (self.indicatorHeight == JXCategoryViewAutomaticDimension) { + return cellFrame.size.height; + } + return self.indicatorHeight; +} + +- (CGFloat)indicatorCornerRadiusValue:(CGRect)cellFrame { + if (self.indicatorCornerRadius == JXCategoryViewAutomaticDimension) { + return [self indicatorHeightValue:cellFrame]/2; + } + return self.indicatorCornerRadius; +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.h new file mode 100644 index 0000000..e58bbdb --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.h @@ -0,0 +1,17 @@ +// +// JXCategoryIndicatorDotLineView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/22. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +/// 点线效果的指示器 +@interface JXCategoryIndicatorDotLineView : JXCategoryIndicatorComponentView + +// 线状态的最大宽度,默认值为 50 +@property (nonatomic, assign) CGFloat lineWidth; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.m new file mode 100644 index 0000000..3a680e4 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.m @@ -0,0 +1,148 @@ +// +// JXCategoryIndicatorDotLineView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/22. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorDotLineView.h" +#import "JXCategoryFactory.h" +#import "JXCategoryViewAnimator.h" + +@interface JXCategoryIndicatorDotLineView () +@property (nonatomic, strong) JXCategoryViewAnimator *animator; +@end + +@implementation JXCategoryIndicatorDotLineView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (void)configureDefaulteValue { + self.indicatorWidth = 10; + self.indicatorHeight = 10; + _lineWidth = 50; +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + CGFloat dotWidth = [self indicatorWidthValue:model.selectedCellFrame]; + CGFloat dotHeight = [self indicatorHeightValue:model.selectedCellFrame]; + self.backgroundColor = self.indicatorColor; + self.layer.cornerRadius = [self indicatorHeightValue:model.selectedCellFrame]/2; + + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - dotWidth)/2; + CGFloat y = self.superview.bounds.size.height - dotHeight - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + y = self.verticalMargin; + } + self.frame = CGRectMake(x, y, dotWidth, dotHeight); +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + if (self.animator.isExecuting) { + [self.animator invalid]; + self.animator = nil; + } + CGFloat dotWidth = [self indicatorWidthValue:model.selectedCellFrame]; + CGRect rightCellFrame = model.rightCellFrame; + CGRect leftCellFrame = model.leftCellFrame; + CGFloat percent = model.percent; + CGFloat targetX = 0; + CGFloat targetWidth = dotWidth; + CGFloat leftWidth = dotWidth; + CGFloat rightWidth = dotWidth; + CGFloat leftX = leftCellFrame.origin.x + (leftCellFrame.size.width - leftWidth)/2; + CGFloat rightX = rightCellFrame.origin.x + (rightCellFrame.size.width - rightWidth)/2; + CGFloat centerX = leftX + (rightX - leftX - self.lineWidth)/2; + + //前50%,移动x,增加宽度;后50%,移动x并减小width + if (percent <= 0.5) { + targetX = [JXCategoryFactory interpolationFrom:leftX to:centerX percent:percent*2]; + targetWidth = [JXCategoryFactory interpolationFrom:dotWidth to:self.lineWidth percent:percent*2]; + }else { + targetX = [JXCategoryFactory interpolationFrom:centerX to:rightX percent:(percent - 0.5)*2]; + targetWidth = [JXCategoryFactory interpolationFrom:self.lineWidth to:dotWidth percent:(percent - 0.5)*2]; + } + + //允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了; + if (self.isScrollEnabled == YES || (self.isScrollEnabled == NO && percent == 0)) { + CGRect frame = self.frame; + frame.origin.x = targetX; + frame.size.width = targetWidth; + self.frame = frame; + } +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + CGFloat dotWidth = [self indicatorWidthValue:model.selectedCellFrame]; + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - dotWidth)/2; + CGRect targetIndicatorFrame = self.frame; + targetIndicatorFrame.origin.x = x; + if (self.isScrollEnabled) { + if (self.scrollStyle == JXCategoryIndicatorScrollStyleSameAsUserScroll && (model.selectedType == JXCategoryCellSelectedTypeClick | model.selectedType == JXCategoryCellSelectedTypeCode)) { + if (self.animator.isExecuting) { + [self.animator invalid]; + self.animator = nil; + } + CGFloat leftX = 0; + CGFloat rightX = 0; + BOOL isNeedReversePercent = NO; + if (self.frame.origin.x > model.selectedCellFrame.origin.x) { + leftX = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - dotWidth)/2;; + rightX = self.frame.origin.x; + isNeedReversePercent = YES; + }else { + leftX = self.frame.origin.x; + rightX = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - dotWidth)/2; + } + CGFloat centerX = leftX + (rightX - leftX - self.lineWidth)/2; + __weak typeof(self) weakSelf = self; + self.animator = [[JXCategoryViewAnimator alloc] init]; + self.animator.progressCallback = ^(CGFloat percent) { + if (isNeedReversePercent) { + percent = 1 - percent; + } + CGFloat targetX = 0; + CGFloat targetWidth = 0; + if (percent <= 0.5) { + targetX = [JXCategoryFactory interpolationFrom:leftX to:centerX percent:percent*2]; + targetWidth = [JXCategoryFactory interpolationFrom:dotWidth to:self.lineWidth percent:percent*2]; + }else { + targetX = [JXCategoryFactory interpolationFrom:centerX to:rightX percent:(percent - 0.5)*2]; + targetWidth = [JXCategoryFactory interpolationFrom:self.lineWidth to:dotWidth percent:(percent - 0.5)*2]; + } + CGRect toFrame = weakSelf.frame; + toFrame.origin.x = targetX; + toFrame.size.width = targetWidth; + weakSelf.frame = toFrame; + }; + [self.animator start]; + }else if (self.scrollStyle == JXCategoryIndicatorScrollStyleSimple) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.frame = targetIndicatorFrame; + } completion: nil]; + } + }else { + self.frame = targetIndicatorFrame; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.h new file mode 100644 index 0000000..04a1738 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.h @@ -0,0 +1,20 @@ +// +// JXCategoryIndicatorImageView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +@interface JXCategoryIndicatorImageView : JXCategoryIndicatorComponentView + +// 指示器图片 +@property (nonatomic, strong, readonly) UIImageView *indicatorImageView; +// 图片是否开启滚动,默认值为 NO +@property (nonatomic, assign) BOOL indicatorImageViewRollEnabled; +// 图片的尺寸,默认值为 CGSizeMake(30, 20) +@property (nonatomic, assign) CGSize indicatorImageViewSize; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.m new file mode 100644 index 0000000..02dc891 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.m @@ -0,0 +1,117 @@ +// +// JXCategoryIndicatorImageView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorImageView.h" +#import "JXCategoryFactory.h" + +@implementation JXCategoryIndicatorImageView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupIndicatorImageView]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self setupIndicatorImageView]; + } + return self; +} + +- (void)setupIndicatorImageView { + _indicatorImageViewSize = CGSizeMake(30, 20); + _indicatorImageViewRollEnabled = NO; + + _indicatorImageView = [[UIImageView alloc] init]; + self.indicatorImageView.frame = CGRectMake(0, 0, self.indicatorImageViewSize.width, self.indicatorImageViewSize.height); + self.indicatorImageView.contentMode = UIViewContentModeScaleAspectFit; + [self addSubview:self.indicatorImageView]; +} + +#pragma mark - Custom Accessors + +- (void)setIndicatorImageViewSize:(CGSize)indicatorImageViewSize { + _indicatorImageViewSize = indicatorImageViewSize; + + self.indicatorImageView.frame = CGRectMake(0, 0, self.indicatorImageViewSize.width, self.indicatorImageViewSize.height); +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - self.indicatorImageViewSize.width)/2; + CGFloat y = self.superview.bounds.size.height - self.indicatorImageViewSize.height - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + y = self.verticalMargin; + } + self.frame = CGRectMake(x, y, self.indicatorImageViewSize.width, self.indicatorImageViewSize.height); +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + CGRect rightCellFrame = model.rightCellFrame; + CGRect leftCellFrame = model.leftCellFrame; + CGFloat percent = model.percent; + CGFloat targetWidth = self.indicatorImageViewSize.width; + CGFloat targetX = 0; + + if (percent == 0) { + targetX = leftCellFrame.origin.x + (leftCellFrame.size.width - targetWidth)/2.0; + }else { + CGFloat leftX = leftCellFrame.origin.x + (leftCellFrame.size.width - targetWidth)/2; + CGFloat rightX = rightCellFrame.origin.x + (rightCellFrame.size.width - targetWidth)/2; + targetX = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:percent]; + } + + //允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了; + if (self.isScrollEnabled == YES || (self.isScrollEnabled == NO && percent == 0)) { + CGRect frame = self.frame; + frame.origin.x = targetX; + self.frame = frame; + + if (self.indicatorImageViewRollEnabled) { + self.indicatorImageView.transform = CGAffineTransformMakeRotation(M_PI*2*percent); + } + } +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + CGRect toFrame = self.frame; + toFrame.origin.x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - self.indicatorImageViewSize.width)/2; + if (self.isScrollEnabled) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ + self.frame = toFrame; + } completion:^(BOOL finished) { + }]; + if (self.indicatorImageViewRollEnabled && (model.selectedType == JXCategoryCellSelectedTypeCode || model.selectedType == JXCategoryCellSelectedTypeClick)) { + [self.indicatorImageView.layer removeAnimationForKey:@"rotate"]; + CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; + if (model.selectedIndex > model.lastSelectedIndex) { + rotateAnimation.fromValue = @(0); + rotateAnimation.toValue = @(M_PI*2); + }else { + rotateAnimation.fromValue = @(M_PI*2); + rotateAnimation.toValue = @(0); + } + rotateAnimation.fillMode = kCAFillModeBackwards; + rotateAnimation.removedOnCompletion = YES; + rotateAnimation.duration = 0.25; + [self.indicatorImageView.layer addAnimation:rotateAnimation forKey:@"rotate"]; + } + }else { + self.frame = toFrame; + } +} + + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.h new file mode 100644 index 0000000..54c784a --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.h @@ -0,0 +1,28 @@ +// +// JXCategoryIndicatorLineView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +typedef NS_ENUM(NSUInteger, JXCategoryIndicatorLineStyle) { + JXCategoryIndicatorLineStyle_Normal = 0, + JXCategoryIndicatorLineStyle_Lengthen = 1, + JXCategoryIndicatorLineStyle_LengthenOffset = 2, +}; + +@interface JXCategoryIndicatorLineView : JXCategoryIndicatorComponentView + +@property (nonatomic, assign) JXCategoryIndicatorLineStyle lineStyle; + +/** + line 滚动时沿 x 轴方向上的偏移量,默认值为 10。 + + lineStyle 为 JXCategoryIndicatorLineStyle_LengthenOffset 有用。 + */ +@property (nonatomic, assign) CGFloat lineScrollOffsetX; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.m new file mode 100644 index 0000000..87ffbe6 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.m @@ -0,0 +1,202 @@ +// +// JXCategoryIndicatorLineView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorLineView.h" +#import "JXCategoryFactory.h" +#import "JXCategoryViewDefines.h" +#import "JXCategoryViewAnimator.h" + +@interface JXCategoryIndicatorLineView () +@property (nonatomic, strong) JXCategoryViewAnimator *animator; +@end + +@implementation JXCategoryIndicatorLineView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (void)configureDefaulteValue { + _lineStyle = JXCategoryIndicatorLineStyle_Normal; + _lineScrollOffsetX = 10; + self.indicatorHeight = 3; +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + self.backgroundColor = self.indicatorColor; + self.layer.cornerRadius = [self indicatorCornerRadiusValue:model.selectedCellFrame]; + + CGFloat selectedLineWidth = [self indicatorWidthValue:model.selectedCellFrame]; + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - selectedLineWidth)/2; + CGFloat y = self.superview.bounds.size.height - [self indicatorHeightValue:model.selectedCellFrame] - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + y = self.verticalMargin; + } + self.frame = CGRectMake(x, y, selectedLineWidth, [self indicatorHeightValue:model.selectedCellFrame]); +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + if (self.animator.isExecuting) { + [self.animator invalid]; + self.animator = nil; + } + CGRect rightCellFrame = model.rightCellFrame; + CGRect leftCellFrame = model.leftCellFrame; + CGFloat percent = model.percent; + CGFloat targetX = leftCellFrame.origin.x; + CGFloat targetWidth = [self indicatorWidthValue:leftCellFrame]; + + CGFloat leftWidth = targetWidth; + CGFloat rightWidth = [self indicatorWidthValue:rightCellFrame]; + CGFloat leftX = leftCellFrame.origin.x + (leftCellFrame.size.width - leftWidth)/2; + CGFloat rightX = rightCellFrame.origin.x + (rightCellFrame.size.width - rightWidth)/2; + + if (self.lineStyle == JXCategoryIndicatorLineStyle_Normal) { + targetX = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:percent]; + if (self.indicatorWidth == JXCategoryViewAutomaticDimension) { + targetWidth = [JXCategoryFactory interpolationFrom:leftWidth to:rightWidth percent:percent]; + } + }else if (self.lineStyle == JXCategoryIndicatorLineStyle_Lengthen) { + CGFloat maxWidth = rightX - leftX + rightWidth; + //前50%,只增加width;后50%,移动x并减小width + if (percent <= 0.5) { + targetX = leftX; + targetWidth = [JXCategoryFactory interpolationFrom:leftWidth to:maxWidth percent:percent*2]; + }else { + targetX = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:(percent - 0.5)*2]; + targetWidth = [JXCategoryFactory interpolationFrom:maxWidth to:rightWidth percent:(percent - 0.5)*2]; + } + }else if (self.lineStyle == JXCategoryIndicatorLineStyle_LengthenOffset) { + //前50%,增加width,并少量移动x;后50%,少量移动x并减小width + CGFloat offsetX = self.lineScrollOffsetX;//x的少量偏移量 + CGFloat maxWidth = rightX - leftX + rightWidth - offsetX*2; + if (percent <= 0.5) { + targetX = [JXCategoryFactory interpolationFrom:leftX to:leftX + offsetX percent:percent*2];; + targetWidth = [JXCategoryFactory interpolationFrom:leftWidth to:maxWidth percent:percent*2]; + }else { + targetX = [JXCategoryFactory interpolationFrom:(leftX + offsetX) to:rightX percent:(percent - 0.5)*2]; + targetWidth = [JXCategoryFactory interpolationFrom:maxWidth to:rightWidth percent:(percent - 0.5)*2]; + } + } + //允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了; + if (self.isScrollEnabled == YES || (self.isScrollEnabled == NO && percent == 0)) { + CGRect frame = self.frame; + frame.origin.x = targetX; + frame.size.width = targetWidth; + self.frame = frame; + } +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + CGRect targetIndicatorFrame = self.frame; + CGFloat targetIndicatorWidth = [self indicatorWidthValue:model.selectedCellFrame]; + targetIndicatorFrame.origin.x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - targetIndicatorWidth)/2.0; + targetIndicatorFrame.size.width = targetIndicatorWidth; + if (self.isScrollEnabled) { + if (self.scrollStyle == JXCategoryIndicatorScrollStyleSameAsUserScroll && (model.selectedType == JXCategoryCellSelectedTypeClick | model.selectedType == JXCategoryCellSelectedTypeCode)) { + if (self.animator.isExecuting) { + [self.animator invalid]; + self.animator = nil; + } + CGFloat leftX = 0; + CGFloat rightX = 0; + CGFloat leftWidth = 0; + CGFloat rightWidth = 0; + BOOL isNeedReversePercent = NO; + if (self.frame.origin.x > model.selectedCellFrame.origin.x) { + leftWidth = [self indicatorWidthValue:model.selectedCellFrame]; + rightWidth = self.frame.size.width; + leftX = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - leftWidth)/2;; + rightX = self.frame.origin.x; + isNeedReversePercent = YES; + }else { + leftWidth = self.frame.size.width; + rightWidth = [self indicatorWidthValue:model.selectedCellFrame]; + leftX = self.frame.origin.x; + rightX = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - rightWidth)/2; + } + __weak typeof(self) weakSelf = self; + if (self.lineStyle == JXCategoryIndicatorLineStyle_Normal) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.frame = targetIndicatorFrame; + } completion: nil]; + }else if (self.lineStyle == JXCategoryIndicatorLineStyle_Lengthen) { + CGFloat maxWidth = rightX - leftX + rightWidth; + //前50%,只增加width;后50%,移动x并减小width + self.animator = [[JXCategoryViewAnimator alloc] init]; + self.animator.progressCallback = ^(CGFloat percent) { + if (isNeedReversePercent) { + percent = 1 - percent; + } + CGFloat targetX = 0; + CGFloat targetWidth = 0; + if (percent <= 0.5) { + targetX = leftX; + targetWidth = [JXCategoryFactory interpolationFrom:leftWidth to:maxWidth percent:percent*2]; + }else { + targetX = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:(percent - 0.5)*2]; + targetWidth = [JXCategoryFactory interpolationFrom:maxWidth to:rightWidth percent:(percent - 0.5)*2]; + } + CGRect toFrame = weakSelf.frame; + toFrame.origin.x = targetX; + toFrame.size.width = targetWidth; + weakSelf.frame = toFrame; + }; + [self.animator start]; + }else if (self.lineStyle == JXCategoryIndicatorLineStyle_LengthenOffset) { + //前50%,增加width,并少量移动x;后50%,少量移动x并减小width + CGFloat offsetX = self.lineScrollOffsetX;//x的少量偏移量 + CGFloat maxWidth = rightX - leftX + rightWidth - offsetX*2; + self.animator = [[JXCategoryViewAnimator alloc] init]; + self.animator.progressCallback = ^(CGFloat percent) { + if (isNeedReversePercent) { + percent = 1 - percent; + } + CGFloat targetX = 0; + CGFloat targetWidth = 0; + if (percent <= 0.5) { + targetX = [JXCategoryFactory interpolationFrom:leftX to:leftX + offsetX percent:percent*2];; + targetWidth = [JXCategoryFactory interpolationFrom:leftWidth to:maxWidth percent:percent*2]; + }else { + targetX = [JXCategoryFactory interpolationFrom:(leftX + offsetX) to:rightX percent:(percent - 0.5)*2]; + targetWidth = [JXCategoryFactory interpolationFrom:maxWidth to:rightWidth percent:(percent - 0.5)*2]; + } + CGRect toFrame = weakSelf.frame; + toFrame.origin.x = targetX; + toFrame.size.width = targetWidth; + weakSelf.frame = toFrame; + }; + [self.animator start]; + } + }else if (self.scrollStyle == JXCategoryIndicatorScrollStyleSimple) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.frame = targetIndicatorFrame; + } completion: nil]; + } + }else { + self.frame = targetIndicatorFrame; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.h new file mode 100644 index 0000000..5fe134e --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.h @@ -0,0 +1,30 @@ +// +// JXCategoryIndicatorRainbowLineView.h +// JXCategoryView +// +// Created by jiaxin on 2018/12/13. +// Copyright © 2018 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorLineView.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + 彩虹效果的指示器 + + !!!: 会无视 JXCategoryIndicatorLineView 的 indicatorColor 属性,以 indicatorColors 为准。 + */ +@interface JXCategoryIndicatorRainbowLineView : JXCategoryIndicatorLineView + +/** + 指示器颜色数组 + + 数量需要与 cell 的数量相等。没有提供默认值,必须要赋值该属性。 + categoryView 在 reloadData 的时候,也要一并更新该属性,不然会出现数组越界。 + */ +@property (nonatomic, strong) NSArray *indicatorColors; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.m new file mode 100644 index 0000000..9978c8c --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.m @@ -0,0 +1,38 @@ +// +// JXCategoryIndicatorRainbowLineView.m +// JXCategoryView +// +// Created by jiaxin on 2018/12/13. +// Copyright © 2018 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorRainbowLineView.h" +#import "JXCategoryFactory.h" + +@implementation JXCategoryIndicatorRainbowLineView + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + [super jx_refreshState:model]; + + UIColor *color = self.indicatorColors[model.selectedIndex]; + self.backgroundColor = color; +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + [super jx_contentScrollViewDidScroll:model]; + + UIColor *leftColor = self.indicatorColors[model.leftIndex]; + UIColor *rightColor = self.indicatorColors[model.rightIndex]; + UIColor *color = [JXCategoryFactory interpolationColorFrom:leftColor to:rightColor percent:model.percent]; + self.backgroundColor = color; +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + [super jx_selectedCell:model]; + + UIColor *color = self.indicatorColors[model.selectedIndex]; + self.backgroundColor = color; +} + + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.h b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.h new file mode 100644 index 0000000..e4dfdb2 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.h @@ -0,0 +1,14 @@ +// +// JXCategoryIndicatorTriangleView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorComponentView.h" + +/// 三角形样式的指示器 +@interface JXCategoryIndicatorTriangleView : JXCategoryIndicatorComponentView + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.m b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.m new file mode 100644 index 0000000..96f5ab0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.m @@ -0,0 +1,109 @@ +// +// JXCategoryIndicatorTriangleView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/17. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorTriangleView.h" +#import "JXCategoryFactory.h" + +@interface JXCategoryIndicatorTriangleView () +@property (nonatomic, strong) CAShapeLayer *triangleLayer; +@end + +@implementation JXCategoryIndicatorTriangleView + +#pragma mark - Initialize + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self configureDefaulteValue]; + } + return self; +} + +- (void)configureDefaulteValue { + self.indicatorWidth = 14; + self.indicatorHeight = 10; + + _triangleLayer = [CAShapeLayer layer]; + [self.layer addSublayer:self.triangleLayer]; +} + +#pragma mark - JXCategoryIndicatorProtocol + +- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model { + CGFloat x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - [self indicatorWidthValue:model.selectedCellFrame])/2; + CGFloat y = self.superview.bounds.size.height - [self indicatorHeightValue:model.selectedCellFrame] - self.verticalMargin; + if (self.componentPosition == JXCategoryComponentPosition_Top) { + y = self.verticalMargin; + } + self.frame = CGRectMake(x, y, [self indicatorWidthValue:model.selectedCellFrame], [self indicatorHeightValue:model.selectedCellFrame]); + + [CATransaction begin]; + [CATransaction setDisableActions:NO]; + self.triangleLayer.fillColor = self.indicatorColor.CGColor; + self.triangleLayer.frame = self.bounds; + UIBezierPath *path = [UIBezierPath bezierPath]; + if (self.componentPosition == JXCategoryComponentPosition_Bottom) { + [path moveToPoint:CGPointMake(self.bounds.size.width/2, 0)]; + [path addLineToPoint:CGPointMake(0, self.bounds.size.height)]; + [path addLineToPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height)]; + } else { + [path moveToPoint:CGPointMake(0, 0)]; + [path addLineToPoint:CGPointMake(self.bounds.size.width, 0)]; + [path addLineToPoint:CGPointMake(self.bounds.size.width/2, self.bounds.size.height)]; + } + [path closePath]; + self.triangleLayer.path = path.CGPath; + [CATransaction commit]; +} + +- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model { + CGRect rightCellFrame = model.rightCellFrame; + CGRect leftCellFrame = model.leftCellFrame; + CGFloat percent = model.percent; + CGFloat targetWidth = [self indicatorWidthValue:model.leftCellFrame]; + CGFloat targetX = 0; + + if (percent == 0) { + targetX = leftCellFrame.origin.x + (leftCellFrame.size.width - targetWidth)/2.0; + } else { + CGFloat leftX = leftCellFrame.origin.x + (leftCellFrame.size.width - targetWidth)/2; + CGFloat rightX = rightCellFrame.origin.x + (rightCellFrame.size.width - targetWidth)/2; + targetX = [JXCategoryFactory interpolationFrom:leftX to:rightX percent:percent]; + } + + //允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了; + if (self.isScrollEnabled == YES || (self.isScrollEnabled == NO && percent == 0)) { + CGRect frame = self.frame; + frame.origin.x = targetX; + self.frame = frame; + } +} + +- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model { + CGRect toFrame = self.frame; + toFrame.origin.x = model.selectedCellFrame.origin.x + (model.selectedCellFrame.size.width - [self indicatorWidthValue:model.selectedCellFrame])/2; + if (self.isScrollEnabled) { + [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ + self.frame = toFrame; + } completion:^(BOOL finished) { + }]; + } else { + self.frame = toFrame; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCell.h b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCell.h new file mode 100644 index 0000000..27796d5 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCell.h @@ -0,0 +1,13 @@ +// +// JXCategoryComponetCell.h +// DQGuess +// +// Created by jiaxin on 2018/7/25. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryBaseCell.h" + +@interface JXCategoryIndicatorCell : JXCategoryBaseCell + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCell.m b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCell.m new file mode 100644 index 0000000..390701f --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCell.m @@ -0,0 +1,52 @@ +// +// JXCategoryComponetCell.m +// DQGuess +// +// Created by jiaxin on 2018/7/25. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryIndicatorCell.h" +#import "JXCategoryIndicatorCellModel.h" + +@interface JXCategoryIndicatorCell () +@property (nonatomic, strong) UIView *separatorLine; +@end + +@implementation JXCategoryIndicatorCell + +- (void)initializeViews { + [super initializeViews]; + + self.separatorLine = [[UIView alloc] init]; + self.separatorLine.hidden = YES; + [self.contentView addSubview:self.separatorLine]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + JXCategoryIndicatorCellModel *model = (JXCategoryIndicatorCellModel *)self.cellModel; + CGFloat lineWidth = model.separatorLineSize.width; + CGFloat lineHeight = model.separatorLineSize.height; + + self.separatorLine.frame = CGRectMake(self.bounds.size.width - lineWidth + self.cellModel.cellSpacing/2, (self.bounds.size.height - lineHeight)/2.0, lineWidth, lineHeight); +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryIndicatorCellModel *model = (JXCategoryIndicatorCellModel *)cellModel; + self.separatorLine.backgroundColor = model.separatorLineColor; + self.separatorLine.hidden = !model.isSepratorLineShowEnabled; + + if (model.isCellBackgroundColorGradientEnabled) { + if (model.isSelected) { + self.contentView.backgroundColor = model.cellBackgroundSelectedColor; + }else { + self.contentView.backgroundColor = model.cellBackgroundUnselectedColor; + } + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCellModel.h b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCellModel.h new file mode 100644 index 0000000..21effb0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCellModel.h @@ -0,0 +1,24 @@ +// +// JXCategoryComponentCellModel.h +// DQGuess +// +// Created by jiaxin on 2018/7/25. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import +#import "JXCategoryBaseCellModel.h" + +@interface JXCategoryIndicatorCellModel : JXCategoryBaseCellModel + +@property (nonatomic, assign, getter=isSepratorLineShowEnabled) BOOL sepratorLineShowEnabled; +@property (nonatomic, strong) UIColor *separatorLineColor; +@property (nonatomic, assign) CGSize separatorLineSize; + +@property (nonatomic, assign) CGRect backgroundViewMaskFrame; // 底部指示器的 frame 转换到 cell 的 frame + +@property (nonatomic, assign, getter=isCellBackgroundColorGradientEnabled) BOOL cellBackgroundColorGradientEnabled; +@property (nonatomic, strong) UIColor *cellBackgroundSelectedColor; +@property (nonatomic, strong) UIColor *cellBackgroundUnselectedColor; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCellModel.m b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCellModel.m new file mode 100644 index 0000000..d79d6f4 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorCellModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryComponentCellModel.m +// DQGuess +// +// Created by jiaxin on 2018/7/25. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryIndicatorCellModel.h" + +@implementation JXCategoryIndicatorCellModel + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorView.h b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorView.h new file mode 100644 index 0000000..a172268 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorView.h @@ -0,0 +1,48 @@ +// +// JXCategoryComponentView.h +// DQGuess +// +// Created by jiaxin on 2018/7/25. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryBaseView.h" +#import "JXCategoryIndicatorCell.h" +#import "JXCategoryIndicatorCellModel.h" +#import "JXCategoryIndicatorProtocol.h" + +@interface JXCategoryIndicatorView : JXCategoryBaseView + +@property (nonatomic, strong) NSArray *> *indicators; + +//----------------------ellBackgroundColor-----------------------// +//cell的背景色是否渐变。默认:NO +@property (nonatomic, assign, getter=isCellBackgroundColorGradientEnabled) BOOL cellBackgroundColorGradientEnabled; +//cell普通状态的背景色。默认:[UIColor clearColor] +@property (nonatomic, strong) UIColor *cellBackgroundUnselectedColor; +//cell选中状态的背景色。默认:[UIColor grayColor] +@property (nonatomic, strong) UIColor *cellBackgroundSelectedColor; + +//----------------------separatorLine-----------------------// +//是否显示分割线。默认为NO +@property (nonatomic, assign, getter=isSeparatorLineShowEnabled) BOOL separatorLineShowEnabled; +//分割线颜色。默认为[UIColor lightGrayColor] +@property (nonatomic, strong) UIColor *separatorLineColor; +//分割线的size。默认为CGSizeMake(1/[UIScreen mainScreen].scale, 20) +@property (nonatomic, assign) CGSize separatorLineSize; + +@end + +@interface JXCategoryIndicatorView (UISubclassingIndicatorHooks) + +/** + 当contentScrollView滚动时候,处理跟随手势的过渡效果。 + 根据cellModel的左右位置、是否选中、ratio进行过滤数据计算。 + + @param leftCellModel 左边的cellModel + @param rightCellModel 右边的cellModel + @param ratio 从左往右方向计算的百分比 + */ +- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratio NS_REQUIRES_SUPER; + +@end diff --git a/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorView.m b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorView.m new file mode 100644 index 0000000..861ccde --- /dev/null +++ b/Pods/JXCategoryView/Sources/Indicator/JXCategoryIndicatorView.m @@ -0,0 +1,209 @@ +// +// JXCategoryIndicatorView.m +// DQGuess +// +// Created by jiaxin on 2018/7/25. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryIndicatorView.h" +#import "JXCategoryIndicatorBackgroundView.h" +#import "JXCategoryFactory.h" + +@interface JXCategoryIndicatorView() + +@end + +@implementation JXCategoryIndicatorView + +- (void)initializeData { + [super initializeData]; + + _separatorLineShowEnabled = NO; + _separatorLineColor = [UIColor lightGrayColor]; + _separatorLineSize = CGSizeMake(1/[UIScreen mainScreen].scale, 20); + _cellBackgroundColorGradientEnabled = NO; + _cellBackgroundUnselectedColor = [UIColor whiteColor]; + _cellBackgroundSelectedColor = [UIColor lightGrayColor]; +} + +- (void)initializeViews { + [super initializeViews]; +} + +- (void)setIndicators:(NSArray *> *)indicators { + _indicators = indicators; + + self.collectionView.indicators = indicators; +} + +- (void)refreshState { + [super refreshState]; + + CGRect selectedCellFrame = CGRectZero; + JXCategoryIndicatorCellModel *selectedCellModel; + for (int i = 0; i < self.dataSource.count; i++) { + JXCategoryIndicatorCellModel *cellModel = (JXCategoryIndicatorCellModel *)self.dataSource[i]; + cellModel.sepratorLineShowEnabled = self.isSeparatorLineShowEnabled; + cellModel.separatorLineColor = self.separatorLineColor; + cellModel.separatorLineSize = self.separatorLineSize; + cellModel.backgroundViewMaskFrame = CGRectZero; + cellModel.cellBackgroundColorGradientEnabled = self.isCellBackgroundColorGradientEnabled; + cellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor; + cellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor; + if (i == self.dataSource.count - 1) { + cellModel.sepratorLineShowEnabled = NO; + } + if (i == self.selectedIndex) { + selectedCellModel = cellModel; + selectedCellFrame = [self getTargetCellFrame:i]; + } + } + + for (UIView *indicator in self.indicators) { + if (self.dataSource.count <= 0) { + indicator.hidden = YES; + } else { + indicator.hidden = NO; + JXCategoryIndicatorParamsModel *indicatorParamsModel = [[JXCategoryIndicatorParamsModel alloc] init]; + indicatorParamsModel.selectedIndex = self.selectedIndex; + indicatorParamsModel.selectedCellFrame = selectedCellFrame; + [indicator jx_refreshState:indicatorParamsModel]; + + if ([indicator isKindOfClass:[JXCategoryIndicatorBackgroundView class]]) { + CGRect maskFrame = indicator.frame; + maskFrame.origin.x = maskFrame.origin.x - selectedCellFrame.origin.x; + selectedCellModel.backgroundViewMaskFrame = maskFrame; + } + } + } +} + +- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel { + [super refreshSelectedCellModel:selectedCellModel unselectedCellModel:unselectedCellModel]; + + JXCategoryIndicatorCellModel *myUnselectedCellModel = (JXCategoryIndicatorCellModel *)unselectedCellModel; + myUnselectedCellModel.backgroundViewMaskFrame = CGRectZero; + myUnselectedCellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor; + myUnselectedCellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor; + + JXCategoryIndicatorCellModel *myselectedCellModel = (JXCategoryIndicatorCellModel *)selectedCellModel; + myselectedCellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor; + myselectedCellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor; +} + +- (void)contentOffsetOfContentScrollViewDidChanged:(CGPoint)contentOffset { + [super contentOffsetOfContentScrollViewDidChanged:contentOffset]; + + CGFloat ratio = contentOffset.x/self.contentScrollView.bounds.size.width; + if (ratio > self.dataSource.count - 1 || ratio < 0) { + //超过了边界,不需要处理 + return; + } + ratio = MAX(0, MIN(self.dataSource.count - 1, ratio)); + NSInteger baseIndex = floorf(ratio); + if (baseIndex + 1 >= self.dataSource.count) { + //右边越界了,不需要处理 + return; + } + CGFloat remainderRatio = ratio - baseIndex; + + CGRect leftCellFrame = [self getTargetCellFrame:baseIndex]; + CGRect rightCellFrame = [self getTargetCellFrame:baseIndex + 1]; + + JXCategoryIndicatorParamsModel *indicatorParamsModel = [[JXCategoryIndicatorParamsModel alloc] init]; + indicatorParamsModel.selectedIndex = self.selectedIndex; + indicatorParamsModel.leftIndex = baseIndex; + indicatorParamsModel.leftCellFrame = leftCellFrame; + indicatorParamsModel.rightIndex = baseIndex + 1; + indicatorParamsModel.rightCellFrame = rightCellFrame; + indicatorParamsModel.percent = remainderRatio; + if (remainderRatio == 0) { + for (UIView *indicator in self.indicators) { + [indicator jx_contentScrollViewDidScroll:indicatorParamsModel]; + } + } else { + JXCategoryIndicatorCellModel *leftCellModel = (JXCategoryIndicatorCellModel *)self.dataSource[baseIndex]; + leftCellModel.selectedType = JXCategoryCellSelectedTypeUnknown; + JXCategoryIndicatorCellModel *rightCellModel = (JXCategoryIndicatorCellModel *)self.dataSource[baseIndex + 1]; + rightCellModel.selectedType = JXCategoryCellSelectedTypeUnknown; + [self refreshLeftCellModel:leftCellModel rightCellModel:rightCellModel ratio:remainderRatio]; + + for (UIView *indicator in self.indicators) { + [indicator jx_contentScrollViewDidScroll:indicatorParamsModel]; + if ([indicator isKindOfClass:[JXCategoryIndicatorBackgroundView class]]) { + CGRect leftMaskFrame = indicator.frame; + leftMaskFrame.origin.x = leftMaskFrame.origin.x - leftCellFrame.origin.x; + leftCellModel.backgroundViewMaskFrame = leftMaskFrame; + + CGRect rightMaskFrame = indicator.frame; + rightMaskFrame.origin.x = rightMaskFrame.origin.x - rightCellFrame.origin.x; + rightCellModel.backgroundViewMaskFrame = rightMaskFrame; + } + } + + JXCategoryBaseCell *leftCell = (JXCategoryBaseCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:baseIndex inSection:0]]; + [leftCell reloadData:leftCellModel]; + JXCategoryBaseCell *rightCell = (JXCategoryBaseCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:baseIndex + 1 inSection:0]]; + [rightCell reloadData:rightCellModel]; + } +} + +- (BOOL)selectCellAtIndex:(NSInteger)index selectedType:(JXCategoryCellSelectedType)selectedType { + NSInteger lastSelectedIndex = self.selectedIndex; + BOOL result = [super selectCellAtIndex:index selectedType:selectedType]; + if (!result) { + return NO; + } + + CGRect clickedCellFrame = [self getTargetSelectedCellFrame:index selectedType:selectedType]; + + JXCategoryIndicatorCellModel *selectedCellModel = (JXCategoryIndicatorCellModel *)self.dataSource[index]; + selectedCellModel.selectedType = selectedType; + for (UIView *indicator in self.indicators) { + JXCategoryIndicatorParamsModel *indicatorParamsModel = [[JXCategoryIndicatorParamsModel alloc] init]; + indicatorParamsModel.lastSelectedIndex = lastSelectedIndex; + indicatorParamsModel.selectedIndex = index; + indicatorParamsModel.selectedCellFrame = clickedCellFrame; + indicatorParamsModel.selectedType = selectedType; + [indicator jx_selectedCell:indicatorParamsModel]; + if ([indicator isKindOfClass:[JXCategoryIndicatorBackgroundView class]]) { + CGRect maskFrame = indicator.frame; + maskFrame.origin.x = maskFrame.origin.x - clickedCellFrame.origin.x; + selectedCellModel.backgroundViewMaskFrame = maskFrame; + } + } + + JXCategoryIndicatorCell *selectedCell = (JXCategoryIndicatorCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + [selectedCell reloadData:selectedCellModel]; + + return YES; +} + +@end + +@implementation JXCategoryIndicatorView (UISubclassingIndicatorHooks) + +- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratio { + if (self.isCellBackgroundColorGradientEnabled) { + //处理cell背景色渐变 + JXCategoryIndicatorCellModel *leftModel = (JXCategoryIndicatorCellModel *)leftCellModel; + JXCategoryIndicatorCellModel *rightModel = (JXCategoryIndicatorCellModel *)rightCellModel; + if (leftModel.isSelected) { + leftModel.cellBackgroundSelectedColor = [JXCategoryFactory interpolationColorFrom:self.cellBackgroundSelectedColor to:self.cellBackgroundUnselectedColor percent:ratio]; + leftModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor; + }else { + leftModel.cellBackgroundUnselectedColor = [JXCategoryFactory interpolationColorFrom:self.cellBackgroundSelectedColor to:self.cellBackgroundUnselectedColor percent:ratio]; + leftModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor; + } + if (rightModel.isSelected) { + rightModel.cellBackgroundSelectedColor = [JXCategoryFactory interpolationColorFrom:self.cellBackgroundUnselectedColor to:self.cellBackgroundSelectedColor percent:ratio]; + rightModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor; + }else { + rightModel.cellBackgroundUnselectedColor = [JXCategoryFactory interpolationColorFrom:self.cellBackgroundUnselectedColor to:self.cellBackgroundSelectedColor percent:ratio]; + rightModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor; + } + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/JXCategoryView.h b/Pods/JXCategoryView/Sources/JXCategoryView.h new file mode 100644 index 0000000..d90c0cc --- /dev/null +++ b/Pods/JXCategoryView/Sources/JXCategoryView.h @@ -0,0 +1,23 @@ + + +#import "JXCategoryBaseView.h" +#import "JXCategoryIndicatorView.h" +#import "JXCategoryTitleView.h" +#import "JXCategoryImageView.h" +#import "JXCategoryTitleImageView.h" +#import "JXCategoryNumberView.h" +#import "JXCategoryDotView.h" + +#import "JXCategoryFactory.h" +#import "JXCategoryIndicatorProtocol.h" +#import "JXCategoryViewDefines.h" +#import "JXCategoryListContainerView.h" + +#import "JXCategoryIndicatorComponentView.h" +#import "JXCategoryIndicatorLineView.h" +#import "JXCategoryIndicatorTriangleView.h" +#import "JXCategoryIndicatorImageView.h" +#import "JXCategoryIndicatorBackgroundView.h" +#import "JXCategoryIndicatorBallView.h" +#import "JXCategoryIndicatorRainbowLineView.h" + diff --git a/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCell.h b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCell.h new file mode 100644 index 0000000..acbc2db --- /dev/null +++ b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCell.h @@ -0,0 +1,13 @@ +// +// JXCategoryNumberCell.h +// DQGuess +// +// Created by jiaxin on 2018/4/9. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryTitleCell.h" + +@interface JXCategoryNumberCell : JXCategoryTitleCell +@property (nonatomic, strong) UILabel *numberLabel; +@end diff --git a/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCell.m b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCell.m new file mode 100644 index 0000000..e9bcbd4 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCell.m @@ -0,0 +1,62 @@ +// +// JXCategoryNumberCell.m +// DQGuess +// +// Created by jiaxin on 2018/4/9. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryNumberCell.h" +#import "JXCategoryNumberCellModel.h" + +@interface JXCategoryNumberCell () +@property (nonatomic, strong) NSLayoutConstraint *numberCenterXConstraint; +@property (nonatomic, strong) NSLayoutConstraint *numberCenterYConstraint; +@property (nonatomic, strong) NSLayoutConstraint *numberHeightConstraint; +@property (nonatomic, strong) NSLayoutConstraint *numberWidthConstraint; +@end + +@implementation JXCategoryNumberCell + +- (void)prepareForReuse { + [super prepareForReuse]; + + self.numberLabel.text = nil; +} + +- (void)initializeViews { + [super initializeViews]; + + self.numberLabel = [[UILabel alloc] init]; + self.numberLabel.textAlignment = NSTextAlignmentCenter; + self.numberLabel.layer.masksToBounds = YES; + [self.contentView addSubview:self.numberLabel]; + self.numberLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.numberCenterXConstraint = [self.numberLabel.centerXAnchor constraintEqualToAnchor:self.titleLabel.trailingAnchor]; + self.numberCenterYConstraint = [self.numberLabel.centerYAnchor constraintEqualToAnchor:self.titleLabel.topAnchor]; + self.numberHeightConstraint = [self.numberLabel.heightAnchor constraintEqualToConstant:0]; + self.numberWidthConstraint = [self.numberLabel.widthAnchor constraintEqualToConstant:0]; + [NSLayoutConstraint activateConstraints:@[self.numberCenterXConstraint, self.numberCenterYConstraint, self.numberWidthConstraint, self.numberHeightConstraint]]; +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryNumberCellModel *myCellModel = (JXCategoryNumberCellModel *)cellModel; + self.numberLabel.hidden = (myCellModel.count == 0); + self.numberLabel.backgroundColor = myCellModel.numberBackgroundColor; + self.numberLabel.font = myCellModel.numberLabelFont; + self.numberLabel.textColor = myCellModel.numberTitleColor; + self.numberLabel.text = myCellModel.numberString; + self.numberLabel.layer.cornerRadius = myCellModel.numberLabelHeight/2.0; + self.numberHeightConstraint.constant = myCellModel.numberLabelHeight; + self.numberCenterXConstraint.constant = myCellModel.numberLabelOffset.x; + self.numberCenterYConstraint.constant = myCellModel.numberLabelOffset.y; + if (myCellModel.count < 10 && myCellModel.shouldMakeRoundWhenSingleNumber) { + self.numberWidthConstraint.constant = myCellModel.numberLabelHeight; + }else { + self.numberWidthConstraint.constant = myCellModel.numberStringWidth + myCellModel.numberLabelWidthIncrement; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCellModel.h b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCellModel.h new file mode 100644 index 0000000..0622a64 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCellModel.h @@ -0,0 +1,25 @@ +// +// JXCategoryNumberCellModel.h +// DQGuess +// +// Created by jiaxin on 2018/4/24. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryTitleCellModel.h" + +@interface JXCategoryNumberCellModel : JXCategoryTitleCellModel + +@property (nonatomic, assign) NSInteger count; +@property (nonatomic, copy) NSString *numberString; +@property (nonatomic, assign, readonly) CGFloat numberStringWidth; +@property (nonatomic, copy) void(^numberStringFormatterBlock)(NSInteger number); +@property (nonatomic, strong) UIColor *numberBackgroundColor; +@property (nonatomic, strong) UIColor *numberTitleColor; +@property (nonatomic, assign) CGFloat numberLabelWidthIncrement; +@property (nonatomic, assign) CGFloat numberLabelHeight; +@property (nonatomic, strong) UIFont *numberLabelFont; +@property (nonatomic, assign) CGPoint numberLabelOffset; +@property (nonatomic, assign) BOOL shouldMakeRoundWhenSingleNumber; + +@end diff --git a/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCellModel.m b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCellModel.m new file mode 100644 index 0000000..43a940a --- /dev/null +++ b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberCellModel.m @@ -0,0 +1,37 @@ +// +// JXCategoryNumberCellModel.m +// DQGuess +// +// Created by jiaxin on 2018/4/24. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryNumberCellModel.h" + +@implementation JXCategoryNumberCellModel + +- (void)setNumberString:(NSString *)numberString { + _numberString = numberString; + + [self updateNumberSizeWidthIfNeeded]; +} + +- (void)setNumberLabelHeight:(CGFloat)numberLabelHeight { + _numberLabelHeight = numberLabelHeight; + + [self updateNumberSizeWidthIfNeeded]; +} + +- (void)setNumberLabelFont:(UIFont *)numberLabelFont { + _numberLabelFont = numberLabelFont; + + [self updateNumberSizeWidthIfNeeded]; +} + +- (void)updateNumberSizeWidthIfNeeded { + if (self.numberLabelFont != nil) { + _numberStringWidth = [self.numberString boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, self.numberLabelHeight) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.numberLabelFont} context:nil].size.width; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Number/JXCategoryNumberView.h b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberView.h new file mode 100644 index 0000000..af033a4 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberView.h @@ -0,0 +1,60 @@ +// +// JXCategoryNumberView.h +// DQGuess +// +// Created by jiaxin on 2018/4/9. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryTitleView.h" +#import "JXCategoryNumberCell.h" +#import "JXCategoryNumberCellModel.h" + +@interface JXCategoryNumberView : JXCategoryTitleView + +/** + 需要与titles的count对应 + */ +@property (nonatomic, strong) NSArray *counts; + +/** + 内部默认不会格式化数字,直接转成字符串显示。比如业务需要数字超过999显示999+,可以通过该block实现。 + */ +@property (nonatomic, copy) NSString *(^numberStringFormatterBlock)(NSInteger number); + +/** + numberLabel的font,默认:[UIFont systemFontOfSize:11] + */ +@property (nonatomic, strong) UIFont *numberLabelFont; + +/** + 数字的背景色,默认:[UIColor colorWithRed:241/255.0 green:147/255.0 blue:95/255.0 alpha:1] + */ +@property (nonatomic, strong) UIColor *numberBackgroundColor; + +/** + 数字的title颜色,默认:[UIColor whiteColor] + */ +@property (nonatomic, strong) UIColor *numberTitleColor; + +/** + numberLabel的宽度补偿,label真实的宽度是文字内容的宽度加上补偿的宽度,默认:10 + */ +@property (nonatomic, assign) CGFloat numberLabelWidthIncrement; + +/** + numberLabel的高度,默认:14 + */ +@property (nonatomic, assign) CGFloat numberLabelHeight; + +/** + numberLabel x,y方向的偏移 (+值:水平方向向右,竖直方向向下) + */ +@property (nonatomic, assign) CGPoint numberLabelOffset; + +/** +当是单一数字时,是否让numberLabel变成圆。即numberLabel的宽度等于高度,cornerRadius等于高度/2。当为true,单一数字时会忽略numberLabelWidthIncrement属性。默认为NO; +*/ +@property (nonatomic, assign) BOOL shouldMakeRoundWhenSingleNumber; + +@end diff --git a/Pods/JXCategoryView/Sources/Number/JXCategoryNumberView.m b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberView.m new file mode 100644 index 0000000..c7a7b40 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Number/JXCategoryNumberView.m @@ -0,0 +1,61 @@ +// +// JXCategoryNumberView.m +// DQGuess +// +// Created by jiaxin on 2018/4/9. +// Copyright © 2018年 jingbo. All rights reserved. +// + +#import "JXCategoryNumberView.h" + +@implementation JXCategoryNumberView + +- (void)dealloc { + self.numberStringFormatterBlock = nil; +} + +- (void)initializeData { + [super initializeData]; + + self.cellSpacing = 25; + _numberTitleColor = [UIColor whiteColor]; + _numberBackgroundColor = [UIColor colorWithRed:241/255.0 green:147/255.0 blue:95/255.0 alpha:1]; + _numberLabelHeight = 14; + _numberLabelWidthIncrement = 10; + _numberLabelFont = [UIFont systemFontOfSize:11]; + _shouldMakeRoundWhenSingleNumber = NO; +} + +- (Class)preferredCellClass { + return [JXCategoryNumberCell class]; +} + +- (void)refreshDataSource { + NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:self.titles.count]; + for (int i = 0; i < self.titles.count; i++) { + JXCategoryNumberCellModel *cellModel = [[JXCategoryNumberCellModel alloc] init]; + [tempArray addObject:cellModel]; + } + self.dataSource = [NSArray arrayWithArray:tempArray]; +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + [super refreshCellModel:cellModel index:index]; + + JXCategoryNumberCellModel *myCellModel = (JXCategoryNumberCellModel *)cellModel; + myCellModel.count = [self.counts[index] integerValue]; + if (self.numberStringFormatterBlock != nil) { + myCellModel.numberString = self.numberStringFormatterBlock(myCellModel.count); + }else { + myCellModel.numberString = [NSString stringWithFormat:@"%ld", (long)myCellModel.count]; + } + myCellModel.numberBackgroundColor = self.numberBackgroundColor; + myCellModel.numberTitleColor = self.numberTitleColor; + myCellModel.numberLabelHeight = self.numberLabelHeight; + myCellModel.numberLabelOffset = self.numberLabelOffset; + myCellModel.numberLabelWidthIncrement = self.numberLabelWidthIncrement; + myCellModel.numberLabelFont = self.numberLabelFont; + myCellModel.shouldMakeRoundWhenSingleNumber = self.shouldMakeRoundWhenSingleNumber; +} + +@end diff --git a/Pods/JXCategoryView/Sources/PrivacyInfo.xcprivacy b/Pods/JXCategoryView/Sources/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..9021190 --- /dev/null +++ b/Pods/JXCategoryView/Sources/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/Pods/JXCategoryView/Sources/RLTManager/RTLManager.h b/Pods/JXCategoryView/Sources/RLTManager/RTLManager.h new file mode 100644 index 0000000..6c0471e --- /dev/null +++ b/Pods/JXCategoryView/Sources/RLTManager/RTLManager.h @@ -0,0 +1,20 @@ +// +// RTLManager.h +// JXCategoryView +// +// Created by jiaxin on 2020/7/3. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RTLManager : NSObject + ++ (BOOL)supportRTL; ++ (void)horizontalFlipView:(UIView *)view; ++ (void)horizontalFlipViewIfNeeded:(UIView *)view; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/JXCategoryView/Sources/RLTManager/RTLManager.m b/Pods/JXCategoryView/Sources/RLTManager/RTLManager.m new file mode 100644 index 0000000..9ce9eab --- /dev/null +++ b/Pods/JXCategoryView/Sources/RLTManager/RTLManager.m @@ -0,0 +1,26 @@ +// +// RTLManager.m +// JXCategoryView +// +// Created by jiaxin on 2020/7/3. +// + +#import "RTLManager.h" + +@implementation RTLManager + ++ (BOOL)supportRTL { + return [UIView userInterfaceLayoutDirectionForSemanticContentAttribute:UIView.appearance.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft; +} + ++ (void)horizontalFlipView:(UIView *)view { + view.transform = CGAffineTransformMakeScale(-1, 1); +} + ++ (void)horizontalFlipViewIfNeeded:(UIView *)view { + if ([self supportRTL]) { + [self horizontalFlipView:view]; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.h b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.h new file mode 100644 index 0000000..8ab54d6 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.h @@ -0,0 +1,27 @@ +// +// JXCategoryTitleCell.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorCell.h" +#import "JXCategoryViewDefines.h" +@class JXCategoryTitleCellModel; + +@interface JXCategoryTitleCell : JXCategoryIndicatorCell + +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *maskTitleLabel; +@property (nonatomic, strong) NSLayoutConstraint *titleLabelCenterX; +@property (nonatomic, strong) NSLayoutConstraint *titleLabelCenterY; +@property (nonatomic, strong) NSLayoutConstraint *maskTitleLabelCenterX; + +- (JXCategoryCellSelectedAnimationBlock)preferredTitleZoomAnimationBlock:(JXCategoryTitleCellModel *)cellModel baseScale:(CGFloat)baseScale; + +- (JXCategoryCellSelectedAnimationBlock)preferredTitleStrokeWidthAnimationBlock:(JXCategoryTitleCellModel *)cellModel attributedString:(NSMutableAttributedString *)attributedString; + +- (JXCategoryCellSelectedAnimationBlock)preferredTitleColorAnimationBlock:(JXCategoryTitleCellModel *)cellModel; + +@end diff --git a/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.m b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.m new file mode 100644 index 0000000..ae2b446 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.m @@ -0,0 +1,240 @@ +// +// JXCategoryTitleCell.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCell.h" +#import "JXCategoryTitleCellModel.h" +#import "JXCategoryFactory.h" +#import "RTLManager.h" + +@interface JXCategoryTitleCell () +@property (nonatomic, strong) CALayer *titleMaskLayer; +@property (nonatomic, strong) CALayer *maskTitleMaskLayer; +@property (nonatomic, strong) NSLayoutConstraint *maskTitleLabelCenterY; +@end + +@implementation JXCategoryTitleCell + +- (void)initializeViews { + [super initializeViews]; + + self.isAccessibilityElement = true; + self.accessibilityTraits = UIAccessibilityTraitButton; + _titleLabel = [[UILabel alloc] init]; + self.titleLabel.clipsToBounds = YES; + self.titleLabel.textAlignment = NSTextAlignmentCenter; + self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.contentView addSubview:self.titleLabel]; + + self.titleLabelCenterX = [self.titleLabel.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor constant:0]; + self.titleLabelCenterY = [self.titleLabel.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor constant:0]; + + _titleMaskLayer = [CALayer layer]; + self.titleMaskLayer.backgroundColor = [UIColor redColor].CGColor; + + _maskTitleLabel = [[UILabel alloc] init]; + self.maskTitleLabel.hidden = YES; + self.maskTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.maskTitleLabel.textAlignment = NSTextAlignmentCenter; + [self.contentView addSubview:self.maskTitleLabel]; + + self.maskTitleLabelCenterX = [self.maskTitleLabel.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor]; + self.maskTitleLabelCenterY = [self.maskTitleLabel.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor]; + + _maskTitleMaskLayer = [CALayer layer]; + self.maskTitleMaskLayer.backgroundColor = [UIColor redColor].CGColor; + self.maskTitleLabel.layer.mask = self.maskTitleMaskLayer; + + [NSLayoutConstraint activateConstraints:@[self.titleLabelCenterX, self.titleLabelCenterY, self.maskTitleLabelCenterX, self.maskTitleLabelCenterY]]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + JXCategoryTitleCellModel *myCellModel = (JXCategoryTitleCellModel *)self.cellModel; + switch (myCellModel.titleLabelAnchorPointStyle) { + case JXCategoryTitleLabelAnchorPointStyleCenter: { + self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 0.5); + self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 0.5); + self.titleLabelCenterY.constant = 0 + myCellModel.titleLabelVerticalOffset; + break; + } + case JXCategoryTitleLabelAnchorPointStyleTop: { + self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 0); + self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 0); + CGFloat percent = (myCellModel.titleLabelCurrentZoomScale - myCellModel.titleLabelNormalZoomScale)/(myCellModel.titleLabelSelectedZoomScale - myCellModel.titleLabelNormalZoomScale); + self.titleLabelCenterY.constant = -myCellModel.titleHeight/2 - myCellModel.titleLabelVerticalOffset - myCellModel.titleLabelZoomSelectedVerticalOffset*percent; + break; + } + case JXCategoryTitleLabelAnchorPointStyleBottom: { + self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 1); + self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 1); + CGFloat percent = (myCellModel.titleLabelCurrentZoomScale - myCellModel.titleLabelNormalZoomScale)/(myCellModel.titleLabelSelectedZoomScale - myCellModel.titleLabelNormalZoomScale); + self.titleLabelCenterY.constant = myCellModel.titleHeight/2 + myCellModel.titleLabelVerticalOffset + myCellModel.titleLabelZoomSelectedVerticalOffset*percent; + break; + } + } +} + + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryTitleCellModel *myCellModel = (JXCategoryTitleCellModel *)cellModel; + self.accessibilityLabel = myCellModel.title; + self.titleLabel.numberOfLines = myCellModel.titleNumberOfLines; + self.maskTitleLabel.numberOfLines = myCellModel.titleNumberOfLines; + + if (myCellModel.isTitleLabelZoomEnabled) { + //先把font设置为缩放的最大值,再缩小到最小值,最后根据当前的titleLabelZoomScale值,进行缩放更新。这样就能避免transform从小到大时字体模糊 + UIFont *maxScaleFont = [UIFont fontWithDescriptor:myCellModel.titleFont.fontDescriptor size:myCellModel.titleFont.pointSize*myCellModel.titleLabelSelectedZoomScale]; + CGFloat baseScale = myCellModel.titleFont.lineHeight/maxScaleFont.lineHeight; + if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) { + JXCategoryCellSelectedAnimationBlock block = [self preferredTitleZoomAnimationBlock:myCellModel baseScale:baseScale]; + [self addSelectedAnimationBlock:block]; + } else { + self.titleLabel.font = maxScaleFont; + self.maskTitleLabel.font = maxScaleFont; + CGAffineTransform currentTransform = CGAffineTransformMakeScale(baseScale*myCellModel.titleLabelCurrentZoomScale, baseScale*myCellModel.titleLabelCurrentZoomScale); + self.titleLabel.transform = currentTransform; + self.maskTitleLabel.transform = currentTransform; + } + } else { + if (myCellModel.isSelected) { + self.titleLabel.font = myCellModel.titleSelectedFont; + self.maskTitleLabel.font = myCellModel.titleSelectedFont; + } else { + self.titleLabel.font = myCellModel.titleFont; + self.maskTitleLabel.font = myCellModel.titleFont; + } + } + + NSString *titleString = myCellModel.title ? myCellModel.title : @""; + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:titleString]; + if (myCellModel.isTitleLabelStrokeWidthEnabled) { + if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) { + JXCategoryCellSelectedAnimationBlock block = [self preferredTitleStrokeWidthAnimationBlock:myCellModel attributedString:attributedString]; + [self addSelectedAnimationBlock:block]; + } else { + [attributedString addAttribute:NSStrokeWidthAttributeName value:@(myCellModel.titleLabelCurrentStrokeWidth) range:NSMakeRange(0, titleString.length)]; + self.titleLabel.attributedText = attributedString; + self.maskTitleLabel.attributedText = attributedString; + } + } else { + self.titleLabel.attributedText = attributedString; + self.maskTitleLabel.attributedText = attributedString; + } + + if (myCellModel.isTitleLabelMaskEnabled) { + self.maskTitleLabel.hidden = NO; + self.titleLabel.textColor = myCellModel.titleNormalColor; + self.maskTitleLabel.textColor = myCellModel.titleSelectedColor; + [self.contentView setNeedsLayout]; + [self.contentView layoutIfNeeded]; + + CGRect topMaskframe = myCellModel.backgroundViewMaskFrame; + //将相对于cell的backgroundViewMaskFrame转换为相对于maskTitleLabel + //使用self.bounds.size.width而不是self.contentView.bounds.size.width。因为某些情况下,会出现self.bounds是正确的,而self.contentView.bounds还是重用前的状态。 + topMaskframe.origin.y = 0; + CGRect bottomMaskFrame = topMaskframe; + CGFloat maskStartX = 0; + if (self.maskTitleLabel.bounds.size.width >= self.bounds.size.width) { + topMaskframe.origin.x -= (self.maskTitleLabel.bounds.size.width -self.bounds.size.width)/2; + bottomMaskFrame.size.width = self.maskTitleLabel.bounds.size.width; + maskStartX = -(self.maskTitleLabel.bounds.size.width -self.bounds.size.width)/2; + } else { + bottomMaskFrame.size.width = self.bounds.size.width; + topMaskframe.origin.x -= (self.bounds.size.width -self.maskTitleLabel.bounds.size.width)/2; + maskStartX = 0; + } + bottomMaskFrame.origin.x = topMaskframe.origin.x; + if (topMaskframe.origin.x > maskStartX) { + bottomMaskFrame.origin.x = topMaskframe.origin.x - bottomMaskFrame.size.width; + } else { + bottomMaskFrame.origin.x = CGRectGetMaxX(topMaskframe); + } + + // 适配RTL布局(镜像x值) + if ([RTLManager supportRTL]) { + topMaskframe.origin.x = self.maskTitleMaskLayer.superlayer.frame.size.width - CGRectGetMaxX(topMaskframe); + bottomMaskFrame.origin.x = self.titleMaskLayer.superlayer.frame.size.width - CGRectGetMaxX(bottomMaskFrame); + } + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + if (topMaskframe.size.width > 0 && CGRectIntersectsRect(topMaskframe, self.maskTitleLabel.frame)) { + self.titleLabel.layer.mask = self.titleMaskLayer; + self.maskTitleMaskLayer.frame = topMaskframe; + self.titleMaskLayer.frame = bottomMaskFrame; + } else { + self.maskTitleMaskLayer.frame = topMaskframe; + self.titleLabel.layer.mask = nil; + } + [CATransaction commit]; + } else { + self.maskTitleLabel.hidden = YES; + self.titleLabel.layer.mask = nil; + if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) { + JXCategoryCellSelectedAnimationBlock block = [self preferredTitleColorAnimationBlock:myCellModel]; + [self addSelectedAnimationBlock:block]; + } else { + self.titleLabel.textColor = myCellModel.titleCurrentColor; + } + } + + [self startSelectedAnimationIfNeeded:myCellModel]; +} + +#pragma mark - Public + +- (JXCategoryCellSelectedAnimationBlock)preferredTitleZoomAnimationBlock:(JXCategoryTitleCellModel *)cellModel baseScale:(CGFloat)baseScale { + __weak typeof(self) weakSelf = self; + return ^(CGFloat percent) { + if (cellModel.isSelected) { + //将要选中,scale从小到大插值渐变 + cellModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:cellModel.titleLabelNormalZoomScale to:cellModel.titleLabelSelectedZoomScale percent:percent]; + } else { + //将要取消选中,scale从大到小插值渐变 + cellModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:cellModel.titleLabelSelectedZoomScale to:cellModel.titleLabelNormalZoomScale percent:percent]; + } + CGAffineTransform currentTransform = CGAffineTransformMakeScale(baseScale*cellModel.titleLabelCurrentZoomScale, baseScale*cellModel.titleLabelCurrentZoomScale); + weakSelf.titleLabel.transform = currentTransform; + weakSelf.maskTitleLabel.transform = currentTransform; + }; +} + +- (JXCategoryCellSelectedAnimationBlock)preferredTitleStrokeWidthAnimationBlock:(JXCategoryTitleCellModel *)cellModel attributedString:(NSMutableAttributedString *)attributedString { + __weak typeof(self) weakSelf = self; + return ^(CGFloat percent) { + if (cellModel.isSelected) { + //将要选中,StrokeWidth从小到大插值渐变 + cellModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:cellModel.titleLabelNormalStrokeWidth to:cellModel.titleLabelSelectedStrokeWidth percent:percent]; + } else { + //将要取消选中,StrokeWidth从大到小插值渐变 + cellModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:cellModel.titleLabelSelectedStrokeWidth to:cellModel.titleLabelNormalStrokeWidth percent:percent]; + } + [attributedString addAttribute:NSStrokeWidthAttributeName value:@(cellModel.titleLabelCurrentStrokeWidth) range:NSMakeRange(0, attributedString.string.length)]; + weakSelf.titleLabel.attributedText = attributedString; + weakSelf.maskTitleLabel.attributedText = attributedString; + }; +} + +- (JXCategoryCellSelectedAnimationBlock)preferredTitleColorAnimationBlock:(JXCategoryTitleCellModel *)cellModel { + __weak typeof(self) weakSelf = self; + return ^(CGFloat percent) { + if (cellModel.isSelected) { + //将要选中,textColor从titleNormalColor到titleSelectedColor插值渐变 + cellModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:cellModel.titleNormalColor to:cellModel.titleSelectedColor percent:percent]; + } else { + //将要取消选中,textColor从titleSelectedColor到titleNormalColor插值渐变 + cellModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:cellModel.titleSelectedColor to:cellModel.titleNormalColor percent:percent]; + } + weakSelf.titleLabel.textColor = cellModel.titleCurrentColor; + }; +} + +@end diff --git a/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.h b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.h new file mode 100644 index 0000000..ea7a298 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.h @@ -0,0 +1,44 @@ +// +// JXCategoryTitleCellModel.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorCellModel.h" +#import +#import "JXCategoryViewDefines.h" + +@interface JXCategoryTitleCellModel : JXCategoryIndicatorCellModel + +@property (nonatomic, copy) NSString *title; + +@property (nonatomic, assign, readonly) CGFloat titleHeight; + +@property (nonatomic, assign) NSInteger titleNumberOfLines; +@property (nonatomic, assign) CGFloat titleLabelVerticalOffset; + +@property (nonatomic, strong) UIColor *titleNormalColor; +@property (nonatomic, strong) UIColor *titleCurrentColor; +@property (nonatomic, strong) UIColor *titleSelectedColor; + +@property (nonatomic, strong) UIFont *titleFont; +@property (nonatomic, strong) UIFont *titleSelectedFont; + +@property (nonatomic, assign, getter=isTitleLabelMaskEnabled) BOOL titleLabelMaskEnabled; +@property (nonatomic, assign, getter=isTitleLabelZoomEnabled) BOOL titleLabelZoomEnabled; + +@property (nonatomic, assign) CGFloat titleLabelNormalZoomScale; +@property (nonatomic, assign) CGFloat titleLabelCurrentZoomScale; +@property (nonatomic, assign) CGFloat titleLabelSelectedZoomScale; +@property (nonatomic, assign) CGFloat titleLabelZoomSelectedVerticalOffset; + +@property (nonatomic, assign, getter=isTitleLabelStrokeWidthEnabled) BOOL titleLabelStrokeWidthEnabled; +@property (nonatomic, assign) CGFloat titleLabelNormalStrokeWidth; +@property (nonatomic, assign) CGFloat titleLabelCurrentStrokeWidth; +@property (nonatomic, assign) CGFloat titleLabelSelectedStrokeWidth; + +@property (nonatomic, assign) JXCategoryTitleLabelAnchorPointStyle titleLabelAnchorPointStyle; + +@end diff --git a/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.m b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.m new file mode 100644 index 0000000..bf0a27c --- /dev/null +++ b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.m @@ -0,0 +1,31 @@ +// +// JXCategoryTitleCellModel.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCellModel.h" + +@implementation JXCategoryTitleCellModel + +- (void)setTitle:(NSString *)title { + _title = title; + + [self updateNumberSizeWidthIfNeeded]; +} + +- (void)setTitleFont:(UIFont *)titleFont { + _titleFont = titleFont; + + [self updateNumberSizeWidthIfNeeded]; +} + +- (void)updateNumberSizeWidthIfNeeded { + if (self.titleFont) { + _titleHeight = [self.title boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.titleFont} context:nil].size.height; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.h b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.h new file mode 100644 index 0000000..33af07b --- /dev/null +++ b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.h @@ -0,0 +1,63 @@ +// +// JXCategoryView.h +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryIndicatorView.h" +#import "JXCategoryTitleCell.h" +#import "JXCategoryTitleCellModel.h" +#import "JXCategoryViewDefines.h" + +@class JXCategoryTitleView; + +@protocol JXCategoryTitleViewDataSource +@optional +// 如果将JXCategoryTitleView嵌套进UITableView的cell,每次重用的时候,JXCategoryTitleView进行reloadData时,会重新计算所有的title宽度。所以该应用场景,需要UITableView的cellModel缓存titles的文字宽度,再通过该代理方法返回给JXCategoryTitleView。 +// 如果实现了该方法就以该方法返回的宽度为准,不触发内部默认的文字宽度计算。 +- (CGFloat)categoryTitleView:(JXCategoryTitleView *)titleView widthForTitle:(NSString *)title; +@end + + +@interface JXCategoryTitleView : JXCategoryIndicatorView + +@property (nonatomic, weak) id titleDataSource; + +@property (nonatomic, strong) NSArray *titles; + +@property (nonatomic, assign) NSInteger titleNumberOfLines; //默认:1 + +@property (nonatomic, strong) UIColor *titleColor; //默认:[UIColor blackColor] + +@property (nonatomic, strong) UIColor *titleSelectedColor; //默认:[UIColor redColor] + +@property (nonatomic, strong) UIFont *titleFont; //默认:[UIFont systemFontOfSize:15] + +@property (nonatomic, strong) UIFont *titleSelectedFont; //文字被选中的字体。默认:与titleFont一样 + +@property (nonatomic, assign, getter=isTitleColorGradientEnabled) BOOL titleColorGradientEnabled; //默认:NO,title的颜色是否渐变过渡 + +@property (nonatomic, assign, getter=isTitleLabelMaskEnabled) BOOL titleLabelMaskEnabled; //默认:NO,titleLabel是否遮罩过滤。 + +//----------------------titleLabelZoomEnabled-----------------------// +@property (nonatomic, assign, getter=isTitleLabelZoomEnabled) BOOL titleLabelZoomEnabled; //默认为NO。为YES时titleSelectedFont失效,以titleFont为准。 + +@property (nonatomic, assign, getter=isTitleLabelZoomScrollGradientEnabled) BOOL titleLabelZoomScrollGradientEnabled; //手势滚动中,是否需要更新状态。默认为YES + +@property (nonatomic, assign) CGFloat titleLabelZoomScale; //默认1.2,titleLabelZoomEnabled为YES才生效。是对字号的缩放,比如titleFont的pointSize为10,放大之后字号就是10*1.2=12。 + +@property (nonatomic, assign) CGFloat titleLabelZoomSelectedVerticalOffset; //titleLabelZoomEnabled设置为YES,会对titleLabel进行transform缩放,当titleLabelZoomScale过大时(比如设置为2),选中的文本被放大之后底部会有很大的空白,从视觉上看就跟其他未选中的文本不在一个水平线上。这个时候就可以用这个值进行调整。 + +//----------------------titleLabelStrokeWidth-----------------------// +@property (nonatomic, assign, getter=isTitleLabelStrokeWidthEnabled) BOOL titleLabelStrokeWidthEnabled; //默认:NO + +@property (nonatomic, assign) CGFloat titleLabelSelectedStrokeWidth; //默认:-3,用于控制字体的粗细(底层通过NSStrokeWidthAttributeName实现)。使用该属性,务必让titleFont和titleSelectedFont设置为一样的!!! + +//----------------------titleLabel缩放中心位置-----------------------// +@property (nonatomic, assign) CGFloat titleLabelVerticalOffset; //titleLabel锚点垂直方向的位置偏移,数值越大越偏离中心,默认为:0 + +@property (nonatomic, assign) JXCategoryTitleLabelAnchorPointStyle titleLabelAnchorPointStyle; //titleLabel锚点位置,用于调整titleLabel缩放时的基准位置。默认为:JXCategoryTitleLabelAnchorPointStyleCenter + +@end diff --git a/Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.m b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.m new file mode 100644 index 0000000..ac2d5a0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.m @@ -0,0 +1,164 @@ +// +// JXCategoryView.m +// UI系列测试 +// +// Created by jiaxin on 2018/3/15. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleView.h" +#import "JXCategoryFactory.h" + +@implementation JXCategoryTitleView + +- (void)initializeData { + [super initializeData]; + + _titleNumberOfLines = 1; + _titleLabelZoomEnabled = NO; + _titleLabelZoomScale = 1.2; + _titleColor = [UIColor blackColor]; + _titleSelectedColor = [UIColor redColor]; + _titleFont = [UIFont systemFontOfSize:15]; + _titleColorGradientEnabled = NO; + _titleLabelMaskEnabled = NO; + _titleLabelZoomScrollGradientEnabled = YES; + _titleLabelStrokeWidthEnabled = NO; + _titleLabelSelectedStrokeWidth = -3; + _titleLabelVerticalOffset = 0; + _titleLabelAnchorPointStyle = JXCategoryTitleLabelAnchorPointStyleCenter; +} + +- (UIFont *)titleSelectedFont { + if (_titleSelectedFont) { + return _titleSelectedFont; + } + return self.titleFont; +} + +#pragma mark - Override + +- (Class)preferredCellClass { + return [JXCategoryTitleCell class]; +} + +- (void)refreshDataSource { + NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:self.titles.count]; + for (int i = 0; i < self.titles.count; i++) { + JXCategoryTitleCellModel *cellModel = [[JXCategoryTitleCellModel alloc] init]; + [tempArray addObject:cellModel]; + } + self.dataSource = [NSArray arrayWithArray:tempArray]; +} + +- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel { + [super refreshSelectedCellModel:selectedCellModel unselectedCellModel:unselectedCellModel]; + + JXCategoryTitleCellModel *myUnselectedCellModel = (JXCategoryTitleCellModel *)unselectedCellModel; + JXCategoryTitleCellModel *myselectedCellModel = (JXCategoryTitleCellModel *)selectedCellModel; + if (self.isSelectedAnimationEnabled && (selectedCellModel.selectedType == JXCategoryCellSelectedTypeClick || selectedCellModel.selectedType == JXCategoryCellSelectedTypeCode)) { + //开启了动画过渡,且cell在屏幕内,current的属性值会在cell里面进行动画插值更新 + //1、当unselectedCell在屏幕外的时候,还是需要在这里更新值 + //2、当selectedCell在屏幕外的时候,还是需要在这里更新值(比如调用selectItemAtIndex方法选中的时候) + BOOL isUnselectedCellVisible = NO; + BOOL isSelectedCellVisible = NO; + NSArray *indexPaths = [self.collectionView indexPathsForVisibleItems]; + for (NSIndexPath *indexPath in indexPaths) { + if (indexPath.item == myUnselectedCellModel.index) { + isUnselectedCellVisible = YES; + continue; + } else if (indexPath.item == myselectedCellModel.index) { + isSelectedCellVisible = YES; + continue; + } + } + if (!isUnselectedCellVisible) { + //但是当unselectedCell在屏幕外时,不会在cell里面通过动画插值更新,在这里直接更新 + myUnselectedCellModel.titleCurrentColor = myUnselectedCellModel.titleNormalColor; + myUnselectedCellModel.titleLabelCurrentZoomScale = myUnselectedCellModel.titleLabelNormalZoomScale; + myUnselectedCellModel.titleLabelCurrentStrokeWidth = myUnselectedCellModel.titleLabelNormalStrokeWidth; + } + if (!isSelectedCellVisible) { + //但是当selectedCell在屏幕外时,不会在cell里面通过动画插值更新,在这里直接更新 + myselectedCellModel.titleCurrentColor = myselectedCellModel.titleSelectedColor; + myselectedCellModel.titleLabelCurrentZoomScale = myselectedCellModel.titleLabelSelectedZoomScale; + myselectedCellModel.titleLabelCurrentStrokeWidth = myselectedCellModel.titleLabelSelectedStrokeWidth; + } + } else { + //没有开启动画,可以直接更新属性 + myselectedCellModel.titleCurrentColor = myselectedCellModel.titleSelectedColor; + myselectedCellModel.titleLabelCurrentZoomScale = myselectedCellModel.titleLabelSelectedZoomScale; + myselectedCellModel.titleLabelCurrentStrokeWidth = myselectedCellModel.titleLabelSelectedStrokeWidth; + + myUnselectedCellModel.titleCurrentColor = myUnselectedCellModel.titleNormalColor; + myUnselectedCellModel.titleLabelCurrentZoomScale = myUnselectedCellModel.titleLabelNormalZoomScale; + myUnselectedCellModel.titleLabelCurrentStrokeWidth = myUnselectedCellModel.titleLabelNormalStrokeWidth; + } +} + +- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratio { + [super refreshLeftCellModel:leftCellModel rightCellModel:rightCellModel ratio:ratio]; + + JXCategoryTitleCellModel *leftModel = (JXCategoryTitleCellModel *)leftCellModel; + JXCategoryTitleCellModel *rightModel = (JXCategoryTitleCellModel *)rightCellModel; + + if (self.isTitleLabelZoomEnabled && self.isTitleLabelZoomScrollGradientEnabled) { + leftModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:self.titleLabelZoomScale to:1.0 percent:ratio]; + rightModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:1.0 to:self.titleLabelZoomScale percent:ratio]; + } + + if (self.isTitleLabelStrokeWidthEnabled) { + leftModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:leftModel.titleLabelSelectedStrokeWidth to:leftModel.titleLabelNormalStrokeWidth percent:ratio]; + rightModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:rightModel.titleLabelNormalStrokeWidth to:rightModel.titleLabelSelectedStrokeWidth percent:ratio]; + } + + if (self.isTitleColorGradientEnabled) { + leftModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:self.titleSelectedColor to:self.titleColor percent:ratio]; + rightModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:self.titleColor to:self.titleSelectedColor percent:ratio]; + } +} + +- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index { + if (self.cellWidth == JXCategoryViewAutomaticDimension) { + if (self.titleDataSource && [self.titleDataSource respondsToSelector:@selector(categoryTitleView:widthForTitle:)]) { + return [self.titleDataSource categoryTitleView:self widthForTitle:self.titles[index]]; + } else { + return ceilf([self.titles[index] boundingRectWithSize:CGSizeMake(MAXFLOAT, self.bounds.size.height) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : self.titleFont} context:nil].size.width); + } + } else { + return self.cellWidth; + } +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + [super refreshCellModel:cellModel index:index]; + + JXCategoryTitleCellModel *model = (JXCategoryTitleCellModel *)cellModel; + model.title = self.titles[index]; + model.titleNumberOfLines = self.titleNumberOfLines; + model.titleFont = self.titleFont; + model.titleSelectedFont = self.titleSelectedFont; + model.titleNormalColor = self.titleColor; + model.titleSelectedColor = self.titleSelectedColor; + model.titleLabelMaskEnabled = self.isTitleLabelMaskEnabled; + model.titleLabelZoomEnabled = self.isTitleLabelZoomEnabled; + model.titleLabelNormalZoomScale = 1; + model.titleLabelZoomSelectedVerticalOffset = self.titleLabelZoomSelectedVerticalOffset; + model.titleLabelSelectedZoomScale = self.titleLabelZoomScale; + model.titleLabelStrokeWidthEnabled = self.isTitleLabelStrokeWidthEnabled; + model.titleLabelNormalStrokeWidth = 0; + model.titleLabelSelectedStrokeWidth = self.titleLabelSelectedStrokeWidth; + model.titleLabelVerticalOffset = self.titleLabelVerticalOffset; + model.titleLabelAnchorPointStyle = self.titleLabelAnchorPointStyle; + if (index == self.selectedIndex) { + model.titleCurrentColor = model.titleSelectedColor; + model.titleLabelCurrentZoomScale = model.titleLabelSelectedZoomScale; + model.titleLabelCurrentStrokeWidth= model.titleLabelSelectedStrokeWidth; + }else { + model.titleCurrentColor = model.titleNormalColor; + model.titleLabelCurrentZoomScale = model.titleLabelNormalZoomScale; + model.titleLabelCurrentStrokeWidth = model.titleLabelNormalStrokeWidth; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCell.h b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCell.h new file mode 100644 index 0000000..e430a67 --- /dev/null +++ b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCell.h @@ -0,0 +1,15 @@ +// +// JXCategoryImageCell.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/8. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCell.h" + +@interface JXCategoryTitleImageCell : JXCategoryTitleCell + +@property (nonatomic, strong) UIImageView *imageView; + +@end diff --git a/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCell.m b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCell.m new file mode 100644 index 0000000..ae6c39d --- /dev/null +++ b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCell.m @@ -0,0 +1,148 @@ +// +// JXCategoryImageCell.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/8. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleImageCell.h" +#import "JXCategoryTitleImageCellModel.h" + +@interface JXCategoryTitleImageCell() +@property (nonatomic, strong) id currentImageInfo; +@property (nonatomic, strong) NSString *currentImageName; +@property (nonatomic, strong) NSURL *currentImageURL; +@property (nonatomic, strong) UIStackView *stackView; +@property (nonatomic, strong) NSLayoutConstraint *imageViewWidthConstraint; +@property (nonatomic, strong) NSLayoutConstraint *imageViewHeightConstraint; +@end + +@implementation JXCategoryTitleImageCell + +- (void)prepareForReuse { + [super prepareForReuse]; + + self.currentImageInfo = nil; + self.currentImageName = nil; + self.currentImageURL = nil; +} + +- (void)initializeViews { + [super initializeViews]; + + [self.titleLabel removeFromSuperview]; + + _imageView = [[UIImageView alloc] init]; + self.imageView.translatesAutoresizingMaskIntoConstraints = NO; + self.imageView.contentMode = UIViewContentModeScaleAspectFit; + self.imageViewWidthConstraint = [self.imageView.widthAnchor constraintEqualToConstant:0]; + self.imageViewWidthConstraint.active = YES; + self.imageViewHeightConstraint = [self.imageView.heightAnchor constraintEqualToConstant:0]; + self.imageViewHeightConstraint.active = YES; + + _stackView = [[UIStackView alloc] init]; + self.stackView.alignment = UIStackViewAlignmentCenter; + [self.contentView addSubview:self.stackView]; + self.stackView.translatesAutoresizingMaskIntoConstraints = NO; + [self.stackView.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor].active = YES; + [self.stackView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor].active = YES; +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryTitleImageCellModel *myCellModel = (JXCategoryTitleImageCellModel *)cellModel; + + self.titleLabel.hidden = NO; + self.imageView.hidden = NO; + [self.stackView removeArrangedSubview:self.titleLabel]; + [self.stackView removeArrangedSubview:self.imageView]; + CGSize imageSize = myCellModel.imageSize; + self.imageViewWidthConstraint.constant = imageSize.width; + self.imageViewHeightConstraint.constant = imageSize.height; + self.stackView.spacing = myCellModel.titleImageSpacing; + + switch (myCellModel.imageType) { + case JXCategoryTitleImageType_TopImage: { + self.stackView.axis = UILayoutConstraintAxisVertical; + [self.stackView addArrangedSubview:self.imageView]; + [self.stackView addArrangedSubview:self.titleLabel]; + break; + } + case JXCategoryTitleImageType_LeftImage: { + self.stackView.axis = UILayoutConstraintAxisHorizontal; + [self.stackView addArrangedSubview:self.imageView]; + [self.stackView addArrangedSubview:self.titleLabel]; + break; + } + case JXCategoryTitleImageType_BottomImage: { + self.stackView.axis = UILayoutConstraintAxisVertical; + [self.stackView addArrangedSubview:self.titleLabel]; + [self.stackView addArrangedSubview:self.imageView]; + break; + } + case JXCategoryTitleImageType_RightImage: { + self.stackView.axis = UILayoutConstraintAxisHorizontal; + [self.stackView addArrangedSubview:self.titleLabel]; + [self.stackView addArrangedSubview:self.imageView]; + break; + } + case JXCategoryTitleImageType_OnlyImage: { + self.titleLabel.hidden = YES; + [self.stackView addArrangedSubview:self.imageView]; + break; + } + case JXCategoryTitleImageType_OnlyTitle: { + self.imageView.hidden = YES; + [self.stackView addArrangedSubview:self.titleLabel]; + break; + } + } + + //因为`- (void)reloadData:(JXCategoryBaseCellModel *)cellModel`方法会回调多次,尤其是左右滚动的时候会调用无数次,如果每次都触发图片加载,会非常消耗性能。所以只会在图片发生了变化的时候,才进行图片加载。 + if (myCellModel.loadImageBlock != nil) { + id currentImageInfo = myCellModel.imageInfo; + if (myCellModel.isSelected) { + currentImageInfo = myCellModel.selectedImageInfo; + } + if (currentImageInfo && ![currentImageInfo isEqual:self.currentImageInfo]) { + self.currentImageInfo = currentImageInfo; + if (myCellModel.loadImageBlock) { + myCellModel.loadImageBlock(self.imageView, currentImageInfo); + } + } + }else { + NSString *currentImageName; + NSURL *currentImageURL; + if (myCellModel.imageName) { + currentImageName = myCellModel.imageName; + } else if (myCellModel.imageURL) { + currentImageURL = myCellModel.imageURL; + } + if (myCellModel.isSelected) { + if (myCellModel.selectedImageName) { + currentImageName = myCellModel.selectedImageName; + } else if (myCellModel.selectedImageURL) { + currentImageURL = myCellModel.selectedImageURL; + } + } + if (currentImageName && ![currentImageName isEqualToString:self.currentImageName]) { + self.currentImageName = currentImageName; + self.imageView.image = [UIImage imageNamed:currentImageName]; + } else if (currentImageURL && ![currentImageURL.absoluteString isEqualToString:self.currentImageURL.absoluteString]) { + self.currentImageURL = currentImageURL; + if (myCellModel.loadImageCallback) { + myCellModel.loadImageCallback(self.imageView, currentImageURL); + } + } + } + + if (myCellModel.isImageZoomEnabled) { + self.imageView.transform = CGAffineTransformMakeScale(myCellModel.imageZoomScale, myCellModel.imageZoomScale); + } else { + self.imageView.transform = CGAffineTransformIdentity; + } +} + +@end diff --git a/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCellModel.h b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCellModel.h new file mode 100644 index 0000000..bd0111a --- /dev/null +++ b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCellModel.h @@ -0,0 +1,43 @@ +// +// JXCategoryTitleImageCellModel.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/8. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCellModel.h" + +typedef NS_ENUM(NSUInteger, JXCategoryTitleImageType) { + JXCategoryTitleImageType_TopImage = 0, + JXCategoryTitleImageType_LeftImage, + JXCategoryTitleImageType_BottomImage, + JXCategoryTitleImageType_RightImage, + JXCategoryTitleImageType_OnlyImage, + JXCategoryTitleImageType_OnlyTitle, +}; + +@interface JXCategoryTitleImageCellModel : JXCategoryTitleCellModel + +@property (nonatomic, assign) JXCategoryTitleImageType imageType; + +@property (nonatomic, strong) id imageInfo; +@property (nonatomic, strong) id selectedImageInfo; +@property (nonatomic, copy) void(^loadImageBlock)(UIImageView *imageView, id info); + +@property (nonatomic, assign) CGSize imageSize; //默认CGSizeMake(20, 20) + +@property (nonatomic, assign) CGFloat titleImageSpacing; //titleLabel和ImageView的间距,默认5 + +@property (nonatomic, assign, getter=isImageZoomEnabled) BOOL imageZoomEnabled; + +@property (nonatomic, assign) CGFloat imageZoomScale; + +/// 以下属性将会被弃用 +@property (nonatomic, copy) NSString *imageName; //加载bundle内的图片 +@property (nonatomic, strong) NSURL *imageURL; //图片URL +@property (nonatomic, copy) NSString *selectedImageName; +@property (nonatomic, strong) NSURL *selectedImageURL; +@property (nonatomic, copy) void(^loadImageCallback)(UIImageView *imageView, NSURL *imageURL); + +@end diff --git a/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCellModel.m b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCellModel.m new file mode 100644 index 0000000..ecf3539 --- /dev/null +++ b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageCellModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryTitleImageCellModel.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/8. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleImageCellModel.h" + +@implementation JXCategoryTitleImageCellModel + +@end diff --git a/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageView.h b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageView.h new file mode 100644 index 0000000..9a48f43 --- /dev/null +++ b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageView.h @@ -0,0 +1,42 @@ +// +// JXCategoryTitleImageView.h +// JXCategoryView +// +// Created by jiaxin on 2018/8/8. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleView.h" +#import "JXCategoryTitleImageCell.h" +#import "JXCategoryTitleImageCellModel.h" + +@interface JXCategoryTitleImageView : JXCategoryTitleView + +//imageInfo数组可以传入imageName字符串或者image的URL地址等,然后会通过loadImageBlock透传回来,把imageView对于图片的加载过程完全交给使用者决定。 +@property (nonatomic, strong) NSArray *imageInfoArray; +@property (nonatomic, strong) NSArray *selectedImageInfoArray; +@property (nonatomic, copy) void(^loadImageBlock)(UIImageView *imageView, id info); +//图片尺寸。默认CGSizeMake(20, 20) +@property (nonatomic, assign) CGSize imageSize; +//titleLabel和ImageView的间距,默认5 +@property (nonatomic, assign) CGFloat titleImageSpacing; +//图片是否缩放。默认为NO +@property (nonatomic, assign, getter=isImageZoomEnabled) BOOL imageZoomEnabled; +//图片缩放的最大scale。默认1.2,imageZoomEnabled为YES才生效 +@property (nonatomic, assign) CGFloat imageZoomScale; +//默认@[JXCategoryTitleImageType_LeftImage...] +@property (nonatomic, strong) NSArray *imageTypes; + +//下面的属性将会被弃用,请使用`imageInfoArray`、`selectedImageInfoArray`、`loadImageBlock`属性完成需求。 +//普通状态下的imageNames,通过[UIImage imageNamed:]方法加载 +@property (nonatomic, strong) NSArray *imageNames; +//选中状态下的imageNames,通过[UIImage imageNamed:]方法加载。可选 +@property (nonatomic, strong) NSArray *selectedImageNames; +//普通状态下的imageURLs,通过loadImageCallback回调加载 +@property (nonatomic, strong) NSArray *imageURLs; +//选中状态下的selectedImageURLs,通过loadImageCallback回调加载 +@property (nonatomic, strong) NSArray *selectedImageURLs; +//使用imageURL从远端下载图片进行加载,建议使用SDWebImage等第三方库进行下载。 +@property (nonatomic, copy) void(^loadImageCallback)(UIImageView *imageView, NSURL *imageURL); + +@end diff --git a/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageView.m b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageView.m new file mode 100644 index 0000000..ad2f560 --- /dev/null +++ b/Pods/JXCategoryView/Sources/TitleImage/JXCategoryTitleImageView.m @@ -0,0 +1,126 @@ +// +// JXCategoryTitleImageView.m +// JXCategoryView +// +// Created by jiaxin on 2018/8/8. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleImageView.h" +#import "JXCategoryTitleImageCell.h" +#import "JXCategoryTitleImageCellModel.h" +#import "JXCategoryFactory.h" + +@implementation JXCategoryTitleImageView + +- (void)dealloc { + self.loadImageBlock = nil; + self.loadImageCallback = nil; +} + +- (void)initializeData { + [super initializeData]; + + _imageSize = CGSizeMake(20, 20); + _titleImageSpacing = 5; + _imageZoomEnabled = NO; + _imageZoomScale = 1.2; +} + +- (Class)preferredCellClass { + return [JXCategoryTitleImageCell class]; +} + +- (void)refreshDataSource { + NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:self.titles.count]; + for (int i = 0; i < self.titles.count; i++) { + JXCategoryTitleImageCellModel *cellModel = [[JXCategoryTitleImageCellModel alloc] init]; + [tempArray addObject:cellModel]; + } + self.dataSource = [NSArray arrayWithArray:tempArray]; + + if (!self.imageTypes || (self.imageTypes.count == 0)) { + NSMutableArray *types = [NSMutableArray arrayWithCapacity:self.titles.count]; + for (int i = 0; i< self.titles.count; i++) { + [types addObject:@(JXCategoryTitleImageType_LeftImage)]; + } + self.imageTypes = [NSArray arrayWithArray:types]; + } +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + [super refreshCellModel:cellModel index:index]; + + JXCategoryTitleImageCellModel *myCellModel = (JXCategoryTitleImageCellModel *)cellModel; + myCellModel.loadImageBlock = self.loadImageBlock; + myCellModel.loadImageCallback = self.loadImageCallback; + myCellModel.imageType = [self.imageTypes[index] integerValue]; + myCellModel.imageSize = self.imageSize; + myCellModel.titleImageSpacing = self.titleImageSpacing; + if (self.imageInfoArray && self.imageInfoArray.count != 0) { + myCellModel.imageInfo = self.imageInfoArray[index]; + }else if (self.imageNames && self.imageNames.count != 0) { + myCellModel.imageName = self.imageNames[index]; + }else if (self.imageURLs && self.imageURLs.count != 0) { + myCellModel.imageURL = self.imageURLs[index]; + } + if (self.selectedImageInfoArray && self.selectedImageInfoArray.count != 0) { + myCellModel.selectedImageInfo = self.selectedImageInfoArray[index]; + }else if (self.selectedImageNames && self.selectedImageNames.count != 0) { + myCellModel.selectedImageName = self.selectedImageNames[index]; + }else if (self.selectedImageURLs && self.selectedImageURLs.count != 0) { + myCellModel.selectedImageURL = self.selectedImageURLs[index]; + } + myCellModel.imageZoomEnabled = self.imageZoomEnabled; + myCellModel.imageZoomScale = ((index == self.selectedIndex) ? self.imageZoomScale : 1.0); +} + +- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel { + [super refreshSelectedCellModel:selectedCellModel unselectedCellModel:unselectedCellModel]; + + JXCategoryTitleImageCellModel *myUnselectedCellModel = (JXCategoryTitleImageCellModel *)unselectedCellModel; + myUnselectedCellModel.imageZoomScale = 1.0; + + JXCategoryTitleImageCellModel *myselectedCellModel = (JXCategoryTitleImageCellModel *)selectedCellModel; + myselectedCellModel.imageZoomScale = self.imageZoomScale; +} + +- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratio { + [super refreshLeftCellModel:leftCellModel rightCellModel:rightCellModel ratio:ratio]; + + JXCategoryTitleImageCellModel *leftModel = (JXCategoryTitleImageCellModel *)leftCellModel; + JXCategoryTitleImageCellModel *rightModel = (JXCategoryTitleImageCellModel *)rightCellModel; + + if (self.isImageZoomEnabled) { + leftModel.imageZoomScale = [JXCategoryFactory interpolationFrom:self.imageZoomScale to:1.0 percent:ratio]; + rightModel.imageZoomScale = [JXCategoryFactory interpolationFrom:1.0 to:self.imageZoomScale percent:ratio]; + } +} + +- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index { + if (self.cellWidth == JXCategoryViewAutomaticDimension) { + CGFloat titleWidth = [super preferredCellWidthAtIndex:index]; + JXCategoryTitleImageType type = [self.imageTypes[index] integerValue]; + CGFloat cellWidth = 0; + switch (type) { + case JXCategoryTitleImageType_OnlyTitle: + cellWidth = titleWidth; + break; + case JXCategoryTitleImageType_OnlyImage: + cellWidth = self.imageSize.width; + break; + case JXCategoryTitleImageType_LeftImage: + case JXCategoryTitleImageType_RightImage: + cellWidth = titleWidth + self.titleImageSpacing + self.imageSize.width; + break; + case JXCategoryTitleImageType_TopImage: + case JXCategoryTitleImageType_BottomImage: + cellWidth = MAX(titleWidth, self.imageSize.width); + break; + } + return cellWidth; + } + return self.cellWidth; +} + +@end diff --git a/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.h b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.h new file mode 100644 index 0000000..804a6fb --- /dev/null +++ b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.h @@ -0,0 +1,17 @@ +// +// JXCategoryTitleVerticalZoomCell.h +// JXCategoryView +// +// Created by jiaxin on 2019/2/14. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCell.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface JXCategoryTitleVerticalZoomCell : JXCategoryTitleCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.m b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.m new file mode 100644 index 0000000..3d13438 --- /dev/null +++ b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.m @@ -0,0 +1,45 @@ +// +// JXCategoryTitleVerticalZoomCell.m +// JXCategoryView +// +// Created by jiaxin on 2019/2/14. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleVerticalZoomCell.h" +#import "JXCategoryTitleVerticalZoomCellModel.h" + +@implementation JXCategoryTitleVerticalZoomCell + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + + JXCategoryTitleVerticalZoomCellModel *myCellModel = (JXCategoryTitleVerticalZoomCellModel *)cellModel; + + if (myCellModel.isTitleLabelZoomEnabled) { + //先把font设置为缩放的最大值,再缩小到最小值,最后根据当前的titleLabelZoomScale值,进行缩放更新。这样就能避免transform从小到大时字体模糊 + UIFont *maxScaleFont = [UIFont fontWithDescriptor:myCellModel.titleFont.fontDescriptor size:myCellModel.titleFont.pointSize*myCellModel.maxVerticalFontScale]; + CGFloat baseScale = myCellModel.titleFont.lineHeight/maxScaleFont.lineHeight; + if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) { + JXCategoryCellSelectedAnimationBlock block = [self preferredTitleZoomAnimationBlock:myCellModel baseScale:baseScale]; + [self addSelectedAnimationBlock:block]; + } else { + self.titleLabel.font = maxScaleFont; + self.maskTitleLabel.font = maxScaleFont; + CGAffineTransform currentTransform = CGAffineTransformMakeScale(baseScale*myCellModel.titleLabelCurrentZoomScale, baseScale*myCellModel.titleLabelCurrentZoomScale); + self.titleLabel.transform = currentTransform; + self.maskTitleLabel.transform = currentTransform; + } + } else { + if (myCellModel.isSelected) { + self.titleLabel.font = myCellModel.titleSelectedFont; + self.maskTitleLabel.font = myCellModel.titleSelectedFont; + }else { + self.titleLabel.font = myCellModel.titleFont; + self.maskTitleLabel.font = myCellModel.titleFont; + } + } + + [self.titleLabel sizeToFit]; +} +@end diff --git a/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.h b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.h new file mode 100644 index 0000000..3c7ea4b --- /dev/null +++ b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.h @@ -0,0 +1,19 @@ +// +// JXCategoryTitleVerticalZoomCellModel.h +// JXCategoryView +// +// Created by jiaxin on 2019/2/14. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleCellModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface JXCategoryTitleVerticalZoomCellModel : JXCategoryTitleCellModel + +@property (nonatomic, assign) CGFloat maxVerticalFontScale; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.m b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.m new file mode 100644 index 0000000..3bf0ba0 --- /dev/null +++ b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.m @@ -0,0 +1,13 @@ +// +// JXCategoryTitleVerticalZoomCellModel.m +// JXCategoryView +// +// Created by jiaxin on 2019/2/14. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleVerticalZoomCellModel.h" + +@implementation JXCategoryTitleVerticalZoomCellModel + +@end diff --git a/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.h b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.h new file mode 100644 index 0000000..e3eb813 --- /dev/null +++ b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.h @@ -0,0 +1,34 @@ +// +// JXCategoryTitleVerticalZoomView.h +// JXCategoryView +// +// Created by jiaxin on 2019/2/14. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleView.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + 垂直方向的缩放值范围:minVerticalFontScale~maxVerticalFontScale; + 垂直方向cellSpacing范围:minVerticalCellSpacing~maxVerticalCellSpacing,用于达到缩小时cell更加紧凑 + 根据UI设计师给你的参数,去多次尝试设置上面的值来达到同样的效果。多尝试几次就知道每个属性设置之后的效果。 + */ +@interface JXCategoryTitleVerticalZoomView : JXCategoryTitleView + +@property (nonatomic, assign) CGFloat maxVerticalFontScale; //垂直方向最大的缩放值 +@property (nonatomic, assign) CGFloat minVerticalFontScale; //垂直方向最小的缩放值 +@property (nonatomic, assign) CGFloat maxVerticalCellSpacing; //垂直方向最大的cellSpacing +@property (nonatomic, assign) CGFloat minVerticalCellSpacing; //垂直方向最小的cellSpacing + +/** + 当前列表滚动时,根据当前垂直方向categoryView高度变化的百分比,刷新布局 + + @param percent 当前垂直方向categoryView高度变化百分比 + */ +- (void)listDidScrollWithVerticalHeightPercent:(CGFloat)percent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.m b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.m new file mode 100644 index 0000000..b8fe745 --- /dev/null +++ b/Pods/JXCategoryView/Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.m @@ -0,0 +1,94 @@ +// +// JXCategoryTitleVerticalZoomView.m +// JXCategoryView +// +// Created by jiaxin on 2019/2/14. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXCategoryTitleVerticalZoomView.h" +#import "JXCategoryTitleVerticalZoomCellModel.h" +#import "JXCategoryTitleVerticalZoomCell.h" +#import "JXCategoryFactory.h" + +@interface JXCategoryTitleVerticalZoomView () +@property (nonatomic, assign) CGFloat currentVerticalScale; //当前垂直方向的缩放基准值 +@end + +@implementation JXCategoryTitleVerticalZoomView + +- (void)initializeData { + [super initializeData]; + + _maxVerticalFontScale = 2; + _minVerticalFontScale = 1.3; + _currentVerticalScale = _maxVerticalFontScale; + self.cellWidthZoomEnabled = YES; + self.cellWidthZoomScale = _maxVerticalFontScale; + self.contentEdgeInsetLeft = 15; + self.titleLabelZoomScale = _currentVerticalScale; + self.titleLabelZoomEnabled = YES; + self.selectedAnimationEnabled = YES; + _maxVerticalCellSpacing = 20; + _minVerticalCellSpacing = 10; + self.cellSpacing = _maxVerticalCellSpacing; +} + +- (void)listDidScrollWithVerticalHeightPercent:(CGFloat)percent { + CGFloat currentScale = [JXCategoryFactory interpolationFrom:self.minVerticalFontScale to:self.maxVerticalFontScale percent:percent]; + BOOL shouldReloadData = NO; + if (self.currentVerticalScale != currentScale) { + //有变化才允许reloadData + shouldReloadData = YES; + } + self.currentVerticalScale = currentScale; + self.cellWidthZoomScale = currentScale; + self.cellSpacing = [JXCategoryFactory interpolationFrom:self.minVerticalCellSpacing to:self.maxVerticalCellSpacing percent:percent]; + if (shouldReloadData) { + [self refreshDataSource]; + [self refreshState]; + [self.collectionView.collectionViewLayout invalidateLayout]; + [self.collectionView reloadData]; + } +} + +- (void)setCurrentVerticalScale:(CGFloat)currentVerticalScale { + _currentVerticalScale = currentVerticalScale; + + self.titleLabelZoomScale = currentVerticalScale; +} + +- (void)setMaxVerticalCellSpacing:(CGFloat)maxVerticalCellSpacing { + _maxVerticalCellSpacing = maxVerticalCellSpacing; + + self.cellSpacing = maxVerticalCellSpacing; +} + +- (void)setMaxVerticalFontScale:(CGFloat)maxVerticalFontScale { + _maxVerticalFontScale = maxVerticalFontScale; + + self.titleLabelZoomScale = maxVerticalFontScale; + self.cellWidthZoomScale = maxVerticalFontScale; +} + +- (Class)preferredCellClass { + return [JXCategoryTitleVerticalZoomCell class]; +} + +- (void)refreshDataSource { + NSMutableArray *tempArray = [NSMutableArray array]; + for (int i = 0; i < self.titles.count; i++) { + JXCategoryTitleVerticalZoomCellModel *cellModel = [[JXCategoryTitleVerticalZoomCellModel alloc] init]; + [tempArray addObject:cellModel]; + } + self.dataSource = tempArray; +} + +- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index { + [super refreshCellModel:cellModel index:index]; + + JXCategoryTitleVerticalZoomCellModel *model = (JXCategoryTitleVerticalZoomCellModel *)cellModel; + model.maxVerticalFontScale = self.maxVerticalFontScale; +} + +@end diff --git a/Pods/JXPagingView/LICENSE b/Pods/JXPagingView/LICENSE new file mode 100644 index 0000000..0fdb1e7 --- /dev/null +++ b/Pods/JXPagingView/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 暴走的鑫鑫 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/JXPagingView/README.md b/Pods/JXPagingView/README.md new file mode 100644 index 0000000..b8f2efd --- /dev/null +++ b/Pods/JXPagingView/README.md @@ -0,0 +1,294 @@ +# JXPagingView + +类似微博主页、简书主页、QQ联系人页面等效果。多页面嵌套,既可以上下滑动,也可以左右滑动切换页面。支持HeaderView悬浮、支持下拉刷新、上拉加载更多。 + +## 功能特点 + +- 支持OC与Swift; +- 支持列表懒加载,等到列表真正显示的时候才加载,而不是一次性加载所有列表; +- 支持首页下拉刷新、列表视图下拉刷新、列表视图上拉加载更多; +- 支持悬浮SectionHeader的垂直位置调整; +- 支持从顶部用力往上滚动,下面的列表会跟着滚动,而不会突然卡主,需要使用`JXPagerSmoothView`类; +- 列表封装简洁,只要遵从`JXPagingViewListViewDelegate`协议即可。UIView、UIViewController等都可以; +- 使用JXCategoryView/JXSegmentedView分类控制器,几乎支持所有主流效果、高度自定义、可灵活扩展; +- 支持横竖屏切换; +- 支持点击状态栏滚动当前列表到顶部; +- 支持列表显示和消失的生命周期方法; +- isListHorizontalScrollEnabled属性控制列表是否可以左右滑动,默认YES; +- 支持`FDFullscreenPopGesture`等全屏手势兼容处理; + +## 预览 + +| 效果 | 预览图 | +|-------|-------| +| **头图缩放**
参考[ZoomViewController](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagerViewExample-OC/JXPagerViewExample-OC/Example/Zoom/ZoomViewController.m)类 | ![Zoom](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/Zoom.gif) | +| **主页下拉刷新&列表上拉加载更多**
参考[RefreshViewController](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagerViewExample-OC/JXPagerViewExample-OC/Example/Refresh/RefreshViewController.m)类 | ![Refresh](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/Refresh.gif) | +| **列表下拉刷新**
参考[ListRefreshViewController](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagerViewExample-OC/JXPagerViewExample-OC/Example/Refresh/ListRefreshViewController.m)类 | ![Refresh](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/ListRefresh.gif) | +| **悬浮sectionHeader位置调整** | ![Refresh](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/PinSectionHeaderPosition.gif) | +| **导航栏隐藏**
参考[NaviBarHiddenViewController](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagerViewExample-OC/JXPagerViewExample-OC/Example/NavigationBarHidden/NaviBarHiddenViewController.m)类 | ![Refresh](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/NaviHidden.gif) | +| **CollectionView列表示例**
参考[CollectionViewViewController.swift](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagingViewExample/JXPagingViewExample/Example/CollectionView/CollectionViewViewController.swift)类
只有swift的demo工程有该示例 | ![Refresh](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/CollectionViewList.gif) | +| **HeaderView更新高度示例**
参考[HeightChangeAnimationViewController.swift](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagingViewExample/JXPagingViewExample/Example/HeightChange/HeightChangeAnimationViewController.swift)类
只有swift demo工程才有该示例 | ![Refresh](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/HeaderViewHeightChange.gif) | +| **PagingView嵌套CategoryView**
参考[NestViewController](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagerViewExample-OC/JXPagerViewExample-OC/Example/Nest/NestViewController.m)类
只有 **OC!OC!OC!** 的demo工程才有该示例
操作比较特殊,如果需要此效果,
请认真参考源码,有问题多试试
参考NestViewController.h类 | ![Nest](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/Nest.gif) | +| **CategoryView嵌套PagingView**
参考[NestViewController.swift](https://github.com/pujiaxin33/JXPagingView/tree/master/Examples/JXPagingViewExample/JXPagingViewExample/Example/CategoryNestPaging/NestViewController.swift)类
只有 **Swift!Swift!Swift!** 的demo工程才有该示例
操作比较特殊,如果需要此效果,
请认真参考源码,有问题多试试
参考NestViewController.swift类 | ![Nest](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/CategoryNestPaging.gif) | +| **点击状态栏** | ![Zoom](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/StatusBarClicked.gif) | +| **横竖屏旋转** | ![Zoom](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/ScreenRotate.gif) | +| **JXPageListView**
顶部需要自定义cell的场景,类似于电商APP首页,滑动到列表最底部才是分类控制器
该效果是另一个库,点击查看[JXPageListView](https://github.com/pujiaxin33/JXPageListView)
该效果是另一个库,点击查看[JXPageListView](https://github.com/pujiaxin33/JXPageListView)
该效果是另一个库,点击查看[JXPageListView](https://github.com/pujiaxin33/JXPageListView) | ![list](https://github.com/pujiaxin33/JXPageListView/blob/master/JXPageListView/Gif/headerLoading.gif) | +| **JXPagerSmoothView**
类似淘宝、转转首页
从顶部用力往上滚动,下面的列表会继续滚动 | ![smooth](https://github.com/pujiaxin33/JXExampleImages/blob/master/JXPaingView/smooth.gif) | + +## 安装 + +### 手动 + +**Swift版本:** Clone代码,拖入JXPagingView-Swift文件夹,使用`JXPagingView`类; + +**OC版本:** Clone代码,拖入JXPagerView文件夹,使用`JXPagerView`类; + +### CocoaPods + +- **Swift版本** + +支持swift版本:5.0+ + +```ruby +target '' do + pod 'JXPagingView/Paging' +end +``` + +- **OC版本** +```ruby +target '' do + pod 'JXPagingView/Pager' +end +``` + +Swift与OC的仓库地址不一样,请注意选择! + +先`pod repo update`然后再`pod install` + + +## 使用 + +swift版本使用类似,只是类名及相关API更改为`JXPagingView`,具体细节请查看Swfit工程。 + +### 1、初始化`JXCategoryTitleView`和`JXPagerView` + +```Objective-C +self.categoryView = [[JXCategoryTitleView alloc] initWithFrame:frame]; +//配置categoryView,细节参考源码 + +self.pagerView = [[JXPagerView alloc] initWithDelegate:self]; +[self.view addSubview:self.pagerView]; + +//⚠️⚠️⚠️将pagerView的listContainerView和categoryView.listContainer进行关联,这样列表就可以和categoryView联动了。⚠️⚠️⚠️ +self.categoryView.listContainer = (id)self.pagerView.listContainerView; +``` + +**Swift版本列表关联代码** +```Swift +//给JXPagingListContainerView添加extension,表示遵从JXSegmentedViewListContainer的协议 +extension JXPagingListContainerView: JXSegmentedViewListContainer {} +//⚠️⚠️⚠️将pagingView的listContainerView和segmentedView.listContainer进行关联,这样列表就可以和categoryView联动了。⚠️⚠️⚠️ +segmentedView.listContainer = pagingView.listContainerView +``` + +### 2、实现`JXPagerViewDelegate`协议 + +```Objective-C +/** + 返回tableHeaderView的高度,因为内部需要比对判断,只能是整型数 + */ +- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView { + return JXTableHeaderViewHeight; +} + +/** + 返回tableHeaderView + */ +- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView { + return self.userHeaderView; +} + + +/** + 返回悬浮HeaderView的高度,因为内部需要比对判断,只能是整型数 + */ +- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { + return JXheightForHeaderInSection; +} + + +/** + 返回悬浮HeaderView + */ +- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { + return self.categoryView; +} + +/** + 返回列表的数量 + */ +- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView { + //和categoryView的item数量一致 + return self.titles.count; +} + +/** + 根据index初始化一个对应列表实例。注意:一定要是新生成的实例!!! + 只要遵循JXPagerViewListViewDelegate即可,无论你返回的是UIView还是UIViewController都可以。 + */ +- (id)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index { + TestListBaseView *listView = [[TestListBaseView alloc] init]; + if (index == 0) { + listView.dataSource = @[@"橡胶火箭", @"橡胶火箭炮", @"橡胶机关枪"...].mutableCopy; + }else if (index == 1) { + listView.dataSource = @[@"吃烤肉", @"吃鸡腿肉", @"吃牛肉", @"各种肉"].mutableCopy; + }else { + listView.dataSource = @[@"【剑士】罗罗诺亚·索隆", @"【航海士】娜美", @"【狙击手】乌索普"...].mutableCopy; + } + [listView beginFirstRefresh]; + return listView; +} +``` + +### 3、实现`JXPagerViewListViewDelegate`协议 + +列表可以是任意类,UIView、UIViewController等等都可以,只要实现了`JXPagerViewListViewDelegate`协议就行。 + +⚠️⚠️⚠️一定要保证`scrollCallback`的正确回调,许多朋友都容易疏忽这一点,导致异常,务必重点注意! + +下面的使用代码参考的是`TestListBaseView`类 + +```Objective-C +/** + 返回listView。如果是vc包裹的就是vc.view;如果是自定义view包裹的,就是自定义view自己。 + */ +- (UIView *)listView { + return self; +} + +/** + 返回listView内部持有的UIScrollView或UITableView或UICollectionView + 主要用于mainTableView已经显示了header,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView + */ +- (UIScrollView *)listScrollView { + return self.tableView; +} + + +/** + 当listView内部持有的UIScrollView或UITableView或UICollectionView的代理方法`scrollViewDidScroll`回调时,需要调用该代理方法传入的callback + */ +- (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback { + self.scrollCallback = callback; +} +``` + +### 4、列表回调处理 + +`TestListBaseView`在其`tableView`的滚动回调中,通过调用上面持有的scrollCallback,把列表的滚动事件回调给JXPagerView内部。 +```Objective-C +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + !self.scrollCallback ?: self.scrollCallback(scrollView); +} +``` + +## 实现原理 + +[实现原理](https://github.com/pujiaxin33/JXPagingView/blob/master/Document/JXPagingView%E5%8E%9F%E7%90%86.md) + +## `JXPagerSmoothView` + +如果你需要类似于**淘宝**、**转转**首页从顶部header用力往上滚动之后,下面的列表会跟着滚动的效果。因为`JXPagerView`的实现原理限制,当用户从顶部header的位置用力往上滚动,`JXPagerView`会在`JXCategoryView`刚好在顶部的时候突然停住。这个时候就需要使用`JXPagerSmoothView`,swift版本叫`JXPagingSmoothView`。 + +因为与`JXPagerView`的原理完全不同,所以各自会有一些特性的区别,但是从使用体验来说,是完全一致的。具体使用细节请参考demo示例。 + +实现原理参考[JXPagerSmoothView文章解析](https://juejin.im/post/5ddb2fe4f265da7def5424c7) + + +## 特殊说明 + +### JXCategoryView、JXSegmentedView +悬浮的HeaderView,用的是我写的:[OC版本-JXCategoryView](https://github.com/pujiaxin33/JXCategoryView) 、[Swift版本-JXSegmentedView](https://github.com/pujiaxin33/JXSegmentedView)。几乎实现了所有主流效果,而且非常容易自定义扩展,强烈推荐阅读。 + + +### 头图缩放说明 +头图缩放原理,参考这个库:[JXTableViewZoomHeaderImageView](https://github.com/pujiaxin33/JXTableViewZoomHeaderImageView) + +### 列表下拉刷新说明 + +需要使用`JXPagerListRefreshView`类(是`JXPagerView`的子类) + +### JXPagerListContainerType说明 + +UIScrollView:优势:没有其他副作用。劣势:实时的视图内存占用相对大一点,因为所有加载之后的列表视图都在视图层级里面。 +UICollectionView:优势:因为列表被添加到cell上,实时的视图内存占用更少,适合内存要求特别高的场景。劣势:因为cell重用机制的问题,导致列表被移除屏幕外之后,会被放入缓存区,而不存在于视图层级中。如果刚好你的列表使用了下拉刷新视图,在快速切换过程中,就会导致下拉刷新回调不成功的问题。(使用MJRefresh会出现此问题)一句话概括:使用CollectionView的时候,就不要让列表使用下拉刷新加载。 + +### 关于下方列表视图的代理方法`- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath`有时候需要点击两次才回调 + +出现步骤:当手指放在下方列表视图往下拉,直到TableHeaderView完全显示。 + +原因:经过上面的步骤之后,手指已经离开屏幕且列表视图已经完全静止,UIScrollView的isDragging属性却依然是true。就导致了后续的第一次点击,让系统认为当前UIScrollView依然在滚动,该点击就让UIScrollView停止下来,没有继续转发给UITableView,就没有转化成didSelectRow事件。 + +解决方案:经过N种尝试之后,还是没有回避掉系统的`isDragging`异常为true的bug。大家可以在自定义cell最下方放置一个与cell同大小的button,把button的touchUpInside事件当做`didSelectRow`的回调。因为UIButton在响应链中的优先级要高于UIGestureRecognizer。 + +代码:请参考`TestTableViewCell`类的配置。 + +### 指定默认选中index + +默认显示index=2的列表,代码如下: +``` +self.pagerView.defaultSelectedIndex = 2; +self.categoryView.defaultSelectedIndex = 2; +``` + +### 顶部轮播图手势处理 + +如果TableHeaderView添加了轮播图,获取其他可以横向滚动的UIScrollView。如果不处理,就会出现左右滚动轮播图的时候又可以触发整个页面的上下滚动。为了规避该问题,请参考示例仓库中`BannerViewController`类的处理方法。即可同一时间只允许左右滚动或者上下滚动。 + +### 关于列表用UIViewController封装且要支持横竖屏的tips + +在列表UIViewController类里面一定要加上下面这段代码:(不要问我为什么,我也不知道,谁知道系统内部是怎么操作的,反正加上就没毛病了) +``` +- (void)loadView { + self.view = [[UIView alloc] init]; +} +``` + +### `JXPagerSmoothView` header有UITextField或者`UITextView` +详情参考OC版本示例【滚动延续 Header有输入框】 + +列表自定义子类化`UITableView`或者`UICollectionView`,然后重载`scrollRectToVisible`方法,示例代码如下。 +```Object-C +@implementation TestTableView +- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated { + [self setContentOffset:CGPointMake(self.contentOffset.x, rect.origin.y) animated:animated]; +} +@end +``` + +### `FDFullscreenPopGesture`等全屏手势兼容处理 + +[全屏手势兼容处理文档,点击查看 ❗️❗️❗️](https://github.com/pujiaxin33/JXPagingView/blob/master/Document/%E5%85%A8%E5%B1%8F%E6%89%8B%E5%8A%BF%E5%A4%84%E7%90%86.md) + + +## 迁移指南 +- **0.0.9版本**:将下面两个API的返回值修改为了NSUInteger(swift版本为Int),之前版本是CGFloat,升级为0.0.9及以上的时候,记得修改一下使用地方的返回值类型,不然会引起crash。 + - `- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView` + - `- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView` +- **1.0.0版本**: + 删除代理方法`- (NSArray > *)listViewsInPagerView:(JXPagerView *)pagerView;`,请参考示例使用下面两个代理方法: + - `- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView;` + - `- (id)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index;` +- **2.0.0版本**:`JXPagerListContainerView`进行了重构,列表拥有了完整的生命周期方法。列表是`UIViewController`类,`viewWillAppear`等生命周期方法将会正确触发。 +- + - 删除了collectionView,用`scrollView`属性替换。 + - 和`CategoryView`的联动绑定代码更新为`self.categoryView.listContainer = (id)self.pagerView.listContainerView;`。 + - `JXPagerView`新增`- (instancetype)initWithDelegate:(id)delegate listContainerType:(JXPagerListContainerType)type`初始化方法,可以指定列表容器为`UIScrollView`或者`UICollectionView`; + + +## 补充 + +有不明白的地方,建议多看下源码。再有疑问的,欢迎提Issue交流🤝 + + diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerListContainerView.h b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListContainerView.h new file mode 100644 index 0000000..6287361 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListContainerView.h @@ -0,0 +1,128 @@ +// +// JXCategoryListScrollView.h +// JXCategoryView +// +// Created by jiaxin on 2018/9/12. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +@class JXPagerListContainerView; +@class JXPagerListContainerScrollView; + +@protocol JXPagerViewListViewDelegate + +/** + 返回listView。如果是vc包裹的就是vc.view;如果是自定义view包裹的,就是自定义view自己。 + + @return UIView + */ +- (UIView *)listView; + +/** + 返回listView内部持有的UIScrollView或UITableView或UICollectionView + 主要用于mainTableView已经显示了header,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView + + @return listView内部持有的UIScrollView或UITableView或UICollectionView + */ +- (UIScrollView *)listScrollView; + +/** + 当listView内部持有的UIScrollView或UITableView或UICollectionView的代理方法`scrollViewDidScroll`回调时,需要调用该代理方法传入的callback + + @param callback `scrollViewDidScroll`回调时调用的callback + */ +- (void)listViewDidScrollCallback:(void (^)(UIScrollView *scrollView))callback; + +@optional + +- (void)listScrollViewWillResetContentOffset; +- (void)listWillAppear; +- (void)listDidAppear; +- (void)listWillDisappear; +- (void)listDidDisappear; + +@end + +/** + 列表容器视图的类型 + + - ScrollView: UIScrollView。优势:没有其他副作用。劣势:实时的视图内存占用相对大一点,因为所有加载之后的列表视图都在视图层级里面。 + - CollectionView: 使用UICollectionView。优势:因为列表被添加到cell上,实时的视图内存占用更少,适合内存要求特别高的场景。劣势:因为cell重用机制的问题,导致列表被移除屏幕外之后,会被放入缓存区,而不存在于视图层级中。如果刚好你的列表使用了下拉刷新视图,在快速切换过程中,就会导致下拉刷新回调不成功的问题。一句话概括:使用CollectionView的时候,就不要让列表使用下拉刷新加载。 + */ +typedef NS_ENUM(NSUInteger, JXPagerListContainerType) { + JXPagerListContainerType_ScrollView, + JXPagerListContainerType_CollectionView, +}; + +@protocol JXPagerListContainerViewDelegate +/** + 返回list的数量 + + @param listContainerView 列表的容器视图 + @return list的数量 + */ +- (NSInteger)numberOfListsInlistContainerView:(JXPagerListContainerView *)listContainerView; + +/** + 根据index返回一个对应列表实例,需要是遵从`JXPagerViewListViewDelegate`协议的对象。 + 你可以代理方法调用的时候初始化对应列表,达到懒加载的效果。这也是默认推荐的初始化列表方法。你也可以提前创建好列表,等该代理方法回调的时候再返回也可以,达到预加载的效果。 + 如果列表是用自定义UIView封装的,就让自定义UIView遵从`JXPagerViewListViewDelegate`协议,该方法返回自定义UIView即可。 + 如果列表是用自定义UIViewController封装的,就让自定义UIViewController遵从`JXPagerViewListViewDelegate`协议,该方法返回自定义UIViewController即可。 + + @param listContainerView 列表的容器视图 + @param index 目标下标 + @return 遵从JXPagerViewListViewDelegate协议的list实例 + */ +- (id)listContainerView:(JXPagerListContainerView *)listContainerView initListForIndex:(NSInteger)index; + +@optional +/** + 返回自定义UIScrollView或UICollectionView的Class + 某些特殊情况需要自己处理UIScrollView内部逻辑。比如项目用了FDFullscreenPopGesture,需要处理手势相关代理。 + + @param listContainerView JXPagerListContainerView + @return 自定义UIScrollView实例 + */ +- (Class)scrollViewClassInlistContainerView:(JXPagerListContainerView *)listContainerView; + +/** + 控制能否初始化对应index的列表。有些业务需求,需要在某些情况才允许初始化某些列表,通过通过该代理实现控制。 + */ +- (BOOL)listContainerView:(JXPagerListContainerView *)listContainerView canInitListAtIndex:(NSInteger)index; +- (void)listContainerViewDidScroll:(UIScrollView *)scrollView; +- (void)listContainerViewWillBeginDragging:(JXPagerListContainerView *)listContainerView; +- (void)listContainerViewWDidEndScroll:(JXPagerListContainerView *)listContainerView; +- (void)listContainerView:(JXPagerListContainerView *)listContainerView listDidAppearAtIndex:(NSInteger)index; + +@end + +@interface JXPagerListContainerView : UIView + +@property (nonatomic, assign, readonly) JXPagerListContainerType containerType; +@property (nonatomic, strong, readonly) UIScrollView *scrollView; +@property (nonatomic, strong, readonly) NSDictionary > *validListDict; //已经加载过的列表字典。key是index,value是对应的列表 +@property (nonatomic, strong) UIColor *listCellBackgroundColor; //默认:[UIColor whiteColor] +/** + 滚动切换的时候,滚动距离超过一页的多少百分比,就触发列表的初始化。默认0.01(即列表显示了一点就触发加载)。范围0~1,开区间不包括0和1 + */ +@property (nonatomic, assign) CGFloat initListPercent; +///当使用Category嵌套Paging的时候,需要设置为YES,默认为NO; +@property (nonatomic, assign, getter=isCategoryNestPagingEnabled) BOOL categoryNestPagingEnabled; +@property (nonatomic, assign, readonly) NSInteger currentIndex; + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithType:(JXPagerListContainerType)type delegate:(id)delegate NS_DESIGNATED_INITIALIZER; + +@end + +@interface JXPagerListContainerView (ListContainer) +- (void)setDefaultSelectedIndex:(NSInteger)index; +- (UIScrollView *)contentScrollView; +- (void)reloadData; +- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex; +- (void)didClickSelectedItemAtIndex:(NSInteger)index; +@end + diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerListContainerView.m b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListContainerView.m new file mode 100644 index 0000000..14358b7 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListContainerView.m @@ -0,0 +1,597 @@ +// +// JXPagerListContainerView.m +// JXCategoryView +// +// Created by jiaxin on 2018/9/12. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXPagerListContainerView.h" +#import + +@interface JXPagerListContainerScrollView: UIScrollView +@property (nonatomic, assign, getter=isCategoryNestPagingEnabled) BOOL categoryNestPagingEnabled; +@end +@implementation JXPagerListContainerScrollView +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + if (self.isCategoryNestPagingEnabled) { + if ([gestureRecognizer isMemberOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")]) { + CGFloat velocityX = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:gestureRecognizer.view].x; + //x大于0就是往右滑 + if (velocityX > 0) { + if (self.contentOffset.x == 0) { + return NO; + } + }else if (velocityX < 0) { + //x小于0就是往左滑 + if (self.contentOffset.x + self.bounds.size.width == self.contentSize.width) { + return NO; + } + } + } + } + return YES; +} +@end + +@interface JXPagerListContainerCollectionView: UICollectionView +@property (nonatomic, assign, getter=isCategoryNestPagingEnabled) BOOL categoryNestPagingEnabled; +@end +@implementation JXPagerListContainerCollectionView +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + if (self.isCategoryNestPagingEnabled) { + if ([gestureRecognizer isMemberOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")]) { + CGFloat velocityX = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:gestureRecognizer.view].x; + //x大于0就是往右滑 + if (velocityX > 0) { + if (self.contentOffset.x == 0) { + return NO; + } + }else if (velocityX < 0) { + //x小于0就是往左滑 + if (self.contentOffset.x + self.bounds.size.width == self.contentSize.width) { + return NO; + } + } + } + } + return YES; +} +@end + +@interface JXPagerListContainerViewController : UIViewController +@property (copy) void(^viewWillAppearBlock)(void); +@property (copy) void(^viewDidAppearBlock)(void); +@property (copy) void(^viewWillDisappearBlock)(void); +@property (copy) void(^viewDidDisappearBlock)(void); +@end + +@implementation JXPagerListContainerViewController +- (void)dealloc +{ + self.viewWillAppearBlock = nil; + self.viewDidAppearBlock = nil; + self.viewWillDisappearBlock = nil; + self.viewDidDisappearBlock = nil; +} +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + self.viewWillAppearBlock(); +} +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + self.viewDidAppearBlock(); +} +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + self.viewWillDisappearBlock(); +} +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + self.viewDidDisappearBlock(); +} +- (BOOL)shouldAutomaticallyForwardAppearanceMethods { return NO; } +@end + +@interface JXPagerListContainerView () +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, assign) NSInteger currentIndex; +@property (nonatomic, strong) NSMutableDictionary > *validListDict; +@property (nonatomic, assign) NSInteger willAppearIndex; +@property (nonatomic, assign) NSInteger willDisappearIndex; +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) JXPagerListContainerViewController *containerVC; +@end + +@implementation JXPagerListContainerView + +- (instancetype)initWithType:(JXPagerListContainerType)type delegate:(id)delegate{ + self = [super initWithFrame:CGRectZero]; + if (self) { + _containerType = type; + _delegate = delegate; + _validListDict = [NSMutableDictionary dictionary]; + _willAppearIndex = -1; + _willDisappearIndex = -1; + _initListPercent = 0.01; + [self initializeViews]; + } + return self; +} + +- (void)initializeViews { + _listCellBackgroundColor = [UIColor whiteColor]; + _containerVC = [[JXPagerListContainerViewController alloc] init]; + self.containerVC.view.backgroundColor = [UIColor clearColor]; + [self addSubview:self.containerVC.view]; + __weak typeof(self) weakSelf = self; + self.containerVC.viewWillAppearBlock = ^{ + [weakSelf listWillAppear:weakSelf.currentIndex]; + }; + self.containerVC.viewDidAppearBlock = ^{ + [weakSelf listDidAppear:weakSelf.currentIndex]; + }; + self.containerVC.viewWillDisappearBlock = ^{ + [weakSelf listWillDisappear:weakSelf.currentIndex]; + }; + self.containerVC.viewDidDisappearBlock = ^{ + [weakSelf listDidDisappear:weakSelf.currentIndex]; + }; + if (self.containerType == JXPagerListContainerType_ScrollView) { + if (self.delegate && + [self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerView:)] && + [[self.delegate scrollViewClassInlistContainerView:self] isKindOfClass:object_getClass([UIScrollView class])]) { + _scrollView = (UIScrollView *)[[[self.delegate scrollViewClassInlistContainerView:self] alloc] init]; + }else { + _scrollView = [[JXPagerListContainerScrollView alloc] init]; + } + self.scrollView.backgroundColor = [UIColor clearColor]; + self.scrollView.delegate = self; + self.scrollView.pagingEnabled = YES; + self.scrollView.showsHorizontalScrollIndicator = NO; + self.scrollView.showsVerticalScrollIndicator = NO; + self.scrollView.scrollsToTop = NO; + self.scrollView.bounces = NO; + if (@available(iOS 11.0, *)) { + self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [self.containerVC.view addSubview:self.scrollView]; + }else { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + layout.minimumLineSpacing = 0; + layout.minimumInteritemSpacing = 0; + if (self.delegate && + [self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerView:)] && + [[self.delegate scrollViewClassInlistContainerView:self] isKindOfClass:object_getClass([UICollectionView class])]) { + _collectionView = (UICollectionView *)[[[self.delegate scrollViewClassInlistContainerView:self] alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + }else { + _collectionView = [[JXPagerListContainerCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + } + self.collectionView.backgroundColor = [UIColor clearColor]; + self.collectionView.pagingEnabled = YES; + self.collectionView.showsHorizontalScrollIndicator = NO; + self.collectionView.showsVerticalScrollIndicator = NO; + self.collectionView.scrollsToTop = NO; + self.collectionView.bounces = NO; + self.collectionView.dataSource = self; + self.collectionView.delegate = self; + [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; + if (@available(iOS 10.0, *)) { + self.collectionView.prefetchingEnabled = NO; + } + if (@available(iOS 11.0, *)) { + self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [self.containerVC.view addSubview:self.collectionView]; + //让外部统一访问scrollView + _scrollView = _collectionView; + } +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + + UIResponder *next = newSuperview; + while (next != nil) { + if ([next isKindOfClass:[UIViewController class]]) { + [((UIViewController *)next) addChildViewController:self.containerVC]; + break; + } + next = next.nextResponder; + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + self.containerVC.view.frame = self.bounds; + if (self.containerType == JXPagerListContainerType_ScrollView) { + if (CGRectEqualToRect(self.scrollView.frame, CGRectZero) || !CGSizeEqualToSize(self.scrollView.bounds.size, self.bounds.size)) { + self.scrollView.frame = self.bounds; + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height); + [_validListDict enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull index, id _Nonnull list, BOOL * _Nonnull stop) { + [list listView].frame = CGRectMake(index.intValue*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); + }]; + self.scrollView.contentOffset = CGPointMake(self.currentIndex*self.scrollView.bounds.size.width, 0); + }else { + self.scrollView.frame = self.bounds; + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height); + } + }else { + if (CGRectEqualToRect(self.collectionView.frame, CGRectZero) || !CGSizeEqualToSize(self.collectionView.bounds.size, self.bounds.size)) { + self.collectionView.frame = self.bounds; + [self.collectionView.collectionViewLayout invalidateLayout]; + [self.collectionView reloadData]; + [self.collectionView setContentOffset:CGPointMake(self.collectionView.bounds.size.width*self.currentIndex, 0) animated:NO]; + }else { + self.collectionView.frame = self.bounds; + } + } +} + + +- (void)setinitListPercent:(CGFloat)initListPercent { + _initListPercent = initListPercent; + if (initListPercent <= 0 || initListPercent >= 1) { + NSAssert(NO, @"initListPercent值范围为开区间(0,1),即不包括0和1"); + } +} + +- (void)setCategoryNestPagingEnabled:(BOOL)categoryNestPagingEnabled { + _categoryNestPagingEnabled = categoryNestPagingEnabled; + if ([self.scrollView isKindOfClass:[JXPagerListContainerScrollView class]]) { + ((JXPagerListContainerScrollView *)self.scrollView).categoryNestPagingEnabled = categoryNestPagingEnabled; + }else if ([self.scrollView isKindOfClass:[JXPagerListContainerCollectionView class]]) { + ((JXPagerListContainerCollectionView *)self.scrollView).categoryNestPagingEnabled = categoryNestPagingEnabled; + } +} + +#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return [self.delegate numberOfListsInlistContainerView:self]; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; + cell.contentView.backgroundColor = self.listCellBackgroundColor; + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + id list = _validListDict[@(indexPath.item)]; + if (list != nil) { + //fixme:如果list是UIViewController,如果这里的frame修改是`[list listView].frame = cell.bounds;`。那么就必须给list vc添加如下代码: + //- (void)loadView { + // self.view = [[UIView alloc] init]; + //} + //所以,总感觉是把UIViewController当做普通view使用,导致了系统内部的bug。所以,缓兵之计就是用下面的方法,暂时解决问题。 + if ([list isKindOfClass:[UIViewController class]]) { + [list listView].frame = cell.contentView.bounds; + } else { + [list listView].frame = cell.bounds; + } + [cell.contentView addSubview:[list listView]]; + } + return cell; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return self.bounds.size; +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewDidScroll:)]) { + [self.delegate listContainerViewDidScroll:scrollView]; + } + if (!scrollView.isDragging && !scrollView.isTracking && !scrollView.isDecelerating) { + return; + } + CGFloat ratio = scrollView.contentOffset.x/scrollView.bounds.size.width; + NSInteger maxCount = round(scrollView.contentSize.width/scrollView.bounds.size.width); + NSInteger leftIndex = floorf(ratio); + leftIndex = MAX(0, MIN(maxCount - 1, leftIndex)); + NSInteger rightIndex = leftIndex + 1; + if (ratio < 0 || rightIndex >= maxCount) { + [self listDidAppearOrDisappear:scrollView]; + return; + } + CGFloat remainderRatio = ratio - leftIndex; + if (rightIndex == self.currentIndex) { + //当前选中的在右边,用户正在从右边往左边滑动 + if (self.validListDict[@(leftIndex)] == nil && remainderRatio < (1 - self.initListPercent)) { + [self initListIfNeededAtIndex:leftIndex]; + }else if (self.validListDict[@(leftIndex)] != nil) { + if (self.willAppearIndex == -1) { + self.willAppearIndex = leftIndex; + [self listWillAppear:self.willAppearIndex]; + } + } + if (self.willDisappearIndex == -1) { + self.willDisappearIndex = rightIndex; + [self listWillDisappear:self.willDisappearIndex]; + } + }else { + //当前选中的在左边,用户正在从左边往右边滑动 + if (self.validListDict[@(rightIndex)] == nil && remainderRatio > self.initListPercent) { + [self initListIfNeededAtIndex:rightIndex]; + }else if (self.validListDict[@(rightIndex)] != nil) { + if (self.willAppearIndex == -1) { + self.willAppearIndex = rightIndex; + [self listWillAppear:self.willAppearIndex]; + } + } + if (self.willDisappearIndex == -1) { + self.willDisappearIndex = leftIndex; + [self listWillDisappear:self.willDisappearIndex]; + } + } + [self listDidAppearOrDisappear:scrollView]; +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (self.willDisappearIndex != -1) { + [self listWillAppear:self.willDisappearIndex]; + [self listWillDisappear:self.willAppearIndex]; + [self listDidAppear:self.willDisappearIndex]; + [self listDidDisappear:self.willAppearIndex]; + self.willDisappearIndex = -1; + self.willAppearIndex = -1; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWDidEndScroll:)]) { + [self.delegate listContainerViewWDidEndScroll:self]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWillBeginDragging:)]) { + [self.delegate listContainerViewWillBeginDragging:self]; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { + if (!decelerate) { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWDidEndScroll:)]) { + [self.delegate listContainerViewWDidEndScroll:self]; + } + } +} + +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWDidEndScroll:)]) { + [self.delegate listContainerViewWDidEndScroll:self]; + } +} + +#pragma mark - JXCategoryViewListContainer + +- (UIScrollView *)contentScrollView { + return self.scrollView; +} + +- (void)setDefaultSelectedIndex:(NSInteger)index { + self.currentIndex = index; +} + +- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex { +} + +- (void)didClickSelectedItemAtIndex:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + self.willAppearIndex = -1; + self.willDisappearIndex = -1; + if (self.currentIndex != index) { + [self listWillDisappear:self.currentIndex]; + [self listDidDisappear:self.currentIndex]; + [self listWillAppear:index]; + [self listDidAppear:index]; + } +} + +- (void)reloadData { + for (id list in _validListDict.allValues) { + [[list listView] removeFromSuperview]; + if ([list isKindOfClass:[UIViewController class]]) { + [(UIViewController *)list removeFromParentViewController]; + } + } + [_validListDict removeAllObjects]; + + if (self.containerType == JXPagerListContainerType_ScrollView) { + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height); + }else { + [self.collectionView reloadData]; + } + [self listWillAppear:self.currentIndex]; + [self listDidAppear:self.currentIndex]; +} + +#pragma mark - Private + +- (void)initListIfNeededAtIndex:(NSInteger)index { + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:canInitListAtIndex:)]) { + BOOL canInitList = [self.delegate listContainerView:self canInitListAtIndex:index]; + if (!canInitList) { + return; + } + } + id list = _validListDict[@(index)]; + if (list != nil) { + //列表已经创建好了 + return; + } + list = [self.delegate listContainerView:self initListForIndex:index]; + if ([list isKindOfClass:[UIViewController class]]) { + [self.containerVC addChildViewController:(UIViewController *)list]; + } + _validListDict[@(index)] = list; + + switch (self.containerType) { + case JXPagerListContainerType_ScrollView: { + [list listView].frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); + [self.scrollView addSubview:[list listView]]; + break; + } + case JXPagerListContainerType_CollectionView: { + UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + if (cell != nil) { + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + [list listView].frame = cell.contentView.bounds; + [cell.contentView addSubview:[list listView]]; + } + break; + } + + } +} + +- (void)listWillAppear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + id list = _validListDict[@(index)]; + if (list != nil) { + if (list && [list respondsToSelector:@selector(listWillAppear)]) { + [list listWillAppear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC beginAppearanceTransition:YES animated:NO]; + } + }else { + //当前列表未被创建(页面初始化或通过点击触发的listWillAppear) + BOOL canInitList = YES; + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:canInitListAtIndex:)]) { + canInitList = [self.delegate listContainerView:self canInitListAtIndex:index]; + } + if (canInitList) { + id list = _validListDict[@(index)]; + if (list == nil) { + list = [self.delegate listContainerView:self initListForIndex:index]; + if ([list isKindOfClass:[UIViewController class]]) { + [self.containerVC addChildViewController:(UIViewController *)list]; + } + _validListDict[@(index)] = list; + } + if (self.containerType == JXPagerListContainerType_ScrollView) { + if ([list listView].superview == nil) { + [list listView].frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); + [self.scrollView addSubview:[list listView]]; + + if (list && [list respondsToSelector:@selector(listWillAppear)]) { + [list listWillAppear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC beginAppearanceTransition:YES animated:NO]; + } + } + }else { + UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + [list listView].frame = cell.contentView.bounds; + [cell.contentView addSubview:[list listView]]; + + if (list && [list respondsToSelector:@selector(listWillAppear)]) { + [list listWillAppear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC beginAppearanceTransition:YES animated:NO]; + } + } + } + } +} + +- (void)listDidAppear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + self.currentIndex = index; + id list = _validListDict[@(index)]; + if (list && [list respondsToSelector:@selector(listDidAppear)]) { + [list listDidAppear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC endAppearanceTransition]; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:listDidAppearAtIndex:)]) { + [self.delegate listContainerView:self listDidAppearAtIndex:index]; + } +} + +- (void)listWillDisappear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + id list = _validListDict[@(index)]; + if (list && [list respondsToSelector:@selector(listWillDisappear)]) { + [list listWillDisappear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC beginAppearanceTransition:NO animated:NO]; + } +} + +- (void)listDidDisappear:(NSInteger)index { + if (![self checkIndexValid:index]) { + return; + } + id list = _validListDict[@(index)]; + if (list && [list respondsToSelector:@selector(listDidDisappear)]) { + [list listDidDisappear]; + } + if ([list isKindOfClass:[UIViewController class]]) { + UIViewController *listVC = (UIViewController *)list; + [listVC endAppearanceTransition]; + } +} + +- (BOOL)checkIndexValid:(NSInteger)index { + NSUInteger count = [self.delegate numberOfListsInlistContainerView:self]; + if (count <= 0 || index >= count) { + return NO; + } + return YES; +} + +- (void)listDidAppearOrDisappear:(UIScrollView *)scrollView { + CGFloat currentIndexPercent = scrollView.contentOffset.x/scrollView.bounds.size.width; + if (self.willAppearIndex != -1 || self.willDisappearIndex != -1) { + NSInteger disappearIndex = self.willDisappearIndex; + NSInteger appearIndex = self.willAppearIndex; + if (self.willAppearIndex > self.willDisappearIndex) { + //将要出现的列表在右边 + if (currentIndexPercent >= self.willAppearIndex) { + self.willDisappearIndex = -1; + self.willAppearIndex = -1; + [self listDidDisappear:disappearIndex]; + [self listDidAppear:appearIndex]; + } + }else { + //将要出现的列表在左边 + if (currentIndexPercent <= self.willAppearIndex) { + self.willDisappearIndex = -1; + self.willAppearIndex = -1; + [self listDidDisappear:disappearIndex]; + [self listDidAppear:appearIndex]; + } + } + } +} + +@end + + diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerListRefreshView.h b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListRefreshView.h new file mode 100644 index 0000000..e347531 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListRefreshView.h @@ -0,0 +1,14 @@ +// +// JXPagingListRefreshView.h +// JXPagingView +// +// Created by jiaxin on 2018/8/28. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXPagerView.h" + +@interface JXPagerListRefreshView : JXPagerView + +@end diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerListRefreshView.m b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListRefreshView.m new file mode 100644 index 0000000..c5b371c --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerListRefreshView.m @@ -0,0 +1,109 @@ +// +// JXPagerListRefreshView.m +// JXPagerView +// +// Created by jiaxin on 2018/8/28. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXPagerListRefreshView.h" + +@interface JXPagerListRefreshView() +@property (nonatomic, assign) CGFloat lastScrollingListViewContentOffsetY; +@end + +@implementation JXPagerListRefreshView + +- (instancetype)initWithDelegate:(id)delegate listContainerType:(JXPagerListContainerType)type { + self = [super initWithDelegate:delegate listContainerType:type]; + if (self) { + self.mainTableView.bounces = NO; + } + return self; +} + +- (void)preferredProcessListViewDidScroll:(UIScrollView *)scrollView { + BOOL shouldProcess = YES; + if (self.currentScrollingListView.contentOffset.y > self.lastScrollingListViewContentOffsetY) { + //往上滚动 + }else { + //往下滚动 + if (self.mainTableView.contentOffset.y == 0) { + shouldProcess = NO; + }else { + if (self.mainTableView.contentOffset.y < self.mainTableViewMaxContentOffsetY) { + //mainTableView的header还没有消失,让listScrollView一直为0 + if (self.currentList && [self.currentList respondsToSelector:@selector(listScrollViewWillResetContentOffset)]) { + [self.currentList listScrollViewWillResetContentOffset]; + } + [self setListScrollViewToMinContentOffsetY:self.currentScrollingListView]; + if (self.automaticallyDisplayListVerticalScrollIndicator) { + self.currentScrollingListView.showsVerticalScrollIndicator = NO; + } + } + } + } + if (shouldProcess) { + if (self.mainTableView.contentOffset.y < self.mainTableViewMaxContentOffsetY) { + //处于下拉刷新的状态,scrollView.contentOffset.y为负数,就重置为0 + if (self.currentScrollingListView.contentOffset.y > [self minContentOffsetYInListScrollView:self.currentScrollingListView]) { + //mainTableView的header还没有消失,让listScrollView一直为0 + if (self.currentList && [self.currentList respondsToSelector:@selector(listScrollViewWillResetContentOffset)]) { + [self.currentList listScrollViewWillResetContentOffset]; + } + [self setListScrollViewToMinContentOffsetY:self.currentScrollingListView]; + if (self.automaticallyDisplayListVerticalScrollIndicator) { + self.currentScrollingListView.showsVerticalScrollIndicator = NO; + } + } + } else { + //mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条 + self.mainTableView.contentOffset = CGPointMake(0, self.mainTableViewMaxContentOffsetY); + if (self.automaticallyDisplayListVerticalScrollIndicator) { + self.currentScrollingListView.showsVerticalScrollIndicator = YES; + } + } + } + self.lastScrollingListViewContentOffsetY = self.currentScrollingListView.contentOffset.y; +} + +- (void)preferredProcessMainTableViewDidScroll:(UIScrollView *)scrollView { + if (self.pinSectionHeaderVerticalOffset != 0) { + if (!(self.currentScrollingListView != nil && self.currentScrollingListView.contentOffset.y > [self minContentOffsetYInListScrollView:self.currentScrollingListView])) { + //没有处于滚动某一个listView的状态 + if (scrollView.contentOffset.y <= 0) { + self.mainTableView.bounces = NO; + self.mainTableView.contentOffset = CGPointZero; + return; + }else { + self.mainTableView.bounces = YES; + } + } + } + if (self.currentScrollingListView != nil && self.currentScrollingListView.contentOffset.y > [self minContentOffsetYInListScrollView:self.currentScrollingListView]) { + //mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动 + [self setMainTableViewToMaxContentOffsetY]; + } + + if (scrollView.contentOffset.y < self.mainTableViewMaxContentOffsetY) { + //mainTableView已经显示了header,listView的contentOffset需要重置 + for (id list in self.validListDict.allValues) { + //正在下拉刷新时,不需要重置 + UIScrollView *listScrollView = [list listScrollView]; + if (listScrollView.contentOffset.y > 0) { + if ([list respondsToSelector:@selector(listScrollViewWillResetContentOffset)]) { + [list listScrollViewWillResetContentOffset]; + } + [self setListScrollViewToMinContentOffsetY:listScrollView]; + } + } + } + + if (scrollView.contentOffset.y > self.mainTableViewMaxContentOffsetY && self.currentScrollingListView.contentOffset.y == [self minContentOffsetYInListScrollView:self.currentScrollingListView]) { + //当往上滚动mainTableView的headerView时,滚动到底时,修复listView往上小幅度滚动 + [self setMainTableViewToMaxContentOffsetY]; + } +} + + +@end diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerMainTableView.h b/Pods/JXPagingView/Sources/JXPagerView/JXPagerMainTableView.h new file mode 100644 index 0000000..baf5cf4 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerMainTableView.h @@ -0,0 +1,19 @@ +// +// JXPagingMainTableView.h +// JXPagingView +// +// Created by jiaxin on 2018/8/27. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import + +@protocol JXPagerMainTableViewGestureDelegate + +- (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; + +@end + +@interface JXPagerMainTableView : UITableView +@property (nonatomic, weak) id gestureDelegate; +@end diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerMainTableView.m b/Pods/JXPagingView/Sources/JXPagerView/JXPagerMainTableView.m new file mode 100644 index 0000000..8cd9fe6 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerMainTableView.m @@ -0,0 +1,25 @@ +// +// JXPagerMainTableView.m +// JXPagerView +// +// Created by jiaxin on 2018/8/27. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXPagerMainTableView.h" + +@interface JXPagerMainTableView () + +@end + +@implementation JXPagerMainTableView + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + if (self.gestureDelegate && [self.gestureDelegate respondsToSelector:@selector(mainTableViewGestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) { + return [self.gestureDelegate mainTableViewGestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; + }else { + return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]; + } +} + +@end diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerSmoothView.h b/Pods/JXPagingView/Sources/JXPagerView/JXPagerSmoothView.h new file mode 100644 index 0000000..246b8e5 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerSmoothView.h @@ -0,0 +1,91 @@ +// +// JXPagerSmoothView.h +// JXPagerViewExample-OC +// +// Created by jiaxin on 2019/11/15. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import + +@class JXPagerSmoothView; + +@protocol JXPagerSmoothViewListViewDelegate +/** +返回listView。如果是vc包裹的就是vc.view;如果是自定义view包裹的,就是自定义view自己。 +*/ +- (UIView *)listView; +/** + 返回JXPagerSmoothViewListViewDelegate内部持有的UIScrollView或UITableView或UICollectionView + */ +- (UIScrollView *)listScrollView; + +@optional +- (void)listDidAppear; +- (void)listDidDisappear; + +@end + +@protocol JXPagerSmoothViewDataSource + +/** + 返回页面header的高度 + */ +- (CGFloat)heightForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView; + +/** + 返回页面header视图 + */ +- (UIView *)viewForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView; + +/** + 返回悬浮视图的高度 + */ +- (CGFloat)heightForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView; + +/** + 返回悬浮视图 + */ +- (UIView *)viewForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView; + +/** + 返回列表的数量 + */ +- (NSInteger)numberOfListsInPagerView:(JXPagerSmoothView *)pagerView; + +/** + 根据index初始化一个对应列表实例,需要是遵从`JXPagerSmoothViewListViewDelegate`协议的对象。 + 如果列表是用自定义UIView封装的,就让自定义UIView遵从`JXPagerSmoothViewListViewDelegate`协议,该方法返回自定义UIView即可。 + 如果列表是用自定义UIViewController封装的,就让自定义UIViewController遵从`JXPagerSmoothViewListViewDelegate`协议,该方法返回自定义UIViewController即可。 + + @param pagerView pagerView description + @param index index description + @return 新生成的列表实例 + */ +- (id)pagerView:(JXPagerSmoothView *)pagerView initListAtIndex:(NSInteger)index; + +@end + +@protocol JXPagerSmoothViewDelegate +- (void)pagerSmoothViewDidScroll:(UIScrollView *)scrollView; +@end + +@interface JXPagerSmoothView : UIView + +/** + 当前已经加载过的列表:key就是@(index)值,value是对应的列表。 + */ +@property (nonatomic, strong, readonly) NSDictionary > *listDict; +@property (nonatomic, strong, readonly) UICollectionView *listCollectionView; +@property (nonatomic, assign) NSInteger defaultSelectedIndex; +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithDataSource:(id)dataSource NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; + +- (void)reloadData; + +@end + diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerSmoothView.m b/Pods/JXPagingView/Sources/JXPagerView/JXPagerSmoothView.m new file mode 100644 index 0000000..69856c0 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerSmoothView.m @@ -0,0 +1,361 @@ +// +// JXPagerSmoothView.m +// JXPagerViewExample-OC +// +// Created by jiaxin on 2019/11/15. +// Copyright © 2019 jiaxin. All rights reserved. +// + +#import "JXPagerSmoothView.h" + +static NSString *JXPagerSmoothViewCollectionViewCellIdentifier = @"cell"; + +@interface JXPagerSmoothCollectionView : UICollectionView +@property (nonatomic, strong) UIView *pagerHeaderContainerView; +@end +@implementation JXPagerSmoothCollectionView +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + CGPoint point = [touch locationInView:self.pagerHeaderContainerView]; + if (CGRectContainsPoint(self.pagerHeaderContainerView.bounds, point)) { + return NO; + } + return YES; +} +@end + +@interface JXPagerSmoothView () + +@property (nonatomic, weak) id dataSource; +@property (nonatomic, strong) JXPagerSmoothCollectionView *listCollectionView; +@property (nonatomic, strong) NSMutableDictionary > *listDict; +@property (nonatomic, strong) NSMutableDictionary *listHeaderDict; +@property (nonatomic, assign, getter=isSyncListContentOffsetEnabled) BOOL syncListContentOffsetEnabled; +@property (nonatomic, strong) UIView *pagerHeaderContainerView; +@property (nonatomic, assign) CGFloat currentPagerHeaderContainerViewY; +@property (nonatomic, assign) NSInteger currentIndex; +@property (nonatomic, strong) UIScrollView *currentListScrollView; +@property (nonatomic, assign) CGFloat heightForPagerHeader; +@property (nonatomic, assign) CGFloat heightForPinHeader; +@property (nonatomic, assign) CGFloat heightForPagerHeaderContainerView; +@property (nonatomic, assign) CGFloat currentListInitializeContentOffsetY; +@property (nonatomic, strong) UIScrollView *singleScrollView; +@end + +@implementation JXPagerSmoothView + +- (void)dealloc +{ + for (id list in self.listDict.allValues) { + [[list listScrollView] removeObserver:self forKeyPath:@"contentOffset"]; + [[list listScrollView] removeObserver:self forKeyPath:@"contentSize"]; + } +} + +- (instancetype)initWithDataSource:(id)dataSource +{ + self = [super initWithFrame:CGRectZero]; + if (self) { + _dataSource = dataSource; + _listDict = [NSMutableDictionary dictionary]; + _listHeaderDict = [NSMutableDictionary dictionary]; + [self initializeViews]; + } + return self; +} + +- (void)initializeViews { + self.pagerHeaderContainerView = [[UIView alloc] init]; + + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + layout.minimumLineSpacing = 0; + layout.minimumInteritemSpacing = 0; + _listCollectionView = [[JXPagerSmoothCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + self.listCollectionView.dataSource = self; + self.listCollectionView.delegate = self; + self.listCollectionView.pagingEnabled = YES; + self.listCollectionView.bounces = NO; + self.listCollectionView.showsHorizontalScrollIndicator = NO; + self.listCollectionView.scrollsToTop = NO; + [self.listCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:JXPagerSmoothViewCollectionViewCellIdentifier]; + if (@available(iOS 10.0, *)) { + self.listCollectionView.prefetchingEnabled = NO; + } + if (@available(iOS 11.0, *)) { + self.listCollectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + _listCollectionView.pagerHeaderContainerView = self.pagerHeaderContainerView; + [self addSubview:self.listCollectionView]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + self.listCollectionView.frame = self.bounds; + if (CGRectEqualToRect(self.pagerHeaderContainerView.frame, CGRectZero)) { + [self reloadData]; + } + if (self.singleScrollView != nil) { + self.singleScrollView.frame = self.bounds; + } +} + +- (void)reloadData { + self.currentListScrollView = nil; + self.currentIndex = self.defaultSelectedIndex; + self.currentPagerHeaderContainerViewY = 0; + self.syncListContentOffsetEnabled = NO; + + [self.listHeaderDict removeAllObjects]; + for (id list in self.listDict.allValues) { + [[list listScrollView] removeObserver:self forKeyPath:@"contentOffset"]; + [[list listScrollView] removeObserver:self forKeyPath:@"contentSize"]; + [[list listView] removeFromSuperview]; + } + [_listDict removeAllObjects]; + + self.heightForPagerHeader = [self.dataSource heightForPagerHeaderInPagerView:self]; + self.heightForPinHeader = [self.dataSource heightForPinHeaderInPagerView:self]; + self.heightForPagerHeaderContainerView = self.heightForPagerHeader + self.heightForPinHeader; + + UIView *pagerHeader = [self.dataSource viewForPagerHeaderInPagerView:self]; + UIView *pinHeader = [self.dataSource viewForPinHeaderInPagerView:self]; + [self.pagerHeaderContainerView addSubview:pagerHeader]; + [self.pagerHeaderContainerView addSubview:pinHeader]; + + self.pagerHeaderContainerView.frame = CGRectMake(0, 0, self.bounds.size.width, self.heightForPagerHeaderContainerView); + pagerHeader.frame = CGRectMake(0, 0, self.bounds.size.width, self.heightForPagerHeader); + pinHeader.frame = CGRectMake(0, self.heightForPagerHeader, self.bounds.size.width, self.heightForPinHeader); + [self.listCollectionView setContentOffset:CGPointMake(self.listCollectionView.bounds.size.width*self.defaultSelectedIndex, 0) animated:NO]; + [self.listCollectionView reloadData]; + + if ([self.dataSource numberOfListsInPagerView:self] == 0) { + self.singleScrollView = [[UIScrollView alloc] init]; + [self addSubview:self.singleScrollView]; + [self.singleScrollView addSubview:pagerHeader]; + self.singleScrollView.contentSize = CGSizeMake(self.bounds.size.width, self.heightForPagerHeader); + }else if (self.singleScrollView != nil) { + [self.singleScrollView removeFromSuperview]; + self.singleScrollView = nil; + } +} + +#pragma mark - UICollectionViewDataSource & UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return self.bounds.size; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return [self.dataSource numberOfListsInPagerView:self]; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:JXPagerSmoothViewCollectionViewCellIdentifier forIndexPath:indexPath]; + id list = self.listDict[@(indexPath.item)]; + if (list == nil) { + list = [self.dataSource pagerView:self initListAtIndex:indexPath.item]; + _listDict[@(indexPath.item)] = list; + [[list listView] setNeedsLayout]; + [[list listView] layoutIfNeeded]; + UIScrollView *listScrollView = [list listScrollView]; + if ([listScrollView isKindOfClass:[UITableView class]]) { + ((UITableView *)listScrollView).estimatedRowHeight = 0; + ((UITableView *)listScrollView).estimatedSectionFooterHeight = 0; + ((UITableView *)listScrollView).estimatedSectionHeaderHeight = 0; + } + if (@available(iOS 11.0, *)) { + listScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + listScrollView.contentInset = UIEdgeInsetsMake(self.heightForPagerHeaderContainerView, 0, 0, 0); + self.currentListInitializeContentOffsetY = -listScrollView.contentInset.top + MIN(-self.currentPagerHeaderContainerViewY, self.heightForPagerHeader); + listScrollView.contentOffset = CGPointMake(0, self.currentListInitializeContentOffsetY); + UIView *listHeader = [[UIView alloc] initWithFrame:CGRectMake(0, -self.heightForPagerHeaderContainerView, self.bounds.size.width, self.heightForPagerHeaderContainerView)]; + [listScrollView addSubview:listHeader]; + if (self.pagerHeaderContainerView.superview == nil) { + [listHeader addSubview:self.pagerHeaderContainerView]; + } + self.listHeaderDict[@(indexPath.item)] = listHeader; + [listScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; + [listScrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil]; + } + for (id listItem in self.listDict.allValues) { + [listItem listScrollView].scrollsToTop = (listItem == list); + } + UIView *listView = [list listView]; + if (listView != nil && listView.superview != cell.contentView) { + for (UIView *view in cell.contentView.subviews) { + [view removeFromSuperview]; + } + listView.frame = cell.contentView.bounds; + [cell.contentView addSubview:listView]; + } + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + [self listDidAppear:indexPath.item]; +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + [self listDidDisappear:indexPath.item]; +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerSmoothViewDidScroll:)]) { + [self.delegate pagerSmoothViewDidScroll:scrollView]; + } + CGFloat indexPercent = scrollView.contentOffset.x/scrollView.bounds.size.width; + NSInteger index = floor(indexPercent); + UIScrollView *listScrollView = [self.listDict[@(index)] listScrollView]; + if (indexPercent - index == 0 && index != self.currentIndex && !(scrollView.isDragging || scrollView.isDecelerating) && listScrollView.contentOffset.y <= -self.heightForPinHeader) { + [self horizontalScrollDidEndAtIndex:index]; + }else { + //左右滚动的时候,就把listHeaderContainerView添加到self,达到悬浮在顶部的效果 + if (self.pagerHeaderContainerView.superview != self) { + self.pagerHeaderContainerView.frame = CGRectMake(0, self.currentPagerHeaderContainerViewY, self.pagerHeaderContainerView.bounds.size.width, self.pagerHeaderContainerView.bounds.size.height); + [self addSubview:self.pagerHeaderContainerView]; + } + } + if (index != self.currentIndex) { + self.currentIndex = index; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { + if (!decelerate) { + NSInteger index = scrollView.contentOffset.x/scrollView.bounds.size.width; + [self horizontalScrollDidEndAtIndex:index]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + NSInteger index = scrollView.contentOffset.x/scrollView.bounds.size.width; + [self horizontalScrollDidEndAtIndex:index]; +} + +#pragma mark - KVO + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqualToString:@"contentOffset"]) { + UIScrollView *scrollView = (UIScrollView *)object; + if (scrollView != nil) { + [self listDidScroll:scrollView]; + } + }else if([keyPath isEqualToString:@"contentSize"]) { + UIScrollView *scrollView = (UIScrollView *)object; + if (scrollView != nil) { + CGFloat minContentSizeHeight = self.bounds.size.height - self.heightForPinHeader; + if (minContentSizeHeight > scrollView.contentSize.height) { + scrollView.contentSize = CGSizeMake(scrollView.contentSize.width, minContentSizeHeight); + //新的scrollView第一次加载的时候重置contentOffset + if (_currentListScrollView != nil && scrollView != _currentListScrollView) { + scrollView.contentOffset = CGPointMake(0, self.currentListInitializeContentOffsetY); + } + } + } + }else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +#pragma mark - Event + +- (void)listDidScroll:(UIScrollView *)scrollView { + if (self.listCollectionView.isDragging || self.listCollectionView.isDecelerating) { + return; + } + NSInteger listIndex = [self listIndexForListScrollView:scrollView]; + if (listIndex != self.currentIndex) { + return; + } + self.currentListScrollView = scrollView; + CGFloat contentOffsetY = scrollView.contentOffset.y + self.heightForPagerHeaderContainerView; + if (contentOffsetY < self.heightForPagerHeader) { + self.syncListContentOffsetEnabled = YES; + self.currentPagerHeaderContainerViewY = -contentOffsetY; + for (id list in self.listDict.allValues) { + if ([list listScrollView] != self.currentListScrollView) { + [[list listScrollView] setContentOffset:scrollView.contentOffset animated:NO]; + } + } + UIView *listHeader = [self listHeaderForListScrollView:scrollView]; + if (self.pagerHeaderContainerView.superview != listHeader) { + self.pagerHeaderContainerView.frame = CGRectMake(0, 0, self.pagerHeaderContainerView.bounds.size.width, self.pagerHeaderContainerView.bounds.size.height); + [listHeader addSubview:self.pagerHeaderContainerView]; + } + }else { + if (self.pagerHeaderContainerView.superview != self) { + self.pagerHeaderContainerView.frame = CGRectMake(0, -self.heightForPagerHeader, self.pagerHeaderContainerView.bounds.size.width, self.pagerHeaderContainerView.bounds.size.height); + [self addSubview:self.pagerHeaderContainerView]; + } + if (self.isSyncListContentOffsetEnabled) { + self.syncListContentOffsetEnabled = NO; + self.currentPagerHeaderContainerViewY = -self.heightForPagerHeader; + for (id list in self.listDict.allValues) { + if ([list listScrollView] != scrollView) { + [[list listScrollView] setContentOffset:CGPointMake(0, -self.heightForPinHeader) animated:NO]; + } + } + } + } +} + +#pragma mark - Private + +- (UIView *)listHeaderForListScrollView:(UIScrollView *)scrollView { + for (NSNumber *index in self.listDict) { + if ([self.listDict[index] listScrollView] == scrollView) { + return self.listHeaderDict[index]; + } + } + return nil; +} + +- (NSInteger)listIndexForListScrollView:(UIScrollView *)scrollView { + for (NSNumber *index in self.listDict) { + if ([self.listDict[index] listScrollView] == scrollView) { + return [index integerValue]; + } + } + return 0; +} + +- (void)listDidAppear:(NSInteger)index { + NSUInteger count = [self.dataSource numberOfListsInPagerView:self]; + if (count <= 0 || index >= count) { + return; + } + + id list = self.listDict[@(index)]; + if (list && [list respondsToSelector:@selector(listDidAppear)]) { + [list listDidAppear]; + } +} + +- (void)listDidDisappear:(NSInteger)index { + NSUInteger count = [self.dataSource numberOfListsInPagerView:self]; + if (count <= 0 || index >= count) { + return; + } + id list = self.listDict[@(index)]; + if (list && [list respondsToSelector:@selector(listDidDisappear)]) { + [list listDidDisappear]; + } +} + +/// 列表左右切换滚动结束之后,需要把pagerHeaderContainerView添加到当前index的列表上面 +- (void)horizontalScrollDidEndAtIndex:(NSInteger)index { + self.currentIndex = index; + UIView *listHeader = self.listHeaderDict[@(index)]; + UIScrollView *listScrollView = [self.listDict[@(index)] listScrollView]; + if (listHeader != nil && listScrollView.contentOffset.y <= -self.heightForPinHeader) { + for (id listItem in self.listDict.allValues) { + [listItem listScrollView].scrollsToTop = ([listItem listScrollView] == listScrollView); + } + self.pagerHeaderContainerView.frame = CGRectMake(0, 0, self.pagerHeaderContainerView.bounds.size.width, self.pagerHeaderContainerView.bounds.size.height); + [listHeader addSubview:self.pagerHeaderContainerView]; + } +} + +@end diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerView.h b/Pods/JXPagingView/Sources/JXPagerView/JXPagerView.h new file mode 100644 index 0000000..3dd6c6a --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerView.h @@ -0,0 +1,131 @@ +// +// JXPagerView.h +// JXPagerView +// +// Created by jiaxin on 2018/8/27. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import +#import "JXPagerMainTableView.h" +#import "JXPagerListContainerView.h" +@class JXPagerView; + +@protocol JXPagerViewDelegate + +/** + 返回tableHeaderView的高度,因为内部需要比对判断,只能是整型数 + */ +- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView; + +/** + 返回tableHeaderView + */ +- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView; + +/** + 返回悬浮HeaderView的高度,因为内部需要比对判断,只能是整型数 + */ +- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView; + +/** + 返回悬浮HeaderView。我用的是自己封装的JXCategoryView(Github:https://github.com/pujiaxin33/JXCategoryView),你也可以选择其他的三方库或者自己写 + */ +- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView; + +/** + 返回列表的数量 + */ +- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView; + +/** + 根据index初始化一个对应列表实例,需要是遵从`JXPagerViewListViewDelegate`协议的对象。 + 如果列表是用自定义UIView封装的,就让自定义UIView遵从`JXPagerViewListViewDelegate`协议,该方法返回自定义UIView即可。 + 如果列表是用自定义UIViewController封装的,就让自定义UIViewController遵从`JXPagerViewListViewDelegate`协议,该方法返回自定义UIViewController即可。 + 注意:一定要是新生成的实例!!! + + @param pagerView pagerView description + @param index index description + @return 新生成的列表实例 + */ +- (id)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index; + +@optional + +/// 返回对应index的列表唯一标识 +/// @param pagerView pagerView description +/// @param index index description +- (NSString *)pagerView:(JXPagerView *)pagerView listIdentifierAtIndex:(NSInteger)index; +- (void)mainTableViewDidScroll:(UIScrollView *)scrollView __attribute__ ((deprecated)); +- (void)pagerView:(JXPagerView *)pagerView mainTableViewDidScroll:(UIScrollView *)scrollView; +- (void)pagerView:(JXPagerView *)pagerView mainTableViewWillBeginDragging:(UIScrollView *)scrollView; +- (void)pagerView:(JXPagerView *)pagerView mainTableViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; +- (void)pagerView:(JXPagerView *)pagerView mainTableViewDidEndDecelerating:(UIScrollView *)scrollView; +- (void)pagerView:(JXPagerView *)pagerView mainTableViewDidEndScrollingAnimation:(UIScrollView *)scrollView; + +/** + 返回自定义UIScrollView或UICollectionView的Class + 某些特殊情况需要自己处理列表容器内UIScrollView内部逻辑。比如项目用了FDFullscreenPopGesture,需要处理手势相关代理。 + + @param pagerView JXPagerView + @return 自定义UIScrollView实例 + */ +- (Class)scrollViewClassInlistContainerViewInPagerView:(JXPagerView *)pagerView; + +@end + +@interface JXPagerView : UIView +/** + 需要和self.categoryView.defaultSelectedIndex保持一致 + */ +@property (nonatomic, assign) NSInteger defaultSelectedIndex; +@property (nonatomic, strong, readonly) JXPagerMainTableView *mainTableView; +@property (nonatomic, strong, readonly) JXPagerListContainerView *listContainerView; +/** + 当前已经加载过可用的列表字典,key就是index值,value是对应的列表。 + */ +@property (nonatomic, strong, readonly) NSDictionary > *validListDict; +/** + 顶部固定sectionHeader的垂直偏移量。数值越大越往下沉。 + */ +@property (nonatomic, assign) NSInteger pinSectionHeaderVerticalOffset; +/** + 是否允许列表左右滑动。默认:YES + */ +@property (nonatomic, assign) BOOL isListHorizontalScrollEnabled; +/** + 是否允许当前列表自动显示或隐藏列表是垂直滚动指示器。YES:悬浮的headerView滚动到顶部开始滚动列表时,就会显示,反之隐藏。NO:内部不会处理列表的垂直滚动指示器。默认为:YES。 + */ +@property (nonatomic, assign) BOOL automaticallyDisplayListVerticalScrollIndicator; +/** + 当allowsCacheList为true时,请务必实现代理方法`- (NSString *)pagerView:(JXPagerView *)pagerView listIdentifierAtIndex:(NSInteger)index` + */ +@property (nonatomic, assign) BOOL allowsCacheList; + +- (instancetype)initWithDelegate:(id)delegate; +- (instancetype)initWithDelegate:(id)delegate listContainerType:(JXPagerListContainerType)type NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (void)reloadData; +- (void)resizeTableHeaderViewHeightWithAnimatable:(BOOL)animatable duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve; + +@end + +/** +暴露给子类使用,请勿直接使用相关属性和方法! +*/ +@interface JXPagerView (UISubclassingGet) +@property (nonatomic, strong, readonly) UIScrollView *currentScrollingListView; +@property (nonatomic, strong, readonly) id currentList; +@property (nonatomic, assign, readonly) CGFloat mainTableViewMaxContentOffsetY; +@end + +@interface JXPagerView (UISubclassingHooks) +- (void)preferredProcessListViewDidScroll:(UIScrollView *)scrollView; +- (void)preferredProcessMainTableViewDidScroll:(UIScrollView *)scrollView; +- (void)setMainTableViewToMaxContentOffsetY; +- (void)setListScrollViewToMinContentOffsetY:(UIScrollView *)scrollView; +- (CGFloat)minContentOffsetYInListScrollView:(UIScrollView *)scrollView; +@end + diff --git a/Pods/JXPagingView/Sources/JXPagerView/JXPagerView.m b/Pods/JXPagingView/Sources/JXPagerView/JXPagerView.m new file mode 100644 index 0000000..cb57ae7 --- /dev/null +++ b/Pods/JXPagingView/Sources/JXPagerView/JXPagerView.m @@ -0,0 +1,409 @@ +// +// JXPagerView.m +// JXPagerView +// +// Created by jiaxin on 2018/8/27. +// Copyright © 2018年 jiaxin. All rights reserved. +// + +#import "JXPagerView.h" +@class JXPagerListContainerScrollView; +@class JXPagerListContainerCollectionView; + +@interface JXPagerView () +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) JXPagerMainTableView *mainTableView; +@property (nonatomic, strong) JXPagerListContainerView *listContainerView; +@property (nonatomic, strong) UIScrollView *currentScrollingListView; +@property (nonatomic, strong) id currentList; +@property (nonatomic, strong) NSMutableDictionary > *validListDict; +@property (nonatomic, strong) UIView *tableHeaderContainerView; +@property (nonatomic, strong) NSMutableDictionary> *listCache; +@end + +@implementation JXPagerView + +- (instancetype)initWithDelegate:(id)delegate { + return [self initWithDelegate:delegate listContainerType:JXPagerListContainerType_CollectionView]; +} + +- (instancetype)initWithDelegate:(id)delegate listContainerType:(JXPagerListContainerType)type { + self = [super initWithFrame:CGRectZero]; + if (self) { + _delegate = delegate; + _validListDict = [NSMutableDictionary dictionary]; + _automaticallyDisplayListVerticalScrollIndicator = YES; + _isListHorizontalScrollEnabled = YES; + + _mainTableView = [[JXPagerMainTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + self.mainTableView.showsVerticalScrollIndicator = NO; + self.mainTableView.showsHorizontalScrollIndicator = NO; + self.mainTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.mainTableView.scrollsToTop = NO; + self.mainTableView.dataSource = self; + self.mainTableView.delegate = self; + [self refreshTableHeaderView]; + [self.mainTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; + if (@available(iOS 11.0, *)) { + self.mainTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 150000 + if (@available(iOS 15.0, *)) { + self.mainTableView.sectionHeaderTopPadding = 0; + } +#endif + [self addSubview:self.mainTableView]; + + _listContainerView = [[JXPagerListContainerView alloc] initWithType:type delegate:self]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + if (!CGRectEqualToRect(self.bounds, self.mainTableView.frame)) { + self.mainTableView.frame = self.bounds; + [self.mainTableView reloadData]; + } +} + +- (void)setDefaultSelectedIndex:(NSInteger)defaultSelectedIndex { + _defaultSelectedIndex = defaultSelectedIndex; + + self.listContainerView.defaultSelectedIndex = defaultSelectedIndex; +} + +- (void)setIsListHorizontalScrollEnabled:(BOOL)isListHorizontalScrollEnabled { + _isListHorizontalScrollEnabled = isListHorizontalScrollEnabled; + + self.listContainerView.scrollView.scrollEnabled = isListHorizontalScrollEnabled; +} + +- (void)reloadData { + self.currentList = nil; + self.currentScrollingListView = nil; + [_validListDict removeAllObjects]; + //根据新数据删除不需要的list + if (self.allowsCacheList) { + NSMutableArray *newListIdentifierArray = [NSMutableArray array]; + if (self.delegate && [self.delegate respondsToSelector:@selector(numberOfListsInPagerView:)]) { + NSInteger listCount = [self.delegate numberOfListsInPagerView:self]; + for (NSInteger index = 0; index < listCount; index ++) { + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerView:listIdentifierAtIndex:)]) { + NSString *listIdentifier = [self.delegate pagerView:self listIdentifierAtIndex:index]; + [newListIdentifierArray addObject:listIdentifier]; + } + } + } + NSArray *existedKeys = self.listCache.allKeys; + for (NSString *listIdentifier in existedKeys) { + if (![newListIdentifierArray containsObject:listIdentifier]) { + [self.listCache removeObjectForKey:listIdentifier]; + } + } + } + [self refreshTableHeaderView]; + if (self.pinSectionHeaderVerticalOffset != 0 && self.mainTableView.contentOffset.y > self.pinSectionHeaderVerticalOffset) { + self.mainTableView.contentOffset = CGPointZero; + } + [self.mainTableView reloadData]; + [self.listContainerView reloadData]; +} + +- (void)resizeTableHeaderViewHeightWithAnimatable:(BOOL)animatable duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve { + if (animatable) { + UIViewAnimationOptions options = UIViewAnimationOptionCurveLinear; + switch (curve) { + case UIViewAnimationCurveEaseIn: options = UIViewAnimationOptionCurveEaseIn; break; + case UIViewAnimationCurveEaseOut: options = UIViewAnimationOptionCurveEaseOut; break; + case UIViewAnimationCurveEaseInOut: options = UIViewAnimationOptionCurveEaseInOut; break; + default: break; + } + [UIView animateWithDuration:duration delay:0 options:options animations:^{ + CGRect frame = self.tableHeaderContainerView.bounds; + frame.size.height = [self.delegate tableHeaderViewHeightInPagerView:self]; + self.tableHeaderContainerView.frame = frame; + self.mainTableView.tableHeaderView = self.tableHeaderContainerView; + [self.mainTableView setNeedsLayout]; + [self.mainTableView layoutIfNeeded]; + } completion:^(BOOL finished) { }]; + }else { + CGRect frame = self.tableHeaderContainerView.bounds; + frame.size.height = [self.delegate tableHeaderViewHeightInPagerView:self]; + self.tableHeaderContainerView.frame = frame; + self.mainTableView.tableHeaderView = self.tableHeaderContainerView; + } +} + +#pragma mark - Private + +- (void)refreshTableHeaderView { + UIView *tableHeaderView = [self.delegate tableHeaderViewInPagerView:self]; + UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, [self.delegate tableHeaderViewHeightInPagerView:self])]; + [containerView addSubview:tableHeaderView]; + tableHeaderView.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:tableHeaderView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeTop multiplier:1 constant:0]; + NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:tableHeaderView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeLeading multiplier:1 constant:0]; + NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:tableHeaderView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; + NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:tableHeaderView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]; + [containerView addConstraints:@[top, leading, bottom, trailing]]; + self.tableHeaderContainerView = containerView; + self.mainTableView.tableHeaderView = containerView; +} + +- (void)adjustMainScrollViewToTargetContentInsetIfNeeded:(UIEdgeInsets)insets { + if (UIEdgeInsetsEqualToEdgeInsets(insets, self.mainTableView.contentInset) == NO) { + self.mainTableView.delegate = nil; + self.mainTableView.contentInset = insets; + self.mainTableView.delegate = self; + } +} + +- (void)listViewDidScroll:(UIScrollView *)scrollView { + self.currentScrollingListView = scrollView; + [self preferredProcessListViewDidScroll:scrollView]; +} + +//仅用于处理设置了pinSectionHeaderVerticalOffset,又添加了MJRefresh的下拉刷新。这种情况会导致JXPagingView和MJRefresh来回设置contentInset值。针对这种及其特殊的情况,就内部特殊处理了。通过下面的判断条件,来判定当前是否处于下拉刷新中。请勿让pinSectionHeaderVerticalOffset和下拉刷新设置的contentInset.top值相同。 +//具体原因参考:https://github.com/pujiaxin33/JXPagingView/issues/203 +- (BOOL)isSetMainScrollViewContentInsetToZeroEnabled:(UIScrollView *)scrollView { + //scrollView.contentInset.top不为0,且scrollView.contentInset.top不等于pinSectionHeaderVerticalOffset,即可认为列表正在刷新。所以这里必须要保证pinSectionHeaderVerticalOffset和MJRefresh的mj_insetT的值不相等。 + BOOL isRefreshing = scrollView.contentInset.top != 0 && scrollView.contentInset.top != self.pinSectionHeaderVerticalOffset; + return !isRefreshing; +} + +#pragma mark - UITableViewDataSource, UITableViewDelegate + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 1; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return MAX(self.bounds.size.height - [self.delegate heightForPinSectionHeaderInPagerView:self] - self.pinSectionHeaderVerticalOffset, 0); +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.backgroundColor = [UIColor clearColor]; + if (self.listContainerView.superview != cell.contentView) { + [cell.contentView addSubview:self.listContainerView]; + } + if (!CGRectEqualToRect(self.listContainerView.frame, cell.bounds)) { + self.listContainerView.frame = cell.bounds; + } + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return [self.delegate heightForPinSectionHeaderInPagerView:self]; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + return [self.delegate viewForPinSectionHeaderInPagerView:self]; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 1; +} + +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + UIView *footer = [[UIView alloc] initWithFrame:CGRectZero]; + footer.backgroundColor = [UIColor clearColor]; + return footer; +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.pinSectionHeaderVerticalOffset != 0) { + if (!(self.currentScrollingListView != nil && self.currentScrollingListView.contentOffset.y > [self minContentOffsetYInListScrollView:self.currentScrollingListView])) { + //没有处于滚动某一个listView的状态 + if (scrollView.contentOffset.y >= self.pinSectionHeaderVerticalOffset) { + //固定的位置就是contentInset.top + [self adjustMainScrollViewToTargetContentInsetIfNeeded:UIEdgeInsetsMake(self.pinSectionHeaderVerticalOffset, 0, 0, 0)]; + }else { + if ([self isSetMainScrollViewContentInsetToZeroEnabled:scrollView]) { + [self adjustMainScrollViewToTargetContentInsetIfNeeded:UIEdgeInsetsZero]; + } + } + } + } + [self preferredProcessMainTableViewDidScroll:scrollView]; + if (self.delegate && [self.delegate respondsToSelector:@selector(mainTableViewDidScroll:)]) { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + [self.delegate mainTableViewDidScroll:scrollView]; + #pragma GCC diagnostic pop + } + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerView:mainTableViewDidScroll:)]) { + [self.delegate pagerView:self mainTableViewDidScroll:scrollView]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + self.listContainerView.scrollView.scrollEnabled = NO; + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerView:mainTableViewWillBeginDragging:)]) { + [self.delegate pagerView:self mainTableViewWillBeginDragging:scrollView]; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { + if (self.isListHorizontalScrollEnabled && !decelerate) { + self.listContainerView.scrollView.scrollEnabled = YES; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerView:mainTableViewDidEndDragging:willDecelerate:)]) { + [self.delegate pagerView:self mainTableViewDidEndDragging:scrollView willDecelerate:decelerate]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (self.isListHorizontalScrollEnabled) { + self.listContainerView.scrollView.scrollEnabled = YES; + } + if ([self isSetMainScrollViewContentInsetToZeroEnabled:scrollView]) { + if (self.mainTableView.contentInset.top != 0 && self.pinSectionHeaderVerticalOffset != 0) { + [self adjustMainScrollViewToTargetContentInsetIfNeeded:UIEdgeInsetsZero]; + } + } + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerView:mainTableViewDidEndDecelerating:)]) { + [self.delegate pagerView:self mainTableViewDidEndDecelerating:scrollView]; + } +} + +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + if (self.isListHorizontalScrollEnabled) { + self.listContainerView.scrollView.scrollEnabled = YES; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(pagerView:mainTableViewDidEndScrollingAnimation:)]) { + [self.delegate pagerView:self mainTableViewDidEndScrollingAnimation:scrollView]; + } +} + +#pragma mark - JXPagerListContainerViewDelegate + +- (NSInteger)numberOfListsInlistContainerView:(JXPagerListContainerView *)listContainerView { + return [self.delegate numberOfListsInPagerView:self]; +} + +- (id)listContainerView:(JXPagerListContainerView *)listContainerView initListForIndex:(NSInteger)index { + id list = self.validListDict[@(index)]; + if (list == nil) { + if (self.allowsCacheList && self.delegate && [self.delegate respondsToSelector:@selector(pagerView:listIdentifierAtIndex:)]) { + NSString *listIdentifier = [self.delegate pagerView:self listIdentifierAtIndex:index]; + list = self.listCache[listIdentifier]; + } + } + if (list == nil) { + list = [self.delegate pagerView:self initListAtIndex:index]; + __weak typeof(self)weakSelf = self; + __weak typeof(id) weakList = list; + [list listViewDidScrollCallback:^(UIScrollView *scrollView) { + weakSelf.currentList = weakList; + [weakSelf listViewDidScroll:scrollView]; + }]; + _validListDict[@(index)] = list; + if (self.allowsCacheList && self.delegate && [self.delegate respondsToSelector:@selector(pagerView:listIdentifierAtIndex:)]) { + NSString *listIdentifier = [self.delegate pagerView:self listIdentifierAtIndex:index]; + self.listCache[listIdentifier] = list; + } + } + return list; +} + + +- (void)listContainerViewWillBeginDragging:(JXPagerListContainerView *)listContainerView { + self.mainTableView.scrollEnabled = NO; +} + +- (void)listContainerViewWDidEndScroll:(JXPagerListContainerView *)listContainerView { + self.mainTableView.scrollEnabled = YES; +} + +- (void)listContainerView:(JXPagerListContainerView *)listContainerView listDidAppearAtIndex:(NSInteger)index { + self.currentScrollingListView = [self.validListDict[@(index)] listScrollView]; + for (id listItem in self.validListDict.allValues) { + if (listItem == self.validListDict[@(index)]) { + [listItem listScrollView].scrollsToTop = YES; + }else { + [listItem listScrollView].scrollsToTop = NO; + } + } +} + +- (Class)scrollViewClassInlistContainerView:(JXPagerListContainerView *)listContainerView { + if (self.delegate && [self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerViewInPagerView:)]) { + return [self.delegate scrollViewClassInlistContainerViewInPagerView:self]; + } + return nil; +} + +@end + +@implementation JXPagerView (UISubclassingGet) + +- (CGFloat)mainTableViewMaxContentOffsetY { + return [self.delegate tableHeaderViewHeightInPagerView:self] - self.pinSectionHeaderVerticalOffset; +} + +@end + +@implementation JXPagerView (UISubclassingHooks) + +- (void)preferredProcessListViewDidScroll:(UIScrollView *)scrollView { + if (self.mainTableView.contentOffset.y < self.mainTableViewMaxContentOffsetY) { + //mainTableView的header还没有消失,让listScrollView一直为0 + if (self.currentList && [self.currentList respondsToSelector:@selector(listScrollViewWillResetContentOffset)]) { + [self.currentList listScrollViewWillResetContentOffset]; + } + [self setListScrollViewToMinContentOffsetY:scrollView]; + if (self.automaticallyDisplayListVerticalScrollIndicator) { + scrollView.showsVerticalScrollIndicator = NO; + } + }else { + //mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条 + self.mainTableView.contentOffset = CGPointMake(0, self.mainTableViewMaxContentOffsetY); + if (self.automaticallyDisplayListVerticalScrollIndicator) { + scrollView.showsVerticalScrollIndicator = YES; + } + } +} + +- (void)preferredProcessMainTableViewDidScroll:(UIScrollView *)scrollView { + if (self.currentScrollingListView != nil && self.currentScrollingListView.contentOffset.y > [self minContentOffsetYInListScrollView:self.currentScrollingListView]) { + //mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动 + [self setMainTableViewToMaxContentOffsetY]; + } + + if (scrollView.contentOffset.y < self.mainTableViewMaxContentOffsetY) { + //mainTableView已经显示了header,listView的contentOffset需要重置 + for (id list in self.validListDict.allValues) { + if ([list respondsToSelector:@selector(listScrollViewWillResetContentOffset)]) { + [list listScrollViewWillResetContentOffset]; + } + [self setListScrollViewToMinContentOffsetY:[list listScrollView]]; + } + } + + if (scrollView.contentOffset.y > self.mainTableViewMaxContentOffsetY && self.currentScrollingListView.contentOffset.y == [self minContentOffsetYInListScrollView:self.currentScrollingListView]) { + //当往上滚动mainTableView的headerView时,滚动到底时,修复listView往上小幅度滚动 + [self setMainTableViewToMaxContentOffsetY]; + } +} + +- (void)setMainTableViewToMaxContentOffsetY { + self.mainTableView.contentOffset = CGPointMake(0, self.mainTableViewMaxContentOffsetY); +} + +- (void)setListScrollViewToMinContentOffsetY:(UIScrollView *)scrollView { + scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, [self minContentOffsetYInListScrollView:scrollView]); +} + +- (CGFloat)minContentOffsetYInListScrollView:(UIScrollView *)scrollView { + if (@available(iOS 11.0, *)) { + return -scrollView.adjustedContentInset.top; + } + return -scrollView.contentInset.top; +} + + +@end diff --git a/Pods/JXPagingView/Sources/PrivacyInfo.xcprivacy b/Pods/JXPagingView/Sources/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..9021190 --- /dev/null +++ b/Pods/JXPagingView/Sources/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/Pods/LSTPopView/LICENSE b/Pods/LSTPopView/LICENSE new file mode 100644 index 0000000..96fd23b --- /dev/null +++ b/Pods/LSTPopView/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 490790096@qq.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.h b/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.h new file mode 100644 index 0000000..5619414 --- /dev/null +++ b/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.h @@ -0,0 +1,231 @@ +// +// LSTPopView.h +// LoSenTrad +// +// Created by LoSenTrad on 2020/2/22. +// + +/** + 联系方式---> QQ群: 1045568246 微信: a_LSTKit , 邮箱: losentrad@163.com 欢迎反馈建议和问题 + + 博客地址 如果觉得好用 伸出你的小指头 点Star 点赞 点收藏! 就是给予我最大的支持! + github: https://github.com/LoSenTrad/LSTPopView + 简书: https://www.jianshu.com/p/8023a85dc2a2 + cocoachina: http://www.cocoachina.com/articles/899060 + */ + +#import +#import "LSTPopViewProtocol.h" +#import "UIView+LSTPV.h" + + +#define LSTPopViewWK(object) __weak typeof(object) wk_##object = object; +#define LSTPopViewSS(object) __strong typeof(object) object = weak##object; + + +NS_ASSUME_NONNULL_BEGIN + +@interface LSTPopView : UIView + + +/** 代理 支持多代理 */ +@property (nonatomic, weak) id _Nullable delegate; +/** 标识 默认为空 */ +@property (nonatomic, copy) NSString *_Nullable identifier; +/** 弹窗容器 */ +@property (nonatomic, readonly) UIView *parentView; +/** 自定义view */ +@property (nonatomic, readonly) UIView *currCustomView; +/** 弹窗位置 默认LSTHemStyleCenter */ +@property (nonatomic, assign) LSTHemStyle hemStyle; +/** 显示时动画弹窗样式 默认LSTPopStyleNO */ +@property (nonatomic, assign) LSTPopStyle popStyle; +/** 移除时动画弹窗样式 默认LSTDismissStyleNO */ +@property (nonatomic, assign) LSTDismissStyle dismissStyle; +/** 显示时动画时长,> 0。不设置则使用默认的动画时长 设置成LSTPopStyleNO, 该属性无效 */ +@property (nonatomic, assign) NSTimeInterval popDuration; +/** 隐藏时动画时长,>0。不设置则使用默认的动画时长 设置成LSTDismissStyleNO, 该属性无效 */ +@property (nonatomic, assign) NSTimeInterval dismissDuration; +/** 弹窗水平方向(X)偏移量校准 默认0 */ +@property (nonatomic, assign) CGFloat adjustX; +/** 弹窗垂直方向(Y)偏移量校准 默认0 */ +@property (nonatomic, assign) CGFloat adjustY; +/** 背景颜色 默认rgb(0,0,0) 透明度0.3 */ +@property (nullable,nonatomic,strong) UIColor *bgColor; +/** 显示时背景的透明度,取值(0.0~1.0),默认为0.3 */ +@property (nonatomic, assign) CGFloat bgAlpha; +/** 是否隐藏背景 默认NO */ +@property (nonatomic, assign) BOOL isHideBg; +/** 显示时点击背景是否移除弹窗,默认为NO。 */ +@property (nonatomic, assign) BOOL isClickBgDismiss; +/** 是否监听屏幕旋转,默认为YES */ +@property (nonatomic, assign) BOOL isObserverScreenRotation; +/** 是否支持点击回馈 默认NO (暂时关闭) */ +@property (nonatomic, assign) BOOL isClickFeedback; +/** 是否规避键盘 默认YES */ +@property (nonatomic, assign) BOOL isAvoidKeyboard; +/** 弹窗和键盘的距离 默认10 */ +@property (nonatomic, assign) CGFloat avoidKeyboardSpace; +/** 显示多长时间 默认0 不会消失 */ +@property (nonatomic, assign) NSTimeInterval showTime; +/** 自定view圆角方向设置 默认UIRectCornerAllCorners 当cornerRadius>0时生效*/ +@property (nonatomic, assign) UIRectCorner rectCorners; +/** 自定义view圆角大小 */ +@property (nonatomic, assign) CGFloat cornerRadius; +/** 弹出震动反馈 默认NO iOS10+ 系统才有此效果 */ +@property (nonatomic, assign) BOOL isImpactFeedback; + +//************ 群组相关属性 **************** +/** 群组标识 统一给弹窗编队 方便独立管理 默认为nil,统一全局处理 */ +@property (nullable,nonatomic,strong) NSString *groupId; +/** 是否堆叠 默认NO 如果是YES priority优先级不生效*/ +@property (nonatomic,assign) BOOL isStack; +/** 单显示 默认NO 只会显示优先级最高的popView */ +@property (nonatomic, assign) BOOL isSingle; +/** 优先级 范围0~1000 (默认0,遵循先进先出) isStack和isSingle为NO的时候生效 */ +@property (nonatomic, assign) CGFloat priority; +//**************************************** + +//************ 拖拽手势相关属性 **************** +/** 拖拽方向 默认 不可拖拽 */ +@property (nonatomic, assign) LSTDragStyle dragStyle; +/** X轴或者Y轴拖拽移除临界距离 范围(0 ~ +∞) 默认0 不拖拽移除 基使用于dragStyle */ +@property (nonatomic, assign) CGFloat dragDistance; +/** 拖拽移除动画类型 默认同dismissStyle */ +@property (nonatomic, assign) LSTDismissStyle dragDismissStyle; +/** 拖拽消失动画时间 默认同 dismissDuration */ +@property (nonatomic, assign) NSTimeInterval dragDismissDuration; +/** 拖拽复原动画时间 默认0.25s */ +@property (nonatomic, assign) NSTimeInterval dragReboundTime; + +/** 轻扫方向 默认 不可轻扫 前提开启dragStyle */ +@property (nonatomic, assign) LSTSweepStyle sweepStyle; +/** 轻扫速率 控制轻扫移除 默认1000 基于使用sweepStyle */ +@property (nonatomic, assign) CGFloat swipeVelocity; +/** 轻扫移除的动画 默认LSTSweepDismissStyleVelocity */ +@property (nonatomic, assign) LSTSweepDismissStyle sweepDismissStyle; + +//@property (nonatomic, strong) NSArray *xDragDistances;//待计划 +//@property (nonatomic, strong) NSArray *yDragDistances;//待计划 + +//**************************************** + +/** 点击背景 */ +@property (nullable, nonatomic, copy) void(^bgClickBlock)(void); +/** 长按背景 */ +@property (nullable, nonatomic, copy) void(^bgLongPressBlock)(void); + +/** 弹窗pan手势偏移量 */ +@property (nullable, nonatomic, copy) void(^panOffsetBlock)(CGPoint offset); + + +//以下键盘弹出/收起 第三方键盘会多次回调(百度,搜狗测试得出), 原生键盘回调一次 +/** 键盘将要弹出 */ +@property (nullable, nonatomic, copy) void(^keyboardWillShowBlock)(void); +/** 键盘弹出完毕 */ +@property (nullable, nonatomic, copy) void(^keyboardDidShowBlock)(void); +/** 键盘frame将要改变 */ +@property (nullable, nonatomic, copy) void(^keyboardFrameWillChangeBlock)(CGRect beginFrame,CGRect endFrame,CGFloat duration); +/** 键盘frame改变完毕 */ +@property (nullable, nonatomic, copy) void(^keyboardFrameDidChangeBlock)(CGRect beginFrame,CGRect endFrame,CGFloat duration); +/** 键盘将要收起 */ +@property (nullable, nonatomic, copy) void(^keyboardWillHideBlock)(void); +/** 键盘收起完毕 */ +@property (nullable, nonatomic, copy) void(^keyboardDidHideBlock)(void); + +//************ 生命周期回调(Block) ************ +/** 将要显示 回调 */ +@property (nullable, nonatomic, copy) void(^popViewWillPopBlock)(void); +/** 已经显示完毕 回调 */ +@property (nullable, nonatomic, copy) void(^popViewDidPopBlock)(void); +/** 将要开始移除 回调 */ +@property (nullable, nonatomic, copy) void(^popViewWillDismissBlock)(void); +/** 已经移除完毕 回调 */ +@property (nullable, nonatomic, copy) void(^popViewDidDismissBlock)(void); +/** 倒计时 回调 */ +@property (nullable, nonatomic, copy) void(^popViewCountDownBlock)(LSTPopView *popView,NSTimeInterval timeInterval); +//******************************************** + + +/* + 以下是构建方法 + customView: 已定义view + popStyle: 弹出动画 + dismissStyle: 移除动画 + parentView: 弹窗父容器 + */ ++ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView; + ++ (nullable instancetype)initWithCustomView:(UIView *)customView + popStyle:(LSTPopStyle)popStyle + dismissStyle:(LSTDismissStyle)dismissStyle; + ++ (nullable instancetype)initWithCustomView:(UIView *)customView + parentView:(UIView *_Nullable)parentView + popStyle:(LSTPopStyle)popStyle + dismissStyle:(LSTDismissStyle)dismissStyle; +/* + 以下是弹出方法 + popStyle: 弹出动画 优先级大于全局的popStyle 局部起作用 + duration: 弹出时间 优先级大于全局的popDuration 局部起作用 +*/ +- (void)pop; +- (void)popWithStyle:(LSTPopStyle)popStyle; +- (void)popWithDuration:(NSTimeInterval)duration; +- (void)popWithStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration; + + +/* + 以下是弹出方法 + dismissStyle: 弹出动画 优先级大于全局的dismissStyle 局部起作用 + duration: 弹出时间 优先级大于全局的dismissDuration 局部起作用 +*/ +- (void)dismiss; +- (void)dismissWithStyle:(LSTDismissStyle)dismissStyle; +- (void)dismissWithDuration:(NSTimeInterval)duration; +- (void)dismissWithStyle:(LSTDismissStyle)dismissStyle duration:(NSTimeInterval)duration; + + +/** 删除指定代理 */ +- (void)removeForDelegate:(id)delegate; +/** 删除代理池 删除所有代理 */ +- (void)removeAllDelegate; + + + +#pragma mark - ***** 以下是 窗口管理api ***** + +/** 获取全局(整个app内)所有popView */ ++ (NSArray *)getAllPopView; +/** 获取当前页面所有popView */ ++ (NSArray *)getAllPopViewForParentView:(UIView *)parentView; +/** 获取当前页面指定编队的所有popView */ ++ (NSArray *)getAllPopViewForPopView:(UIView *)popView; +/** + 读取popView (有可能会跨编队读取弹窗) + 建议使用getPopViewForGroupId:forkey: 方法进行精确读取 + */ ++ (LSTPopView *)getPopViewForKey:(NSString *)key; +/** 移除popView */ ++ (void)removePopView:(LSTPopView *)popView; +/** + 移除popView 通过唯一key (有可能会跨编队误删弹窗) + 建议使用removePopViewForGroupId:forkey: 方法进行精确删除 +*/ ++ (void)removePopViewForKey:(NSString *)key; +/** 移除所有popView */ ++ (void)removeAllPopView; +/** 移除 最后一个弹出的 popView */ ++ (void)removeLastPopView; + + +/** 开启调试view 建议设置成 线上隐藏 测试打开 */ ++ (void)setLogStyle:(LSTPopViewLogStyle)logStyle; + + +@end + + + + +NS_ASSUME_NONNULL_END diff --git a/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.m b/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.m new file mode 100644 index 0000000..ea76039 --- /dev/null +++ b/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.m @@ -0,0 +1,1775 @@ +// +// LSTPopView.m +// LoSenTrad +// +// Created by LoSenTrad on 2020/2/22. +// + +#import "LSTPopView.h" +#import +#import "LSTTimer.h" + + + +static NSString *const LSTPopViewLogTitle = @"LSTPopView日志 ---> :"; +static LSTPopViewLogStyle _logStyle; + + +@interface LSTPopViewManager : NSObject + +/** 单例 */ +LSTPopViewManager *LSTPopViewM(void); + +@end + +@interface LSTPopViewManager () + +/** 储存已经展示popView */ +@property (nonatomic,strong) NSMutableArray *popViewMarr; +/** 按顺序弹窗顺序存储已显示的 popview */ +@property (nonatomic,strong) NSPointerArray *showList; +/** 储存待移除的popView */ +@property (nonatomic,strong) NSHashTable *removeList; +/** 内存信息View */ +@property (nonatomic,strong) UILabel *infoView; + +@end + +@implementation LSTPopViewManager + +static LSTPopViewManager *_instance; + +LSTPopViewManager *LSTPopViewM() { + return [LSTPopViewManager sharedInstance]; +} + ++ (instancetype)sharedInstance { + if (!_instance) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _instance = [[self alloc] init]; + }); + } + return _instance; +} + ++ (id)allocWithZone:(struct _NSZone *)zone { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _instance = [super allocWithZone:zone]; + }); + return _instance; +} + ++ (NSArray *)getAllPopView { + return LSTPopViewM().popViewMarr; +} +/** 获取当前页面所有popView */ ++ (NSArray *)getAllPopViewForParentView:(UIView *)parentView { + NSMutableArray *mArr = LSTPopViewM().popViewMarr; + NSMutableArray *resMarr = [NSMutableArray array]; + for (id obj in mArr) { + LSTPopView *popView = (LSTPopView *)obj; + if ([popView.parentView isEqual:parentView]) { + [resMarr addObject:obj]; + } + } + return [NSArray arrayWithArray:resMarr]; +} + +/** 获取当前页面指定编队的所有popView */ ++ (NSArray *)getAllPopViewForPopView:(LSTPopView *)popView { + NSArray *mArr = [self getAllPopViewForParentView:popView.parentView]; + NSMutableArray *resMarr = [NSMutableArray array]; + for (id obj in mArr) { + LSTPopView *tPopView = (LSTPopView *)obj; + + if (popView.groupId == nil && tPopView.groupId == nil) { + [resMarr addObject:obj]; + continue; + } + if ([tPopView.groupId isEqual:popView.groupId]) { + [resMarr addObject:obj]; + continue; + } + } + return [NSArray arrayWithArray:resMarr]; +} + +/** 读取popView */ ++ (LSTPopView *)getPopViewForKey:(NSString *)key { + if (key.length<=0) { return nil; } + NSMutableArray *mArr = LSTPopViewM().popViewMarr; + for (id obj in mArr) { + LSTPopView *popView = (LSTPopView *)obj; + if ([popView.identifier isEqualToString:key]) { + return popView; + } + } + return nil; +} + ++ (void)savePopView:(LSTPopView *)popView { + [LSTPopViewM().popViewMarr addObject:popView]; + + //优先级排序 + [self sortingArr]; + + if (_logStyle & LSTPopViewLogStyleWindow) { + [self setInfoData]; + } + if (_logStyle & LSTPopViewLogStyleConsole) { + [self setConsoleLog]; + } +} + +/** 移除popView */ ++ (void)removePopView:(LSTPopView *)popView { + if (!popView) { return; } + NSArray *arr = LSTPopViewM().popViewMarr; + for (id obj in arr) { + LSTPopView *tPopView = (LSTPopView *)obj; + + if ([tPopView isEqual:popView]) { +// [LSTPopViewM().popViewMarr removeObject:obj]; + [tPopView dismissWithStyle:LSTDismissStyleNO]; + break; + } + } + + if (_logStyle & LSTPopViewLogStyleWindow) { + [self setInfoData]; + } + if (_logStyle & LSTPopViewLogStyleConsole) { + [self setConsoleLog]; + } +} + +/** 移除popView */ ++ (void)removePopViewForKey:(NSString *)key { + if (key.length<=0) { return; } + NSArray *arr = LSTPopViewM().popViewMarr; + for (id obj in arr) { + LSTPopView *tPopView = (LSTPopView *)obj; + + if ([tPopView.identifier isEqualToString:key]) { +// [LSTPopViewM().popViewMarr removeObject:obj]; + [tPopView dismissWithStyle:LSTDismissStyleNO]; + break; + } + } + if (_logStyle & LSTPopViewLogStyleWindow) { + [self setInfoData]; + } + if (_logStyle & LSTPopViewLogStyleConsole) { + [self setConsoleLog]; + } +} +/** 移除所有popView */ ++ (void)removeAllPopView { + NSMutableArray *arr = LSTPopViewM().popViewMarr; + if (arr.count<=0) { return; } + + NSArray *popViewMarr = [NSArray arrayWithArray:LSTPopViewM().popViewMarr]; + + [popViewMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + LSTPopView *tPopView = (LSTPopView *)obj; + + [tPopView dismissWithStyle:LSTDismissStyleNO]; + }]; + + if (_logStyle & LSTPopViewLogStyleWindow) { + [self setInfoData]; + } + if (_logStyle & LSTPopViewLogStyleConsole) { + [self setConsoleLog]; + } +} + ++ (void)removeLastPopView { + NSPointerArray *showList = LSTPopViewM().showList; + for (NSInteger i = showList.count - 1; i >= 0; i --) { + LSTPopView *popView = [showList pointerAtIndex:i]; + if (popView) { + [self removePopView:popView]; + [showList addPointer:NULL]; + [showList compact]; + break; + } + } +} + +#pragma mark - ***** Other 其他 ***** + ++ (void)setInfoData { + LSTPopViewM().infoView.text = [NSString stringWithFormat:@"S:%zd R:%zd",LSTPopViewM().popViewMarr.count,LSTPopViewM().removeList.allObjects.count]; +} + ++ (void)setConsoleLog { + LSTPVLog(@"%@ S:%zd个 R:%zd个",LSTPopViewLogTitle,LSTPopViewM().popViewMarr.count,LSTPopViewM().removeList.allObjects.count); +} + +//冒泡排序 ++ (void)sortingArr { + NSMutableArray *arr = LSTPopViewM().popViewMarr; + for (int i = 0; i < arr.count; i++) { + for (int j = i+1; j < arr.count; j++) { + LSTPopView *iPopView = (LSTPopView *)arr[i]; + + LSTPopView *jPopView = (LSTPopView *)arr[j]; + + if (iPopView.priority > jPopView.priority) { + [arr exchangeObjectAtIndex:i withObjectAtIndex:j]; + } + } + } +} + +/** 转移popView到待移除队列 */ ++ (void)transferredToRemoveQueueWithPopView:(LSTPopView *)popView { + NSArray *popViewMarr = LSTPopViewM().popViewMarr; + + [popViewMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + LSTPopView *tPopView = (LSTPopView *)obj; + + if ([popView isEqual:tPopView]) { + [LSTPopViewM().removeList addObject:obj]; + [LSTPopViewM().popViewMarr removeObject:obj]; + } + }]; +} + ++ (void)destroyInRemoveQueue:(LSTPopView *)popView { + if (LSTPopViewM().removeList.allObjects.count <= 0) { + [self transferredToRemoveQueueWithPopView:popView]; + } + + if (_logStyle&LSTPopViewLogStyleWindow) { + [self setInfoData]; + } + if (_logStyle&LSTPopViewLogStyleConsole) { + [self setConsoleLog]; + } +} + +#pragma mark - ***** 懒加载 ***** + +- (UILabel *)infoView { + if(_infoView) return _infoView; + _infoView = [[UILabel alloc] init]; + _infoView.backgroundColor = UIColor.orangeColor; + _infoView.textAlignment = NSTextAlignmentCenter; + _infoView.font = [UIFont systemFontOfSize:11]; + _infoView.frame = CGRectMake(pv_ScreenWidth()-70, pv_IsIphoneX_ALL()? 40:20, 60, 10); + _infoView.layer.cornerRadius = 1; + _infoView.layer.masksToBounds = YES; + UIView *superView = [UIApplication sharedApplication].keyWindow; + [superView addSubview:_infoView]; + return _infoView; +} + +- (NSMutableArray *)popViewMarr { + if(_popViewMarr) return _popViewMarr; + _popViewMarr = [NSMutableArray array]; + return _popViewMarr; +} + +- (NSHashTable *)removeList { + if (_removeList) return _removeList; + _removeList = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]; + return _removeList; +} + +- (NSPointerArray *)showList { + if (_showList) return _showList; + _showList = [NSPointerArray pointerArrayWithOptions:(NSPointerFunctionsWeakMemory)]; + return _showList; +} + +@end + + +static const NSTimeInterval LSTPopViewDefaultDuration = -1.0f; +// 角度转弧度 +#define LST_DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI) + + +@interface LSTPopViewBgView : UIView + +/** 是否隐藏背景 默认NO */ +@property (nonatomic, assign) BOOL isHideBg; + +@end + +@implementation LSTPopViewBgView + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ + UIView *hitView = [super hitTest:point withEvent:event]; + if(hitView == self && self.isHideBg){ + return nil; + } + return hitView; +} + +@end + +@interface LSTPopView () + +/** 弹窗容器 默认是app UIWindow 可指定view作为容器 */ +@property (nonatomic, weak) UIView *container; +/** 背景层 */ +@property (nonatomic, strong) LSTPopViewBgView *backgroundView; +/** 自定义视图 */ +@property (nonatomic,strong) UIView *customView; +/** 规避键盘偏移量 */ +@property (nonatomic, assign) CGFloat avoidKeyboardOffset; +/** 代理池 */ +@property (nonatomic, strong) NSHashTable > *delegates; +/** 背景点击手势 */ +@property (nonatomic, strong) UITapGestureRecognizer *tapGesture; +/** 自定义View滑动手势 */ +@property (nonatomic, strong) UIPanGestureRecognizer *panGesture; +//当前正在拖拽的是否是tableView +@property (nonatomic, assign) BOOL isDragScrollView; +/** 标记popView中是否有UIScrollView, UITableView, UICollectionView */ +@property (nonatomic, weak) UIScrollView *scrollerView; +/** 记录自定义view原始Frame */ +@property (nonatomic, assign) CGRect originFrame; +/** 标记dragDismissStyle是否被复制 */ +@property (nonatomic, assign) BOOL isDragDismissStyle; +/** 是否弹出键盘 */ +@property (nonatomic,assign,readonly) BOOL isShowKeyboard; +/** 弹出键盘的高度 */ +@property (nonatomic, assign) CGFloat keyboardY; + +@end + +@implementation LSTPopView + + +#pragma mark - ***** 初始化 ***** + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self initSubViews]; + } + return self; +} + +- (void)initSubViews { + //初始化配置 + _isClickBgDismiss = NO; + _isObserverScreenRotation = YES; + _bgAlpha = 0.25; + _popStyle = LSTPopStyleFade; + _dismissStyle = LSTDismissStyleFade; + _popDuration = LSTPopViewDefaultDuration; + _dismissDuration = LSTPopViewDefaultDuration; + _hemStyle = LSTHemStyleCenter; + _adjustX = 0; + _adjustY = 0; + _isClickFeedback = NO; + _isAvoidKeyboard = YES; + _avoidKeyboardSpace = 10; + _bgColor = [UIColor blackColor]; + _identifier = @""; + _isShowKeyboard = NO; + _showTime = 0.0; + _priority = 0; + _isHideBg = NO; + _isShowKeyboard = NO; + _isImpactFeedback = NO; + _rectCorners = UIRectCornerAllCorners; + + _isSingle = NO; + + //拖拽相关属性初始化 + _dragStyle = LSTDragStyleNO; + _dragDismissStyle = LSTDismissStyleNO; + _dragDistance = 0.0f; + _dragReboundTime = 0.25; + _dragDismissDuration = LSTPopViewDefaultDuration; + _swipeVelocity = 1000.0f; + + _isDragDismissStyle = NO; +} + ++ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView { + return [self initWithCustomView:customView popStyle:LSTPopStyleNO dismissStyle:LSTDismissStyleNO]; +} + + ++ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView + popStyle:(LSTPopStyle)popStyle + dismissStyle:(LSTDismissStyle)dismissStyle { + + return [self initWithCustomView:customView + parentView:nil + popStyle:popStyle + dismissStyle:dismissStyle]; +} + ++ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView + parentView:(UIView *)parentView + popStyle:(LSTPopStyle)popStyle + dismissStyle:(LSTDismissStyle)dismissStyle { + // 检测自定义视图是否存在(check customView is exist) + if (!customView) { return nil; } + if (![parentView isKindOfClass:[UIView class]] && parentView != nil) { + LSTPVLog(@"parentView is error !!!"); + return nil; + } + + CGRect popViewFrame = CGRectZero; + if (parentView) { + popViewFrame = parentView.bounds; + } else { + popViewFrame = CGRectMake(0, 0, pv_ScreenWidth(), pv_ScreenHeight()); + } + + LSTPopView *popView = [[LSTPopView alloc] initWithFrame:popViewFrame]; + popView.backgroundColor = [UIColor clearColor]; + + popView.container = parentView? parentView : [UIApplication sharedApplication].keyWindow; + + popView.customView = customView; + popView.backgroundView = [[LSTPopViewBgView alloc] initWithFrame:popView.bounds]; + popView.backgroundView.backgroundColor = [UIColor clearColor]; + popView.popStyle = popStyle; + popView.dismissStyle = dismissStyle; + + [popView addSubview:popView.backgroundView]; + [popView.backgroundView addSubview:customView]; + + //背景添加手势 + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:popView action:@selector(popViewBgViewTap:)]; + tap.delegate = popView; + popView.tapGesture = tap; + [popView.backgroundView addGestureRecognizer:tap]; + + //添加拖拽手势 + popView.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:popView action:@selector(pan:)]; + popView.panGesture.delegate = popView; + [popView.customView addGestureRecognizer:popView.panGesture]; + + // [popView.backgroundView addTarget:popView action:@selector(popViewBgViewTap:) forControlEvents:UIControlEventTouchUpInside];; + + + // UILongPressGestureRecognizer *customViewLP = [[UILongPressGestureRecognizer alloc] initWithTarget:popView action:@selector(bgLongPressEvent:)]; + // [popView.backgroundView addGestureRecognizer:customViewLP]; + + // UITapGestureRecognizer *customViewTap = [[UITapGestureRecognizer alloc] initWithTarget:popView action:@selector(customViewClickEvent:)]; + // [popView.customView addGestureRecognizer:customViewTap]; + + //键盘将要显示 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:nil]; + //键盘显示完毕 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(keyboardDidShow:) + name:UIKeyboardDidShowNotification + object:nil]; + //键盘frame将要改变 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(keyboardWillChangeFrame:) + name:UIKeyboardWillChangeFrameNotification + object:nil]; + //键盘frame改变完毕 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(keyboardDidChangeFrame:) + name:UIKeyboardDidChangeFrameNotification + object:nil]; + //键盘将要收起 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; + //键盘收起完毕 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(keyboardDidHide:) + name:UIKeyboardDidHideNotification + object:nil]; + //屏幕旋转 + [[NSNotificationCenter defaultCenter] addObserver:popView + selector:@selector(statusBarOrientationChange:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; + //监听customView frame + [popView.customView addObserver:popView + forKeyPath:@"frame" + options:NSKeyValueObservingOptionOld + context:NULL]; + return popView; +} + +- (void)dealloc { + [self.customView removeObserver:self forKeyPath:@"frame"]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + //从待移除队列中销毁 + [LSTPopViewManager destroyInRemoveQueue:self]; + [self lst_PopViewDidDismissForPopView:self]; + self.popViewDidDismissBlock? self.popViewDidDismissBlock():nil; +} + +- (void)removeFromSuperview { + + [super removeFromSuperview]; + + [LSTPopViewManager transferredToRemoveQueueWithPopView:self]; +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + UIView *hitView = [super hitTest:point withEvent:event]; + if (hitView != self.customView) { + if(hitView == self && self.isHideBg){ return nil; } + } + return hitView; +} + +#pragma mark - ***** 代理方法 ***** +- (void)lst_PopViewBgClickForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewBgClickForPopView:popView]; + } + } +} + +- (void)lst_PopViewBgLongPressForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewBgLongPressForPopView:popView]; + } + } +} + +- (void)lst_PopViewWillPopForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewWillPopForPopView:popView]; + } + } +} + +- (void)lst_PopViewDidPopForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewDidPopForPopView:popView]; + } + } +} + +- (void)lst_PopViewCountDownForPopView:(LSTPopView *)popView forCountDown:(NSTimeInterval)timeInterval { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewCountDownForPopView:popView forCountDown:timeInterval]; + } + } +} + +- (void)lst_PopViewCountDownFinishForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewCountDownFinishForPopView:popView]; + } + } +} + +- (void)lst_PopViewWillDismissForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewWillDismissForPopView:popView]; + } + } +} + +- (void)lst_PopViewDidDismissForPopView:(LSTPopView *)popView { + for (id delegate in _delegates.copy) { + if ([delegate respondsToSelector:_cmd]) { + [delegate lst_PopViewDidDismissForPopView:popView]; + } + } +} + +#pragma mark - ***** 界面布局 ***** + +- (void)setCustomViewFrameWithHeight:(CGFloat)height { + + CGFloat changeY = 0; + switch (self.hemStyle) { + case LSTHemStyleTop ://贴顶 + { + self.customView.pv_X = _backgroundView.pv_CenterX - _customView.pv_Size.width*0.5 + _adjustX; + self.customView.pv_Y = _adjustY; + changeY = _adjustY; + } + break; + case LSTHemStyleLeft ://贴左 + { + self.customView.pv_X = _adjustX; + self.customView.pv_Y = _backgroundView.pv_CenterY - _customView.pv_Size.height*0.5 + _adjustY; + changeY = height*0.5; + } + break; + case LSTHemStyleBottom ://贴底 + { + self.customView.pv_X = _backgroundView.pv_CenterX - _customView.pv_Size.width*0.5 + _adjustX; + [self.customView layoutIfNeeded]; + self.customView.pv_Y = _backgroundView.pv_Height - _customView.pv_Height + _adjustY; + changeY = height; + } + break; + case LSTHemStyleRight ://贴右 + { + self.customView.pv_X = _backgroundView.pv_Width - _customView.pv_Width + _adjustX; + self.customView.pv_Y = _backgroundView.pv_CenterY - _customView.pv_Size.height*0.5 + _adjustY; + changeY = height*0.5; + } + break; + case LSTHemStyleTopLeft :///贴顶和左 + { + self.customView.pv_X = _adjustX; + self.customView.pv_Y = _adjustY; + changeY = _adjustY; + } + break; + case LSTHemStyleBottomLeft ://贴底和左 + { + self.customView.pv_X = _adjustX; + [self.customView layoutIfNeeded]; + self.customView.pv_Y = _backgroundView.pv_Height - _customView.pv_Height + _adjustY; + changeY = height; + } + break; + case LSTHemStyleBottomRight ://贴底和右 + { + self.customView.pv_X = _backgroundView.pv_Width - _customView.pv_Width + _adjustX; + [self.customView layoutIfNeeded]; + self.customView.pv_Y = _backgroundView.pv_Height - _customView.pv_Height + _adjustY; + changeY = height; + } + break; + case LSTHemStyleTopRight ://贴顶和右 + { + self.customView.pv_X = _backgroundView.pv_Width - _customView.pv_Width + _adjustX; + self.customView.pv_Y = _adjustY; + changeY = _adjustY; + } + break; + default://居中 + { + self.customView.pv_X = _backgroundView.pv_CenterX - _customView.pv_Size.width*0.5 + _adjustX; + self.customView.pv_Y = _backgroundView.pv_CenterY - _customView.pv_Size.height*0.5 + _adjustY; + changeY = height*0.5; + } + break; + } + + CGFloat originBottom = _originFrame.origin.y + _originFrame.size.height + _avoidKeyboardSpace; + if (_isShowKeyboard && (originBottom > _keyboardY)) {//键盘已经显示 + CGFloat Y = _keyboardY - _customView.pv_Height - _avoidKeyboardSpace; + _customView.pv_Y = Y; + CGRect newFrame = _originFrame; + newFrame.origin.y = newFrame.origin.y - changeY; + newFrame.size = CGSizeMake(_originFrame.size.width, _customView.pv_Height); + self.originFrame = newFrame; + }else {//没有键盘显示 + self.originFrame = _customView.frame; + } + + [self setCustomViewCorners]; +} + +- (void)setCustomViewCorners { + + BOOL isSetCorner = NO; + + if (self.rectCorners & UIRectCornerTopLeft) { + isSetCorner = YES; + } + if (self.rectCorners & UIRectCornerTopRight) { + isSetCorner = YES; + } + if (self.rectCorners & UIRectCornerBottomLeft) { + isSetCorner = YES; + } + if (self.rectCorners & UIRectCornerBottomRight) { + isSetCorner = YES; + } + if (self.rectCorners & UIRectCornerAllCorners) { + isSetCorner = YES; + } + + if (isSetCorner && self.cornerRadius>0) { + UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.customView.bounds byRoundingCorners:self.rectCorners cornerRadii:CGSizeMake(self.cornerRadius, self.cornerRadius)]; + + CAShapeLayer * layer = [[CAShapeLayer alloc]init]; + layer.frame = self.customView.bounds; + layer.path = path.CGPath; + self.customView.layer.mask = layer; + } + +} + +#pragma mark - ***** setter 设置器/数据处理 ***** + +- (void)setPopDuration:(NSTimeInterval)popDuration { + if (popDuration <= 0.0) { return; } + _popDuration = popDuration; +} + +- (void)setDismissDuration:(NSTimeInterval)dismissDuration { + if (dismissDuration <= 0.0) { return; } + _dismissDuration = dismissDuration; +} + +- (void)setDragDismissDuration:(NSTimeInterval)dragDismissDuration { + if (dragDismissDuration <= 0.0) { return; } + _dragDismissDuration = dragDismissDuration; +} + +- (void)setHemStyle:(LSTHemStyle)hemStyle { + _hemStyle = hemStyle; +} + +- (void)setAdjustX:(CGFloat)adjustX { + _adjustX = adjustX; +// self.customView.x = _customView.x + adjustX; +// self.originFrame = _customView.frame; + [self setCustomViewFrameWithHeight:0]; +} + +- (void)setAdjustY:(CGFloat)adjustY { + _adjustY = adjustY; +// self.customView.y = _customView.y + adjustY; +// self.originFrame = _customView.frame; + [self setCustomViewFrameWithHeight:0]; +} + +- (void)setIsObserverScreenRotation:(BOOL)isObserverScreenRotation { + _isObserverScreenRotation = isObserverScreenRotation; +} + +- (void)setBgAlpha:(CGFloat)bgAlpha { + _bgAlpha = (bgAlpha <= 0.0f) ? 0.0f : ((bgAlpha > 1.0) ? 1.0 : bgAlpha); + } + +- (void)setIsClickFeedback:(BOOL)isClickFeedback { + _isClickFeedback = isClickFeedback; +} + +- (void)setIsHideBg:(BOOL)isHideBg { + _isHideBg = isHideBg; + self.backgroundView.isHideBg = isHideBg; + self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; +} + +- (void)setShowTime:(NSTimeInterval)showTime { + _showTime = showTime; +} + +- (void)setDelegate:(id)delegate { + if ([self.delegates containsObject:delegate]) return; + [self.delegates addObject:delegate]; +} + +- (void)setDragDismissStyle:(LSTDismissStyle)dragDismissStyle { + _dragDismissStyle = dragDismissStyle; + self.isDragDismissStyle = YES; +} + +#pragma mark - ***** pop 弹出 ***** +- (void)pop { + [self popWithStyle:self.popStyle duration:self.popDuration]; +} + +- (void)popWithStyle:(LSTPopStyle)popStyle { + [self popWithStyle:popStyle duration:self.popDuration]; +} + +- (void)popWithDuration:(NSTimeInterval)duration { + [self popWithStyle:self.popStyle duration:duration]; +} + +- (void)popWithStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration { + [self popWithPopStyle:popStyle duration:duration isOutStack:NO]; +} + +- (void)popWithPopStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration isOutStack:(BOOL)isOutStack { + + NSTimeInterval resDuration = [self getPopDuration:duration]; + + [self setCustomViewFrameWithHeight:0]; + + self.originFrame = self.customView.frame; + + BOOL startTimer = NO; + + if (self.isSingle) {//单显 + NSArray *popViewArr = [LSTPopViewManager getAllPopViewForPopView:self]; + for (id obj in popViewArr) {//移除所有popView和移除定a时器 + LSTPopView *lastPopView = (LSTPopView *)obj; + + [lastPopView dismissWithDismissStyle:LSTDismissStyleNO duration:0.2 isRemove:YES]; + } + startTimer = YES; + }else {//多显 + if (!isOutStack) {//处理隐藏倒数第二个popView + NSArray *popViewArr = [LSTPopViewManager getAllPopViewForPopView:self]; + if (popViewArr.count >= 1) { + id obj = popViewArr[popViewArr.count - 1]; + LSTPopView *lastPopView = (LSTPopView *)obj; + + if (self.isStack) {//堆叠显示 + startTimer = YES; + }else { + if (self.priority >= lastPopView.priority) {//置顶显示 + if (lastPopView.isShowKeyboard) { + [lastPopView endEditing:YES]; + } + [lastPopView dismissWithDismissStyle:LSTDismissStyleFade duration:0.2 isRemove:NO]; + startTimer = YES; + } else {//隐藏显示 + if (!self.parentView) { + self.container = [UIApplication sharedApplication].keyWindow; + } + [LSTPopViewManager savePopView:self]; + return; + } + } + } else { + startTimer = YES; + } + } + } + +// if (!isOutStack){ +// [self.parentView addSubview:self]; +// } + if (!self.superview) { + [self.container addSubview:self]; + [LSTPopViewM().showList addPointer:(__bridge void * _Nullable)self]; + } + + if (!isOutStack){ + [self lst_PopViewWillPopForPopView:self]; + + self.popViewWillPopBlock? self.popViewWillPopBlock():nil; + } + //动画处理 + [self popAnimationWithPopStyle:popStyle duration:resDuration]; + //震动反馈 + [self beginImpactFeedback]; + + LSTPopViewWK(self);; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(resDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + if (!isOutStack){ + [self lst_PopViewDidPopForPopView:self]; + wk_self.popViewDidPopBlock? wk_self.popViewDidPopBlock():nil; + } + if (startTimer){ [self startTimer]; } + }); + + //保存popView + if (!isOutStack) { [LSTPopViewManager savePopView:self]; } +} + +- (void)popAnimationWithPopStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration { + + LSTPopViewWK(self); + if (popStyle == LSTPopStyleFade) {//渐变出现 + self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + self.customView.alpha = 0.0f; + [UIView animateWithDuration:0.2 animations:^{ + self.backgroundView.backgroundColor =[self getNewColorWith:self.bgColor alpha:self.bgAlpha]; + self.customView.alpha = 1.0f; + }]; + } else if (popStyle == LSTPopStyleNO){//无动画 + self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + [UIView animateWithDuration:0.1 animations:^{ + self.backgroundView.backgroundColor =[self getNewColorWith:self.bgColor alpha:self.bgAlpha]; + }]; + self.customView.alpha = 1.0f; + } else {//有动画 + self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + [UIView animateWithDuration:duration animations:^{ + wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:self.bgAlpha]; + }]; + //自定义view过渡动画 + [self hanlePopAnimationWithDuration:duration popStyle:popStyle]; + } +} + +- (void)hanlePopAnimationWithDuration:(NSTimeInterval)duration + popStyle:(LSTPopStyle)popStyle { + + self.alpha = 0; + [UIView animateWithDuration:duration*0.2 animations:^{ + self.alpha = 1; + }]; + + LSTPopViewWK(self); + switch (popStyle) { + case LSTPopStyleScale:// < 缩放动画,先放大,后恢复至原大小 + { + [self animationWithLayer:_customView.layer duration:((0.3*duration)/0.7) values:@[@0.0, @1.2, @1.0]]; // 另外一组动画值(the other animation values) @[@0.0, @1.2, @0.9, @1.0] + } + break; + case LSTPopStyleSmoothFromTop: + case LSTPopStyleSmoothFromBottom: + case LSTPopStyleSmoothFromLeft: + case LSTPopStyleSmoothFromRight: + case LSTPopStyleSpringFromTop: + case LSTPopStyleSpringFromLeft: + case LSTPopStyleSpringFromBottom: + case LSTPopStyleSpringFromRight: + { + CGPoint startPosition = self.customView.layer.position; + if (popStyle == LSTPopStyleSmoothFromTop || popStyle == LSTPopStyleSpringFromTop) { + self.customView.layer.position = CGPointMake(startPosition.x, -_customView.pv_Height*0.5); + + } else if (popStyle == LSTPopStyleSmoothFromLeft || popStyle == LSTPopStyleSpringFromLeft) { + self.customView.layer.position = CGPointMake(-_customView.pv_Width*0.5, startPosition.y); + + } else if (popStyle == LSTPopStyleSmoothFromBottom || popStyle == LSTPopStyleSpringFromBottom) { + self.customView.layer.position = CGPointMake(startPosition.x, CGRectGetMaxY(self.frame) + _customView.pv_Height*0.5); + + } else { + self.customView.layer.position = CGPointMake(CGRectGetMaxX(self.frame) + _customView.pv_Width*0.5 , startPosition.y); + } + + CGFloat damping = 1.0; + if (popStyle == LSTPopStyleSpringFromTop|| + popStyle == LSTPopStyleSpringFromLeft|| + popStyle == LSTPopStyleSpringFromBottom|| + popStyle == LSTPopStyleSpringFromRight) { + damping = 0.65; + } + + [UIView animateWithDuration:duration + delay:0 + usingSpringWithDamping:damping + initialSpringVelocity:1.0 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + + wk_self.customView.layer.position = startPosition; + } completion:nil]; + } + break; + case LSTPopStyleCardDropFromLeft: + case LSTPopStyleCardDropFromRight: + { + CGPoint startPosition = self.customView.layer.position; + if (popStyle == LSTPopStyleCardDropFromLeft) { + self.customView.layer.position = CGPointMake(startPosition.x * 1.0, -_customView.pv_Height*0.5); + self.customView.transform = CGAffineTransformMakeRotation(LST_DEGREES_TO_RADIANS(15.0)); + } else { + self.customView.layer.position = CGPointMake(startPosition.x * 1.0, -_customView.pv_Height*0.5); + self.customView.transform = CGAffineTransformMakeRotation(LST_DEGREES_TO_RADIANS(-15.0)); + } + + [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.75 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ + wk_self.customView.layer.position = startPosition; + } completion:nil]; + + [UIView animateWithDuration:duration*0.6 animations:^{ + wk_self.customView.layer.transform = CATransform3DMakeRotation(LST_DEGREES_TO_RADIANS((popStyle == LSTPopStyleCardDropFromRight) ? 5.5 : -5.5), 0, 0, 0); + } completion:^(BOOL finished) { + [UIView animateWithDuration:duration*0.2 animations:^{ + wk_self.customView.transform = CGAffineTransformMakeRotation(LST_DEGREES_TO_RADIANS((popStyle == LSTPopStyleCardDropFromRight) ? -1.0 : 1.0)); + } completion:^(BOOL finished) { + [UIView animateWithDuration:duration*0.2 animations:^{ + wk_self.customView.transform = CGAffineTransformMakeRotation(0.0); + } completion:nil]; + }]; + }]; + } + break; + default: + break; + } +} + +#pragma mark - ***** dismiss 移除 ***** + +- (void)dismiss { + [self dismissWithStyle:self.dismissStyle duration:self.dismissDuration]; +} + +- (void)dismissWithStyle:(LSTDismissStyle)dismissStyle { + [self dismissWithStyle:dismissStyle duration:self.dismissDuration]; +} + +- (void)dismissWithDuration:(NSTimeInterval)duration { + [self dismissWithStyle:self.dismissStyle duration:duration]; +} + +- (void)dismissWithStyle:(LSTDismissStyle)dismissStyle duration:(NSTimeInterval)duration { + [self dismissWithDismissStyle:dismissStyle duration:duration isRemove:YES]; +} + +- (void)dismissWithDismissStyle:(LSTDismissStyle)dismissStyle + duration:(NSTimeInterval)duration + isRemove:(BOOL)isRemove { + + NSTimeInterval resDuration = [self getDismissDuration:duration]; + + if (isRemove) { + //把当前popView转移到待移除队列 避免线程安全问题 + [LSTPopViewManager transferredToRemoveQueueWithPopView:self]; + } + + [self lst_PopViewWillDismissForPopView:self]; + + self.popViewWillDismissBlock? self.popViewWillDismissBlock():nil; + + LSTPopViewWK(self) + [self dismissAnimationWithDismissStyle:dismissStyle duration:resDuration]; + + if (!self.isSingle && (isRemove && [LSTPopViewManager getAllPopViewForPopView:self].count >= 1)){//多显 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(resDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + //popView出栈 + if (!self.isStack && [LSTPopViewManager getAllPopViewForPopView:self].count >= 1) { + NSArray *popViewArr = [LSTPopViewManager getAllPopViewForPopView:self]; + id obj = popViewArr[popViewArr.count-1]; + LSTPopView *tPopView = (LSTPopView *)obj; + if (!tPopView.superview) { + [tPopView.container addSubview:tPopView]; + [LSTPopViewM().showList addPointer:(__bridge void * _Nullable)tPopView]; + } + [tPopView popWithPopStyle:LSTPopStyleFade duration:0.25 isOutStack:YES]; + } + }); + } + if (isRemove) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(resDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [wk_self removeFromSuperview]; + }); + } +} + +- (void)dismissAnimationWithDismissStyle:(LSTDismissStyle)dismissStyle duration:(NSTimeInterval)duration { + + LSTPopViewWK(self); + if (dismissStyle == LSTPopStyleFade) { + [UIView animateWithDuration:0.2 animations:^{ + wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + wk_self.customView.alpha = 0.0f; + }]; + }else if (dismissStyle == LSTPopStyleNO){ + wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + wk_self.customView.alpha = 0.0f; + }else {//有动画 + [UIView animateWithDuration:duration*0.8 animations:^{ + wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + }]; + [self hanleDismissAnimationWithDuration:duration withDismissStyle:dismissStyle]; + } +} + +- (void)hanleDismissAnimationWithDuration:(NSTimeInterval)duration + withDismissStyle:(LSTDismissStyle)dismissStyle { + + [UIView animateWithDuration:duration*0.8 animations:^{ + self.alpha = 0; + }]; + + LSTPopViewWK(self);; + switch (dismissStyle) { + case LSTDismissStyleScale: + { + [self animationWithLayer:self.customView.layer duration:((0.2*duration)/0.8) values:@[@1.0, @0.66, @0.33, @0.01]]; + } + break; + case LSTDismissStyleSmoothToTop: + case LSTDismissStyleSmoothToBottom: + case LSTDismissStyleSmoothToLeft: + case LSTDismissStyleSmoothToRight: + { + CGPoint startPosition = self.customView.layer.position; + CGPoint endPosition = self.customView.layer.position; + if (dismissStyle == LSTDismissStyleSmoothToTop) { + endPosition = CGPointMake(startPosition.x, -(_customView.pv_Height*0.5)); + + } else if (dismissStyle == LSTDismissStyleSmoothToBottom) { + endPosition = CGPointMake(startPosition.x, CGRectGetMaxY(self.frame) + _customView.pv_Height*0.5); + + } else if (dismissStyle == LSTDismissStyleSmoothToLeft) { + endPosition = CGPointMake(-_customView.pv_Width*0.5, startPosition.y); + + } else { + endPosition = CGPointMake(CGRectGetMaxX(self.frame) + _customView.pv_Width*0.5, startPosition.y); + } + + [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + wk_self.customView.layer.position = endPosition; + } completion:nil]; + } + break; + case LSTDismissStyleCardDropToLeft: + case LSTDismissStyleCardDropToRight: + { + CGPoint startPosition = self.customView.layer.position; + BOOL isLandscape = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation); + __block CGFloat rotateEndY = 0.0f; + [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ + if (dismissStyle == LSTDismissStyleCardDropToLeft) { + wk_self.customView.transform = CGAffineTransformMakeRotation(M_1_PI * 0.75); + if (isLandscape) rotateEndY = fabs(wk_self.customView.frame.origin.y); + wk_self.customView.layer.position = CGPointMake(startPosition.x, CGRectGetMaxY(wk_self.frame) + startPosition.y + rotateEndY); + } else { + wk_self.customView.transform = CGAffineTransformMakeRotation(-M_1_PI * 0.75); + if (isLandscape) rotateEndY = fabs(wk_self.customView.frame.origin.y); + wk_self.customView.layer.position = CGPointMake(startPosition.x * 1.25, CGRectGetMaxY(wk_self.frame) + startPosition.y + rotateEndY); + } + } completion:nil]; + } + break; + case LSTDismissStyleCardDropToTop: + { + CGPoint startPosition = self.customView.layer.position; + CGPoint endPosition = CGPointMake(startPosition.x, -startPosition.y); + [UIView animateWithDuration:duration*0.2 animations:^{ + wk_self.customView.layer.position = CGPointMake(startPosition.x, startPosition.y + 50.0f); + } completion:^(BOOL finished) { + [UIView animateWithDuration:duration*0.8 animations:^{ + wk_self.customView.layer.position = endPosition; + } completion:nil]; + }]; + } + break; + default: + break; + } +} + +#pragma mark - ***** other 其他 ***** + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if([keyPath isEqualToString:@"frame"]) { + CGRect newFrame = CGRectNull; + CGRect oldFrame = CGRectNull; + if([object valueForKeyPath:keyPath] != [NSNull null]) { + //此处为获取新的frame + newFrame = [[object valueForKeyPath:keyPath] CGRectValue]; + oldFrame = [[change valueForKeyPath:@"old"] CGRectValue]; + if (!CGSizeEqualToSize(newFrame.size, oldFrame.size)) { + [self setCustomViewFrameWithHeight:newFrame.size.height-oldFrame.size.height]; + } + } + }else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +//按钮的压下事件 按钮缩小 +- (void)bgLongPressEvent:(UIGestureRecognizer *)ges { + + // [self.delegateMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + // + // if ([obj respondsToSelector:@selector(lst_PopViewBgLongPressForPopView:)]) { + // [obj lst_PopViewBgLongPressForPopView:self]; + // } + // + // }]; + + self.bgLongPressBlock? self.bgLongPressBlock():nil; + + // switch (ges.state) { + // case UIGestureRecognizerStateBegan: + // { + // CGFloat scale = 0.95; + // [UIView animateWithDuration:0.35 animations:^{ + // ges.view.transform = CGAffineTransformMakeScale(scale, scale); + // }]; + // } + // break; + // case UIGestureRecognizerStateEnded: + // case UIGestureRecognizerStateCancelled: + // { + // [UIView animateWithDuration:0.35 animations:^{ + // ges.view.transform = CGAffineTransformMakeScale(1.0, 1.0); + // } completion:^(BOOL finished) { + // }]; + // } + // break; + // + // default: + // break; + // } +} + +- (void)customViewClickEvent:(UIGestureRecognizer *)ges { + if (self.isClickFeedback) { + CGFloat scale = 0.95; + [UIView animateWithDuration:0.25 animations:^{ + ges.view.transform = CGAffineTransformMakeScale(scale, scale); + } completion:^(BOOL finished) { + [UIView animateWithDuration:0.25 animations:^{ + ges.view.transform = CGAffineTransformMakeScale(1.0, 1.0); + } completion:^(BOOL finished) { + + }]; + }]; + } +} + +- (void)popViewBgViewTap:(UIButton *)tap { + + // [self.delegateMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + // + // if ([obj respondsToSelector:@selector(lst_PopViewBgClickForPopView:)]) { + // [obj lst_PopViewBgClickForPopView:self]; + // } + // + // }]; + + if (self.bgClickBlock) { + if (self.isShowKeyboard) { + [self endEditing:YES]; + } + self.bgClickBlock(); + } + + if (_isClickBgDismiss) { + [self dismiss]; + } +} + +- (NSTimeInterval)getPopDuration:(NSTimeInterval)currDuration { + + if (_popStyle == LSTPopStyleNO) { return 0.0f; } + + if (_popStyle == LSTPopStyleFade) { return 0.2f; } + + if (currDuration<=0) { self.popDuration = LSTPopViewDefaultDuration; } + + if (self.popDuration == LSTPopViewDefaultDuration) { + NSTimeInterval defaultDuration = 0.0f; + + if (_popStyle == LSTPopStyleScale) { + defaultDuration = 0.3f; + } + if (_popStyle == LSTPopStyleSmoothFromTop || + _popStyle == LSTPopStyleSmoothFromLeft || + _popStyle == LSTPopStyleSmoothFromBottom || + _popStyle == LSTPopStyleSmoothFromRight || + _popStyle == LSTPopStyleSpringFromTop || + _popStyle == LSTPopStyleSpringFromLeft || + _popStyle == LSTPopStyleSpringFromBottom || + _popStyle == LSTPopStyleSpringFromRight || + _popStyle == LSTPopStyleCardDropFromLeft || + _popStyle == LSTPopStyleCardDropFromRight) { + defaultDuration = 0.6f; + } + return defaultDuration; + } else { + return currDuration; + } +} +- (NSTimeInterval)getDismissDuration:(NSTimeInterval)currDuration { + + if (_dismissStyle == LSTDismissStyleNO) { return 0.0f; } + + if (_dismissStyle == LSTDismissStyleFade) { return 0.2f; } + + if (self.dismissDuration == LSTPopViewDefaultDuration) { + NSTimeInterval defaultDuration = 0.0f; + if (_dismissStyle == LSTDismissStyleNO) { + defaultDuration = 0.0f; + } + + if (_dismissStyle == LSTDismissStyleScale) { + defaultDuration = 0.3f; + } + if (_dismissStyle == LSTDismissStyleSmoothToTop || + _dismissStyle == LSTDismissStyleSmoothToBottom || + _dismissStyle == LSTDismissStyleSmoothToLeft || + _dismissStyle == LSTDismissStyleSmoothToRight || + _dismissStyle == LSTDismissStyleCardDropToLeft || + _dismissStyle == LSTDismissStyleCardDropToRight || + _dismissStyle == LSTDismissStyleCardDropToTop) { + defaultDuration = 0.5f; + } + return defaultDuration; + } else { + return currDuration; + } +} +- (NSTimeInterval)getDragDismissDuration { + if (self.dragDismissDuration == LSTPopViewDefaultDuration) { + return [self getDismissDuration:self.dismissDuration]; + } else { + return self.dragDismissDuration; + } +} + +- (void)animationWithLayer:(CALayer *)layer duration:(CGFloat)duration values:(NSArray *)values { + CAKeyframeAnimation *KFAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; + KFAnimation.duration = duration; + KFAnimation.removedOnCompletion = NO; + KFAnimation.fillMode = kCAFillModeForwards; + // KFAnimation.delegate = self;//造成强应用 popView释放不了 + NSMutableArray *valueArr = [NSMutableArray arrayWithCapacity:values.count]; + for (NSUInteger i = 0; i 0) { + LSTPopViewWK(self);; + NSString *idStr = [NSString stringWithFormat:@"LSTPopView_%p",self]; + [LSTTimer addMinuteTimerForTime:self.showTime identifier:idStr handle:^(NSString * _Nonnull day, NSString * _Nonnull hour, NSString * _Nonnull minute, NSString * _Nonnull second, NSString * _Nonnull ms) { + + if (wk_self.popViewCountDownBlock) { + wk_self.popViewCountDownBlock(wk_self, [second doubleValue]); + } + [wk_self lst_PopViewCountDownForPopView:wk_self forCountDown:[second doubleValue]]; + } finish:^(NSString * _Nonnull identifier) { + [wk_self lst_PopViewCountDownFinishForPopView:wk_self]; + [self dismiss]; + } pause:^(NSString * _Nonnull identifier) {}]; + } +} + +/** 删除指定代理 */ +- (void)removeForDelegate:(id)delegate { + if (delegate) { + if ([self.delegates containsObject:delegate]) { + [self.delegates removeObject:delegate]; + } + } +} + +/** 删除代理池 删除所有代理 */ +- (void)removeAllDelegate { + if (self.delegates.count > 0) { + [self.delegates removeAllObjects]; + } +} + +- (void)beginImpactFeedback { + if (self.isImpactFeedback) { + if (@available(iOS 10.0, *)) { + UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; + [feedBackGenertor impactOccurred]; + } + } +} + +#pragma mark - ***** 横竖屏改变 ***** + +- (void)statusBarOrientationChange:(NSNotification *)notification { + if (self.isObserverScreenRotation) { + CGRect originRect = self.customView.frame; + self.frame = CGRectMake(0, 0, pv_ScreenWidth(), pv_ScreenHeight()); + self.backgroundView.frame = self.bounds; + self.customView.frame = originRect; + [self setCustomViewFrameWithHeight:0]; + } +} + +#pragma mark - ***** 键盘弹出/收回 ***** + +- (void)keyboardWillShow:(NSNotification *)notification{ + // LSTPVLog(@"keyboardWillShow"); + _isShowKeyboard = YES; + + self.keyboardWillShowBlock? self.keyboardWillShowBlock():nil; + + if (!self.isAvoidKeyboard) { return; } + CGFloat customViewMaxY = self.customView.pv_Bottom + self.avoidKeyboardSpace; + CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; + CGRect keyboardEedFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; + CGFloat keyboardMaxY = keyboardEedFrame.origin.y; + self.isAvoidKeyboard = YES; + self.avoidKeyboardOffset = customViewMaxY - keyboardMaxY; + self.keyboardY = keyboardEedFrame.origin.y; + //键盘遮挡到弹窗 + if ((keyboardMaxY keyboardMaxY)) { + //执行动画 + [UIView animateWithDuration:duration animations:^{ + self.customView.pv_Y = self.customView.pv_Y - self.avoidKeyboardOffset; + }]; + } +} + +- (void)keyboardDidShow:(NSNotification *)notification{ + _isShowKeyboard = YES; + self.keyboardDidShowBlock? self.keyboardDidShowBlock():nil; +} + +- (void)keyboardWillHide:(NSNotification *)notification{ + + _isShowKeyboard = NO; + self.keyboardWillHideBlock? self.keyboardWillHideBlock():nil; + if (!self.isAvoidKeyboard) { + return; + } + CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; + [UIView animateWithDuration:duration animations:^{ + self.customView.pv_Y = self.originFrame.origin.y; + }]; +} + +- (void)keyboardDidHide:(NSNotification *)notification{ + _isShowKeyboard = NO; + self.keyboardDidHideBlock? self.keyboardDidHideBlock():nil; +} + +- (void)keyboardWillChangeFrame:(NSNotification *)notification{ + // LSTPVLog(@"键盘frame将要改变"); + if (self.keyboardFrameWillChangeBlock) { + CGRect keyboardBeginFrame = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + CGRect keyboardEedFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; + CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; + self.keyboardFrameWillChangeBlock(keyboardBeginFrame,keyboardEedFrame,duration); + } +} + +- (void)keyboardDidChangeFrame:(NSNotification *)notification{ + // LSTPVLog(@"键盘frame已经改变"); + if (self.keyboardFrameDidChangeBlock) { + CGRect keyboardBeginFrame = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + CGRect keyboardEedFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; + CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]; + self.keyboardFrameDidChangeBlock(keyboardBeginFrame,keyboardEedFrame,duration); + } + +} + +#pragma mark - ***** UIGestureRecognizerDelegate ***** + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + + if(gestureRecognizer == self.panGesture) { + UIView *touchView = touch.view; + while (touchView != nil) { + if([touchView isKindOfClass:[UIScrollView class]]) { + self.isDragScrollView = YES; + self.scrollerView = (UIScrollView *)touchView; + break; + } else if(touchView == self.customView) { + self.isDragScrollView = NO; + break; + } + touchView = (id)[touchView nextResponder]; + } + } + return YES; +} + + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + if(gestureRecognizer == self.tapGesture) { + //如果是点击手势 + CGPoint point = [gestureRecognizer locationInView:self.customView]; + BOOL iscontain = [self.customView.layer containsPoint:point]; + if(iscontain) { + return NO; + } + } else if(gestureRecognizer == self.panGesture){ + //如果是自己加的拖拽手势 + // LSTPVLog(@"gestureRecognizerShouldBegin"); + } + return YES; +} + +//3. 是否与其他手势共存,一般使用默认值(默认返回NO:不与任何手势共存) +- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + if(gestureRecognizer == self.panGesture) { + if ([otherGestureRecognizer isKindOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")] || [otherGestureRecognizer isKindOfClass:NSClassFromString(@"UIPanGestureRecognizer")] ) { + if([otherGestureRecognizer.view isKindOfClass:[UIScrollView class]] ) { + return YES; + } + } + } + return NO; +} + +//拖拽手势 +- (void)pan:(UIPanGestureRecognizer *)panGestureRecognizer { + + self.panOffsetBlock?self.panOffsetBlock(CGPointMake(_customView.pv_X-_originFrame.origin.x, _customView.pv_Y-_originFrame.origin.y)):nil; + + if (self.dragStyle == LSTDragStyleNO) {return;} + // 获取手指的偏移量 + CGPoint transP = [panGestureRecognizer translationInView:self.customView]; + + CGPoint velocity = [panGestureRecognizer velocityInView:[UIApplication sharedApplication].keyWindow]; + if(self.isDragScrollView) {//含有tableView,collectionView,scrollView + //如果当前拖拽的是tableView + if(self.scrollerView.contentOffset.y <= 0) { + //如果tableView置于顶端 + if(transP.y > 0) { + //如果向下拖拽 + self.scrollerView.contentOffset = CGPointMake(0, 0); + self.scrollerView.panGestureRecognizer.enabled = NO; + self.isDragScrollView = NO; + //向下拖 + self.customView.frame = CGRectMake(_customView.pv_X, _customView.pv_Y + transP.y, _customView.pv_Width, _customView.pv_Height); + } else { + //如果向上拖拽 + } + } + } else {//不含有tableView,collectionView,scrollView + + CGFloat customViewX = self.customView.pv_X; + CGFloat customViewY = self.customView.pv_Y; + //X正方向移动 + if ((self.dragStyle & LSTDragStyleX_Positive) && (customViewX >= _originFrame.origin.x)) { + if (transP.x > 0) { + customViewX = customViewX + transP.x; + } else if(transP.x < 0 && customViewX > _originFrame.origin.x ){ + customViewX = (customViewX + transP.x) > _originFrame.origin.x? (customViewX + transP.x):(_originFrame.origin.x); + } + } + //X负方向移动 + if ((self.dragStyle & LSTDragStyleX_Negative) && (customViewX <= self.originFrame.origin.x)) { + if (transP.x < 0) { + customViewX = customViewX + transP.x; + } else if(transP.x > 0 && customViewX < _originFrame.origin.x ){ + customViewX = (customViewX + transP.x) < _originFrame.origin.x? (customViewX + transP.x):(_originFrame.origin.x); + } + } + //Y正方向移动 + if (self.dragStyle & LSTDragStyleY_Positive && (customViewY >= _originFrame.origin.y)) { + if (transP.y > 0) { + customViewY = customViewY + transP.y; + } else if(transP.y < 0 && customViewY > _originFrame.origin.y ){ + customViewY = (customViewY + transP.y) > _originFrame.origin.y ?(customViewY + transP.y):(_originFrame.origin.y); + } + } + //Y负方向移动 + if (self.dragStyle & LSTDragStyleY_Negative&&(customViewY <= _originFrame.origin.y)) { + if (transP.y < 0) { + customViewY = customViewY + transP.y; + } else if(transP.y > 0 && customViewY < _originFrame.origin.y){ + customViewY = (customViewY + transP.y) < _originFrame.origin.y?(customViewY + transP.y):(_originFrame.origin.y); + } + } + self.customView.frame = CGRectMake(customViewX, customViewY, _customView.pv_Width, _customView.pv_Height); + } + + [panGestureRecognizer setTranslation:CGPointZero inView:self.customView]; + + if(panGestureRecognizer.state == UIGestureRecognizerStateEnded) { + + if (self.scrollerView) { + self.scrollerView.panGestureRecognizer.enabled = YES; + } + + LSTPopViewWK(self) + //拖拽松开回位Block + void (^dragReboundBlock)(void) = ^ { + [UIView animateWithDuration:wk_self.dragReboundTime + delay:0.1f + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + CGRect frame = wk_self.customView.frame; + frame.origin.y = wk_self.frame.size.height - wk_self.customView.frame.size.height; + wk_self.customView.frame = wk_self.originFrame; + } completion:^(BOOL finished) {}]; + }; + //横扫移除Block + void (^sweepBlock)(BOOL,BOOL,BOOL,BOOL) = ^(BOOL isX_P, BOOL isX_N, BOOL isY_P, BOOL isY_N) { + + if (isX_P==NO && isX_N==NO && isY_P==NO && isY_N==NO) { + dragReboundBlock(); + return; + } + + if (isY_P==NO && isY_N==NO && self.sweepDismissStyle == LSTSweepDismissStyleSmooth) {//X轴可轻扫 + if (velocity.x>0) {//正向 + [self dismissWithStyle:LSTDismissStyleSmoothToRight duration:self.dismissDuration]; + } else {//负向 + [self dismissWithStyle:LSTDismissStyleSmoothToLeft duration:self.dismissDuration]; + } + return; + } + + if (isX_P==NO && isX_N==NO && self.sweepDismissStyle == LSTSweepDismissStyleSmooth) {//Y轴可轻扫 + if (velocity.y>0) {//正向 + [self dismissWithStyle:LSTDismissStyleSmoothToBottom duration:self.dismissDuration]; + } else {//负向 + [self dismissWithStyle:LSTDismissStyleSmoothToTop duration:self.dismissDuration]; + } + return; + } + // 移除,以手势速度飞出 + [UIView animateWithDuration:0.5 animations:^{ + wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0]; + self.customView.center = CGPointMake(isX_P || isX_N?velocity.x:self.customView.pv_CenterX, isY_P||isY_N?velocity.y:self.customView.pv_CenterY); + } completion:^(BOOL finished) { + [wk_self dismissWithStyle:LSTDismissStyleFade duration:0.1]; + }]; + }; + + double velocityX = sqrt(pow(velocity.x, 2)); + double velocityY = sqrt(pow(velocity.y, 2)); + if((velocityX >= self.swipeVelocity)||(velocityY >= self.swipeVelocity)) {//轻扫 + + if (self.scrollerView.contentOffset.y>0) { + return; + } + + //可轻扫移除的方向 + BOOL isX_P = NO; + BOOL isX_N = NO; + BOOL isY_P = NO; + BOOL isY_N = NO; + + if ((self.dragStyle & LSTDragStyleX_Positive) && velocity.x>0 && velocityX >= self.swipeVelocity) { + isX_P = self.sweepStyle & LSTSweepStyleX_Positive? YES:NO; + } + if ((self.dragStyle & LSTDragStyleX_Negative) && velocity.x<0 && velocityX >= self.swipeVelocity) { + isX_N = self.sweepStyle & LSTSweepStyleX_Negative? YES:NO; + } + + if ((self.dragStyle & LSTDragStyleY_Positive) && velocity.y>0 && velocityY >= self.swipeVelocity) { + isY_P = self.sweepStyle & LSTSweepStyleY_Positive? YES:NO; + } + if ((self.dragStyle & LSTDragStyleY_Negative) && velocity.y <0 && velocityY >= self.swipeVelocity) { + isY_N = self.sweepStyle & LSTSweepStyleY_Negative? YES:NO; + } + sweepBlock(isX_P,isX_N,isY_P,isY_N); +// LSTPVLog(@"isX=%@,isY=%@,velocityX=%lf,velocityY=%lf",isX?@"YES":@"NO",isY?@"YES":@"NO",velocityX,velocityY); + }else {//普通拖拽 + BOOL isCanDismiss = NO; + if (self.dragStyle & LSTDragStyleAll) { + + if (fabs(self.customView.frame.origin.x - self.originFrame.origin.x)>=self.dragDistance && self.dragDistance!=0) { + isCanDismiss = YES; + } + if (fabs(self.customView.frame.origin.y - self.originFrame.origin.y)>=self.dragDistance && self.dragDistance!=0) { + isCanDismiss = YES; + } + + if (isCanDismiss) { + [self dismissWithStyle:_isDragDismissStyle? self.dragDismissStyle:self.dismissStyle + duration:self.getDragDismissDuration]; + }else { + dragReboundBlock(); + } + } else { + dragReboundBlock(); + } + } + } +} + +#pragma mark - ***** 懒加载 ***** + +- (NSHashTable> *)delegates { + if (_delegates) return _delegates; + _delegates = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]; + return _delegates; +} + +- (UIView *)parentView { + return self.container; +} + +- (UIView *)currCustomView { + return self.customView; +} + +#pragma mark - ***** 以下是 窗口管理api ***** + +/** 保存popView */ ++ (void)savePopView:(LSTPopView *)popView { + [LSTPopViewManager savePopView:popView]; +} + +/** 获取全局(整个app内)所有popView */ ++ (NSArray *)getAllPopView { + return [LSTPopViewManager getAllPopView]; +} + +/** 获取当前页面所有popView */ ++ (NSArray *)getAllPopViewForParentView:(UIView *)parentView { + return [LSTPopViewManager getAllPopViewForParentView:parentView]; +} + +/** 获取当前页面指定编队的所有popView */ ++ (NSArray *)getAllPopViewForPopView:(LSTPopView *)popView { + return [LSTPopViewManager getAllPopViewForPopView:popView]; +} + +/** + 读取popView (有可能会跨编队读取弹窗) + 建议使用getPopViewForGroupId:forkey: 方法进行精确读取 + */ ++ (LSTPopView *)getPopViewForKey:(NSString *)key { + return [LSTPopViewManager getPopViewForKey:key]; +} + +/** 移除popView */ ++ (void)removePopView:(LSTPopView *)popView { + [LSTPopViewManager removePopView:popView]; +} + +/** + 移除popView 通过唯一key (有可能会跨编队误删弹窗) + 建议使用removePopViewForGroupId:forkey: 方法进行精确删除 + */ ++ (void)removePopViewForKey:(NSString *)key { + [LSTPopViewManager removePopViewForKey:key]; +} + +/** 移除所有popView */ ++ (void)removeAllPopView { + [LSTPopViewManager removeAllPopView]; +} + +/** 移除 最后一个弹出的 popView */ ++ (void)removeLastPopView { + return [LSTPopViewManager removeLastPopView]; +} + +/** 开启调试view 建议设置成 线上隐藏 测试打开 */ ++ (void)setLogStyle:(LSTPopViewLogStyle)logStyle { + _logStyle = logStyle; + + if (logStyle == LSTPopViewLogStyleNO) { + [LSTPopViewM().infoView removeFromSuperview]; + LSTPopViewM().infoView = nil; + } +} + +@end + + + diff --git a/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopViewProtocol.h b/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopViewProtocol.h new file mode 100644 index 0000000..dc9d63e --- /dev/null +++ b/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopViewProtocol.h @@ -0,0 +1,143 @@ +// +// LSTPopViewProtocol.h +// LSTCategory +// +// Created by LoSenTrad on 2020/5/30. +// + +#import +@class LSTPopView; + + +#ifdef DEBUG +#define LSTPVLog(format, ...) printf("class: <%p %s:(第%d行) > method: %s \n%s\n", self, [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, [[NSString stringWithFormat:(format), ##__VA_ARGS__] UTF8String] ) +#else +#define LSTPVLog(format, ...) +#endif + +/** 调试日志类型 */ +typedef NS_ENUM(NSInteger, LSTPopViewLogStyle) { + LSTPopViewLogStyleNO = 0, // 关闭调试信息(窗口和控制台日志输出) + LSTPopViewLogStyleWindow, // 开启左上角小窗 + LSTPopViewLogStyleConsole, // 开启控制台日志输出 + LSTPopViewLogStyleALL // 开启小窗和控制台日志 +}; + +/** 显示动画样式 */ +typedef NS_ENUM(NSInteger, LSTPopStyle) { + LSTPopStyleFade = 0, // 默认 渐变出现 + LSTPopStyleNO, // 无动画 + LSTPopStyleScale, // 缩放 先放大 后恢复至原大小 + LSTPopStyleSmoothFromTop, // 顶部 平滑淡入动画 + LSTPopStyleSmoothFromLeft, // 左侧 平滑淡入动画 + LSTPopStyleSmoothFromBottom, // 底部 平滑淡入动画 + LSTPopStyleSmoothFromRight, // 右侧 平滑淡入动画 + LSTPopStyleSpringFromTop, // 顶部 平滑淡入动画 带弹簧 + LSTPopStyleSpringFromLeft, // 左侧 平滑淡入动画 带弹簧 + LSTPopStyleSpringFromBottom, // 底部 平滑淡入动画 带弹簧 + LSTPopStyleSpringFromRight, // 右侧 平滑淡入动画 带弹簧 + LSTPopStyleCardDropFromLeft, // 顶部左侧 掉落动画 + LSTPopStyleCardDropFromRight, // 顶部右侧 掉落动画 +}; +/** 消失动画样式 */ +typedef NS_ENUM(NSInteger, LSTDismissStyle) { + LSTDismissStyleFade = 0, // 默认 渐变消失 + LSTDismissStyleNO, // 无动画 + LSTDismissStyleScale, // 缩放 + LSTDismissStyleSmoothToTop, // 顶部 平滑淡出动画 + LSTDismissStyleSmoothToLeft, // 左侧 平滑淡出动画 + LSTDismissStyleSmoothToBottom, // 底部 平滑淡出动画 + LSTDismissStyleSmoothToRight, // 右侧 平滑淡出动画 + LSTDismissStyleCardDropToLeft, // 卡片从中间往左侧掉落 + LSTDismissStyleCardDropToRight, // 卡片从中间往右侧掉落 + LSTDismissStyleCardDropToTop, // 卡片从中间往顶部移动消失 +}; +/** 主动动画样式(开发中) */ +typedef NS_ENUM(NSInteger, LSTActivityStyle) { + LSTActivityStyleNO = 0, /// 无动画 + LSTActivityStyleScale, /// 缩放 + LSTActivityStyleShake, /// 抖动 +}; +/** 弹窗位置 */ +typedef NS_ENUM(NSInteger, LSTHemStyle) { + LSTHemStyleCenter = 0, //居中 + LSTHemStyleTop, //贴顶 + LSTHemStyleLeft, //贴左 + LSTHemStyleBottom, //贴底 + LSTHemStyleRight, //贴右 + LSTHemStyleTopLeft, //贴顶和左 + LSTHemStyleBottomLeft, //贴底和左 + LSTHemStyleBottomRight, //贴底和右 + LSTHemStyleTopRight //贴顶和右 +}; +/** 拖拽方向 */ +typedef NS_ENUM(NSInteger, LSTDragStyle) { + LSTDragStyleNO = 0, //默认 不能拖拽窗口 + LSTDragStyleX_Positive = 1<<0, //X轴正方向拖拽 + LSTDragStyleX_Negative = 1<<1, //X轴负方向拖拽 + LSTDragStyleY_Positive = 1<<2, //Y轴正方向拖拽 + LSTDragStyleY_Negative = 1<<3, //Y轴负方向拖拽 + LSTDragStyleX = (LSTDragStyleX_Positive|LSTDragStyleX_Negative), //X轴方向拖拽 + LSTDragStyleY = (LSTDragStyleY_Positive|LSTDragStyleY_Negative), //Y轴方向拖拽 + LSTDragStyleAll = (LSTDragStyleX|LSTDragStyleY) //全向拖拽 +}; +///** 可轻扫消失的方向 */ +typedef NS_ENUM(NSInteger, LSTSweepStyle) { + LSTSweepStyleNO = 0, //默认 不能拖拽窗口 + LSTSweepStyleX_Positive = 1<<0, //X轴正方向拖拽 + LSTSweepStyleX_Negative = 1<<1, //X轴负方向拖拽 + LSTSweepStyleY_Positive = 1<<2, //Y轴正方向拖拽 + LSTSweepStyleY_Negative = 1<<3, //Y轴负方向拖拽 + LSTSweepStyleX = (LSTSweepStyleX_Positive|LSTSweepStyleX_Negative), //X轴方向拖拽 + LSTSweepStyleY = (LSTSweepStyleY_Positive|LSTSweepStyleY_Negative), //Y轴方向拖拽 + LSTSweepStyleALL = (LSTSweepStyleX|LSTSweepStyleY) //全向轻扫 +}; + +/** + 可轻扫消失动画类型 对单向横扫 设置有效 + LSTSweepDismissStyleSmooth: 自动适应选择以下其一 + LSTDismissStyleSmoothToTop, + LSTDismissStyleSmoothToLeft, + LSTDismissStyleSmoothToBottom , + LSTDismissStyleSmoothToRight + */ +typedef NS_ENUM(NSInteger, LSTSweepDismissStyle) { + LSTSweepDismissStyleVelocity = 0, //默认加速度 移除 + LSTSweepDismissStyleSmooth = 1 //平顺移除 +}; + + +NS_ASSUME_NONNULL_BEGIN + +@protocol LSTPopViewProtocol + + +/** 点击弹窗 回调 */ +- (void)lst_PopViewBgClickForPopView:(LSTPopView *)popView; +/** 长按弹窗 回调 */ +- (void)lst_PopViewBgLongPressForPopView:(LSTPopView *)popView; + + + + +// ****** 生命周期 ****** +/** 将要显示 */ +- (void)lst_PopViewWillPopForPopView:(LSTPopView *)popView; +/** 已经显示完毕 */ +- (void)lst_PopViewDidPopForPopView:(LSTPopView *)popView; +/** 倒计时进行中 timeInterval:时长 */ +- (void)lst_PopViewCountDownForPopView:(LSTPopView *)popView forCountDown:(NSTimeInterval)timeInterval; +/** 倒计时倒计时完成 */ +- (void)lst_PopViewCountDownFinishForPopView:(LSTPopView *)popView; +/** 将要开始移除 */ +- (void)lst_PopViewWillDismissForPopView:(LSTPopView *)popView; +/** 已经移除完毕 */ +- (void)lst_PopViewDidDismissForPopView:(LSTPopView *)popView; +//*********************** + + + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/LSTPopView/LSTPopView/Classes/Code/UIView+LSTPV.h b/Pods/LSTPopView/LSTPopView/Classes/Code/UIView+LSTPV.h new file mode 100644 index 0000000..d2d2735 --- /dev/null +++ b/Pods/LSTPopView/LSTPopView/Classes/Code/UIView+LSTPV.h @@ -0,0 +1,49 @@ +// +// UIView+LSTPV.h +// LSTPopView +// +// Created by LoSenTrad on 2020/11/30. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (LSTPV) + +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_X; +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_Y; +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_Width; +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_Height; +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_CenterX; +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_CenterY; +/** 获取/设置view的x坐标 */ +@property (nonatomic, assign) CGFloat pv_Top; +/** 获取/设置view的左边坐标 */ +@property (nonatomic, assign) CGFloat pv_Left; +/** 获取/设置view的底部坐标Y */ +@property (nonatomic, assign) CGFloat pv_Bottom; +/** 获取/设置view的右边坐标 */ +@property (nonatomic, assign) CGFloat pv_Right; +/** 获取/设置view的size */ +@property (nonatomic, assign) CGSize pv_Size; + + +/** 是否是苹果X系列(刘海屏系列) */ +BOOL pv_IsIphoneX_ALL(void); +/** 屏幕大小 */ +CGSize pv_ScreenSize(void); +/** 屏幕宽度 */ +CGFloat pv_ScreenWidth(void); +/** 屏幕高度 */ +CGFloat pv_ScreenHeight(void); + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/LSTPopView/LSTPopView/Classes/Code/UIView+LSTPV.m b/Pods/LSTPopView/LSTPopView/Classes/Code/UIView+LSTPV.m new file mode 100644 index 0000000..a7944ab --- /dev/null +++ b/Pods/LSTPopView/LSTPopView/Classes/Code/UIView+LSTPV.m @@ -0,0 +1,148 @@ +// +// UIView+LSTPV.m +// LSTPopView +// +// Created by LoSenTrad on 2020/11/30. +// + +#import "UIView+LSTPV.h" + +@implementation UIView (LSTPV) + + +- (void)setPv_X:(CGFloat)pv_X { + CGRect frame = self.frame; + frame.origin.x = pv_X; + self.frame = frame; +} + +- (CGFloat)pv_X { + return self.frame.origin.x; +} + +- (void)setPv_Y:(CGFloat)pv_Y { + CGRect frame = self.frame; + frame.origin.y = pv_Y; + self.frame = frame; +} + +- (CGFloat)pv_Y { + return self.frame.origin.y; +} + +- (void)setPv_Width:(CGFloat)pv_Width { + CGRect frame = self.frame; + frame.size.width = pv_Width; + self.frame = frame; +} + +- (CGFloat)pv_Width { + return self.frame.size.width; +} + +- (void)setPv_Height:(CGFloat)pv_Height { + CGRect frame = self.frame; + frame.size.height = pv_Height; + self.frame = frame; +} + +- (CGFloat)pv_Height { + return self.frame.size.height; +} + +- (void)setPv_Size:(CGSize)pv_Size { + CGRect frame = self.frame; + frame.size = pv_Size; + self.frame = frame; +} + +- (CGSize)pv_Size { + return self.frame.size; +} + +- (void)setPv_CenterX:(CGFloat)pv_CenterX { + CGPoint center = self.center; + center.x = pv_CenterX; + self.center = center; +} + +- (CGFloat)pv_CenterX { + return self.center.x; +} + +- (void)setPv_CenterY:(CGFloat)pv_CenterY { + CGPoint center = self.center; + center.y = pv_CenterY; + self.center = center; +} + +- (CGFloat)pv_CenterY { + return self.center.y; +} + +- (void)setPv_Top:(CGFloat)pv_Top { + CGRect newframe = self.frame; + newframe.origin.y = pv_Top; + self.frame = newframe; +} + +- (CGFloat)pv_Top { + return self.frame.origin.y; +} + +- (void)setPv_Left:(CGFloat)pv_Left { + CGRect newframe = self.frame; + newframe.origin.x = pv_Left; + self.frame = newframe; +} + +- (CGFloat)pv_Left { + return self.frame.origin.x; +} + +- (void)setPv_Bottom:(CGFloat)pv_Bottom { + CGRect newframe = self.frame; + newframe.origin.y = pv_Bottom - self.frame.size.height; + self.frame = newframe; +} + +- (CGFloat)pv_Bottom { + return self.frame.origin.y + self.frame.size.height; +} + +- (void)setPv_Right:(CGFloat)pv_Right { + CGFloat delta = pv_Right - (self.frame.origin.x + self.frame.size.width); + CGRect newframe = self.frame; + newframe.origin.x += delta ; + self.frame = newframe; +} + +- (CGFloat)pv_Right { + return self.frame.origin.x + self.frame.size.width; +} + +/** 是否是苹果X系列(刘海屏系列) */ +BOOL pv_IsIphoneX_ALL(void) { + BOOL isPhoneX = NO; + if (@available(iOS 11.0, *)) { + isPhoneX = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0; + } + return isPhoneX; +} + +CGSize pv_ScreenSize(void) { + CGSize size = [UIScreen mainScreen].bounds.size; + return size; +} + +CGFloat pv_ScreenWidth(void) { + CGSize size = [UIScreen mainScreen].bounds.size; + return size.width; +} + +CGFloat pv_ScreenHeight(void) { + CGSize size = [UIScreen mainScreen].bounds.size; + return size.height; +} + +@end diff --git a/Pods/LSTPopView/README.md b/Pods/LSTPopView/README.md new file mode 100644 index 0000000..469d510 --- /dev/null +++ b/Pods/LSTPopView/README.md @@ -0,0 +1,178 @@ +# LSTPopView iOS万能弹窗 + +[![Platform](https://img.shields.io/badge/platform-iOS-red.svg)](https://developer.apple.com/iphone/index.action) [![Language](http://img.shields.io/badge/language-OC-yellow.svg?style=flat )](https://en.wikipedia.org/wiki/Objective-C) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://mit-license.org) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/LSTPopView.svg)](https://img.shields.io/cocoapods/v/LSTPopView.svg) + +### LSTPopView 万能弹窗,功能强大,易于拓展,性能优化和内存控制让其运行更加的流畅和稳健, LSTPopView的出现,可以让我们更专注弹窗页面的布局. 省心省力 ! 提高开发效率 ! + +## 前言 +- 考虑到笔者的精力问题,遇到问题请先查看 API、效仿Demo、阅读README、搜索 Issues。如果是BUG 或 Feature,最好是提Issue +- 联系方式: LoSenTrad@163.com, QQ群:1045568246, 微信:a_LSTKit +- 开发环境: Xcode12.3, iOS13.5, iPhone XS Max + +## 博客地址 +- github: [https://github.com/LoSenTrad/LSTPopView](https://github.com/LoSenTrad/LSTPopView) +- CSDN: [https://blog.csdn.net/u012400600/article/details/106279654](https://blog.csdn.net/u012400600/article/details/106279654) +- 简书: [https://www.jianshu.com/p/8023a85dc2a2](https://www.jianshu.com/p/8023a85dc2a2) + +## 目录 +* [特性](#特性) +* [版本更新历史](#版本更新历史) +* [安装](#安装) +* [基本使用](#基本使用) +* [使用注意事项](#使用注意事项) +* [演示效果](#演示效果) +* [作者](#作者) +* [版权](#版权) + +## 特性 +- 提供丰富的api,高度自定义弹窗,简单入手使用 +- 支持弹出动画,消失动画,主动动画等多重动画搭配 +- 支持点击,长按,拖拽,横扫手势交互 +- 支持多弹窗管理:编队,堆叠,优先级等 +- 支持指定弹窗父类,eg: UIWindow,self.view等 +- 安全且内存占用小,弹窗内存自动回收 +- 提供生命周期api,自定义动画控制 +- 自动规避键盘,防止被键盘遮挡 +- 支持定时器,多定时器机制 +- 支持纯代码/xib页面 +- 支持横竖屏切换 +- 支持多代理机制 +- 支持二次封装,比如组件LSTHUD,LSTAlertView等 + +## 版本更新历史 +- [点我查看](https://github.com/LoSenTrad/LSTPopView/blob/master/UPDATE_HISTORY.md) + +## 安装 +- OC版本安装 + - CocoaPods安装: 在podfile文件中添加以下描述,然后 `pod install` 或者 `pod update` + + ``` + pod 'LSTPopView' + ``` + - Carthage安装:(暂时未适配) +- Swift版本安装 + - (计划开发中) + +- 手动导入集成 + - 1.拖动LSTPopView文件下5个文件到项目中 + + ```objective-c + LSTPopView.h + LSTPopView.m + UIView+LSTPV.h + UIView+LSTPV.m + LSTPopViewProtocol.h + ``` + - 2.在项目中podfile添加依赖库LSTTimer: https://github.com/LoSenTrad/LSTTimer + ```ruby + pod 'LSTTimer' + ``` + +## 基本使用 +- 代码示例 + + ```objective-c + //自定义view + LSTPopViewTVView *customView = [[LSTPopViewTVView alloc] initWithFrame:CGRectMake(0, 0, 300,400)]; + //创建弹窗PopViiew 指定父容器self.view, 不指定默认是app window + LSTPopView *popView = [LSTPopView initWithCustomView:customView + parentView:self.view + popStyle:LSTPopStyleSmoothFromBottom + dismissStyle:LSTDismissStyleSmoothToBottom]; + //弹窗位置: 居中 贴顶 贴左 贴底 贴右 + popView.hemStyle = LSTHemStyleBottom; + LSTPopViewWK(popView) + //点击背景触发 + popView.bgClickBlock = ^{ [wk_popView dismiss]; }; + //弹窗显示 + [popView pop]; + ``` + +- 调试日志 + ```objective-c + /** 调试日志类型 */ + typedef NS_ENUM(NSInteger, LSTPopViewLogStyle) { + LSTPopViewLogStyleNO = 0, // 关闭调试信息(窗口和控制台日志输出) + LSTPopViewLogStyleWindow, // 开启左上角小窗 + LSTPopViewLogStyleConsole, // 开启控制台日志输出 + LSTPopViewLogStyleALL // 开启小窗和控制台日志 + }; + ``` + - 调试小窗: S表示当前已经显示的弹窗数, R表示在移除队列的弹窗, S+R是表示当前所有的弹窗数 + + + + + +## 使用注意事项 +#### (一定用weak修饰) +- 解析: LSTPopView对每个弹窗都有自动内存销毁机制, 外部对弹窗的强引用对打破这种自动内存销毁机制, 比如成员变量用strong修饰,否则弹窗不能自动销毁,导致内存回收不了. +- 类成员变量使用规范: + + ```objective-c + //成员变量用weak修饰, 不可以用strong修饰 + @property (nonatomic,weak) LSTPopView *popView; + ``` +- 成员变量的创建 + ```objective-c + LSTPopViewTVView *customView = [[LSTPopViewTVView alloc] initWithFrame:CGRectMake(0, 0, 300,400)]; + //弹窗实例创建 + LSTPopView *popView = [LSTPopView initWithCustomView:customView + popStyle:LSTPopStyleSmoothFromBottom + dismissStyle:LSTDismissStyleSmoothToBottom]; + //这里赋值给成员变量self.popView + self.popView = popView; + [popView pop]; + ``` + +- 错误使用: + ```objective-c + //直接赋值给成员变量 导致成员变量为空, 请参考以上使用规范 + self.popView = [LSTPopView initWithCustomView:customView + popStyle:LSTPopStyleSmoothFromBottom + dismissStyle:LSTDismissStyleSmoothToBottom]; + ``` + + +## 演示效果 + +- 应用市场常用的示例场景 + +|QQ,微信,UC,微博,抖音
图片名称|拖拽移除,横扫移除
图片名称 | +|---|---| + +- 丰富的出入场动画, 拖拽, 横扫动画 + +|弹出动画,中间,自上,自左,自下,自左
图片名称|移除动画,中间,至上,至左,至下,至左
图片名称 |拖拽,横扫动画
图片名称 | +|---|---|---| + +- 弹窗位置 + +|弹窗位置,中间,贴顶,贴左,贴底,贴右
图片名称|X轴,Y轴调教,宽度和高度调教
图片名称 | +|---|---| + +- 自动规避键盘遮挡,指定容器,定时器 + +|自动规避键盘遮挡
图片名称|指定容器弹出
图片名称|弹窗计时
图片名称| +|---|---|---| + +- 多弹窗管理(优先级,编队) + +|app启动多弹窗优先级显示
图片名称|多窗口编队使用
图片名称| +|---|---| + + - 支持横竖屏 + +|屏幕旋转
图片名称| +|---| + + + +## 作者 + +LoSenTrad@163.com, QQ群:1045568246, 微信:a_LSTKit + +## 版权 + + 尊重劳动成果, 人人有责. + diff --git a/Pods/LSTTimer/LICENSE b/Pods/LSTTimer/LICENSE new file mode 100644 index 0000000..96fd23b --- /dev/null +++ b/Pods/LSTTimer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 490790096@qq.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Pods/LSTTimer/LSTTimer/Classes/LSTTimer.h b/Pods/LSTTimer/LSTTimer/Classes/LSTTimer.h new file mode 100644 index 0000000..1e3c079 --- /dev/null +++ b/Pods/LSTTimer/LSTTimer/Classes/LSTTimer.h @@ -0,0 +1,165 @@ +// +// LSTTimer.h +// LSTTimer +// +// Created by LoSenTrad on 2020/7/13. +// + +#import + + + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^LSTTimerChangeBlock)(NSString *day, NSString *hour, NSString *minute, NSString *second, NSString *ms); +typedef void(^LSTTimerFinishBlock)(NSString *identifier); +typedef void(^LSTTimerPauseBlock)(NSString *identifier); + + + +/** 倒计时变化通知类型 */ +typedef NS_ENUM(NSInteger, LSTTimerSecondChangeNFType) { + LSTTimerSecondChangeNFTypeNone = 0, + LSTTimerSecondChangeNFTypeMS, //每100ms(毫秒) 发出一次 + LSTTimerSecondChangeNFTypeSecond, //每1s(秒) 发出一次 + +}; + +@interface LSTTimer : NSObject + + +/** 单例 */ +LSTTimer *LSTTimerM(void); + +#pragma mark - ***** 配置计时任务通知回调 ***** +/// 设置倒计时任务的通知回调 +/// @param name 通知名 +/// @param identifier 倒计时任务的标识 +/// @param type 倒计时变化通知类型 ++ (void)setNotificationForName:(NSString *)name identifier:(NSString *)identifier changeNFType:(LSTTimerSecondChangeNFType)type; + +#pragma mark - ***** 添加计时任务(100ms回调一次) ***** +/// 添加计时任务 +/// @param time 时间长度 +/// @param handle 每100ms回调一次 ++ (void)addTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle; +/// 添加计时任务 +/// @param time 时间长度 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 ++ (void)addTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle; +/// 添加计时任务 +/// @param time 时间长度 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 +/// @param finishBlock 计时完成回调 +/// @param pauseBlock 计时暂停回调 ++ (void)addTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock; +/// 添加计时任务,持久化到硬盘 +/// @param time 时间长度 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 ++ (void)addDiskTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle; +/// 添加计时任务,持久化到硬盘 +/// @param time 添加计时任务,持久化到硬盘 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 +/// @param finishBlock 计时完成回调 +/// @param pauseBlock 计时暂停回调 ++ (void)addDiskTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock; + + + +#pragma mark - ***** 添加计时任务(1s回调一次) ***** +/// 添加计时任务 +/// @param time 时间长度 +/// @param handle 计时任务标识 ++ (void)addMinuteTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle; +/// 添加计时任务 +/// @param time 时间长度 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 ++ (void)addMinuteTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle; + +/// 添加计时任务 +/// @param time 时间长度 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 +/// @param finishBlock 计时完成回调 +/// @param pauseBlock 计时暂停回调 ++ (void)addMinuteTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock; + +/// 添加计时任务 +/// @param time 时间长度 +/// @param identifier 计时任务标识 +/// @param handle 每100ms回调一次 +/// @param finishBlock 计时完成回调 +/// @param pauseBlock 计时暂停回调 ++ (void)addDiskMinuteTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock; + + +#pragma mark - ***** 获取计时任务时间间隔 ***** +/// 通过任务标识获取 计时任务 间隔(毫秒) +/// @param identifier 计时任务标识 ++ (NSTimeInterval)getTimeIntervalForIdentifier:(NSString *)identifier; + + +#pragma mark - ***** 暂停计时任务 ***** +/// 通过标识暂停计时任务 +/// @param identifier 计时任务标识 ++ (BOOL)pauseTimerForIdentifier:(NSString *)identifier; +/// 暂停所有计时任务 ++ (void)pauseAllTimer; + +#pragma mark - ***** 重启计时任务 ***** +/// 通过标识重启 计时任务 +/// @param identifier 计时任务标识 ++ (BOOL)restartTimerForIdentifier:(NSString *)identifier; +/// 重启所有计时任务 ++ (void)restartAllTimer; + +#pragma mark - ***** 重置计时任务(恢复初始状态) ***** +/// 通过标识重置 计时任务 +/// @param identifier 计时任务标识 ++ (BOOL)resetTimerForIdentifier:(NSString *)identifier; +/// 重置所有计时任务 ++ (void)resetAllTimer; + +#pragma mark - ***** 移除计时任务 ***** +/// 通过标识移除计时任务 +/// @param identifier 计时任务标识 ++ (BOOL)removeTimerForIdentifier:(NSString *)identifier; +/// 移除所有计时任务 ++ (void)removeAllTimer; + +#pragma mark - ***** 格式化时间 ***** +/// 将毫秒数 格式化成 时:分:秒:毫秒 +/// @param time 时间长度(毫秒单位) +/// @param handle 格式化完成回调 ++ (void)formatDateForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/LSTTimer/LSTTimer/Classes/LSTTimer.m b/Pods/LSTTimer/LSTTimer/Classes/LSTTimer.m new file mode 100644 index 0000000..648ae00 --- /dev/null +++ b/Pods/LSTTimer/LSTTimer/Classes/LSTTimer.m @@ -0,0 +1,790 @@ +// +// LSTTimer.m +// LSTTimer +// +// Created by LoSenTrad on 2020/7/13. +// + +#import "LSTTimer.h" + + +#define LSTPopViewTimerPath(name) [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"LSTTimer_%@_Timer",name]] + +@interface LSTPopViewTimerModel : NSObject + +/** 毫秒为单位计算 */ +@property (nonatomic, assign) NSTimeInterval time; +/** 原始开始时间 毫秒 */ +@property (nonatomic, assign) NSTimeInterval oriTime; +/** 进度单位 */ +@property (nonatomic, assign) NSTimeInterval unit; +/** 定时器执行block */ + +/** 是否本地持久化保存定时数据 */ +@property (nonatomic,assign) BOOL isDisk; +/** 是否暂停 */ +@property (nonatomic,assign) BOOL isPause; +/** 标识 */ +@property (nonatomic, copy) NSString *identifier; +/** 通知名称 */ +@property (nonatomic, copy) NSString *NFName; +/** 通知类型 0.不发通知 1.毫秒通知 2.秒通知 */ +@property (nonatomic, assign) LSTTimerSecondChangeNFType NFType; + + +@property (nonatomic, copy) LSTTimerChangeBlock handleBlock; +/** 定时器执行block */ +@property (nonatomic, copy) LSTTimerFinishBlock finishBlock; +/** 定时器执行block */ +@property (nonatomic, copy) LSTTimerPauseBlock pauseBlock; + ++ (instancetype)timeInterval:(NSInteger)timeInterval; + +@end + +@implementation LSTPopViewTimerModel + ++ (instancetype)timeInterval:(NSInteger)timeInterval { + LSTPopViewTimerModel *object = [LSTPopViewTimerModel new]; + object.time = timeInterval*1000; + object.oriTime = timeInterval*1000; + return object; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeDouble:self.time forKey:@"timeInterval"]; + [aCoder encodeDouble:self.oriTime forKey:@"oriTime"]; + [aCoder encodeDouble:self.unit forKey:@"unit"]; + [aCoder encodeBool:self.isDisk forKey:@"isDisk"]; + [aCoder encodeBool:self.isPause forKey:@"isPause"]; + [aCoder encodeObject:self.identifier forKey:@"identifier"]; + [aCoder encodeBool:self.NFType forKey:@"NFType"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.time = [aDecoder decodeDoubleForKey:@"timeInterval"]; + self.oriTime = [aDecoder decodeDoubleForKey:@"oriTime"]; + self.unit = [aDecoder decodeDoubleForKey:@"unit"]; + self.isDisk = [aDecoder decodeBoolForKey:@"isDisk"]; + self.isPause = [aDecoder decodeBoolForKey:@"isPause"]; + self.identifier = [aDecoder decodeObjectForKey:@"identifier"]; + self.NFType = [aDecoder decodeBoolForKey:@"NFType"]; + } + return self; +} + +@end + +@interface LSTTimer () + +@property (nonatomic, strong) NSTimer * _Nullable showTimer; +/** 储存多个计时器数据源 */ +@property (nonatomic, strong) NSMutableDictionary *timerMdic; + + +@end + +@implementation LSTTimer + +static LSTTimer *_instance; + + +LSTTimer *LSTTimerM() { + return [LSTTimer sharedInstance]; +} + ++ (instancetype)sharedInstance { + if (!_instance) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _instance = [[self alloc] init]; + }); + } + return _instance; +} + + ++ (id)allocWithZone:(struct _NSZone *)zone { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _instance = [super allocWithZone:zone]; + }); + return _instance; +} + +/// 设置倒计时任务的通知回调 +/// @param name 通知名 +/// @param identifier 倒计时任务的标识 +/// @param type 倒计时变化通知类型 ++ (void)setNotificationForName:(NSString *)name identifier:(NSString *)identifier changeNFType:(LSTTimerSecondChangeNFType)type { + if (identifier.length<=0) { + NSLog(@"计时器标识不能为空"); + return; + } + LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier]; + if (model) { + model.NFType = type; + model.NFName = name; + return; + }else { + NSLog(@"找不到计时器任务"); + return; + } +} + + +/** 添加定时器并开启计时 */ ++ (void)addTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle { + [self initTimerForForTime:time identifier:nil ForIsDisk:NO unit:0 handle:handle finish:nil pause:nil]; +} +/** 添加定时器并开启计时 */ ++ (void)addTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:NO + unit:-1 + handle:handle + finish:nil + pause:nil]; +} +/** 添加定时器并开启计时 */ ++ (void)addTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:NO + unit:-1 + handle:handle + finish:finishBlock + pause:pauseBlock]; +} + +/** 添加定时器并开启计时 */ ++ (void)addDiskTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:YES + unit:-1 + handle:handle + finish:nil + pause:nil]; +} + +/** 添加定时器并开启计时 */ ++ (void)addDiskTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:YES + unit:-1 + handle:handle + finish:finishBlock + pause:pauseBlock]; +} + + +/** 添加定时器并开启计时 */ ++ (void)addMinuteTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle { + [self initTimerForForTime:time identifier:nil ForIsDisk:NO unit:1000 handle:handle finish:nil pause:nil]; +} +/** 添加定时器并开启计时 */ ++ (void)addMinuteTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:NO + unit:1000 + handle:handle + finish:nil + pause:nil]; +} + +/** 添加定时器并开启计时 */ ++ (void)addMinuteTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:NO + unit:1000 + handle:handle + finish:finishBlock + pause:pauseBlock]; +} + +/** 添加定时器并开启计时 */ ++ (void)addDiskMinuteTimerForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock { + + [self initTimerForForTime:time + identifier:identifier + ForIsDisk:YES + unit:1000 + handle:handle + finish:finishBlock + pause:pauseBlock]; +} + +//总初始化入口 ++ (void)initTimerForForTime:(NSTimeInterval)time + identifier:(NSString *)identifier + ForIsDisk:(BOOL)isDisk + unit:(NSTimeInterval)unit + handle:(LSTTimerChangeBlock)handle + finish:(LSTTimerFinishBlock)finishBlock + pause:(LSTTimerPauseBlock)pauseBlock { + + if (identifier.length<=0) { + LSTPopViewTimerModel *model = [LSTPopViewTimerModel timeInterval:time]; + model.isDisk = isDisk; + model.identifier = [NSString stringWithFormat:@"%p",model]; + model.unit = unit; + model.handleBlock = handle; + model.finishBlock = finishBlock; + model.pauseBlock = pauseBlock; + [LSTTimerM().timerMdic setObject:model forKey:model.identifier]; + if (model.handleBlock) { + NSInteger totalSeconds = model.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(model.time))%1000/10; + NSString *ss = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ss.integerValue < 10) { + ss = [NSString stringWithFormat:@"0%@", ss]; + } + model.handleBlock(days,hours,minute,second,ss); + + } + // 发出通知 + if (model.NFType != LSTTimerSecondChangeNFTypeNone) { + [[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil]; + } + if (model.isDisk) { + [self savaForTimerModel:model]; + } + [self initTimer]; + return; + } + + + BOOL isTempDisk = [LSTTimer timerIsExistInDiskForIdentifier:identifier];//磁盘有任务 + BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//内存有任务 + + if (!isRAM && !isTempDisk) {//新任务 + LSTPopViewTimerModel *model = [LSTPopViewTimerModel timeInterval:time]; + model.handleBlock = handle; + model.isDisk = isDisk; + model.identifier = identifier; + model.unit = unit; + model.finishBlock = finishBlock; + model.pauseBlock = pauseBlock; + [LSTTimerM().timerMdic setObject:model forKey:identifier]; + if (model.handleBlock) { + + NSInteger totalSeconds = model.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(model.time))%1000/10; + NSString *ss = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ss.integerValue < 10) { + ss = [NSString stringWithFormat:@"0%@", ss]; + } + if (model.isDisk) { + [self savaForTimerModel:model]; + } + model.handleBlock(days,hours,minute,second,ss); + + } + // 发出通知 + if (model.NFType != LSTTimerSecondChangeNFTypeNone) { + [[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil]; + } + [self initTimer]; + } + + + if (isRAM && !isTempDisk) {//内存任务 + LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier]; + model.isPause = NO; + model.handleBlock = handle; + model.isDisk = isDisk; + model.finishBlock = finishBlock; + model.pauseBlock = pauseBlock; + if (model.isDisk) { + [self savaForTimerModel:model]; + } +// [self initTimer]; + } + + if (!isRAM && isTempDisk) {//硬盘的任务 + LSTPopViewTimerModel *model = [LSTTimer getTimerModelForIdentifier:identifier]; + if (isDisk == NO) { + [LSTTimer deleteForIdentifier:identifier]; + } + model.isPause = NO; + model.isDisk = isDisk; + model.handleBlock = handle; + model.finishBlock = finishBlock; + model.pauseBlock = pauseBlock; + [LSTTimerM().timerMdic setObject:model forKey:identifier]; + if (model.handleBlock) { + NSInteger totalSeconds = model.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(model.time))%1000/10; + NSString *ss = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ss.integerValue < 10) { + ss = [NSString stringWithFormat:@"0%@", ss]; + } + model.handleBlock(days,hours,minute,second,ss); + + } + // 发出通知 + if (model.NFType != LSTTimerSecondChangeNFTypeNone) { + [[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil]; + } + if (model.isDisk) { + [self savaForTimerModel:model]; + } + [self initTimer]; + } + + if (isRAM && isTempDisk) {//硬盘的任务 + LSTPopViewTimerModel *model = [LSTTimer getTimerModelForIdentifier:identifier]; + model.isPause = NO; + if (isDisk == NO) { + [LSTTimer deleteForIdentifier:identifier]; + } + model.isDisk = isDisk; + model.handleBlock = handle; + model.finishBlock = finishBlock; + model.pauseBlock = pauseBlock; + [LSTTimerM().timerMdic setObject:model forKey:identifier]; + if (model.handleBlock) { + NSInteger totalSeconds = model.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(model.time))%1000/10; + NSString *ss = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ss.integerValue < 10) { + ss = [NSString stringWithFormat:@"0%@", ss]; + } + model.handleBlock(days,hours,minute,second,ss); + + } + // 发出通知 + if (model.NFType != LSTTimerSecondChangeNFTypeNone) { + [[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil]; + } + if (model.isDisk) { + [self savaForTimerModel:model]; + } +// [self initTimer]; + } + +} + ++ (NSTimeInterval)getTimeIntervalForIdentifier:(NSString *)identifier { + if (identifier.length<=0) { + return 0.0; + } + + BOOL isTempDisk = [LSTTimer timerIsExistInDiskForIdentifier:identifier];//磁盘有任务 + BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//内存有任务 + + + if (isTempDisk) { + LSTPopViewTimerModel *model = [LSTTimer loadTimerForIdentifier:identifier]; + return model.oriTime - model.time; + }else if (isRAM) { + LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier]; + return model.oriTime - model.time; + }else { + NSLog(@"找不到计时任务"); + return 0.0; + } + +} + ++ (BOOL)pauseTimerForIdentifier:(NSString *)identifier { + if (identifier.length<=0) { + NSLog(@"计时器标识不能为空"); + return NO; + } + LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier]; + + if (model) { + model.isPause = YES; + if (model.pauseBlock) { model.pauseBlock(model.identifier); } + return YES; + }else { + NSLog(@"找不到计时器任务"); + return NO; + } +} + ++ (void)pauseAllTimer { + [LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) { + obj.isPause = YES; + if (obj.pauseBlock) { obj.pauseBlock(obj.identifier); } + }]; +} + ++ (BOOL)restartTimerForIdentifier:(NSString *)identifier { + if (identifier.length<=0) { + NSLog(@"计时器标识不能为空"); + return NO; + } + + //只有内存任务才能重启, 硬盘任务只能调用addTimer系列方法重启 + BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//内存有任务 + if (isRAM) { + LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier]; + model.isPause = NO; + return YES; + }else { + NSLog(@"找不到计时器任务"); + return NO; + } + + +} ++ (void)restartAllTimer { + + if (LSTTimerM().timerMdic.count<=0) { + return; + } + + [LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) { + obj.isPause = NO; + }]; +} + ++ (BOOL)resetTimerForIdentifier:(NSString *)identifier { + if (identifier.length<=0) { + NSLog(@"计时器标识不能为空"); + return NO; + } + + //只有内存任务才能重启, 硬盘任务只能调用addTimer系列方法重启 + BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//内存有任务 + if (isRAM) { + LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier]; + model.isPause = NO; + model.time = model.oriTime; + if (model.handleBlock) { + NSInteger totalSeconds = model.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(model.time))%1000/10; + NSString *ss = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ss.integerValue < 10) { + ss = [NSString stringWithFormat:@"0%@", ss]; + } + model.handleBlock(days,hours,minute,second,ss); + + } + return YES; + }else { + NSLog(@"找不到计时器任务"); + return NO; + } +} + ++ (void)resetAllTimer { + if (LSTTimerM().timerMdic.count<=0) { + return; + } + + [LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) { + obj.isPause = NO; + obj.time = obj.oriTime; + if (obj.handleBlock) { + NSInteger totalSeconds = obj.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(obj.time))%1000/10; + NSString *ss = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ss.integerValue < 10) { + ss = [NSString stringWithFormat:@"0%@", ss]; + } + obj.handleBlock(days,hours,minute,second,ss); + + } + }]; +} + ++ (BOOL)removeTimerForIdentifier:(NSString *)identifier { + if (identifier.length<=0) { + NSLog(@"计时器标识不能为空"); + return NO; + } + + [LSTTimerM().timerMdic removeObjectForKey:identifier]; + if (LSTTimerM().timerMdic.count<=0) {//如果没有计时任务了 就销毁计时器 + [LSTTimerM().showTimer invalidate]; + LSTTimerM().showTimer = nil; + } + return YES; +} + ++ (void)removeAllTimer { + [LSTTimerM().timerMdic removeAllObjects]; + [LSTTimerM().showTimer invalidate]; + LSTTimerM().showTimer = nil; +} + +/** increase YES: 递增 NO: 递减 */ ++ (void)initTimer { + + if (LSTTimerM().showTimer) { + return; + } + + NSTimer *timer = [NSTimer timerWithTimeInterval:0.01f target:LSTTimerM() selector:@selector(timerChange) userInfo:nil repeats:YES]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + LSTTimerM().showTimer = timer; + +} + +- (void)timerChange { + // 时间差+ + [LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) { + if (!obj.isPause) { + + obj.time = obj.time-10.0; + + if (obj.unit>-1) { + obj.unit = obj.unit-10.0; + } + + if (obj.time<0) {//计时结束 + obj.time = 0; + obj.isPause = YES; + } + NSInteger totalSeconds = obj.time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(obj.time))%1000/10; + NSString *ms = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ms.integerValue < 10) { + ms = [NSString stringWithFormat:@"0%@", ms]; + } + + + + if (obj.unit<=-1) { + if (obj.handleBlock) {obj.handleBlock(days,hours,minute,second,ms);} + + if (obj.NFType == LSTTimerSecondChangeNFTypeMS) { + // 发出通知 + [[NSNotificationCenter defaultCenter] postNotificationName:obj.NFName object:nil userInfo:nil]; + } + }else if (obj.unit == 0) { + if (obj.handleBlock) {obj.handleBlock(days,hours,minute,second,ms);} + obj.unit = 1000; + if (obj.NFType == LSTTimerSecondChangeNFTypeSecond) { + // 发出通知 + [[NSNotificationCenter defaultCenter] postNotificationName:obj.NFName object:nil userInfo:nil]; + } + } + + if (obj.isDisk) { + [LSTTimer savaForTimerModel:obj]; + } + + if (obj.time<=0) {//计时器计时完毕自动移除计时任务 + if (obj.finishBlock) { obj.finishBlock(obj.identifier); } + [LSTTimerM().timerMdic removeObjectForKey:obj.identifier]; + [LSTTimer deleteForIdentifier:obj.identifier]; + } + + } + }]; + +} + +- (NSMutableDictionary *)timerMdic { + if(_timerMdic) return _timerMdic; + _timerMdic = [NSMutableDictionary dictionary]; + return _timerMdic; +} + + + +#pragma mark - ***** other ***** + ++ (BOOL)timerIsExistInDiskForIdentifier:(NSString *)identifier { + NSString *filePath = LSTPopViewTimerPath(identifier); + BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath]; + return isExist; +} + +/** 格式化时间 */ ++ (void)formatDateForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle { + if (handle) { + NSInteger totalSeconds = time/1000.0; + NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24]; + NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24]; + NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60]; + NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60]; + CGFloat sss = ((NSInteger)(time))%1000/10; + NSString *ms = [NSString stringWithFormat:@"%.lf", sss]; + + if (hours.integerValue < 10) { + hours = [NSString stringWithFormat:@"0%@", hours]; + } + if (minute.integerValue < 10) { + minute = [NSString stringWithFormat:@"0%@", minute]; + } + if (second.integerValue < 10) { + second = [NSString stringWithFormat:@"0%@", second]; + } + if (ms.integerValue < 10) { + ms = [NSString stringWithFormat:@"0%@", ms]; + } + + handle(days,hours,minute,second,ms); + } +} + + ++ (BOOL)savaForTimerModel:(LSTPopViewTimerModel *)model { + NSString *filePath = LSTPopViewTimerPath(model.identifier); + return [NSKeyedArchiver archiveRootObject:model toFile:filePath]; +} + ++ (LSTPopViewTimerModel *)loadTimerForIdentifier:(NSString *)identifier{ + NSString *filePath = LSTPopViewTimerPath(identifier); + return [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; +} + ++ (BOOL)deleteForIdentifier:(NSString *)identifier { + NSString *filePath = LSTPopViewTimerPath(identifier); + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isExist = [fileManager fileExistsAtPath:filePath]; + if (isExist) { + return [fileManager removeItemAtPath:filePath error:nil]; + } + return NO; +} + ++ (LSTPopViewTimerModel *)getTimerModelForIdentifier:(NSString *)identifier { + if (identifier.length<=0) { + return nil; + } + LSTPopViewTimerModel *model = [LSTTimer loadTimerForIdentifier:identifier]; + return model; + +} + + +@end diff --git a/Pods/LSTTimer/README.md b/Pods/LSTTimer/README.md new file mode 100644 index 0000000..45a0f1f --- /dev/null +++ b/Pods/LSTTimer/README.md @@ -0,0 +1,72 @@ +# LSTTimer 性能和精度兼得的iOS计时器组件 + +[![Platform](https://img.shields.io/badge/platform-iOS-red.svg)](https://developer.apple.com/iphone/index.action) [![Language](http://img.shields.io/badge/language-OC-yellow.svg?style=flat )](https://en.wikipedia.org/wiki/Objective-C) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://mit-license.org) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/LSTPopView.svg)](https://img.shields.io/cocoapods/v/LSTTimer.svg) + +## 前言 +- 在项目开发中,计时器任务的需求很多, LSTTimer的出现就是为了更好统一管理项目中的计时器任务. +- 欢迎coder们发现问题或者提供更好的idea,一起努力完善 + +## 博客地址 +- github: [https://github.com/LoSenTrad/LSTTimer](https://github.com/LoSenTrad/LSTTimer) +- 简书: [https://www.jianshu.com/p/4f05c7e26bb1](https://www.jianshu.com/p/4f05c7e26bb1) + +## 实现思路 +LSTTimer单例设计, 内部持有一个NSTimer和计时任务池, 所有的计时任务都被添加到任务池里面; NSTimer每100ms(毫秒)执行一次遍历计时任务池, 每个计时任务会进行的时间差运算. + +## 特性 + +- 提供丰富的api,简单入手使用 +- 单例设计,安全且占用内存少,统一管理app所有计时任务 +- 单计时器任务池设计,一个NSTimer完成多个计时任务 +- 计时任务精确度:100ms(100毫秒) +- 支持计时格式--> 天:时:分:秒:毫秒 +- 支持硬盘持久化计时任务 +- 支持列表计时任务和各种花里胡哨的计时任务 + +## 版本更新历史[点我](https://github.com/LoSenTrad/LSTTimer/blob/master/UPDATE_HISTORY.md) + +## 安装 + +- CocoaPods安装: 在podfile文件中添加以下描述,然后 `pod install` 或者 `pod update` + + ```ruby + pod 'LSTTimer' + ``` +- Carthage安装:(暂时未适配) + +## 效果演示(gif图比较大,请耐心等待~) + +- 应用市场常用的示例场景 + - 支持 天:时:分:秒:毫秒 + - 列表计时方案:只需一个计时任务 + +|常用示例场景
图片名称|列表倒计时
图片名称| +|---|---| + +- 内存计时任务 +(当前页面添加计时任务,退出当前页面,计时任务不会停止,而是存在于app的整个生命周期内.当然了,也可以手动移除) + +|内存计时任务
图片名称| +|---| + +- 硬盘计时任务 + +(当前页面添加硬盘计时任务,退出app,计时任务保存在硬盘,再次打开进入app,如果计时任务没有结束,继续该计时任务) + +|自动规避键盘遮挡
图片名称| +|---| + + +## 作者 + +490790096@qq.com, LoSenTrad@163.com + +## 版权 + + 尊重劳动成果, 人人有责. + + + + + + diff --git a/Pods/LYEmptyView/LICENSE b/Pods/LYEmptyView/LICENSE new file mode 100644 index 0000000..6d38ce5 --- /dev/null +++ b/Pods/LYEmptyView/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 yang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/LYEmptyView/LYEmptyView/LYEmptyBaseView.h b/Pods/LYEmptyView/LYEmptyView/LYEmptyBaseView.h new file mode 100644 index 0000000..e2b273d --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/LYEmptyBaseView.h @@ -0,0 +1,146 @@ +// +// LYEmptyBaseView.h +// LYEmptyViewDemo +// +// Created by liyang on 2017/5/5. +// Copyright © 2017年 liyang. All rights reserved. +// + +#import +#import "UIView+LYExtension.h" + +//事件回调 +typedef void (^LYActionTapBlock)(void); + +@interface LYEmptyBaseView : UIView + +/////////属性传递(可修改) +/* image 的优先级大于 imageStr,只有一个有效*/ +@property (nonatomic, strong)UIImage *image; +@property (nonatomic, copy) NSString *imageStr; +@property (nonatomic, copy) NSString *titleStr; +@property (nonatomic, copy) NSString *detailStr; +@property (nonatomic, copy) NSString *btnTitleStr; + +/////////属性传递 (只读) +@property (nonatomic,strong,readonly) UIView *contentView; +@property (nonatomic, weak, readonly) id actionBtnTarget; +@property (nonatomic,assign,readonly) SEL actionBtnAction; +@property (nonatomic, copy, readonly) LYActionTapBlock btnClickBlock; +@property (nonatomic,strong,readonly) UIView *customView; + +/** + emptyView点击事件 + */ +@property (nonatomic, copy) LYActionTapBlock tapEmptyViewBlock; + + +///初始化配置 +- (void)prepare; + +///重置Subviews +- (void)setupSubviews; + + +/** + 构造方法 - 创建emptyView + + @param image 占位图片 + @param titleStr 标题 + @param detailStr 详细描述 + @param btnTitleStr 按钮的名称 + @param target 响应的对象 + @param action 按钮点击事件 + @return 返回一个emptyView + */ ++ (instancetype)emptyActionViewWithImage:(UIImage *)image + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + target:(id)target + action:(SEL)action; + +/** + 构造方法 - 创建emptyView + + @param image 占位图片 + @param titleStr 占位描述 + @param detailStr 详细描述 + @param btnTitleStr 按钮的名称 + @param btnClickBlock 按钮点击事件回调 + @return 返回一个emptyView + */ ++ (instancetype)emptyActionViewWithImage:(UIImage *)image + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + btnClickBlock:(LYActionTapBlock)btnClickBlock; + +/** + 构造方法 - 创建emptyView + + @param imageStr 占位图片名称 + @param titleStr 标题 + @param detailStr 详细描述 + @param btnTitleStr 按钮的名称 + @param target 响应的对象 + @param action 按钮点击事件 + @return 返回一个emptyView + */ ++ (instancetype)emptyActionViewWithImageStr:(NSString *)imageStr + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + target:(id)target + action:(SEL)action; + +/** + 构造方法 - 创建emptyView + + @param imageStr 占位图片名称 + @param titleStr 占位描述 + @param detailStr 详细描述 + @param btnTitleStr 按钮的名称 + @param btnClickBlock 按钮点击事件回调 + @return 返回一个emptyView + */ ++ (instancetype)emptyActionViewWithImageStr:(NSString *)imageStr + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + btnClickBlock:(LYActionTapBlock)btnClickBlock; + +/** + 构造方法 - 创建emptyView + + @param image 占位图片 + @param titleStr 占位描述 + @param detailStr 详细描述 + @return 返回一个没有点击事件的emptyView + */ ++ (instancetype)emptyViewWithImage:(UIImage *)image + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr; + +/** + 构造方法 - 创建emptyView + + @param imageStr 占位图片名称 + @param titleStr 占位描述 + @param detailStr 详细描述 + @return 返回一个没有点击事件的emptyView + */ ++ (instancetype)emptyViewWithImageStr:(NSString *)imageStr + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr; + +/** + 构造方法 - 创建一个自定义的emptyView + + @param customView 自定义view + @return 返回一个自定义内容的emptyView + */ ++ (instancetype)emptyViewWithCustomView:(UIView *)customView; + + +@end diff --git a/Pods/LYEmptyView/LYEmptyView/LYEmptyBaseView.m b/Pods/LYEmptyView/LYEmptyView/LYEmptyBaseView.m new file mode 100644 index 0000000..a5898aa --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/LYEmptyBaseView.m @@ -0,0 +1,212 @@ +// +// LYEmptyBaseView.h +// LYEmptyViewDemo +// +// Created by liyang on 2017/5/5. +// Copyright © 2017年 liyang. All rights reserved. +// + +#import "LYEmptyBaseView.h" + +@interface LYEmptyBaseView () + +@end + +@implementation LYEmptyBaseView + +#pragma mark - ------------------ Life Cycle ------------------ +- (instancetype)init +{ + self = [super init]; + if (self) { + [self initialize]; + [self prepare]; + } + return self; +} + +- (void)initialize{ +} + +- (void)prepare{ + self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + UIView *view = self.superview; + //不是UIView,不做操作 + if (view && [view isKindOfClass:[UIView class]]){ + self.ly_width = view.ly_width; + self.ly_height = view.ly_height; + } + + [self setupSubviews]; +} + +- (void)setupSubviews{ +} + +- (void)willMoveToSuperview:(UIView *)newSuperview +{ + [super willMoveToSuperview:newSuperview]; + + //不是UIView,不做操作 + if (newSuperview && ![newSuperview isKindOfClass:[UIView class]]) return; + + if (newSuperview) { + self.ly_width = newSuperview.ly_width; + self.ly_height = newSuperview.ly_height; + } +} + +#pragma mark - ------------------ 实例化 ------------------ ++ (instancetype)emptyActionViewWithImage:(UIImage *)image + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + target:(id)target + action:(SEL)action{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithImage:image imageStr:nil titleStr:titleStr detailStr:detailStr btnTitleStr:btnTitleStr target:target action:action btnClickBlock:nil]; + + return emptyView; +} + ++ (instancetype)emptyActionViewWithImage:(UIImage *)image + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + btnClickBlock:(LYActionTapBlock)btnClickBlock{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithImage:image imageStr:nil titleStr:titleStr detailStr:detailStr btnTitleStr:btnTitleStr target:nil action:nil btnClickBlock:btnClickBlock]; + + return emptyView; +} + ++ (instancetype)emptyActionViewWithImageStr:(NSString *)imageStr + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + target:(id)target + action:(SEL)action{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithImage:nil imageStr:imageStr titleStr:titleStr detailStr:detailStr btnTitleStr:btnTitleStr target:target action:action btnClickBlock:nil]; + + return emptyView; +} + ++ (instancetype)emptyActionViewWithImageStr:(NSString *)imageStr + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr + btnTitleStr:(NSString *)btnTitleStr + btnClickBlock:(LYActionTapBlock)btnClickBlock{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithImage:nil imageStr:imageStr titleStr:titleStr detailStr:detailStr btnTitleStr:btnTitleStr target:nil action:nil btnClickBlock:btnClickBlock]; + + return emptyView; +} + ++ (instancetype)emptyViewWithImage:(UIImage *)image + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithImage:image imageStr:nil titleStr:titleStr detailStr:detailStr btnTitleStr:nil target:nil action:nil btnClickBlock:nil]; + + return emptyView; +} + ++ (instancetype)emptyViewWithImageStr:(NSString *)imageStr + titleStr:(NSString *)titleStr + detailStr:(NSString *)detailStr{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithImage:nil imageStr:imageStr titleStr:titleStr detailStr:detailStr btnTitleStr:nil target:nil action:nil btnClickBlock:nil]; + + return emptyView; +} + ++ (instancetype)emptyViewWithCustomView:(UIView *)customView{ + + LYEmptyBaseView *emptyView = [[self alloc] init]; + [emptyView creatEmptyViewWithCustomView:customView]; + + return emptyView; +} + +- (void)creatEmptyViewWithImage:(UIImage *)image imageStr:(NSString *)imageStr titleStr:(NSString *)titleStr detailStr:(NSString *)detailStr btnTitleStr:(NSString *)btnTitleStr target:(id)target action:(SEL)action btnClickBlock:(LYActionTapBlock)btnClickBlock{ + + _image = image; + _imageStr = imageStr; + _titleStr = titleStr; + _detailStr = detailStr; + _btnTitleStr = btnTitleStr; + _actionBtnTarget = target; + _actionBtnAction = action; + _btnClickBlock = btnClickBlock; + + //内容物背景视图 + if (!_contentView) { + _contentView = [[UIView alloc] initWithFrame:CGRectZero]; + [self addSubview:_contentView]; + } + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapEmptyView:)]; + [self addGestureRecognizer:tap]; +} + +- (void)creatEmptyViewWithCustomView:(UIView *)customView{ + + //内容物背景视图 + if (!_contentView) { + _contentView = [[UIView alloc] initWithFrame:CGRectZero]; + [self addSubview:_contentView]; + } + + if (!_customView) { + [_contentView addSubview:customView]; + } + _customView = customView; + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapEmptyView:)]; + [self addGestureRecognizer:tap]; +} + +#pragma mark - ------------------ Event Method ------------------ +- (void)tapEmptyView:(UITapGestureRecognizer *)tap{ + if (_tapEmptyViewBlock) { + _tapEmptyViewBlock(); + } +} + +#pragma mark - ------------------ Setter ------------------ + +- (void)setImage:(UIImage *)image{ + _image = image; + [self setNeedsLayout]; +} +- (void)setImageStr:(NSString *)imageStr{ + _imageStr = imageStr; + [self setNeedsLayout]; +} +- (void)setTitleStr:(NSString *)titleStr{ + _titleStr = titleStr; + [self setNeedsLayout]; +} +- (void)setDetailStr:(NSString *)detailStr{ + _detailStr = detailStr; + [self setNeedsLayout]; +} +- (void)setBtnTitleStr:(NSString *)btnTitleStr{ + _btnTitleStr = btnTitleStr; + [self setNeedsLayout]; +} + +@end diff --git a/Pods/LYEmptyView/LYEmptyView/LYEmptyView.h b/Pods/LYEmptyView/LYEmptyView/LYEmptyView.h new file mode 100755 index 0000000..a6c2a92 --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/LYEmptyView.h @@ -0,0 +1,142 @@ +// +// LYEmptyView.h +// LYEmptyViewDemo +// +// Created by liyang on 2017/5/10. +// Copyright © 2017年 liyang. All rights reserved. +// + +#import "LYEmptyBaseView.h" + +@interface LYEmptyView : LYEmptyBaseView + +/** + 是否自动显隐EmptyView, default=YES + */ +@property (nonatomic, assign) BOOL autoShowEmptyView; + +/** + 占位图是否完全覆盖父视图, default=NO + 当设置为YES后,占位图的backgroundColor默认为浅白色,可自行设置 + */ +@property (nonatomic, assign) BOOL emptyViewIsCompleteCoverSuperView; + +/** + 内容物上每个子控件之间的间距 default is 20.f , 这是统一设置的,每个子控件可单独设置 + */ +@property (nonatomic, assign) CGFloat subViewMargin; + +/** + 内容物-垂直方向偏移 (此属性与contentViewY 互斥,只有一个会有效) + */ +@property (nonatomic, assign) CGFloat contentViewOffset; + +/** + 内容物-Y坐标 (此属性与contentViewOffset 互斥,只有一个会有效) + */ +@property (nonatomic, assign) CGFloat contentViewY; + +/** + 是否忽略scrollView的contentInset + */ +@property (nonatomic, assign) BOOL ignoreContentInset; + + +//-------------------------- image --------------------------// +/** + 图片可设置固定大小 (default=图片实际大小) + */ +@property (nonatomic, assign) CGSize imageSize; + + +//-------------------------- titleLab 相关 --------------------------// +/** + 标题字体, 大小default is 16.f + */ +@property (nonatomic, strong) UIFont *titleLabFont; + +/** + 标题文字颜色 + */ +@property (nonatomic, strong) UIColor *titleLabTextColor; + +/** + 标题与图片之间的间距 default is @subViewMargin + */ +@property (nonatomic, assign) CGFloat titleLabMargin; + + +//-------------------------- detailLab 相关 --------------------------// +/** + 详细描述字体,大小default is 14.f + */ +@property (nonatomic, strong) UIFont *detailLabFont; + +/** + 详细描述最大行数, default is 2 + */ +@property (nonatomic, assign) NSInteger detailLabMaxLines; + +/** + 详细描述文字颜色 + */ +@property (nonatomic, strong) UIColor *detailLabTextColor; + +/** + 详细描述文字行间距 + */ +@property (nonatomic, assign) NSInteger detailLabLineSpacing; + +/** + 详细描述 与 (标题或图片) 之间的间距 default is @subViewMargin + */ +@property (nonatomic, assign) CGFloat detailLabMargin; + + +//-------------------------- Button 相关 --------------------------// +/** + 按钮字体, 大小default is 14.f + */ +@property (nonatomic, strong) UIFont *actionBtnFont; +/** + 按钮的高度, default is 40.f + */ +@property (nonatomic, assign) CGFloat actionBtnHeight; +/** + 按钮的宽度, default is 0.f, (此属性和actionBtnHorizontalMargin只有一个有效,都>0时,此属性优先级大) + */ +@property (nonatomic, assign) CGFloat actionBtnWidth; +/** + 按钮的水平方向内边距, default is 30.f, (此属性和actionBtnWidth只有一个有效,都>0时,此属性优先级小) + */ +@property (nonatomic, assign) CGFloat actionBtnHorizontalMargin; +/** + 按钮的圆角大小, default is 0 + */ +@property (nonatomic, assign) CGFloat actionBtnCornerRadius; +/** + 按钮边框border的宽度, default is 0 + */ +@property (nonatomic, assign) CGFloat actionBtnBorderWidth; +/** + 按钮边框颜色 + */ +@property (nonatomic, strong) UIColor *actionBtnBorderColor; +/** + 按钮文字颜色 + */ +@property (nonatomic, strong) UIColor *actionBtnTitleColor; +/** + 按钮背景颜色 + */ +@property (nonatomic, strong) UIColor *actionBtnBackGroundColor; +/** + 按钮背景渐变颜色集合,2个 + */ +@property (nonatomic, strong) NSArray *actionBtnBackGroundGradientColors; +/** + 按钮 与 (详细描述或标题或图片) 之间的间距 default is @subViewMargin + */ +@property (nonatomic, assign) CGFloat actionBtnMargin; + +@end diff --git a/Pods/LYEmptyView/LYEmptyView/LYEmptyView.m b/Pods/LYEmptyView/LYEmptyView/LYEmptyView.m new file mode 100755 index 0000000..5178b45 --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/LYEmptyView.m @@ -0,0 +1,656 @@ +// +// LYEmptyView.m +// LYEmptyViewDemo +// +// Created by liyang on 2017/5/10. +// Copyright © 2017年 liyang. All rights reserved. +// + +#import "LYEmptyView.h" + +//每个子控件之间的间距 +#define kSubViewMargin 20.f + +//描述字体 +#define kTitleLabFont [UIFont systemFontOfSize:16.f] + +//详细描述字体 +#define kDetailLabFont [UIFont systemFontOfSize:14.f] + +//按钮字体大小 +#define kActionBtnFont [UIFont systemFontOfSize:14.f] + +//按钮高度 +#define kActionBtnHeight 40.f +//按钮宽度 +#define kActionBtnWidth 120.f +//水平方向内边距 +#define kActionBtnHorizontalMargin 30.f + +//背景色 +#define kBackgroundColor [UIColor colorWithRed:250.f/255.f green:250.f/255.f blue:250.f/255.f alpha:1.f] +//黑色 +#define kBlackColor [UIColor colorWithRed:0.3f green:0.3f blue:0.3f alpha:1.f] +//灰色 +#define kGrayColor [UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1.f] + +@interface LYEmptyView () + +@property (nonatomic, strong) UIImageView *promptImageView; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *detailLabel; +@property (nonatomic, strong) UIButton *actionButton; +@property (nonatomic, strong) UIView *customV; + +@end + +@implementation LYEmptyView +{ + CGFloat contentMaxWidth; //最大宽度 + CGFloat contentWidth; //内容物宽度 + CGFloat contentHeight; //内容物高度 + CGFloat subViweMargin; //内容物上每个子控件之间的间距 +} + +- (void)initialize{ + self.actionBtnHeight = 40.f; + self.actionBtnWidth = 120.f; + self.actionBtnHorizontalMargin = 30.f; + self.detailLabMaxLines = 2; +} + +- (void)prepare{ + [super prepare]; + + self.autoShowEmptyView = YES; //默认自动显隐 + self.contentViewY = 1000; //默认值,用来判断是否设置过content的Y值 +} + +- (void)setupSubviews{ + [super setupSubviews]; + + contentMaxWidth = self.emptyViewIsCompleteCoverSuperView ? self.ly_width : self.ly_width - 30.f; + contentWidth = 0;//内容物宽度 + contentHeight = 0;//内容物高度 + subViweMargin = self.subViewMargin ? self.subViewMargin : kSubViewMargin; + + //占位图片 + UIImage *image; + if (self.imageStr.length) { + image = [UIImage imageNamed:self.imageStr]; + } + if(self.image){ + [self setupPromptImageView:self.image]; + }else if (image) { + [self setupPromptImageView:image]; + } else{ + if (_promptImageView) { + [self.promptImageView removeFromSuperview]; + self.promptImageView = nil; + } + } + + //标题 + if (self.titleStr.length) { + [self setupTitleLabel:self.titleStr]; + }else{ + if (_titleLabel) { + [self.titleLabel removeFromSuperview]; + self.titleLabel = nil; + } + } + + //详细描述 + if (self.detailStr.length) { + [self setupDetailLabel:self.detailStr]; + }else{ + if (_detailLabel) { + [self.detailLabel removeFromSuperview]; + self.detailLabel = nil; + } + } + + //按钮 + if (self.btnTitleStr.length) { + if (self.actionBtnTarget && self.actionBtnAction) { + [self setupActionBtn:self.btnTitleStr target:self.actionBtnTarget action:self.actionBtnAction btnClickBlock:nil]; + }else if (self.btnClickBlock) { + [self setupActionBtn:self.btnTitleStr target:nil action:nil btnClickBlock:self.btnClickBlock]; + }else{ + if (_actionButton) { + [self.actionButton removeFromSuperview]; + self.actionButton = nil; + } + } + }else{ + if (_actionButton) { + [self.actionButton removeFromSuperview]; + self.actionButton = nil; + } + } + + //自定义view + if (self.customView) { + contentWidth = self.customView.ly_width; + contentHeight = self.customView.ly_maxY; + } + + ///设置frame + [self setSubViewFrame]; +} + +- (void)setSubViewFrame{ + + //emptyView初始宽高 + CGFloat originEmptyWidth = self.ly_width; + CGFloat originEmptyHeight = self.ly_height; + + CGFloat emptyViewCenterX = originEmptyWidth * 0.5f; + CGFloat emptyViewCenterY = originEmptyHeight * 0.5f; + + //不是完全覆盖父视图时,重新设置self的frame(大小为content的大小) + if (!self.emptyViewIsCompleteCoverSuperView) { + self.ly_size = CGSizeMake(contentWidth, contentHeight); + } + self.center = CGPointMake(emptyViewCenterX, emptyViewCenterY); + + //设置contentView + self.contentView.ly_size = CGSizeMake(contentWidth, contentHeight); + if (self.emptyViewIsCompleteCoverSuperView) { + self.contentView.center = CGPointMake(emptyViewCenterX, emptyViewCenterY); + } else { + self.contentView.center = CGPointMake(contentWidth*0.5, contentHeight*0.5); + } + + //子控件的centerX设置 + CGFloat centerX = self.contentView.ly_width * 0.5f; + if (self.customView) { + self.customView.ly_centerX = centerX; + + }else{ + _promptImageView.ly_centerX = centerX; + _titleLabel.ly_centerX = centerX; + _detailLabel.ly_centerX = centerX; + _actionButton.ly_centerX = centerX; + } + + if (self.contentViewOffset) { //有无设置偏移 + self.ly_centerY += self.contentViewOffset; + + } else if (self.contentViewY < 1000) { //有无设置Y坐标值 + self.ly_y = self.contentViewY; + + } + + //是否忽略scrollView的contentInset + if (self.ignoreContentInset && [self.superview isKindOfClass:[UIScrollView class]]) { + UIScrollView *scrollView = (UIScrollView *)self.superview; + self.ly_centerY -= scrollView.contentInset.top; + self.ly_centerX -= scrollView.contentInset.left; + self.ly_centerY += scrollView.contentInset.bottom; + self.ly_centerX += scrollView.contentInset.right; + } +} + +#pragma mark - ------------------ Setup View ------------------ +- (void)setupPromptImageView:(UIImage *)img{ + + self.promptImageView.image = img; + + CGFloat imgViewWidth = img.size.width; + CGFloat imgViewHeight = img.size.height; + + if (self.imageSize.width && self.imageSize.height) {//设置了宽高大小 + if (imgViewWidth > imgViewHeight) {//以宽为基准,按比例缩放高度 + imgViewHeight = (imgViewHeight / imgViewWidth) * self.imageSize.width; + imgViewWidth = self.imageSize.width; + + }else{//以高为基准,按比例缩放宽度 + imgViewWidth = (imgViewWidth / imgViewHeight) * self.imageSize.height; + imgViewHeight = self.imageSize.height; + } + } + self.promptImageView.frame = CGRectMake(0, 0, imgViewWidth, imgViewHeight); + + contentWidth = self.promptImageView.ly_size.width; + contentHeight = self.promptImageView.ly_maxY; +} + +- (void)setupTitleLabel:(NSString *)titleStr{ + + UIFont *font = self.titleLabFont.pointSize ? self.titleLabFont : kTitleLabFont; + CGFloat fontSize = font.pointSize; + UIColor *textColor = self.titleLabTextColor ? self.titleLabTextColor : kBlackColor; + CGFloat titleMargin = self.titleLabMargin > 0 ? self.titleLabMargin : (contentHeight == 0 ?: subViweMargin); + CGSize size = [self returnTextWidth:titleStr size:CGSizeMake(contentMaxWidth, fontSize + 5) font:font]; + + CGFloat width = size.width; + CGFloat height = size.height; + + self.titleLabel.frame = CGRectMake(0, contentHeight + titleMargin, width, height); + self.titleLabel.font = font; + self.titleLabel.text = titleStr; + self.titleLabel.textColor = textColor; + + contentWidth = width > contentWidth ? width : contentWidth; + contentHeight = self.titleLabel.ly_maxY; +} + +- (void)setupDetailLabel:(NSString *)detailStr{ + + UIColor *textColor = self.detailLabTextColor ? self.detailLabTextColor : kGrayColor; + UIFont *font = self.detailLabFont.pointSize ? self.detailLabFont : kDetailLabFont; + CGFloat fontSize = font.pointSize; + CGFloat maxLines = self.detailLabMaxLines > 0 ? self.detailLabMaxLines : 1; + CGFloat detailMargin = self.detailLabMargin > 0 ? self.detailLabMargin : (contentHeight == 0 ?: subViweMargin); + self.detailLabel.font = font; + self.detailLabel.textColor = textColor; + self.detailLabel.text = detailStr; + + CGFloat width = 0; + CGFloat height = 0; + + //设置行高 + if(self.detailLabLineSpacing){ + + CGFloat maxHeight = maxLines * (fontSize + 5) + (maxLines-1) * self.detailLabLineSpacing; + + NSDictionary *dic = [self sizeWithAttributedString:self.detailLabel.text font:font lineSpacing:self.detailLabLineSpacing maxSize:CGSizeMake(contentMaxWidth, maxHeight)]; + + NSMutableAttributedString *attStr = dic[@"attributed"]; + NSValue *sizeValue = dic[@"size"]; + CGSize size = sizeValue.CGSizeValue; + width = size.width; + height = size.height; + self.detailLabel.attributedText = attStr; + + } + else{ + + CGFloat maxHeight = maxLines * (fontSize + 5); + CGSize size = [self returnTextWidth:detailStr size:CGSizeMake(contentMaxWidth, maxHeight) font:font];//计算得出label大小 + width = size.width; + height = size.height; + } + + self.detailLabel.frame = CGRectMake(0, contentHeight + detailMargin, width, height); + + contentWidth = width > contentWidth ? width : contentWidth; + contentHeight = self.detailLabel.ly_maxY; + +} + +- (void)setupActionBtn:(NSString *)btnTitle target:(id)target action:(SEL)action btnClickBlock:(LYActionTapBlock)btnClickBlock{ + + UIFont *font = self.actionBtnFont.pointSize ? self.actionBtnFont : kActionBtnFont; + CGFloat fontSize = font.pointSize; + UIColor *titleColor = self.actionBtnTitleColor ?: kBlackColor; + UIColor *backGColor = self.actionBtnBackGroundColor ?: [UIColor whiteColor]; + UIColor *borderColor = self.actionBtnBorderColor ?: [UIColor colorWithRed:0.8f green:0.8f blue:0.8f alpha:1.f]; + CGFloat borderWidth = self.actionBtnBorderWidth ?: 0; + CGFloat cornerRadius = self.actionBtnCornerRadius ?: 0; + CGFloat width = self.actionBtnWidth; + CGFloat horiMargin = self.actionBtnHorizontalMargin; + CGFloat height = self.actionBtnHeight; + CGSize textSize = [self returnTextWidth:btnTitle size:CGSizeMake(contentMaxWidth, fontSize) font:font];//计算得出title文字内容大小 + if (height < textSize.height) { + height = textSize.height + 4.f; + } + + //按钮的宽 + CGFloat btnWidth = textSize.width; + if (width) { + btnWidth = width; + } else if (horiMargin) { + btnWidth = textSize.width + horiMargin * 2.f; + } + + //按钮的高 + CGFloat btnHeight = height; + btnWidth = btnWidth > contentMaxWidth ? contentMaxWidth : btnWidth; + CGFloat btnMargin = self.actionBtnMargin > 0 ? self.actionBtnMargin : (contentHeight == 0 ?: subViweMargin); + + self.actionButton.frame = CGRectMake(0, contentHeight + btnMargin, btnWidth, btnHeight); + [self.actionButton setTitle:btnTitle forState:UIControlStateNormal]; + self.actionButton.titleLabel.font = font; + self.actionButton.backgroundColor = backGColor; + if (self.actionBtnBackGroundGradientColors) [self addGradientWithView:self.actionButton gradientColors:self.actionBtnBackGroundGradientColors]; + [self.actionButton setTitleColor:titleColor forState:UIControlStateNormal]; + self.actionButton.layer.borderColor = borderColor.CGColor; + self.actionButton.layer.borderWidth = borderWidth; + self.actionButton.layer.cornerRadius = cornerRadius; + + //添加事件 + if (target && action) { + [self.actionButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; + [self.actionButton addTarget:self action:@selector(actionBtnClick:) forControlEvents:UIControlEventTouchUpInside]; + }else if (btnClickBlock) { + [self.actionButton addTarget:self action:@selector(actionBtnClick:) forControlEvents:UIControlEventTouchUpInside]; + } + + contentWidth = btnWidth > contentWidth ? btnWidth : contentWidth; + contentHeight = self.actionButton.ly_maxY; +} + +#pragma mark - ------------------ Event Method ------------------ +- (void)actionBtnClick:(UIButton *)sender{ + if (self.btnClickBlock) { + self.btnClickBlock(); + } +} + +#pragma mark - ------------------ setter ------------------ + +- (void)setEmptyViewIsCompleteCoverSuperView:(BOOL)emptyViewIsCompleteCoverSuperView{ + _emptyViewIsCompleteCoverSuperView = emptyViewIsCompleteCoverSuperView; + if (emptyViewIsCompleteCoverSuperView) { + if (!self.backgroundColor || [self.backgroundColor isEqual:[UIColor clearColor]]) { + self.backgroundColor = kBackgroundColor; + } + [self setNeedsLayout]; + }else{ + self.backgroundColor = [UIColor clearColor]; + } +} + +#pragma mark 内容物背景视图 相关 +- (void)setSubViewMargin:(CGFloat)subViewMargin{ + if (_subViewMargin != subViewMargin) { + _subViewMargin = subViewMargin; + + [self reSetupSubviews]; + } +} +- (void)setTitleLabMargin:(CGFloat)titleLabMargin{ + if (_titleLabMargin != titleLabMargin) { + _titleLabMargin = titleLabMargin; + + [self reSetupSubviews]; + } +} +- (void)setDetailLabMargin:(CGFloat)detailLabMargin{ + if (_detailLabMargin != detailLabMargin) { + _detailLabMargin = detailLabMargin; + + [self reSetupSubviews]; + } +} +- (void)setActionBtnMargin:(CGFloat)actionBtnMargin{ + if (_actionBtnMargin != actionBtnMargin) { + _actionBtnMargin = actionBtnMargin; + + [self reSetupSubviews]; + } +} +- (void)reSetupSubviews{ + if (_promptImageView || _titleLabel || _detailLabel || _actionButton || self.customView) {//此判断的意思只是确定self是否已加载完毕 + [self setupSubviews]; + } +} +- (void)setContentViewOffset:(CGFloat)contentViewOffset{ + if (_contentViewOffset != contentViewOffset) { + _contentViewOffset = contentViewOffset; + + if (_promptImageView || _titleLabel || _detailLabel || _actionButton || self.customView) { + self.ly_centerY += self.contentViewOffset; + } + } +} +- (void)setContentViewY:(CGFloat)contentViewY{ + if (_contentViewY != contentViewY) { + _contentViewY = contentViewY; + + if (_promptImageView || _titleLabel || _detailLabel || _actionButton || self.customView) { + self.ly_y = self.contentViewY; + } + } +} + +#pragma mark 提示图Image 相关 +- (void)setImageSize:(CGSize)imageSize{ + if (_imageSize.width != imageSize.width || _imageSize.height != imageSize.height) { + _imageSize = imageSize; + + if (_promptImageView) { + [self setupSubviews]; + } + } +} + +#pragma mark 描述Label 相关 +- (void)setTitleLabFont:(UIFont *)titleLabFont{ + if (_titleLabFont != titleLabFont) { + _titleLabFont = titleLabFont; + + if (_titleLabel) { + [self setupSubviews]; + } + } + +} +- (void)setTitleLabTextColor:(UIColor *)titleLabTextColor{ + if (_titleLabTextColor != titleLabTextColor) { + _titleLabTextColor = titleLabTextColor; + + if (_titleLabel) { + _titleLabel.textColor = titleLabTextColor; + } + } +} + +#pragma mark 详细描述Label 相关 +- (void)setDetailLabFont:(UIFont *)detailLabFont{ + if (_detailLabFont != detailLabFont) { + _detailLabFont = detailLabFont; + + if (_detailLabel) { + [self setupSubviews]; + } + } +} +- (void)setDetailLabMaxLines:(NSInteger)detailLabMaxLines{ + if (_detailLabMaxLines != detailLabMaxLines) { + _detailLabMaxLines = detailLabMaxLines; + + if (_detailLabel) { + [self setupSubviews]; + } + } +} +- (void)setDetailLabTextColor:(UIColor *)detailLabTextColor{ + if (_detailLabTextColor != detailLabTextColor) { + _detailLabTextColor = detailLabTextColor; + + if (_detailLabel) { + _detailLabel.textColor = detailLabTextColor; + } + } +} + +- (void)setDetailLabLineSpacing:(NSInteger)detailLabLineSpacing{ + if (_detailLabLineSpacing != detailLabLineSpacing) { + _detailLabLineSpacing = detailLabLineSpacing; + + if (_detailLabel) { + [self setupSubviews]; + } + } +} + +#pragma mark Button 相关 +//////////大小位置相关-需要重新布局 +- (void)setActionBtnFont:(UIFont *)actionBtnFont{ + if (_actionBtnFont != actionBtnFont) { + _actionBtnFont = actionBtnFont; + + if (_actionButton) { + [self setupSubviews]; + } + } +} +- (void)setActionBtnHeight:(CGFloat)actionBtnHeight{ + if (_actionBtnHeight != actionBtnHeight) { + _actionBtnHeight = actionBtnHeight; + + if (_actionButton) { + [self setupSubviews]; + } + } +} +- (void)setActionBtnWidth:(CGFloat)actionBtnWidth{ + if (_actionBtnWidth != actionBtnWidth) { + _actionBtnWidth = actionBtnWidth; + + if (_actionButton) { + [self setupSubviews]; + } + } +} +- (void)setActionBtnHorizontalMargin:(CGFloat)actionBtnHorizontalMargin{ + if (_actionBtnHorizontalMargin != actionBtnHorizontalMargin) { + _actionBtnHorizontalMargin = actionBtnHorizontalMargin; + + if (_actionButton) { + [self setupSubviews]; + } + } +} +//////////其他相关-直接赋值 +- (void)setActionBtnCornerRadius:(CGFloat)actionBtnCornerRadius{ + if (_actionBtnCornerRadius != actionBtnCornerRadius) { + _actionBtnCornerRadius = actionBtnCornerRadius; + + if (_actionButton) { + _actionButton.layer.cornerRadius = actionBtnCornerRadius; + } + } +} +- (void)setActionBtnBorderWidth:(CGFloat)actionBtnBorderWidth{ + if (actionBtnBorderWidth != _actionBtnBorderWidth) { + _actionBtnBorderWidth = actionBtnBorderWidth; + + if (_actionButton) { + _actionButton.layer.borderWidth = actionBtnBorderWidth; + } + } +} +- (void)setActionBtnBorderColor:(UIColor *)actionBtnBorderColor{ + if (_actionBtnBorderColor != actionBtnBorderColor) { + _actionBtnBorderColor = actionBtnBorderColor; + + if (_actionButton) { + _actionButton.layer.borderColor = actionBtnBorderColor.CGColor; + } + } +} +- (void)setActionBtnTitleColor:(UIColor *)actionBtnTitleColor{ + if (_actionBtnTitleColor != actionBtnTitleColor) { + _actionBtnTitleColor = actionBtnTitleColor; + + if (_actionButton) { + [_actionButton setTitleColor:actionBtnTitleColor forState:UIControlStateNormal]; + } + } +} +- (void)setActionBtnBackGroundColor:(UIColor *)actionBtnBackGroundColor{ + if (actionBtnBackGroundColor != _actionBtnBackGroundColor) { + _actionBtnBackGroundColor = actionBtnBackGroundColor; + + if (_actionButton) { + [_actionButton setBackgroundColor:actionBtnBackGroundColor]; + } + } +} +- (void)setActionBtnBackGroundGradientColors:(NSArray *)actionBtnBackGroundGradientColors +{ + if (actionBtnBackGroundGradientColors.count >= 2) { + _actionBtnBackGroundGradientColors = [actionBtnBackGroundGradientColors subarrayWithRange:NSMakeRange(0, 2)]; + if (_actionButton) { + [self addGradientWithView:_actionButton gradientColors:_actionBtnBackGroundGradientColors]; + } + } +} + +#pragma mark - ------------------ getter ------------------ +- (UIImageView *)promptImageView{ + if (!_promptImageView) { + _promptImageView = [[UIImageView alloc] init]; + _promptImageView.contentMode = UIViewContentModeScaleAspectFit; + [self.contentView addSubview:_promptImageView]; + } + return _promptImageView; +} +- (UILabel *)titleLabel{ + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + [self.contentView addSubview:_titleLabel]; + } + return _titleLabel; +} +- (UILabel *)detailLabel{ + if (!_detailLabel) { + _detailLabel = [[UILabel alloc] init]; + _detailLabel.textAlignment = NSTextAlignmentCenter; + _detailLabel.numberOfLines = 0; + [self.contentView addSubview:_detailLabel]; + } + return _detailLabel; +} +- (UIButton *)actionButton{ + if (!_actionButton) { + _actionButton = [[UIButton alloc] init]; + _actionButton.layer.masksToBounds = YES; + [self.contentView addSubview:_actionButton]; + } + return _actionButton; +} + +#pragma mark - ------------------ Help Method ------------------ +- (CGSize)returnTextWidth:(NSString *)text size:(CGSize)size font:(UIFont *)font{ + CGSize textSize = [text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil].size; + return textSize; +} + +- (NSDictionary *)sizeWithAttributedString:(NSString *)string font:(UIFont *)font lineSpacing:(CGFloat)lineSpacing maxSize:(CGSize)maxSize{ + + NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; + paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; + paragraphStyle.lineSpacing = lineSpacing; // 设置行间距 + paragraphStyle.alignment = NSTextAlignmentCenter; + + NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:string attributes:@{NSParagraphStyleAttributeName: paragraphStyle, NSFontAttributeName:font}]; + + CGSize size = [attributedStr boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size; + + NSDictionary *dic = @{ + @"attributed":attributedStr, + @"size": [NSValue valueWithCGSize:size] + }; + return dic; +} + +- (void)addGradientWithView:(UIView *)view gradientColors:(NSArray *)gradientColors +{ + [view setBackgroundColor:[UIColor clearColor]]; + + NSArray *colors = @[(__bridge id)[gradientColors.firstObject CGColor], + (__bridge id)[gradientColors.lastObject CGColor]]; + CAGradientLayer *layer = [CAGradientLayer layer]; + layer.colors = colors; + layer.locations = @[@0.3, @0.5, @1.0]; + layer.startPoint = CGPointMake(0, 0); + layer.endPoint = CGPointMake(1.0, 0); + layer.frame = view.bounds; + layer.masksToBounds = YES; + layer.cornerRadius = view.frame.size.height * 0.5; + + CALayer *firstLayer = self.layer.sublayers.firstObject; + if ([firstLayer isKindOfClass:[CAGradientLayer class]]) { + [view.layer replaceSublayer:firstLayer with:layer]; + } else { + [view.layer insertSublayer:layer atIndex:0]; + } +} + +@end diff --git a/Pods/LYEmptyView/LYEmptyView/LYEmptyViewHeader.h b/Pods/LYEmptyView/LYEmptyView/LYEmptyViewHeader.h new file mode 100644 index 0000000..e99b96f --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/LYEmptyViewHeader.h @@ -0,0 +1,15 @@ +// +// LYEmptyViewHeader.h +// LYEmptyViewDemo +// +// Created by 李阳 on 2017/5/11. +// Copyright © 2017年 liyang. All rights reserved. +// + +#ifndef LYEmptyViewHeader_h +#define LYEmptyViewHeader_h + +#import "LYEmptyView.h" +#import "UIView+Empty.h" + +#endif /* LYEmptyViewHeader_h */ diff --git a/Pods/LYEmptyView/LYEmptyView/UIView+Empty.h b/Pods/LYEmptyView/LYEmptyView/UIView+Empty.h new file mode 100644 index 0000000..2ac8e07 --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/UIView+Empty.h @@ -0,0 +1,54 @@ +// +// UIView+Empty.h +// LYEmptyViewDemo +// +// Created by liyang on 2018/5/10. +// Copyright © 2018年 liyang. All rights reserved. +// + +#import + +@class LYEmptyView; + +@interface UIView (Empty) + +/** + 空页面占位图控件 + */ +@property (nonatomic, strong) LYEmptyView *ly_emptyView; + +/////////////////////// +/////////////////////// +//使用下面的四个方法请将EmptyView的autoShowEmptyView值置为NO,关闭自动显隐,以保证不受自动显隐的影响 +/////////////////////// +/////////////////////// + +/** + 一般用于开始请求网络时调用,ly_startLoading调用时会暂时隐藏emptyView + 当调用ly_endLoading方法时,ly_endLoading方法内部会根据当前的tableView/collectionView的 + DataSource来自动判断是否显示emptyView + */ +- (void)ly_startLoading; + +/** + 在想要刷新emptyView状态时调用 + 注意:ly_endLoading 的调用时机,有刷新UI的地方一定要等到刷新UI的方法之后调用, + 因为只有刷新了UI,view的DataSource才会更新,故调用此方法才能正确判断是否有内容。 + */ +- (void)ly_endLoading; + + +//调用下面两个手动显隐的方法,不受DataSource的影响,单独设置显示与隐藏(前提是关闭autoShowEmptyView) + +/** + 手动调用显示emptyView + */ +- (void)ly_showEmptyView; + +/** + 手动调用隐藏emptyView + */ +- (void)ly_hideEmptyView; + +@end + diff --git a/Pods/LYEmptyView/LYEmptyView/UIView+Empty.m b/Pods/LYEmptyView/LYEmptyView/UIView+Empty.m new file mode 100644 index 0000000..5cc2332 --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/UIView+Empty.m @@ -0,0 +1,224 @@ +// +// UIView+Empty.m +// LYEmptyViewDemo +// +// Created by liyang on 2018/5/10. +// Copyright © 2018年 liyang. All rights reserved. +// + +#import "UIView+Empty.h" +#import +#import "LYEmptyView.h" + +#pragma mark - ------------------ UIView ------------------ + +@implementation UIView (Empty) + ++ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2 +{ + method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2)); +} + +#pragma mark - Setter/Getter + +static char kEmptyViewKey; +- (void)setLy_emptyView:(LYEmptyView *)ly_emptyView{ + if (ly_emptyView != self.ly_emptyView) { + + objc_setAssociatedObject(self, &kEmptyViewKey, ly_emptyView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + for (UIView *view in self.subviews) { + if ([view isKindOfClass:[LYEmptyView class]]) { + [view removeFromSuperview]; + } + } + [self addSubview:self.ly_emptyView]; + + if ([self isKindOfClass:[UITableView class]] || [self isKindOfClass:[UICollectionView class]]) { + [self getDataAndSet]; // 添加时根据DataSource去决定显隐 + } else { + self.ly_emptyView.hidden = YES;// 添加时默认隐藏 + } + } +} +- (LYEmptyView *)ly_emptyView{ + return objc_getAssociatedObject(self, &kEmptyViewKey); +} + +#pragma mark - Private Method (UITableView、UICollectionView有效) +- (NSInteger)totalDataCount +{ + NSInteger totalCount = 0; + if ([self isKindOfClass:[UITableView class]]) { + UITableView *tableView = (UITableView *)self; + + for (NSInteger section = 0; section < tableView.numberOfSections; section++) { + totalCount += [tableView numberOfRowsInSection:section]; + } + } else if ([self isKindOfClass:[UICollectionView class]]) { + UICollectionView *collectionView = (UICollectionView *)self; + + for (NSInteger section = 0; section < collectionView.numberOfSections; section++) { + totalCount += [collectionView numberOfItemsInSection:section]; + } + } + return totalCount; +} +- (void)getDataAndSet{ + //没有设置emptyView的,直接返回 + if (!self.ly_emptyView) { + return; + } + + if ([self totalDataCount] == 0) { + [self show]; + }else{ + [self hide]; + } +} +- (void)show{ + //当不自动显隐时,内部自动调用show方法时也不要去显示,要显示的话只有手动去调用 ly_showEmptyView + if (!self.ly_emptyView.autoShowEmptyView) { + return; + } + + [self ly_showEmptyView]; +} +- (void)hide{ + //当不自动显隐时,内部自动调用hide方法时也不要去隐藏,要隐藏的话只有手动去调用 ly_hideEmptyView + if (!self.ly_emptyView.autoShowEmptyView) { + return; + } + + [self ly_hideEmptyView]; +} + +#pragma mark - Public Method +- (void)ly_showEmptyView{ + + NSAssert(![self isKindOfClass:[LYEmptyView class]], @"LYEmptyView及其子类不能调用ly_showEmptyView方法"); + + self.ly_emptyView.hidden = NO; + + //让 emptyBGView 始终保持在最上层 + [self bringSubviewToFront:self.ly_emptyView]; +} +- (void)ly_hideEmptyView{ + NSAssert(![self isKindOfClass:[LYEmptyView class]], @"LYEmptyView及其子类不能调用ly_hideEmptyView方法"); + self.ly_emptyView.hidden = YES; +} +- (void)ly_startLoading{ + NSAssert(![self isKindOfClass:[LYEmptyView class]], @"LYEmptyView及其子类不能调用ly_startLoading方法"); + self.ly_emptyView.hidden = YES; +} +- (void)ly_endLoading{ + NSAssert(![self isKindOfClass:[LYEmptyView class]], @"LYEmptyView及其子类不能调用ly_endLoading方法"); + self.ly_emptyView.hidden = [self totalDataCount]; +} + +@end + +#pragma mark - ------------------ UITableView ------------------ + +@implementation UITableView (Empty) ++ (void)load{ + + [self exchangeInstanceMethod1:@selector(reloadData) method2:@selector(ly_reloadData)]; + + ///section + [self exchangeInstanceMethod1:@selector(insertSections:withRowAnimation:) method2:@selector(ly_insertSections:withRowAnimation:)]; + [self exchangeInstanceMethod1:@selector(deleteSections:withRowAnimation:) method2:@selector(ly_deleteSections:withRowAnimation:)]; + [self exchangeInstanceMethod1:@selector(reloadSections:withRowAnimation:) method2:@selector(ly_reloadSections:withRowAnimation:)]; + + ///row + [self exchangeInstanceMethod1:@selector(insertRowsAtIndexPaths:withRowAnimation:) method2:@selector(ly_insertRowsAtIndexPaths:withRowAnimation:)]; + [self exchangeInstanceMethod1:@selector(deleteRowsAtIndexPaths:withRowAnimation:) method2:@selector(ly_deleteRowsAtIndexPaths:withRowAnimation:)]; + [self exchangeInstanceMethod1:@selector(reloadRowsAtIndexPaths:withRowAnimation:) method2:@selector(ly_reloadRowsAtIndexPaths:withRowAnimation:)]; +} +- (void)ly_reloadData{ + [self ly_reloadData]; + [self getDataAndSet]; +} +///section +- (void)ly_insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{ + [self ly_insertSections:sections withRowAnimation:animation]; + [self getDataAndSet]; +} +- (void)ly_deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{ + [self ly_deleteSections:sections withRowAnimation:animation]; + [self getDataAndSet]; +} +- (void)ly_reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{ + [self ly_reloadSections:sections withRowAnimation:animation]; + [self getDataAndSet]; +} + +///row +- (void)ly_insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation{ + [self ly_insertRowsAtIndexPaths:indexPaths withRowAnimation:animation]; + [self getDataAndSet]; +} +- (void)ly_deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation{ + [self ly_deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation]; + [self getDataAndSet]; +} +- (void)ly_reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation{ + [self ly_reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation]; + [self getDataAndSet]; +} + + +@end + +#pragma mark - ------------------ UICollectionView ------------------ + +@implementation UICollectionView (Empty) + ++ (void)load{ + + [self exchangeInstanceMethod1:@selector(reloadData) method2:@selector(ly_reloadData)]; + + ///section + [self exchangeInstanceMethod1:@selector(insertSections:) method2:@selector(ly_insertSections:)]; + [self exchangeInstanceMethod1:@selector(deleteSections:) method2:@selector(ly_deleteSections:)]; + [self exchangeInstanceMethod1:@selector(reloadSections:) method2:@selector(ly_reloadSections:)]; + + ///item + [self exchangeInstanceMethod1:@selector(insertItemsAtIndexPaths:) method2:@selector(ly_insertItemsAtIndexPaths:)]; + [self exchangeInstanceMethod1:@selector(deleteItemsAtIndexPaths:) method2:@selector(ly_deleteItemsAtIndexPaths:)]; + [self exchangeInstanceMethod1:@selector(reloadItemsAtIndexPaths:) method2:@selector(ly_reloadItemsAtIndexPaths:)]; + +} +- (void)ly_reloadData{ + [self ly_reloadData]; + [self getDataAndSet]; +} +///section +- (void)ly_insertSections:(NSIndexSet *)sections{ + [self ly_insertSections:sections]; + [self getDataAndSet]; +} +- (void)ly_deleteSections:(NSIndexSet *)sections{ + [self ly_deleteSections:sections]; + [self getDataAndSet]; +} +- (void)ly_reloadSections:(NSIndexSet *)sections{ + [self ly_reloadSections:sections]; + [self getDataAndSet]; +} + +///item +- (void)ly_insertItemsAtIndexPaths:(NSArray *)indexPaths{ + [self ly_insertItemsAtIndexPaths:indexPaths]; + [self getDataAndSet]; +} +- (void)ly_deleteItemsAtIndexPaths:(NSArray *)indexPaths{ + [self ly_deleteItemsAtIndexPaths:indexPaths]; + [self getDataAndSet]; +} +- (void)ly_reloadItemsAtIndexPaths:(NSArray *)indexPaths{ + [self ly_reloadItemsAtIndexPaths:indexPaths]; + [self getDataAndSet]; +} +@end + diff --git a/Pods/LYEmptyView/LYEmptyView/UIView+LYExtension.h b/Pods/LYEmptyView/LYEmptyView/UIView+LYExtension.h new file mode 100644 index 0000000..44fabf0 --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/UIView+LYExtension.h @@ -0,0 +1,26 @@ +// +// UIView+LYExtension.h +// LYEmptyViewDemo +// +// Created by 李阳 on 2017/5/12. +// Copyright © 2017年 liyang. All rights reserved. +// + +#import + +@interface UIView (LYExtension) + +@property (nonatomic, assign) CGFloat ly_x; +@property (nonatomic, assign) CGFloat ly_y; +@property (nonatomic, assign) CGFloat ly_width; +@property (nonatomic, assign) CGFloat ly_height; +@property (nonatomic, assign) CGFloat ly_centerX; +@property (nonatomic, assign) CGFloat ly_centerY; +@property (nonatomic, assign) CGSize ly_size; +@property (nonatomic, assign) CGPoint ly_origin; +@property (nonatomic, assign, readonly) CGFloat ly_maxX; +@property (nonatomic, assign, readonly) CGFloat ly_maxY; + + +@end + diff --git a/Pods/LYEmptyView/LYEmptyView/UIView+LYExtension.m b/Pods/LYEmptyView/LYEmptyView/UIView+LYExtension.m new file mode 100644 index 0000000..a1ab06e --- /dev/null +++ b/Pods/LYEmptyView/LYEmptyView/UIView+LYExtension.m @@ -0,0 +1,108 @@ +// +// UIView+LYExtension.m +// LYEmptyViewDemo +// +// Created by 李阳 on 2017/5/12. +// Copyright © 2017年 liyang. All rights reserved. +// + +#import "UIView+LYExtension.h" + +@implementation UIView (LYExtension) + +- (void)setLy_x:(CGFloat)ly_x{ + + CGRect frame = self.frame; + frame.origin.x = ly_x; + self.frame = frame; +} +- (CGFloat)ly_x +{ + return self.frame.origin.x; +} + +- (void)setLy_y:(CGFloat)ly_y{ + + CGRect frame = self.frame; + frame.origin.y = ly_y; + self.frame = frame; +} +- (CGFloat)ly_y +{ + return self.frame.origin.y; +} + +- (void)setLy_centerX:(CGFloat)ly_centerX{ + CGPoint center = self.center; + center.x = ly_centerX; + self.center = center; +} +- (CGFloat)ly_centerX +{ + return self.center.x; +} + +- (void)setLy_centerY:(CGFloat)ly_centerY +{ + CGPoint center = self.center; + center.y = ly_centerY; + self.center = center; +} +- (CGFloat)ly_centerY +{ + return self.center.y; +} + +- (void)setLy_width:(CGFloat)ly_width +{ + CGRect frame = self.frame; + frame.size.width = ly_width; + self.frame = frame; +} +- (CGFloat)ly_width +{ + return self.frame.size.width; +} + +- (void)setLy_height:(CGFloat)ly_height +{ + CGRect frame = self.frame; + frame.size.height = ly_height; + self.frame = frame; +} +- (CGFloat)ly_height +{ + return self.frame.size.height; +} + +- (void)setLy_size:(CGSize)ly_size +{ + CGRect frame = self.frame; + frame.size = ly_size; + self.frame = frame; +} +- (CGSize)ly_size +{ + return self.frame.size; +} + +- (void)setLy_origin:(CGPoint)ly_origin +{ + CGRect frame = self.frame; + frame.origin = ly_origin; + self.frame = frame; +} + +- (CGPoint)ly_origin +{ + return self.frame.origin; +} +- (CGFloat)ly_maxX{ + return self.frame.origin.x + self.frame.size.width; +} +- (CGFloat)ly_maxY{ + return self.frame.origin.y + self.frame.size.height; +} + +@end + diff --git a/Pods/LYEmptyView/README.md b/Pods/LYEmptyView/README.md new file mode 100644 index 0000000..404cd9d --- /dev/null +++ b/Pods/LYEmptyView/README.md @@ -0,0 +1,297 @@ +# LYEmptyView +不需要遵循协议,不需要设置代理,不需要实现代理方法,只需这一句代码,就可为一个UITableViwe/UICollectionView集成空白页面占位图。
`self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty];` + +#### 注意点: +#### 1.除UITableViwe/UICollectionView外,这些View(包括UIScrollView)没有DataSource,代码层面无法判断有无数据,需手动管理显示隐藏,调用示例请移步示例8 + +| 特点 | 描述 | +| ---------- | -----------| +| 与项目完全解耦 | 在需要集成的界面中加入一行代码即可集成,与原代码没有一点耦合度 | +| 0学习成本 | 无需关心视图的显示隐藏时机,只需加入一行代码即可,框架监听了系统刷新UI的方法,其内部计算后自动进行显示隐藏 | +| 调用简单 | 利用分类+runtime,使调用非常简便 | +| 高度自定义   | 利用继承特性,可对框架进行二次封装,使自定义更简便 | +| 支持全部的刷新方法 | reload...、insert...、delete...等方法。你的项目中调用这些刷新方法时,该框架都会自动根据DataSource自动进行计算判断是否显示emptyView | + +# 目录 +* [一、效果展示](#效果展示)
+* [二、集成方式](#集成方式)
+* [三、使用参考示例](#使用参考示例)
+ * [1.一行代码集成空内容视图](#一行代码集成空内容视图)
+ * [2.自由选择空内容元素](#自由选择空内容元素)
+ * [3.自定义空内容元素](#自定义空内容元素)
+ * [4.自定义元素的UI样式](#自定义元素的UI样式)
+ * [5.二次封装](#二次封装)
+ * [6.延迟显示emptyView](#延迟显示emptyView)
+ * [7.特殊需求,手动控制emptyView的显示隐藏](#特殊需求,手动控制emptyView的显示隐藏)
+ * [8.普通view调用示例](#普通view调用示例)
+ * [9.占位图完全覆盖父视图](#占位图完全覆盖父视图)
+ +## 一、效果展示 + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/ImitateOtherApp.png) + +## 二、集成方式 + +1.Cocoapods方式集成: `pod 'LYEmptyView'`
+使用时导入头文件 `#import ` +

+2.手动下载集成: 将LYEmptyView文件夹,导入你的工程
+使用时导入头文件:`#import "LYEmptyViewHeader.h"` + + +## 三、使用参考示例 + +### 1.一行代码集成空内容视图 + +```Objective-C +//框架方法 +self.tableView.ly_emptyView = [LYEmptyView emptyViewWithImageStr:@"noData" + titleStr:@"暂无数据,点击重新加载" + detailStr:@""]; +``` + +PS:可对库进行二次封装,调用更简洁(二次封装方法在下面的示例5中会讲到) +```Objective-C +//二次封装方法,调用简洁 +self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty]; +``` + +完全低耦合,在你的项目中加入这一行代码就可集成
+不管项目中是reloadData方法刷UI还是insert、delete等方式刷UI,不需做其他任何操作,只需这一行代码就可实现以下效果 + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/example1.gif) + +### 2.自由选择空内容元素 +```Objective-C +交互事件可选择SEL或block方式 +self.tableView.ly_emptyView = [LYEmptyView emptyActionViewWithImageStr:@"noData" + titleStr:@"无数据" + detailStr:@"请稍后再试!" + btnTitleStr:@"重新加载" + target:target + action:action]; +self.tableView.ly_emptyView = [LYEmptyView emptyActionViewWithImageStr:@"noData" + titleStr:@"" + detailStr:@"" + btnTitleStr:@"" + btnClickBlock:^{}]; +// imageStr   : 占位图片 +// titleStr   : 标题 +// detailStr   : 详细描述 +// btnTitleStr : 按钮标题 +``` +框架提供四个元素,传入相应元素的字符串即可显示对应元素(按钮的显示前提是传入target,action或btnClickBlock) +可根据项目需求,自由进行组合,如下只展示了部分组合效果 + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/example2.png) + +### 3.自定义空内容元素 +特殊情况下,如果空内容状态布局不满足需求时,可进行自定义
+通过方法` + (instancetype)emptyViewWithCustomView:(UIView *)customView;`
+传入一个View 即可创建一个自定义的emptyView +```Objective-C +self.tableView.ly_emptyView = [LYEmptyView emptyViewWithCustomView:customView]; +``` + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/example3.png) + + +### 4.自定义元素的UI样式 +这里自定义UI样式需要很多代码,别担心,在示例5中会讲解二次封装的方式,封装后调用时就只需要一行代码了 ^_^ +```Objective-C + //初始化一个emptyView + LYEmptyView *emptyView = [LYEmptyView emptyActionViewWithImageStr:@"noData" + titleStr:@"无数据" + detailStr:@"请稍后再试!" + btnTitleStr:@"重新加载" + btnClickBlock:^{}]; + //元素竖直方向的间距 + emptyView.subViewMargin = 20.f; + //标题颜色 + emptyView.titleLabTextColor = MainColor(90, 180, 160); + //描述字体 + emptyView.detailLabFont = [UIFont systemFontOfSize:17]; + //按钮背景色 + emptyView.actionBtnBackGroundColor = MainColor(90, 180, 160); + + //设置空内容占位图 + self.tableView.ly_emptyView = emptyView; +``` +>这里只列举了一些常用的属性,更多属性请到LYEmptyView.h查看 + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/example4.png) +### 5.二次封装 +第4小节的示例代码,修改emptyView的样式需要一个个属性单独去改,如果项目中每个界面都这么写就显得很麻烦,而且不易维护
+解决办法是对库进行二次封装,二次封装后,对UI样式单独管理,方便维护
+ +##### 1)新建一个类继承自LYEmptyView,例如demo中的MyDIYEmpty +##### 2)重写`- (void)prepare` 方法,并修改想要改变的元素的UI样式 +```Objective-C +- (void)prepare{ + [super prepare]; + + self.titleLabFont = [UIFont systemFontOfSize:25]; + self.titleLabTextColor = MainColor(90, 180, 160); + + self.detailLabFont = [UIFont systemFontOfSize:17]; + self.detailLabTextColor = MainColor(180, 120, 90); + self.detailLabMaxLines = 5; + + self.actionBtnBackGroundColor = MainColor(90, 180, 160); + self.actionBtnTitleColor = [UIColor whiteColor]; +} +``` +操作上面的两步就可实现对样式的单独管理
+调用方法不变,只是调用的类变成了MYDiyEmpty +```Objective-C +self.tableView.ly_emptyView = [MyDIYEmpty emptyActionViewWithImageStr:@"noData" + titleStr:@"无数据" + detailStr:@"请稍后再试!" + btnTitleStr:@"重新加载" +                                                        btnClickBlock:^{}]; +``` +##### 3)进一步封装显示的元素内容,比如无数据状态图、无网络状态图
+在MyDIYEmpty.h定义方法`+ (instancetype)diyNoDataEmpty;`
+在MyDIYEmpty.m实现方法 +```Objective-C ++ (instancetype)diyNoDataEmpty{ + return [MyDIYEmpty emptyViewWithImageStr:@"nodata" + titleStr:@"暂无数据" + detailStr:@"请检查您的网络连接是否正确!"]; +} +``` +>经过3步封装,自定义了UI样式,使管理更方便,使调用更简洁
+self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty]; + +### 6.延迟显示emptyView +如示例1图,框架自动根据DataSource计算是否显示emptyView,在空页面发起网络请求时,DataSource肯定为空,会自动显示emptyView,有的产品需求可能不希望这样,希望发起请求时暂时隐藏emptyView。 +本框架提供了两个方法可实现此需求,两个方法都是scrollView的分类,调用非常方便 +```Objective-C + /** + 一般用于开始请求网络时调用,ly_startLoading调用时会暂时隐藏emptyView + 当调用ly_endLoading方法时,ly_endLoading方法内部会根据当前的tableView/collectionView的 + DataSource来自动判断是否显示emptyView + */ +- (void)ly_startLoading; + + /** + 在想要刷新emptyView状态时调用 + 注意:ly_endLoading 的调用时机,有刷新UI的地方一定要等到刷新UI的方法之后调用, + 因为只有刷新了UI,view的DataSource才会更新,故调用此方法才能正确判断是否有内容。 + */ +- (void)ly_endLoading; +``` + +*注意点:使用这两个方法,请先将emptyView的autoShowEmptyView属性置为NO,关闭自动显隐 + +以下是调用示例(具体细节可参看demo中的demo2) +```Objective-C +//1.先设置样式 +self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty]; +//2.关闭自动显隐(此步可封装进自定义类中,相关调用就可省去这步) +self.tableView.ly_emptyView.autoShowEmptyView = NO; +//3.网络请求时调用 +[self.tableView ly_startLoading]; +//4.刷新UI时调用(保证在刷新UI后调用) +[self.tableView ly_endLoading]; +``` + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/example6.gif) + +### 7.特殊需求,手动控制emptyView的显示隐藏 +在某些特殊界面下,有的tableView/collectionView有固定的一些死数据,其它的数据根据网络加载,这时根据以上的示例方法可能达不到这需求。
+本框架提供另外的两个方法来解决这个问题。 + +```Objective-C +/** + 手动调用显示emptyView + */ +- (void)ly_showEmptyView; + +/** + 手动调用隐藏emptyView + */ +- (void)ly_hideEmptyView; +``` + +*注意点:使用这两个方法,请先将emptyView的autoShowEmptyView属性置为NO,关闭自动显隐 + +以下是调用示例(具体细节可参看demo中的demo4) +```Objective-C +//1.先设置样式 +self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty]; +//2.关闭自动显隐(此步可封装进自定义类中,相关调用就可省去这步) +self.tableView.ly_emptyView.autoShowEmptyView = NO; +//3.显示emptyView +[self.tableView ly_showEmptyView]; +//4.隐藏emptyView +[self.tableView ly_hideEmptyView]; +``` + +![](https://github.com/dev-liyang/LYEmptyView/blob/master/images/example7.gif) + +### 8.普通view调用示例 +因普通view(包括scrollView)没有DataSource,代码层面无法判断view上有无数据,所以view想要实现占位图, +还需通过两个方法来手动控制emptyView的显示和隐藏。 +以下是调用示例 +```Objective-C +//1.先设置样式 +self.view.ly_emptyView = [MyDIYEmpty diyNoDataEmpty]; +//2.显示emptyView +[self.view ly_showEmptyView]; +//3.隐藏emptyView +[self.view ly_hideEmptyView]; +``` +### 9.占位图完全覆盖父视图 +每个项目需求不同,有的占位图内容多大,占位图就多大,这种情况是默认的,不用设置属性。而有的占位图想要和父视图一样大,以达到覆盖住父视图的目的,这种情况下将LYEmptyView的emptyViewIsCompleteCoverSuperView属性值设置为YES即可。 +```Objective-C +DemoEmptyView *emptyView = [DemoEmptyView diyEmptyView]; +emptyView.emptyViewIsCompleteCoverSuperView = YES;//完全覆盖父视图,背景色默认为浅白色,可自行设置 +//emptyView.backgroundColor = [UIColor redColor];//自己设置背景色为红色,此设置也可封装到公共的地方(DemoEmptyView),就不用每次都单独设置了 +self.tableView.ly_emptyView = emptyView; +``` + +## 更新记录 + +### 2019-08-16 (pod V1.3.0) +* 1.detailLab添加行间距属性 +* 2.每个子控件可单独设置间距 +* 3.actionBtn添加渐变背景颜色属性 +* 4.更改添加emptyView时其显隐的逻辑 + +### 2019-07-04 (pod V1.2.5) +* 1.新增属性:按钮宽度actionBtnWidth +* 2.修改属性默认值:按钮的圆角actionBtnCornerRadius默认改为0 + +### 2019-06-18 (pod V1.2.4) +* 1.将点击重试事件加到emptyView上(当设置empty完全覆盖父视图时,就可实现点击屏幕重试的效果) +* 2.swift项目中imageNamed:方法string为nil时崩溃解决 + +### 2018-12-04 (pod V1.2.3) +* 1.fix bug:当子控件的文字被设置为空并再次设置为非空时, 子控件无法正常显示 +* 2.新增属性:ignoreContentInset,是否忽略scrollView的contentInset + +### 2018-09-11 (pod V1.2.2) +* 新增构造方法,具体请查看LYEmptyBaseView.h + +### 2018-08-22 (pod V1.2.1) +* 大神的建议,不要手动调用layoutSubviews。优化baseView里setter方法调用的重绘机制,使用setNeedsLayout更加优美 + +### 2018-07-31 (pod V1.2.0) +* 新增属性:emptyViewIsCompleteCoverSuperView, 占位图是否完全覆盖父视图 + +### 2018-05-11 (pod V1.1.0) +* 新增普通View可设置占位图,实现所有的View都能集成占位图 + +### 2018-03-26 (pod V1.0.3) +* 添加reloadSections、reloadRows、reloadItems 等方法的监听 +* emptyBaseView setter 方法bug fix + +### 2018-02-09 (pod V1.0.2) +* 解决只是在导入本框架的情况下,导致UIScrollView上的内容不显示的bug + + +## 技术交流 +本人QQ:944801216
+技术交流群:818290484
+大家有任何的问题和建议,可以联系我,我一定尽力为大家解决问题,也可以进群和大家一起交流。 diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index f68bbab..3166a6d 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -16,9 +16,20 @@ PODS: - AFNetworking/NSURLSession - Bugly (2.6.1) - DZNEmptyDataSet (1.8.1) + - FLAnimatedImage (1.0.17) + - HWPanModal (0.9.9) + - JXCategoryView (1.6.8) + - JXPagingView/Pager (2.1.3) - LookinServer (1.2.8): - LookinServer/Core (= 1.2.8) - LookinServer/Core (1.2.8) + - LSTPopView (0.3.10): + - LSTPopView/Code (= 0.3.10) + - LSTTimer + - LSTPopView/Code (0.3.10): + - LSTTimer + - LSTTimer (0.2.10) + - LYEmptyView (1.3.1) - Masonry (1.1.0) - MBProgressHUD (1.2.0) - MJExtension (3.4.2) @@ -31,7 +42,13 @@ DEPENDENCIES: - AFNetworking (= 4.0.1) - Bugly - DZNEmptyDataSet (= 1.8.1) + - FLAnimatedImage (~> 1.0.17) + - HWPanModal (~> 0.9.9) + - JXCategoryView (~> 1.6.8) + - JXPagingView/Pager (~> 2.1.3) - LookinServer + - LSTPopView (~> 0.3.10) + - LYEmptyView (~> 1.3.1) - Masonry (= 1.1.0) - MBProgressHUD (= 1.2.0) - MJExtension (= 3.4.2) @@ -43,7 +60,14 @@ SPEC REPOS: - AFNetworking - Bugly - DZNEmptyDataSet + - FLAnimatedImage + - HWPanModal + - JXCategoryView + - JXPagingView - LookinServer + - LSTPopView + - LSTTimer + - LYEmptyView - Masonry - MBProgressHUD - MJExtension @@ -54,13 +78,20 @@ SPEC CHECKSUMS: AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58 Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31 DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7 + FLAnimatedImage: bbf914596368867157cc71b38a8ec834b3eeb32b + HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2 + JXCategoryView: 262d503acea0b1278c79a1c25b7332ffaef4d518 + JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e LookinServer: 1b2b61c6402ae29fa22182d48f5cd067b4e99e80 + LSTPopView: 9379f00f6ce7d1fc620b50ab00ed3ef97b2d4d52 + LSTTimer: caf8f02ff366ca175cf4c1778d26c166183c1b6f + LYEmptyView: b6d418cfa38b78df0cf243f9a9c25ccbdc399922 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 SDWebImage: f29024626962457f3470184232766516dee8dfea -PODFILE CHECKSUM: e80851eaead44de926040a227bf16809774cc3d2 +PODFILE CHECKSUM: 74f734479eb0a17a905a260cec140c37703d4479 COCOAPODS: 1.16.2 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index ca6e5f9..8a4f23b 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -19,1110 +19,1612 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 00DAE48C9A4FBCD1FCAA922CA57B45F9 /* SDWebImageDownloaderRequestModifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AEE1DAEE2CD1BAB6DBCBC50916263A4 /* SDWebImageDownloaderRequestModifier.m */; }; - 021ACCD4343D154E4782A5ECE222A8DF /* LookinIvarTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = E05CD820CF8075CB902341061803D784 /* LookinIvarTrace.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 042D40751BD2F51FBE9FECD4707CBBE9 /* SDDeviceHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = F4DCF85783AA9A1B3A613F5BAC3C0FEC /* SDDeviceHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0453019EC6578A67B82CF569EC765546 /* SDFileAttributeHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 599EA7E2BEEE9D88C43DF182C6A874D1 /* SDFileAttributeHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 05E2B7C1DB7528A0BBEA1521BE0DBAF1 /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = EA5E2A6BFD8D228A6FF7C7C749D642DB /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 06C4E233E7977DB81A24482E69B2D7D7 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9F495B1E192CA5A7EA012DC8524457 /* UIImage+Transform.m */; }; - 0845A6CB7AE77A99CC475BD14101FE87 /* LookinAttrType.h in Headers */ = {isa = PBXBuildFile; fileRef = B12DF9FA146221C01FCE0D22DDBDC890 /* LookinAttrType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 08719ABCE689ED74FE7486B1E49DAA6C /* MJRefreshBackStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 58AA57BAA26D8C03E401EEFD3C78271F /* MJRefreshBackStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 089F3C4BAA46A37EC5763DD312771021 /* SDImageIOAnimatedCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = BF86BA22A3F81C27DE4346E22477D2CD /* SDImageIOAnimatedCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 08D50C5AC969A3701B6F9137CF3A10F1 /* UIImage+ForceDecode.m in Sources */ = {isa = PBXBuildFile; fileRef = BB09D1C81119E88D019FD33037BC5587 /* UIImage+ForceDecode.m */; }; - 09A2ACBC8CE1761652EAA20886AEFE10 /* SDImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FE87671299E95720DB52DD3375B566E /* SDImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0B0E6CECDF516BC83756C1D5515A725B /* SDAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = E70D2DE5FE013503515AE432AE16071A /* SDAsyncBlockOperation.m */; }; - 0B449236AF25C6C11B0DE3D6D0E4A19B /* LookinEventHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = F746B8A0D89C293CD78D1EE71CD25FF1 /* LookinEventHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0BE3B8DB6034364E7CF3AE9D01C7C0B4 /* CALayer+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBF905BC343AA0D52B6BC0B1E5B22E9 /* CALayer+Lookin.m */; }; - 0C79142D1349DD9A969F47A0A8AAA0CB /* Lookin_PTProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 84E9E0A3D552DFF9EC45D14794237342 /* Lookin_PTProtocol.m */; }; - 0EF10747EF2A02413E84BD5EF7C87A4B /* MJRefreshNormalHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 854F1B8C164960BB0D2721562BD6E7E5 /* MJRefreshNormalHeader.m */; }; - 0F1D0F5DCC8C94A4C684DF846D14F436 /* SDWebImagePrefetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE77633CA7FA3526B2AA79AB5F21A42 /* SDWebImagePrefetcher.m */; }; - 0FF9F459ED16719292443A4C99B52B20 /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D6CF72BA8B7618D0238AD641B57FE35 /* SDImageCache.m */; }; - 10017B43AC38C3A89D7AC1376C6E7066 /* SDImageLoadersManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 9964200935BD2352FD5DAD8C2AC9FE07 /* SDImageLoadersManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 104D9196010D2A8C52C0C19E9C9D52E8 /* MBProgressHUD-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 16C85770D72E9770C476992A31B3655F /* MBProgressHUD-dummy.m */; }; - 117F4B6F653A8DA2637C5C93B4993884 /* Peertalk.h in Headers */ = {isa = PBXBuildFile; fileRef = ED81CDC30BE2F7BBA09422B3CD1BDF85 /* Peertalk.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 11C929E6BFB46F981685446F26DCE605 /* MJRefreshAutoFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = D404BDF65C17843DC41C1611EAAA22EB /* MJRefreshAutoFooter.m */; }; - 11D4DC1FCE5647EEA8484AA4A880AF8F /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A6D5DE8BC7E18B47355B8494A426209 /* MBProgressHUD.m */; }; - 126496714AD564062A8C10787CC01B8B /* MJFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = 47E596E1EB48CB4E8DE37CC0D5122787 /* MJFoundation.m */; }; - 14943D0EE97A4966510A86F5C3FC66A5 /* MJExtension-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 808621872AB88E6448666731EB043018 /* MJExtension-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 14CA284AC4FF1EED75E785641EE98034 /* SDImageCacheConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F43D293502C6A280429EF2DEFA6C0E6 /* SDImageCacheConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 150116E888969E8304BA3E2BB6529461 /* LookinHierarchyFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DAD9E82D42212E9D52E28737BC21479 /* LookinHierarchyFile.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 15B27182B591769C57B55544260DC886 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 165F1C9CBD621828C788A3018D0426C5 /* SDImageAPNGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = BF679E0482D915265B5050368ABBB701 /* SDImageAPNGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0005259AEE76604A26E43EA994475B68 /* HWShoppingCartPresentingAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = C5D725B550FCED60C80870F1B120D3B4 /* HWShoppingCartPresentingAnimation.m */; }; + 00DAE48C9A4FBCD1FCAA922CA57B45F9 /* SDWebImageDownloaderRequestModifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 607560CCA2D3766D85B5AEE557812D0E /* SDWebImageDownloaderRequestModifier.m */; }; + 01D2F1D0ABE13AAB2CDC0C25E378E964 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EAC20398B46C2C580B542618314D9E /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 020FEDA58170EE1ABDF9E268D373CF4F /* JXCategoryNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = D5119B7CF0FE429CF0E185983E72F98F /* JXCategoryNumberView.m */; }; + 021ACCD4343D154E4782A5ECE222A8DF /* LookinIvarTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C9A4038FA1CE3381055E02DAAEC90E /* LookinIvarTrace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 03623FBDBE9F6B422E9A5C6EAD321A58 /* HWPanModalPresenterProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DE4F66BD16AF47C58F5E08D62D7916E3 /* HWPanModalPresenterProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 042D40751BD2F51FBE9FECD4707CBBE9 /* SDDeviceHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = F287F335FB60871C584FAC1904FF4181 /* SDDeviceHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0453019EC6578A67B82CF569EC765546 /* SDFileAttributeHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0ED5656E5971882A3EA314E222EBC2C5 /* SDFileAttributeHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 05E2B7C1DB7528A0BBEA1521BE0DBAF1 /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 7083FA062632CC52050FC4EB53D64E3A /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 05EEA40D460AB9A5A6E8D33AAAEF801E /* JXPagingView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 10AACE3BDEFABB8B9E709942B03E5595 /* JXPagingView-dummy.m */; }; + 06C4E233E7977DB81A24482E69B2D7D7 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EBF81CE72AA8B4B06F1BC37CFA7B96A /* UIImage+Transform.m */; }; + 0845A6CB7AE77A99CC475BD14101FE87 /* LookinAttrType.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E1D6C567F43B4A9410AC83170573DE /* LookinAttrType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 08719ABCE689ED74FE7486B1E49DAA6C /* MJRefreshBackStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = ED2A7F3394578B0F6BEA7FBFFE1E2291 /* MJRefreshBackStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 089F3C4BAA46A37EC5763DD312771021 /* SDImageIOAnimatedCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = B75E67C2319B8FDBF4D6263203A06D6B /* SDImageIOAnimatedCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 08D50C5AC969A3701B6F9137CF3A10F1 /* UIImage+ForceDecode.m in Sources */ = {isa = PBXBuildFile; fileRef = CF91BA63B659D0E10C9E123EBEAB8FA3 /* UIImage+ForceDecode.m */; }; + 09A2ACBC8CE1761652EAA20886AEFE10 /* SDImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5EF3B546633CC3DB26A173DE519AC3D7 /* SDImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0A7342FACEBA0077F1B06178940883DB /* HWPanModal.h in Headers */ = {isa = PBXBuildFile; fileRef = EC37DBDA721D0EFF5AB018086BE1B195 /* HWPanModal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0AA1842830C770B1E299BAC977E813D9 /* JXCategoryIndicatorRainbowLineView.h in Headers */ = {isa = PBXBuildFile; fileRef = D25C8F67455D872A48F4797213321EA4 /* JXCategoryIndicatorRainbowLineView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B0E6CECDF516BC83756C1D5515A725B /* SDAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A03E8820B42DFF0FCE849CB64302CAF /* SDAsyncBlockOperation.m */; }; + 0B449236AF25C6C11B0DE3D6D0E4A19B /* LookinEventHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 05EE9449F14265ADB3100E60632AB642 /* LookinEventHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0BE3B8DB6034364E7CF3AE9D01C7C0B4 /* CALayer+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 657631264951C7514A1788B1C6316E7F /* CALayer+Lookin.m */; }; + 0C312924F0A07471A1D04AD15D32BF3A /* JXCategoryIndicatorRainbowLineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 021930E01F482BDF2DEAAA2AF9FDCF18 /* JXCategoryIndicatorRainbowLineView.m */; }; + 0C79142D1349DD9A969F47A0A8AAA0CB /* Lookin_PTProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6F5F5F32C55F6B9F4E87EC57A0A074 /* Lookin_PTProtocol.m */; }; + 0D6EFFD314E70C1E547970D8CEF11131 /* JXPagerMainTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C2DAB09AC8F3AD6E82FDC5DB2562CB4 /* JXPagerMainTableView.m */; }; + 0E97928FD3B4476EDC015E83A8E2CAA3 /* UIView+Empty.m in Sources */ = {isa = PBXBuildFile; fileRef = A34A186C33DB71F8C4ACB6E0705472D0 /* UIView+Empty.m */; }; + 0EF10747EF2A02413E84BD5EF7C87A4B /* MJRefreshNormalHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 61D65BB6AAD351E64F3FE46FACDEED4F /* MJRefreshNormalHeader.m */; }; + 0F1D0F5DCC8C94A4C684DF846D14F436 /* SDWebImagePrefetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AA439B2B87976D37C23F7DCCE897F8C /* SDWebImagePrefetcher.m */; }; + 0FF9F459ED16719292443A4C99B52B20 /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 77715D6F65035CFA25715F00E4915BA5 /* SDImageCache.m */; }; + 10017B43AC38C3A89D7AC1376C6E7066 /* SDImageLoadersManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C1F5F86210D3FB1EF59D8665E7C4A77 /* SDImageLoadersManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 104D9196010D2A8C52C0C19E9C9D52E8 /* MBProgressHUD-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D30B8333D334528105E28100C243348D /* MBProgressHUD-dummy.m */; }; + 117F4B6F653A8DA2637C5C93B4993884 /* Peertalk.h in Headers */ = {isa = PBXBuildFile; fileRef = 70D52E1253BDF6EF05A1C5C1D46734EA /* Peertalk.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 11AD210D385F977383AFB974D3CDEF53 /* JXCategoryListContainerRTLCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E948F26A10F663204E24603E8527A7F5 /* JXCategoryListContainerRTLCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 11C929E6BFB46F981685446F26DCE605 /* MJRefreshAutoFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 14CF605A6E1A867AA3131733CCE53D99 /* MJRefreshAutoFooter.m */; }; + 11D4DC1FCE5647EEA8484AA4A880AF8F /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 347DA9A1002297848F6BF9D97BB1F302 /* MBProgressHUD.m */; }; + 126496714AD564062A8C10787CC01B8B /* MJFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF14CEE3203A4E740B9A9FD66CCABA4 /* MJFoundation.m */; }; + 12EC136F97CCCDD8C3765925FABA52CD /* HWPanModalHeight.h in Headers */ = {isa = PBXBuildFile; fileRef = EF7183977EF6286C16A64DBC3D765320 /* HWPanModalHeight.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1399CD097E164E2C7A6882F0C8FFA525 /* JXCategoryIndicatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 92A35222DEEC452079F1343331C6E154 /* JXCategoryIndicatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 14943D0EE97A4966510A86F5C3FC66A5 /* MJExtension-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2713EAAF042877733E01E359F3224ABF /* MJExtension-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 14CA284AC4FF1EED75E785641EE98034 /* SDImageCacheConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = E368F7BC820788B717CC047A744E4326 /* SDImageCacheConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 150116E888969E8304BA3E2BB6529461 /* LookinHierarchyFile.h in Headers */ = {isa = PBXBuildFile; fileRef = FDCCFFDED68135F2816CA2167E15CF64 /* LookinHierarchyFile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 15B27182B591769C57B55544260DC886 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 165F1C9CBD621828C788A3018D0426C5 /* SDImageAPNGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 3501E850F701BA678364B4AFBF1C8417 /* SDImageAPNGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 168889E3E897E6D6102A2AA7F7C47496 /* JXCategoryIndicatorComponentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C2A3B1C753D4547646108720BF5321 /* JXCategoryIndicatorComponentView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16D7DCB7CC985C33EEC41B371C029C84 /* SDWebImage-SDWebImage in Resources */ = {isa = PBXBuildFile; fileRef = CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */; }; - 1708C1D28B421C4AD310426D1695CE77 /* SDAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CD27E7A66F8B685B7056B181A0D4D46 /* SDAnimatedImage.m */; }; - 1754DD5511A7BF462B116F70B0D4006A /* SDWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = EFBFF769FFEA0B2F71A0E5EDE7DCDDF3 /* SDWebImageOperation.m */; }; - 1830558A4D2D63C8E76BC3136D8213F9 /* UIImage+ExtendedCacheData.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B54AFD2BD6CA59B1C3B03B1146FE77F /* UIImage+ExtendedCacheData.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18660FA595DBE133BB784E813A7122A8 /* SDImageHEICCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9C32EDDDB1CA2666760FDE90B64590 /* SDImageHEICCoder.m */; }; - 186B573F1BEB8A23419A02814A7741DB /* MJRefreshFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E4BD7B01B4DA8E6A41CD86E6AB6B44 /* MJRefreshFooter.m */; }; - 18AD90784D549657DF51BC8377DA3085 /* SDWebImageDownloaderResponseModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = F6B25A4160A5D48C609C6C2B58E46DE9 /* SDWebImageDownloaderResponseModifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1B52E938D7999FC0CDA2AA22674948EB /* LookinAttributesGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 1948F2AFCD4F7087CA46FB78E5A05ABD /* LookinAttributesGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1B6CE67196EE181E6B56788EFC7E00D3 /* SDImageGIFCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F0FAF8AA7D9999CB7B6AC14DC9F613F /* SDImageGIFCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1BC44E2FDD197D5210A23C9CCF1A906B /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 299CDB086FE0568EE14EAB79D7B74437 /* SDWebImageCompat.m */; }; - 1C5CCB87E5B9C500F07A8244D7906295 /* LookinAppInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F6981AC25702BE9417B498391042242 /* LookinAppInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1C8B70C74291A3076746C3B18781568E /* SDImageCachesManagerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AB362641176A92218B886FD83548F6C2 /* SDImageCachesManagerOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1CA85ECC202E5CF62530BAD7C0DCDAF2 /* LookinHierarchyInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C9BCDBD08949F0C3053B9F87567E0B2 /* LookinHierarchyInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1D18A1A5D485D57192B021A8765C0AF5 /* LookinTuple.h in Headers */ = {isa = PBXBuildFile; fileRef = E785CD9E03330FEEAB8EA2F65DA92853 /* LookinTuple.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1EA011B45EC780B434507AFB3D9647ED /* NSObject+MJCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6EC6E349C4E8476F9617E9150D43FE /* NSObject+MJCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1EC3AEA15AE416A53357261B37C622BD /* LKS_TraceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 46771EF8828C8A7519CEFD7A8DF062BE /* LKS_TraceManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1ECC5F320AEFB120081358B4FFB7442F /* NSString+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = A3A3B77B219A105E2636BBFACE42D7A8 /* NSString+MJExtension.m */; }; - 1EDC6F899051F0E858270F7556AF2F12 /* UIVisualEffectView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731C084E8B9BB6A54629DDFEBD14EA1 /* UIVisualEffectView+LookinServer.m */; }; - 1EDF5F5B68D4A76CE59D5B6CC7B6C469 /* LookinAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = F74FD66E160DEA3B30F3C017DE8ED1BA /* LookinAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1EE04FF3866D1CDDBEFEBA7F795824AD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 1FD36A180D43C773D95D8E5BF719494C /* LookinDisplayItemDetail.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB512E1904C9AC07E6CEBA4DE525DB /* LookinDisplayItemDetail.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1FDEA3FFA45F29C1331723E9579D66A5 /* LookinAutoLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 528C15198BF77FCE909FB6A717EA8C53 /* LookinAutoLayoutConstraint.m */; }; - 2055774CD703B52DABFB1CC588394A94 /* MJExtension-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A7BA44CD5FDF42B32263B5F4259A024 /* MJExtension-dummy.m */; }; - 20D618EF3EA5E3BE96DA24D36E3CA9EF /* SDAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = BDD492D9CC4757F16B776F8B08A1A49F /* SDAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 20E738E52B4712385489A62374C74C7F /* Lookin_PTUSBHub.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C8E3573AF9C6E24E9DFBDDB57A91B44 /* Lookin_PTUSBHub.m */; }; - 22516EA77E7120000632C30BD9A03927 /* UIScrollView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = B640B3AD2FE955C7A51E5B1F84A61189 /* UIScrollView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 231A40F14D020AE2F61AA5C3289E6CF9 /* UITextView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E9FADEFBF123E3EB09754AA63F0510E1 /* UITextView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2460C08042AF8B7D0492A062F755986E /* NSString+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ED91326A0371ACE08A353BC67F60F6B /* NSString+Lookin.m */; }; - 24E8E4ED0B5D988E3346E6638619F4E4 /* SDImageFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = B6F3F601094A8014DC41447620116D80 /* SDImageFrame.m */; }; - 24E963C1D6245F98BAC8A0ACCB7DE987 /* NSBundle+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6B85BD26EE974026A447B476B2932B /* NSBundle+MJRefresh.m */; }; - 2567FE276DB76481DEFC7DDFE7D775CC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 261C31F4038EC00D5961218C97905E21 /* LookinConnectionResponseAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BF2F8A5A2E35CC31448E86BCF471F49 /* LookinConnectionResponseAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 27212D06F5EDE3BB10264D93075B2275 /* LookinDashboardBlueprint.h in Headers */ = {isa = PBXBuildFile; fileRef = 713E37659AD7D79DA6664C3D3ECF01F7 /* LookinDashboardBlueprint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2759D8D4FCE58812ADECB348E369C6F0 /* LKS_MultiplatformAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 31C69A4489CC7299F114CDEAFBE0DE3C /* LKS_MultiplatformAdapter.m */; }; - 27CC45A4ABE5B40723D35310D05CD146 /* LKS_EventHandlerMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CB82C5681E372AE74735E8F3B7211E5 /* LKS_EventHandlerMaker.m */; }; - 288CD3416B265CAC1300D7938167AE66 /* MJPropertyKey.h in Headers */ = {isa = PBXBuildFile; fileRef = D197698AA79A94AD39EC006BBB9D3481 /* MJPropertyKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 288D796F3F7B9F42690E24A3B1018B2C /* SDImageIOAnimatedCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C0CAD4F0394CDAF40054888E02EB093 /* SDImageIOAnimatedCoder.m */; }; - 28BA9702905AA2B4C1E9E4878032D4E4 /* MJRefreshConst.h in Headers */ = {isa = PBXBuildFile; fileRef = B9E85A8129A4E7BFE16B2262D78F1DCC /* MJRefreshConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 29F7F0E98FD26A96364DBACD7D5F237A /* SDWebImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6609EE1C9372D5E3C70AF9861CE95D /* SDWebImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2A24F241D7D74FF6DEA953F9DD49391C /* LKS_EventHandlerMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6C055C722C44DA0E562F93906DCD34 /* LKS_EventHandlerMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2CDC7B9EAD356E35FEAF526EEA6A8E91 /* LookinWeakContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = F9B85917A028A675DFE95B885791EDFC /* LookinWeakContainer.m */; }; - 2DC44A09A6C9D6DC7D1BDA2DFCF99EE3 /* MJRefreshConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C9BF32317317006604613DB6B7E6531 /* MJRefreshConfig.m */; }; - 2DDA5F044BC698BC5D48A7CFDDBF71E3 /* LookinAttributeModification.m in Sources */ = {isa = PBXBuildFile; fileRef = FD1216744C111B10EA2988454A525213 /* LookinAttributeModification.m */; }; - 2DDD48230ED9E8068C7E439D79B99A8E /* SDInternalMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F715C3F41E2D739BCA20A8ED2E487A1 /* SDInternalMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 2E86A7C77E43AEA4697979F1F848E68D /* LKS_RequestHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E4000AF0B9EEE3F891ADD766B1967BD3 /* LKS_RequestHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2EFF1EFA2FF0D2F1AE44A9DDBB932425 /* UIScrollView+EmptyDataSet.h in Headers */ = {isa = PBXBuildFile; fileRef = D6E369F88941EA9A46AF58BC88CC0720 /* UIScrollView+EmptyDataSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F6D9BEA582A2DBB70A6C3B2FC2DB91E /* SDWebImageDownloaderResponseModifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 15D08EB14955AB2B841A5E9E16D8D4AE /* SDWebImageDownloaderResponseModifier.m */; }; - 2FEE980BEE23B8E0C7EBB70445EC8C9A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F320516E3A699EEF56C411E9C2DA9C29 /* PrivacyInfo.xcprivacy */; }; - 3187FF0C251D1B78BE87F64F6F6E944A /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 4819E2A59EFDCF27B3C3DDB40C7B2D13 /* SDWebImageTransition.m */; }; - 31DC2EC78AD1F8241AE6051EF9E73B0A /* SDWebImageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 0370FDB753906B18C1B9AFB8BE7D213C /* SDWebImageDefine.m */; }; - 320DE42AF3CFE11FF785FEB1A7E6547B /* SDImageFramePool.m in Sources */ = {isa = PBXBuildFile; fileRef = 131863AC3A27979CE5BF1B35EB9C1CED /* SDImageFramePool.m */; }; - 321F87DA34863DC5C977323BAEDB2B55 /* NSObject+MJCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 45F43707DFF3E5A8EFA1404F7259F5DF /* NSObject+MJCoding.m */; }; - 325CA20B9271F3E008234E1518B79061 /* MJRefresh-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2065E7BBA3909607E34531E7D59623FF /* MJRefresh-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1708C1D28B421C4AD310426D1695CE77 /* SDAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = BDB258BF0BE17AFC3BFB4FB942403B82 /* SDAnimatedImage.m */; }; + 17341EDF872432C3966B77976F3E0470 /* JXCategoryTitleVerticalZoomCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = C4D51AE584C5960F5C6B60C866377741 /* JXCategoryTitleVerticalZoomCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1754DD5511A7BF462B116F70B0D4006A /* SDWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A70A9B1B9D076F21A4C704EAC69B3E9 /* SDWebImageOperation.m */; }; + 1830558A4D2D63C8E76BC3136D8213F9 /* UIImage+ExtendedCacheData.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D2F3BF5EE9E269F816330AC6BF6745F /* UIImage+ExtendedCacheData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18660FA595DBE133BB784E813A7122A8 /* SDImageHEICCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CA6A325AACF7253FFEB9D258746335D /* SDImageHEICCoder.m */; }; + 186B573F1BEB8A23419A02814A7741DB /* MJRefreshFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0260C833576479A14C0F759F9D161479 /* MJRefreshFooter.m */; }; + 18AD90784D549657DF51BC8377DA3085 /* SDWebImageDownloaderResponseModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F1245D39980C8CC23C4FFA557C72FA3 /* SDWebImageDownloaderResponseModifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1B52E938D7999FC0CDA2AA22674948EB /* LookinAttributesGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = E6FEAED2BC2A577A78A12FA14FC3BB6B /* LookinAttributesGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1B6CE67196EE181E6B56788EFC7E00D3 /* SDImageGIFCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C0E279B5FFB9696801CC86ACF92805A /* SDImageGIFCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1BC44E2FDD197D5210A23C9CCF1A906B /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = F00B3F2B17BB2816232EB507B7AC9018 /* SDWebImageCompat.m */; }; + 1C0FA6017CAD67C1A80FFA70024FC6FD /* JXCategoryIndicatorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F9F30602CBEA307F110682B47DBF3B59 /* JXCategoryIndicatorCell.m */; }; + 1C1BC9F0555B36914FF5278D30152DE6 /* JXCategoryNumberView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B8734ED62BE39C69073D2C32183C6FC /* JXCategoryNumberView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1C5CCB87E5B9C500F07A8244D7906295 /* LookinAppInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D8A828331C79742A41F54C2050C90A8 /* LookinAppInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1C8B70C74291A3076746C3B18781568E /* SDImageCachesManagerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A41E1A305241C5A627FAD06CB90A275 /* SDImageCachesManagerOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1CA85ECC202E5CF62530BAD7C0DCDAF2 /* LookinHierarchyInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 26469EA2BF7F49FCDA80695277950B2B /* LookinHierarchyInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1D18A1A5D485D57192B021A8765C0AF5 /* LookinTuple.h in Headers */ = {isa = PBXBuildFile; fileRef = 17A16F153D08C8BBF15070C730EC0C3A /* LookinTuple.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1D3DCD05B685A7CAF291C25D922B1831 /* HWPanModalPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9506DDA8FBAA7420E9B8137BFCFDFA /* HWPanModalPresentationController.m */; }; + 1DB724891F1F6468BDB333369F667F39 /* HWPanModalPresentableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = C644FF26241C14C759578567892EF00D /* HWPanModalPresentableHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1DC161351EBD409CC622E826340E4FD8 /* JXCategoryTitleVerticalZoomCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 25475D081A3343232AD119F5F5A5F24A /* JXCategoryTitleVerticalZoomCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1EA011B45EC780B434507AFB3D9647ED /* NSObject+MJCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2F0E472487CBFBA5CA4F3C62C1BB0B /* NSObject+MJCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1EC3AEA15AE416A53357261B37C622BD /* LKS_TraceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 52AF8374431A1EA8420BA1E29139131E /* LKS_TraceManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1ECC5F320AEFB120081358B4FFB7442F /* NSString+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 15C39377834B42681C3BF6A5471C5F78 /* NSString+MJExtension.m */; }; + 1ED0D560CC57BCED931C26E643B2A96A /* UIView+Empty.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A5F8A5650078BFF9587944F0042AE79 /* UIView+Empty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1EDC6F899051F0E858270F7556AF2F12 /* UIVisualEffectView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = A7DF910F689AA8FEAD1EF63DDDFCB780 /* UIVisualEffectView+LookinServer.m */; }; + 1EDF5F5B68D4A76CE59D5B6CC7B6C469 /* LookinAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 903EBE6439B30182644FFF066DE11129 /* LookinAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F2863645F3DEAC57B592AFFB45D5E77 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 20674A80959A90C9F9E51DBDC8807D93 /* PrivacyInfo.xcprivacy */; }; + 1F778CA18D1F4A50D9F15280B25D10EB /* JXCategoryTitleImageCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B812F8DDDC6CC3E3ACDB1D17716E70C /* JXCategoryTitleImageCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1FD36A180D43C773D95D8E5BF719494C /* LookinDisplayItemDetail.h in Headers */ = {isa = PBXBuildFile; fileRef = 407D327724ADF96791DFD9B922AA254A /* LookinDisplayItemDetail.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1FDEA3FFA45F29C1331723E9579D66A5 /* LookinAutoLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 38F21B02ED02115E613C152CE563BD5A /* LookinAutoLayoutConstraint.m */; }; + 2055774CD703B52DABFB1CC588394A94 /* MJExtension-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 43E163147E40F868F458CD979D77C4E4 /* MJExtension-dummy.m */; }; + 20D5706AD3ED295B4FBACD8825DC3A1E /* JXPagerListRefreshView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B250EFB659FBBBBA5D680859085344D /* JXPagerListRefreshView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 20D618EF3EA5E3BE96DA24D36E3CA9EF /* SDAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 026BB0AEDD69539DEC39191EE0C5214B /* SDAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 20E738E52B4712385489A62374C74C7F /* Lookin_PTUSBHub.m in Sources */ = {isa = PBXBuildFile; fileRef = B1850D4E22F95780586FA04DA695C24C /* Lookin_PTUSBHub.m */; }; + 20FBBC12322412237D48D3695D98E043 /* JXCategoryDotView.m in Sources */ = {isa = PBXBuildFile; fileRef = C86FEA7FA982FA034501F7AB37760D49 /* JXCategoryDotView.m */; }; + 21232E67D630EBF8EA4CB3322B359F0D /* LSTTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5782C68BCDC8C49DD74B206B3FFFF1 /* LSTTimer.m */; }; + 2175B894008D948C762468307BA677B8 /* RTLManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3BA26DC995AB016051D522F5691C91 /* RTLManager.m */; }; + 2210A1E405AB21104E7AF86D05C8AD39 /* LYEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 39267406AD82F75ABB872A20BE14F010 /* LYEmptyView.m */; }; + 22516EA77E7120000632C30BD9A03927 /* UIScrollView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 304FA88F8B2636C2DD7FA535D2BD617D /* UIScrollView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 22C38AE7AB145224FF646303AFED11D2 /* JXCategoryDotCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 931669FB7F8BA540208B2F23E13B2F19 /* JXCategoryDotCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 22F19B23471EE7840581A348EB735BD1 /* UIViewController+LayoutHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = F9AA00EC509DE2C0E25E749F629EF1F6 /* UIViewController+LayoutHelper.m */; }; + 231A40F14D020AE2F61AA5C3289E6CF9 /* UITextView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = FCA4EBF34C88159600AC127D3548346D /* UITextView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2395CE03CE80FC5F9A7F61C48270618B /* JXCategoryViewAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 95BCF1B96C9A492409E9634BC63A400B /* JXCategoryViewAnimator.m */; }; + 2460C08042AF8B7D0492A062F755986E /* NSString+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A08CB30EFC3A6CB342354C253BE4D8 /* NSString+Lookin.m */; }; + 24E8E4ED0B5D988E3346E6638619F4E4 /* SDImageFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 452754C8CDFE17EC42C563B4B6E1F69A /* SDImageFrame.m */; }; + 24E963C1D6245F98BAC8A0ACCB7DE987 /* NSBundle+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ECA4FF1A4B2A73F055139B44105081C /* NSBundle+MJRefresh.m */; }; + 2567FE276DB76481DEFC7DDFE7D775CC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 261C31F4038EC00D5961218C97905E21 /* LookinConnectionResponseAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = D9BB987ADE61FFDF3C240961F2EB4DDB /* LookinConnectionResponseAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 266352AA446DAE8C9502E83810C174D9 /* JXCategoryImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CB6F43E2EFE165260D66B0BFF9A8831 /* JXCategoryImageView.m */; }; + 27212D06F5EDE3BB10264D93075B2275 /* LookinDashboardBlueprint.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AB6F2617132C99A6B5CB953305CCA89 /* LookinDashboardBlueprint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2759D8D4FCE58812ADECB348E369C6F0 /* LKS_MultiplatformAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 957B3209BD81CDA1C8049B3245F6946E /* LKS_MultiplatformAdapter.m */; }; + 27CC45A4ABE5B40723D35310D05CD146 /* LKS_EventHandlerMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = CD6BC672271DF551FD22D8BABC528CA6 /* LKS_EventHandlerMaker.m */; }; + 27CE2AFFB3219A5D3717045970929C80 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 7EC4505824D228FB201DC90A544C01B3 /* PrivacyInfo.xcprivacy */; }; + 288CD3416B265CAC1300D7938167AE66 /* MJPropertyKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 05A7B005509B15E31ECEED7DFEEB1EDB /* MJPropertyKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 288D796F3F7B9F42690E24A3B1018B2C /* SDImageIOAnimatedCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = B92B905C66437721BB933FEDA5B00CB4 /* SDImageIOAnimatedCoder.m */; }; + 28BA9702905AA2B4C1E9E4878032D4E4 /* MJRefreshConst.h in Headers */ = {isa = PBXBuildFile; fileRef = 63A3BD4651AA1DDCB216ABB7FBC3A69E /* MJRefreshConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 29F7F0E98FD26A96364DBACD7D5F237A /* SDWebImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 96AEDA915084E949F39F28D248C2FB43 /* SDWebImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2A24F241D7D74FF6DEA953F9DD49391C /* LKS_EventHandlerMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 51AB8F5FA4517AC80D7763B2894462EB /* LKS_EventHandlerMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2C2405D23D1A7428F65C7D740476ABA2 /* Pods-keyBoard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A2D8E1EB42D41EA6B94901E5B68C9011 /* Pods-keyBoard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2CDC7B9EAD356E35FEAF526EEA6A8E91 /* LookinWeakContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 60F9066C601EE11D24D22C170F05AF13 /* LookinWeakContainer.m */; }; + 2D0E2E3CDCB12399497B4F31D4C20E3E /* HWShoppingCartPresentingAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = FCBCC9D408AF4A848CBB9CEE3327E256 /* HWShoppingCartPresentingAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2DC44A09A6C9D6DC7D1BDA2DFCF99EE3 /* MJRefreshConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C71B9877A51B54673C7FFC0C3276863 /* MJRefreshConfig.m */; }; + 2DDA5F044BC698BC5D48A7CFDDBF71E3 /* LookinAttributeModification.m in Sources */ = {isa = PBXBuildFile; fileRef = 39592D3DD29808CC34F5BDE8FFAD64E6 /* LookinAttributeModification.m */; }; + 2DDD48230ED9E8068C7E439D79B99A8E /* SDInternalMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 962D7794EB805E6D2F4F5F0B58218401 /* SDInternalMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2E86A7C77E43AEA4697979F1F848E68D /* LKS_RequestHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBA747DBA20D4BACF78CA8DE98ADF94 /* LKS_RequestHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2EC1750C894F036194B90CFD26072B0C /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = E386525610DF7AB4E84ED0202969AB8E /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2EC7BA321016EC71EA595E4BAF0B7E8B /* JXCategoryDotCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B890DAD1E942EF3DB7BF5C23113C1B6 /* JXCategoryDotCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2EDA227454079ED3F6371BF34AFD4735 /* JXCategoryIndicatorCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E73D1DD407F0535009A207AB317F8B7 /* JXCategoryIndicatorCellModel.m */; }; + 2EFF1EFA2FF0D2F1AE44A9DDBB932425 /* UIScrollView+EmptyDataSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 2945888F89AB6D3ECBBEDD6E09D1B949 /* UIScrollView+EmptyDataSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2F6D9BEA582A2DBB70A6C3B2FC2DB91E /* SDWebImageDownloaderResponseModifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC98580A0BA844CDD661F01812A35C7 /* SDWebImageDownloaderResponseModifier.m */; }; + 3111CEA93C868CA68CBD351C934FEB80 /* LSTPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 633C3F66E9BA0FD7538C55D5287ED77E /* LSTPopView.m */; }; + 3127F22BF0A5465D472669272D586BDC /* HWPanModalIndicatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDE5AFCF524DCA9CD59B6F4A4738325 /* HWPanModalIndicatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3187FF0C251D1B78BE87F64F6F6E944A /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = A4B49E8FCEA2AFEE938A133ECC269CF2 /* SDWebImageTransition.m */; }; + 31DC2EC78AD1F8241AE6051EF9E73B0A /* SDWebImageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEC6C323BA320F8FE0EFED607BC9994 /* SDWebImageDefine.m */; }; + 31FA8264AA5553AB85039530B1FB8C4B /* JXCategoryNumberCell.h in Headers */ = {isa = PBXBuildFile; fileRef = A23AD7EF4A12F64EAAFE5154D8DC5843 /* JXCategoryNumberCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320DE42AF3CFE11FF785FEB1A7E6547B /* SDImageFramePool.m in Sources */ = {isa = PBXBuildFile; fileRef = BF31B533FDEE0B0DA7ED824B4F336534 /* SDImageFramePool.m */; }; + 321F87DA34863DC5C977323BAEDB2B55 /* NSObject+MJCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 0249A8711339B6CD1E26258C064677E9 /* NSObject+MJCoding.m */; }; + 325CA20B9271F3E008234E1518B79061 /* MJRefresh-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A2E7581F1DA07EBD6D2568091FCCB71 /* MJRefresh-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 327BA3DDA513422E632D3DA4A8FC60EC /* MJRefresh-MJRefresh.Privacy in Resources */ = {isa = PBXBuildFile; fileRef = 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */; }; - 32ACEDCEBE0507A82D6323114A1C74F1 /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DFECBD4586BE9AE288AFFA5027A9A24 /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32F2B91621A2F8F9AD7C8E2B224D73F6 /* SDWebImageDownloaderDecryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = F226E8137EFBE0F2C4ADF98335CAA02A /* SDWebImageDownloaderDecryptor.m */; }; - 32FF240AE9443A1D2CFE27F50B55F591 /* LKS_MultiplatformAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0075507DF323DF510CA1115DE2B33C98 /* LKS_MultiplatformAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 332F2099D726E75CEFAF1F734104A066 /* LookinWeakContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 785DDFE2F3C7BA8AEDE2278087F506EB /* LookinWeakContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3331A013D48A5063B483A51B7E9068ED /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A6A924083322C61BD2DC82A438F46687 /* AFURLSessionManager.m */; }; - 33D3587AF629B2FA21554DA002D6ACB8 /* SDImageCachesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A3CC467742888B5DE59CC393D50BA540 /* SDImageCachesManager.m */; }; - 34B28D4F0168194B6EFAC0520EB7A7F4 /* NSImage+Compatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = CC47954DDA2CCCD6E92132955A0DE728 /* NSImage+Compatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 35D42759A562C482EA5DF574F75CF3B8 /* NSArray+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = FEE404F0AEA8371C4FCFE3F576AA5835 /* NSArray+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 36F4B09E7C71DCC5CEC6057814033C37 /* UIView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 98B6A3897B6D415F51E7F65FD9A20296 /* UIView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3777CD89D444CBBB48AE323B303F3FC7 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFBDDF0554D720E199E1094AAEC3D171 /* ImageIO.framework */; }; - 37B890ABDC7DD441E6AA662325D412E6 /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = B36A499BB6A9A389E077337779129B95 /* MASConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3800EA1B83FDE869FB2E4B049F519962 /* UIViewController+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2567115C715DFD2B942FF9386C729778 /* UIViewController+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 38938E604A7D708E6378A44063EF3512 /* UIImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FA1B344071044AFFAABF1077219DEC22 /* UIImageView+WebCache.m */; }; - 392F62298E0D8C669229E132D791BBF5 /* UIImageView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = A6B89FBB0AA4A7BD7E16AFF20A519DC2 /* UIImageView+LookinServer.m */; }; - 3A1AD84C0DC3C256418CC46739024E96 /* SDmetamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 79462E533AFF776B12B799A128AA5EE8 /* SDmetamacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 3A2FCB914F6EADED828FF05F7E9132AE /* UIView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 61AA277CF1084D31AAA460D8C1A9BE4E /* UIView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3B1C72DC480AB19BD55B6275750D62FE /* NSSet+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = FA2246CD5BC5C3E37CEC58BCA4848181 /* NSSet+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3B8EDFF69A68ABD3735E0C6931CA5C95 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 35618C07738616EC64E35AB9084E01C6 /* AFURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3BB69CB142D744367868F834912993CB /* UITextField+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = CEC88A03608F444860F81FB5EB689938 /* UITextField+LookinServer.m */; }; - 3C7815EEC599DD7D42FDEF19B2FF1563 /* SDWebImageOptionsProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = C0AED8CDD333F60946EF309E2D789249 /* SDWebImageOptionsProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3C7EAECB8C573E714C818BA04EB33773 /* UIImage+MultiFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = C59B65D3E951B3FDACD866C4564C0214 /* UIImage+MultiFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3C8F2F868D0C361CAF43E53CDB8EB631 /* SDWebImageCacheSerializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 794882B4F91B9E9B55DD3DF40E04DA22 /* SDWebImageCacheSerializer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3D0BBFEC1921CE71BC240DC18D8BE540 /* SDImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DF57705B90AB01302C42302B6BB038DD /* SDImageTransformer.m */; }; - 3E3D09700A62280A9EB8D65B97335ED8 /* LKS_CustomDisplayItemsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = C08BFCAD6B6021A9C9686DA64A6CF1AE /* LKS_CustomDisplayItemsMaker.m */; }; - 3FF7252DD60182221BB1E5A167C41A07 /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D3B8DD288273B0C3AFDD2F366BB894B /* UIProgressView+AFNetworking.m */; }; - 40AD5D0AB3ABF7F3A5A4A98BC5B84419 /* LookinAttributesSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B6DD67F49B0103232B5D6B727392FA /* LookinAttributesSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 416DA8B2997381F954DBA6E6A53DA4A2 /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 17422A39378973466DCE06FB6ADA832E /* NSData+ImageContentType.m */; }; - 41A4AAE7E6024E7AAB83DD22FB42D34D /* UIColor+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D4236904A41DC2950754F5BE583BD4A /* UIColor+LookinServer.m */; }; - 425C9EA28FBEB7F7FC09A3F4A88C5955 /* SDWebImageError.m in Sources */ = {isa = PBXBuildFile; fileRef = CE89275D8F89A11FB2761E0461236313 /* SDWebImageError.m */; }; - 442F468E261A1106C291BF52BDBF9DB7 /* MJRefreshHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = D5509360DE46CF0B8D64058FE9FD45E8 /* MJRefreshHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 447BBB1BCA8E0F2D23634888BED6DA81 /* LookinDashboardBlueprint.m in Sources */ = {isa = PBXBuildFile; fileRef = 290A1387E4C301A25D8613FBB0DCEC6A /* LookinDashboardBlueprint.m */; }; - 44CD842019B1CEA681F820F37A30B7C4 /* SDImageFramePool.h in Headers */ = {isa = PBXBuildFile; fileRef = 148FDB67C55B5854E979447E82AFD54E /* SDImageFramePool.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 452C940762F65B125C216F73B369F583 /* MJRefreshStateTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A2C339DB0F9EF94544BE6FCDA59F50F /* MJRefreshStateTrailer.m */; }; - 4571A0EA37DC84F39E3830D38A1531AB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1DF8BF780A4AD9606856AB857CA1D86 /* UIKit.framework */; }; - 45E1583D7EF53489B82C4CA2AD1AD0CF /* MJRefreshBackFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = FDD0D2A5CBDCDA5BDF9600C731F95B24 /* MJRefreshBackFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 464A0100327C8531D86BDC31737CCF75 /* LookinAppInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DE5E3242D0D245F39B1349B5C4819144 /* LookinAppInfo.m */; }; - 4688743B7B845309486559EB7BD5D147 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = CBCBBB0099A9339A1A8ABBEDF291AF92 /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 475B4F3E71C293065AAFDB1888696CF6 /* MJRefreshBackGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CC603030F93055E51FF99944B356CB6 /* MJRefreshBackGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 48916DE9521F627589300512ECC2D4A5 /* NSButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 613A0EC29C46AFB409483355C45FE1C7 /* NSButton+WebCache.m */; }; - 4A15ABB502D625EBE3E63100664AB822 /* LookinCodingValueType.h in Headers */ = {isa = PBXBuildFile; fileRef = A7178BC144BA120067B45EC042E2D156 /* LookinCodingValueType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4A2D7878579537881DD3859B3359F702 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86A260983254EF2D214865E91D3787B2 /* CoreGraphics.framework */; }; - 4B2C2AE16AE3DDA7417AFCF7952588F1 /* SDImageAssetManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E0CFDE214ACE5F071E4BEEF63BDDCD6 /* SDImageAssetManager.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4D2C79AB2D24CFEC864F08D913CE7692 /* SDImageCodersManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 97041A2525062E71B923CEBB11179389 /* SDImageCodersManager.m */; }; - 4DA2C6099343CD55160ECB3EBDDFE1DF /* NSObject+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F2C6DE995A9BCF5E418479898442088 /* NSObject+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4DCA75BFE1558CE59DFC56607E49B3D2 /* MJRefreshConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = B985D3DA018E1C8C3AC44ADE702B404B /* MJRefreshConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4E964FFE29CFF8613C0029C913F39A05 /* LKS_InbuiltAttrModificationHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E91E93486D40A052515660F00B079B5A /* LKS_InbuiltAttrModificationHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4EC8DBADA7BB954276351A639EB4398D /* UIBlurEffect+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 220B8AB16FBD2158AB55D35E9376D13A /* UIBlurEffect+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4ED05DB3E43FF6AE1FA22130B2B50F05 /* UIImage+MemoryCacheCost.h in Headers */ = {isa = PBXBuildFile; fileRef = 80FED7368916E2D1EE8E2B7F26A2618F /* UIImage+MemoryCacheCost.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 50096BAC0F3270FB111E76D32714E579 /* Image+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 19CD19C5B1822DA77E4C7C9F454FD5D5 /* Image+Lookin.m */; }; - 506FC58999564A737C745F2590E9B4D5 /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A3DF7C8B0CA95D284475EF487EC6944 /* AFHTTPSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5111A0A0934551CD2B9DDB1A1CA79FA7 /* SDAnimatedImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A299BC446CAAFD89DBF55F51B07F0F4 /* SDAnimatedImageRep.m */; }; - 512B9661FC34235E0EEB3A6D3E319B88 /* MJPropertyType.m in Sources */ = {isa = PBXBuildFile; fileRef = D15A23E7684648249EA4D7C312BACC22 /* MJPropertyType.m */; }; - 5163FC6D715F6881B1FA1AB13DCEF870 /* UICollectionViewLayout+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = EE4B0CFE38831013E2F465F169783700 /* UICollectionViewLayout+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5174DD2019966DFDC21B8864453ED3DE /* NSObject+MJClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 049541DC9203D75878CAF900D458CC34 /* NSObject+MJClass.m */; }; - 523235228A1C021C67F2E3776A922DC5 /* MJRefreshTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = E603FC069FE0FF9249D8A7348F6E7795 /* MJRefreshTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 526485EF6D2B62B24DB59122FB94BD42 /* SDDeviceHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D2D491E6C287C5C66C4EF6B165E85BD /* SDDeviceHelper.m */; }; - 5308E660E723C11E7691D311FD59C459 /* SDDisplayLink.m in Sources */ = {isa = PBXBuildFile; fileRef = F14968FDB67455000B5A2C9A77C64B07 /* SDDisplayLink.m */; }; - 53433003112C4FE271EC985803862B61 /* SDWebImageCacheKeyFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = DF2FF7F81EC1FE20B9F8B3879085D4FA /* SDWebImageCacheKeyFilter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 53C1722650FCAB2637867D0DC31FC3CB /* Lookin_PTUSBHub.h in Headers */ = {isa = PBXBuildFile; fileRef = 4211A99A6EE6255E875FA46E987F2128 /* Lookin_PTUSBHub.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5490C03887ACF6C4EAC25ADFBB509CE5 /* NSSet+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E5219BC7E7BF5C405E48CC237D2EDC2 /* NSSet+Lookin.m */; }; - 54E268C32915CF908E7AA776909B45EB /* MJRefreshConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 9324A882B3ED55B3EF9D92D946555583 /* MJRefreshConst.m */; }; - 55F7C7F055A18044497F8C88CAE34118 /* SDImageCachesManagerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B6FEE442B47E03714BC3FB94670DCC /* SDImageCachesManagerOperation.m */; }; - 561420A20DC0A84258A902E9EB69A15A /* MJRefreshAutoFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = A417B5FC83ECB57A121FCD14A6DD23D3 /* MJRefreshAutoFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 564714D075CF51356D3D8437846AA6EB /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C457050D64C2C7287BDFC768D33C9AE /* AFURLRequestSerialization.m */; }; - 56D8A7EAE4D72FF6C23421CAB6F21504 /* MJPropertyType.h in Headers */ = {isa = PBXBuildFile; fileRef = 04549DFA210F3D3C27211535994000B3 /* MJPropertyType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 56E800EB3B2BE8AE0BA45A30974D7920 /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E321D3F90B0E3A7E45F64EB551639098 /* Masonry-dummy.m */; }; - 56F1B543BC54204336CB5E50B60F719F /* Color+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FD8426A1028406F5A9C4E27D5C9E76C /* Color+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5735091665AC18FAD028EB68786A85AE /* LKS_CustomAttrGroupsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D58792A3DBAB3667630D1FF53DDFB8D /* LKS_CustomAttrGroupsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 58F7CE37BB4CB3BE806B68A502E6E1A7 /* SDWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = EF15AFFA76ECFCE490107F1DEB31BD62 /* SDWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 596180E0EC9F46D12BA840DC4AA62659 /* UIImage+MemoryCacheCost.m in Sources */ = {isa = PBXBuildFile; fileRef = F66C529D67E3A61B55DFF40E581048ED /* UIImage+MemoryCacheCost.m */; }; - 597E390C0BBB75B8045B651C487C2034 /* SDImageAWebPCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AF433E9D2C6355E77FFBE3AC3CB5B3A /* SDImageAWebPCoder.m */; }; - 5A6D3BE92C77ED70C397567996DFAEB9 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CABC6887E9E2AF4A62642A0C780B4B3 /* AFHTTPSessionManager.m */; }; - 5A8BC91257FF6B36237BF09A7A6EADF6 /* LookinObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A3048EE57AEE9C3B5FDB98C9E7DF4BB9 /* LookinObject.m */; }; - 5AF22814CD055B553AD9D78BE54B94E1 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 219886C4AF0E20C3CD4D4061CAAE8767 /* UIProgressView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5B08596E856E4CC2F34A8A2372F9F764 /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A054792401E8F9F7BEA8441F9C1DA7C7 /* NSArray+MASAdditions.m */; }; - 5BB6B99986FD7111B3AEBE931C7F507B /* MJRefreshAutoStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 80F9F8B5249F11798A805DF46C09F2CA /* MJRefreshAutoStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5BD5D9B8F61C124A62C75D9AC36A07BD /* MJRefreshTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = ABCA85AD5553CAA4C58A12223211E18E /* MJRefreshTrailer.m */; }; - 5C8279C226EB028B044C5A0F4AC5A91A /* SDAssociatedObject.h in Headers */ = {isa = PBXBuildFile; fileRef = B9EF838DEDDB795D85E2F065BD697452 /* SDAssociatedObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5D0DEC179A7B4143769C663082E2662A /* LKS_ExportManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DECAD058B2FE8CD24CC1022B0A1523AB /* LKS_ExportManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5DCBA14510E091D6A1CE499B08B794B5 /* UIImage+Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = E614E7E1FA6658E0B9CF44C05D4E6811 /* UIImage+Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5DFCBADAC7D0FAC82C84A6C8E7BF1DA6 /* MJRefreshStateHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = E0E79E8251323154CB271295CCD93D0A /* MJRefreshStateHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5E10328A83E05D0015D7459FAAEF121D /* SDGraphicsImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E7FA66C9DDB6507631DF1F179557C4A /* SDGraphicsImageRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5F45735DF355530CC955066D3C007E19 /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FD6A0DEDE4E0A17B8A614C8D15158DD /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5F5426608460A8B17C1AE5C2351BAA19 /* UIScrollView+EmptyDataSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C3AD08A39781246EBAC23F5B8A9BDD3 /* UIScrollView+EmptyDataSet.m */; }; - 5FDC4239F7B651092BF582D0F460BAD4 /* UIView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 45DC3F40C3A1FA5B5920DED3DF89557C /* UIView+MJExtension.m */; }; - 6002CB94684D7C786700D2A294146AEC /* Color+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 9278559A57D46FAC97B2480A76E574BE /* Color+Lookin.m */; }; - 61461B0D9D7B81C3F8D24066D9A19DCE /* MJRefreshGifHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FE66EE9C43A4BD03E9F354FADF7098 /* MJRefreshGifHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 61507E402F1F7C58BF119995A0479A22 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C46B6B074DF2D170E6F2ACB5E8C8BA /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 616A8338C42FB01748DF1BDDA944858D /* UIView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FAA44D6FF1A44EB319965DB5E0CC5F73 /* UIView+WebCache.m */; }; - 61857C821395B868C65A8FFE4DA1B4E3 /* MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = B486D1944AF55BFAF5E8F8CDE6F8EB79 /* MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 61EAFBCDC83B2C603918B3C9D9A73A18 /* LookinConnectionAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 5212AF1887982114A494FF962BEF5A35 /* LookinConnectionAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62FE895DF9D65A2955A275D909ECBE18 /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B21CBEE99C5014F0E0F66C420497FCD /* SDAnimatedImageView.m */; }; - 6525ECE1CAFC1259F9E6E5FDDE6CF218 /* UIVisualEffectView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 594925FC6BBDEA3002D153F167630F93 /* UIVisualEffectView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 659D38386A3E09422812283BF27D71D1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 67178A8153B1A2F1D0D544B8093E23C5 /* SDAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A9A2DE85C1D87BCD354418BAF78749 /* SDAnimatedImageView+WebCache.m */; }; - 676775CB29378BB6CA3CA5992E9C6A99 /* SDImageIOAnimatedCoderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9662C23EC2FEA41BE91046E19A928D8C /* SDImageIOAnimatedCoderInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 67FCC0F9B42B1C20A66E99A3D56BED18 /* LookinStaticAsyncUpdateTask.h in Headers */ = {isa = PBXBuildFile; fileRef = D23D41020809113858D4CA46059797CF /* LookinStaticAsyncUpdateTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 683D708C157C95ADB467BDD2230BD4E3 /* UITextField+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = AB70C7432DDB8346C9DB4A27C7C7AEEB /* UITextField+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 68C3E98F8B9D6035962F29AE025DA891 /* UIImage+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = F2087695EC0958A50E2C65A5D2E03159 /* UIImage+LookinServer.m */; }; - 69345CBCB31076EBF8A2C5885AF973AB /* MJRefreshComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 383AEE356898B114D8DD079C51566FF2 /* MJRefreshComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 694B8697854A776E32032999B2EF1FEA /* UIImage+Metadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3FF7FA5E997D3DDAB5C272F8734A6 /* UIImage+Metadata.m */; }; - 6960FF2C4D61A09722930B33B1C7135D /* LKS_ObjectRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 30361FA11468C74A598363E37D30E56C /* LKS_ObjectRegistry.m */; }; - 69A06A02F52EB26259FAD1DF6B121BE1 /* SDCallbackQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 13D448A155C957ECCF95DC54FBE28569 /* SDCallbackQueue.m */; }; - 69AB6A513D5F36D7360FEF4FDA1D60D0 /* UIView+WebCacheState.h in Headers */ = {isa = PBXBuildFile; fileRef = 832592FA01CF620F64F9CED4966CEA99 /* UIView+WebCacheState.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 69E353C99C6EEA3C93CCF2E526460B9D /* UIScrollView+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = AEB9B57AEEA7BDF0C696120F4B110F33 /* UIScrollView+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 69F6E66A089C40FB1063DE15499BCFDE /* LKS_Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 371FD070C447028E0DC76F07BB442FC4 /* LKS_Helper.m */; }; - 6A19379E3B0370EDA447743C9B1A1379 /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3996B697C00897DAFE1DFD73DAA4E114 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6B0978C9398336656EE309E62060AEAB /* SDImageAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CA256AA8704AE9F135214714BAFF153 /* SDImageAssetManager.m */; }; - 6B5C3592B5E911E833D067D0BC785B1A /* SDImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC42F03931384EE2605E5C1FF575608 /* SDImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6BC2A615678C8BAE9F34ABA68BFDEF78 /* LKS_AttrModificationPatchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 79EEB00E9ED2C742987150EA5E0B1341 /* LKS_AttrModificationPatchHandler.m */; }; - 6C57809DCEA4B6C0CA79918A69FD75DE /* LKS_ConnectionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5ABD1279233951A8EAE905C43AD033A4 /* LKS_ConnectionManager.m */; }; - 6C85CA8D99E50C137D056B6057DAC58A /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 9228BFB339DE3C8FD5163C974AB7DE89 /* UIRefreshControl+AFNetworking.m */; }; - 6CA0B4A9E7B2957063163BC673F355CD /* AFAutoPurgingImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C0293D25B82D4CCF17D52B025BDDA03 /* AFAutoPurgingImageCache.m */; }; - 6CE8701D161A4BC0860FAF3951762A34 /* LookinHierarchyFile.m in Sources */ = {isa = PBXBuildFile; fileRef = EFD8B43671F8A160934DA73D3C45B4C0 /* LookinHierarchyFile.m */; }; - 6DE6C7F0FA965828E4FCE687BF75FBBE /* MJRefreshAutoNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 79E1EEF42DE5E1954630A63B8A5E02B6 /* MJRefreshAutoNormalFooter.m */; }; - 6E66305665DBCFBCF5B2480BF705D500 /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BF9DE6E63B2A31CC1EADA84D3E42E7A /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6EFC0630CB2761A2B1FC47176CCD62D1 /* LookinCustomDisplayItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D2347D4EFB2E5610773AF965AA8399 /* LookinCustomDisplayItemInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6EFEEE3AE22E97DCEC4F5A3B88F56FC7 /* SDImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 2254BB0E1CAB331C712E8819CE1CEBA9 /* SDImageLoader.m */; }; - 6F3637EE643EABB1DE9212EA68649A64 /* UIColor+SDHexString.m in Sources */ = {isa = PBXBuildFile; fileRef = F299DB132C67105BBC5A78FBCB87FCF2 /* UIColor+SDHexString.m */; }; - 7074EA7FCC90B4967A437F5C43496828 /* SDDisplayLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 25AADAD73C32FC4E150A4A19780980C4 /* SDDisplayLink.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 711D32EF4A9901567A488291603BF906 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 5248A2EBBCEB19A0BBFA557B594E2DEA /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 71538A1D21015F459964BA625D5EE90A /* NSObject+MJClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 96163189CC5AFA5E4E23D6B0B3EADFF7 /* NSObject+MJClass.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 717F76926C7BCB5B10C3037AD9239084 /* SDImageIOCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E6BDC6A27A05429814F2520B890A63 /* SDImageIOCoder.m */; }; - 71BEB1D9532900291A5A24B1C038516F /* UIColor+SDHexString.h in Headers */ = {isa = PBXBuildFile; fileRef = D6A9452B8FC36F44EC5608AB04827703 /* UIColor+SDHexString.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 71F2B8CBB99087F348C472230200586F /* SDGraphicsImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9843F03B02D2521214C5C5583A9BBDA3 /* SDGraphicsImageRenderer.m */; }; - 723D1925C39764631641D0DBFDF6833B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 724991CA89C46BAFBC08264D94D86484 /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = CA67A34B63E36E76FF453D2ABD613A39 /* AFURLRequestSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 74ABF19BACB99F862DB62AA14508AFA0 /* LookinAttributesGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 594BEBF4113035634E37CC4FC2A11D62 /* LookinAttributesGroup.m */; }; - 74C474676C69A80BEC29B0F55FDF4D19 /* UIView+WebCacheState.m in Sources */ = {isa = PBXBuildFile; fileRef = 96D5456A17DF66E262562E8208ADEFF0 /* UIView+WebCacheState.m */; }; - 74E069F8C9E22C0E37F261A5AB03A613 /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A5A249D6ED704F9FEE1FFBC9B61426F /* SDWebImageDownloaderConfig.m */; }; - 752822FE3F5092322D18FEC4533B79A9 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 94E4D004CAC99A7D4B7144E86418C29C /* SDWebImageDownloader.m */; }; - 75771A97B77FA30A0175A81B480F80EF /* UIImage+ForceDecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A67F3F63FB3C05544B8F66F7ED89E74 /* UIImage+ForceDecode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 772CF8E9CD02ECA4275B6173E2110E80 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 31E7ED25B098BFBF30E180BFC0E2174B /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32ACEDCEBE0507A82D6323114A1C74F1 /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B5075BB968E268BB5D61B393C333DB4 /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32F2B91621A2F8F9AD7C8E2B224D73F6 /* SDWebImageDownloaderDecryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = E38A10934CB29F9B2C75A0785209FA84 /* SDWebImageDownloaderDecryptor.m */; }; + 32FF240AE9443A1D2CFE27F50B55F591 /* LKS_MultiplatformAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = EDA0AA2D50C091E5400CDFDEC4B5B802 /* LKS_MultiplatformAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 332F2099D726E75CEFAF1F734104A066 /* LookinWeakContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = B0922492568B0DD6D1F92C0E3B3A53A1 /* LookinWeakContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3331A013D48A5063B483A51B7E9068ED /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = EA3E73CFAE53223D9EC3DE4B0794DB06 /* AFURLSessionManager.m */; }; + 33D3587AF629B2FA21554DA002D6ACB8 /* SDImageCachesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DFE214BE294126C1B4FFE49DDADA7AEE /* SDImageCachesManager.m */; }; + 34B28D4F0168194B6EFAC0520EB7A7F4 /* NSImage+Compatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = B09C6285E70223CDED72989080A8442A /* NSImage+Compatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 353C1D03325B8F3E65F985DA29245F18 /* UIViewController+LayoutHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC211B96CB1A7D40B3203E4778066C9 /* UIViewController+LayoutHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 35D42759A562C482EA5DF574F75CF3B8 /* NSArray+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 852A42FAC0EA5F64033033841A03891A /* NSArray+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3679603CE8336E00A0BFAA39E10A92D0 /* HWPanModalShadow.h in Headers */ = {isa = PBXBuildFile; fileRef = 568F43CF567335FABEC4825ED4776B19 /* HWPanModalShadow.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 36B3F095DFFC8D2AF2C0A8C523173927 /* HWPanModalContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 091DAAA7597B1233173C3BB1DC8D1D79 /* HWPanModalContainerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 36F4B09E7C71DCC5CEC6057814033C37 /* UIView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 36BEAD7507B8644D14D46C852A6EF20B /* UIView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3777CD89D444CBBB48AE323B303F3FC7 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77F4C0466DFC43C56F1D982F88EF74A0 /* ImageIO.framework */; }; + 37B890ABDC7DD441E6AA662325D412E6 /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = FD61DA71A7253ED59D65D424C86E2C50 /* MASConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3800EA1B83FDE869FB2E4B049F519962 /* UIViewController+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7F47A09BE728487DF546FE00CA555E /* UIViewController+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 381E0DBE152CA0D9C66310CB77A20A83 /* HWPanModalInteractiveAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 74751305705DEA03873DFA2AF4DDC9B7 /* HWPanModalInteractiveAnimator.m */; }; + 38938E604A7D708E6378A44063EF3512 /* UIImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FB718B97DF8D94DCF736C973F8184652 /* UIImageView+WebCache.m */; }; + 392F62298E0D8C669229E132D791BBF5 /* UIImageView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0C012CAB8552E7EA8382B0E5D6B738 /* UIImageView+LookinServer.m */; }; + 3A1AD84C0DC3C256418CC46739024E96 /* SDmetamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 98B3D67E4B164109B9B94A959496BA25 /* SDmetamacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3A2FCB914F6EADED828FF05F7E9132AE /* UIView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 38C2193309DE8B485EA6F0495C08B115 /* UIView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3B1C72DC480AB19BD55B6275750D62FE /* NSSet+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = C1D06F4343D9C630BC102E7BCD9CECCF /* NSSet+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3B62431BEF820E7FC779F344AB2A1D17 /* JXCategoryIndicatorLineView.m in Sources */ = {isa = PBXBuildFile; fileRef = B49F76B93F72D361782D7DA99B65ADC9 /* JXCategoryIndicatorLineView.m */; }; + 3B8EDFF69A68ABD3735E0C6931CA5C95 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1612A7E2EB4D912BD038AFA9FAE11CFD /* AFURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3BB69CB142D744367868F834912993CB /* UITextField+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = C64A52A00F5D8A13BA6BD40D1834BF56 /* UITextField+LookinServer.m */; }; + 3BD85ED8999015326D93D8EEADCCF910 /* HWPanModalPresentationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1724C0944D7BC65545806EE9EDED203D /* HWPanModalPresentationDelegate.m */; }; + 3C7815EEC599DD7D42FDEF19B2FF1563 /* SDWebImageOptionsProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = FD3C0DF69EC6CFA1DD8299F62B1A84FB /* SDWebImageOptionsProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3C7EAECB8C573E714C818BA04EB33773 /* UIImage+MultiFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 517D8EDC9F4BA34E4E4060247125B56D /* UIImage+MultiFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3C8F2F868D0C361CAF43E53CDB8EB631 /* SDWebImageCacheSerializer.h in Headers */ = {isa = PBXBuildFile; fileRef = BD430BA3E5DB115A0F8BF9D6110923AE /* SDWebImageCacheSerializer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3CA9E838F014DC32CFCF6AD36F5D7E58 /* HWPanModalInteractiveAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = 47A97040129EEE8B96AEEA0A9B73DA45 /* HWPanModalInteractiveAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3CE13969772F4180701A575FAB98E978 /* JXPagingView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B4319C3394898C8897D6580DAC5A5124 /* JXPagingView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3D0BBFEC1921CE71BC240DC18D8BE540 /* SDImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = C45DF4498F0949CD4F02FA86BFE50D93 /* SDImageTransformer.m */; }; + 3E3D09700A62280A9EB8D65B97335ED8 /* LKS_CustomDisplayItemsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = C19EBB7B5E5A5B4CB83F93B794EA02A1 /* LKS_CustomDisplayItemsMaker.m */; }; + 3E982309E295BB31C065D62750D0F1FD /* UIView+LSTPV.h in Headers */ = {isa = PBXBuildFile; fileRef = 6757029D58C1BFD772BCC87D14A52E39 /* UIView+LSTPV.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3FF7252DD60182221BB1E5A167C41A07 /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B758502F7753329D591359BA2747831 /* UIProgressView+AFNetworking.m */; }; + 40AD5D0AB3ABF7F3A5A4A98BC5B84419 /* LookinAttributesSection.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE21A3C562355122DA705E505CCA673 /* LookinAttributesSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 416DA8B2997381F954DBA6E6A53DA4A2 /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 928339E7523C1267D5DF15E548454A5E /* NSData+ImageContentType.m */; }; + 41A4AAE7E6024E7AAB83DD22FB42D34D /* UIColor+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = FED91C88820F2942B3A007C5E5D17ACB /* UIColor+LookinServer.m */; }; + 425C9EA28FBEB7F7FC09A3F4A88C5955 /* SDWebImageError.m in Sources */ = {isa = PBXBuildFile; fileRef = A4F1299F85FD74B081B5C5F85EF530B7 /* SDWebImageError.m */; }; + 4281CC31F4D4EAE690F999C778F17E5B /* JXCategoryViewAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FF761C99D422AE106C31A4A7AE469C7 /* JXCategoryViewAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 431023914A5D2653ABAE7AB54880C9AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 4334CCEA5B7EA16A4EF26702D287CB07 /* UIScrollView+Helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDFAC11D184E7F4498FC12FE0AFDCFC /* UIScrollView+Helper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4424E7517B86FE622BCD3D5040FC579C /* JXCategoryTitleCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF1A36FA548FCE3A4F7DA66625E9583 /* JXCategoryTitleCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 442F468E261A1106C291BF52BDBF9DB7 /* MJRefreshHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 16308A5AF08E401B61B68CCD953A0528 /* MJRefreshHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447BBB1BCA8E0F2D23634888BED6DA81 /* LookinDashboardBlueprint.m in Sources */ = {isa = PBXBuildFile; fileRef = 73A2C1D7BD2A650246BEE1A00F6D836C /* LookinDashboardBlueprint.m */; }; + 44CD842019B1CEA681F820F37A30B7C4 /* SDImageFramePool.h in Headers */ = {isa = PBXBuildFile; fileRef = 449CCE39A5A9EA789B9A284113D1025E /* SDImageFramePool.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4503182D5F8EF2F02609862026D2D455 /* HWVisualEffectView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E270235979252FF388A0C6D1E54966D /* HWVisualEffectView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 452C940762F65B125C216F73B369F583 /* MJRefreshStateTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 29792A8AE7CB7444FE7BA20424B814AD /* MJRefreshStateTrailer.m */; }; + 4571A0EA37DC84F39E3830D38A1531AB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F5B3C0CF01454E7AC9226E88FDFBAE6 /* UIKit.framework */; }; + 45E1583D7EF53489B82C4CA2AD1AD0CF /* MJRefreshBackFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DF0242A37C60B9E8BEDC175125BB2 /* MJRefreshBackFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 464A0100327C8531D86BDC31737CCF75 /* LookinAppInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DF85367F662269F3652AFC693AA2B00F /* LookinAppInfo.m */; }; + 4688743B7B845309486559EB7BD5D147 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = B87895ABF5221A865DF2D53247763F89 /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 475B4F3E71C293065AAFDB1888696CF6 /* MJRefreshBackGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = BBA58A99F7E528A8D41BD96706230160 /* MJRefreshBackGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 47C6C10BB05445BCB8CBCA4DADE7E933 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 48916DE9521F627589300512ECC2D4A5 /* NSButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 53155231B4EB5B29274A0546D6F39B91 /* NSButton+WebCache.m */; }; + 4A15ABB502D625EBE3E63100664AB822 /* LookinCodingValueType.h in Headers */ = {isa = PBXBuildFile; fileRef = 99712B41FFAFC24C5F649A94D8DD7FFE /* LookinCodingValueType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4A2D7878579537881DD3859B3359F702 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 638488B4F5FF9C67F848A841B1A34765 /* CoreGraphics.framework */; }; + 4ACC15DF96D179E48E4276AE3C540C7C /* KeyValueObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = A2350DF4D8FE6C892E64B8C644667527 /* KeyValueObserver.m */; }; + 4B2C2AE16AE3DDA7417AFCF7952588F1 /* SDImageAssetManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F5507B4A6BD90BF5F74B1AAC009AD90 /* SDImageAssetManager.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C8C34A09D61A3881DFB1A544A2CA2A5 /* JXCategoryFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C9E2AC9C9AE14EBBFDCDBBA925613E4 /* JXCategoryFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4D2C79AB2D24CFEC864F08D913CE7692 /* SDImageCodersManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 03700B93F7A3FF6F3675D80E5DB1C1C7 /* SDImageCodersManager.m */; }; + 4DA2C6099343CD55160ECB3EBDDFE1DF /* NSObject+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A2BDE1ACE119E645C72F92B4CCAECF4 /* NSObject+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4DCA75BFE1558CE59DFC56607E49B3D2 /* MJRefreshConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B4792E0E693278C27DB918B70E58272 /* MJRefreshConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4DD9F4BAA95C3527A660D3AAD055CF1E /* HWPanModalContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = E6CAC4483459A4704E779D629644670B /* HWPanModalContentView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4E964FFE29CFF8613C0029C913F39A05 /* LKS_InbuiltAttrModificationHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B8796E86BD11BC29D00EED72E50AE91 /* LKS_InbuiltAttrModificationHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4EC8DBADA7BB954276351A639EB4398D /* UIBlurEffect+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = C41AE199679E3EEC03FA1272FE103027 /* UIBlurEffect+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4ECE7F80A917130DE4045E25D741EAF9 /* JXCategoryTitleCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B70A750F053AB9B0B60CBF456ED577A9 /* JXCategoryTitleCellModel.m */; }; + 4ED05DB3E43FF6AE1FA22130B2B50F05 /* UIImage+MemoryCacheCost.h in Headers */ = {isa = PBXBuildFile; fileRef = 0055AF44029FABEF5E29D1BC1B86CC15 /* UIImage+MemoryCacheCost.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 50096BAC0F3270FB111E76D32714E579 /* Image+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = C6553D3214536278C24D990CC36267F3 /* Image+Lookin.m */; }; + 506FC58999564A737C745F2590E9B4D5 /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FB614FC70886C761E2BA7E9C7E7F2D88 /* AFHTTPSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5106193FDEA44A08AAAAB9B8A227CBE9 /* HWPanModalPanGestureDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = F764EB4004D4A21398D072493BD19D56 /* HWPanModalPanGestureDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5111A0A0934551CD2B9DDB1A1CA79FA7 /* SDAnimatedImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = C94F3031AB6C5451E9610DBD24FE9029 /* SDAnimatedImageRep.m */; }; + 512B9661FC34235E0EEB3A6D3E319B88 /* MJPropertyType.m in Sources */ = {isa = PBXBuildFile; fileRef = 073DE0C455B2CE33A0FBA3C6ECF4F8CF /* MJPropertyType.m */; }; + 5163FC6D715F6881B1FA1AB13DCEF870 /* UICollectionViewLayout+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 70021D526E8906DE61E9D2D0F92A78C3 /* UICollectionViewLayout+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5174DD2019966DFDC21B8864453ED3DE /* NSObject+MJClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D149C2EB765D348E439D96EC2A80A04 /* NSObject+MJClass.m */; }; + 523235228A1C021C67F2E3776A922DC5 /* MJRefreshTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = 572433DB55AF2085E2E4D419FCE37679 /* MJRefreshTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 526485EF6D2B62B24DB59122FB94BD42 /* SDDeviceHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = F947DB2E34F4112ED83356B8AA944880 /* SDDeviceHelper.m */; }; + 52E60EE26D065DB63D272298AC8867DF /* JXCategoryTitleVerticalZoomView.h in Headers */ = {isa = PBXBuildFile; fileRef = 996C55702A2E4E7B3785C0C5454598C9 /* JXCategoryTitleVerticalZoomView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5308E660E723C11E7691D311FD59C459 /* SDDisplayLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 1679E08A4A241FB86455E71FDFB20D9F /* SDDisplayLink.m */; }; + 53433003112C4FE271EC985803862B61 /* SDWebImageCacheKeyFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = B4F7FC0CFCBE2143A4999C2F356D2B47 /* SDWebImageCacheKeyFilter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 53C1722650FCAB2637867D0DC31FC3CB /* Lookin_PTUSBHub.h in Headers */ = {isa = PBXBuildFile; fileRef = 210B700E8324769F741C26126E6B1F4A /* Lookin_PTUSBHub.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 541AD3B0F5EA216EE730ECC6E8B84C31 /* HWPanModalPresentationAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 831897EBD9EF72C4D55D02DE399C410A /* HWPanModalPresentationAnimator.m */; }; + 546DE9D8142C6D8554E083C6FD65D0BE /* JXCategoryIndicatorTriangleView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B766998FBEAD558A15F06134D5A9335 /* JXCategoryIndicatorTriangleView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5490C03887ACF6C4EAC25ADFBB509CE5 /* NSSet+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = E312EC8FB74A492C6D5A647700644AC4 /* NSSet+Lookin.m */; }; + 54E268C32915CF908E7AA776909B45EB /* MJRefreshConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 8638AEC16F5A3F7D05EF0F7C39544261 /* MJRefreshConst.m */; }; + 55910DBCDF99E39955BE01EAD8251081 /* JXCategoryImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C9A23E37AE09BB9DC1BC766BD3A6AA /* JXCategoryImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 55F7C7F055A18044497F8C88CAE34118 /* SDImageCachesManagerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9E5D3590E1EC14CD269A8B340CE3F0 /* SDImageCachesManagerOperation.m */; }; + 561420A20DC0A84258A902E9EB69A15A /* MJRefreshAutoFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = DE7E60B5B6A0850596F935D95CAFE167 /* MJRefreshAutoFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 564714D075CF51356D3D8437846AA6EB /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = DE378B71C4559C86FA84F1AB2F15BD03 /* AFURLRequestSerialization.m */; }; + 56D8A7EAE4D72FF6C23421CAB6F21504 /* MJPropertyType.h in Headers */ = {isa = PBXBuildFile; fileRef = A0329494F5B3BBF4A9C54DD83622388B /* MJPropertyType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 56E800EB3B2BE8AE0BA45A30974D7920 /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 07001E763AE097A75E1AFBEB80197373 /* Masonry-dummy.m */; }; + 56F1B543BC54204336CB5E50B60F719F /* Color+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BE10EB8B74E3D1DE4172EF863BC22F8 /* Color+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5735091665AC18FAD028EB68786A85AE /* LKS_CustomAttrGroupsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FF07E10C8C0B816653B6836CCFFD04 /* LKS_CustomAttrGroupsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 579DDC4FE78455D88E0350C3268D96C4 /* JXCategoryIndicatorComponentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D490F15AED6B55BCD64F4D5193A9375 /* JXCategoryIndicatorComponentView.m */; }; + 58852265A6A355CDF8D25BCD71F54F3D /* Pods-keyBoard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 969A9A842778EFB5D62826500DFF4E11 /* Pods-keyBoard-dummy.m */; }; + 58F7CE37BB4CB3BE806B68A502E6E1A7 /* SDWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A92BC89EBEE6C3CE964CA994B506EA43 /* SDWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 596180E0EC9F46D12BA840DC4AA62659 /* UIImage+MemoryCacheCost.m in Sources */ = {isa = PBXBuildFile; fileRef = 0451FF8513ABCE79BA473B450192579B /* UIImage+MemoryCacheCost.m */; }; + 597E390C0BBB75B8045B651C487C2034 /* SDImageAWebPCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = BC30CFC7778FEADF9DCBF0A4ABA1769C /* SDImageAWebPCoder.m */; }; + 5A6D3BE92C77ED70C397567996DFAEB9 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A11C415AC80BAC0B06685E1F8AC7C7C8 /* AFHTTPSessionManager.m */; }; + 5A8BC91257FF6B36237BF09A7A6EADF6 /* LookinObject.m in Sources */ = {isa = PBXBuildFile; fileRef = CFC8ED8D34DD2679124911EB0F515607 /* LookinObject.m */; }; + 5AF22814CD055B553AD9D78BE54B94E1 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = EB461C49F04DBE8D8B709BDAA4911ADC /* UIProgressView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5B08596E856E4CC2F34A8A2372F9F764 /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E34DAE4904CE87FBB70688EA36DF9D3 /* NSArray+MASAdditions.m */; }; + 5BB6B99986FD7111B3AEBE931C7F507B /* MJRefreshAutoStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C065D632F2F749CBD48B178A68B1631 /* MJRefreshAutoStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5BD5D9B8F61C124A62C75D9AC36A07BD /* MJRefreshTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C64D6AC35DE27CAD74CA154541AF1C9 /* MJRefreshTrailer.m */; }; + 5C8279C226EB028B044C5A0F4AC5A91A /* SDAssociatedObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E4BFFACAA945CC17167910BF3C319571 /* SDAssociatedObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5CAB535753B28B463140F421E9B00136 /* JXCategoryIndicatorCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 913F72595D3AEFAFE006FD96A54FD8DA /* JXCategoryIndicatorCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5D0DEC179A7B4143769C663082E2662A /* LKS_ExportManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C47102257C212ED978684D39466579B /* LKS_ExportManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5DCBA14510E091D6A1CE499B08B794B5 /* UIImage+Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 429004AF40A48DE835234068590E6A94 /* UIImage+Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5DFCBADAC7D0FAC82C84A6C8E7BF1DA6 /* MJRefreshStateHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = F8CEEFBE4317D04F4FD181E44C90A119 /* MJRefreshStateHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5E10328A83E05D0015D7459FAAEF121D /* SDGraphicsImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = D444527057532BACBF8EC98BE62D3E03 /* SDGraphicsImageRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5EE53074B8A35D48AB76CAF38C88A37A /* JXCategoryView.h in Headers */ = {isa = PBXBuildFile; fileRef = 892976CDE28E9BEF86BFABB5F84E72F6 /* JXCategoryView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5EFCAC311A0285F51E8B1B0F7416D7D8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 5F45735DF355530CC955066D3C007E19 /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EB329DC3D8A252CA69C19DAF330A784 /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5F5426608460A8B17C1AE5C2351BAA19 /* UIScrollView+EmptyDataSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 45FCB10C5ADD911EC17F1E6BAAFE9892 /* UIScrollView+EmptyDataSet.m */; }; + 5FDC4239F7B651092BF582D0F460BAD4 /* UIView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 60696FE70F42B1A0CD7B0614C2A2F16C /* UIView+MJExtension.m */; }; + 6002CB94684D7C786700D2A294146AEC /* Color+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2681504ECC11F7B0563ECF0A1FDDFA /* Color+Lookin.m */; }; + 61461B0D9D7B81C3F8D24066D9A19DCE /* MJRefreshGifHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7718D3A1CB256B2263AD76B8EFDC9B86 /* MJRefreshGifHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 61507E402F1F7C58BF119995A0479A22 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 986324EA3CC9A3BDF0E5C7B1763862EE /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 616A8338C42FB01748DF1BDDA944858D /* UIView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F8CCC7FB49429A8093BC8191C6474D58 /* UIView+WebCache.m */; }; + 61857C821395B868C65A8FFE4DA1B4E3 /* MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 13AC6B7EC0E45B7BC751451206C8C575 /* MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 61EAFBCDC83B2C603918B3C9D9A73A18 /* LookinConnectionAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 10DBEAC7DAAC95D5A947ACA061058C0B /* LookinConnectionAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6204F3E4E75772BB6CAB13CD53D9D93E /* JXPagerSmoothView.m in Sources */ = {isa = PBXBuildFile; fileRef = CF46C0579CB3C54966C0F025487DB215 /* JXPagerSmoothView.m */; }; + 620A0FFFDE5AEF215E28135566106BA4 /* JXCategoryBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D939E1825294C23871CD06F0A1E6A2 /* JXCategoryBaseView.m */; }; + 62FE895DF9D65A2955A275D909ECBE18 /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 883434364AD74D3F77868A0CF2FB7A09 /* SDAnimatedImageView.m */; }; + 6525ECE1CAFC1259F9E6E5FDDE6CF218 /* UIVisualEffectView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9ABEB6B0A44AC8BCBC6CB1A8A8A9A0FF /* UIVisualEffectView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 659D38386A3E09422812283BF27D71D1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 6630C0B541E50903F9AD81FD847CFE7A /* JXCategoryIndicatorBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = D68722AFBA338282E0B3C89AFE0F83AC /* JXCategoryIndicatorBackgroundView.m */; }; + 67178A8153B1A2F1D0D544B8093E23C5 /* SDAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A2C2A9B920BB92B872BA2AC2EA086220 /* SDAnimatedImageView+WebCache.m */; }; + 676775CB29378BB6CA3CA5992E9C6A99 /* SDImageIOAnimatedCoderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = EF1815C1F114106321929B2F631067E5 /* SDImageIOAnimatedCoderInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 67FCC0F9B42B1C20A66E99A3D56BED18 /* LookinStaticAsyncUpdateTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 09799A44FC43F3184E20B590CC73FFC7 /* LookinStaticAsyncUpdateTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 683D708C157C95ADB467BDD2230BD4E3 /* UITextField+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D2F2FDA20E8BC9884D1E9ED05D83DDF /* UITextField+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68C3E98F8B9D6035962F29AE025DA891 /* UIImage+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 20C453B83E1025092DAD587080018B43 /* UIImage+LookinServer.m */; }; + 69345CBCB31076EBF8A2C5885AF973AB /* MJRefreshComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E9C6ED309FB0F6481FF6639AA9C417B /* MJRefreshComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 694B8697854A776E32032999B2EF1FEA /* UIImage+Metadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5C516541F7C7AC40E990C05307FEEF /* UIImage+Metadata.m */; }; + 6960FF2C4D61A09722930B33B1C7135D /* LKS_ObjectRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = CB5214881D82D6C122FB4D3B471F9D93 /* LKS_ObjectRegistry.m */; }; + 69A06A02F52EB26259FAD1DF6B121BE1 /* SDCallbackQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BD134826FCB54429F667B8DBF296710 /* SDCallbackQueue.m */; }; + 69AB6A513D5F36D7360FEF4FDA1D60D0 /* UIView+WebCacheState.h in Headers */ = {isa = PBXBuildFile; fileRef = 919C930C4E0162377E3C95D0F6F11177 /* UIView+WebCacheState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69E353C99C6EEA3C93CCF2E526460B9D /* UIScrollView+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0511947F57D1CF3F274B6414AE449B /* UIScrollView+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69F6E66A089C40FB1063DE15499BCFDE /* LKS_Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D2B4D757199E020DE43661B60EB2819 /* LKS_Helper.m */; }; + 6A19379E3B0370EDA447743C9B1A1379 /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 855BA7199BD9AC7B4687AF3F66E21279 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6B0978C9398336656EE309E62060AEAB /* SDImageAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 87B2A7EE05A20B3EDDFE045A6B7911E5 /* SDImageAssetManager.m */; }; + 6B5C3592B5E911E833D067D0BC785B1A /* SDImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D8BE2762FA18EF88A5BAD861C739B02 /* SDImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6B9D333C18DDBF4E7CC889F7FDE05EEA /* JXCategoryDotView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EFBD2E7A88C44123D980C42CB8702A4 /* JXCategoryDotView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6BC2A615678C8BAE9F34ABA68BFDEF78 /* LKS_AttrModificationPatchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = DEFCE7D8BFD813860A380F7F5B5EB401 /* LKS_AttrModificationPatchHandler.m */; }; + 6BE86A0FFB0D69C6098CC75E1FB4E8B5 /* JXCategoryIndicatorCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 5EFCD05B81004D2C239BFBEBEE4DC3D5 /* JXCategoryIndicatorCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6BF5DB46D42D8B9D536C870EC77BF4A3 /* JXCategoryIndicatorBallView.m in Sources */ = {isa = PBXBuildFile; fileRef = F9FBE6B4C01D1445DBFC466AEA64E5D8 /* JXCategoryIndicatorBallView.m */; }; + 6C57809DCEA4B6C0CA79918A69FD75DE /* LKS_ConnectionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA49453EBB9C905AD701D17F18479113 /* LKS_ConnectionManager.m */; }; + 6C76DB1B99B98C951F687DE80FE6F463 /* JXPagerListRefreshView.m in Sources */ = {isa = PBXBuildFile; fileRef = 659E098AEC86E789470E344EB23EC1DD /* JXPagerListRefreshView.m */; }; + 6C85CA8D99E50C137D056B6057DAC58A /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E9CB1F62E65A837FF5E47B2FC3ECA1 /* UIRefreshControl+AFNetworking.m */; }; + 6CA0B4A9E7B2957063163BC673F355CD /* AFAutoPurgingImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ED87146FC94850F3891F867B1931F652 /* AFAutoPurgingImageCache.m */; }; + 6CE8701D161A4BC0860FAF3951762A34 /* LookinHierarchyFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1C13D0C9F5E8ED93D0398C379507C1 /* LookinHierarchyFile.m */; }; + 6D637D02F5EE50D21C8548061956C898 /* UIViewController+Presentation.h in Headers */ = {isa = PBXBuildFile; fileRef = DB3B6BBCBC04C438F099DE5DEC15C188 /* UIViewController+Presentation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DE6C7F0FA965828E4FCE687BF75FBBE /* MJRefreshAutoNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6021531912761F1BDBFE14A61784B26D /* MJRefreshAutoNormalFooter.m */; }; + 6E4DE8085E69AD1DDB49B059DCE286DB /* HWBackgroundConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F0DA836C065C821DDDE100A36B1C087 /* HWBackgroundConfig.m */; }; + 6E66305665DBCFBCF5B2480BF705D500 /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 59CF9D4B8C92110B4BC1E1792E4AAEA5 /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6EFC0630CB2761A2B1FC47176CCD62D1 /* LookinCustomDisplayItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDFB85C3FF1851267A20FACB64B4497 /* LookinCustomDisplayItemInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6EFEEE3AE22E97DCEC4F5A3B88F56FC7 /* SDImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = B9E1D06297B630EA32D1369915C0CB97 /* SDImageLoader.m */; }; + 6F3637EE643EABB1DE9212EA68649A64 /* UIColor+SDHexString.m in Sources */ = {isa = PBXBuildFile; fileRef = 343C42E325F84441C510AF8DEE739ADF /* UIColor+SDHexString.m */; }; + 6F75FDB9BE37C9A8473F97B1696B5D09 /* JXCategoryListContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = D9CF33220A4EDFF59077DE1F83605414 /* JXCategoryListContainerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7053A9EB6335BEAC9EFDF2D5320E6E2A /* UIView+HW_Frame.m in Sources */ = {isa = PBXBuildFile; fileRef = ECA7ED760D61427E9195A2805DB71798 /* UIView+HW_Frame.m */; }; + 7074EA7FCC90B4967A437F5C43496828 /* SDDisplayLink.h in Headers */ = {isa = PBXBuildFile; fileRef = B5F6ED51FA52849CB3D9D44DD45396E2 /* SDDisplayLink.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 70D30BC7134E3C8006BF0B6A4B438057 /* JXCategoryTitleImageCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 524557CADCF9674C470A7B1764594AEC /* JXCategoryTitleImageCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 711D32EF4A9901567A488291603BF906 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = EE827BC4171898B142EBDE3C763AFC7F /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 713D162A627185DA38847832AB5BDA44 /* LSTPopView.h in Headers */ = {isa = PBXBuildFile; fileRef = DB7D4CE7BA063A9CA415CD86C8825985 /* LSTPopView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 71538A1D21015F459964BA625D5EE90A /* NSObject+MJClass.h in Headers */ = {isa = PBXBuildFile; fileRef = DEDA7D852A16AEB2E4133F8138BB40A3 /* NSObject+MJClass.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 717F76926C7BCB5B10C3037AD9239084 /* SDImageIOCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 04094D9F916F0B3E8A409CF5EEC45FCC /* SDImageIOCoder.m */; }; + 71BEB1D9532900291A5A24B1C038516F /* UIColor+SDHexString.h in Headers */ = {isa = PBXBuildFile; fileRef = DC85B08C4C82F12C3AA7970FE44E1D9F /* UIColor+SDHexString.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 71F2B8CBB99087F348C472230200586F /* SDGraphicsImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 46F71F9F19999F6D4F186847FA3CC8F7 /* SDGraphicsImageRenderer.m */; }; + 723D1925C39764631641D0DBFDF6833B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 724991CA89C46BAFBC08264D94D86484 /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4228538168305A12A3465600D6FA372A /* AFURLRequestSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7276688DEA6FB95D4DEB7F3D019C3958 /* HWPageSheetPresentingAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EC115C953943E0027F6AD5AFEE41A30 /* HWPageSheetPresentingAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 728107C8D8479AADE986F4EC23233DC3 /* UIScrollView+Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 330AFA4D280CBB2EE073DCC942489EAB /* UIScrollView+Helper.m */; }; + 73B19D03C7B7DF1C944544165F742D82 /* HWPanModalContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BED1E57A7780D7944D806EF7FB48648 /* HWPanModalContainerView.m */; }; + 743BBA00940EF6877AE1D5014755D0D6 /* UIView+LYExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B4EEA7B77703F45AB157AC651CEF4EA /* UIView+LYExtension.m */; }; + 74ABF19BACB99F862DB62AA14508AFA0 /* LookinAttributesGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B1EDD790AB62D80A6CA23D5272938B /* LookinAttributesGroup.m */; }; + 74C474676C69A80BEC29B0F55FDF4D19 /* UIView+WebCacheState.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E4925A54FF503F963785651A98856BD /* UIView+WebCacheState.m */; }; + 74E069F8C9E22C0E37F261A5AB03A613 /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 6650E50E5FAFFD61FC973E5A0D5C8398 /* SDWebImageDownloaderConfig.m */; }; + 752822FE3F5092322D18FEC4533B79A9 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = B453C947A0F7F0133F2F98F9E8EF1E43 /* SDWebImageDownloader.m */; }; + 75771A97B77FA30A0175A81B480F80EF /* UIImage+ForceDecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 317AEF64C0405ADA2DB47569A6D72FC4 /* UIImage+ForceDecode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 76019F9FDD44B8F79261AD55C8728164 /* UIView+HW_Frame.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B0B272843C604B68C602DEE1AD3605F /* UIView+HW_Frame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 76C8C631DF9AC2F667369EEA0CE46522 /* HWDimmedView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1705DF1CC5E82194523F85FE871354 /* HWDimmedView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 772CF8E9CD02ECA4275B6173E2110E80 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = EBEEA0239556FEF194877FD307A4ADD6 /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 780EDF2615923E89C179EB5A60D2DA41 /* JXCategoryCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 051A66FC7C22537DD150BA86539EC9D4 /* JXCategoryCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7873F2F89CD0A435FAB776BC27BFB56A /* MJExtension-MJExtension in Resources */ = {isa = PBXBuildFile; fileRef = 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */; }; - 78A3C3994AFFC6A2D4970AEB6D797CE5 /* LKS_HierarchyDetailsHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 94310BE9068195ADA7842BD0A9A7F782 /* LKS_HierarchyDetailsHandler.m */; }; - 7902D28FC9EF5AFEB452F508C7F266B1 /* MJRefreshAutoNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF1C0B2DCF27A6785AA511B6C9290B9 /* MJRefreshAutoNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7989A6E79BFA78440C39F568D972305C /* MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = A53791C99F3E8789C928D8471E4310AC /* MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7A4EB9ED5D4E03170FFE61FCB299687B /* SDAnimatedImagePlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D30CE312289056E4C5788AB47438FED /* SDAnimatedImagePlayer.m */; }; - 7C45DBA62EE045C4922404182F6393B8 /* SDWebImageError.h in Headers */ = {isa = PBXBuildFile; fileRef = EE96F8DD901EEB1A8375B055EDF7DBBE /* SDWebImageError.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7C53FB6BBB0CBAA879F1603B0FEDB80B /* LookinAttributesSection.m in Sources */ = {isa = PBXBuildFile; fileRef = EF6193F470BF021CAED5E3E0DC4F602E /* LookinAttributesSection.m */; }; - 7C5505A2D3F2A697A5F324787061F4B7 /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BA0DD426F8305DA317D708459ABA12F /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7C8782A3078662BC2EF639A9608A2C82 /* LKS_InbuiltAttrModificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 37559870F51779045F8C7A57C1303E2D /* LKS_InbuiltAttrModificationHandler.m */; }; - 7D736CE5AD0A987D2A7D2FD72E31BF41 /* CALayer+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = A99D2B8B886EDA66D95608FD72CE97AF /* CALayer+LookinServer.m */; }; - 7E4F0978B25350B2B28678A0BE7B3785 /* LKS_HierarchyDisplayItemsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FBF3084E82AF80B1B017FB5240AF4F /* LKS_HierarchyDisplayItemsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7E8A564A958AF81E5F63F34B8E550E58 /* LookinAttributeModification.h in Headers */ = {isa = PBXBuildFile; fileRef = 06660480BC631DCE06583A85704487AB /* LookinAttributeModification.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7F10C0D094C74F2FA4CD38C7FD77B0A8 /* WKWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 0426BF3118E242E4EA8BB1145A2A6F60 /* WKWebView+AFNetworking.m */; }; - 7F886FC2763F0BF1625A24EE4F94C04D /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 32556CF656ADFF88DE99F135C7BE2EB7 /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7FA8C78DB021A7731D30D80C102DE042 /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EEEDD3CF0530751FD80AFB402DAB153 /* NSObject+MJKeyValue.m */; }; - 7FF8A56511E71D6FEC966BF9FEE135B5 /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 245FCAB926AF197B8F4E931DD8477D4A /* AFNetworkActivityIndicatorManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 810C8D7902163BBA0185A4A112B2DFD6 /* LKS_TraceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A3868E0511721B009DE0A628C978E4AF /* LKS_TraceManager.m */; }; - 813BE4C96A6D39C13EC50C6CD164F0AF /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 63B2D397715E1B3990E46DFCAE0A73D5 /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 81A5635CEA2AD9623E30CAE9AFC3BF65 /* NSBundle+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E12075C58652877783AAD26D8A6ED78 /* NSBundle+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 821FF6B43F7ADAB6B60459D2966B33CB /* CALayer+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = E857EC016B703D1261AC73360907C980 /* CALayer+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 83530BF68848CD2C4A79A1FD69B304A5 /* SDImageGIFCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = E5514D264E4855320B70B7010325576C /* SDImageGIFCoder.m */; }; - 83A4F2816C1B3F072E1A26A34C3BC4AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 8414CFEEB64ACA817EB88D2FEADDA3B3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 854807558DCB972EDDFC1D00032BA6E4 /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 99418F0A943BD9FF46795740F7385472 /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 85AB23275E9D19394969235E5DC2300E /* MJRefreshHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 5989AAAB35D0B7EF697456F3897FACEC /* MJRefreshHeader.m */; }; - 85BB8B4B5C29C5EEC52282F33A4CAF23 /* LookinCustomAttrModification.m in Sources */ = {isa = PBXBuildFile; fileRef = 4730B0C65CA50BE6D828887D7CC8EB9F /* LookinCustomAttrModification.m */; }; - 85C0B4EE334B9972299E62DE61A4BB56 /* SDImageLoadersManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D601D33EE8BB8396FF4AED582379432E /* SDImageLoadersManager.m */; }; - 860CB3A5D2E13B946CD2EFB7F749C4CF /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = F53768EF8D38709F253FC1C181B05162 /* UIActivityIndicatorView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 864972FB0DF4B464B1B505AA5F788E91 /* SDInternalMacros.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9EB519F0B4BF7D539877F733F7BCAF /* SDInternalMacros.m */; }; - 88473AE7C22F952DACB39FA0758D1624 /* SDMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 24998A1052F45827E4FFAFAF7FA1542E /* SDMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8872BEB0954C0254A792469F4DBC9891 /* MJRefreshAutoStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9450EAE5D947C741A2403ADD203E1875 /* MJRefreshAutoStateFooter.m */; }; - 88A23DF6F5638AC66C28C4102824E8B5 /* NSImage+Compatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B993C5AF69BCC11CB58D180BE7475BE /* NSImage+Compatibility.m */; }; - 891AB9476B659A3490DCE45A52A8D132 /* Pods-keyBoard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A2D8E1EB42D41EA6B94901E5B68C9011 /* Pods-keyBoard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 89B88FAD396608AAA9F935E471BB3CB9 /* LKS_HierarchyDetailsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E355B215CED31C4C6EF33EEB9E95B38 /* LKS_HierarchyDetailsHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 89EAB8D0452D0E2114ED971B10D98CC3 /* LKS_HierarchyDisplayItemsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E2B86406A2B5383183DAE9ABBBB3893 /* LKS_HierarchyDisplayItemsMaker.m */; }; - 8A256CA266FB314BBD4DB2287DAEF247 /* LookinAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCB45CBC3B45614560DA456506F73F1 /* LookinAttribute.m */; }; - 8AF38EDB1E9BF0D334AEB23C488870B8 /* NSData+ImageContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DBD5C23623A08CDD875999AA28A1F8D /* NSData+ImageContentType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8C6C7E25C5A24C936F81823978190E96 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = B4D76F7EB1CE870804724BC071C5ACB3 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8D8AD606ECD8E1F247965CD43956D412 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA8F3F4E9CF14305D8C83582492FEA87 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 78A3C3994AFFC6A2D4970AEB6D797CE5 /* LKS_HierarchyDetailsHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 0719BBC5095E9B709A7485C347010514 /* LKS_HierarchyDetailsHandler.m */; }; + 7902D28FC9EF5AFEB452F508C7F266B1 /* MJRefreshAutoNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 77973C87CC9649629EBEE249DCC355F5 /* MJRefreshAutoNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79534562F85AA71041043B395DE14AD0 /* HWPanModalContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E31AD6314EC8102DE4FC6291C0FE66F /* HWPanModalContentView.m */; }; + 79701CF51014A7C02D810F9DAEFE6D79 /* JXCategoryTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B49837A2AA042F710F43F143A929D49F /* JXCategoryTitleCell.m */; }; + 7989A6E79BFA78440C39F568D972305C /* MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = F64D04ACE9EB0341E57129D44479C065 /* MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7A4EB9ED5D4E03170FFE61FCB299687B /* SDAnimatedImagePlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A5D6AD5CB7122607D6E477D373A31E2 /* SDAnimatedImagePlayer.m */; }; + 7BC817F176759B34FDC3C9A3BDE900BF /* LYEmptyBaseView.h in Headers */ = {isa = PBXBuildFile; fileRef = B5885DEE0FCB371101A605FDA3D3F35C /* LYEmptyBaseView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7C45DBA62EE045C4922404182F6393B8 /* SDWebImageError.h in Headers */ = {isa = PBXBuildFile; fileRef = 16465B6B7358098E137335C9985BBBBC /* SDWebImageError.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7C53FB6BBB0CBAA879F1603B0FEDB80B /* LookinAttributesSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F8D39C76EB84B28054B453882C78E41 /* LookinAttributesSection.m */; }; + 7C5505A2D3F2A697A5F324787061F4B7 /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AC368BF52013B3AE323DC35D782A044B /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7C8782A3078662BC2EF639A9608A2C82 /* LKS_InbuiltAttrModificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A1DAAC915F745C515E0BF4D613B5CB1C /* LKS_InbuiltAttrModificationHandler.m */; }; + 7D1C6E10B8E0F98E19048BB416A39A0D /* LYEmptyBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0C4CB17BF463D490AE3400293A0D47 /* LYEmptyBaseView.m */; }; + 7D1E98BE9558F6E5E29B0E81EC526A90 /* JXCategoryImageCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 9234E8779322D7F9722AF6E18FF9F6F3 /* JXCategoryImageCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7D4B5D7A593F4436B57347FD2A5072B4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 7AC0215893BDD3C5E126FCE996097AB4 /* PrivacyInfo.xcprivacy */; }; + 7D736CE5AD0A987D2A7D2FD72E31BF41 /* CALayer+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 798B3DCD95877B6C7D997E0652FB6E9A /* CALayer+LookinServer.m */; }; + 7DFACBAC8324FE3F177FA465E0006A9C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A0497973DD4190C4C37CC950C86C6F2B /* PrivacyInfo.xcprivacy */; }; + 7E4F0978B25350B2B28678A0BE7B3785 /* LKS_HierarchyDisplayItemsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = F1FB9919B7B8171A6A8679BDDA407F68 /* LKS_HierarchyDisplayItemsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E8A564A958AF81E5F63F34B8E550E58 /* LookinAttributeModification.h in Headers */ = {isa = PBXBuildFile; fileRef = B915A35174E3017D6DC61C0A3E31050E /* LookinAttributeModification.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7F10C0D094C74F2FA4CD38C7FD77B0A8 /* WKWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = A1C4717F035C7128013EA7E000DAC18A /* WKWebView+AFNetworking.m */; }; + 7F886FC2763F0BF1625A24EE4F94C04D /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 48A816CF0BA23EA39A514E31ED98C5D3 /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7FA48BF8B9F73775654E75CEB5363FF4 /* UIViewController+PanModalPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 82F6D1678A37FB68B3455162AB8BDAA2 /* UIViewController+PanModalPresenter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7FA8C78DB021A7731D30D80C102DE042 /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7575113B17F46DF34D3C118CB31308 /* NSObject+MJKeyValue.m */; }; + 7FF8A56511E71D6FEC966BF9FEE135B5 /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = A198AAC0BC41558B9FC61F89E90D900F /* AFNetworkActivityIndicatorManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 80EBFDD01E84CE4E8AE5BAE9CB3C7C1D /* HWPanModalAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = EDA5337EF8951852F4AA839734BF6786 /* HWPanModalAnimator.m */; }; + 810C8D7902163BBA0185A4A112B2DFD6 /* LKS_TraceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C7F42FC60A06A5673FA7DE53298188E2 /* LKS_TraceManager.m */; }; + 8128D2BD3AC890F75E7AD243AA104C13 /* JXCategoryIndicatorParamsModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1936EF3FEE34E513D746BA5037CDEE80 /* JXCategoryIndicatorParamsModel.m */; }; + 813BE4C96A6D39C13EC50C6CD164F0AF /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 404BBFC3B5A2ADAEF4E188881B357111 /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81A5635CEA2AD9623E30CAE9AFC3BF65 /* NSBundle+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 412FD8B68949345873B82E2D0C864C85 /* NSBundle+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 821FF6B43F7ADAB6B60459D2966B33CB /* CALayer+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 768785318FEB9536A4DAAD47BD76396B /* CALayer+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 83530BF68848CD2C4A79A1FD69B304A5 /* SDImageGIFCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 763CF36C11B6092D9D5485AC2363F205 /* SDImageGIFCoder.m */; }; + 83A4F2816C1B3F072E1A26A34C3BC4AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 8414CFEEB64ACA817EB88D2FEADDA3B3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 854807558DCB972EDDFC1D00032BA6E4 /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = CBD58A6BE5B4D23DDB42D3D26A87CAEA /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 85AB23275E9D19394969235E5DC2300E /* MJRefreshHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 66E849825D4B5783372753D6820DE97F /* MJRefreshHeader.m */; }; + 85BB8B4B5C29C5EEC52282F33A4CAF23 /* LookinCustomAttrModification.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E445C787AA09C1E3A771E4C7DBCE2CA /* LookinCustomAttrModification.m */; }; + 85C0B4EE334B9972299E62DE61A4BB56 /* SDImageLoadersManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E585503EB164F6C036C85B124140368 /* SDImageLoadersManager.m */; }; + 85ED10431A6C01970A3DAD8A8C9BF25F /* JXPagerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8310CCDF3085A9EE32455CB865148664 /* JXPagerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 860CB3A5D2E13B946CD2EFB7F749C4CF /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB771163568003A2EA8F4B1A606B9ED /* UIActivityIndicatorView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 864972FB0DF4B464B1B505AA5F788E91 /* SDInternalMacros.m in Sources */ = {isa = PBXBuildFile; fileRef = F1CF9E4569F5B94286E175AF9D675C11 /* SDInternalMacros.m */; }; + 874CE8F3650D220092077846A46598E6 /* JXCategoryTitleImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E91A12C513A640E68663D4ED668C0FC /* JXCategoryTitleImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 88197D535BEBB0F4B71F106AE300631D /* JXCategoryBaseView.h in Headers */ = {isa = PBXBuildFile; fileRef = 45E71D8592674E85D7D5DA4831A592BE /* JXCategoryBaseView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 88473AE7C22F952DACB39FA0758D1624 /* SDMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 256D50D68BFC3FD314552D1D0BC2044D /* SDMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8872BEB0954C0254A792469F4DBC9891 /* MJRefreshAutoStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CF1445CC744306AE4ECBA85DFD6DB27 /* MJRefreshAutoStateFooter.m */; }; + 88889F5DA04EB4FA08125742B5E522DA /* JXCategoryTitleView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5105F32D29B4C0D80B780EE2DF6D2898 /* JXCategoryTitleView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 88A23DF6F5638AC66C28C4102824E8B5 /* NSImage+Compatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 23763927ED025640A4CAA94867A3D823 /* NSImage+Compatibility.m */; }; + 89B88FAD396608AAA9F935E471BB3CB9 /* LKS_HierarchyDetailsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA159570B75D1C95DC0E0B5836BACFF /* LKS_HierarchyDetailsHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 89EAB8D0452D0E2114ED971B10D98CC3 /* LKS_HierarchyDisplayItemsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 00B27A1456536538B2E7220C71AA3F4F /* LKS_HierarchyDisplayItemsMaker.m */; }; + 8A256CA266FB314BBD4DB2287DAEF247 /* LookinAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = B267D6EC269C7ADF7A4202363528E8C2 /* LookinAttribute.m */; }; + 8AF38EDB1E9BF0D334AEB23C488870B8 /* NSData+ImageContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 00449113F3BDDB46E11CEE02CF1F29A1 /* NSData+ImageContentType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8B47B7F220A2B9E121EFF5A28B477972 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 8B990235A0006E1F9C1E6F68AD81F77C /* JXCategoryView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D98B4BEA4820634A8F01172731FF97B7 /* JXCategoryView-dummy.m */; }; + 8C6C7E25C5A24C936F81823978190E96 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = FED4C87CAD14B9336A225C943B75263C /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8D2CBEBF5F1DA6766A833CCD0BF02B5B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 638488B4F5FF9C67F848A841B1A34765 /* CoreGraphics.framework */; }; + 8D8AD606ECD8E1F247965CD43956D412 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = A39050EBA53940D0CE63B52BF031BE6C /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8F30C8026F48C60D5B2CAE9CFC166004 /* Pods-CustomKeyboard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CB13D51E717D347023EEB57263E3072 /* Pods-CustomKeyboard-dummy.m */; }; - 8FF7B6477BFA6E6ABA168E1417291D5F /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = ABFE70D35403EBB3D3B8E84170698E30 /* MASCompositeConstraint.m */; }; - 906DCE66CD5BD236081D468616199BB7 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = AE4708C50A24F74BB9721BF97FDD4782 /* SDWebImageOptionsProcessor.m */; }; - 91AAF555B286FBF53E4F98D092B406BD /* SDWebImageTransitionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E3D65B846C5EFBA9201404CD8BDC1DA /* SDWebImageTransitionInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 91E8B94F8E02ABF5197DF5AE7D0B3934 /* SDWebImageDownloaderDecryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 15EEB72FE94B15511A9B077601BFC002 /* SDWebImageDownloaderDecryptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 928371B066E1211CE87089668D5BCB4C /* SDDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F52BB443191BF5EA87C6419E4BAFFD5 /* SDDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 928A1ED0692DF0229F66A87135F93F2A /* LKS_CustomAttrModificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = FB260AFEB0CD406D8CDEDE623A1369CF /* LKS_CustomAttrModificationHandler.m */; }; - 9345137ED10358B60E37D05FB6165759 /* SDFileAttributeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4223ACF818570B18B88D6B2884075BF1 /* SDFileAttributeHelper.m */; }; - 9358FC6C6DA728AEE250D8E7DD236946 /* MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = BB20479CEB729CCB614B58BD2EFB3BB7 /* MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 93E8C78EAE0B7613201813966B8E04E2 /* Image+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 2039E8AAF8AAC77E31E425C61871263D /* Image+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 955B87902E039163281C4F47C95DB851 /* MJRefreshBackNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 426AEC2F7F358DEDB66C3F2D15F925A4 /* MJRefreshBackNormalFooter.m */; }; - 96E97174F4614FFA0649085022CB4AFE /* SDWebImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EA4BA3056A1FE6B47E97AA549D4B9423 /* SDWebImage-dummy.m */; }; - 97235408E59E16C18B6BDA1D29E1CB26 /* SDWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 036896A95CE28AB066292A03BAD2BFFA /* SDWebImageManager.m */; }; - 97385A64CA020489951EF769392C6DCF /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AE06F501FB1F02940458122AC396D62 /* UIView+WebCacheOperation.m */; }; - 9887678D7D6BC165694560D92AF2C31A /* LookinConnectionResponseAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B6B095661E36C4E8A066559D4D5AF33 /* LookinConnectionResponseAttachment.m */; }; - 98AB6B8EB7FF096BCE87488C5AB3DF1C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - 9A7FB1E975A5955C896E6B195C521804 /* MJRefreshBackNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = B70FF2E3C927A22C388C16FE8C3F56DB /* MJRefreshBackNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9A89C16038149623A1DF06D47E7F953A /* LookinStaticAsyncUpdateTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DDE67F73A61A7328413374AFFA92E85 /* LookinStaticAsyncUpdateTask.m */; }; - 9B06400877E40C173F5A1C9761F288CB /* UITextView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = D54A6D034409C4B729B7DBA2D502B89D /* UITextView+LookinServer.m */; }; - 9B1EF09A8A473D92C1258B00791BF5F0 /* UIView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E3ADFF983A9B025AF718C3D24404E480 /* UIView+LookinServer.m */; }; - 9B3420DEB8A0CCB9E1241A669AEFCA8E /* SDAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BA061B3651D9243CBD96694626B95C1 /* SDAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9B9343E8599EE5196BA75E842DCB48B7 /* NSBezierPath+SDRoundedCorners.h in Headers */ = {isa = PBXBuildFile; fileRef = F2817892F9F21CF8BF9F8F35D58385AD /* NSBezierPath+SDRoundedCorners.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 9CE425B89294BE2C13E70A86E75B15CF /* SDDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D6C233C8BB873C737FFE3E1DFBC2A186 /* SDDiskCache.m */; }; - 9D422527A25BAE6A207DEFE11958ABBC /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = E5F4E4918198D7216ABDC0BE4C9BFCE9 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9DDDCFC08B54A61C519DA78F94464E6B /* LookinHierarchyInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 56A3EB69345768D61D52161327AE66C8 /* LookinHierarchyInfo.m */; }; - 9DE398BDF0CD7F38181F2F751AC18CB2 /* Pods-keyBoard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 969A9A842778EFB5D62826500DFF4E11 /* Pods-keyBoard-dummy.m */; }; - 9DF446F8CA5BC4D4098766EC9063012C /* SDWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BF41BBB1EBC1FE4F91BE320D947ED64 /* SDWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9DFFD4780CA32B8E53D9F4FBC8B3F5AC /* LookinAttrIdentifiers.h in Headers */ = {isa = PBXBuildFile; fileRef = 94CD4DB147D9FC14A9FB75335D8AAAF6 /* LookinAttrIdentifiers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9E3C5CB1C97B2ED16218956999BFF7AC /* LookinTuple.m in Sources */ = {isa = PBXBuildFile; fileRef = D03549B19B7C1700178CF12088FCE44C /* LookinTuple.m */; }; - 9E6B00AF2ECE462D4D3C42AFC02F2AD7 /* LookinEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 189A631A2ED6331F0A226846AD73B1E4 /* LookinEventHandler.m */; }; - 9EBA682DA814406E9E5EF300587AF341 /* LookinAutoLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0301A3F865A2919DCD43EE9D0DC363A5 /* LookinAutoLayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9F89DCAA4092F3897E43E89842069A26 /* LKS_AttrModificationPatchHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 477B43B19C3181419CE0D39929320355 /* LKS_AttrModificationPatchHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9FB234EB4D8B5BCC699DB491E204594F /* LKS_GestureTargetActionsSearcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E82EAB687527F885E79D9835727B3F8 /* LKS_GestureTargetActionsSearcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A078A275FFFA48D620074790DA3CA6CE /* MJRefreshStateHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D3A9927A87E21A8976D18DC44FE50014 /* MJRefreshStateHeader.m */; }; - A0E0DC76F51300E7EB1EBA5492DE854D /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D125D803F381B689272DFC8613DDA9A /* UIImageView+AFNetworking.m */; }; - A1560247914C760D9EE5F7A2392CC06C /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DFD54923DA02EA135A1A1E2F56CBDE1 /* UIImage+GIF.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1A1266FD70CEB545FD7602CC33F2F7B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D673941813D9CA4EFFC6C32109054DC5 /* QuartzCore.framework */; }; - A1ACD509069144C27542774A41FE0243 /* UITableView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE0A8B09C0AF83117C6BC9602D5D41F /* UITableView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1DC9EFDF50DF0EAF24D9D7C219AD2C1 /* NSObject+MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 364231170128CA2CD3F9589FE34C2FAE /* NSObject+MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1E44277704AD68E867FD7C955A6632D /* MJRefreshBackGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 948E1E3EDCE53B021791B9169CCC28BD /* MJRefreshBackGifFooter.m */; }; - A324722BA42F21E98F158EA6C133D715 /* LookinServerDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBDC1C9F54DE3E90674A96F19B3458A /* LookinServerDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A3EA39A13714B3103B82F4066A642F53 /* MJExtensionConst.h in Headers */ = {isa = PBXBuildFile; fileRef = C342060C11E55E0DDCC3A84C8C1FBC35 /* MJExtensionConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6728DA26A7C457B78A7A3CCFA9D9A10 /* UILabel+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = ECA6154AE35962F20A086F5A3633C0CC /* UILabel+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6B2B022993BBC55550CFBB0A0C78209 /* LookinConnectionAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = A6EB4E3885146B9E8EBACA05C540E733 /* LookinConnectionAttachment.m */; }; - A6FCF74348D1907891FBDE3F2E331136 /* DZNEmptyDataSet-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = FBE4C2596FA0518DD6CED29332B75B5B /* DZNEmptyDataSet-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A839428F403C52D8AA3466B65E20C27A /* NSButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 1110127348EF0DD2FF03A68A13D86895 /* NSButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A86CC1AFDFDD692DC4EE66F57C0F39E6 /* UIScrollView+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 0236FAD4E41045C8223B36E40BDEDF2C /* UIScrollView+MJRefresh.m */; }; - A8AD2AE9695630E93DE504211EBAFBF1 /* LKS_CustomDisplayItemsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F10AABF341F29547C8D1C780B3F8861 /* LKS_CustomDisplayItemsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A92AB5E65CA85947368E46E6627F1BFB /* UIButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FC8B5F084763484BB92BA1D312960E45 /* UIButton+WebCache.m */; }; - A93BA1C5A4FFEF3ACF371690485A2703 /* NSObject+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 87D20D63606C6DC8B53F345069126C44 /* NSObject+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A9609EEBDD5FD40292925E80ED84D5DF /* LookinServer-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C4BB81E05861A9C00B09F3A39D27B164 /* LookinServer-dummy.m */; }; - A9A49E4A3BE8882F60DF32BAF39DE191 /* SDWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C7AE763582816CA9E57C0D78A7D1A49 /* SDWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A9BEDE2ADF9D1E0D0D1A241806A1A486 /* LKSConfigManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A98ADD6BF259F1E366B570C576632 /* LKSConfigManager.m */; }; - AA1EA8F0F0470F1596B1FFA58ABF3375 /* SDWebImageDownloaderOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C5C306F08907FB9E1301EA07220C6EB /* SDWebImageDownloaderOperation.m */; }; - ABCB80C4813C849FC93D57676820C907 /* SDImageCacheDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CA1F0AA7C906C09D35E1B3B781EB6E0 /* SDImageCacheDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AC14E56ECA7A4980A8E1CA68E800B12C /* SDWebImagePrefetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E83988FA8D9C00FAEEA94EE0633C2C5 /* SDWebImagePrefetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AC710813CB6A1DAEEE45914402F864D2 /* MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = DF383723C6CD6F7B6FCFE6C752DF50AF /* MJProperty.m */; }; - AE69A3B75BEEB9E2C54168BF0C502BC6 /* LKS_RequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C023D8DAEB5C5E7F36F7020DDBFE63 /* LKS_RequestHandler.m */; }; - AE7B02645B8F769CA5F215EE8F7CC5B0 /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6289794567935CA3DC8B5C49AEA74043 /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AF185CDCA462AD6450543676951C82F9 /* LKS_ObjectRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = FF266D90F27C22E50821C68FB0B959D8 /* LKS_ObjectRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AFD1D411A9387DCEC6F0034653E23787 /* DZNEmptyDataSet-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CE89D1B7CAF7D6D1E509FE1267800A /* DZNEmptyDataSet-dummy.m */; }; - AFDC0B8255B2F3CED8E609F8A3BD1CDB /* LKS_AttrGroupsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = EA281F7D07872BD2CB3C821E84CCC544 /* LKS_AttrGroupsMaker.m */; }; - B030B558BE97E0225652EFB8C8FA431F /* AFAutoPurgingImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A565D25677F6FEEAD298666682CDA4B2 /* AFAutoPurgingImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B09F08548ACA8379445F6525011EE219 /* MJRefreshBackStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E24EFDE111F674B782A0DB6E26DA6D2 /* MJRefreshBackStateFooter.m */; }; - B2704AFFC5CC053154839DB44924D255 /* SDImageCoderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = A57C810A36EA495CAFAEDAD83C19A651 /* SDImageCoderHelper.m */; }; - B2B5444DFE63D2835A7561C1D64C9344 /* LKS_CustomAttrModificationHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B6D6A1ACFBDDF049322F2ED0C17DE /* LKS_CustomAttrModificationHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B2BC43DEC8DE2B9234693FE3782AB76C /* LKSConfigManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FD83C0A67C6DD93C76CB6563151D889 /* LKSConfigManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B331CE2D3DEB461E738B886086A365F9 /* SDImageGraphics.h in Headers */ = {isa = PBXBuildFile; fileRef = 89485243816A18F41367AE862167C061 /* SDImageGraphics.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B48A975992E58328254C494F133DE467 /* NSObject+MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 336D23D3AF9B2B8FD356A62D7B4A2A05 /* NSObject+MJProperty.m */; }; - B4F231C5CBAB3D4A184699D0066E0E83 /* SDImageAWebPCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 93FB055BA93E62482AD7154A938F761A /* SDImageAWebPCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B565C08CE947CF591B1D3582272D5E1D /* LKS_CustomAttrSetterManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D74E044AA7CFE331B6C3B53D98B1022 /* LKS_CustomAttrSetterManager.m */; }; - B59E60FBC9665FC1061B88B8E6FD9FAF /* Masonry-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C3AFC445B760812F9E6924ABB9CC15 /* Masonry-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B5AF87C11A465F666473F6191D173905 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = C9154FA9EFF76FE4C993ADDBEB9A5EE4 /* UIView+WebCacheOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B5C521FFB8E09DFE348238E21556842F /* UILabel+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = C23D52958B18447DC5C865BB12951C58 /* UILabel+LookinServer.m */; }; - B66356D4E7E43B3D15324569AA7EBB05 /* SDWebImageDownloaderOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 929BD46DB08827C3FD713BC0E928C239 /* SDWebImageDownloaderOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B680C2604BD8BC9644AE7C67BC46B9BB /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 82B53F06F74B4F928AF69994EDA63D71 /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B741DBE2A466E6211F879EF997D9322D /* SDImageCodersManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 89023F2C23C8826F172885D263CC29D2 /* SDImageCodersManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B79864F972C51037B350802D8CD48024 /* LKS_GestureTargetActionsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F1EE18C1314EB74EEB6B6392E8EFB08 /* LKS_GestureTargetActionsSearcher.m */; }; - B81566F19789EBD9BE2714E2A6059D36 /* LookinDisplayItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E9ED096883562D4C47E188D0E5CB3065 /* LookinDisplayItem.m */; }; - B95C63A039D9D08896421291DEBD3AEB /* SDWebImageCacheKeyFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 960792D55E0D95EDBE31A27683F9FEEF /* SDWebImageCacheKeyFilter.m */; }; - BA904ABA8ED36CC4E5EB2B2004CA1F18 /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = F68B2B4FABAF7DB3BFD45E81B3302EEE /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BACAA91A92F35CD7E7795232A83F21D1 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD65B80E7AA07416BB8F502F3C3A438 /* AFNetworkActivityIndicatorManager.m */; }; - BADA31750A2136D073EDA4461DBE1EEA /* UIButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 615CFF22184D20B3B6107165A49D6FEF /* UIButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BBA61EF31BFDFA6FCA34DC4EBE6E1D9A /* NSString+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 52EF359F996014A062F3A2945F10438A /* NSString+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BBD85F9E0E25710317253841091C391F /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A6057C23DD0D9C9A5559F8F0DC47A97D /* PrivacyInfo.xcprivacy */; }; - BBF5FDA7D647517E2F904FE8E5596D96 /* LKS_AttrGroupsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB9874FA4C241C24657D3A825C00C66 /* LKS_AttrGroupsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC2F9B1D6986FEB23B4FB1288B512538 /* MJRefreshNormalTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E1E4CE0CD5AF60097B9523ED2201F8 /* MJRefreshNormalTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC5458210A973BC7A29D1F45D458A14B /* AFNetworking-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0696D0619ACA95D8E9E7EFDC0CD595D2 /* AFNetworking-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC7A1933CCF40C3C5E2E4A70AD2D0657 /* LookinDisplayItemDetail.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3E4B841669D08E886FD8D7A86C654E /* LookinDisplayItemDetail.m */; }; - BCDC1E1D46DD124B5726A064D2EE66A3 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CBB9E2731CD9B8F896AD9F7398CD3F6 /* UIImage+MultiFormat.m */; }; - BCEFDE57BB0E0B36731C8D39FFA1BE2C /* SDWebImageDownloaderRequestModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = ED216C76AB8BA24D783B6A22E1E01C97 /* SDWebImageDownloaderRequestModifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BD30193C1E3D7B1F17B1B1F3F08BE655 /* UICollectionViewLayout+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D4D5B8A3207BDAE71FAE9F1B443CBF /* UICollectionViewLayout+MJRefresh.m */; }; - BDBE494BAC544843982C3CA96A6C41DD /* SDAnimatedImagePlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A522D0661C437F2B97B12A18A3478A1 /* SDAnimatedImagePlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BF0C3D2782FE1425C2F1F8827132A94B /* MJFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = D9B1F5912311585292CF1DB19B5FF418 /* MJFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BF22D137EF6324675FA50080C5D93C00 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D45408149C7FF7C3CD91B6DDBFB7448 /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BFAC671767912906E90060B0F4BED5FB /* LookinCustomAttrModification.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F154763B55BC95D1F3E0C64970B8D48 /* LookinCustomAttrModification.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C0D7926E41A294ACA98D7B033B283919 /* WKWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E466B1532DEF5F8A8FE002C3882E69E /* WKWebView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C1D9802BE2A6410FFDFB1650FB9BA317 /* LookinDisplayItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 7597119135479FEF90DC7CA9DDBF03A6 /* LookinDisplayItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C1DD8C6A64F948E4C53560C76B995DA4 /* SDAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = DB89640D4CA100127D613D0379809B5A /* SDAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2033A68F13923BF9B3EE19F39FC1411 /* UIColor+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = F81A89C6E769F9B774524A9FE4BA70B5 /* UIColor+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2068AEACC2D9C7F1FFE41AA25B12A68 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 21628153BCD0325102EB502FB5AEDF0F /* MASUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2840BF1950FF7EE2DCD6D55F768A49C /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D64DD7369F8D81EDC16FC3539F46D73 /* UIImage+GIF.m */; }; + 8FF4E9A492CA258F45C0BC51F6F69650 /* JXCategoryTitleImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EADC8693C7692FBBE4CE165F51B28E9 /* JXCategoryTitleImageCell.m */; }; + 8FF7B6477BFA6E6ABA168E1417291D5F /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 70CD4567ACE296214EA982091E2B8F90 /* MASCompositeConstraint.m */; }; + 906DCE66CD5BD236081D468616199BB7 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B82CFD6AD23DAB70352983FFFA8DBBE /* SDWebImageOptionsProcessor.m */; }; + 91AAF555B286FBF53E4F98D092B406BD /* SDWebImageTransitionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = ACD18D412C592E0FB706C10554E5283E /* SDWebImageTransitionInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 91AFF41167C616A131F2E24563B8DDD8 /* JXPagingView-JXPagerView in Resources */ = {isa = PBXBuildFile; fileRef = E03F152E95B6924D2486511337D24503 /* JXPagingView-JXPagerView */; }; + 91BEBD471C408E6C72763AFB6926242B /* JXCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EC4E80691EA4009AB067722DA72E4D5 /* JXCategoryTitleImageView.m */; }; + 91E8B94F8E02ABF5197DF5AE7D0B3934 /* SDWebImageDownloaderDecryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ED4F75E10F9C3D76FF139C89BBB8154 /* SDWebImageDownloaderDecryptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 928371B066E1211CE87089668D5BCB4C /* SDDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A464713D364DCC51BD1C744435EF31A3 /* SDDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 928A1ED0692DF0229F66A87135F93F2A /* LKS_CustomAttrModificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D00729EFDA62359B2F2AA1EF43FADFD9 /* LKS_CustomAttrModificationHandler.m */; }; + 9345137ED10358B60E37D05FB6165759 /* SDFileAttributeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 72CEA2C3193763834CD0E25D8DB88F2D /* SDFileAttributeHelper.m */; }; + 9358FC6C6DA728AEE250D8E7DD236946 /* MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = AB379411892DE9D6AC2BA478DD047B45 /* MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 93E2C24501FAE3C3B886B9879786EF22 /* JXCategoryTitleVerticalZoomCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F3BAE7C9BD506017B4C0D7BBB9100900 /* JXCategoryTitleVerticalZoomCell.m */; }; + 93E8C78EAE0B7613201813966B8E04E2 /* Image+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 8679B55EBC5DC660D8E798D1B986FC22 /* Image+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 940CD731A431894B0EE4E3283E6F352F /* JXCategoryBaseCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 897530E070833B039DC2821D0B63B137 /* JXCategoryBaseCellModel.m */; }; + 955B87902E039163281C4F47C95DB851 /* MJRefreshBackNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = A64A22A853C13E4375B73E01D1D90CB1 /* MJRefreshBackNormalFooter.m */; }; + 96C1D55B3436C158B4CBB4E3D0AE53EE /* UIColor+JXAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = EA759F283932CC196A3C378E0037B993 /* UIColor+JXAdd.m */; }; + 96E97174F4614FFA0649085022CB4AFE /* SDWebImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 61C0CC288A628CFA871D599D497E2A8E /* SDWebImage-dummy.m */; }; + 97235408E59E16C18B6BDA1D29E1CB26 /* SDWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = EFC3A24D1CE615DA957AE8C5AC47E5D7 /* SDWebImageManager.m */; }; + 97385A64CA020489951EF769392C6DCF /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 43901AAA2BB40AE5F534540676833E30 /* UIView+WebCacheOperation.m */; }; + 9887678D7D6BC165694560D92AF2C31A /* LookinConnectionResponseAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = B2B7D0FDFC6ECF60B59728E60160431B /* LookinConnectionResponseAttachment.m */; }; + 98AB6B8EB7FF096BCE87488C5AB3DF1C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 9A7FB1E975A5955C896E6B195C521804 /* MJRefreshBackNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = E45A9679E38D826E316675D8F368F69C /* MJRefreshBackNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9A89C16038149623A1DF06D47E7F953A /* LookinStaticAsyncUpdateTask.m in Sources */ = {isa = PBXBuildFile; fileRef = FCBD8DFA94436F5E62F1AA0F1AD2F2FA /* LookinStaticAsyncUpdateTask.m */; }; + 9B06400877E40C173F5A1C9761F288CB /* UITextView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D8DC297A0249D2FB0109542F14B89AB /* UITextView+LookinServer.m */; }; + 9B1EF09A8A473D92C1258B00791BF5F0 /* UIView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 76AEEFCD2262D6843C63EB46FD6663BB /* UIView+LookinServer.m */; }; + 9B3420DEB8A0CCB9E1241A669AEFCA8E /* SDAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = A1411B1EA7A3C51DB2072BF40B4D5A60 /* SDAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9B9343E8599EE5196BA75E842DCB48B7 /* NSBezierPath+SDRoundedCorners.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A5839D54BEE8A98756D5288A3E5050 /* NSBezierPath+SDRoundedCorners.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9BBBDC6BB6583BCAA75242231B62B530 /* HWPanModalPresentationUpdateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = EF62C88D7041DEBD26117AF61789D8AB /* HWPanModalPresentationUpdateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9C623DECA454522DB641AA29C86F6387 /* LSTTimer-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A3211D6272FC8FFC9717C01969D328F7 /* LSTTimer-dummy.m */; }; + 9C6A760E54D2281BBE39A443C0F78D55 /* LYEmptyViewHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA5C6E28985540EE03804DDC4277D459 /* LYEmptyViewHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9CE425B89294BE2C13E70A86E75B15CF /* SDDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FAA3871C50E5746944D1C3FA3E4736CE /* SDDiskCache.m */; }; + 9D07985CF518269347F3FD5FE6D22609 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + 9D422527A25BAE6A207DEFE11958ABBC /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 060133813AFA51D11B917CB91A3D4950 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D859B99561C389C0F494428F66F1871 /* HWDimmedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9230BE776665C8EB51C8889631B1B31B /* HWDimmedView.m */; }; + 9DDDCFC08B54A61C519DA78F94464E6B /* LookinHierarchyInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F901625B3879AD34FA2A0373208F59 /* LookinHierarchyInfo.m */; }; + 9DF446F8CA5BC4D4098766EC9063012C /* SDWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 949A8C57291DF7D8139F90AD367DB80C /* SDWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9DFFD4780CA32B8E53D9F4FBC8B3F5AC /* LookinAttrIdentifiers.h in Headers */ = {isa = PBXBuildFile; fileRef = F32705CBE56ACF430653A1C459F5351E /* LookinAttrIdentifiers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9E3C5CB1C97B2ED16218956999BFF7AC /* LookinTuple.m in Sources */ = {isa = PBXBuildFile; fileRef = B5157027D16B7E61C1D5AB091D10458E /* LookinTuple.m */; }; + 9E6B00AF2ECE462D4D3C42AFC02F2AD7 /* LookinEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D4CFF1EB3CBDD5217E39DD58BD101359 /* LookinEventHandler.m */; }; + 9E7FD4501C2EF7FBF3379D21E46DB07B /* JXCategoryBaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD544A644986722B86F15A292995457 /* JXCategoryBaseCell.m */; }; + 9EBA682DA814406E9E5EF300587AF341 /* LookinAutoLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 97DE751E0ED3939932D72FB39C5A934A /* LookinAutoLayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F89DCAA4092F3897E43E89842069A26 /* LKS_AttrModificationPatchHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = ADF656282B85E6C974597F555BDE3F21 /* LKS_AttrModificationPatchHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F8A77D8902C98115735987BA80BD5C9 /* UIView+LYExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA8B3EFCD9E73829676C70CE3E88BE0 /* UIView+LYExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9FB234EB4D8B5BCC699DB491E204594F /* LKS_GestureTargetActionsSearcher.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7E9357D1D22FB737AEE89305734112 /* LKS_GestureTargetActionsSearcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A078A275FFFA48D620074790DA3CA6CE /* MJRefreshStateHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 3259CC7D8EE4331CC9B8A86DA09EA5B3 /* MJRefreshStateHeader.m */; }; + A0ADDB3C7DF96DF0E6BC53086778A103 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F5B3C0CF01454E7AC9226E88FDFBAE6 /* UIKit.framework */; }; + A0B7A3B941134AA95A20F5A85165CC72 /* LSTPopView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C98FF255A58DDF6F211BD72458B9C3D0 /* LSTPopView-dummy.m */; }; + A0E0DC76F51300E7EB1EBA5492DE854D /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = B628043D13CE1145E17714D58AB2A687 /* UIImageView+AFNetworking.m */; }; + A1560247914C760D9EE5F7A2392CC06C /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = FB1FCAC52ADC49B2B3A81FFCCD3D56EE /* UIImage+GIF.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A1A1266FD70CEB545FD7602CC33F2F7B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDEE6097B6411333154FEF90A280E3E4 /* QuartzCore.framework */; }; + A1ACD509069144C27542774A41FE0243 /* UITableView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E847BE3D7FA245C62A989A8A4F90542A /* UITableView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A1BFCC1BC5107F5F72BDBDB98E12559C /* JXCategoryViewDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = B4750EDA171CA7EB95AFE62489A712EF /* JXCategoryViewDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A1C02A0C13BE4A139BC38BBE20217FA2 /* JXCategoryView-JXCategoryView in Resources */ = {isa = PBXBuildFile; fileRef = BB4F011171FCB76B1AEBE390F843E930 /* JXCategoryView-JXCategoryView */; }; + A1DC9EFDF50DF0EAF24D9D7C219AD2C1 /* NSObject+MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6F8F3E8953AADD74838D4A882F45A1 /* NSObject+MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A1E44277704AD68E867FD7C955A6632D /* MJRefreshBackGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = FD937703BB1091324CC7A54FB95A5217 /* MJRefreshBackGifFooter.m */; }; + A324722BA42F21E98F158EA6C133D715 /* LookinServerDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = EB54379A72A5DCC64A2C9D42F05AE928 /* LookinServerDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A325C7E5098EB5641EF49D279EA9EF03 /* JXCategoryTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FEE8F6EEF601125225DCB1FEACED91C /* JXCategoryTitleView.m */; }; + A3EA39A13714B3103B82F4066A642F53 /* MJExtensionConst.h in Headers */ = {isa = PBXBuildFile; fileRef = 65CCB6F10EC6B284E771B999975CE0B0 /* MJExtensionConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A59F64C74CB407EBC0385F026FC7234A /* LYEmptyView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F19C07EBC4D3E8EF1AD6C474E7F24FE /* LYEmptyView-dummy.m */; }; + A643679AC9795083558C6D8E33AF6151 /* JXCategoryBaseCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B1B153E1909E0A9DFA6E6097FD363D /* JXCategoryBaseCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6728DA26A7C457B78A7A3CCFA9D9A10 /* UILabel+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = D5909A44E1AC01893309CADDDBC4E50C /* UILabel+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6B2B022993BBC55550CFBB0A0C78209 /* LookinConnectionAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C75F181A3E07F7E7B4B017B48488393 /* LookinConnectionAttachment.m */; }; + A6FCF74348D1907891FBDE3F2E331136 /* DZNEmptyDataSet-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6523AFC889399B6B25C08CCBEEE2F0B6 /* DZNEmptyDataSet-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A760FF1452F08B787F0997D91F4A2C98 /* HWPageSheetPresentingAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = F5EB73BE761C595601603CE39EC8D850 /* HWPageSheetPresentingAnimation.m */; }; + A839428F403C52D8AA3466B65E20C27A /* NSButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CE2B5265F3721FD7EAE15556CCDB1151 /* NSButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A86CC1AFDFDD692DC4EE66F57C0F39E6 /* UIScrollView+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B94BD4B7CE09D63E43117EFC4B15D0D /* UIScrollView+MJRefresh.m */; }; + A8AD2AE9695630E93DE504211EBAFBF1 /* LKS_CustomDisplayItemsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 98935AEC9F6608D5CCBFEF667B9F658A /* LKS_CustomDisplayItemsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A92AB5E65CA85947368E46E6627F1BFB /* UIButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E8B2553B72F322F7DC0ED38BB760DDC6 /* UIButton+WebCache.m */; }; + A93BA1C5A4FFEF3ACF371690485A2703 /* NSObject+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A9477BE731926B610D9B847EF5B7347 /* NSObject+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9609EEBDD5FD40292925E80ED84D5DF /* LookinServer-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D00FB0A2824B0B4E8A345D97C52AA3B /* LookinServer-dummy.m */; }; + A9A49E4A3BE8882F60DF32BAF39DE191 /* SDWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 253C2858A52DB3FD4BE13D65D2B6C2A6 /* SDWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BEDE2ADF9D1E0D0D1A241806A1A486 /* LKSConfigManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 32E665F5EEABCF137D52CE4A3889C9F0 /* LKSConfigManager.m */; }; + AA1EA8F0F0470F1596B1FFA58ABF3375 /* SDWebImageDownloaderOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 35B67A3C0E25A19B996355E03ED4A3CD /* SDWebImageDownloaderOperation.m */; }; + ABCB80C4813C849FC93D57676820C907 /* SDImageCacheDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = B2C2A4CA80B5FE7CB8927FAEE4CAF5F4 /* SDImageCacheDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AC14E56ECA7A4980A8E1CA68E800B12C /* SDWebImagePrefetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 6099FBA2A3EE3D602B49D82E19FA5875 /* SDWebImagePrefetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AC710813CB6A1DAEEE45914402F864D2 /* MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7E307063029FFE21DDCDC0455FA473 /* MJProperty.m */; }; + AD01931D200C49153984E27CBCEFE9D1 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D1046C4A0F4D596969B881D83BCC0FA1 /* FLAnimatedImage.m */; }; + AD395F6BD7F53258A431E9479D07C6AF /* JXCategoryTitleImageCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B28192DA39251C0AC1C30AE245A9A547 /* JXCategoryTitleImageCellModel.m */; }; + AE69A3B75BEEB9E2C54168BF0C502BC6 /* LKS_RequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = DF017A36F518C19E10298190FD8A84C4 /* LKS_RequestHandler.m */; }; + AE7B02645B8F769CA5F215EE8F7CC5B0 /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B8AB8065F8811289957B59E9EBA6B47 /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AF17C7BD3344504E243E234004B4593E /* JXCategoryIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1817B2506E6D89DAFA8176C4A51738C0 /* JXCategoryIndicatorView.m */; }; + AF185CDCA462AD6450543676951C82F9 /* LKS_ObjectRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA6FCFCE1CB3F169BDBDCE936950B5 /* LKS_ObjectRegistry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AFD1D411A9387DCEC6F0034653E23787 /* DZNEmptyDataSet-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B8322800FD1F06BC2FEA3A9EEA874E20 /* DZNEmptyDataSet-dummy.m */; }; + AFDC0B8255B2F3CED8E609F8A3BD1CDB /* LKS_AttrGroupsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 00AE10F23D2B898E9F45884FD9904B2F /* LKS_AttrGroupsMaker.m */; }; + B01F27CEAE1971DEC56A8811FE669EB6 /* UIViewController+Presentation.m in Sources */ = {isa = PBXBuildFile; fileRef = F6CDCEC9BF52B36734600241EB9CC345 /* UIViewController+Presentation.m */; }; + B030B558BE97E0225652EFB8C8FA431F /* AFAutoPurgingImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = C3DBF2503619D6F278D203DBF5D29B4E /* AFAutoPurgingImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B03761E468C3B0F1BFEB2401CF2D5245 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + B09F08548ACA8379445F6525011EE219 /* MJRefreshBackStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = E7485AA213719656370219B55A0AAE3C /* MJRefreshBackStateFooter.m */; }; + B0F512045830FAB66AE7526E35501800 /* JXCategoryImageCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = D51E4D4230E01D5F3D9340BDF320C3E1 /* JXCategoryImageCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2704AFFC5CC053154839DB44924D255 /* SDImageCoderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FEE19DBCD45615CC389DD7223D3C447A /* SDImageCoderHelper.m */; }; + B2B5444DFE63D2835A7561C1D64C9344 /* LKS_CustomAttrModificationHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EFF4D34DD5391DCE7D206B11306BCE5 /* LKS_CustomAttrModificationHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2BC43DEC8DE2B9234693FE3782AB76C /* LKSConfigManager.h in Headers */ = {isa = PBXBuildFile; fileRef = A4CFB2BE169777F50B29077639FCFEC4 /* LKSConfigManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2E706AF15CBC9BBDA6B180AA008345E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0FFF1AB10AC30C72DB3B2F106B23E5B3 /* PrivacyInfo.xcprivacy */; }; + B331CE2D3DEB461E738B886086A365F9 /* SDImageGraphics.h in Headers */ = {isa = PBXBuildFile; fileRef = 5EA970CCF2164DC59ECEE9DE06B1BCBA /* SDImageGraphics.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B48A975992E58328254C494F133DE467 /* NSObject+MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = D44C8E719DA4251716FDA4B2519C022D /* NSObject+MJProperty.m */; }; + B4F231C5CBAB3D4A184699D0066E0E83 /* SDImageAWebPCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = BF3C6AEB909F4472F8D8E4E21B25B716 /* SDImageAWebPCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B565C08CE947CF591B1D3582272D5E1D /* LKS_CustomAttrSetterManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F363F53534ED7FE5A4BB0A1E1863D5E7 /* LKS_CustomAttrSetterManager.m */; }; + B59E60FBC9665FC1061B88B8E6FD9FAF /* Masonry-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 128CF11122A7C2009F733361122E39A1 /* Masonry-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B5AF87C11A465F666473F6191D173905 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6ABA6691731EEA533F56170FB03C5C /* UIView+WebCacheOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B5C521FFB8E09DFE348238E21556842F /* UILabel+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BD526972490CFC41EE7106FF8E272CC /* UILabel+LookinServer.m */; }; + B66356D4E7E43B3D15324569AA7EBB05 /* SDWebImageDownloaderOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 304D443FD07AF14BA7F1628D80971669 /* SDWebImageDownloaderOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B680C2604BD8BC9644AE7C67BC46B9BB /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A98EB9CE425ECC87D9747E4EAC3DB0C /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B741DBE2A466E6211F879EF997D9322D /* SDImageCodersManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BC7EB117F009B160822B3FFCCC63F2A /* SDImageCodersManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B79864F972C51037B350802D8CD48024 /* LKS_GestureTargetActionsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C81473AB6162F68681F317D8EC207A4C /* LKS_GestureTargetActionsSearcher.m */; }; + B81566F19789EBD9BE2714E2A6059D36 /* LookinDisplayItem.m in Sources */ = {isa = PBXBuildFile; fileRef = AE19AE8E2478EF2E39C49272A1998EFE /* LookinDisplayItem.m */; }; + B8CA1F338C44C633916650FD85DA5A30 /* HWPanModalPresentationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 87888E540A812F012C68F804E8F5AE7B /* HWPanModalPresentationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B948DCB652CEF1509FBE410D85844A53 /* JXCategoryView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3EF9D4544217A0B4E13DA6B530C974 /* JXCategoryView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B95C63A039D9D08896421291DEBD3AEB /* SDWebImageCacheKeyFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = C909F8904D301FB96965DD62CE4E2CA7 /* SDWebImageCacheKeyFilter.m */; }; + B987864019E987FE32AB26A9CF2C8E12 /* UIViewController+PanModalDefault.h in Headers */ = {isa = PBXBuildFile; fileRef = E8C71212CAB0DCBF4059538A93053A4A /* UIViewController+PanModalDefault.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BA904ABA8ED36CC4E5EB2B2004CA1F18 /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = AE4CC2528765A45B472AD5B813D01119 /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BACAA91A92F35CD7E7795232A83F21D1 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6516BB90D0CA47F75712B356350A9FC1 /* AFNetworkActivityIndicatorManager.m */; }; + BADA31750A2136D073EDA4461DBE1EEA /* UIButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 731A2E2A09E554B786F7BD8D9285D1CC /* UIButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BBA61EF31BFDFA6FCA34DC4EBE6E1D9A /* NSString+Lookin.h in Headers */ = {isa = PBXBuildFile; fileRef = 92670C1E3C13D6C6157E7AFB4347DB17 /* NSString+Lookin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BBF5FDA7D647517E2F904FE8E5596D96 /* LKS_AttrGroupsMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 313050E8524ED89E2B2CF8F5C1CC7633 /* LKS_AttrGroupsMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BC2F9B1D6986FEB23B4FB1288B512538 /* MJRefreshNormalTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = 83340409B38BF2A20F089A4B919FC02F /* MJRefreshNormalTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BC5458210A973BC7A29D1F45D458A14B /* AFNetworking-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E8510A179E756198B5FC915A27736E /* AFNetworking-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BC7A1933CCF40C3C5E2E4A70AD2D0657 /* LookinDisplayItemDetail.m in Sources */ = {isa = PBXBuildFile; fileRef = 15D6A20A536D39FB4F4DE78CEC3512CE /* LookinDisplayItemDetail.m */; }; + BCDC1E1D46DD124B5726A064D2EE66A3 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 373258A2F6DFCE8ADD1C1D42DE5EF5D3 /* UIImage+MultiFormat.m */; }; + BCEEAFC24178DE5AABACC74245CE1739 /* JXCategoryIndicatorDotLineView.h in Headers */ = {isa = PBXBuildFile; fileRef = C398AC4FA166ECBDBFA37681D3C108CC /* JXCategoryIndicatorDotLineView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BCEFDE57BB0E0B36731C8D39FFA1BE2C /* SDWebImageDownloaderRequestModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = B2CE10A014B3B7826BFF751346CE7495 /* SDWebImageDownloaderRequestModifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BD2F6B06ADB5136DA881D1B918367125 /* UIViewController+PanModalPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A1E2D85798C902C2A1E1B714EF78587 /* UIViewController+PanModalPresenter.m */; }; + BD30193C1E3D7B1F17B1B1F3F08BE655 /* UICollectionViewLayout+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = BE1A1849BD6BB4B796D54DCBEF79FB7A /* UICollectionViewLayout+MJRefresh.m */; }; + BD7E02AB6057AD5A6AC513C34D508135 /* JXCategoryIndicatorBackgroundView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5EE479D553AE99C7C893E8B21299B3AC /* JXCategoryIndicatorBackgroundView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BDBE494BAC544843982C3CA96A6C41DD /* SDAnimatedImagePlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C1E503B34448DC968FB5BDFADFAE70F /* SDAnimatedImagePlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BE4F0DF600FBF07E812D262B293CF76C /* UIView+LSTPV.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B1E80842E43848FFB0F162AFF96E774 /* UIView+LSTPV.m */; }; + BE7F6E08A9BDA2EF6FA625EB5CD685EC /* JXCategoryCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = E81450568229FA708143E74A7A580F89 /* JXCategoryCollectionView.m */; }; + BF0C3D2782FE1425C2F1F8827132A94B /* MJFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 99650956C6DC18187951AE72D50E44A2 /* MJFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BF22D137EF6324675FA50080C5D93C00 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 05FF40C91ADEB302CBF4314535A1A6E7 /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BFAC671767912906E90060B0F4BED5FB /* LookinCustomAttrModification.h in Headers */ = {isa = PBXBuildFile; fileRef = F5B865CFCA1FF1600CB766B9BC34B8D9 /* LookinCustomAttrModification.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BFD8EC99CD8DA66E3C6C0B3EE8CC4859 /* JXCategoryNumberCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 292BBC0398F56F3818017A7314541B45 /* JXCategoryNumberCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C04D578067F77AAB6717D32712CC39A2 /* HWPanModal-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EFF4EEBD779C7DB39B6B044205385FA /* HWPanModal-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C07F8A334C739FD38D9CB5C5239D683F /* JXCategoryTitleCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E01ADBA325921AF74B0FBD58F7BB5032 /* JXCategoryTitleCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C0D7926E41A294ACA98D7B033B283919 /* WKWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = B052BF123A39C5CF4B531584A2A83BED /* WKWebView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C16483526F6C6287240A75EDCB7E2F2F /* FLAnimatedImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CCD2F6CD21BCE8D4DC6CE0FB91B91CB /* FLAnimatedImage-dummy.m */; }; + C1D9802BE2A6410FFDFB1650FB9BA317 /* LookinDisplayItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE8AE5699FC4ACD4283D4626ACDF742 /* LookinDisplayItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C1DD8C6A64F948E4C53560C76B995DA4 /* SDAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 37977014CE5B8A9E93F1EC56C3AC6D52 /* SDAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2033A68F13923BF9B3EE19F39FC1411 /* UIColor+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = A810CCF3953514350B557ABBEEBE5FF6 /* UIColor+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2068AEACC2D9C7F1FFE41AA25B12A68 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BFABBA210FF6BEF09CABCCBE8AE590F /* MASUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C22BFD04EAB76981E7F112D57A1F5E79 /* JXCategoryNumberCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B51D3C0C65114DF44F6DDB3ED9C4E4E /* JXCategoryNumberCell.m */; }; + C2840BF1950FF7EE2DCD6D55F768A49C /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2AEB4C3E4F6147F107DF9376FA7264 /* UIImage+GIF.m */; }; C2F8C43CFD4C890405F217DA7E00C839 /* Pods-CustomKeyboard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DDD0462C32F55EF5E9CB1056459809F /* Pods-CustomKeyboard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2FE60A10C792613E45031AE6E851ECB /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = BBC10C6127599FC7CD74CA6E613C44DB /* MASViewConstraint.m */; }; - C4CC01ED368863C6E3220988FBC6CEFB /* LKS_CustomAttrSetterManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F98B3E6FF4A7A436AEB00C4FE95820A2 /* LKS_CustomAttrSetterManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C60DB44F719853DE3B7157960DAF9270 /* MJRefreshComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = EF2661A0DF69E1828AB8D83F666F4FBC /* MJRefreshComponent.m */; }; - C6A100159974349FEAAC99B82BE0F872 /* SDImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 97003D4D841CDDF5214C70A6CC7425DF /* SDImageLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C6FEC1088121FEA7DDC3384B7ECF3B44 /* LKS_Helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 567AA7AB9514E985494C554A1802C03B /* LKS_Helper.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C71935C30C1AEDF32B96670BD8FA64CE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1DF8BF780A4AD9606856AB857CA1D86 /* UIKit.framework */; }; - C857B8D2D0BAA5A8A764F9E1C4B85807 /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 904AEE3BB6B326E7E1CFD8B0A34306AB /* ViewController+MASAdditions.m */; }; - C8771885BEA9EA0BD2E2C474587325E2 /* LKS_ExportManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A306B5D1B1BD0232E2121BA1E0EA27F9 /* LKS_ExportManager.m */; }; - C8EC35DFB0945DBE2F2FF9ECFE6D9711 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 96E64D1052C3FD60EB6BBB8A95EE1349 /* NSLayoutConstraint+MASDebugAdditions.m */; }; - C93E972E75F84674690300123984EC43 /* SDAssociatedObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D7966DEA2CA0101B9FC2C01A1A2909B /* SDAssociatedObject.m */; }; - C992A335399F942237E754EE65C40CA5 /* LookinObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E70A8D54BBD1266CC7CAFB4BD5CE317B /* LookinObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C993A4D0CFA51E567F458CA65C1298AA /* MBProgressHUD-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D219431FF998A6D0FA270965A4CDE56D /* MBProgressHUD-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C9B63C6ED2ED691EA83D3EE65939444B /* Lookin_PTProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1550F0B5EA5360BFA35606256AB6EF51 /* Lookin_PTProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C9E19D164C26414115CC969ED9A303C1 /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AE5F5B6D6DAD0B45FC2D30EE6FBEE81 /* MASLayoutConstraint.m */; }; - C9E8C9372C2DA29D302B058BE3AE9877 /* CALayer+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 26476CAEC54A4CE04264494F816DFD2C /* CALayer+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CA1E0DCDF679EA2DE2ED0915426E1D04 /* SDWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD58163B84A00F8FD88E21AE9F6DF12 /* SDWeakProxy.m */; }; - CA56274BE7CBB3E759E0364785DF9799 /* Lookin_PTChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 341D877992B274AC6FD93AB03542E561 /* Lookin_PTChannel.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CE86196C00DC1D658B6CB7D47A0233AA /* LKS_ConnectionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 613D22FE29FDFD98F1BA3415B19FB040 /* LKS_ConnectionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CFF8D1A5E4C2097EF05E1021FE112886 /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 54354678DA42B275327F1EABDD57F9BD /* SDWebImageIndicator.m */; }; - D06BB547D59D183FD1DDD84DEBAC9EE8 /* SDWebImageCacheSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 42189E436FCC0F9F0BAA536F3BF84910 /* SDWebImageCacheSerializer.m */; }; - D091F05269EE0566B665B00C7D912F8E /* Lookin_PTChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93AFD572FFECC065D5DF0E8764C35B66 /* Lookin_PTChannel.m */; }; - D1230E19DD1507E6370B80DF6653AC2A /* NSArray+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 49A24CBDEFCE6B22E2D355C6D04AC9B4 /* NSArray+Lookin.m */; }; - D2AF9A7FD73B95960FDA4FD06C4BED08 /* NSObject+MJKeyValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5210B0534D834B2EF86FDFCE90B73F2D /* NSObject+MJKeyValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2CD8848F856EC9942A76610AAE66F0A /* SDImageIOCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = B00A278D1C0A05DD872C02CEFE3B53AC /* SDImageIOCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D559CC4D0695CEE05F3B4C1C06475044 /* UIImageView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CAEA0BC49D62C0D220FA986A5391EEC /* UIImageView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D5C046C46961BE465293625D6B870620 /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A4CDCDF549B87D4E437ED8A4615D91 /* AFNetworking-dummy.m */; }; - D62A672EEB252581BD972DDA862BE1DD /* SDWebImage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 037A3F50C10BD2A3B9D2C3743608A737 /* SDWebImage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D662C83ECE8BEDA5FFB52F3575CA3E1A /* SDImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 34206822AA40B77DF3E1B3B5D326158F /* SDImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D663837F4347AF58660EE6F7FD426ECE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - D788BA4B9E8186271BA75CA52B30502C /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 59AE847A100A8834951E42690C982455 /* View+MASAdditions.m */; }; - D7B3E8948DB04BD8FB6748419DA03EA9 /* SDAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 241065D9A03A30BC61C328A01C40E560 /* SDAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D89C7D5455E3E8E2D7EC6B880253BD9B /* LookinIvarTrace.m in Sources */ = {isa = PBXBuildFile; fileRef = 872090FEDB94946E441D4F936A1357C0 /* LookinIvarTrace.m */; }; - D90607B4E56247B19B14462E487BA86E /* MJRefreshNormalTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = E25013592494E49EB3F378AA4A68FB7A /* MJRefreshNormalTrailer.m */; }; - D90DED0F5638B1C44F4B6C62D600D240 /* MJRefreshFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 120B89B8756AC54266917A34CDCADBB2 /* MJRefreshFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D90DF1376DF5E2EA644313BCD2E03058 /* MJRefresh.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 352F463EFB3454F98E285A844376EC28 /* MJRefresh.bundle */; }; - D968461E31E8FF3FF6BA1DC621B0433B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1DF8BF780A4AD9606856AB857CA1D86 /* UIKit.framework */; }; - DBA9500CBBA5FF6FCBBA115AE4D12152 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A62C9B59CFA9D74EE95F526BE485EC8 /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DBD9152526A180771BF7D7CD209B957E /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F61B84FD6B8249C85FCBF56257E34C6 /* AFSecurityPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DD7F63D4E4640C7386877BB787740272 /* LookinServer-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B1A8FD671105727BDE389DF6E59E7187 /* LookinServer-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DDA16FB9C21AD941442357DAE6939530 /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = E727648E6DB0C84B6B5C85D16CF9D6AC /* UIKit+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DE5A78F116018E2AC54714238276574D /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E423D2DE3EB3895273EDB5BC21FDE9 /* UIActivityIndicatorView+AFNetworking.m */; }; - DE98ECCCA7106A4EA575EF34830D41FF /* MJRefresh-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D47A5312A106ED050240FD5A4E84CE4 /* MJRefresh-dummy.m */; }; - DEA09692CF813A23899CD4949A9B6801 /* SDAnimatedImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 33E548EC20D55A1581EF030D8F590720 /* SDAnimatedImageRep.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DED9ADFC8CC65243FC54E008A853742C /* MJPropertyKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F39E9FDE611BCC2A514A77F1EB63E8B /* MJPropertyKey.m */; }; - DF2B15402CE105F5A8CE48BBDCFFD5DD /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = F57A932DBB8EE96EEDB42899B11A3E40 /* MASConstraint.m */; }; - DF525E5405FAD3B98B0C2D966EB2DD95 /* UIViewController+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AF7E49BBE304E0327E319036BE5671B /* UIViewController+LookinServer.m */; }; - E0B48B9D5D45AF3500FC718459D66E6C /* LookinDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E6089EEBB83334AD3EFA96BE408F86D /* LookinDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E0BCF21E9FA59F638C13ECCECC4D9690 /* SDMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 59D0E9B54F4868B1B1BDE17140B78250 /* SDMemoryCache.m */; }; - E1BF615DD0422B06C97542F03C879D41 /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 743C4A42055B7373FB20F646193D0919 /* AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E1DE69F6BB6235A6EDB6C99A184BEDB4 /* UIScrollView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = F61E20013C3B1EBDF05023CF2525C38C /* UIScrollView+MJExtension.m */; }; - E3FC6BEE41652C0500F57E0CB83B347F /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 35182E600B80DDDFBA4A4B90FAA71EFD /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E4F1B478580D6D7328BC29607BDE46F6 /* UIImage+ExtendedCacheData.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB52034FF7403843EE79E4975D6D70 /* UIImage+ExtendedCacheData.m */; }; - E50613C67DD02AF6EA825DA0B31EFFAD /* SDImageGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6C24AA261BA4AFA4E02DA1EFA44065 /* SDImageGraphics.m */; }; - E55B3151D86660E28CEABC3CDE6B1508 /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D93B5DFF8656FC20174F5CDCB325540 /* UIButton+AFNetworking.m */; }; - E5B057BC87284367918B2DB9CA084B4E /* MJRefreshAutoGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E49D88BA109001AA94CB4B1CBCC6353 /* MJRefreshAutoGifFooter.m */; }; - E76969F9B01139118427505B18F9CD21 /* SDImageHEICCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 67A65AF14731E6A6CF631892AB163C2D /* SDImageHEICCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E7FEAB9F421F7EBAF021F792D8E9C4D6 /* LookinCustomDisplayItemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C5B4FB13625B33C4ABB17DDEF05C782 /* LookinCustomDisplayItemInfo.m */; }; - E82964ED7092CDCDAD08BC596A57B43A /* UIImage+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 241D729CBB4E30C3E09474F7F34CB9FA /* UIImage+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8AB529B9E0B4C23921344F6C4ABFEA4 /* SDImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F12865FFC70E396EDFB92C4A7F13D7 /* SDImageCoder.m */; }; - E930A5612DC6D120BE040AD17C6D1BCD /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 07F0D69559BBD9895C4D0BD66F33AC55 /* MASViewAttribute.m */; }; - EA82B6D97C9C5D0558047AF552D63203 /* SDWebImageDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 01E24F0E64AEC0E54DBDB063CE89097A /* SDWebImageDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EABCB60A26B06BF576E50BBD2F89A385 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */; }; - EB3DF628891F7D6AB114718AF760CB2A /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 319E8C485C3E5DB2BFBF15AA61E5ABA9 /* UIImageView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EB646114ABEA7A4D6C2A724404778670 /* LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A10CFE082F8338A031688B47CDED17 /* LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EBC9AA5D4A55F79BB5CBF6CC92719FAF /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B9232C2E4F4A27C4FBD3F8EA3E351AF5 /* PrivacyInfo.xcprivacy */; }; - EC8E84A8FFADDCA562A8608D141D9027 /* MJRefreshAutoGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = C79FFC2722DEE9A1F54D8DBDD3CB2A2C /* MJRefreshAutoGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EC9B34262AED632D7EFB49804337648E /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = B069597AD0812CBF01ACDD3CE4B6F843 /* Masonry.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ECE64B732F9FA7C402DDEEC58DCB9D98 /* SDImageAPNGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = F6908A3C9CC8A527E2C3CB20A2C51560 /* SDImageAPNGCoder.m */; }; - ED8991A8AE7C04362C2BED3875DC1656 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 05D83C1EC3DD8D27EE1C07CFDE18D72E /* AFURLResponseSerialization.m */; }; - ED8F64FF98CFAE0B12CF60A1B0E6BAF8 /* SDCallbackQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 19F3928D9276C0125AA1EBDB31A470E1 /* SDCallbackQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE6E8FE636D2C02E3D2FC1E8555B4612 /* MJRefreshNormalHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 5932D997195DFCB258D366D038A56978 /* MJRefreshNormalHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EED016DE8173CD38CC01D88CD2628984 /* NSString+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = AF4D3A8A4AF29616DFF2E40A94DA00AE /* NSString+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EF6A6C725598F572A70C5FCEE328C184 /* SDImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = BD3AE781F5CE5DD3063848F6F78DD40B /* SDImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1D845E22D5B8FC6AFC3C2E41DA1B6DF /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 62E02B7B42A91CD6887912774FAE6528 /* AFNetworkReachabilityManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F2AD91050B1FE3C8BC78567F1FDE3ED5 /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D6C729EB2C2561DF46F90B1EE029B4 /* AFURLResponseSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F2C9F9038FBEFD951516694AE873A2B9 /* MBProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D069519EE909290F7C452231691CA88 /* MBProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F3263D294D688533EB974E37C61F1E24 /* MJExtensionConst.m in Sources */ = {isa = PBXBuildFile; fileRef = BCE109BED042388EE5FB3949ADA18281 /* MJExtensionConst.m */; }; - F3AECEF6D3BB919B3E7392942E1BC58B /* MJRefreshBackFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = AB22EEA7E251269666B0DD8D3FCD0892 /* MJRefreshBackFooter.m */; }; - F3F4A6309BD95DFAA4DCC60A4E07C515 /* UITableView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7584B9C7664B986D7C6582FD3280C473 /* UITableView+LookinServer.m */; }; - F49CB22863CCFEC7817D259F27F91C57 /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = B6D81E3EC47029DCA820DF6AA652C734 /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F53BE4449AE5896F76325E4DCB6D0B13 /* SDImageCachesManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 99F9CF6DCFC4C32DE7AC87FA68FD05DA /* SDImageCachesManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F60F90EAF35CFF40DF1C33557965787D /* MJRefreshStateTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDB2F652BC38BC05396DCC9F34040CD /* MJRefreshStateTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F62B0711DA506CCB3DF79F65134566C7 /* Lookin_PTPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D703CF356A8E2B3B3665722366223A5 /* Lookin_PTPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F68889CD481716EE5D6B75EBD8FD53A6 /* SDImageCoderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = FF5518BA3449B11DB02406C2A9A9AA75 /* SDImageCoderHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F6A0D6EA1B5DC3FE04DC4A1B0A914121 /* UIView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 12119FD9C09B77E5C8A003238C89E88A /* UIView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F6A2DEEA8E8B92D365AFDDBD5E8C1218 /* NSObject+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = BA48F14A970C2FE9AE9B9A3F4EF27D84 /* NSObject+Lookin.m */; }; - F6D1C960368EB1E067ABD0BFF707FC56 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D891833337A0E2AFA0DBB31899C747F /* MASConstraintMaker.m */; }; - F7623E7C314AA5010D8D0BD6ED4AAAD4 /* AFImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = A67D546CB537E231FE83AA071A555BB7 /* AFImageDownloader.m */; }; - F8616FAFEE1124368CB96473CE20CDB4 /* LookinAttrIdentifiers.m in Sources */ = {isa = PBXBuildFile; fileRef = 75E99E8BA24E841D85C9E942E3654D62 /* LookinAttrIdentifiers.m */; }; - F8F1B1196CAA5114BA9A95AA7E6D6AEB /* UIBlurEffect+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = D950E8533947A1D8B1CABC80463AFF52 /* UIBlurEffect+LookinServer.m */; }; - F9789D86D3279D71B398B550F27C3EFF /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34294BB6B51E74AFE5298D85D957E2F6 /* AFSecurityPolicy.m */; }; - FA3021DED76B9B182CC9195A60EB1209 /* NSBezierPath+SDRoundedCorners.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BAD239072CC7DFB1FD50FE4374085D1 /* NSBezierPath+SDRoundedCorners.m */; }; - FA6DA93357E2E9E9AADDFB3E39DEB6C2 /* NSObject+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = E66FFAE76E02A3342AF857261F059F70 /* NSObject+LookinServer.m */; }; - FCDEC6A53CF5517E1AF5B331FD65F6D9 /* SDImageCacheConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 4770EEEC71445F1C55A5C71E32517009 /* SDImageCacheConfig.m */; }; - FCEE5BD645E95FF55468C4AB6D17CFDA /* UIImageView+HighlightedWebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F0BE45EAE3F2E6B703C484173BD9CDAD /* UIImageView+HighlightedWebCache.m */; }; - FDACBA49610EA6F39CABB7FE44B137D1 /* AFImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C9902E0E2D0A78C2A349E20322FC80 /* AFImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FE07C069C2E3543002CEB5D751ABA9AC /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D18C326A9F4C285AD294832344E63FF /* AFNetworkReachabilityManager.m */; }; - FEA8BA4F82CCBD1D28DCC7EF39FB4096 /* SDImageCacheDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = C839ECCA7B6B8EF19AFC3658241117C8 /* SDImageCacheDefine.m */; }; - FEE883575278D5BE8F185437AB5DB3BB /* MJRefreshGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F0234E8EBBDCA694F549267CF8444C2 /* MJRefreshGifHeader.m */; }; - FFC6D50089FA32FD7AAF25747E56EA60 /* LKS_CustomAttrGroupsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 667106A3B29FC2624F444E79272C8235 /* LKS_CustomAttrGroupsMaker.m */; }; + C2FE60A10C792613E45031AE6E851ECB /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE35A6903D3E473ACA2703E7286A28E /* MASViewConstraint.m */; }; + C4CC01ED368863C6E3220988FBC6CEFB /* LKS_CustomAttrSetterManager.h in Headers */ = {isa = PBXBuildFile; fileRef = A0925E96742E33F78D548F10A7C0475D /* LKS_CustomAttrSetterManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C60DB44F719853DE3B7157960DAF9270 /* MJRefreshComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C9E32D40F89FB7470530B4F8AAB6162 /* MJRefreshComponent.m */; }; + C6A100159974349FEAAC99B82BE0F872 /* SDImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = C8ED101794ADA1876F4FFCBD1F79D622 /* SDImageLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C6FEC1088121FEA7DDC3384B7ECF3B44 /* LKS_Helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CA454A209E71894BC9366B10B95D086 /* LKS_Helper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C71935C30C1AEDF32B96670BD8FA64CE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F5B3C0CF01454E7AC9226E88FDFBAE6 /* UIKit.framework */; }; + C74589E03918328E4D27EFCBF6C4A0B8 /* JXCategoryBaseCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D7A76984F1E3BB7440B31DF8D5447F0 /* JXCategoryBaseCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C857B8D2D0BAA5A8A764F9E1C4B85807 /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DB1B5D6DA097974C176F91F3853055EC /* ViewController+MASAdditions.m */; }; + C8685678D1B020F87365D022216FFE29 /* JXCategoryIndicatorImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = EF2876A2D62001FE741FE92492A10CFF /* JXCategoryIndicatorImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C8771885BEA9EA0BD2E2C474587325E2 /* LKS_ExportManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 207535A186296DE018201ED1B7DDD076 /* LKS_ExportManager.m */; }; + C8EC35DFB0945DBE2F2FF9ECFE6D9711 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D8B8A062E76BF87D54F581F6428D4E28 /* NSLayoutConstraint+MASDebugAdditions.m */; }; + C922BFFF717515E5878910DF4078CE1E /* JXCategoryIndicatorDotLineView.m in Sources */ = {isa = PBXBuildFile; fileRef = FD7C0DEE68BC5E8256170F72FCC61847 /* JXCategoryIndicatorDotLineView.m */; }; + C93E972E75F84674690300123984EC43 /* SDAssociatedObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 321334B98147E6E64FCE056E3717FEE0 /* SDAssociatedObject.m */; }; + C992A335399F942237E754EE65C40CA5 /* LookinObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 371A20C759D3E78183B0BC7EA626FA2D /* LookinObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C993A4D0CFA51E567F458CA65C1298AA /* MBProgressHUD-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A8AF8342462E3EDE8E3D40F840DFA00C /* MBProgressHUD-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C9A72F0A93329C42B77395B0F6CEA26C /* HWPanModalPresentable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A10B1AFB4B6959F4A11AB1B1BC4A437 /* HWPanModalPresentable.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C9B63C6ED2ED691EA83D3EE65939444B /* Lookin_PTProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E05D85B85A84A7D628539AD042EC841 /* Lookin_PTProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C9E19D164C26414115CC969ED9A303C1 /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DEDD90DB6CF7DD05B6B753765E65AAD /* MASLayoutConstraint.m */; }; + C9E8C9372C2DA29D302B058BE3AE9877 /* CALayer+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77DEC7B6CE458C6AAB89A25A3E05BA4B /* CALayer+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA1E0DCDF679EA2DE2ED0915426E1D04 /* SDWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 98901829A364C7B4F13375AEB6AA0FBE /* SDWeakProxy.m */; }; + CA543D086B4C8E314FB43F0B78147FE9 /* LSTTimer-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 88F65BAED091224357C1ABFEA1C484FA /* LSTTimer-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA56274BE7CBB3E759E0364785DF9799 /* Lookin_PTChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C3DB4C7661755654D296A929BE2CE7 /* Lookin_PTChannel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA9AFE3460622CC65F75A2DDE845F6E9 /* JXPagerSmoothView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B167FA26CB7B8DC98E1A68B1B44BA8A /* JXPagerSmoothView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CE2AF36EBB17CDA2652CBADD4A7ABF82 /* JXCategoryImageCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 570A4EA50A989D93BDAC90837E4F3637 /* JXCategoryImageCellModel.m */; }; + CE86196C00DC1D658B6CB7D47A0233AA /* LKS_ConnectionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 769C3408F11A51A90B589A6DBB334C55 /* LKS_ConnectionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEC9EF043F69710AC29940EB4E1E2B19 /* RTLManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 22A80188C121A76950A88A3321260BFD /* RTLManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CF7005F2C42AC2E2DD6D437D52C7048B /* HWPresentingVCAnimatedTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F1989DBFF7A3D94A0CF758DF35B3F6 /* HWPresentingVCAnimatedTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CFF8D1A5E4C2097EF05E1021FE112886 /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = A56060BC793E00F370FD0DF3B4157376 /* SDWebImageIndicator.m */; }; + D06BB547D59D183FD1DDD84DEBAC9EE8 /* SDWebImageCacheSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6771046C7CF97C82B7D303F2AFD49E /* SDWebImageCacheSerializer.m */; }; + D08901EA319887BE6D694F8333BE8D1F /* JXCategoryIndicatorTriangleView.m in Sources */ = {isa = PBXBuildFile; fileRef = C31C4A7197700436AFBAB631C088A6AE /* JXCategoryIndicatorTriangleView.m */; }; + D091F05269EE0566B665B00C7D912F8E /* Lookin_PTChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 862D8BDF52FBE8FCF3A562F5A62C802E /* Lookin_PTChannel.m */; }; + D0E37358C3DCF2A8A572C4F38BB0569B /* JXCategoryListContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = C63CFE9D73B31D9EBEF51E32F9AC7286 /* JXCategoryListContainerView.m */; }; + D121163078CA9BBE54A83BD73EF784CF /* LSTPopViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D7595F0F8BE4F40C64D68F0D491C6C6 /* LSTPopViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D1230E19DD1507E6370B80DF6653AC2A /* NSArray+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AAF4EE016C54A7F264F9B8FBB0853C8 /* NSArray+Lookin.m */; }; + D2AF9A7FD73B95960FDA4FD06C4BED08 /* NSObject+MJKeyValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B41D364B66F85CF33EB15116929CF48 /* NSObject+MJKeyValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D2CD8848F856EC9942A76610AAE66F0A /* SDImageIOCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = E4718E4C19C181FBAEBD080580F8C026 /* SDImageIOCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D31558927DE3F62D1BB1FC416E6F237D /* JXCategoryDotCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AF0216318F4C1EBD4207012E5E70EB1 /* JXCategoryDotCellModel.m */; }; + D3615499AFE4D2A8EC2E773F4D8A82B2 /* KeyValueObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 05D708E8F9065868500ABC98E789B739 /* KeyValueObserver.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D380F9C945002DBF2E7D64983ABDC890 /* JXPagerListContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 57460121EED43E41D624C46A92FE9E08 /* JXPagerListContainerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D559CC4D0695CEE05F3B4C1C06475044 /* UIImageView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 310DC522C0637DDB20D8D38412CB4153 /* UIImageView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D5C046C46961BE465293625D6B870620 /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 18106F0763EC023048DB3F77457B9596 /* AFNetworking-dummy.m */; }; + D62A672EEB252581BD972DDA862BE1DD /* SDWebImage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = FB84DF0F5016EBAF04FE5FE9F22081C0 /* SDWebImage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D662C83ECE8BEDA5FFB52F3575CA3E1A /* SDImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DEEA81C89F22AF300ABFA4E5550B7B06 /* SDImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D663837F4347AF58660EE6F7FD426ECE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + D737D93725B0E072027AB6DA9C4DDDEC /* HWPanModalAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = CF7B4B9CB0EF762A12884D6FE337E068 /* HWPanModalAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D788BA4B9E8186271BA75CA52B30502C /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1069EA3A85D1A1A87FE087B0FE402436 /* View+MASAdditions.m */; }; + D7B3E8948DB04BD8FB6748419DA03EA9 /* SDAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B705DD8FCD54B3AFD61B70C82828ACE4 /* SDAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D89C7D5455E3E8E2D7EC6B880253BD9B /* LookinIvarTrace.m in Sources */ = {isa = PBXBuildFile; fileRef = 6148399DD529311A930CEF2A2AC2FBD4 /* LookinIvarTrace.m */; }; + D90607B4E56247B19B14462E487BA86E /* MJRefreshNormalTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DE6908A836615F946533A6FEE623373 /* MJRefreshNormalTrailer.m */; }; + D90DED0F5638B1C44F4B6C62D600D240 /* MJRefreshFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 800ECE845D6F36BE51A284DFCAE27307 /* MJRefreshFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D90DF1376DF5E2EA644313BCD2E03058 /* MJRefresh.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 083F5143D12F213638EF9FE439F1CEFA /* MJRefresh.bundle */; }; + D93EA925FC24665584B3653514A56706 /* JXCategoryIndicatorImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = B3443BE7FBE80A857A146093C743D9BF /* JXCategoryIndicatorImageView.m */; }; + D968461E31E8FF3FF6BA1DC621B0433B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F5B3C0CF01454E7AC9226E88FDFBAE6 /* UIKit.framework */; }; + DBA9500CBBA5FF6FCBBA115AE4D12152 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = BE9E061AE26F933A7BBEFF3D94E9B32D /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DBB7D12AC159E50D059772E4B6CF1D2F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + DBD9152526A180771BF7D7CD209B957E /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C354F545C0CC91C4033DC0D648B3819 /* AFSecurityPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCCBFE0D3914D33369C19AC135AB54AA /* HWBackgroundConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = FC8583F4233091326F271A4C13185F5B /* HWBackgroundConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DD7F63D4E4640C7386877BB787740272 /* LookinServer-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 469576EF612EDF18C057B4FB1E423192 /* LookinServer-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDA16FB9C21AD941442357DAE6939530 /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = CBB2B3782C3C4626F075A8900436D09D /* UIKit+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDB268F1408C6AA5860C768310E9B9D6 /* LSTPopView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D7C0280DF79D384D6CBED6E080E02BB8 /* LSTPopView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE5A78F116018E2AC54714238276574D /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = BF141C03BAA67847DFB6B6DFF0D1CBFC /* UIActivityIndicatorView+AFNetworking.m */; }; + DE98ECCCA7106A4EA575EF34830D41FF /* MJRefresh-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 741E2A603352D4102F1DAFBB68C69122 /* MJRefresh-dummy.m */; }; + DEA09692CF813A23899CD4949A9B6801 /* SDAnimatedImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 674659ECD497CB56B02FD385F68621CA /* SDAnimatedImageRep.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DED9ADFC8CC65243FC54E008A853742C /* MJPropertyKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 57A3558C23C0EFA92D7C80FBF8A6332A /* MJPropertyKey.m */; }; + DF2B15402CE105F5A8CE48BBDCFFD5DD /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 23B6D3BC0C4291E4CB154E7F35862BCB /* MASConstraint.m */; }; + DF525E5405FAD3B98B0C2D966EB2DD95 /* UIViewController+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A9BFDE06B11541EA7E87336A09C3816 /* UIViewController+LookinServer.m */; }; + E038F02D08E33A673A360ED34648A027 /* JXCategoryDotCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 87D7822F88C7B9608DF7E50878B7970B /* JXCategoryDotCell.m */; }; + E0B48B9D5D45AF3500FC718459D66E6C /* LookinDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DD55E3EFF5073BEBD483D293C40A0D6 /* LookinDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E0BCF21E9FA59F638C13ECCECC4D9690 /* SDMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C202F1C5D8455CDDCAE965BD7BAAFC3B /* SDMemoryCache.m */; }; + E0DB14976CA6F6E604FD5E4EDF3378E7 /* JXPagerListContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = E0742EB318197474CB672E4520705ACC /* JXPagerListContainerView.m */; }; + E1B4145C5201DB66B65520B36849067C /* HWPanModal-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE235E52EF7BBF7348F9B4CAB71F7D8 /* HWPanModal-dummy.m */; }; + E1BF615DD0422B06C97542F03C879D41 /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 860D7179002683A0368E532B751FC40E /* AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E1DE69F6BB6235A6EDB6C99A184BEDB4 /* UIScrollView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = B8F1319B150BB3DBD94BEB4C80F6F296 /* UIScrollView+MJExtension.m */; }; + E2DF1B379D9444D40D78320E90B1DC07 /* JXCategoryIndicatorLineView.h in Headers */ = {isa = PBXBuildFile; fileRef = A527D460219BC25D3D8E05E8A68C23C9 /* JXCategoryIndicatorLineView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3FC6BEE41652C0500F57E0CB83B347F /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = D7F6132E07FDE40130D6C51920456A21 /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E42D6EF120A5C17DA2F6FD6473CE7E7A /* JXCategoryTitleVerticalZoomCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 230B07768E56A05E48373DAA2EAC05DE /* JXCategoryTitleVerticalZoomCellModel.m */; }; + E4773572BED239AA7D618F1C05BAF51E /* HWPanModalPresentationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EBFFAE4CE0471C78DB70755CFCC7609 /* HWPanModalPresentationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E4B688B8A0D07AFB883A52250CA874A1 /* JXCategoryNumberCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5633AC0E53EEE3085AFE9CB101E6C0CF /* JXCategoryNumberCellModel.m */; }; + E4F1B478580D6D7328BC29607BDE46F6 /* UIImage+ExtendedCacheData.m in Sources */ = {isa = PBXBuildFile; fileRef = A7A348B5BB8CB7A444F827000C95DAE5 /* UIImage+ExtendedCacheData.m */; }; + E50613C67DD02AF6EA825DA0B31EFFAD /* SDImageGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = E9FA8ED817E86A0F4415B8E73B62DCF8 /* SDImageGraphics.m */; }; + E52DCE394A6E02B6BA11FA64624F68F3 /* JXCategoryIndicatorParamsModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E03A823CD994C7C3DEA8D91B90C5DE /* JXCategoryIndicatorParamsModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E55B3151D86660E28CEABC3CDE6B1508 /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = BF0EE7E880EA65C279154531EF91F5E8 /* UIButton+AFNetworking.m */; }; + E5B057BC87284367918B2DB9CA084B4E /* MJRefreshAutoGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7F3F9323470C634DC0D469E7C13B10 /* MJRefreshAutoGifFooter.m */; }; + E7520DAA65004368C61453B8A2740295 /* HWPanModalShadow.m in Sources */ = {isa = PBXBuildFile; fileRef = 513C1A2EE22268DD51EB02AE24E3B579 /* HWPanModalShadow.m */; }; + E76969F9B01139118427505B18F9CD21 /* SDImageHEICCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 55488AFE93BF97340EF80D0D6C1E2CA0 /* SDImageHEICCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E77175BDAE33AADF66766B28AA710247 /* JXPagerMainTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = D564B14F434E85E8016FF192E33548A8 /* JXPagerMainTableView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E7FEAB9F421F7EBAF021F792D8E9C4D6 /* LookinCustomDisplayItemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 44B0B0F109E74E6F92B6497967BCE536 /* LookinCustomDisplayItemInfo.m */; }; + E82964ED7092CDCDAD08BC596A57B43A /* UIImage+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 60195DBDE404C5ECBC4E710D0F5E50E7 /* UIImage+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E8AB529B9E0B4C23921344F6C4ABFEA4 /* SDImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E79D80C613F4B57826DA627018BB1C5 /* SDImageCoder.m */; }; + E930A5612DC6D120BE040AD17C6D1BCD /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = B9CA9F01554205BFBACCA553143C8676 /* MASViewAttribute.m */; }; + E97B2C62D3EE772504A939BEE7D6B459 /* HWPanModalPresentationAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = DB48FEC8123075E04395CF34F6F8227D /* HWPanModalPresentationAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EA82B6D97C9C5D0558047AF552D63203 /* SDWebImageDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 3313EDBDBF7A4CA0DC32526D9ED0B496 /* SDWebImageDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EABCB60A26B06BF576E50BBD2F89A385 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + EB3DF628891F7D6AB114718AF760CB2A /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = ED332DDCE634104C42A2AF8F698EDFB2 /* UIImageView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EB646114ABEA7A4D6C2A724404778670 /* LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E23048DA7D038B179D12173BA0F800DB /* LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC6671997676ABEBC34F2BE6C01266B1 /* LSTTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 68AAA13D71385283DB69A35327BC2F47 /* LSTTimer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC8E84A8FFADDCA562A8608D141D9027 /* MJRefreshAutoGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE9A594E8A127B7273A7D82E1882497 /* MJRefreshAutoGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC9B34262AED632D7EFB49804337648E /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E2CD23DF8D29ECCE7278412B1BFFFA2 /* Masonry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC9B8D81AEAF11E16149869246F7D4C1 /* JXCategoryFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = B82D0099E75E96FE5ACCF5B647388551 /* JXCategoryFactory.m */; }; + ECC6BC85943DB873215826A344A462FD /* JXCategoryIndicatorBallView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4AC508097EE18B75D5D75FDA7CF5C1 /* JXCategoryIndicatorBallView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ECE64B732F9FA7C402DDEEC58DCB9D98 /* SDImageAPNGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 07274C755D75F4A07C925D1DDE5FA529 /* SDImageAPNGCoder.m */; }; + ED8991A8AE7C04362C2BED3875DC1656 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DD3D7BBD826081D1399FCDA65D59838 /* AFURLResponseSerialization.m */; }; + ED8F64FF98CFAE0B12CF60A1B0E6BAF8 /* SDCallbackQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 402736588AC9D07AA589F2943BAE3C89 /* SDCallbackQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EDB9E11998290348E4DFB5140D678942 /* HWPanContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94CE97E5A9659D6EE58C83DCB52F73D5 /* HWPanContainerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EE101918DFCDC1D6728BF910DB5AF29A /* JXPagerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 044A47D1E36901CA79D51CC72EA995C9 /* JXPagerView.m */; }; + EE6E8FE636D2C02E3D2FC1E8555B4612 /* MJRefreshNormalHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = D411D25D78A2F9E3CF17B20443ED9F40 /* MJRefreshNormalHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EED016DE8173CD38CC01D88CD2628984 /* NSString+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 12702606A08588ACD81E031A777BAB70 /* NSString+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EEF0BF7E53148EB20BED242061BDC5ED /* JXCategoryTitleVerticalZoomView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43BA7B9A75BE654B8242649314595C2D /* JXCategoryTitleVerticalZoomView.m */; }; + EF51279C724969A99FF5EF85F832FC00 /* LYEmptyView.h in Headers */ = {isa = PBXBuildFile; fileRef = 374CEB5E4CAC5B1889E4B3A57B47546E /* LYEmptyView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EF6A6C725598F572A70C5FCEE328C184 /* SDImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EAD8B1C822E0F2BAB884329D798190B /* SDImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F1A04C26FAF235FD6B0AF30E7ACD5DD5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */; }; + F1ABB5428A1CCF2EAC42A4C3B388F25D /* JXCategoryIndicatorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DFC8007FA865661CA9E295ADD1014BA /* JXCategoryIndicatorView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F1D845E22D5B8FC6AFC3C2E41DA1B6DF /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C0082C9FF6875DA300AE3D8453DCB62 /* AFNetworkReachabilityManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F2892F71762EC5410EE733B862712BB3 /* LYEmptyView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C00601FB0A8CFBE203150BAEC58E95FC /* LYEmptyView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F2AD91050B1FE3C8BC78567F1FDE3ED5 /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A6B26A93BDE64568CF7AF44D709974 /* AFURLResponseSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F2C9F9038FBEFD951516694AE873A2B9 /* MBProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DC759BB8D0141E0F064F3BCA7197315 /* MBProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3263D294D688533EB974E37C61F1E24 /* MJExtensionConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D0DE149DDBAC4B5DCFA0C2217970015 /* MJExtensionConst.m */; }; + F3AECEF6D3BB919B3E7392942E1BC58B /* MJRefreshBackFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = A7EA79586CBF531A23E8B00CFA7B82C7 /* MJRefreshBackFooter.m */; }; + F3DA1005917E252B306712DAAA287FB0 /* UIViewController+PanModalDefault.m in Sources */ = {isa = PBXBuildFile; fileRef = B95FDE5F86C6AC76E24A82E181084256 /* UIViewController+PanModalDefault.m */; }; + F3F4A6309BD95DFAA4DCC60A4E07C515 /* UITableView+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = B77422F87DF00923771B3EF8E6C0A9BF /* UITableView+LookinServer.m */; }; + F43396B5CB23638E5509B3ED61AE6192 /* JXCategoryListContainerRTLCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 96D1E2DE4F6F4EB00BD41C7ABD504109 /* JXCategoryListContainerRTLCell.m */; }; + F458385338076D8734DD74BE4A94B33F /* UIColor+JXAdd.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D72A1C48CB238B4D5F50BA925DEDEAE /* UIColor+JXAdd.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F47EBDD360E642A0499A767BC7C17B4B /* HWPanIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E6EFEE426EA2068D5FE2B73740D659 /* HWPanIndicatorView.m */; }; + F49CB22863CCFEC7817D259F27F91C57 /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = E0DD4370E4AF2D75716AE1B5D67EABEB /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F53BE4449AE5896F76325E4DCB6D0B13 /* SDImageCachesManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 839CCD719F79C7FBC2909C72822FB470 /* SDImageCachesManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F600BB873FD4764BAA9E02826F804486 /* FLAnimatedImage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 7FAB126742756E8C628ED27AEC1B9567 /* FLAnimatedImage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F60F90EAF35CFF40DF1C33557965787D /* MJRefreshStateTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = AB1D54171867DC3B104DAE8C6D30F644 /* MJRefreshStateTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F62B0711DA506CCB3DF79F65134566C7 /* Lookin_PTPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B523AAA92DB90BD5B95092AF6B85BFB /* Lookin_PTPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F68889CD481716EE5D6B75EBD8FD53A6 /* SDImageCoderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A3E40CB9D351DF0E70C7A452071E82E1 /* SDImageCoderHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F6A0D6EA1B5DC3FE04DC4A1B0A914121 /* UIView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = DC7496C927F9E881D19A203C207B5417 /* UIView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F6A2DEEA8E8B92D365AFDDBD5E8C1218 /* NSObject+Lookin.m in Sources */ = {isa = PBXBuildFile; fileRef = B6575913AB2C7FDA723D279165349FF6 /* NSObject+Lookin.m */; }; + F6A34F74BE7FE816114D7F3902296AF2 /* HWVisualEffectView.m in Sources */ = {isa = PBXBuildFile; fileRef = F5D8EBF4698D8B331794EA6F9BF47665 /* HWVisualEffectView.m */; }; + F6D1C960368EB1E067ABD0BFF707FC56 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 673C80521DE4F20FDE3E9A82E6EBEC53 /* MASConstraintMaker.m */; }; + F7623E7C314AA5010D8D0BD6ED4AAAD4 /* AFImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 41B61F60FDADCD1988F2A5F1B93F6FB0 /* AFImageDownloader.m */; }; + F847E3C26E5AC43CD73364AD3DF49AFE /* JXCategoryImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8067C53E08CA3787D9D5C3551F86EF9D /* JXCategoryImageCell.m */; }; + F8616FAFEE1124368CB96473CE20CDB4 /* LookinAttrIdentifiers.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4F497397BEDE35BC05F6C2B6D33577 /* LookinAttrIdentifiers.m */; }; + F8F1B1196CAA5114BA9A95AA7E6D6AEB /* UIBlurEffect+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = B041D1C998D0894DB89A31049CC1B872 /* UIBlurEffect+LookinServer.m */; }; + F9789D86D3279D71B398B550F27C3EFF /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4883D2BC668CDDE38C319AC414885077 /* AFSecurityPolicy.m */; }; + FA3021DED76B9B182CC9195A60EB1209 /* NSBezierPath+SDRoundedCorners.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F0487226F5EBEBA3C6D3E1743C5260 /* NSBezierPath+SDRoundedCorners.m */; }; + FA6DA93357E2E9E9AADDFB3E39DEB6C2 /* NSObject+LookinServer.m in Sources */ = {isa = PBXBuildFile; fileRef = A566FD7AC8F85BE1E72F6DF11FEA6338 /* NSObject+LookinServer.m */; }; + FB6E014B34F33B89E5060DA1F00168A5 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77F4C0466DFC43C56F1D982F88EF74A0 /* ImageIO.framework */; }; + FC32143CA2A916F032F2B569313315AA /* HWPanContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 453FB14441528B4AE2CF3592D5874C54 /* HWPanContainerView.m */; }; + FCDEC6A53CF5517E1AF5B331FD65F6D9 /* SDImageCacheConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C3D9450A4AAE9542E6A1A0473B7DF812 /* SDImageCacheConfig.m */; }; + FCEE5BD645E95FF55468C4AB6D17CFDA /* UIImageView+HighlightedWebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F139F3BFF4ABD0678E7947E118F47774 /* UIImageView+HighlightedWebCache.m */; }; + FD3AF10F8723DABEE406D25592B5F562 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 148EEB030F62D4D33B4C03AE45AD6C08 /* FLAnimatedImageView.m */; }; + FDACBA49610EA6F39CABB7FE44B137D1 /* AFImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 36CBA5AB35EE7DE7B4A5CDBAC4BE20A8 /* AFImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FDD4C4D4F03502D5CB0B8763009A0948 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDEE6097B6411333154FEF90A280E3E4 /* QuartzCore.framework */; }; + FE07C069C2E3543002CEB5D751ABA9AC /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C75FCCDECEB6A92A56B67E27033473B6 /* AFNetworkReachabilityManager.m */; }; + FEA8BA4F82CCBD1D28DCC7EF39FB4096 /* SDImageCacheDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = C74EA9D59FFCBE16D0C0E5B7B2D53516 /* SDImageCacheDefine.m */; }; + FEE3D901B4A4638F9E00935144E982B3 /* HWPanModalPresentableHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FC2E352D2D0DD942A9B4488E3654AB0 /* HWPanModalPresentableHandler.m */; }; + FEE883575278D5BE8F185437AB5DB3BB /* MJRefreshGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = B6242B29A00A9DBC6FF1CD09266BBF54 /* MJRefreshGifHeader.m */; }; + FF106518AFECA24E74B1D649E4F9AC70 /* HWPanIndicatorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A15AB0AB6FCF1589E2A6CEDC3CF0B95 /* HWPanIndicatorView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FFC6D50089FA32FD7AAF25747E56EA60 /* LKS_CustomAttrGroupsMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = AB2B98D8DC3605842D8528F53C1896A2 /* LKS_CustomAttrGroupsMaker.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 17A6BBBD906DDCB7334A02B16B07B4DB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85; - remoteInfo = MJExtension; - }; - 17AC289E8A24B84DB147B7977008DB53 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1; - remoteInfo = AFNetworking; - }; - 1CC061C6A0CA52E13056E44543CDE4BD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; - remoteInfo = Masonry; - }; - 551922F754B651AFCAAB56605458A1A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; - remoteInfo = Masonry; - }; - 6610EBAD645971628D6E656F2A7FB551 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6868056D761E163D10FDAF8CF1C4D9B8; - remoteInfo = MJRefresh; - }; - 7D22DC5F48A287865357EE41131C6668 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 638FEAAFC575BB76BC6AC055CDDA3506; - remoteInfo = LookinServer; - }; - 8C2E663FC9840B2B7BABEF079AD58862 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 94CFBA7D633ECA58DF85C327B035E6A3; - remoteInfo = "SDWebImage-SDWebImage"; - }; - A311284721E0C3165FAA791C3EE6961E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0; - remoteInfo = MBProgressHUD; - }; - AD74DB90134D3DB33FAC2C873C0764E9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85; - remoteInfo = MJExtension; - }; - B0F47C29852712CF2F2C1E658ECD1809 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7; - remoteInfo = DZNEmptyDataSet; - }; - BBBA8C59A31486B3AE2F16C6A4AAAB66 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = B26054DF1DEA11585A231AF6D1D80D5E; - remoteInfo = "MJRefresh-MJRefresh.Privacy"; - }; - C85024A705A5032AA3907BF36C187CEA /* PBXContainerItemProxy */ = { + 02FAAF39D5DC83544D9E66B036B176EA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 4A68CFD979D413A619DF631BB121D98F; remoteInfo = Bugly; }; - D8B3BBDA3C526A079F33D20BFE81FDA0 /* PBXContainerItemProxy */ = { + 080FDB8CF401316D3CCD779F38297489 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7; - remoteInfo = DZNEmptyDataSet; + remoteGlobalIDString = 4AA4C7BB776C55F3421BA137B643DD64; + remoteInfo = LYEmptyView; }; - F295793354A8BF65125212DAE1C81DF5 /* PBXContainerItemProxy */ = { + 0AC2AD8EAFB742F27A3D34C64E40AFC6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 3847153A6E5EEFB86565BA840768F429; - remoteInfo = SDWebImage; + remoteGlobalIDString = 8BEAFAA726C1965864B79B4B441AA513; + remoteInfo = JXCategoryView; }; - F34B1D580EA71604D4CC7C4C5807E366 /* PBXContainerItemProxy */ = { + 492374464B2EEB82B866DBC203FB6CF9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85; + remoteInfo = MJExtension; + }; + 4B52CF33FA25735578A3E44A4CD0C61E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 16704C6B67439DA959DB043702C75A7A; + remoteInfo = "JXPagingView-JXPagerView"; + }; + 4F853CA6F77CC1808AF5BAF0CCAB86C0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85; + remoteInfo = MJExtension; + }; + 586A5F02457EAA9AECE8CFCC7EDC4A36 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1; remoteInfo = AFNetworking; }; - F4000FEC7CADA56B75E5CC31E64EC891 /* PBXContainerItemProxy */ = { + 6B502CE29B8265D64E66B68DA64E8BAF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = B32AF3F43989CBA171BB1FB3957A4509; - remoteInfo = "MJExtension-MJExtension"; + remoteGlobalIDString = 94CFBA7D633ECA58DF85C327B035E6A3; + remoteInfo = "SDWebImage-SDWebImage"; }; - F9524D7CD6D352CCF289944EBCA3B3FB /* PBXContainerItemProxy */ = { + 6C0462143C24DADCF6D346CFCCF1F2DF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0; remoteInfo = MBProgressHUD; }; + 6C532ADBCD9DB30208C8082362062867 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3847153A6E5EEFB86565BA840768F429; + remoteInfo = SDWebImage; + }; + 70663BD3E4659CFF0C7EF0B56DBC9C78 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0; + remoteInfo = MBProgressHUD; + }; + 71C3BF8323A3B89C42C815297FB1B486 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 638FEAAFC575BB76BC6AC055CDDA3506; + remoteInfo = LookinServer; + }; + 9D62F9D7E8B03E6D53909480991C8AEA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A2609DB0612F95A3450D2E02CA850A0; + remoteInfo = LSTTimer; + }; + A2D6E99D61C37E2D571D73F75FCFE0B4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B26054DF1DEA11585A231AF6D1D80D5E; + remoteInfo = "MJRefresh-MJRefresh.Privacy"; + }; + A3A1467D883FED3ABCAC49113A737098 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A2609DB0612F95A3450D2E02CA850A0; + remoteInfo = LSTTimer; + }; + B0121AEB150BEE5708989CCC69A51E6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6868056D761E163D10FDAF8CF1C4D9B8; + remoteInfo = MJRefresh; + }; + BAEC79AAEBBDF2BA3087612B7E05FD8E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E79E29F55A2453370D27112480FCF6A2; + remoteInfo = "JXCategoryView-JXCategoryView"; + }; + C30FB24BD734A3779E20934DB3D4D9C8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B32AF3F43989CBA171BB1FB3957A4509; + remoteInfo = "MJExtension-MJExtension"; + }; + C548A30C8E9A6CD52D6655421F9E80B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1; + remoteInfo = AFNetworking; + }; + CEFF12BAC2DF7A2FB2A16265805F8779 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C4E1020AF425614337737213AA26DBD5; + remoteInfo = JXPagingView; + }; + D031B103E98AAB5CEC13491B24F6A82E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7; + remoteInfo = DZNEmptyDataSet; + }; + D9630B9E5DE60DCADFA9106CF013D735 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8B7D23DD98E41BAE91418E9E85F191D6; + remoteInfo = LSTPopView; + }; + DB09B1B3C4EF493AB0763F0795077728 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 31DCABABCA873FBA7A92FEB47D71ED8E; + remoteInfo = HWPanModal; + }; + F02666E823668E7F6E705B610204BBE2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7; + remoteInfo = DZNEmptyDataSet; + }; + F24DDDDEE9FC26F48E2EA84062015B72 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; + remoteInfo = Masonry; + }; + F518DC696627DF925BE789501947DBC7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; + remoteInfo = Masonry; + }; + FD339A2CF804D4CD1FADE6633BE4DB45 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4A8E8992707D01510894596DB9BCCA00; + remoteInfo = FLAnimatedImage; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0075507DF323DF510CA1115DE2B33C98 /* LKS_MultiplatformAdapter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_MultiplatformAdapter.h; path = Src/Main/Server/Others/LKS_MultiplatformAdapter.h; sourceTree = ""; }; - 00E5C0F46BD576A82A38738DB780C7D9 /* AFNetworking.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = AFNetworking.modulemap; sourceTree = ""; }; - 01E24F0E64AEC0E54DBDB063CE89097A /* SDWebImageDefine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDefine.h; path = SDWebImage/Core/SDWebImageDefine.h; sourceTree = ""; }; - 0236FAD4E41045C8223B36E40BDEDF2C /* UIScrollView+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJRefresh.m"; path = "MJRefresh/UIScrollView+MJRefresh.m"; sourceTree = ""; }; - 0301A3F865A2919DCD43EE9D0DC363A5 /* LookinAutoLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAutoLayoutConstraint.h; path = Src/Main/Shared/LookinAutoLayoutConstraint.h; sourceTree = ""; }; - 036896A95CE28AB066292A03BAD2BFFA /* SDWebImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageManager.m; path = SDWebImage/Core/SDWebImageManager.m; sourceTree = ""; }; - 0370FDB753906B18C1B9AFB8BE7D213C /* SDWebImageDefine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDefine.m; path = SDWebImage/Core/SDWebImageDefine.m; sourceTree = ""; }; - 037A3F50C10BD2A3B9D2C3743608A737 /* SDWebImage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-umbrella.h"; sourceTree = ""; }; - 0426BF3118E242E4EA8BB1145A2A6F60 /* WKWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "WKWebView+AFNetworking.m"; path = "UIKit+AFNetworking/WKWebView+AFNetworking.m"; sourceTree = ""; }; - 04549DFA210F3D3C27211535994000B3 /* MJPropertyType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyType.h; path = MJExtension/MJPropertyType.h; sourceTree = ""; }; - 049541DC9203D75878CAF900D458CC34 /* NSObject+MJClass.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJClass.m"; path = "MJExtension/NSObject+MJClass.m"; sourceTree = ""; }; - 05D83C1EC3DD8D27EE1C07CFDE18D72E /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; sourceTree = ""; }; - 06660480BC631DCE06583A85704487AB /* LookinAttributeModification.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttributeModification.h; path = Src/Main/Shared/LookinAttributeModification.h; sourceTree = ""; }; - 0696D0619ACA95D8E9E7EFDC0CD595D2 /* AFNetworking-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-umbrella.h"; sourceTree = ""; }; - 07F0D69559BBD9895C4D0BD66F33AC55 /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; - 0AC3ECEAAABFC0FEDCE3E1B814F1A7E5 /* MJRefresh.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJRefresh.modulemap; sourceTree = ""; }; - 0AF433E9D2C6355E77FFBE3AC3CB5B3A /* SDImageAWebPCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAWebPCoder.m; path = SDWebImage/Core/SDImageAWebPCoder.m; sourceTree = ""; }; + 00449113F3BDDB46E11CEE02CF1F29A1 /* NSData+ImageContentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+ImageContentType.h"; path = "SDWebImage/Core/NSData+ImageContentType.h"; sourceTree = ""; }; + 0055AF44029FABEF5E29D1BC1B86CC15 /* UIImage+MemoryCacheCost.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MemoryCacheCost.h"; path = "SDWebImage/Core/UIImage+MemoryCacheCost.h"; sourceTree = ""; }; + 00AE10F23D2B898E9F45884FD9904B2F /* LKS_AttrGroupsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_AttrGroupsMaker.m; path = Src/Main/Server/Others/LKS_AttrGroupsMaker.m; sourceTree = ""; }; + 00B27A1456536538B2E7220C71AA3F4F /* LKS_HierarchyDisplayItemsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_HierarchyDisplayItemsMaker.m; path = Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.m; sourceTree = ""; }; + 00C9A4038FA1CE3381055E02DAAEC90E /* LookinIvarTrace.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinIvarTrace.h; path = Src/Base/LookinIvarTrace.h; sourceTree = ""; }; + 021930E01F482BDF2DEAAA2AF9FDCF18 /* JXCategoryIndicatorRainbowLineView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorRainbowLineView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.m; sourceTree = ""; }; + 0249A8711339B6CD1E26258C064677E9 /* NSObject+MJCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJCoding.m"; path = "MJExtension/NSObject+MJCoding.m"; sourceTree = ""; }; + 0260C833576479A14C0F759F9D161479 /* MJRefreshFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshFooter.m; path = MJRefresh/Base/MJRefreshFooter.m; sourceTree = ""; }; + 026BB0AEDD69539DEC39191EE0C5214B /* SDAsyncBlockOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAsyncBlockOperation.h; path = SDWebImage/Private/SDAsyncBlockOperation.h; sourceTree = ""; }; + 03700B93F7A3FF6F3675D80E5DB1C1C7 /* SDImageCodersManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCodersManager.m; path = SDWebImage/Core/SDImageCodersManager.m; sourceTree = ""; }; + 04094D9F916F0B3E8A409CF5EEC45FCC /* SDImageIOCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageIOCoder.m; path = SDWebImage/Core/SDImageIOCoder.m; sourceTree = ""; }; + 044A47D1E36901CA79D51CC72EA995C9 /* JXPagerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXPagerView.m; path = Sources/JXPagerView/JXPagerView.m; sourceTree = ""; }; + 0451FF8513ABCE79BA473B450192579B /* UIImage+MemoryCacheCost.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MemoryCacheCost.m"; path = "SDWebImage/Core/UIImage+MemoryCacheCost.m"; sourceTree = ""; }; + 04996832466C0B682760DEB660586A88 /* MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJRefresh-Info.plist"; sourceTree = ""; }; + 051A66FC7C22537DD150BA86539EC9D4 /* JXCategoryCollectionView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryCollectionView.h; path = Sources/Common/JXCategoryCollectionView.h; sourceTree = ""; }; + 05A7B005509B15E31ECEED7DFEEB1EDB /* MJPropertyKey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyKey.h; path = MJExtension/MJPropertyKey.h; sourceTree = ""; }; + 05D708E8F9065868500ABC98E789B739 /* KeyValueObserver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = KeyValueObserver.h; path = Sources/KVO/KeyValueObserver.h; sourceTree = ""; }; + 05EE9449F14265ADB3100E60632AB642 /* LookinEventHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinEventHandler.h; path = Src/Main/Shared/LookinEventHandler.h; sourceTree = ""; }; + 05FF40C91ADEB302CBF4314535A1A6E7 /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; + 060133813AFA51D11B917CB91A3D4950 /* AFCompatibilityMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFCompatibilityMacros.h; path = AFNetworking/AFCompatibilityMacros.h; sourceTree = ""; }; + 06878A6718B46A5E825D03CB581CD8B2 /* LookinServer-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LookinServer-Info.plist"; sourceTree = ""; }; + 07001E763AE097A75E1AFBEB80197373 /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; + 0719BBC5095E9B709A7485C347010514 /* LKS_HierarchyDetailsHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_HierarchyDetailsHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.m; sourceTree = ""; }; + 07274C755D75F4A07C925D1DDE5FA529 /* SDImageAPNGCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAPNGCoder.m; path = SDWebImage/Core/SDImageAPNGCoder.m; sourceTree = ""; }; + 073DE0C455B2CE33A0FBA3C6ECF4F8CF /* MJPropertyType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyType.m; path = MJExtension/MJPropertyType.m; sourceTree = ""; }; + 07C3DB4C7661755654D296A929BE2CE7 /* Lookin_PTChannel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTChannel.h; path = Src/Main/Shared/Peertalk/Lookin_PTChannel.h; sourceTree = ""; }; + 083F5143D12F213638EF9FE439F1CEFA /* MJRefresh.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MJRefresh.bundle; path = MJRefresh/MJRefresh.bundle; sourceTree = ""; }; + 091DAAA7597B1233173C3BB1DC8D1D79 /* HWPanModalContainerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalContainerView.h; path = Sources/View/PanModal/HWPanModalContainerView.h; sourceTree = ""; }; + 09799A44FC43F3184E20B590CC73FFC7 /* LookinStaticAsyncUpdateTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinStaticAsyncUpdateTask.h; path = Src/Main/Shared/LookinStaticAsyncUpdateTask.h; sourceTree = ""; }; + 0A70A9B1B9D076F21A4C704EAC69B3E9 /* SDWebImageOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOperation.m; path = SDWebImage/Core/SDWebImageOperation.m; sourceTree = ""; }; + 0A7D8AD4481BE4F0D7389A1662CCA111 /* Masonry.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Masonry.modulemap; sourceTree = ""; }; + 0AD4477B34BC6EAF1A362183974F34DC /* Bugly.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Bugly.release.xcconfig; sourceTree = ""; }; + 0AE235E52EF7BBF7348F9B4CAB71F7D8 /* HWPanModal-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HWPanModal-dummy.m"; sourceTree = ""; }; 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-CustomKeyboard"; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0BDAABEB54032920AAEBA43908724F60 /* ResourceBundle-MJExtension-MJExtension-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MJExtension-MJExtension-Info.plist"; sourceTree = ""; }; - 0BF41BBB1EBC1FE4F91BE320D947ED64 /* SDWebImageOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOperation.h; path = SDWebImage/Core/SDWebImageOperation.h; sourceTree = ""; }; - 0C31E11F6B40D55EB650013FAC1B59C0 /* SDWebImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.release.xcconfig; sourceTree = ""; }; + 0B4EEA7B77703F45AB157AC651CEF4EA /* UIView+LYExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+LYExtension.m"; path = "LYEmptyView/UIView+LYExtension.m"; sourceTree = ""; }; + 0B5075BB968E268BB5D61B393C333DB4 /* UIImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+WebCache.h"; path = "SDWebImage/Core/UIImageView+WebCache.h"; sourceTree = ""; }; + 0BC7EB117F009B160822B3FFCCC63F2A /* SDImageCodersManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCodersManager.h; path = SDWebImage/Core/SDImageCodersManager.h; sourceTree = ""; }; + 0BED1E57A7780D7944D806EF7FB48648 /* HWPanModalContainerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalContainerView.m; path = Sources/View/PanModal/HWPanModalContainerView.m; sourceTree = ""; }; 0C4AE62ED97252893F28F670D61AFB24 /* Pods-keyBoard-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-keyBoard-Info.plist"; sourceTree = ""; }; - 0C5C306F08907FB9E1301EA07220C6EB /* SDWebImageDownloaderOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderOperation.m; path = SDWebImage/Core/SDWebImageDownloaderOperation.m; sourceTree = ""; }; - 0CE9804DA47B24CF925450C7924EF999 /* Masonry.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Masonry.modulemap; sourceTree = ""; }; - 0D18C326A9F4C285AD294832344E63FF /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; + 0C6F8F3E8953AADD74838D4A882F45A1 /* NSObject+MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJProperty.h"; path = "MJExtension/NSObject+MJProperty.h"; sourceTree = ""; }; + 0C7575113B17F46DF34D3C118CB31308 /* NSObject+MJKeyValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJKeyValue.m"; path = "MJExtension/NSObject+MJKeyValue.m"; sourceTree = ""; }; + 0CA8B3EFCD9E73829676C70CE3E88BE0 /* UIView+LYExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+LYExtension.h"; path = "LYEmptyView/UIView+LYExtension.h"; sourceTree = ""; }; + 0CE35A6903D3E473ACA2703E7286A28E /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; + 0CF1A36FA548FCE3A4F7DA66625E9583 /* JXCategoryTitleCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleCell.h; path = Sources/Title/JXCategoryTitleCell.h; sourceTree = ""; }; 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CustomKeyboard.debug.xcconfig"; sourceTree = ""; }; - 0D703CF356A8E2B3B3665722366223A5 /* Lookin_PTPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTPrivate.h; path = Src/Main/Shared/Peertalk/Lookin_PTPrivate.h; sourceTree = ""; }; - 0E24EFDE111F674B782A0DB6E26DA6D2 /* MJRefreshBackStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackStateFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m; sourceTree = ""; }; + 0D6771046C7CF97C82B7D303F2AFD49E /* SDWebImageCacheSerializer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCacheSerializer.m; path = SDWebImage/Core/SDWebImageCacheSerializer.m; sourceTree = ""; }; + 0DEA9604C374890EC86557DA00C054E0 /* LookinServer.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LookinServer.modulemap; sourceTree = ""; }; 0E732C0D026ACBC7DBD039DC3BDC2BCE /* Pods-keyBoard.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-keyBoard.modulemap"; sourceTree = ""; }; - 0F0234E8EBBDCA694F549267CF8444C2 /* MJRefreshGifHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshGifHeader.m; path = MJRefresh/Custom/Header/MJRefreshGifHeader.m; sourceTree = ""; }; - 0FD3FF7FA5E997D3DDAB5C272F8734A6 /* UIImage+Metadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Metadata.m"; path = "SDWebImage/Core/UIImage+Metadata.m"; sourceTree = ""; }; - 107E924936A407875330C174B34260AC /* SDWebImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SDWebImage-Info.plist"; sourceTree = ""; }; - 1110127348EF0DD2FF03A68A13D86895 /* NSButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSButton+WebCache.h"; path = "SDWebImage/Core/NSButton+WebCache.h"; sourceTree = ""; }; - 120B89B8756AC54266917A34CDCADBB2 /* MJRefreshFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshFooter.h; path = MJRefresh/Base/MJRefreshFooter.h; sourceTree = ""; }; - 12119FD9C09B77E5C8A003238C89E88A /* UIView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+LookinServer.h"; path = "Src/Main/Server/Category/UIView+LookinServer.h"; sourceTree = ""; }; - 12F12865FFC70E396EDFB92C4A7F13D7 /* SDImageCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCoder.m; path = SDWebImage/Core/SDImageCoder.m; sourceTree = ""; }; - 131863AC3A27979CE5BF1B35EB9C1CED /* SDImageFramePool.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageFramePool.m; path = SDWebImage/Private/SDImageFramePool.m; sourceTree = ""; }; - 13D448A155C957ECCF95DC54FBE28569 /* SDCallbackQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDCallbackQueue.m; path = SDWebImage/Core/SDCallbackQueue.m; sourceTree = ""; }; - 148FDB67C55B5854E979447E82AFD54E /* SDImageFramePool.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageFramePool.h; path = SDWebImage/Private/SDImageFramePool.h; sourceTree = ""; }; - 1550F0B5EA5360BFA35606256AB6EF51 /* Lookin_PTProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTProtocol.h; path = Src/Main/Shared/Peertalk/Lookin_PTProtocol.h; sourceTree = ""; }; - 15D08EB14955AB2B841A5E9E16D8D4AE /* SDWebImageDownloaderResponseModifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderResponseModifier.m; path = SDWebImage/Core/SDWebImageDownloaderResponseModifier.m; sourceTree = ""; }; - 15E423D2DE3EB3895273EDB5BC21FDE9 /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; - 15EEB72FE94B15511A9B077601BFC002 /* SDWebImageDownloaderDecryptor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderDecryptor.h; path = SDWebImage/Core/SDWebImageDownloaderDecryptor.h; sourceTree = ""; }; - 16C85770D72E9770C476992A31B3655F /* MBProgressHUD-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MBProgressHUD-dummy.m"; sourceTree = ""; }; - 17422A39378973466DCE06FB6ADA832E /* NSData+ImageContentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+ImageContentType.m"; path = "SDWebImage/Core/NSData+ImageContentType.m"; sourceTree = ""; }; - 189A631A2ED6331F0A226846AD73B1E4 /* LookinEventHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinEventHandler.m; path = Src/Main/Shared/LookinEventHandler.m; sourceTree = ""; }; - 18DB01964CBE026F2E6511875E1A98E2 /* Bugly.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Bugly.debug.xcconfig; sourceTree = ""; }; - 1948F2AFCD4F7087CA46FB78E5A05ABD /* LookinAttributesGroup.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttributesGroup.h; path = Src/Main/Shared/LookinAttributesGroup.h; sourceTree = ""; }; - 19CD19C5B1822DA77E4C7C9F454FD5D5 /* Image+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "Image+Lookin.m"; path = "Src/Main/Shared/Category/Image+Lookin.m"; sourceTree = ""; }; - 19F3928D9276C0125AA1EBDB31A470E1 /* SDCallbackQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDCallbackQueue.h; path = SDWebImage/Core/SDCallbackQueue.h; sourceTree = ""; }; - 1A62C9B59CFA9D74EE95F526BE485EC8 /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; - 1C3AD08A39781246EBAC23F5B8A9BDD3 /* UIScrollView+EmptyDataSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+EmptyDataSet.m"; path = "Source/UIScrollView+EmptyDataSet.m"; sourceTree = ""; }; - 1C5B4FB13625B33C4ABB17DDEF05C782 /* LookinCustomDisplayItemInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinCustomDisplayItemInfo.m; path = Src/Main/Shared/LookinCustomDisplayItemInfo.m; sourceTree = ""; }; - 1CA256AA8704AE9F135214714BAFF153 /* SDImageAssetManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAssetManager.m; path = SDWebImage/Private/SDImageAssetManager.m; sourceTree = ""; }; - 1D4236904A41DC2950754F5BE583BD4A /* UIColor+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+LookinServer.m"; path = "Src/Main/Server/Category/UIColor+LookinServer.m"; sourceTree = ""; }; - 1D74E044AA7CFE331B6C3B53D98B1022 /* LKS_CustomAttrSetterManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomAttrSetterManager.m; path = Src/Main/Server/Others/LKS_CustomAttrSetterManager.m; sourceTree = ""; }; + 0EBF81CE72AA8B4B06F1BC37CFA7B96A /* UIImage+Transform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Transform.m"; path = "SDWebImage/Core/UIImage+Transform.m"; sourceTree = ""; }; + 0ED5656E5971882A3EA314E222EBC2C5 /* SDFileAttributeHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDFileAttributeHelper.h; path = SDWebImage/Private/SDFileAttributeHelper.h; sourceTree = ""; }; + 0F1705DF1CC5E82194523F85FE871354 /* HWDimmedView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWDimmedView.h; path = Sources/View/HWDimmedView.h; sourceTree = ""; }; + 0FC2E352D2D0DD942A9B4488E3654AB0 /* HWPanModalPresentableHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalPresentableHandler.m; path = Sources/Mediator/HWPanModalPresentableHandler.m; sourceTree = ""; }; + 0FFF1AB10AC30C72DB3B2F106B23E5B3 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = MJExtension/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 1069EA3A85D1A1A87FE087B0FE402436 /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; + 10AACE3BDEFABB8B9E709942B03E5595 /* JXPagingView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "JXPagingView-dummy.m"; sourceTree = ""; }; + 10DBEAC7DAAC95D5A947ACA061058C0B /* LookinConnectionAttachment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinConnectionAttachment.h; path = Src/Main/Shared/LookinConnectionAttachment.h; sourceTree = ""; }; + 12702606A08588ACD81E031A777BAB70 /* NSString+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+MJExtension.h"; path = "MJExtension/NSString+MJExtension.h"; sourceTree = ""; }; + 128CF11122A7C2009F733361122E39A1 /* Masonry-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-umbrella.h"; sourceTree = ""; }; + 13AC6B7EC0E45B7BC751451206C8C575 /* MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtension.h; path = MJExtension/MJExtension.h; sourceTree = ""; }; + 148EEB030F62D4D33B4C03AE45AD6C08 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImageView.m; path = FLAnimatedImage/FLAnimatedImageView.m; sourceTree = ""; }; + 14CF605A6E1A867AA3131733CCE53D99 /* MJRefreshAutoFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoFooter.m; path = MJRefresh/Base/MJRefreshAutoFooter.m; sourceTree = ""; }; + 15C39377834B42681C3BF6A5471C5F78 /* NSString+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+MJExtension.m"; path = "MJExtension/NSString+MJExtension.m"; sourceTree = ""; }; + 15D6A20A536D39FB4F4DE78CEC3512CE /* LookinDisplayItemDetail.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinDisplayItemDetail.m; path = Src/Main/Shared/LookinDisplayItemDetail.m; sourceTree = ""; }; + 1612A7E2EB4D912BD038AFA9FAE11CFD /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; + 16308A5AF08E401B61B68CCD953A0528 /* MJRefreshHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshHeader.h; path = MJRefresh/Base/MJRefreshHeader.h; sourceTree = ""; }; + 163DD1C8E32A767AC162D451FB47DECB /* LSTPopView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LSTPopView.debug.xcconfig; sourceTree = ""; }; + 16465B6B7358098E137335C9985BBBBC /* SDWebImageError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageError.h; path = SDWebImage/Core/SDWebImageError.h; sourceTree = ""; }; + 1679E08A4A241FB86455E71FDFB20D9F /* SDDisplayLink.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDisplayLink.m; path = SDWebImage/Private/SDDisplayLink.m; sourceTree = ""; }; + 1724C0944D7BC65545806EE9EDED203D /* HWPanModalPresentationDelegate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalPresentationDelegate.m; path = Sources/Delegate/HWPanModalPresentationDelegate.m; sourceTree = ""; }; + 17A16F153D08C8BBF15070C730EC0C3A /* LookinTuple.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinTuple.h; path = Src/Main/Shared/LookinTuple.h; sourceTree = ""; }; + 18106F0763EC023048DB3F77457B9596 /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; + 1817B2506E6D89DAFA8176C4A51738C0 /* JXCategoryIndicatorView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorView.m; path = Sources/Indicator/JXCategoryIndicatorView.m; sourceTree = ""; }; + 18EAC20398B46C2C580B542618314D9E /* FLAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImageView.h; path = FLAnimatedImage/include/FLAnimatedImageView.h; sourceTree = ""; }; + 1936EF3FEE34E513D746BA5037CDEE80 /* JXCategoryIndicatorParamsModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorParamsModel.m; path = Sources/Common/JXCategoryIndicatorParamsModel.m; sourceTree = ""; }; + 1B1E80842E43848FFB0F162AFF96E774 /* UIView+LSTPV.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+LSTPV.m"; path = "LSTPopView/Classes/Code/UIView+LSTPV.m"; sourceTree = ""; }; + 1B41D364B66F85CF33EB15116929CF48 /* NSObject+MJKeyValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJKeyValue.h"; path = "MJExtension/NSObject+MJKeyValue.h"; sourceTree = ""; }; + 1B82CFD6AD23DAB70352983FFFA8DBBE /* SDWebImageOptionsProcessor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOptionsProcessor.m; path = SDWebImage/Core/SDWebImageOptionsProcessor.m; sourceTree = ""; }; + 1BFABBA210FF6BEF09CABCCBE8AE590F /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; + 1C9E2AC9C9AE14EBBFDCDBBA925613E4 /* JXCategoryFactory.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryFactory.h; path = Sources/Common/JXCategoryFactory.h; sourceTree = ""; }; + 1CA6A325AACF7253FFEB9D258746335D /* SDImageHEICCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageHEICCoder.m; path = SDWebImage/Core/SDImageHEICCoder.m; sourceTree = ""; }; + 1D0C4CB17BF463D490AE3400293A0D47 /* LYEmptyBaseView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LYEmptyBaseView.m; path = LYEmptyView/LYEmptyBaseView.m; sourceTree = ""; }; + 1D490F15AED6B55BCD64F4D5193A9375 /* JXCategoryIndicatorComponentView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorComponentView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.m; sourceTree = ""; }; 1D774D8146EBC82B4A77204A273761B8 /* Pods-CustomKeyboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CustomKeyboard.release.xcconfig"; sourceTree = ""; }; - 1E12075C58652877783AAD26D8A6ED78 /* NSBundle+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBundle+MJRefresh.h"; path = "MJRefresh/NSBundle+MJRefresh.h"; sourceTree = ""; }; - 1F43D293502C6A280429EF2DEFA6C0E6 /* SDImageCacheConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheConfig.h; path = SDWebImage/Core/SDImageCacheConfig.h; sourceTree = ""; }; - 1FC42F03931384EE2605E5C1FF575608 /* SDImageFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageFrame.h; path = SDWebImage/Core/SDImageFrame.h; sourceTree = ""; }; + 1D8DC297A0249D2FB0109542F14B89AB /* UITextView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextView+LookinServer.m"; path = "Src/Main/Server/Category/UITextView+LookinServer.m"; sourceTree = ""; }; + 1DD3D7BBD826081D1399FCDA65D59838 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; sourceTree = ""; }; + 1E2CD23DF8D29ECCE7278412B1BFFFA2 /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; + 1EC115C953943E0027F6AD5AFEE41A30 /* HWPageSheetPresentingAnimation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPageSheetPresentingAnimation.h; path = Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.h; sourceTree = ""; }; + 1EFF4D34DD5391DCE7D206B11306BCE5 /* LKS_CustomAttrModificationHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomAttrModificationHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.h; sourceTree = ""; }; + 1EFF4EEBD779C7DB39B6B044205385FA /* HWPanModal-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HWPanModal-umbrella.h"; sourceTree = ""; }; + 1F9506DDA8FBAA7420E9B8137BFCFDFA /* HWPanModalPresentationController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalPresentationController.m; path = Sources/Controller/HWPanModalPresentationController.m; sourceTree = ""; }; 1FFED36A657123030ABB700256D73F15 /* Masonry */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Masonry; path = Masonry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2039E8AAF8AAC77E31E425C61871263D /* Image+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Image+Lookin.h"; path = "Src/Main/Shared/Category/Image+Lookin.h"; sourceTree = ""; }; - 2065E7BBA3909607E34531E7D59623FF /* MJRefresh-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-umbrella.h"; sourceTree = ""; }; - 20C240076DD8D1DC14E751DAFAE98662 /* DZNEmptyDataSet-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "DZNEmptyDataSet-Info.plist"; sourceTree = ""; }; - 21628153BCD0325102EB502FB5AEDF0F /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; - 219886C4AF0E20C3CD4D4061CAAE8767 /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; - 220B8AB16FBD2158AB55D35E9376D13A /* UIBlurEffect+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIBlurEffect+LookinServer.h"; path = "Src/Main/Server/Category/UIBlurEffect+LookinServer.h"; sourceTree = ""; }; - 2254BB0E1CAB331C712E8819CE1CEBA9 /* SDImageLoader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageLoader.m; path = SDWebImage/Core/SDImageLoader.m; sourceTree = ""; }; - 23D7D1DC3E63FD87D87BE6C2EB198360 /* AFNetworking-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "AFNetworking-Info.plist"; sourceTree = ""; }; - 241065D9A03A30BC61C328A01C40E560 /* SDAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "SDAnimatedImageView+WebCache.h"; path = "SDWebImage/Core/SDAnimatedImageView+WebCache.h"; sourceTree = ""; }; - 241D729CBB4E30C3E09474F7F34CB9FA /* UIImage+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+LookinServer.h"; path = "Src/Main/Server/Category/UIImage+LookinServer.h"; sourceTree = ""; }; - 245FCAB926AF197B8F4E931DD8477D4A /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; - 24998A1052F45827E4FFAFAF7FA1542E /* SDMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDMemoryCache.h; path = SDWebImage/Core/SDMemoryCache.h; sourceTree = ""; }; - 25391D44BC144DD932559C9E9069347F /* SDWebImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-prefix.pch"; sourceTree = ""; }; + 20674A80959A90C9F9E51DBDC8807D93 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = MJRefresh/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 207535A186296DE018201ED1B7DDD076 /* LKS_ExportManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_ExportManager.m; path = Src/Main/Server/Others/LKS_ExportManager.m; sourceTree = ""; }; + 20C453B83E1025092DAD587080018B43 /* UIImage+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+LookinServer.m"; path = "Src/Main/Server/Category/UIImage+LookinServer.m"; sourceTree = ""; }; + 210B700E8324769F741C26126E6B1F4A /* Lookin_PTUSBHub.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTUSBHub.h; path = Src/Main/Shared/Peertalk/Lookin_PTUSBHub.h; sourceTree = ""; }; + 22A80188C121A76950A88A3321260BFD /* RTLManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RTLManager.h; path = Sources/RLTManager/RTLManager.h; sourceTree = ""; }; + 230B07768E56A05E48373DAA2EAC05DE /* JXCategoryTitleVerticalZoomCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleVerticalZoomCellModel.m; path = Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.m; sourceTree = ""; }; + 23763927ED025640A4CAA94867A3D823 /* NSImage+Compatibility.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSImage+Compatibility.m"; path = "SDWebImage/Core/NSImage+Compatibility.m"; sourceTree = ""; }; + 23B693321C3E2CA46CF401E48AE2795D /* MJExtension-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJExtension-Info.plist"; sourceTree = ""; }; + 23B6D3BC0C4291E4CB154E7F35862BCB /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; + 253C2858A52DB3FD4BE13D65D2B6C2A6 /* SDWebImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageManager.h; path = SDWebImage/Core/SDWebImageManager.h; sourceTree = ""; }; + 25475D081A3343232AD119F5F5A5F24A /* JXCategoryTitleVerticalZoomCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleVerticalZoomCell.h; path = Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.h; sourceTree = ""; }; 25664483ABF4DC8EC03E7472AA04333B /* LookinServer */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = LookinServer; path = LookinServer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2567115C715DFD2B942FF9386C729778 /* UIViewController+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+LookinServer.h"; path = "Src/Main/Server/Category/UIViewController+LookinServer.h"; sourceTree = ""; }; - 25AADAD73C32FC4E150A4A19780980C4 /* SDDisplayLink.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDisplayLink.h; path = SDWebImage/Private/SDDisplayLink.h; sourceTree = ""; }; - 2625A6F485FAAFFDD766C135FDF8F796 /* DZNEmptyDataSet.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = DZNEmptyDataSet.modulemap; sourceTree = ""; }; - 26476CAEC54A4CE04264494F816DFD2C /* CALayer+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CALayer+LookinServer.h"; path = "Src/Main/Server/Category/CALayer+LookinServer.h"; sourceTree = ""; }; - 26E9B5584E3E3AA9E7AF8978192DF06B /* DZNEmptyDataSet-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DZNEmptyDataSet-prefix.pch"; sourceTree = ""; }; - 2731C084E8B9BB6A54629DDFEBD14EA1 /* UIVisualEffectView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIVisualEffectView+LookinServer.m"; path = "Src/Main/Server/Category/UIVisualEffectView+LookinServer.m"; sourceTree = ""; }; + 256D50D68BFC3FD314552D1D0BC2044D /* SDMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDMemoryCache.h; path = SDWebImage/Core/SDMemoryCache.h; sourceTree = ""; }; + 26469EA2BF7F49FCDA80695277950B2B /* LookinHierarchyInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinHierarchyInfo.h; path = Src/Main/Shared/LookinHierarchyInfo.h; sourceTree = ""; }; + 2713EAAF042877733E01E359F3224ABF /* MJExtension-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-umbrella.h"; sourceTree = ""; }; + 2795C0F083BB71E948BE56DAFC73957B /* LSTPopView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LSTPopView.modulemap; sourceTree = ""; }; 281686F4C9CC2C718B45E1DEB7E63948 /* Pods-CustomKeyboard-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-CustomKeyboard-acknowledgements.markdown"; sourceTree = ""; }; - 290A1387E4C301A25D8613FBB0DCEC6A /* LookinDashboardBlueprint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinDashboardBlueprint.m; path = Src/Main/Shared/LookinDashboardBlueprint.m; sourceTree = ""; }; - 2940A878AE956B2190BA5A68D63DC5AD /* MBProgressHUD.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.debug.xcconfig; sourceTree = ""; }; - 299CDB086FE0568EE14EAB79D7B74437 /* SDWebImageCompat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCompat.m; path = SDWebImage/Core/SDWebImageCompat.m; sourceTree = ""; }; - 2A5A249D6ED704F9FEE1FFBC9B61426F /* SDWebImageDownloaderConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderConfig.m; path = SDWebImage/Core/SDWebImageDownloaderConfig.m; sourceTree = ""; }; - 2A67F3F63FB3C05544B8F66F7ED89E74 /* UIImage+ForceDecode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ForceDecode.h"; path = "SDWebImage/Core/UIImage+ForceDecode.h"; sourceTree = ""; }; - 2A7BA44CD5FDF42B32263B5F4259A024 /* MJExtension-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJExtension-dummy.m"; sourceTree = ""; }; - 2AEE1DAEE2CD1BAB6DBCBC50916263A4 /* SDWebImageDownloaderRequestModifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderRequestModifier.m; path = SDWebImage/Core/SDWebImageDownloaderRequestModifier.m; sourceTree = ""; }; + 292BBC0398F56F3818017A7314541B45 /* JXCategoryNumberCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryNumberCellModel.h; path = Sources/Number/JXCategoryNumberCellModel.h; sourceTree = ""; }; + 2945888F89AB6D3ECBBEDD6E09D1B949 /* UIScrollView+EmptyDataSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+EmptyDataSet.h"; path = "Source/UIScrollView+EmptyDataSet.h"; sourceTree = ""; }; + 29792A8AE7CB7444FE7BA20424B814AD /* MJRefreshStateTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m; sourceTree = ""; }; + 2A03E8820B42DFF0FCE849CB64302CAF /* SDAsyncBlockOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAsyncBlockOperation.m; path = SDWebImage/Private/SDAsyncBlockOperation.m; sourceTree = ""; }; + 2A1E2D85798C902C2A1E1B714EF78587 /* UIViewController+PanModalPresenter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+PanModalPresenter.m"; path = "Sources/Presenter/UIViewController+PanModalPresenter.m"; sourceTree = ""; }; + 2A4AC508097EE18B75D5D75FDA7CF5C1 /* JXCategoryIndicatorBallView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorBallView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.h; sourceTree = ""; }; + 2A98EB9CE425ECC87D9747E4EAC3DB0C /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; + 2B0B272843C604B68C602DEE1AD3605F /* UIView+HW_Frame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+HW_Frame.h"; path = "Sources/Category/UIView+HW_Frame.h"; sourceTree = ""; }; 2B276B0A79173A1D6E83C9B4FB9A4A57 /* MJExtension */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MJExtension; path = MJExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2BA061B3651D9243CBD96694626B95C1 /* SDAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImage.h; path = SDWebImage/Core/SDAnimatedImage.h; sourceTree = ""; }; - 2CC603030F93055E51FF99944B356CB6 /* MJRefreshBackGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackGifFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h; sourceTree = ""; }; - 2CFE5CE900A783BD5709EEF033BA8475 /* LookinServer-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LookinServer-Info.plist"; sourceTree = ""; }; - 2D069519EE909290F7C452231691CA88 /* MBProgressHUD.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = MBProgressHUD.h; sourceTree = ""; }; - 2D3B8DD288273B0C3AFDD2F366BB894B /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; - 2D93B5DFF8656FC20174F5CDCB325540 /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; - 2DAD93B79D27664FE05E862A2C992A45 /* LookinServer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LookinServer.release.xcconfig; sourceTree = ""; }; - 2DFD54923DA02EA135A1A1E2F56CBDE1 /* UIImage+GIF.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+GIF.h"; path = "SDWebImage/Core/UIImage+GIF.h"; sourceTree = ""; }; - 2EEEDD3CF0530751FD80AFB402DAB153 /* NSObject+MJKeyValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJKeyValue.m"; path = "MJExtension/NSObject+MJKeyValue.m"; sourceTree = ""; }; - 2F154763B55BC95D1F3E0C64970B8D48 /* LookinCustomAttrModification.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinCustomAttrModification.h; path = Src/Main/Shared/LookinCustomAttrModification.h; sourceTree = ""; }; - 2F6981AC25702BE9417B498391042242 /* LookinAppInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAppInfo.h; path = Src/Main/Shared/LookinAppInfo.h; sourceTree = ""; }; - 2FD6A0DEDE4E0A17B8A614C8D15158DD /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; - 2FE87671299E95720DB52DD3375B566E /* SDImageCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCoder.h; path = SDWebImage/Core/SDImageCoder.h; sourceTree = ""; }; - 30361FA11468C74A598363E37D30E56C /* LKS_ObjectRegistry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_ObjectRegistry.m; path = Src/Main/Server/Others/LKS_ObjectRegistry.m; sourceTree = ""; }; - 30A10CFE082F8338A031688B47CDED17 /* LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinServer.h; path = Src/Main/Server/LookinServer.h; sourceTree = ""; }; - 319E8C485C3E5DB2BFBF15AA61E5ABA9 /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; - 31C3AFC445B760812F9E6924ABB9CC15 /* Masonry-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-umbrella.h"; sourceTree = ""; }; - 31C69A4489CC7299F114CDEAFBE0DE3C /* LKS_MultiplatformAdapter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_MultiplatformAdapter.m; path = Src/Main/Server/Others/LKS_MultiplatformAdapter.m; sourceTree = ""; }; - 31E7ED25B098BFBF30E180BFC0E2174B /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; - 32556CF656ADFF88DE99F135C7BE2EB7 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; - 336D23D3AF9B2B8FD356A62D7B4A2A05 /* NSObject+MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJProperty.m"; path = "MJExtension/NSObject+MJProperty.m"; sourceTree = ""; }; - 33E548EC20D55A1581EF030D8F590720 /* SDAnimatedImageRep.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageRep.h; path = SDWebImage/Core/SDAnimatedImageRep.h; sourceTree = ""; }; - 341D877992B274AC6FD93AB03542E561 /* Lookin_PTChannel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTChannel.h; path = Src/Main/Shared/Peertalk/Lookin_PTChannel.h; sourceTree = ""; }; - 34206822AA40B77DF3E1B3B5D326158F /* SDImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCache.h; path = SDWebImage/Core/SDImageCache.h; sourceTree = ""; }; - 34294BB6B51E74AFE5298D85D957E2F6 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; - 35182E600B80DDDFBA4A4B90FAA71EFD /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; - 352F463EFB3454F98E285A844376EC28 /* MJRefresh.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MJRefresh.bundle; path = MJRefresh/MJRefresh.bundle; sourceTree = ""; }; - 35618C07738616EC64E35AB9084E01C6 /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; + 2B4792E0E693278C27DB918B70E58272 /* MJRefreshConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConfig.h; path = MJRefresh/MJRefreshConfig.h; sourceTree = ""; }; + 2B53DEB14A9698F954D95E54715C1911 /* DZNEmptyDataSet-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "DZNEmptyDataSet-Info.plist"; sourceTree = ""; }; + 2CB55990BE7673BB5930FB77BB2A2C33 /* FLAnimatedImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FLAnimatedImage.debug.xcconfig; sourceTree = ""; }; + 2CCD2F6CD21BCE8D4DC6CE0FB91B91CB /* FLAnimatedImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImage-dummy.m"; sourceTree = ""; }; + 2D0DE149DDBAC4B5DCFA0C2217970015 /* MJExtensionConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJExtensionConst.m; path = MJExtension/MJExtensionConst.m; sourceTree = ""; }; + 2DC211B96CB1A7D40B3203E4778066C9 /* UIViewController+LayoutHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+LayoutHelper.h"; path = "Sources/Presentable/UIViewController+LayoutHelper.h"; sourceTree = ""; }; + 2DFC8007FA865661CA9E295ADD1014BA /* JXCategoryIndicatorView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorView.h; path = Sources/Indicator/JXCategoryIndicatorView.h; sourceTree = ""; }; + 2E585503EB164F6C036C85B124140368 /* SDImageLoadersManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageLoadersManager.m; path = SDWebImage/Core/SDImageLoadersManager.m; sourceTree = ""; }; + 2E79D80C613F4B57826DA627018BB1C5 /* SDImageCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCoder.m; path = SDWebImage/Core/SDImageCoder.m; sourceTree = ""; }; + 2F04E40EC66FE8A57ECA4BC540959E1D /* ResourceBundle-JXPagerView-JXPagingView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-JXPagerView-JXPagingView-Info.plist"; sourceTree = ""; }; + 2F19C07EBC4D3E8EF1AD6C474E7F24FE /* LYEmptyView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LYEmptyView-dummy.m"; sourceTree = ""; }; + 2F4A1CCB21DB7EA5A2ACEB11E374FBCA /* JXPagingView */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = JXPagingView; path = JXPagingView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 304D443FD07AF14BA7F1628D80971669 /* SDWebImageDownloaderOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderOperation.h; path = SDWebImage/Core/SDWebImageDownloaderOperation.h; sourceTree = ""; }; + 304FA88F8B2636C2DD7FA535D2BD617D /* UIScrollView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJExtension.h"; path = "MJRefresh/UIScrollView+MJExtension.h"; sourceTree = ""; }; + 30E03A823CD994C7C3DEA8D91B90C5DE /* JXCategoryIndicatorParamsModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorParamsModel.h; path = Sources/Common/JXCategoryIndicatorParamsModel.h; sourceTree = ""; }; + 310DC522C0637DDB20D8D38412CB4153 /* UIImageView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+LookinServer.h"; path = "Src/Main/Server/Category/UIImageView+LookinServer.h"; sourceTree = ""; }; + 313050E8524ED89E2B2CF8F5C1CC7633 /* LKS_AttrGroupsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_AttrGroupsMaker.h; path = Src/Main/Server/Others/LKS_AttrGroupsMaker.h; sourceTree = ""; }; + 317AEF64C0405ADA2DB47569A6D72FC4 /* UIImage+ForceDecode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ForceDecode.h"; path = "SDWebImage/Core/UIImage+ForceDecode.h"; sourceTree = ""; }; + 31C9A23E37AE09BB9DC1BC766BD3A6AA /* JXCategoryImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryImageView.h; path = Sources/Image/JXCategoryImageView.h; sourceTree = ""; }; + 321334B98147E6E64FCE056E3717FEE0 /* SDAssociatedObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAssociatedObject.m; path = SDWebImage/Private/SDAssociatedObject.m; sourceTree = ""; }; + 3259CC7D8EE4331CC9B8A86DA09EA5B3 /* MJRefreshStateHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateHeader.m; path = MJRefresh/Custom/Header/MJRefreshStateHeader.m; sourceTree = ""; }; + 32E665F5EEABCF137D52CE4A3889C9F0 /* LKSConfigManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKSConfigManager.m; path = Src/Main/Server/Others/LKSConfigManager.m; sourceTree = ""; }; + 330AFA4D280CBB2EE073DCC942489EAB /* UIScrollView+Helper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+Helper.m"; path = "Sources/Category/UIScrollView+Helper.m"; sourceTree = ""; }; + 3313EDBDBF7A4CA0DC32526D9ED0B496 /* SDWebImageDefine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDefine.h; path = SDWebImage/Core/SDWebImageDefine.h; sourceTree = ""; }; + 343C42E325F84441C510AF8DEE739ADF /* UIColor+SDHexString.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+SDHexString.m"; path = "SDWebImage/Private/UIColor+SDHexString.m"; sourceTree = ""; }; + 347DA9A1002297848F6BF9D97BB1F302 /* MBProgressHUD.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = MBProgressHUD.m; sourceTree = ""; }; + 34F0487226F5EBEBA3C6D3E1743C5260 /* NSBezierPath+SDRoundedCorners.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBezierPath+SDRoundedCorners.m"; path = "SDWebImage/Private/NSBezierPath+SDRoundedCorners.m"; sourceTree = ""; }; + 3501E850F701BA678364B4AFBF1C8417 /* SDImageAPNGCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAPNGCoder.h; path = SDWebImage/Core/SDImageAPNGCoder.h; sourceTree = ""; }; + 353BBBDE951248D62CFDF267ACFAD0A7 /* FLAnimatedImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImage-prefix.pch"; sourceTree = ""; }; + 35B67A3C0E25A19B996355E03ED4A3CD /* SDWebImageDownloaderOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderOperation.m; path = SDWebImage/Core/SDWebImageDownloaderOperation.m; sourceTree = ""; }; 35BFA337F4E1FDE67C773A82CCDFD6DA /* Pods-keyBoard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-keyBoard.debug.xcconfig"; sourceTree = ""; }; - 364231170128CA2CD3F9589FE34C2FAE /* NSObject+MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJProperty.h"; path = "MJExtension/NSObject+MJProperty.h"; sourceTree = ""; }; - 371FD070C447028E0DC76F07BB442FC4 /* LKS_Helper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_Helper.m; path = Src/Main/Server/Others/LKS_Helper.m; sourceTree = ""; }; - 37559870F51779045F8C7A57C1303E2D /* LKS_InbuiltAttrModificationHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_InbuiltAttrModificationHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.m; sourceTree = ""; }; - 383AEE356898B114D8DD079C51566FF2 /* MJRefreshComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshComponent.h; path = MJRefresh/Base/MJRefreshComponent.h; sourceTree = ""; }; - 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 3996B697C00897DAFE1DFD73DAA4E114 /* UIImageView+HighlightedWebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+HighlightedWebCache.h"; path = "SDWebImage/Core/UIImageView+HighlightedWebCache.h"; sourceTree = ""; }; - 3B6B095661E36C4E8A066559D4D5AF33 /* LookinConnectionResponseAttachment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinConnectionResponseAttachment.m; path = Src/Main/Shared/LookinConnectionResponseAttachment.m; sourceTree = ""; }; - 3BBF905BC343AA0D52B6BC0B1E5B22E9 /* CALayer+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CALayer+Lookin.m"; path = "Src/Main/Shared/Category/CALayer+Lookin.m"; sourceTree = ""; }; - 3BF9DE6E63B2A31CC1EADA84D3E42E7A /* SDWebImageTransition.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageTransition.h; path = SDWebImage/Core/SDWebImageTransition.h; sourceTree = ""; }; - 3C0293D25B82D4CCF17D52B025BDDA03 /* AFAutoPurgingImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFAutoPurgingImageCache.m; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.m"; sourceTree = ""; }; - 3CA1F0AA7C906C09D35E1B3B781EB6E0 /* SDImageCacheDefine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheDefine.h; path = SDWebImage/Core/SDImageCacheDefine.h; sourceTree = ""; }; + 36BEAD7507B8644D14D46C852A6EF20B /* UIView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCache.h"; path = "SDWebImage/Core/UIView+WebCache.h"; sourceTree = ""; }; + 36CBA5AB35EE7DE7B4A5CDBAC4BE20A8 /* AFImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFImageDownloader.h; path = "UIKit+AFNetworking/AFImageDownloader.h"; sourceTree = ""; }; + 371A20C759D3E78183B0BC7EA626FA2D /* LookinObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinObject.h; path = Src/Main/Shared/LookinObject.h; sourceTree = ""; }; + 373258A2F6DFCE8ADD1C1D42DE5EF5D3 /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MultiFormat.m"; path = "SDWebImage/Core/UIImage+MultiFormat.m"; sourceTree = ""; }; + 374CEB5E4CAC5B1889E4B3A57B47546E /* LYEmptyView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LYEmptyView.h; path = LYEmptyView/LYEmptyView.h; sourceTree = ""; }; + 37977014CE5B8A9E93F1EC56C3AC6D52 /* SDAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageView.h; path = SDWebImage/Core/SDAnimatedImageView.h; sourceTree = ""; }; + 37C2A3B1C753D4547646108720BF5321 /* JXCategoryIndicatorComponentView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorComponentView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.h; sourceTree = ""; }; + 38C2193309DE8B485EA6F0495C08B115 /* UIView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MJExtension.h"; path = "MJRefresh/UIView+MJExtension.h"; sourceTree = ""; }; + 38F21B02ED02115E613C152CE563BD5A /* LookinAutoLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAutoLayoutConstraint.m; path = Src/Main/Shared/LookinAutoLayoutConstraint.m; sourceTree = ""; }; + 39267406AD82F75ABB872A20BE14F010 /* LYEmptyView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LYEmptyView.m; path = LYEmptyView/LYEmptyView.m; sourceTree = ""; }; + 39592D3DD29808CC34F5BDE8FFAD64E6 /* LookinAttributeModification.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttributeModification.m; path = Src/Main/Shared/LookinAttributeModification.m; sourceTree = ""; }; + 399102B94B534EB49EE0E5512D150CA8 /* LSTPopView */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = LSTPopView; path = LSTPopView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 39D7BCC784A30383722D127896FE591E /* JXPagingView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = JXPagingView.debug.xcconfig; sourceTree = ""; }; + 39D939E1825294C23871CD06F0A1E6A2 /* JXCategoryBaseView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryBaseView.m; path = Sources/Base/JXCategoryBaseView.m; sourceTree = ""; }; + 3A10B1AFB4B6959F4A11AB1B1BC4A437 /* HWPanModalPresentable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresentable.h; path = Sources/Presentable/HWPanModalPresentable.h; sourceTree = ""; }; + 3A1C13D0C9F5E8ED93D0398C379507C1 /* LookinHierarchyFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinHierarchyFile.m; path = Src/Main/Shared/LookinHierarchyFile.m; sourceTree = ""; }; + 3A9477BE731926B610D9B847EF5B7347 /* NSObject+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+LookinServer.h"; path = "Src/Main/Server/Category/NSObject+LookinServer.h"; sourceTree = ""; }; + 3AF0216318F4C1EBD4207012E5E70EB1 /* JXCategoryDotCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryDotCellModel.m; path = Sources/Dot/JXCategoryDotCellModel.m; sourceTree = ""; }; + 3B250EFB659FBBBBA5D680859085344D /* JXPagerListRefreshView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXPagerListRefreshView.h; path = Sources/JXPagerView/JXPagerListRefreshView.h; sourceTree = ""; }; + 3B812F8DDDC6CC3E3ACDB1D17716E70C /* JXCategoryTitleImageCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleImageCellModel.h; path = Sources/TitleImage/JXCategoryTitleImageCellModel.h; sourceTree = ""; }; + 3C530EFDCDFFC732A409BADBE3F0D068 /* MBProgressHUD.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MBProgressHUD.modulemap; sourceTree = ""; }; + 3C71B9877A51B54673C7FFC0C3276863 /* MJRefreshConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConfig.m; path = MJRefresh/MJRefreshConfig.m; sourceTree = ""; }; + 3CA454A209E71894BC9366B10B95D086 /* LKS_Helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_Helper.h; path = Src/Main/Server/Others/LKS_Helper.h; sourceTree = ""; }; 3CB13D51E717D347023EEB57263E3072 /* Pods-CustomKeyboard-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CustomKeyboard-dummy.m"; sourceTree = ""; }; - 3CF065C3DEDD146A59230103D73E1A55 /* LookinServer.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LookinServer.modulemap; sourceTree = ""; }; - 3D64DD7369F8D81EDC16FC3539F46D73 /* UIImage+GIF.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+GIF.m"; path = "SDWebImage/Core/UIImage+GIF.m"; sourceTree = ""; }; - 3D6CF72BA8B7618D0238AD641B57FE35 /* SDImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCache.m; path = SDWebImage/Core/SDImageCache.m; sourceTree = ""; }; - 3D7966DEA2CA0101B9FC2C01A1A2909B /* SDAssociatedObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAssociatedObject.m; path = SDWebImage/Private/SDAssociatedObject.m; sourceTree = ""; }; - 3D891833337A0E2AFA0DBB31899C747F /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; - 3DD65B80E7AA07416BB8F502F3C3A438 /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; - 3DDB2F652BC38BC05396DCC9F34040CD /* MJRefreshStateTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h; sourceTree = ""; }; - 3E2A55F2F78E11DEDCF2FA119B3E1912 /* MJExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.release.xcconfig; sourceTree = ""; }; - 3E2B86406A2B5383183DAE9ABBBB3893 /* LKS_HierarchyDisplayItemsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_HierarchyDisplayItemsMaker.m; path = Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.m; sourceTree = ""; }; - 3E5219BC7E7BF5C405E48CC237D2EDC2 /* NSSet+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSSet+Lookin.m"; path = "Src/Main/Shared/Category/NSSet+Lookin.m"; sourceTree = ""; }; - 3ED91326A0371ACE08A353BC67F60F6B /* NSString+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+Lookin.m"; path = "Src/Main/Shared/Category/NSString+Lookin.m"; sourceTree = ""; }; - 3F39E9FDE611BCC2A514A77F1EB63E8B /* MJPropertyKey.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyKey.m; path = MJExtension/MJPropertyKey.m; sourceTree = ""; }; - 3F61B84FD6B8249C85FCBF56257E34C6 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; - 400DE9B9180EAE02FE3ADA6DB9EFD64F /* LookinServer-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LookinServer-prefix.pch"; sourceTree = ""; }; - 40B6DD67F49B0103232B5D6B727392FA /* LookinAttributesSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttributesSection.h; path = Src/Main/Shared/LookinAttributesSection.h; sourceTree = ""; }; - 4211A99A6EE6255E875FA46E987F2128 /* Lookin_PTUSBHub.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTUSBHub.h; path = Src/Main/Shared/Peertalk/Lookin_PTUSBHub.h; sourceTree = ""; }; - 42189E436FCC0F9F0BAA536F3BF84910 /* SDWebImageCacheSerializer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCacheSerializer.m; path = SDWebImage/Core/SDWebImageCacheSerializer.m; sourceTree = ""; }; - 4223ACF818570B18B88D6B2884075BF1 /* SDFileAttributeHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDFileAttributeHelper.m; path = SDWebImage/Private/SDFileAttributeHelper.m; sourceTree = ""; }; - 426AEC2F7F358DEDB66C3F2D15F925A4 /* MJRefreshBackNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackNormalFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m; sourceTree = ""; }; + 3D72A1C48CB238B4D5F50BA925DEDEAE /* UIColor+JXAdd.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+JXAdd.h"; path = "Sources/Common/UIColor+JXAdd.h"; sourceTree = ""; }; + 3D8A828331C79742A41F54C2050C90A8 /* LookinAppInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAppInfo.h; path = Src/Main/Shared/LookinAppInfo.h; sourceTree = ""; }; + 3DDFB85C3FF1851267A20FACB64B4497 /* LookinCustomDisplayItemInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinCustomDisplayItemInfo.h; path = Src/Main/Shared/LookinCustomDisplayItemInfo.h; sourceTree = ""; }; + 3DF983F1377AD739C3DF33AE51632FCF /* Bugly.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Bugly.debug.xcconfig; sourceTree = ""; }; + 3E05D85B85A84A7D628539AD042EC841 /* Lookin_PTProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTProtocol.h; path = Src/Main/Shared/Peertalk/Lookin_PTProtocol.h; sourceTree = ""; }; + 3E34DAE4904CE87FBB70688EA36DF9D3 /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; + 3ED4F75E10F9C3D76FF139C89BBB8154 /* SDWebImageDownloaderDecryptor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderDecryptor.h; path = SDWebImage/Core/SDWebImageDownloaderDecryptor.h; sourceTree = ""; }; + 3F0DA836C065C821DDDE100A36B1C087 /* HWBackgroundConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWBackgroundConfig.m; path = Sources/View/HWBackgroundConfig.m; sourceTree = ""; }; + 402736588AC9D07AA589F2943BAE3C89 /* SDCallbackQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDCallbackQueue.h; path = SDWebImage/Core/SDCallbackQueue.h; sourceTree = ""; }; + 404BBFC3B5A2ADAEF4E188881B357111 /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; + 406C8D3FB686F0A24482B5EC0964787A /* DZNEmptyDataSet.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = DZNEmptyDataSet.modulemap; sourceTree = ""; }; + 407D327724ADF96791DFD9B922AA254A /* LookinDisplayItemDetail.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDisplayItemDetail.h; path = Src/Main/Shared/LookinDisplayItemDetail.h; sourceTree = ""; }; + 412FD8B68949345873B82E2D0C864C85 /* NSBundle+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBundle+MJRefresh.h"; path = "MJRefresh/NSBundle+MJRefresh.h"; sourceTree = ""; }; + 41B61F60FDADCD1988F2A5F1B93F6FB0 /* AFImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFImageDownloader.m; path = "UIKit+AFNetworking/AFImageDownloader.m"; sourceTree = ""; }; + 4201C2CD51C00E5AC0EC45DC41B32695 /* HWPanModal.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HWPanModal.debug.xcconfig; sourceTree = ""; }; + 4228538168305A12A3465600D6FA372A /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; + 429004AF40A48DE835234068590E6A94 /* UIImage+Metadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Metadata.h"; path = "SDWebImage/Core/UIImage+Metadata.h"; sourceTree = ""; }; + 438B056E0DAE53D40DB4894FF36879AF /* LookinServer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LookinServer.release.xcconfig; sourceTree = ""; }; + 43901AAA2BB40AE5F534540676833E30 /* UIView+WebCacheOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheOperation.m"; path = "SDWebImage/Core/UIView+WebCacheOperation.m"; sourceTree = ""; }; + 43BA7B9A75BE654B8242649314595C2D /* JXCategoryTitleVerticalZoomView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleVerticalZoomView.m; path = Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.m; sourceTree = ""; }; + 43E163147E40F868F458CD979D77C4E4 /* MJExtension-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJExtension-dummy.m"; sourceTree = ""; }; 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "MJExtension-MJExtension"; path = MJExtension.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 45DC3F40C3A1FA5B5920DED3DF89557C /* UIView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MJExtension.m"; path = "MJRefresh/UIView+MJExtension.m"; sourceTree = ""; }; - 45EDC4788D38048F75B7F3CD0BEF1783 /* MJRefresh.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.release.xcconfig; sourceTree = ""; }; - 45F43707DFF3E5A8EFA1404F7259F5DF /* NSObject+MJCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJCoding.m"; path = "MJExtension/NSObject+MJCoding.m"; sourceTree = ""; }; - 46771EF8828C8A7519CEFD7A8DF062BE /* LKS_TraceManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_TraceManager.h; path = Src/Main/Server/Others/LKS_TraceManager.h; sourceTree = ""; }; - 4730B0C65CA50BE6D828887D7CC8EB9F /* LookinCustomAttrModification.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinCustomAttrModification.m; path = Src/Main/Shared/LookinCustomAttrModification.m; sourceTree = ""; }; - 4770EEEC71445F1C55A5C71E32517009 /* SDImageCacheConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheConfig.m; path = SDWebImage/Core/SDImageCacheConfig.m; sourceTree = ""; }; - 477B43B19C3181419CE0D39929320355 /* LKS_AttrModificationPatchHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_AttrModificationPatchHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.h; sourceTree = ""; }; - 47E596E1EB48CB4E8DE37CC0D5122787 /* MJFoundation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJFoundation.m; path = MJExtension/MJFoundation.m; sourceTree = ""; }; - 4819E2A59EFDCF27B3C3DDB40C7B2D13 /* SDWebImageTransition.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageTransition.m; path = SDWebImage/Core/SDWebImageTransition.m; sourceTree = ""; }; - 48A9A2DE85C1D87BCD354418BAF78749 /* SDAnimatedImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "SDAnimatedImageView+WebCache.m"; path = "SDWebImage/Core/SDAnimatedImageView+WebCache.m"; sourceTree = ""; }; - 49A24CBDEFCE6B22E2D355C6D04AC9B4 /* NSArray+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Lookin.m"; path = "Src/Main/Shared/Category/NSArray+Lookin.m"; sourceTree = ""; }; - 4B2A98ADD6BF259F1E366B570C576632 /* LKSConfigManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKSConfigManager.m; path = Src/Main/Server/Others/LKSConfigManager.m; sourceTree = ""; }; - 4C9BF32317317006604613DB6B7E6531 /* MJRefreshConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConfig.m; path = MJRefresh/MJRefreshConfig.m; sourceTree = ""; }; - 4D125D803F381B689272DFC8613DDA9A /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; - 4D2D491E6C287C5C66C4EF6B165E85BD /* SDDeviceHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDeviceHelper.m; path = SDWebImage/Private/SDDeviceHelper.m; sourceTree = ""; }; - 4D47A5312A106ED050240FD5A4E84CE4 /* MJRefresh-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJRefresh-dummy.m"; sourceTree = ""; }; - 4E7FA66C9DDB6507631DF1F179557C4A /* SDGraphicsImageRenderer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDGraphicsImageRenderer.h; path = SDWebImage/Core/SDGraphicsImageRenderer.h; sourceTree = ""; }; - 4FD8426A1028406F5A9C4E27D5C9E76C /* Color+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Color+Lookin.h"; path = "Src/Main/Shared/Category/Color+Lookin.h"; sourceTree = ""; }; - 504A6EFB974AF03849BCBDD8A6C0A198 /* SDWebImage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SDWebImage.modulemap; sourceTree = ""; }; - 5104591E28208BB976FFAD3D7AFA2F58 /* AFNetworking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.debug.xcconfig; sourceTree = ""; }; - 51D6AF1225DCDC66E13DAA2BCB6B1DCF /* ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; sourceTree = ""; }; - 5210B0534D834B2EF86FDFCE90B73F2D /* NSObject+MJKeyValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJKeyValue.h"; path = "MJExtension/NSObject+MJKeyValue.h"; sourceTree = ""; }; - 5212AF1887982114A494FF962BEF5A35 /* LookinConnectionAttachment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinConnectionAttachment.h; path = Src/Main/Shared/LookinConnectionAttachment.h; sourceTree = ""; }; - 5248A2EBBCEB19A0BBFA557B594E2DEA /* SDWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImage.h; path = WebImage/SDWebImage.h; sourceTree = ""; }; - 52832E51BDED300B58102A301664AD5A /* DZNEmptyDataSet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DZNEmptyDataSet.release.xcconfig; sourceTree = ""; }; - 528C15198BF77FCE909FB6A717EA8C53 /* LookinAutoLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAutoLayoutConstraint.m; path = Src/Main/Shared/LookinAutoLayoutConstraint.m; sourceTree = ""; }; - 52CE89D1B7CAF7D6D1E509FE1267800A /* DZNEmptyDataSet-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DZNEmptyDataSet-dummy.m"; sourceTree = ""; }; - 52EF359F996014A062F3A2945F10438A /* NSString+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+Lookin.h"; path = "Src/Main/Shared/Category/NSString+Lookin.h"; sourceTree = ""; }; - 52FBF3084E82AF80B1B017FB5240AF4F /* LKS_HierarchyDisplayItemsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_HierarchyDisplayItemsMaker.h; path = Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.h; sourceTree = ""; }; + 449CCE39A5A9EA789B9A284113D1025E /* SDImageFramePool.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageFramePool.h; path = SDWebImage/Private/SDImageFramePool.h; sourceTree = ""; }; + 44B0B0F109E74E6F92B6497967BCE536 /* LookinCustomDisplayItemInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinCustomDisplayItemInfo.m; path = Src/Main/Shared/LookinCustomDisplayItemInfo.m; sourceTree = ""; }; + 452754C8CDFE17EC42C563B4B6E1F69A /* SDImageFrame.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageFrame.m; path = SDWebImage/Core/SDImageFrame.m; sourceTree = ""; }; + 4531FCCC5DE7D00D6F827809F7CD4289 /* MJExtension-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-prefix.pch"; sourceTree = ""; }; + 453FB14441528B4AE2CF3592D5874C54 /* HWPanContainerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanContainerView.m; path = Sources/View/HWPanContainerView.m; sourceTree = ""; }; + 45E71D8592674E85D7D5DA4831A592BE /* JXCategoryBaseView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryBaseView.h; path = Sources/Base/JXCategoryBaseView.h; sourceTree = ""; }; + 45FCB10C5ADD911EC17F1E6BAAFE9892 /* UIScrollView+EmptyDataSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+EmptyDataSet.m"; path = "Source/UIScrollView+EmptyDataSet.m"; sourceTree = ""; }; + 469576EF612EDF18C057B4FB1E423192 /* LookinServer-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LookinServer-umbrella.h"; sourceTree = ""; }; + 46F71F9F19999F6D4F186847FA3CC8F7 /* SDGraphicsImageRenderer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDGraphicsImageRenderer.m; path = SDWebImage/Core/SDGraphicsImageRenderer.m; sourceTree = ""; }; + 47A97040129EEE8B96AEEA0A9B73DA45 /* HWPanModalInteractiveAnimator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalInteractiveAnimator.h; path = Sources/Animator/HWPanModalInteractiveAnimator.h; sourceTree = ""; }; + 4883D2BC668CDDE38C319AC414885077 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; + 48A816CF0BA23EA39A514E31ED98C5D3 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; + 48E1ED2BAC3C5C1B077AAB67F3325D4E /* DZNEmptyDataSet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DZNEmptyDataSet.debug.xcconfig; sourceTree = ""; }; + 4A15AB0AB6FCF1589E2A6CEDC3CF0B95 /* HWPanIndicatorView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanIndicatorView.h; path = Sources/View/HWPanIndicatorView.h; sourceTree = ""; }; + 4A2BDE1ACE119E645C72F92B4CCAECF4 /* NSObject+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+Lookin.h"; path = "Src/Main/Shared/Category/NSObject+Lookin.h"; sourceTree = ""; }; + 4A4AE7A504C340AE8EE98F70C318D63C /* Masonry.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.release.xcconfig; sourceTree = ""; }; + 4AAF4EE016C54A7F264F9B8FBB0853C8 /* NSArray+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Lookin.m"; path = "Src/Main/Shared/Category/NSArray+Lookin.m"; sourceTree = ""; }; + 4B2681504ECC11F7B0563ECF0A1FDDFA /* Color+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "Color+Lookin.m"; path = "Src/Main/Shared/Category/Color+Lookin.m"; sourceTree = ""; }; + 4B6F5F5F32C55F6B9F4E87EC57A0A074 /* Lookin_PTProtocol.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Lookin_PTProtocol.m; path = Src/Main/Shared/Peertalk/Lookin_PTProtocol.m; sourceTree = ""; }; + 4BC98580A0BA844CDD661F01812A35C7 /* SDWebImageDownloaderResponseModifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderResponseModifier.m; path = SDWebImage/Core/SDWebImageDownloaderResponseModifier.m; sourceTree = ""; }; + 4C354F545C0CC91C4033DC0D648B3819 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; + 4C7F47A09BE728487DF546FE00CA555E /* UIViewController+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+LookinServer.h"; path = "Src/Main/Server/Category/UIViewController+LookinServer.h"; sourceTree = ""; }; + 4D2B4D757199E020DE43661B60EB2819 /* LKS_Helper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_Helper.m; path = Src/Main/Server/Others/LKS_Helper.m; sourceTree = ""; }; + 4EBFFAE4CE0471C78DB70755CFCC7609 /* HWPanModalPresentationDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresentationDelegate.h; path = Sources/Delegate/HWPanModalPresentationDelegate.h; sourceTree = ""; }; + 4F8D39C76EB84B28054B453882C78E41 /* LookinAttributesSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttributesSection.m; path = Src/Main/Shared/LookinAttributesSection.m; sourceTree = ""; }; + 4F973225F70967D6C01DF18ABCACA3C4 /* HWPanModal-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HWPanModal-prefix.pch"; sourceTree = ""; }; + 5048CCD1406058B50480C383463B3C39 /* LYEmptyView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LYEmptyView.debug.xcconfig; sourceTree = ""; }; + 5105F32D29B4C0D80B780EE2DF6D2898 /* JXCategoryTitleView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleView.h; path = Sources/Title/JXCategoryTitleView.h; sourceTree = ""; }; + 513C1A2EE22268DD51EB02AE24E3B579 /* HWPanModalShadow.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalShadow.m; path = Sources/View/HWPanModalShadow.m; sourceTree = ""; }; + 517D8EDC9F4BA34E4E4060247125B56D /* UIImage+MultiFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MultiFormat.h"; path = "SDWebImage/Core/UIImage+MultiFormat.h"; sourceTree = ""; }; + 517EACA3BDCA2E1CB5B954656D4B9F02 /* LYEmptyView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LYEmptyView-prefix.pch"; sourceTree = ""; }; + 51AB8F5FA4517AC80D7763B2894462EB /* LKS_EventHandlerMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_EventHandlerMaker.h; path = Src/Main/Server/Others/LKS_EventHandlerMaker.h; sourceTree = ""; }; + 524557CADCF9674C470A7B1764594AEC /* JXCategoryTitleImageCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleImageCell.h; path = Sources/TitleImage/JXCategoryTitleImageCell.h; sourceTree = ""; }; + 526BF014AFB62CD2E2E5312B573388BC /* JXCategoryView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = JXCategoryView.modulemap; sourceTree = ""; }; + 52AF8374431A1EA8420BA1E29139131E /* LKS_TraceManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_TraceManager.h; path = Src/Main/Server/Others/LKS_TraceManager.h; sourceTree = ""; }; + 52FF07E10C8C0B816653B6836CCFFD04 /* LKS_CustomAttrGroupsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomAttrGroupsMaker.h; path = Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.h; sourceTree = ""; }; + 53155231B4EB5B29274A0546D6F39B91 /* NSButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSButton+WebCache.m"; path = "SDWebImage/Core/NSButton+WebCache.m"; sourceTree = ""; }; 5327DD01C6533D102D66E1636B3827F3 /* Pods-keyBoard-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-keyBoard-acknowledgements.plist"; sourceTree = ""; }; - 54354678DA42B275327F1EABDD57F9BD /* SDWebImageIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageIndicator.m; path = SDWebImage/Core/SDWebImageIndicator.m; sourceTree = ""; }; - 567AA7AB9514E985494C554A1802C03B /* LKS_Helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_Helper.h; path = Src/Main/Server/Others/LKS_Helper.h; sourceTree = ""; }; - 56A3EB69345768D61D52161327AE66C8 /* LookinHierarchyInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinHierarchyInfo.m; path = Src/Main/Shared/LookinHierarchyInfo.m; sourceTree = ""; }; - 57BCCC946B3042A20D0C8F15D69FF943 /* MJExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.debug.xcconfig; sourceTree = ""; }; - 58AA57BAA26D8C03E401EEFD3C78271F /* MJRefreshBackStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackStateFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h; sourceTree = ""; }; - 5932D997195DFCB258D366D038A56978 /* MJRefreshNormalHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalHeader.h; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.h; sourceTree = ""; }; - 594925FC6BBDEA3002D153F167630F93 /* UIVisualEffectView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIVisualEffectView+LookinServer.h"; path = "Src/Main/Server/Category/UIVisualEffectView+LookinServer.h"; sourceTree = ""; }; - 594BEBF4113035634E37CC4FC2A11D62 /* LookinAttributesGroup.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttributesGroup.m; path = Src/Main/Shared/LookinAttributesGroup.m; sourceTree = ""; }; - 5989AAAB35D0B7EF697456F3897FACEC /* MJRefreshHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshHeader.m; path = MJRefresh/Base/MJRefreshHeader.m; sourceTree = ""; }; - 5998234B9DD3C83BCD1DE88EDDEA5DF6 /* SDWebImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.debug.xcconfig; sourceTree = ""; }; - 599EA7E2BEEE9D88C43DF182C6A874D1 /* SDFileAttributeHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDFileAttributeHelper.h; path = SDWebImage/Private/SDFileAttributeHelper.h; sourceTree = ""; }; - 59AE847A100A8834951E42690C982455 /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; - 59D0E9B54F4868B1B1BDE17140B78250 /* SDMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDMemoryCache.m; path = SDWebImage/Core/SDMemoryCache.m; sourceTree = ""; }; - 5ABD1279233951A8EAE905C43AD033A4 /* LKS_ConnectionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_ConnectionManager.m; path = Src/Main/Server/Connection/LKS_ConnectionManager.m; sourceTree = ""; }; - 5AE5F5B6D6DAD0B45FC2D30EE6FBEE81 /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; - 5AF7E49BBE304E0327E319036BE5671B /* UIViewController+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+LookinServer.m"; path = "Src/Main/Server/Category/UIViewController+LookinServer.m"; sourceTree = ""; }; - 5B993C5AF69BCC11CB58D180BE7475BE /* NSImage+Compatibility.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSImage+Compatibility.m"; path = "SDWebImage/Core/NSImage+Compatibility.m"; sourceTree = ""; }; - 5C0CAD4F0394CDAF40054888E02EB093 /* SDImageIOAnimatedCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageIOAnimatedCoder.m; path = SDWebImage/Core/SDImageIOAnimatedCoder.m; sourceTree = ""; }; - 5C457050D64C2C7287BDFC768D33C9AE /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; - 5C7AE763582816CA9E57C0D78A7D1A49 /* SDWebImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageManager.h; path = SDWebImage/Core/SDWebImageManager.h; sourceTree = ""; }; - 5CAEE17C08505E0DF4A1EF22D4CAD064 /* MJExtension-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJExtension-Info.plist"; sourceTree = ""; }; + 541552D5AA99C6DF3406BD050E1467DB /* AFNetworking-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "AFNetworking-Info.plist"; sourceTree = ""; }; + 55488AFE93BF97340EF80D0D6C1E2CA0 /* SDImageHEICCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageHEICCoder.h; path = SDWebImage/Core/SDImageHEICCoder.h; sourceTree = ""; }; + 5633AC0E53EEE3085AFE9CB101E6C0CF /* JXCategoryNumberCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryNumberCellModel.m; path = Sources/Number/JXCategoryNumberCellModel.m; sourceTree = ""; }; + 568F43CF567335FABEC4825ED4776B19 /* HWPanModalShadow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalShadow.h; path = Sources/View/HWPanModalShadow.h; sourceTree = ""; }; + 56F54F2E70EF1B4C4CD6CC49471EBF8F /* JXPagingView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = JXPagingView.modulemap; sourceTree = ""; }; + 570A4EA50A989D93BDAC90837E4F3637 /* JXCategoryImageCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryImageCellModel.m; path = Sources/Image/JXCategoryImageCellModel.m; sourceTree = ""; }; + 572433DB55AF2085E2E4D419FCE37679 /* MJRefreshTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshTrailer.h; path = MJRefresh/Base/MJRefreshTrailer.h; sourceTree = ""; }; + 57460121EED43E41D624C46A92FE9E08 /* JXPagerListContainerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXPagerListContainerView.h; path = Sources/JXPagerView/JXPagerListContainerView.h; sourceTree = ""; }; + 57A3558C23C0EFA92D7C80FBF8A6332A /* MJPropertyKey.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyKey.m; path = MJExtension/MJPropertyKey.m; sourceTree = ""; }; + 57B2E23309380B0E15F50C277205AC0D /* AFNetworking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.release.xcconfig; sourceTree = ""; }; + 59720B9654BC9C6EC9F2FF79FB3FEB5A /* HWPanModal.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HWPanModal.modulemap; sourceTree = ""; }; + 5978BDDC6A977C5D014B3D0CC0294043 /* SDWebImage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SDWebImage.modulemap; sourceTree = ""; }; + 59CF9D4B8C92110B4BC1E1792E4AAEA5 /* SDWebImageTransition.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageTransition.h; path = SDWebImage/Core/SDWebImageTransition.h; sourceTree = ""; }; + 5B758502F7753329D591359BA2747831 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; + 5B766998FBEAD558A15F06134D5A9335 /* JXCategoryIndicatorTriangleView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorTriangleView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.h; sourceTree = ""; }; + 5C64D6AC35DE27CAD74CA154541AF1C9 /* MJRefreshTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshTrailer.m; path = MJRefresh/Base/MJRefreshTrailer.m; sourceTree = ""; }; + 5C847B3748FF7761203F8DDBD028D651 /* LookinServer-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LookinServer-prefix.pch"; sourceTree = ""; }; + 5CB6F43E2EFE165260D66B0BFF9A8831 /* JXCategoryImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryImageView.m; path = Sources/Image/JXCategoryImageView.m; sourceTree = ""; }; + 5CB726B6B5C83EAABA9AC89E76D45643 /* DZNEmptyDataSet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DZNEmptyDataSet.release.xcconfig; sourceTree = ""; }; + 5D2F2FDA20E8BC9884D1E9ED05D83DDF /* UITextField+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextField+LookinServer.h"; path = "Src/Main/Server/Category/UITextField+LookinServer.h"; sourceTree = ""; }; 5DA4577FE3BC4A03751108FFED07B385 /* DZNEmptyDataSet */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DZNEmptyDataSet; path = DZNEmptyDataSet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E0CFDE214ACE5F071E4BEEF63BDDCD6 /* SDImageAssetManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAssetManager.h; path = SDWebImage/Private/SDImageAssetManager.h; sourceTree = ""; }; - 5E355B215CED31C4C6EF33EEB9E95B38 /* LKS_HierarchyDetailsHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_HierarchyDetailsHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.h; sourceTree = ""; }; - 5E83988FA8D9C00FAEEA94EE0633C2C5 /* SDWebImagePrefetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImagePrefetcher.h; path = SDWebImage/Core/SDWebImagePrefetcher.h; sourceTree = ""; }; - 5F52BB443191BF5EA87C6419E4BAFFD5 /* SDDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDiskCache.h; path = SDWebImage/Core/SDDiskCache.h; sourceTree = ""; }; - 613A0EC29C46AFB409483355C45FE1C7 /* NSButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSButton+WebCache.m"; path = "SDWebImage/Core/NSButton+WebCache.m"; sourceTree = ""; }; - 613D22FE29FDFD98F1BA3415B19FB040 /* LKS_ConnectionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_ConnectionManager.h; path = Src/Main/Server/Connection/LKS_ConnectionManager.h; sourceTree = ""; }; - 615CFF22184D20B3B6107165A49D6FEF /* UIButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+WebCache.h"; path = "SDWebImage/Core/UIButton+WebCache.h"; sourceTree = ""; }; - 61A50E7751555885AEB4247687F5DF05 /* DZNEmptyDataSet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DZNEmptyDataSet.debug.xcconfig; sourceTree = ""; }; - 61AA277CF1084D31AAA460D8C1A9BE4E /* UIView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MJExtension.h"; path = "MJRefresh/UIView+MJExtension.h"; sourceTree = ""; }; - 61E1874601B077A6F69725D9EF8827B1 /* MBProgressHUD.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MBProgressHUD.modulemap; sourceTree = ""; }; - 6289794567935CA3DC8B5C49AEA74043 /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; - 62E02B7B42A91CD6887912774FAE6528 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; - 63B2D397715E1B3990E46DFCAE0A73D5 /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; + 5DC759BB8D0141E0F064F3BCA7197315 /* MBProgressHUD.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = MBProgressHUD.h; sourceTree = ""; }; + 5E5C516541F7C7AC40E990C05307FEEF /* UIImage+Metadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Metadata.m"; path = "SDWebImage/Core/UIImage+Metadata.m"; sourceTree = ""; }; + 5E9C6ED309FB0F6481FF6639AA9C417B /* MJRefreshComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshComponent.h; path = MJRefresh/Base/MJRefreshComponent.h; sourceTree = ""; }; + 5EA970CCF2164DC59ECEE9DE06B1BCBA /* SDImageGraphics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageGraphics.h; path = SDWebImage/Core/SDImageGraphics.h; sourceTree = ""; }; + 5EADC8693C7692FBBE4CE165F51B28E9 /* JXCategoryTitleImageCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleImageCell.m; path = Sources/TitleImage/JXCategoryTitleImageCell.m; sourceTree = ""; }; + 5EE479D553AE99C7C893E8B21299B3AC /* JXCategoryIndicatorBackgroundView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorBackgroundView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.h; sourceTree = ""; }; + 5EF3B546633CC3DB26A173DE519AC3D7 /* SDImageCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCoder.h; path = SDWebImage/Core/SDImageCoder.h; sourceTree = ""; }; + 5EFCD05B81004D2C239BFBEBEE4DC3D5 /* JXCategoryIndicatorCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorCellModel.h; path = Sources/Indicator/JXCategoryIndicatorCellModel.h; sourceTree = ""; }; + 60195DBDE404C5ECBC4E710D0F5E50E7 /* UIImage+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+LookinServer.h"; path = "Src/Main/Server/Category/UIImage+LookinServer.h"; sourceTree = ""; }; + 6021531912761F1BDBFE14A61784B26D /* MJRefreshAutoNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoNormalFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m; sourceTree = ""; }; + 60696FE70F42B1A0CD7B0614C2A2F16C /* UIView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MJExtension.m"; path = "MJRefresh/UIView+MJExtension.m"; sourceTree = ""; }; + 607560CCA2D3766D85B5AEE557812D0E /* SDWebImageDownloaderRequestModifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderRequestModifier.m; path = SDWebImage/Core/SDWebImageDownloaderRequestModifier.m; sourceTree = ""; }; + 6099FBA2A3EE3D602B49D82E19FA5875 /* SDWebImagePrefetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImagePrefetcher.h; path = SDWebImage/Core/SDWebImagePrefetcher.h; sourceTree = ""; }; + 60F9066C601EE11D24D22C170F05AF13 /* LookinWeakContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinWeakContainer.m; path = Src/Main/Shared/LookinWeakContainer.m; sourceTree = ""; }; + 6148399DD529311A930CEF2A2AC2FBD4 /* LookinIvarTrace.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinIvarTrace.m; path = Src/Base/LookinIvarTrace.m; sourceTree = ""; }; + 616DFB551B9EEC8F4D98DBDC3C2543CA /* MJExtension.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJExtension.modulemap; sourceTree = ""; }; + 61C0CC288A628CFA871D599D497E2A8E /* SDWebImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SDWebImage-dummy.m"; sourceTree = ""; }; + 61D65BB6AAD351E64F3FE46FACDEED4F /* MJRefreshNormalHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalHeader.m; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.m; sourceTree = ""; }; + 6331F4B8E0F66A8F7B8028B33CF71268 /* LSTTimer.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LSTTimer.modulemap; sourceTree = ""; }; + 633C3F66E9BA0FD7538C55D5287ED77E /* LSTPopView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LSTPopView.m; path = LSTPopView/Classes/Code/LSTPopView.m; sourceTree = ""; }; + 634119E1E65F912498A262851F72517B /* Bugly.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Bugly.framework; sourceTree = ""; }; + 638488B4F5FF9C67F848A841B1A34765 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + 63A3BD4651AA1DDCB216ABB7FBC3A69E /* MJRefreshConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConst.h; path = MJRefresh/MJRefreshConst.h; sourceTree = ""; }; 641251D3092FFCF2B6259BF8676A212E /* Pods-CustomKeyboard-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CustomKeyboard-Info.plist"; sourceTree = ""; }; - 650740D8E20A30E70F588321BC583BBC /* MJRefresh-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-prefix.pch"; sourceTree = ""; }; - 667106A3B29FC2624F444E79272C8235 /* LKS_CustomAttrGroupsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomAttrGroupsMaker.m; path = Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.m; sourceTree = ""; }; - 67A65AF14731E6A6CF631892AB163C2D /* SDImageHEICCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageHEICCoder.h; path = SDWebImage/Core/SDImageHEICCoder.h; sourceTree = ""; }; - 68C023D8DAEB5C5E7F36F7020DDBFE63 /* LKS_RequestHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_RequestHandler.m; path = Src/Main/Server/Connection/LKS_RequestHandler.m; sourceTree = ""; }; - 6A2C339DB0F9EF94544BE6FCDA59F50F /* MJRefreshStateTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m; sourceTree = ""; }; - 6A6FA79B39689AE1D69FBABCD4BB8F7B /* MBProgressHUD-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-prefix.pch"; sourceTree = ""; }; - 6B21CBEE99C5014F0E0F66C420497FCD /* SDAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageView.m; path = SDWebImage/Core/SDAnimatedImageView.m; sourceTree = ""; }; - 6CAEA0BC49D62C0D220FA986A5391EEC /* UIImageView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+LookinServer.h"; path = "Src/Main/Server/Category/UIImageView+LookinServer.h"; sourceTree = ""; }; - 6D30CE312289056E4C5788AB47438FED /* SDAnimatedImagePlayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImagePlayer.m; path = SDWebImage/Core/SDAnimatedImagePlayer.m; sourceTree = ""; }; - 6DAD9E82D42212E9D52E28737BC21479 /* LookinHierarchyFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinHierarchyFile.h; path = Src/Main/Shared/LookinHierarchyFile.h; sourceTree = ""; }; - 6E49D88BA109001AA94CB4B1CBCC6353 /* MJRefreshAutoGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoGifFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m; sourceTree = ""; }; - 6E6089EEBB83334AD3EFA96BE408F86D /* LookinDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDefines.h; path = Src/Main/Shared/LookinDefines.h; sourceTree = ""; }; - 6F10AABF341F29547C8D1C780B3F8861 /* LKS_CustomDisplayItemsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomDisplayItemsMaker.h; path = Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.h; sourceTree = ""; }; - 6FD83C0A67C6DD93C76CB6563151D889 /* LKSConfigManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKSConfigManager.h; path = Src/Main/Server/Others/LKSConfigManager.h; sourceTree = ""; }; - 70E91E9355FAF7D2A8CA2A2112F06A60 /* Bugly.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Bugly.framework; sourceTree = ""; }; - 713E37659AD7D79DA6664C3D3ECF01F7 /* LookinDashboardBlueprint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDashboardBlueprint.h; path = Src/Main/Shared/LookinDashboardBlueprint.h; sourceTree = ""; }; - 71BB52034FF7403843EE79E4975D6D70 /* UIImage+ExtendedCacheData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ExtendedCacheData.m"; path = "SDWebImage/Core/UIImage+ExtendedCacheData.m"; sourceTree = ""; }; - 71C7BAB63ED44B881A65C001AA682ADB /* MBProgressHUD.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.release.xcconfig; sourceTree = ""; }; - 743C4A42055B7373FB20F646193D0919 /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; - 7584B9C7664B986D7C6582FD3280C473 /* UITableView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITableView+LookinServer.m"; path = "Src/Main/Server/Category/UITableView+LookinServer.m"; sourceTree = ""; }; - 7597119135479FEF90DC7CA9DDBF03A6 /* LookinDisplayItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDisplayItem.h; path = Src/Main/Shared/LookinDisplayItem.h; sourceTree = ""; }; - 75E99E8BA24E841D85C9E942E3654D62 /* LookinAttrIdentifiers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttrIdentifiers.m; path = Src/Main/Shared/LookinAttrIdentifiers.m; sourceTree = ""; }; - 785DDFE2F3C7BA8AEDE2278087F506EB /* LookinWeakContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinWeakContainer.h; path = Src/Main/Shared/LookinWeakContainer.h; sourceTree = ""; }; - 79462E533AFF776B12B799A128AA5EE8 /* SDmetamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDmetamacros.h; path = SDWebImage/Private/SDmetamacros.h; sourceTree = ""; }; - 794882B4F91B9E9B55DD3DF40E04DA22 /* SDWebImageCacheSerializer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCacheSerializer.h; path = SDWebImage/Core/SDWebImageCacheSerializer.h; sourceTree = ""; }; - 79803C4DAA3D0FB997F7A51AB226B9D7 /* ResourceBundle-SDWebImage-SDWebImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SDWebImage-SDWebImage-Info.plist"; sourceTree = ""; }; - 79E1EEF42DE5E1954630A63B8A5E02B6 /* MJRefreshAutoNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoNormalFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m; sourceTree = ""; }; - 79EEB00E9ED2C742987150EA5E0B1341 /* LKS_AttrModificationPatchHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_AttrModificationPatchHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.m; sourceTree = ""; }; - 7B54AFD2BD6CA59B1C3B03B1146FE77F /* UIImage+ExtendedCacheData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ExtendedCacheData.h"; path = "SDWebImage/Core/UIImage+ExtendedCacheData.h"; sourceTree = ""; }; - 7BA0DD426F8305DA317D708459ABA12F /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; - 7CB82C5681E372AE74735E8F3B7211E5 /* LKS_EventHandlerMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_EventHandlerMaker.m; path = Src/Main/Server/Others/LKS_EventHandlerMaker.m; sourceTree = ""; }; - 7CBB9E2731CD9B8F896AD9F7398CD3F6 /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MultiFormat.m"; path = "SDWebImage/Core/UIImage+MultiFormat.m"; sourceTree = ""; }; - 7D45408149C7FF7C3CD91B6DDBFB7448 /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; - 7D5B144E69C677553A95B3CCA57BC43C /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; - 7DBD5C23623A08CDD875999AA28A1F8D /* NSData+ImageContentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+ImageContentType.h"; path = "SDWebImage/Core/NSData+ImageContentType.h"; sourceTree = ""; }; - 7DDE67F73A61A7328413374AFFA92E85 /* LookinStaticAsyncUpdateTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinStaticAsyncUpdateTask.m; path = Src/Main/Shared/LookinStaticAsyncUpdateTask.m; sourceTree = ""; }; + 64D49E5BC4A3E2ECFAA63B66E38A6F8D /* FLAnimatedImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FLAnimatedImage-Info.plist"; sourceTree = ""; }; + 6516BB90D0CA47F75712B356350A9FC1 /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; + 6523AFC889399B6B25C08CCBEEE2F0B6 /* DZNEmptyDataSet-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DZNEmptyDataSet-umbrella.h"; sourceTree = ""; }; + 657631264951C7514A1788B1C6316E7F /* CALayer+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CALayer+Lookin.m"; path = "Src/Main/Shared/Category/CALayer+Lookin.m"; sourceTree = ""; }; + 659E098AEC86E789470E344EB23EC1DD /* JXPagerListRefreshView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXPagerListRefreshView.m; path = Sources/JXPagerView/JXPagerListRefreshView.m; sourceTree = ""; }; + 65CCB6F10EC6B284E771B999975CE0B0 /* MJExtensionConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtensionConst.h; path = MJExtension/MJExtensionConst.h; sourceTree = ""; }; + 6650E50E5FAFFD61FC973E5A0D5C8398 /* SDWebImageDownloaderConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderConfig.m; path = SDWebImage/Core/SDWebImageDownloaderConfig.m; sourceTree = ""; }; + 66E849825D4B5783372753D6820DE97F /* MJRefreshHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshHeader.m; path = MJRefresh/Base/MJRefreshHeader.m; sourceTree = ""; }; + 673C80521DE4F20FDE3E9A82E6EBEC53 /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; + 674659ECD497CB56B02FD385F68621CA /* SDAnimatedImageRep.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageRep.h; path = SDWebImage/Core/SDAnimatedImageRep.h; sourceTree = ""; }; + 6757029D58C1BFD772BCC87D14A52E39 /* UIView+LSTPV.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+LSTPV.h"; path = "LSTPopView/Classes/Code/UIView+LSTPV.h"; sourceTree = ""; }; + 68AAA13D71385283DB69A35327BC2F47 /* LSTTimer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LSTTimer.h; path = LSTTimer/Classes/LSTTimer.h; sourceTree = ""; }; + 6A2E7581F1DA07EBD6D2568091FCCB71 /* MJRefresh-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-umbrella.h"; sourceTree = ""; }; + 6A41E1A305241C5A627FAD06CB90A275 /* SDImageCachesManagerOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCachesManagerOperation.h; path = SDWebImage/Private/SDImageCachesManagerOperation.h; sourceTree = ""; }; + 6AB6F2617132C99A6B5CB953305CCA89 /* LookinDashboardBlueprint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDashboardBlueprint.h; path = Src/Main/Shared/LookinDashboardBlueprint.h; sourceTree = ""; }; + 6B94BD4B7CE09D63E43117EFC4B15D0D /* UIScrollView+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJRefresh.m"; path = "MJRefresh/UIScrollView+MJRefresh.m"; sourceTree = ""; }; + 6BD04BB450562622E215B33554778CC3 /* LSTPopView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LSTPopView.release.xcconfig; sourceTree = ""; }; + 6BD526972490CFC41EE7106FF8E272CC /* UILabel+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UILabel+LookinServer.m"; path = "Src/Main/Server/Category/UILabel+LookinServer.m"; sourceTree = ""; }; + 6C1E503B34448DC968FB5BDFADFAE70F /* SDAnimatedImagePlayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImagePlayer.h; path = SDWebImage/Core/SDAnimatedImagePlayer.h; sourceTree = ""; }; + 6C9E32D40F89FB7470530B4F8AAB6162 /* MJRefreshComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshComponent.m; path = MJRefresh/Base/MJRefreshComponent.m; sourceTree = ""; }; + 6CE98E2FC8B92A0E98F20755C88122A4 /* LSTTimer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LSTTimer.debug.xcconfig; sourceTree = ""; }; + 6D00FB0A2824B0B4E8A345D97C52AA3B /* LookinServer-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LookinServer-dummy.m"; sourceTree = ""; }; + 6D149C2EB765D348E439D96EC2A80A04 /* NSObject+MJClass.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJClass.m"; path = "MJExtension/NSObject+MJClass.m"; sourceTree = ""; }; + 6D8BE2762FA18EF88A5BAD861C739B02 /* SDImageFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageFrame.h; path = SDWebImage/Core/SDImageFrame.h; sourceTree = ""; }; + 6DE6908A836615F946533A6FEE623373 /* MJRefreshNormalTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m; sourceTree = ""; }; + 6EAD8B1C822E0F2BAB884329D798190B /* SDImageTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageTransformer.h; path = SDWebImage/Core/SDImageTransformer.h; sourceTree = ""; }; + 6EB329DC3D8A252CA69C19DAF330A784 /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; + 6EE8AE5699FC4ACD4283D4626ACDF742 /* LookinDisplayItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDisplayItem.h; path = Src/Main/Shared/LookinDisplayItem.h; sourceTree = ""; }; + 6F1245D39980C8CC23C4FFA557C72FA3 /* SDWebImageDownloaderResponseModifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderResponseModifier.h; path = SDWebImage/Core/SDWebImageDownloaderResponseModifier.h; sourceTree = ""; }; + 6FD544A644986722B86F15A292995457 /* JXCategoryBaseCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryBaseCell.m; path = Sources/Base/JXCategoryBaseCell.m; sourceTree = ""; }; + 70021D526E8906DE61E9D2D0F92A78C3 /* UICollectionViewLayout+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionViewLayout+MJRefresh.h"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.h"; sourceTree = ""; }; + 7083FA062632CC52050FC4EB53D64E3A /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; + 70CD4567ACE296214EA982091E2B8F90 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; + 70D52E1253BDF6EF05A1C5C1D46734EA /* Peertalk.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Peertalk.h; path = Src/Main/Shared/Peertalk/Peertalk.h; sourceTree = ""; }; + 72B1B153E1909E0A9DFA6E6097FD363D /* JXCategoryBaseCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryBaseCell.h; path = Sources/Base/JXCategoryBaseCell.h; sourceTree = ""; }; + 72CEA2C3193763834CD0E25D8DB88F2D /* SDFileAttributeHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDFileAttributeHelper.m; path = SDWebImage/Private/SDFileAttributeHelper.m; sourceTree = ""; }; + 731A2E2A09E554B786F7BD8D9285D1CC /* UIButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+WebCache.h"; path = "SDWebImage/Core/UIButton+WebCache.h"; sourceTree = ""; }; + 7376537428F41B571A3D20FF9175747F /* LookinServer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LookinServer.debug.xcconfig; sourceTree = ""; }; + 73A2C1D7BD2A650246BEE1A00F6D836C /* LookinDashboardBlueprint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinDashboardBlueprint.m; path = Src/Main/Shared/LookinDashboardBlueprint.m; sourceTree = ""; }; + 73EBDE260791BF4440027F8601391D8B /* LSTTimer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LSTTimer.release.xcconfig; sourceTree = ""; }; + 741E2A603352D4102F1DAFBB68C69122 /* MJRefresh-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJRefresh-dummy.m"; sourceTree = ""; }; + 74751305705DEA03873DFA2AF4DDC9B7 /* HWPanModalInteractiveAnimator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalInteractiveAnimator.m; path = Sources/Animator/HWPanModalInteractiveAnimator.m; sourceTree = ""; }; + 763CF36C11B6092D9D5485AC2363F205 /* SDImageGIFCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageGIFCoder.m; path = SDWebImage/Core/SDImageGIFCoder.m; sourceTree = ""; }; + 768785318FEB9536A4DAAD47BD76396B /* CALayer+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CALayer+Lookin.h"; path = "Src/Main/Shared/Category/CALayer+Lookin.h"; sourceTree = ""; }; + 769C3408F11A51A90B589A6DBB334C55 /* LKS_ConnectionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_ConnectionManager.h; path = Src/Main/Server/Connection/LKS_ConnectionManager.h; sourceTree = ""; }; + 76AEEFCD2262D6843C63EB46FD6663BB /* UIView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+LookinServer.m"; path = "Src/Main/Server/Category/UIView+LookinServer.m"; sourceTree = ""; }; + 7718D3A1CB256B2263AD76B8EFDC9B86 /* MJRefreshGifHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshGifHeader.h; path = MJRefresh/Custom/Header/MJRefreshGifHeader.h; sourceTree = ""; }; + 77715D6F65035CFA25715F00E4915BA5 /* SDImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCache.m; path = SDWebImage/Core/SDImageCache.m; sourceTree = ""; }; + 77973C87CC9649629EBEE249DCC355F5 /* MJRefreshAutoNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoNormalFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h; sourceTree = ""; }; + 77DEC7B6CE458C6AAB89A25A3E05BA4B /* CALayer+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CALayer+LookinServer.h"; path = "Src/Main/Server/Category/CALayer+LookinServer.h"; sourceTree = ""; }; + 77E6EFEE426EA2068D5FE2B73740D659 /* HWPanIndicatorView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanIndicatorView.m; path = Sources/View/HWPanIndicatorView.m; sourceTree = ""; }; + 77F4C0466DFC43C56F1D982F88EF74A0 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; }; + 7819923046C4F6B199F8D45E9F7BA6B0 /* HWPanModal */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = HWPanModal; path = HWPanModal.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7895C7C58218B5F79C76FA1B5A55E669 /* MJRefresh.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.debug.xcconfig; sourceTree = ""; }; + 798B3DCD95877B6C7D997E0652FB6E9A /* CALayer+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CALayer+LookinServer.m"; path = "Src/Main/Server/Category/CALayer+LookinServer.m"; sourceTree = ""; }; + 7A2AEB4C3E4F6147F107DF9376FA7264 /* UIImage+GIF.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+GIF.m"; path = "SDWebImage/Core/UIImage+GIF.m"; sourceTree = ""; }; + 7A307E6A261D750F85B7C9C1575036E4 /* DZNEmptyDataSet-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DZNEmptyDataSet-prefix.pch"; sourceTree = ""; }; + 7A5F8A5650078BFF9587944F0042AE79 /* UIView+Empty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+Empty.h"; path = "LYEmptyView/UIView+Empty.h"; sourceTree = ""; }; + 7AC0215893BDD3C5E126FCE996097AB4 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = Sources/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 7B167FA26CB7B8DC98E1A68B1B44BA8A /* JXPagerSmoothView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXPagerSmoothView.h; path = Sources/JXPagerView/JXPagerSmoothView.h; sourceTree = ""; }; + 7B51D3C0C65114DF44F6DDB3ED9C4E4E /* JXCategoryNumberCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryNumberCell.m; path = Sources/Number/JXCategoryNumberCell.m; sourceTree = ""; }; + 7B582290DB93C466A4DA695035B6DA2E /* MJExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.release.xcconfig; sourceTree = ""; }; + 7B8734ED62BE39C69073D2C32183C6FC /* JXCategoryNumberView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryNumberView.h; path = Sources/Number/JXCategoryNumberView.h; sourceTree = ""; }; + 7BD134826FCB54429F667B8DBF296710 /* SDCallbackQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDCallbackQueue.m; path = SDWebImage/Core/SDCallbackQueue.m; sourceTree = ""; }; + 7BDFAC11D184E7F4498FC12FE0AFDCFC /* UIScrollView+Helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+Helper.h"; path = "Sources/Category/UIScrollView+Helper.h"; sourceTree = ""; }; + 7C1F5F86210D3FB1EF59D8665E7C4A77 /* SDImageLoadersManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageLoadersManager.h; path = SDWebImage/Core/SDImageLoadersManager.h; sourceTree = ""; }; + 7CE9A594E8A127B7273A7D82E1882497 /* MJRefreshAutoGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoGifFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h; sourceTree = ""; }; + 7D6E9AC32A60E19ACB08AED4E4CD31A3 /* LSTTimer-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LSTTimer-prefix.pch"; sourceTree = ""; }; + 7D7595F0F8BE4F40C64D68F0D491C6C6 /* LSTPopViewProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LSTPopViewProtocol.h; path = LSTPopView/Classes/Code/LSTPopViewProtocol.h; sourceTree = ""; }; + 7D7A76984F1E3BB7440B31DF8D5447F0 /* JXCategoryBaseCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryBaseCellModel.h; path = Sources/Base/JXCategoryBaseCellModel.h; sourceTree = ""; }; + 7DCA3ADE9B99025CE2B42367695E1E68 /* LYEmptyView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LYEmptyView-Info.plist"; sourceTree = ""; }; + 7DD55E3EFF5073BEBD483D293C40A0D6 /* LookinDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDefines.h; path = Src/Main/Shared/LookinDefines.h; sourceTree = ""; }; + 7DEDD90DB6CF7DD05B6B753765E65AAD /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; + 7E270235979252FF388A0C6D1E54966D /* HWVisualEffectView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWVisualEffectView.h; path = Sources/View/HWVisualEffectView.h; sourceTree = ""; }; 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "MJRefresh-MJRefresh.Privacy"; path = MJRefresh.Privacy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E82EAB687527F885E79D9835727B3F8 /* LKS_GestureTargetActionsSearcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_GestureTargetActionsSearcher.h; path = Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.h; sourceTree = ""; }; - 7FCB45CBC3B45614560DA456506F73F1 /* LookinAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttribute.m; path = Src/Main/Shared/LookinAttribute.m; sourceTree = ""; }; - 808621872AB88E6448666731EB043018 /* MJExtension-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-umbrella.h"; sourceTree = ""; }; - 80F9F8B5249F11798A805DF46C09F2CA /* MJRefreshAutoStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoStateFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h; sourceTree = ""; }; - 80FED7368916E2D1EE8E2B7F26A2618F /* UIImage+MemoryCacheCost.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MemoryCacheCost.h"; path = "SDWebImage/Core/UIImage+MemoryCacheCost.h"; sourceTree = ""; }; - 82B53F06F74B4F928AF69994EDA63D71 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; - 832592FA01CF620F64F9CED4966CEA99 /* UIView+WebCacheState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheState.h"; path = "SDWebImage/Core/UIView+WebCacheState.h"; sourceTree = ""; }; - 834B6D6A1ACFBDDF049322F2ED0C17DE /* LKS_CustomAttrModificationHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomAttrModificationHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.h; sourceTree = ""; }; - 83A4CDCDF549B87D4E437ED8A4615D91 /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; - 84E9E0A3D552DFF9EC45D14794237342 /* Lookin_PTProtocol.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Lookin_PTProtocol.m; path = Src/Main/Shared/Peertalk/Lookin_PTProtocol.m; sourceTree = ""; }; - 854F1B8C164960BB0D2721562BD6E7E5 /* MJRefreshNormalHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalHeader.m; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.m; sourceTree = ""; }; - 86A260983254EF2D214865E91D3787B2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; - 872090FEDB94946E441D4F936A1357C0 /* LookinIvarTrace.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinIvarTrace.m; path = Src/Base/LookinIvarTrace.m; sourceTree = ""; }; - 87D20D63606C6DC8B53F345069126C44 /* NSObject+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+LookinServer.h"; path = "Src/Main/Server/Category/NSObject+LookinServer.h"; sourceTree = ""; }; - 89023F2C23C8826F172885D263CC29D2 /* SDImageCodersManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCodersManager.h; path = SDWebImage/Core/SDImageCodersManager.h; sourceTree = ""; }; - 89485243816A18F41367AE862167C061 /* SDImageGraphics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageGraphics.h; path = SDWebImage/Core/SDImageGraphics.h; sourceTree = ""; }; - 8A299BC446CAAFD89DBF55F51B07F0F4 /* SDAnimatedImageRep.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageRep.m; path = SDWebImage/Core/SDAnimatedImageRep.m; sourceTree = ""; }; - 8A3DF7C8B0CA95D284475EF487EC6944 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; sourceTree = ""; }; - 8A6D5DE8BC7E18B47355B8494A426209 /* MBProgressHUD.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = MBProgressHUD.m; sourceTree = ""; }; - 8AE06F501FB1F02940458122AC396D62 /* UIView+WebCacheOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheOperation.m"; path = "SDWebImage/Core/UIView+WebCacheOperation.m"; sourceTree = ""; }; + 7E445C787AA09C1E3A771E4C7DBCE2CA /* LookinCustomAttrModification.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinCustomAttrModification.m; path = Src/Main/Shared/LookinCustomAttrModification.m; sourceTree = ""; }; + 7E73D1DD407F0535009A207AB317F8B7 /* JXCategoryIndicatorCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorCellModel.m; path = Sources/Indicator/JXCategoryIndicatorCellModel.m; sourceTree = ""; }; + 7EC4505824D228FB201DC90A544C01B3 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = Sources/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 7FAB126742756E8C628ED27AEC1B9567 /* FLAnimatedImage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImage-umbrella.h"; sourceTree = ""; }; + 800ECE845D6F36BE51A284DFCAE27307 /* MJRefreshFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshFooter.h; path = MJRefresh/Base/MJRefreshFooter.h; sourceTree = ""; }; + 8067C53E08CA3787D9D5C3551F86EF9D /* JXCategoryImageCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryImageCell.m; path = Sources/Image/JXCategoryImageCell.m; sourceTree = ""; }; + 80E9CB1F62E65A837FF5E47B2FC3ECA1 /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; + 81D115D4A9C927BEBA7B66F114F7B4EC /* MJRefresh-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-prefix.pch"; sourceTree = ""; }; + 81F7F63875295940D9A950DB7D2EBDE7 /* SDWebImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.release.xcconfig; sourceTree = ""; }; + 82F6D1678A37FB68B3455162AB8BDAA2 /* UIViewController+PanModalPresenter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+PanModalPresenter.h"; path = "Sources/Presenter/UIViewController+PanModalPresenter.h"; sourceTree = ""; }; + 8310CCDF3085A9EE32455CB865148664 /* JXPagerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXPagerView.h; path = Sources/JXPagerView/JXPagerView.h; sourceTree = ""; }; + 831897EBD9EF72C4D55D02DE399C410A /* HWPanModalPresentationAnimator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalPresentationAnimator.m; path = Sources/Animator/HWPanModalPresentationAnimator.m; sourceTree = ""; }; + 83340409B38BF2A20F089A4B919FC02F /* MJRefreshNormalTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h; sourceTree = ""; }; + 839CCD719F79C7FBC2909C72822FB470 /* SDImageCachesManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCachesManager.h; path = SDWebImage/Core/SDImageCachesManager.h; sourceTree = ""; }; + 83E8510A179E756198B5FC915A27736E /* AFNetworking-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-umbrella.h"; sourceTree = ""; }; + 852A42FAC0EA5F64033033841A03891A /* NSArray+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+Lookin.h"; path = "Src/Main/Shared/Category/NSArray+Lookin.h"; sourceTree = ""; }; + 855BA7199BD9AC7B4687AF3F66E21279 /* UIImageView+HighlightedWebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+HighlightedWebCache.h"; path = "SDWebImage/Core/UIImageView+HighlightedWebCache.h"; sourceTree = ""; }; + 85C4F1C66A75633558DC8F8AE824BC70 /* LYEmptyView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = LYEmptyView.modulemap; sourceTree = ""; }; + 860D7179002683A0368E532B751FC40E /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; + 862D8BDF52FBE8FCF3A562F5A62C802E /* Lookin_PTChannel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Lookin_PTChannel.m; path = Src/Main/Shared/Peertalk/Lookin_PTChannel.m; sourceTree = ""; }; + 8638AEC16F5A3F7D05EF0F7C39544261 /* MJRefreshConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConst.m; path = MJRefresh/MJRefreshConst.m; sourceTree = ""; }; + 8679B55EBC5DC660D8E798D1B986FC22 /* Image+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Image+Lookin.h"; path = "Src/Main/Shared/Category/Image+Lookin.h"; sourceTree = ""; }; + 87888E540A812F012C68F804E8F5AE7B /* HWPanModalPresentationController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresentationController.h; path = Sources/Controller/HWPanModalPresentationController.h; sourceTree = ""; }; + 87B2A7EE05A20B3EDDFE045A6B7911E5 /* SDImageAssetManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAssetManager.m; path = SDWebImage/Private/SDImageAssetManager.m; sourceTree = ""; }; + 87D7822F88C7B9608DF7E50878B7970B /* JXCategoryDotCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryDotCell.m; path = Sources/Dot/JXCategoryDotCell.m; sourceTree = ""; }; + 883434364AD74D3F77868A0CF2FB7A09 /* SDAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageView.m; path = SDWebImage/Core/SDAnimatedImageView.m; sourceTree = ""; }; + 88D479C435BAEE51B8F3BBF87F8D3CC9 /* AFNetworking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.debug.xcconfig; sourceTree = ""; }; + 88F65BAED091224357C1ABFEA1C484FA /* LSTTimer-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LSTTimer-umbrella.h"; sourceTree = ""; }; + 892976CDE28E9BEF86BFABB5F84E72F6 /* JXCategoryView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryView.h; path = Sources/JXCategoryView.h; sourceTree = ""; }; + 897530E070833B039DC2821D0B63B137 /* JXCategoryBaseCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryBaseCellModel.m; path = Sources/Base/JXCategoryBaseCellModel.m; sourceTree = ""; }; + 8A5D6AD5CB7122607D6E477D373A31E2 /* SDAnimatedImagePlayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImagePlayer.m; path = SDWebImage/Core/SDAnimatedImagePlayer.m; sourceTree = ""; }; + 8A9BFDE06B11541EA7E87336A09C3816 /* UIViewController+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+LookinServer.m"; path = "Src/Main/Server/Category/UIViewController+LookinServer.m"; sourceTree = ""; }; + 8B523AAA92DB90BD5B95092AF6B85BFB /* Lookin_PTPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Lookin_PTPrivate.h; path = Src/Main/Shared/Peertalk/Lookin_PTPrivate.h; sourceTree = ""; }; + 8B8796E86BD11BC29D00EED72E50AE91 /* LKS_InbuiltAttrModificationHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_InbuiltAttrModificationHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.h; sourceTree = ""; }; + 8B890DAD1E942EF3DB7BF5C23113C1B6 /* JXCategoryDotCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryDotCell.h; path = Sources/Dot/JXCategoryDotCell.h; sourceTree = ""; }; + 8B8AB8065F8811289957B59E9EBA6B47 /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MBProgressHUD; path = MBProgressHUD.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8BAD239072CC7DFB1FD50FE4374085D1 /* NSBezierPath+SDRoundedCorners.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBezierPath+SDRoundedCorners.m"; path = "SDWebImage/Private/NSBezierPath+SDRoundedCorners.m"; sourceTree = ""; }; - 8C9727D0D56A9017D437CA50176F0474 /* Bugly.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Bugly.release.xcconfig; sourceTree = ""; }; - 8CABC6887E9E2AF4A62642A0C780B4B3 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; - 8CD27E7A66F8B685B7056B181A0D4D46 /* SDAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImage.m; path = SDWebImage/Core/SDAnimatedImage.m; sourceTree = ""; }; - 8E466B1532DEF5F8A8FE002C3882E69E /* WKWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WKWebView+AFNetworking.h"; path = "UIKit+AFNetworking/WKWebView+AFNetworking.h"; sourceTree = ""; }; - 8E6B85BD26EE974026A447B476B2932B /* NSBundle+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBundle+MJRefresh.m"; path = "MJRefresh/NSBundle+MJRefresh.m"; sourceTree = ""; }; - 8F0FAF8AA7D9999CB7B6AC14DC9F613F /* SDImageGIFCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageGIFCoder.h; path = SDWebImage/Core/SDImageGIFCoder.h; sourceTree = ""; }; - 8F715C3F41E2D739BCA20A8ED2E487A1 /* SDInternalMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDInternalMacros.h; path = SDWebImage/Private/SDInternalMacros.h; sourceTree = ""; }; - 904AEE3BB6B326E7E1CFD8B0A34306AB /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; - 9228BFB339DE3C8FD5163C974AB7DE89 /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; - 9278559A57D46FAC97B2480A76E574BE /* Color+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "Color+Lookin.m"; path = "Src/Main/Shared/Category/Color+Lookin.m"; sourceTree = ""; }; - 929BD46DB08827C3FD713BC0E928C239 /* SDWebImageDownloaderOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderOperation.h; path = SDWebImage/Core/SDWebImageDownloaderOperation.h; sourceTree = ""; }; - 9324A882B3ED55B3EF9D92D946555583 /* MJRefreshConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConst.m; path = MJRefresh/MJRefreshConst.m; sourceTree = ""; }; - 93AFD572FFECC065D5DF0E8764C35B66 /* Lookin_PTChannel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Lookin_PTChannel.m; path = Src/Main/Shared/Peertalk/Lookin_PTChannel.m; sourceTree = ""; }; - 93FB055BA93E62482AD7154A938F761A /* SDImageAWebPCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAWebPCoder.h; path = SDWebImage/Core/SDImageAWebPCoder.h; sourceTree = ""; }; - 94310BE9068195ADA7842BD0A9A7F782 /* LKS_HierarchyDetailsHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_HierarchyDetailsHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.m; sourceTree = ""; }; - 9450EAE5D947C741A2403ADD203E1875 /* MJRefreshAutoStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoStateFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m; sourceTree = ""; }; - 948E1E3EDCE53B021791B9169CCC28BD /* MJRefreshBackGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackGifFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m; sourceTree = ""; }; - 94CD4DB147D9FC14A9FB75335D8AAAF6 /* LookinAttrIdentifiers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttrIdentifiers.h; path = Src/Main/Shared/LookinAttrIdentifiers.h; sourceTree = ""; }; - 94E4D004CAC99A7D4B7144E86418C29C /* SDWebImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloader.m; path = SDWebImage/Core/SDWebImageDownloader.m; sourceTree = ""; }; - 960792D55E0D95EDBE31A27683F9FEEF /* SDWebImageCacheKeyFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCacheKeyFilter.m; path = SDWebImage/Core/SDWebImageCacheKeyFilter.m; sourceTree = ""; }; - 96163189CC5AFA5E4E23D6B0B3EADFF7 /* NSObject+MJClass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJClass.h"; path = "MJExtension/NSObject+MJClass.h"; sourceTree = ""; }; - 9641B4F4D8DDE2072CB32BF4C9C2882A /* LookinServer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LookinServer.debug.xcconfig; sourceTree = ""; }; - 964A9667953DC95C883D7E82FD74B649 /* MJExtension-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-prefix.pch"; sourceTree = ""; }; - 9662C23EC2FEA41BE91046E19A928D8C /* SDImageIOAnimatedCoderInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOAnimatedCoderInternal.h; path = SDWebImage/Private/SDImageIOAnimatedCoderInternal.h; sourceTree = ""; }; + 8BE10EB8B74E3D1DE4172EF863BC22F8 /* Color+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Color+Lookin.h"; path = "Src/Main/Shared/Category/Color+Lookin.h"; sourceTree = ""; }; + 8C065D632F2F749CBD48B178A68B1631 /* MJRefreshAutoStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoStateFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h; sourceTree = ""; }; + 8CF1445CC744306AE4ECBA85DFD6DB27 /* MJRefreshAutoStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoStateFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m; sourceTree = ""; }; + 8D2F3BF5EE9E269F816330AC6BF6745F /* UIImage+ExtendedCacheData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ExtendedCacheData.h"; path = "SDWebImage/Core/UIImage+ExtendedCacheData.h"; sourceTree = ""; }; + 8E4925A54FF503F963785651A98856BD /* UIView+WebCacheState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheState.m"; path = "SDWebImage/Core/UIView+WebCacheState.m"; sourceTree = ""; }; + 8EFBD2E7A88C44123D980C42CB8702A4 /* JXCategoryDotView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryDotView.h; path = Sources/Dot/JXCategoryDotView.h; sourceTree = ""; }; + 8FEE8F6EEF601125225DCB1FEACED91C /* JXCategoryTitleView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleView.m; path = Sources/Title/JXCategoryTitleView.m; sourceTree = ""; }; + 8FF761C99D422AE106C31A4A7AE469C7 /* JXCategoryViewAnimator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryViewAnimator.h; path = Sources/Common/JXCategoryViewAnimator.h; sourceTree = ""; }; + 903EBE6439B30182644FFF066DE11129 /* LookinAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttribute.h; path = Src/Main/Shared/LookinAttribute.h; sourceTree = ""; }; + 913F72595D3AEFAFE006FD96A54FD8DA /* JXCategoryIndicatorCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorCell.h; path = Sources/Indicator/JXCategoryIndicatorCell.h; sourceTree = ""; }; + 919C930C4E0162377E3C95D0F6F11177 /* UIView+WebCacheState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheState.h"; path = "SDWebImage/Core/UIView+WebCacheState.h"; sourceTree = ""; }; + 91BC18AA2869958B15FBD2C2367C5DFC /* AFNetworking.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = AFNetworking.modulemap; sourceTree = ""; }; + 9230BE776665C8EB51C8889631B1B31B /* HWDimmedView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWDimmedView.m; path = Sources/View/HWDimmedView.m; sourceTree = ""; }; + 9234E8779322D7F9722AF6E18FF9F6F3 /* JXCategoryImageCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryImageCell.h; path = Sources/Image/JXCategoryImageCell.h; sourceTree = ""; }; + 92670C1E3C13D6C6157E7AFB4347DB17 /* NSString+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+Lookin.h"; path = "Src/Main/Shared/Category/NSString+Lookin.h"; sourceTree = ""; }; + 928339E7523C1267D5DF15E548454A5E /* NSData+ImageContentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+ImageContentType.m"; path = "SDWebImage/Core/NSData+ImageContentType.m"; sourceTree = ""; }; + 92A35222DEEC452079F1343331C6E154 /* JXCategoryIndicatorProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorProtocol.h; path = Sources/Common/JXCategoryIndicatorProtocol.h; sourceTree = ""; }; + 931669FB7F8BA540208B2F23E13B2F19 /* JXCategoryDotCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryDotCellModel.h; path = Sources/Dot/JXCategoryDotCellModel.h; sourceTree = ""; }; + 93B896E371962B657B3B85C108092214 /* SDWebImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.debug.xcconfig; sourceTree = ""; }; + 949A8C57291DF7D8139F90AD367DB80C /* SDWebImageOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOperation.h; path = SDWebImage/Core/SDWebImageOperation.h; sourceTree = ""; }; + 94CE97E5A9659D6EE58C83DCB52F73D5 /* HWPanContainerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanContainerView.h; path = Sources/View/HWPanContainerView.h; sourceTree = ""; }; + 954035BEFF37A926FB7C25E5508CD25D /* MJExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.debug.xcconfig; sourceTree = ""; }; + 957B3209BD81CDA1C8049B3245F6946E /* LKS_MultiplatformAdapter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_MultiplatformAdapter.m; path = Src/Main/Server/Others/LKS_MultiplatformAdapter.m; sourceTree = ""; }; + 95BCF1B96C9A492409E9634BC63A400B /* JXCategoryViewAnimator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryViewAnimator.m; path = Sources/Common/JXCategoryViewAnimator.m; sourceTree = ""; }; + 962D7794EB805E6D2F4F5F0B58218401 /* SDInternalMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDInternalMacros.h; path = SDWebImage/Private/SDInternalMacros.h; sourceTree = ""; }; 969A9A842778EFB5D62826500DFF4E11 /* Pods-keyBoard-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-keyBoard-dummy.m"; sourceTree = ""; }; - 96D5456A17DF66E262562E8208ADEFF0 /* UIView+WebCacheState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheState.m"; path = "SDWebImage/Core/UIView+WebCacheState.m"; sourceTree = ""; }; - 96E64D1052C3FD60EB6BBB8A95EE1349 /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; - 97003D4D841CDDF5214C70A6CC7425DF /* SDImageLoader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageLoader.h; path = SDWebImage/Core/SDImageLoader.h; sourceTree = ""; }; - 97041A2525062E71B923CEBB11179389 /* SDImageCodersManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCodersManager.m; path = SDWebImage/Core/SDImageCodersManager.m; sourceTree = ""; }; - 9843F03B02D2521214C5C5583A9BBDA3 /* SDGraphicsImageRenderer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDGraphicsImageRenderer.m; path = SDWebImage/Core/SDGraphicsImageRenderer.m; sourceTree = ""; }; - 98B6A3897B6D415F51E7F65FD9A20296 /* UIView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCache.h"; path = "SDWebImage/Core/UIView+WebCache.h"; sourceTree = ""; }; - 99418F0A943BD9FF46795740F7385472 /* SDWebImageDownloaderConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderConfig.h; path = SDWebImage/Core/SDWebImageDownloaderConfig.h; sourceTree = ""; }; - 9964200935BD2352FD5DAD8C2AC9FE07 /* SDImageLoadersManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageLoadersManager.h; path = SDWebImage/Core/SDImageLoadersManager.h; sourceTree = ""; }; - 99F9CF6DCFC4C32DE7AC87FA68FD05DA /* SDImageCachesManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCachesManager.h; path = SDWebImage/Core/SDImageCachesManager.h; sourceTree = ""; }; - 9A522D0661C437F2B97B12A18A3478A1 /* SDAnimatedImagePlayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImagePlayer.h; path = SDWebImage/Core/SDAnimatedImagePlayer.h; sourceTree = ""; }; - 9BF2F8A5A2E35CC31448E86BCF471F49 /* LookinConnectionResponseAttachment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinConnectionResponseAttachment.h; path = Src/Main/Shared/LookinConnectionResponseAttachment.h; sourceTree = ""; }; - 9C6609EE1C9372D5E3C70AF9861CE95D /* SDWebImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloader.h; path = SDWebImage/Core/SDWebImageDownloader.h; sourceTree = ""; }; - 9C8E3573AF9C6E24E9DFBDDB57A91B44 /* Lookin_PTUSBHub.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Lookin_PTUSBHub.m; path = Src/Main/Shared/Peertalk/Lookin_PTUSBHub.m; sourceTree = ""; }; - 9C9BCDBD08949F0C3053B9F87567E0B2 /* LookinHierarchyInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinHierarchyInfo.h; path = Src/Main/Shared/LookinHierarchyInfo.h; sourceTree = ""; }; - 9D58792A3DBAB3667630D1FF53DDFB8D /* LKS_CustomAttrGroupsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomAttrGroupsMaker.h; path = Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.h; sourceTree = ""; }; + 96AEDA915084E949F39F28D248C2FB43 /* SDWebImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloader.h; path = SDWebImage/Core/SDWebImageDownloader.h; sourceTree = ""; }; + 96D1E2DE4F6F4EB00BD41C7ABD504109 /* JXCategoryListContainerRTLCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryListContainerRTLCell.m; path = Sources/Common/JXCategoryListContainerRTLCell.m; sourceTree = ""; }; + 97DE751E0ED3939932D72FB39C5A934A /* LookinAutoLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAutoLayoutConstraint.h; path = Src/Main/Shared/LookinAutoLayoutConstraint.h; sourceTree = ""; }; + 986324EA3CC9A3BDF0E5C7B1763862EE /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; + 98768C46376F54DFEB58CDD9F278AC71 /* MBProgressHUD-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-prefix.pch"; sourceTree = ""; }; + 98901829A364C7B4F13375AEB6AA0FBE /* SDWeakProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWeakProxy.m; path = SDWebImage/Private/SDWeakProxy.m; sourceTree = ""; }; + 98935AEC9F6608D5CCBFEF667B9F658A /* LKS_CustomDisplayItemsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomDisplayItemsMaker.h; path = Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.h; sourceTree = ""; }; + 9897B379E415C6537D86A30137A8D274 /* ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; sourceTree = ""; }; + 98B3D67E4B164109B9B94A959496BA25 /* SDmetamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDmetamacros.h; path = SDWebImage/Private/SDmetamacros.h; sourceTree = ""; }; + 99650956C6DC18187951AE72D50E44A2 /* MJFoundation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJFoundation.h; path = MJExtension/MJFoundation.h; sourceTree = ""; }; + 996C55702A2E4E7B3785C0C5454598C9 /* JXCategoryTitleVerticalZoomView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleVerticalZoomView.h; path = Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomView.h; sourceTree = ""; }; + 99712B41FFAFC24C5F649A94D8DD7FFE /* LookinCodingValueType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinCodingValueType.h; path = Src/Main/Shared/LookinCodingValueType.h; sourceTree = ""; }; + 9A3BA26DC995AB016051D522F5691C91 /* RTLManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RTLManager.m; path = Sources/RLTManager/RTLManager.m; sourceTree = ""; }; + 9AA439B2B87976D37C23F7DCCE897F8C /* SDWebImagePrefetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImagePrefetcher.m; path = SDWebImage/Core/SDWebImagePrefetcher.m; sourceTree = ""; }; + 9ABEB6B0A44AC8BCBC6CB1A8A8A9A0FF /* UIVisualEffectView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIVisualEffectView+LookinServer.h"; path = "Src/Main/Server/Category/UIVisualEffectView+LookinServer.h"; sourceTree = ""; }; + 9C0082C9FF6875DA300AE3D8453DCB62 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; + 9C0E279B5FFB9696801CC86ACF92805A /* SDImageGIFCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageGIFCoder.h; path = SDWebImage/Core/SDImageGIFCoder.h; sourceTree = ""; }; + 9C2DAB09AC8F3AD6E82FDC5DB2562CB4 /* JXPagerMainTableView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXPagerMainTableView.m; path = Sources/JXPagerView/JXPagerMainTableView.m; sourceTree = ""; }; + 9C47102257C212ED978684D39466579B /* LKS_ExportManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_ExportManager.h; path = Src/Main/Server/Others/LKS_ExportManager.h; sourceTree = ""; }; + 9C75F181A3E07F7E7B4B017B48488393 /* LookinConnectionAttachment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinConnectionAttachment.m; path = Src/Main/Shared/LookinConnectionAttachment.m; sourceTree = ""; }; + 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 9D4F497397BEDE35BC05F6C2B6D33577 /* LookinAttrIdentifiers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttrIdentifiers.m; path = Src/Main/Shared/LookinAttrIdentifiers.m; sourceTree = ""; }; + 9D7E307063029FFE21DDCDC0455FA473 /* MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJProperty.m; path = MJExtension/MJProperty.m; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9D9C32EDDDB1CA2666760FDE90B64590 /* SDImageHEICCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageHEICCoder.m; path = SDWebImage/Core/SDImageHEICCoder.m; sourceTree = ""; }; 9DDD0462C32F55EF5E9CB1056459809F /* Pods-CustomKeyboard-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-CustomKeyboard-umbrella.h"; sourceTree = ""; }; - 9DFECBD4586BE9AE288AFFA5027A9A24 /* UIImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+WebCache.h"; path = "SDWebImage/Core/UIImageView+WebCache.h"; sourceTree = ""; }; - 9E3D65B846C5EFBA9201404CD8BDC1DA /* SDWebImageTransitionInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageTransitionInternal.h; path = SDWebImage/Private/SDWebImageTransitionInternal.h; sourceTree = ""; }; - 9F1EE18C1314EB74EEB6B6392E8EFB08 /* LKS_GestureTargetActionsSearcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_GestureTargetActionsSearcher.m; path = Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.m; sourceTree = ""; }; - 9F2C6DE995A9BCF5E418479898442088 /* NSObject+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+Lookin.h"; path = "Src/Main/Shared/Category/NSObject+Lookin.h"; sourceTree = ""; }; - A054792401E8F9F7BEA8441F9C1DA7C7 /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; - A1B6FEE442B47E03714BC3FB94670DCC /* SDImageCachesManagerOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCachesManagerOperation.m; path = SDWebImage/Private/SDImageCachesManagerOperation.m; sourceTree = ""; }; - A1BB512E1904C9AC07E6CEBA4DE525DB /* LookinDisplayItemDetail.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinDisplayItemDetail.h; path = Src/Main/Shared/LookinDisplayItemDetail.h; sourceTree = ""; }; + 9E31AD6314EC8102DE4FC6291C0FE66F /* HWPanModalContentView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalContentView.m; path = Sources/View/PanModal/HWPanModalContentView.m; sourceTree = ""; }; + 9E91A12C513A640E68663D4ED668C0FC /* JXCategoryTitleImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleImageView.h; path = Sources/TitleImage/JXCategoryTitleImageView.h; sourceTree = ""; }; + 9EC4E80691EA4009AB067722DA72E4D5 /* JXCategoryTitleImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleImageView.m; path = Sources/TitleImage/JXCategoryTitleImageView.m; sourceTree = ""; }; + 9ECA4FF1A4B2A73F055139B44105081C /* NSBundle+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBundle+MJRefresh.m"; path = "MJRefresh/NSBundle+MJRefresh.m"; sourceTree = ""; }; + 9F5507B4A6BD90BF5F74B1AAC009AD90 /* SDImageAssetManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAssetManager.h; path = SDWebImage/Private/SDImageAssetManager.h; sourceTree = ""; }; + 9F5B3C0CF01454E7AC9226E88FDFBAE6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 9FB49DC67A435D7D63695F113C3D398C /* SDWebImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SDWebImage-Info.plist"; sourceTree = ""; }; + A01B197EE310DCCE265AA065FA12EF38 /* JXCategoryView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "JXCategoryView-Info.plist"; sourceTree = ""; }; + A0329494F5B3BBF4A9C54DD83622388B /* MJPropertyType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyType.h; path = MJExtension/MJPropertyType.h; sourceTree = ""; }; + A0497973DD4190C4C37CC950C86C6F2B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = WebImage/PrivacyInfo.xcprivacy; sourceTree = ""; }; + A0925E96742E33F78D548F10A7C0475D /* LKS_CustomAttrSetterManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomAttrSetterManager.h; path = Src/Main/Server/Others/LKS_CustomAttrSetterManager.h; sourceTree = ""; }; + A11C415AC80BAC0B06685E1F8AC7C7C8 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; + A1411B1EA7A3C51DB2072BF40B4D5A60 /* SDAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImage.h; path = SDWebImage/Core/SDAnimatedImage.h; sourceTree = ""; }; + A14754CFA2BACA27D3CA6DD44F6D8F10 /* ResourceBundle-SDWebImage-SDWebImage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-SDWebImage-SDWebImage-Info.plist"; sourceTree = ""; }; + A16556ABD8D8BADE087CDC162140E59B /* MBProgressHUD-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MBProgressHUD-Info.plist"; sourceTree = ""; }; + A198AAC0BC41558B9FC61F89E90D900F /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; + A1C4717F035C7128013EA7E000DAC18A /* WKWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "WKWebView+AFNetworking.m"; path = "UIKit+AFNetworking/WKWebView+AFNetworking.m"; sourceTree = ""; }; + A1DAAC915F745C515E0BF4D613B5CB1C /* LKS_InbuiltAttrModificationHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_InbuiltAttrModificationHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.m; sourceTree = ""; }; + A2350DF4D8FE6C892E64B8C644667527 /* KeyValueObserver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = KeyValueObserver.m; path = Sources/KVO/KeyValueObserver.m; sourceTree = ""; }; + A23AD7EF4A12F64EAAFE5154D8DC5843 /* JXCategoryNumberCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryNumberCell.h; path = Sources/Number/JXCategoryNumberCell.h; sourceTree = ""; }; + A2C2A9B920BB92B872BA2AC2EA086220 /* SDAnimatedImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "SDAnimatedImageView+WebCache.m"; path = "SDWebImage/Core/SDAnimatedImageView+WebCache.m"; sourceTree = ""; }; A2D8E1EB42D41EA6B94901E5B68C9011 /* Pods-keyBoard-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-keyBoard-umbrella.h"; sourceTree = ""; }; - A3048EE57AEE9C3B5FDB98C9E7DF4BB9 /* LookinObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinObject.m; path = Src/Main/Shared/LookinObject.m; sourceTree = ""; }; - A306B5D1B1BD0232E2121BA1E0EA27F9 /* LKS_ExportManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_ExportManager.m; path = Src/Main/Server/Others/LKS_ExportManager.m; sourceTree = ""; }; - A3868E0511721B009DE0A628C978E4AF /* LKS_TraceManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_TraceManager.m; path = Src/Main/Server/Others/LKS_TraceManager.m; sourceTree = ""; }; - A3A3B77B219A105E2636BBFACE42D7A8 /* NSString+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+MJExtension.m"; path = "MJExtension/NSString+MJExtension.m"; sourceTree = ""; }; - A3CC467742888B5DE59CC393D50BA540 /* SDImageCachesManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCachesManager.m; path = SDWebImage/Core/SDImageCachesManager.m; sourceTree = ""; }; - A417B5FC83ECB57A121FCD14A6DD23D3 /* MJRefreshAutoFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoFooter.h; path = MJRefresh/Base/MJRefreshAutoFooter.h; sourceTree = ""; }; - A4E4BD7B01B4DA8E6A41CD86E6AB6B44 /* MJRefreshFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshFooter.m; path = MJRefresh/Base/MJRefreshFooter.m; sourceTree = ""; }; + A3211D6272FC8FFC9717C01969D328F7 /* LSTTimer-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LSTTimer-dummy.m"; sourceTree = ""; }; + A324C5885C8FB2DC65900A0EE79A0E45 /* MJRefresh.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.release.xcconfig; sourceTree = ""; }; + A34A186C33DB71F8C4ACB6E0705472D0 /* UIView+Empty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+Empty.m"; path = "LYEmptyView/UIView+Empty.m"; sourceTree = ""; }; + A39050EBA53940D0CE63B52BF031BE6C /* UIImage+Transform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Transform.h"; path = "SDWebImage/Core/UIImage+Transform.h"; sourceTree = ""; }; + A3E40CB9D351DF0E70C7A452071E82E1 /* SDImageCoderHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCoderHelper.h; path = SDWebImage/Core/SDImageCoderHelper.h; sourceTree = ""; }; + A464713D364DCC51BD1C744435EF31A3 /* SDDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDiskCache.h; path = SDWebImage/Core/SDDiskCache.h; sourceTree = ""; }; + A4B49E8FCEA2AFEE938A133ECC269CF2 /* SDWebImageTransition.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageTransition.m; path = SDWebImage/Core/SDWebImageTransition.m; sourceTree = ""; }; + A4CFB2BE169777F50B29077639FCFEC4 /* LKSConfigManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKSConfigManager.h; path = Src/Main/Server/Others/LKSConfigManager.h; sourceTree = ""; }; + A4F1299F85FD74B081B5C5F85EF530B7 /* SDWebImageError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageError.m; path = SDWebImage/Core/SDWebImageError.m; sourceTree = ""; }; A4FA15D44DF6BAC7550EDEED10862AA3 /* AFNetworking */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = AFNetworking; path = AFNetworking.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A53791C99F3E8789C928D8471E4310AC /* MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefresh.h; path = MJRefresh/MJRefresh.h; sourceTree = ""; }; - A565D25677F6FEEAD298666682CDA4B2 /* AFAutoPurgingImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFAutoPurgingImageCache.h; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.h"; sourceTree = ""; }; - A57C810A36EA495CAFAEDAD83C19A651 /* SDImageCoderHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCoderHelper.m; path = SDWebImage/Core/SDImageCoderHelper.m; sourceTree = ""; }; - A6057C23DD0D9C9A5559F8F0DC47A97D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = MJRefresh/PrivacyInfo.xcprivacy; sourceTree = ""; }; - A67D546CB537E231FE83AA071A555BB7 /* AFImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFImageDownloader.m; path = "UIKit+AFNetworking/AFImageDownloader.m"; sourceTree = ""; }; - A6A924083322C61BD2DC82A438F46687 /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; - A6B89FBB0AA4A7BD7E16AFF20A519DC2 /* UIImageView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+LookinServer.m"; path = "Src/Main/Server/Category/UIImageView+LookinServer.m"; sourceTree = ""; }; + A527D460219BC25D3D8E05E8A68C23C9 /* JXCategoryIndicatorLineView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorLineView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.h; sourceTree = ""; }; + A56060BC793E00F370FD0DF3B4157376 /* SDWebImageIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageIndicator.m; path = SDWebImage/Core/SDWebImageIndicator.m; sourceTree = ""; }; + A566FD7AC8F85BE1E72F6DF11FEA6338 /* NSObject+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+LookinServer.m"; path = "Src/Main/Server/Category/NSObject+LookinServer.m"; sourceTree = ""; }; + A603B071469D044FB92322560F131681 /* Masonry.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.debug.xcconfig; sourceTree = ""; }; + A64A22A853C13E4375B73E01D1D90CB1 /* MJRefreshBackNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackNormalFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m; sourceTree = ""; }; A6E8FF241173D596A21D4D4B7D86A810 /* Pods-keyBoard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-keyBoard.release.xcconfig"; sourceTree = ""; }; - A6EB4E3885146B9E8EBACA05C540E733 /* LookinConnectionAttachment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinConnectionAttachment.m; path = Src/Main/Shared/LookinConnectionAttachment.m; sourceTree = ""; }; - A7178BC144BA120067B45EC042E2D156 /* LookinCodingValueType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinCodingValueType.h; path = Src/Main/Shared/LookinCodingValueType.h; sourceTree = ""; }; - A8E1E4CE0CD5AF60097B9523ED2201F8 /* MJRefreshNormalTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h; sourceTree = ""; }; - A99D2B8B886EDA66D95608FD72CE97AF /* CALayer+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CALayer+LookinServer.m"; path = "Src/Main/Server/Category/CALayer+LookinServer.m"; sourceTree = ""; }; - AA8F3F4E9CF14305D8C83582492FEA87 /* UIImage+Transform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Transform.h"; path = "SDWebImage/Core/UIImage+Transform.h"; sourceTree = ""; }; - AB22EEA7E251269666B0DD8D3FCD0892 /* MJRefreshBackFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackFooter.m; path = MJRefresh/Base/MJRefreshBackFooter.m; sourceTree = ""; }; - AB362641176A92218B886FD83548F6C2 /* SDImageCachesManagerOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCachesManagerOperation.h; path = SDWebImage/Private/SDImageCachesManagerOperation.h; sourceTree = ""; }; - AB70C7432DDB8346C9DB4A27C7C7AEEB /* UITextField+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextField+LookinServer.h"; path = "Src/Main/Server/Category/UITextField+LookinServer.h"; sourceTree = ""; }; - ABCA85AD5553CAA4C58A12223211E18E /* MJRefreshTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshTrailer.m; path = MJRefresh/Base/MJRefreshTrailer.m; sourceTree = ""; }; - ABFE70D35403EBB3D3B8E84170698E30 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; - AE4708C50A24F74BB9721BF97FDD4782 /* SDWebImageOptionsProcessor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOptionsProcessor.m; path = SDWebImage/Core/SDWebImageOptionsProcessor.m; sourceTree = ""; }; - AEB9B57AEEA7BDF0C696120F4B110F33 /* UIScrollView+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJRefresh.h"; path = "MJRefresh/UIScrollView+MJRefresh.h"; sourceTree = ""; }; - AF4D3A8A4AF29616DFF2E40A94DA00AE /* NSString+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+MJExtension.h"; path = "MJExtension/NSString+MJExtension.h"; sourceTree = ""; }; - B00A278D1C0A05DD872C02CEFE3B53AC /* SDImageIOCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOCoder.h; path = SDWebImage/Core/SDImageIOCoder.h; sourceTree = ""; }; - B069597AD0812CBF01ACDD3CE4B6F843 /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; + A7A348B5BB8CB7A444F827000C95DAE5 /* UIImage+ExtendedCacheData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ExtendedCacheData.m"; path = "SDWebImage/Core/UIImage+ExtendedCacheData.m"; sourceTree = ""; }; + A7DF910F689AA8FEAD1EF63DDDFCB780 /* UIVisualEffectView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIVisualEffectView+LookinServer.m"; path = "Src/Main/Server/Category/UIVisualEffectView+LookinServer.m"; sourceTree = ""; }; + A7EA79586CBF531A23E8B00CFA7B82C7 /* MJRefreshBackFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackFooter.m; path = MJRefresh/Base/MJRefreshBackFooter.m; sourceTree = ""; }; + A810CCF3953514350B557ABBEEBE5FF6 /* UIColor+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+LookinServer.h"; path = "Src/Main/Server/Category/UIColor+LookinServer.h"; sourceTree = ""; }; + A8AF8342462E3EDE8E3D40F840DFA00C /* MBProgressHUD-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-umbrella.h"; sourceTree = ""; }; + A92BC89EBEE6C3CE964CA994B506EA43 /* SDWeakProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWeakProxy.h; path = SDWebImage/Private/SDWeakProxy.h; sourceTree = ""; }; + A9BB84448AE1154A6E3D359329D6E5D8 /* JXPagingView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JXPagingView-prefix.pch"; sourceTree = ""; }; + AA7E9357D1D22FB737AEE89305734112 /* LKS_GestureTargetActionsSearcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_GestureTargetActionsSearcher.h; path = Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.h; sourceTree = ""; }; + AAA2247A63D832BDB9097AE7D635F20C /* ResourceBundle-JXCategoryView-JXCategoryView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-JXCategoryView-JXCategoryView-Info.plist"; sourceTree = ""; }; + AB1D54171867DC3B104DAE8C6D30F644 /* MJRefreshStateTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h; sourceTree = ""; }; + AB2B98D8DC3605842D8528F53C1896A2 /* LKS_CustomAttrGroupsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomAttrGroupsMaker.m; path = Src/Main/Server/Others/LKS_CustomAttrGroupsMaker.m; sourceTree = ""; }; + AB379411892DE9D6AC2BA478DD047B45 /* MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJProperty.h; path = MJExtension/MJProperty.h; sourceTree = ""; }; + ABAC9F2093F2EF164CB968D710D261F5 /* MJRefresh.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJRefresh.modulemap; sourceTree = ""; }; + AC0C26DBF6F4D6A9D8C1BF55FE14DABA /* MBProgressHUD.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.release.xcconfig; sourceTree = ""; }; + AC368BF52013B3AE323DC35D782A044B /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; + AC3EF9D4544217A0B4E13DA6B530C974 /* JXCategoryView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JXCategoryView-umbrella.h"; sourceTree = ""; }; + ACD18D412C592E0FB706C10554E5283E /* SDWebImageTransitionInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageTransitionInternal.h; path = SDWebImage/Private/SDWebImageTransitionInternal.h; sourceTree = ""; }; + ADF656282B85E6C974597F555BDE3F21 /* LKS_AttrModificationPatchHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_AttrModificationPatchHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.h; sourceTree = ""; }; + AE19AE8E2478EF2E39C49272A1998EFE /* LookinDisplayItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinDisplayItem.m; path = Src/Main/Shared/LookinDisplayItem.m; sourceTree = ""; }; + AE4CC2528765A45B472AD5B813D01119 /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; + AEEC6C323BA320F8FE0EFED607BC9994 /* SDWebImageDefine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDefine.m; path = SDWebImage/Core/SDWebImageDefine.m; sourceTree = ""; }; + AF5F1AB306D02EC6A5F39878FAE8BEA1 /* SDWebImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-prefix.pch"; sourceTree = ""; }; + AFBA747DBA20D4BACF78CA8DE98ADF94 /* LKS_RequestHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_RequestHandler.h; path = Src/Main/Server/Connection/LKS_RequestHandler.h; sourceTree = ""; }; + B041D1C998D0894DB89A31049CC1B872 /* UIBlurEffect+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIBlurEffect+LookinServer.m"; path = "Src/Main/Server/Category/UIBlurEffect+LookinServer.m"; sourceTree = ""; }; + B052BF123A39C5CF4B531584A2A83BED /* WKWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WKWebView+AFNetworking.h"; path = "UIKit+AFNetworking/WKWebView+AFNetworking.h"; sourceTree = ""; }; + B0922492568B0DD6D1F92C0E3B3A53A1 /* LookinWeakContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinWeakContainer.h; path = Src/Main/Shared/LookinWeakContainer.h; sourceTree = ""; }; + B09C6285E70223CDED72989080A8442A /* NSImage+Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSImage+Compatibility.h"; path = "SDWebImage/Core/NSImage+Compatibility.h"; sourceTree = ""; }; B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SDWebImage; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B12DF9FA146221C01FCE0D22DDBDC890 /* LookinAttrType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttrType.h; path = Src/Main/Shared/LookinAttrType.h; sourceTree = ""; }; - B1A8FD671105727BDE389DF6E59E7187 /* LookinServer-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LookinServer-umbrella.h"; sourceTree = ""; }; - B36A499BB6A9A389E077337779129B95 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; - B486D1944AF55BFAF5E8F8CDE6F8EB79 /* MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtension.h; path = MJExtension/MJExtension.h; sourceTree = ""; }; - B4D76F7EB1CE870804724BC071C5ACB3 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; - B640B3AD2FE955C7A51E5B1F84A61189 /* UIScrollView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJExtension.h"; path = "MJRefresh/UIScrollView+MJExtension.h"; sourceTree = ""; }; - B6D81E3EC47029DCA820DF6AA652C734 /* SDWebImageIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageIndicator.h; path = SDWebImage/Core/SDWebImageIndicator.h; sourceTree = ""; }; - B6F3F601094A8014DC41447620116D80 /* SDImageFrame.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageFrame.m; path = SDWebImage/Core/SDImageFrame.m; sourceTree = ""; }; - B70FF2E3C927A22C388C16FE8C3F56DB /* MJRefreshBackNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackNormalFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h; sourceTree = ""; }; - B7D4D5B8A3207BDAE71FAE9F1B443CBF /* UICollectionViewLayout+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionViewLayout+MJRefresh.m"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.m"; sourceTree = ""; }; - B9232C2E4F4A27C4FBD3F8EA3E351AF5 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = WebImage/PrivacyInfo.xcprivacy; sourceTree = ""; }; - B985D3DA018E1C8C3AC44ADE702B404B /* MJRefreshConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConfig.h; path = MJRefresh/MJRefreshConfig.h; sourceTree = ""; }; - B9AC91A4E70DD8F8592A5811E8617578 /* Masonry.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.debug.xcconfig; sourceTree = ""; }; - B9E85A8129A4E7BFE16B2262D78F1DCC /* MJRefreshConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConst.h; path = MJRefresh/MJRefreshConst.h; sourceTree = ""; }; - B9EF838DEDDB795D85E2F065BD697452 /* SDAssociatedObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAssociatedObject.h; path = SDWebImage/Private/SDAssociatedObject.h; sourceTree = ""; }; - BA48F14A970C2FE9AE9B9A3F4EF27D84 /* NSObject+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+Lookin.m"; path = "Src/Main/Shared/Category/NSObject+Lookin.m"; sourceTree = ""; }; - BB09D1C81119E88D019FD33037BC5587 /* UIImage+ForceDecode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ForceDecode.m"; path = "SDWebImage/Core/UIImage+ForceDecode.m"; sourceTree = ""; }; - BB20479CEB729CCB614B58BD2EFB3BB7 /* MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJProperty.h; path = MJExtension/MJProperty.h; sourceTree = ""; }; - BBC10C6127599FC7CD74CA6E613C44DB /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; - BCE109BED042388EE5FB3949ADA18281 /* MJExtensionConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJExtensionConst.m; path = MJExtension/MJExtensionConst.m; sourceTree = ""; }; - BD3AE781F5CE5DD3063848F6F78DD40B /* SDImageTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageTransformer.h; path = SDWebImage/Core/SDImageTransformer.h; sourceTree = ""; }; - BDD492D9CC4757F16B776F8B08A1A49F /* SDAsyncBlockOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAsyncBlockOperation.h; path = SDWebImage/Private/SDAsyncBlockOperation.h; sourceTree = ""; }; - BE6604D8C889F73372398B103D4FF327 /* Masonry-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Masonry-Info.plist"; sourceTree = ""; }; - BF679E0482D915265B5050368ABBB701 /* SDImageAPNGCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAPNGCoder.h; path = SDWebImage/Core/SDImageAPNGCoder.h; sourceTree = ""; }; - BF86BA22A3F81C27DE4346E22477D2CD /* SDImageIOAnimatedCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOAnimatedCoder.h; path = SDWebImage/Core/SDImageIOAnimatedCoder.h; sourceTree = ""; }; - C08BFCAD6B6021A9C9686DA64A6CF1AE /* LKS_CustomDisplayItemsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomDisplayItemsMaker.m; path = Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.m; sourceTree = ""; }; - C0AED8CDD333F60946EF309E2D789249 /* SDWebImageOptionsProcessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOptionsProcessor.h; path = SDWebImage/Core/SDWebImageOptionsProcessor.h; sourceTree = ""; }; - C23D52958B18447DC5C865BB12951C58 /* UILabel+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UILabel+LookinServer.m"; path = "Src/Main/Server/Category/UILabel+LookinServer.m"; sourceTree = ""; }; - C342060C11E55E0DDCC3A84C8C1FBC35 /* MJExtensionConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtensionConst.h; path = MJExtension/MJExtensionConst.h; sourceTree = ""; }; - C4BB81E05861A9C00B09F3A39D27B164 /* LookinServer-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LookinServer-dummy.m"; sourceTree = ""; }; - C59B65D3E951B3FDACD866C4564C0214 /* UIImage+MultiFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MultiFormat.h"; path = "SDWebImage/Core/UIImage+MultiFormat.h"; sourceTree = ""; }; - C6F66997EF28E05B21EB7F13B379645A /* AFNetworking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.release.xcconfig; sourceTree = ""; }; - C79FFC2722DEE9A1F54D8DBDD3CB2A2C /* MJRefreshAutoGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoGifFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h; sourceTree = ""; }; - C839ECCA7B6B8EF19AFC3658241117C8 /* SDImageCacheDefine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheDefine.m; path = SDWebImage/Core/SDImageCacheDefine.m; sourceTree = ""; }; - C9154FA9EFF76FE4C993ADDBEB9A5EE4 /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheOperation.h"; path = "SDWebImage/Core/UIView+WebCacheOperation.h"; sourceTree = ""; }; - CA67A34B63E36E76FF453D2ABD613A39 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; + B1850D4E22F95780586FA04DA695C24C /* Lookin_PTUSBHub.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Lookin_PTUSBHub.m; path = Src/Main/Shared/Peertalk/Lookin_PTUSBHub.m; sourceTree = ""; }; + B267D6EC269C7ADF7A4202363528E8C2 /* LookinAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttribute.m; path = Src/Main/Shared/LookinAttribute.m; sourceTree = ""; }; + B28192DA39251C0AC1C30AE245A9A547 /* JXCategoryTitleImageCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleImageCellModel.m; path = Sources/TitleImage/JXCategoryTitleImageCellModel.m; sourceTree = ""; }; + B2B7D0FDFC6ECF60B59728E60160431B /* LookinConnectionResponseAttachment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinConnectionResponseAttachment.m; path = Src/Main/Shared/LookinConnectionResponseAttachment.m; sourceTree = ""; }; + B2C2A4CA80B5FE7CB8927FAEE4CAF5F4 /* SDImageCacheDefine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheDefine.h; path = SDWebImage/Core/SDImageCacheDefine.h; sourceTree = ""; }; + B2CE10A014B3B7826BFF751346CE7495 /* SDWebImageDownloaderRequestModifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderRequestModifier.h; path = SDWebImage/Core/SDWebImageDownloaderRequestModifier.h; sourceTree = ""; }; + B3443BE7FBE80A857A146093C743D9BF /* JXCategoryIndicatorImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorImageView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.m; sourceTree = ""; }; + B4319C3394898C8897D6580DAC5A5124 /* JXPagingView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JXPagingView-umbrella.h"; sourceTree = ""; }; + B453C947A0F7F0133F2F98F9E8EF1E43 /* SDWebImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloader.m; path = SDWebImage/Core/SDWebImageDownloader.m; sourceTree = ""; }; + B4750EDA171CA7EB95AFE62489A712EF /* JXCategoryViewDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryViewDefines.h; path = Sources/Common/JXCategoryViewDefines.h; sourceTree = ""; }; + B49837A2AA042F710F43F143A929D49F /* JXCategoryTitleCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleCell.m; path = Sources/Title/JXCategoryTitleCell.m; sourceTree = ""; }; + B49F76B93F72D361782D7DA99B65ADC9 /* JXCategoryIndicatorLineView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorLineView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorLineView.m; sourceTree = ""; }; + B4F7FC0CFCBE2143A4999C2F356D2B47 /* SDWebImageCacheKeyFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCacheKeyFilter.h; path = SDWebImage/Core/SDWebImageCacheKeyFilter.h; sourceTree = ""; }; + B5157027D16B7E61C1D5AB091D10458E /* LookinTuple.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinTuple.m; path = Src/Main/Shared/LookinTuple.m; sourceTree = ""; }; + B5885DEE0FCB371101A605FDA3D3F35C /* LYEmptyBaseView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LYEmptyBaseView.h; path = LYEmptyView/LYEmptyBaseView.h; sourceTree = ""; }; + B5A6B26A93BDE64568CF7AF44D709974 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; + B5F6ED51FA52849CB3D9D44DD45396E2 /* SDDisplayLink.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDisplayLink.h; path = SDWebImage/Private/SDDisplayLink.h; sourceTree = ""; }; + B6242B29A00A9DBC6FF1CD09266BBF54 /* MJRefreshGifHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshGifHeader.m; path = MJRefresh/Custom/Header/MJRefreshGifHeader.m; sourceTree = ""; }; + B628043D13CE1145E17714D58AB2A687 /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; + B6575913AB2C7FDA723D279165349FF6 /* NSObject+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+Lookin.m"; path = "Src/Main/Shared/Category/NSObject+Lookin.m"; sourceTree = ""; }; + B6ED434773EE7ECEDAB93E7A62107F73 /* FLAnimatedImage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FLAnimatedImage.modulemap; sourceTree = ""; }; + B705DD8FCD54B3AFD61B70C82828ACE4 /* SDAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "SDAnimatedImageView+WebCache.h"; path = "SDWebImage/Core/SDAnimatedImageView+WebCache.h"; sourceTree = ""; }; + B70A750F053AB9B0B60CBF456ED577A9 /* JXCategoryTitleCellModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleCellModel.m; path = Sources/Title/JXCategoryTitleCellModel.m; sourceTree = ""; }; + B74E719F2E64B3E186B6F4B672482329 /* LSTTimer-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LSTTimer-Info.plist"; sourceTree = ""; }; + B75E67C2319B8FDBF4D6263203A06D6B /* SDImageIOAnimatedCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOAnimatedCoder.h; path = SDWebImage/Core/SDImageIOAnimatedCoder.h; sourceTree = ""; }; + B77422F87DF00923771B3EF8E6C0A9BF /* UITableView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITableView+LookinServer.m"; path = "Src/Main/Server/Category/UITableView+LookinServer.m"; sourceTree = ""; }; + B82D0099E75E96FE5ACCF5B647388551 /* JXCategoryFactory.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryFactory.m; path = Sources/Common/JXCategoryFactory.m; sourceTree = ""; }; + B8322800FD1F06BC2FEA3A9EEA874E20 /* DZNEmptyDataSet-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DZNEmptyDataSet-dummy.m"; sourceTree = ""; }; + B87895ABF5221A865DF2D53247763F89 /* SDWebImageCompat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCompat.h; path = SDWebImage/Core/SDWebImageCompat.h; sourceTree = ""; }; + B8F1319B150BB3DBD94BEB4C80F6F296 /* UIScrollView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJExtension.m"; path = "MJRefresh/UIScrollView+MJExtension.m"; sourceTree = ""; }; + B915A35174E3017D6DC61C0A3E31050E /* LookinAttributeModification.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttributeModification.h; path = Src/Main/Shared/LookinAttributeModification.h; sourceTree = ""; }; + B92B905C66437721BB933FEDA5B00CB4 /* SDImageIOAnimatedCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageIOAnimatedCoder.m; path = SDWebImage/Core/SDImageIOAnimatedCoder.m; sourceTree = ""; }; + B95FDE5F86C6AC76E24A82E181084256 /* UIViewController+PanModalDefault.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+PanModalDefault.m"; path = "Sources/Presentable/UIViewController+PanModalDefault.m"; sourceTree = ""; }; + B9CA9F01554205BFBACCA553143C8676 /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; + B9E1D06297B630EA32D1369915C0CB97 /* SDImageLoader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageLoader.m; path = SDWebImage/Core/SDImageLoader.m; sourceTree = ""; }; + BB4F011171FCB76B1AEBE390F843E930 /* JXCategoryView-JXCategoryView */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "JXCategoryView-JXCategoryView"; path = JXCategoryView.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + BBA58A99F7E528A8D41BD96706230160 /* MJRefreshBackGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackGifFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h; sourceTree = ""; }; + BC30CFC7778FEADF9DCBF0A4ABA1769C /* SDImageAWebPCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAWebPCoder.m; path = SDWebImage/Core/SDImageAWebPCoder.m; sourceTree = ""; }; + BC7F3F9323470C634DC0D469E7C13B10 /* MJRefreshAutoGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoGifFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m; sourceTree = ""; }; + BCDE5AFCF524DCA9CD59B6F4A4738325 /* HWPanModalIndicatorProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalIndicatorProtocol.h; path = Sources/View/HWPanModalIndicatorProtocol.h; sourceTree = ""; }; + BCF14CEE3203A4E740B9A9FD66CCABA4 /* MJFoundation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJFoundation.m; path = MJExtension/MJFoundation.m; sourceTree = ""; }; + BD243AB5EB0FB2763BBC742A8BCF80DD /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; + BD3BC591D3DAF10375616FB7F294F926 /* Masonry-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Masonry-Info.plist"; sourceTree = ""; }; + BD430BA3E5DB115A0F8BF9D6110923AE /* SDWebImageCacheSerializer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCacheSerializer.h; path = SDWebImage/Core/SDWebImageCacheSerializer.h; sourceTree = ""; }; + BDB258BF0BE17AFC3BFB4FB942403B82 /* SDAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImage.m; path = SDWebImage/Core/SDAnimatedImage.m; sourceTree = ""; }; + BDEE6097B6411333154FEF90A280E3E4 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + BE1A1849BD6BB4B796D54DCBEF79FB7A /* UICollectionViewLayout+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionViewLayout+MJRefresh.m"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.m"; sourceTree = ""; }; + BE9E061AE26F933A7BBEFF3D94E9B32D /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; + BF0EE7E880EA65C279154531EF91F5E8 /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; + BF141C03BAA67847DFB6B6DFF0D1CBFC /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; + BF31B533FDEE0B0DA7ED824B4F336534 /* SDImageFramePool.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageFramePool.m; path = SDWebImage/Private/SDImageFramePool.m; sourceTree = ""; }; + BF3C6AEB909F4472F8D8E4E21B25B716 /* SDImageAWebPCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageAWebPCoder.h; path = SDWebImage/Core/SDImageAWebPCoder.h; sourceTree = ""; }; + C00601FB0A8CFBE203150BAEC58E95FC /* LYEmptyView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LYEmptyView-umbrella.h"; sourceTree = ""; }; + C19EBB7B5E5A5B4CB83F93B794EA02A1 /* LKS_CustomDisplayItemsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomDisplayItemsMaker.m; path = Src/Main/Server/Others/LKS_CustomDisplayItemsMaker.m; sourceTree = ""; }; + C1D06F4343D9C630BC102E7BCD9CECCF /* NSSet+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSSet+Lookin.h"; path = "Src/Main/Shared/Category/NSSet+Lookin.h"; sourceTree = ""; }; + C202F1C5D8455CDDCAE965BD7BAAFC3B /* SDMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDMemoryCache.m; path = SDWebImage/Core/SDMemoryCache.m; sourceTree = ""; }; + C31C4A7197700436AFBAB631C088A6AE /* JXCategoryIndicatorTriangleView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorTriangleView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.m; sourceTree = ""; }; + C398AC4FA166ECBDBFA37681D3C108CC /* JXCategoryIndicatorDotLineView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorDotLineView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.h; sourceTree = ""; }; + C3A46B03C308EEEB11F2A62BA5D2E8BE /* JXCategoryView */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = JXCategoryView; path = JXCategoryView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C3D9450A4AAE9542E6A1A0473B7DF812 /* SDImageCacheConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheConfig.m; path = SDWebImage/Core/SDImageCacheConfig.m; sourceTree = ""; }; + C3DBF2503619D6F278D203DBF5D29B4E /* AFAutoPurgingImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFAutoPurgingImageCache.h; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.h"; sourceTree = ""; }; + C41AE199679E3EEC03FA1272FE103027 /* UIBlurEffect+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIBlurEffect+LookinServer.h"; path = "Src/Main/Server/Category/UIBlurEffect+LookinServer.h"; sourceTree = ""; }; + C45DF4498F0949CD4F02FA86BFE50D93 /* SDImageTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageTransformer.m; path = SDWebImage/Core/SDImageTransformer.m; sourceTree = ""; }; + C4D51AE584C5960F5C6B60C866377741 /* JXCategoryTitleVerticalZoomCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleVerticalZoomCellModel.h; path = Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCellModel.h; sourceTree = ""; }; + C5D725B550FCED60C80870F1B120D3B4 /* HWShoppingCartPresentingAnimation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWShoppingCartPresentingAnimation.m; path = Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.m; sourceTree = ""; }; + C63CFE9D73B31D9EBEF51E32F9AC7286 /* JXCategoryListContainerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryListContainerView.m; path = Sources/Common/JXCategoryListContainerView.m; sourceTree = ""; }; + C644FF26241C14C759578567892EF00D /* HWPanModalPresentableHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresentableHandler.h; path = Sources/Mediator/HWPanModalPresentableHandler.h; sourceTree = ""; }; + C64A52A00F5D8A13BA6BD40D1834BF56 /* UITextField+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextField+LookinServer.m"; path = "Src/Main/Server/Category/UITextField+LookinServer.m"; sourceTree = ""; }; + C6553D3214536278C24D990CC36267F3 /* Image+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "Image+Lookin.m"; path = "Src/Main/Shared/Category/Image+Lookin.m"; sourceTree = ""; }; + C74EA9D59FFCBE16D0C0E5B7B2D53516 /* SDImageCacheDefine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheDefine.m; path = SDWebImage/Core/SDImageCacheDefine.m; sourceTree = ""; }; + C75FCCDECEB6A92A56B67E27033473B6 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; + C7F42FC60A06A5673FA7DE53298188E2 /* LKS_TraceManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_TraceManager.m; path = Src/Main/Server/Others/LKS_TraceManager.m; sourceTree = ""; }; + C81473AB6162F68681F317D8EC207A4C /* LKS_GestureTargetActionsSearcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_GestureTargetActionsSearcher.m; path = Src/Main/Server/Others/LKS_GestureTargetActionsSearcher.m; sourceTree = ""; }; + C86FEA7FA982FA034501F7AB37760D49 /* JXCategoryDotView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryDotView.m; path = Sources/Dot/JXCategoryDotView.m; sourceTree = ""; }; + C8ED101794ADA1876F4FFCBD1F79D622 /* SDImageLoader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageLoader.h; path = SDWebImage/Core/SDImageLoader.h; sourceTree = ""; }; + C909F8904D301FB96965DD62CE4E2CA7 /* SDWebImageCacheKeyFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCacheKeyFilter.m; path = SDWebImage/Core/SDWebImageCacheKeyFilter.m; sourceTree = ""; }; + C94F3031AB6C5451E9610DBD24FE9029 /* SDAnimatedImageRep.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageRep.m; path = SDWebImage/Core/SDAnimatedImageRep.m; sourceTree = ""; }; + C98FF255A58DDF6F211BD72458B9C3D0 /* LSTPopView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LSTPopView-dummy.m"; sourceTree = ""; }; + C9A08CB30EFC3A6CB342354C253BE4D8 /* NSString+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+Lookin.m"; path = "Src/Main/Shared/Category/NSString+Lookin.m"; sourceTree = ""; }; + C9E1D6C567F43B4A9410AC83170573DE /* LookinAttrType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttrType.h; path = Src/Main/Shared/LookinAttrType.h; sourceTree = ""; }; + CA665BB1B8AEA701C3C1A72312BFE105 /* HWPanModal.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HWPanModal.release.xcconfig; sourceTree = ""; }; CAD1D653361EAFCC0E4FFD8252FC1E74 /* Pods-CustomKeyboard.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-CustomKeyboard.modulemap"; sourceTree = ""; }; - CAE0A8B09C0AF83117C6BC9602D5D41F /* UITableView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITableView+LookinServer.h"; path = "Src/Main/Server/Category/UITableView+LookinServer.h"; sourceTree = ""; }; - CBCBBB0099A9339A1A8ABBEDF291AF92 /* SDWebImageCompat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCompat.h; path = SDWebImage/Core/SDWebImageCompat.h; sourceTree = ""; }; - CC47954DDA2CCCD6E92132955A0DE728 /* NSImage+Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSImage+Compatibility.h"; path = "SDWebImage/Core/NSImage+Compatibility.h"; sourceTree = ""; }; - CC6EC6E349C4E8476F9617E9150D43FE /* NSObject+MJCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJCoding.h"; path = "MJExtension/NSObject+MJCoding.h"; sourceTree = ""; }; - CDE77633CA7FA3526B2AA79AB5F21A42 /* SDWebImagePrefetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImagePrefetcher.m; path = SDWebImage/Core/SDWebImagePrefetcher.m; sourceTree = ""; }; - CE89275D8F89A11FB2761E0461236313 /* SDWebImageError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageError.m; path = SDWebImage/Core/SDWebImageError.m; sourceTree = ""; }; - CEC88A03608F444860F81FB5EB689938 /* UITextField+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextField+LookinServer.m"; path = "Src/Main/Server/Category/UITextField+LookinServer.m"; sourceTree = ""; }; + CAE21A3C562355122DA705E505CCA673 /* LookinAttributesSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttributesSection.h; path = Src/Main/Shared/LookinAttributesSection.h; sourceTree = ""; }; + CB5214881D82D6C122FB4D3B471F9D93 /* LKS_ObjectRegistry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_ObjectRegistry.m; path = Src/Main/Server/Others/LKS_ObjectRegistry.m; sourceTree = ""; }; + CBB2B3782C3C4626F075A8900436D09D /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; + CBD58A6BE5B4D23DDB42D3D26A87CAEA /* SDWebImageDownloaderConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderConfig.h; path = SDWebImage/Core/SDWebImageDownloaderConfig.h; sourceTree = ""; }; + CD6BC672271DF551FD22D8BABC528CA6 /* LKS_EventHandlerMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_EventHandlerMaker.m; path = Src/Main/Server/Others/LKS_EventHandlerMaker.m; sourceTree = ""; }; + CDE56910104E914C73DC565FDFEABE34 /* HWPanModal-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HWPanModal-Info.plist"; sourceTree = ""; }; + CE2B5265F3721FD7EAE15556CCDB1151 /* NSButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSButton+WebCache.h"; path = "SDWebImage/Core/NSButton+WebCache.h"; sourceTree = ""; }; + CE5782C68BCDC8C49DD74B206B3FFFF1 /* LSTTimer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LSTTimer.m; path = LSTTimer/Classes/LSTTimer.m; sourceTree = ""; }; CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "SDWebImage-SDWebImage"; path = SDWebImage.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - CFBDDF0554D720E199E1094AAEC3D171 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; }; - D03549B19B7C1700178CF12088FCE44C /* LookinTuple.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinTuple.m; path = Src/Main/Shared/LookinTuple.m; sourceTree = ""; }; - D15A23E7684648249EA4D7C312BACC22 /* MJPropertyType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyType.m; path = MJExtension/MJPropertyType.m; sourceTree = ""; }; - D197698AA79A94AD39EC006BBB9D3481 /* MJPropertyKey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyKey.h; path = MJExtension/MJPropertyKey.h; sourceTree = ""; }; - D219431FF998A6D0FA270965A4CDE56D /* MBProgressHUD-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-umbrella.h"; sourceTree = ""; }; - D226F4D7ADA4D7570E831057BF0F25E7 /* MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJRefresh-Info.plist"; sourceTree = ""; }; - D23D41020809113858D4CA46059797CF /* LookinStaticAsyncUpdateTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinStaticAsyncUpdateTask.h; path = Src/Main/Shared/LookinStaticAsyncUpdateTask.h; sourceTree = ""; }; - D2BBA8DCCC9E2658211368C22BE1B033 /* MJRefresh.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.debug.xcconfig; sourceTree = ""; }; - D3412473E790C600A01CFF5127EA049C /* MBProgressHUD-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MBProgressHUD-Info.plist"; sourceTree = ""; }; - D3A9927A87E21A8976D18DC44FE50014 /* MJRefreshStateHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateHeader.m; path = MJRefresh/Custom/Header/MJRefreshStateHeader.m; sourceTree = ""; }; - D3C9902E0E2D0A78C2A349E20322FC80 /* AFImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFImageDownloader.h; path = "UIKit+AFNetworking/AFImageDownloader.h"; sourceTree = ""; }; - D404BDF65C17843DC41C1611EAAA22EB /* MJRefreshAutoFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoFooter.m; path = MJRefresh/Base/MJRefreshAutoFooter.m; sourceTree = ""; }; - D4D2347D4EFB2E5610773AF965AA8399 /* LookinCustomDisplayItemInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinCustomDisplayItemInfo.h; path = Src/Main/Shared/LookinCustomDisplayItemInfo.h; sourceTree = ""; }; - D54A6D034409C4B729B7DBA2D502B89D /* UITextView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextView+LookinServer.m"; path = "Src/Main/Server/Category/UITextView+LookinServer.m"; sourceTree = ""; }; - D5509360DE46CF0B8D64058FE9FD45E8 /* MJRefreshHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshHeader.h; path = MJRefresh/Base/MJRefreshHeader.h; sourceTree = ""; }; - D601D33EE8BB8396FF4AED582379432E /* SDImageLoadersManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageLoadersManager.m; path = SDWebImage/Core/SDImageLoadersManager.m; sourceTree = ""; }; - D673941813D9CA4EFFC6C32109054DC5 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; - D6A9452B8FC36F44EC5608AB04827703 /* UIColor+SDHexString.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+SDHexString.h"; path = "SDWebImage/Private/UIColor+SDHexString.h"; sourceTree = ""; }; - D6C233C8BB873C737FFE3E1DFBC2A186 /* SDDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDiskCache.m; path = SDWebImage/Core/SDDiskCache.m; sourceTree = ""; }; - D6E369F88941EA9A46AF58BC88CC0720 /* UIScrollView+EmptyDataSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+EmptyDataSet.h"; path = "Source/UIScrollView+EmptyDataSet.h"; sourceTree = ""; }; + CF46C0579CB3C54966C0F025487DB215 /* JXPagerSmoothView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXPagerSmoothView.m; path = Sources/JXPagerView/JXPagerSmoothView.m; sourceTree = ""; }; + CF6ABA6691731EEA533F56170FB03C5C /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheOperation.h"; path = "SDWebImage/Core/UIView+WebCacheOperation.h"; sourceTree = ""; }; + CF7B4B9CB0EF762A12884D6FE337E068 /* HWPanModalAnimator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalAnimator.h; path = Sources/Animator/HWPanModalAnimator.h; sourceTree = ""; }; + CF91BA63B659D0E10C9E123EBEAB8FA3 /* UIImage+ForceDecode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ForceDecode.m"; path = "SDWebImage/Core/UIImage+ForceDecode.m"; sourceTree = ""; }; + CFC8ED8D34DD2679124911EB0F515607 /* LookinObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinObject.m; path = Src/Main/Shared/LookinObject.m; sourceTree = ""; }; + D00729EFDA62359B2F2AA1EF43FADFD9 /* LKS_CustomAttrModificationHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomAttrModificationHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.m; sourceTree = ""; }; + D0B1EDD790AB62D80A6CA23D5272938B /* LookinAttributesGroup.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttributesGroup.m; path = Src/Main/Shared/LookinAttributesGroup.m; sourceTree = ""; }; + D1046C4A0F4D596969B881D83BCC0FA1 /* FLAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImage.m; path = FLAnimatedImage/FLAnimatedImage.m; sourceTree = ""; }; + D25C8F67455D872A48F4797213321EA4 /* JXCategoryIndicatorRainbowLineView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorRainbowLineView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.h; sourceTree = ""; }; + D30B8333D334528105E28100C243348D /* MBProgressHUD-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MBProgressHUD-dummy.m"; sourceTree = ""; }; + D3FD4542A2D174FC95524833AB672073 /* JXPagingView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = JXPagingView.release.xcconfig; sourceTree = ""; }; + D411D25D78A2F9E3CF17B20443ED9F40 /* MJRefreshNormalHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalHeader.h; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.h; sourceTree = ""; }; + D444527057532BACBF8EC98BE62D3E03 /* SDGraphicsImageRenderer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDGraphicsImageRenderer.h; path = SDWebImage/Core/SDGraphicsImageRenderer.h; sourceTree = ""; }; + D44C8E719DA4251716FDA4B2519C022D /* NSObject+MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJProperty.m"; path = "MJExtension/NSObject+MJProperty.m"; sourceTree = ""; }; + D4CFF1EB3CBDD5217E39DD58BD101359 /* LookinEventHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinEventHandler.m; path = Src/Main/Shared/LookinEventHandler.m; sourceTree = ""; }; + D5119B7CF0FE429CF0E185983E72F98F /* JXCategoryNumberView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryNumberView.m; path = Sources/Number/JXCategoryNumberView.m; sourceTree = ""; }; + D51E4D4230E01D5F3D9340BDF320C3E1 /* JXCategoryImageCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryImageCellModel.h; path = Sources/Image/JXCategoryImageCellModel.h; sourceTree = ""; }; + D564B14F434E85E8016FF192E33548A8 /* JXPagerMainTableView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXPagerMainTableView.h; path = Sources/JXPagerView/JXPagerMainTableView.h; sourceTree = ""; }; + D5909A44E1AC01893309CADDDBC4E50C /* UILabel+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UILabel+LookinServer.h"; path = "Src/Main/Server/Category/UILabel+LookinServer.h"; sourceTree = ""; }; + D5BBA19EC013D7414BE28B29DCA7518D /* FLAnimatedImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FLAnimatedImage.release.xcconfig; sourceTree = ""; }; + D68722AFBA338282E0B3C89AFE0F83AC /* JXCategoryIndicatorBackgroundView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorBackgroundView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.m; sourceTree = ""; }; D742A7EF918BC67B0884AF366F7415FD /* Pods-CustomKeyboard-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CustomKeyboard-acknowledgements.plist"; sourceTree = ""; }; - D8E5E1F0B039F76947E77470F619AB22 /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; - D950E8533947A1D8B1CABC80463AFF52 /* UIBlurEffect+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIBlurEffect+LookinServer.m"; path = "Src/Main/Server/Category/UIBlurEffect+LookinServer.m"; sourceTree = ""; }; - D9B1F5912311585292CF1DB19B5FF418 /* MJFoundation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJFoundation.h; path = MJExtension/MJFoundation.h; sourceTree = ""; }; - DB89640D4CA100127D613D0379809B5A /* SDAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageView.h; path = SDWebImage/Core/SDAnimatedImageView.h; sourceTree = ""; }; - DC3E4B841669D08E886FD8D7A86C654E /* LookinDisplayItemDetail.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinDisplayItemDetail.m; path = Src/Main/Shared/LookinDisplayItemDetail.m; sourceTree = ""; }; + D7C0280DF79D384D6CBED6E080E02BB8 /* LSTPopView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LSTPopView-umbrella.h"; sourceTree = ""; }; + D7F6132E07FDE40130D6C51920456A21 /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; + D8B8A062E76BF87D54F581F6428D4E28 /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; + D98B4BEA4820634A8F01172731FF97B7 /* JXCategoryView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "JXCategoryView-dummy.m"; sourceTree = ""; }; + D9BB987ADE61FFDF3C240961F2EB4DDB /* LookinConnectionResponseAttachment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinConnectionResponseAttachment.h; path = Src/Main/Shared/LookinConnectionResponseAttachment.h; sourceTree = ""; }; + D9CF33220A4EDFF59077DE1F83605414 /* JXCategoryListContainerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryListContainerView.h; path = Sources/Common/JXCategoryListContainerView.h; sourceTree = ""; }; + DA08E928976E65BC11D71562A0E4FBA2 /* LSTPopView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LSTPopView-prefix.pch"; sourceTree = ""; }; + DA0C012CAB8552E7EA8382B0E5D6B738 /* UIImageView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+LookinServer.m"; path = "Src/Main/Server/Category/UIImageView+LookinServer.m"; sourceTree = ""; }; + DA49453EBB9C905AD701D17F18479113 /* LKS_ConnectionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_ConnectionManager.m; path = Src/Main/Server/Connection/LKS_ConnectionManager.m; sourceTree = ""; }; + DB1B5D6DA097974C176F91F3853055EC /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; + DB3B6BBCBC04C438F099DE5DEC15C188 /* UIViewController+Presentation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+Presentation.h"; path = "Sources/Presentable/UIViewController+Presentation.h"; sourceTree = ""; }; + DB48FEC8123075E04395CF34F6F8227D /* HWPanModalPresentationAnimator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresentationAnimator.h; path = Sources/Animator/HWPanModalPresentationAnimator.h; sourceTree = ""; }; + DB7D4CE7BA063A9CA415CD86C8825985 /* LSTPopView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LSTPopView.h; path = LSTPopView/Classes/Code/LSTPopView.h; sourceTree = ""; }; + DBFA6FCFCE1CB3F169BDBDCE936950B5 /* LKS_ObjectRegistry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_ObjectRegistry.h; path = Src/Main/Server/Others/LKS_ObjectRegistry.h; sourceTree = ""; }; + DC7496C927F9E881D19A203C207B5417 /* UIView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+LookinServer.h"; path = "Src/Main/Server/Category/UIView+LookinServer.h"; sourceTree = ""; }; + DC85B08C4C82F12C3AA7970FE44E1D9F /* UIColor+SDHexString.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+SDHexString.h"; path = "SDWebImage/Private/UIColor+SDHexString.h"; sourceTree = ""; }; DCA062FD08AC9694D8D781B3492421C5 /* Pods-keyBoard */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-keyBoard"; path = Pods_keyBoard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DCB771163568003A2EA8F4B1A606B9ED /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; DCFE00F3CC8CED67258D7F7DD13F3156 /* Pods-keyBoard-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-keyBoard-frameworks.sh"; sourceTree = ""; }; - DD9F495B1E192CA5A7EA012DC8524457 /* UIImage+Transform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Transform.m"; path = "SDWebImage/Core/UIImage+Transform.m"; sourceTree = ""; }; - DE365B0506D97BB22271ACD3BE9D48CC /* MJExtension.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJExtension.modulemap; sourceTree = ""; }; - DE5E3242D0D245F39B1349B5C4819144 /* LookinAppInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAppInfo.m; path = Src/Main/Shared/LookinAppInfo.m; sourceTree = ""; }; - DE6C055C722C44DA0E562F93906DCD34 /* LKS_EventHandlerMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_EventHandlerMaker.h; path = Src/Main/Server/Others/LKS_EventHandlerMaker.h; sourceTree = ""; }; - DE9EB519F0B4BF7D539877F733F7BCAF /* SDInternalMacros.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDInternalMacros.m; path = SDWebImage/Private/SDInternalMacros.m; sourceTree = ""; }; - DECAD058B2FE8CD24CC1022B0A1523AB /* LKS_ExportManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_ExportManager.h; path = Src/Main/Server/Others/LKS_ExportManager.h; sourceTree = ""; }; - DF2FF7F81EC1FE20B9F8B3879085D4FA /* SDWebImageCacheKeyFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCacheKeyFilter.h; path = SDWebImage/Core/SDWebImageCacheKeyFilter.h; sourceTree = ""; }; - DF383723C6CD6F7B6FCFE6C752DF50AF /* MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJProperty.m; path = MJExtension/MJProperty.m; sourceTree = ""; }; - DF57705B90AB01302C42302B6BB038DD /* SDImageTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageTransformer.m; path = SDWebImage/Core/SDImageTransformer.m; sourceTree = ""; }; - E05CD820CF8075CB902341061803D784 /* LookinIvarTrace.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinIvarTrace.h; path = Src/Base/LookinIvarTrace.h; sourceTree = ""; }; - E0E79E8251323154CB271295CCD93D0A /* MJRefreshStateHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateHeader.h; path = MJRefresh/Custom/Header/MJRefreshStateHeader.h; sourceTree = ""; }; - E1C46B6B074DF2D170E6F2ACB5E8C8BA /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; - E1DF8BF780A4AD9606856AB857CA1D86 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - E1E6BDC6A27A05429814F2520B890A63 /* SDImageIOCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageIOCoder.m; path = SDWebImage/Core/SDImageIOCoder.m; sourceTree = ""; }; + DD2F0E472487CBFBA5CA4F3C62C1BB0B /* NSObject+MJCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJCoding.h"; path = "MJExtension/NSObject+MJCoding.h"; sourceTree = ""; }; + DE0511947F57D1CF3F274B6414AE449B /* UIScrollView+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJRefresh.h"; path = "MJRefresh/UIScrollView+MJRefresh.h"; sourceTree = ""; }; + DE19C7D984CBC535E4768F5543458A1E /* LSTTimer */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = LSTTimer; path = LSTTimer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DE378B71C4559C86FA84F1AB2F15BD03 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; + DE4F66BD16AF47C58F5E08D62D7916E3 /* HWPanModalPresenterProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresenterProtocol.h; path = Sources/Presenter/HWPanModalPresenterProtocol.h; sourceTree = ""; }; + DE7E60B5B6A0850596F935D95CAFE167 /* MJRefreshAutoFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoFooter.h; path = MJRefresh/Base/MJRefreshAutoFooter.h; sourceTree = ""; }; + DEDA7D852A16AEB2E4133F8138BB40A3 /* NSObject+MJClass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJClass.h"; path = "MJExtension/NSObject+MJClass.h"; sourceTree = ""; }; + DEEA81C89F22AF300ABFA4E5550B7B06 /* SDImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCache.h; path = SDWebImage/Core/SDImageCache.h; sourceTree = ""; }; + DEFCE7D8BFD813860A380F7F5B5EB401 /* LKS_AttrModificationPatchHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_AttrModificationPatchHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_AttrModificationPatchHandler.m; sourceTree = ""; }; + DF017A36F518C19E10298190FD8A84C4 /* LKS_RequestHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_RequestHandler.m; path = Src/Main/Server/Connection/LKS_RequestHandler.m; sourceTree = ""; }; + DF80C06856CA889ADB8807594055C7DF /* JXCategoryView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = JXCategoryView.release.xcconfig; sourceTree = ""; }; + DF85367F662269F3652AFC693AA2B00F /* LookinAppInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAppInfo.m; path = Src/Main/Shared/LookinAppInfo.m; sourceTree = ""; }; + DFE214BE294126C1B4FFE49DDADA7AEE /* SDImageCachesManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCachesManager.m; path = SDWebImage/Core/SDImageCachesManager.m; sourceTree = ""; }; + E00B4B67B95B1D4B1001EF45F23EF0C4 /* LYEmptyView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LYEmptyView.release.xcconfig; sourceTree = ""; }; + E01ADBA325921AF74B0FBD58F7BB5032 /* JXCategoryTitleCellModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryTitleCellModel.h; path = Sources/Title/JXCategoryTitleCellModel.h; sourceTree = ""; }; + E03F152E95B6924D2486511337D24503 /* JXPagingView-JXPagerView */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "JXPagingView-JXPagerView"; path = JXPagerView.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + E0742EB318197474CB672E4520705ACC /* JXPagerListContainerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXPagerListContainerView.m; path = Sources/JXPagerView/JXPagerListContainerView.m; sourceTree = ""; }; + E0DD4370E4AF2D75716AE1B5D67EABEB /* SDWebImageIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageIndicator.h; path = SDWebImage/Core/SDWebImageIndicator.h; sourceTree = ""; }; E214C17CF404D45BDF92DD6C18D371FA /* Pods-keyBoard-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-keyBoard-acknowledgements.markdown"; sourceTree = ""; }; - E25013592494E49EB3F378AA4A68FB7A /* MJRefreshNormalTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m; sourceTree = ""; }; - E321D3F90B0E3A7E45F64EB551639098 /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; - E3ADFF983A9B025AF718C3D24404E480 /* UIView+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+LookinServer.m"; path = "Src/Main/Server/Category/UIView+LookinServer.m"; sourceTree = ""; }; - E4000AF0B9EEE3F891ADD766B1967BD3 /* LKS_RequestHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_RequestHandler.h; path = Src/Main/Server/Connection/LKS_RequestHandler.h; sourceTree = ""; }; + E23048DA7D038B179D12173BA0F800DB /* LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinServer.h; path = Src/Main/Server/LookinServer.h; sourceTree = ""; }; + E312EC8FB74A492C6D5A647700644AC4 /* NSSet+Lookin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSSet+Lookin.m"; path = "Src/Main/Shared/Category/NSSet+Lookin.m"; sourceTree = ""; }; + E368F7BC820788B717CC047A744E4326 /* SDImageCacheConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheConfig.h; path = SDWebImage/Core/SDImageCacheConfig.h; sourceTree = ""; }; + E386525610DF7AB4E84ED0202969AB8E /* FLAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImage.h; path = FLAnimatedImage/include/FLAnimatedImage.h; sourceTree = ""; }; + E38A10934CB29F9B2C75A0785209FA84 /* SDWebImageDownloaderDecryptor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderDecryptor.m; path = SDWebImage/Core/SDWebImageDownloaderDecryptor.m; sourceTree = ""; }; + E45A9679E38D826E316675D8F368F69C /* MJRefreshBackNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackNormalFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h; sourceTree = ""; }; + E4718E4C19C181FBAEBD080580F8C026 /* SDImageIOCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOCoder.h; path = SDWebImage/Core/SDImageIOCoder.h; sourceTree = ""; }; E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MJRefresh; path = MJRefresh.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E5514D264E4855320B70B7010325576C /* SDImageGIFCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageGIFCoder.m; path = SDWebImage/Core/SDImageGIFCoder.m; sourceTree = ""; }; - E5F4E4918198D7216ABDC0BE4C9BFCE9 /* AFCompatibilityMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFCompatibilityMacros.h; path = AFNetworking/AFCompatibilityMacros.h; sourceTree = ""; }; - E603FC069FE0FF9249D8A7348F6E7795 /* MJRefreshTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshTrailer.h; path = MJRefresh/Base/MJRefreshTrailer.h; sourceTree = ""; }; - E614E7E1FA6658E0B9CF44C05D4E6811 /* UIImage+Metadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Metadata.h"; path = "SDWebImage/Core/UIImage+Metadata.h"; sourceTree = ""; }; - E66FFAE76E02A3342AF857261F059F70 /* NSObject+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+LookinServer.m"; path = "Src/Main/Server/Category/NSObject+LookinServer.m"; sourceTree = ""; }; - E70A8D54BBD1266CC7CAFB4BD5CE317B /* LookinObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinObject.h; path = Src/Main/Shared/LookinObject.h; sourceTree = ""; }; - E70D2DE5FE013503515AE432AE16071A /* SDAsyncBlockOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDAsyncBlockOperation.m; path = SDWebImage/Private/SDAsyncBlockOperation.m; sourceTree = ""; }; - E727648E6DB0C84B6B5C85D16CF9D6AC /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; - E785CD9E03330FEEAB8EA2F65DA92853 /* LookinTuple.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinTuple.h; path = Src/Main/Shared/LookinTuple.h; sourceTree = ""; }; - E7FE66EE9C43A4BD03E9F354FADF7098 /* MJRefreshGifHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshGifHeader.h; path = MJRefresh/Custom/Header/MJRefreshGifHeader.h; sourceTree = ""; }; - E857EC016B703D1261AC73360907C980 /* CALayer+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CALayer+Lookin.h"; path = "Src/Main/Shared/Category/CALayer+Lookin.h"; sourceTree = ""; }; - E91E93486D40A052515660F00B079B5A /* LKS_InbuiltAttrModificationHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_InbuiltAttrModificationHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_InbuiltAttrModificationHandler.h; sourceTree = ""; }; - E9ED096883562D4C47E188D0E5CB3065 /* LookinDisplayItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinDisplayItem.m; path = Src/Main/Shared/LookinDisplayItem.m; sourceTree = ""; }; - E9FADEFBF123E3EB09754AA63F0510E1 /* UITextView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextView+LookinServer.h"; path = "Src/Main/Server/Category/UITextView+LookinServer.h"; sourceTree = ""; }; - EA281F7D07872BD2CB3C821E84CCC544 /* LKS_AttrGroupsMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_AttrGroupsMaker.m; path = Src/Main/Server/Others/LKS_AttrGroupsMaker.m; sourceTree = ""; }; - EA4BA3056A1FE6B47E97AA549D4B9423 /* SDWebImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SDWebImage-dummy.m"; sourceTree = ""; }; - EA5E2A6BFD8D228A6FF7C7C749D642DB /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; - ECA6154AE35962F20A086F5A3633C0CC /* UILabel+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UILabel+LookinServer.h"; path = "Src/Main/Server/Category/UILabel+LookinServer.h"; sourceTree = ""; }; - ED216C76AB8BA24D783B6A22E1E01C97 /* SDWebImageDownloaderRequestModifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderRequestModifier.h; path = SDWebImage/Core/SDWebImageDownloaderRequestModifier.h; sourceTree = ""; }; - ED6C24AA261BA4AFA4E02DA1EFA44065 /* SDImageGraphics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageGraphics.m; path = SDWebImage/Core/SDImageGraphics.m; sourceTree = ""; }; - ED81CDC30BE2F7BBA09422B3CD1BDF85 /* Peertalk.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Peertalk.h; path = Src/Main/Shared/Peertalk/Peertalk.h; sourceTree = ""; }; - EE4B0CFE38831013E2F465F169783700 /* UICollectionViewLayout+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionViewLayout+MJRefresh.h"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.h"; sourceTree = ""; }; - EE96F8DD901EEB1A8375B055EDF7DBBE /* SDWebImageError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageError.h; path = SDWebImage/Core/SDWebImageError.h; sourceTree = ""; }; - EF15AFFA76ECFCE490107F1DEB31BD62 /* SDWeakProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWeakProxy.h; path = SDWebImage/Private/SDWeakProxy.h; sourceTree = ""; }; - EF2661A0DF69E1828AB8D83F666F4FBC /* MJRefreshComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshComponent.m; path = MJRefresh/Base/MJRefreshComponent.m; sourceTree = ""; }; - EF6193F470BF021CAED5E3E0DC4F602E /* LookinAttributesSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttributesSection.m; path = Src/Main/Shared/LookinAttributesSection.m; sourceTree = ""; }; - EFBFF769FFEA0B2F71A0E5EDE7DCDDF3 /* SDWebImageOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOperation.m; path = SDWebImage/Core/SDWebImageOperation.m; sourceTree = ""; }; - EFD8B43671F8A160934DA73D3C45B4C0 /* LookinHierarchyFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinHierarchyFile.m; path = Src/Main/Shared/LookinHierarchyFile.m; sourceTree = ""; }; - F0BE45EAE3F2E6B703C484173BD9CDAD /* UIImageView+HighlightedWebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+HighlightedWebCache.m"; path = "SDWebImage/Core/UIImageView+HighlightedWebCache.m"; sourceTree = ""; }; - F14968FDB67455000B5A2C9A77C64B07 /* SDDisplayLink.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDisplayLink.m; path = SDWebImage/Private/SDDisplayLink.m; sourceTree = ""; }; - F2087695EC0958A50E2C65A5D2E03159 /* UIImage+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+LookinServer.m"; path = "Src/Main/Server/Category/UIImage+LookinServer.m"; sourceTree = ""; }; - F226E8137EFBE0F2C4ADF98335CAA02A /* SDWebImageDownloaderDecryptor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderDecryptor.m; path = SDWebImage/Core/SDWebImageDownloaderDecryptor.m; sourceTree = ""; }; - F2817892F9F21CF8BF9F8F35D58385AD /* NSBezierPath+SDRoundedCorners.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBezierPath+SDRoundedCorners.h"; path = "SDWebImage/Private/NSBezierPath+SDRoundedCorners.h"; sourceTree = ""; }; - F299DB132C67105BBC5A78FBCB87FCF2 /* UIColor+SDHexString.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+SDHexString.m"; path = "SDWebImage/Private/UIColor+SDHexString.m"; sourceTree = ""; }; - F320516E3A699EEF56C411E9C2DA9C29 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = MJExtension/PrivacyInfo.xcprivacy; sourceTree = ""; }; - F3D6C729EB2C2561DF46F90B1EE029B4 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; - F4DCF85783AA9A1B3A613F5BAC3C0FEC /* SDDeviceHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDeviceHelper.h; path = SDWebImage/Private/SDDeviceHelper.h; sourceTree = ""; }; - F53768EF8D38709F253FC1C181B05162 /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; - F53F6F5B0D7E0FF60505964233E5C608 /* Masonry.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.release.xcconfig; sourceTree = ""; }; - F57A932DBB8EE96EEDB42899B11A3E40 /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; - F61E20013C3B1EBDF05023CF2525C38C /* UIScrollView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJExtension.m"; path = "MJRefresh/UIScrollView+MJExtension.m"; sourceTree = ""; }; - F66C529D67E3A61B55DFF40E581048ED /* UIImage+MemoryCacheCost.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MemoryCacheCost.m"; path = "SDWebImage/Core/UIImage+MemoryCacheCost.m"; sourceTree = ""; }; - F68B2B4FABAF7DB3BFD45E81B3302EEE /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; - F6908A3C9CC8A527E2C3CB20A2C51560 /* SDImageAPNGCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageAPNGCoder.m; path = SDWebImage/Core/SDImageAPNGCoder.m; sourceTree = ""; }; - F6B25A4160A5D48C609C6C2B58E46DE9 /* SDWebImageDownloaderResponseModifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderResponseModifier.h; path = SDWebImage/Core/SDWebImageDownloaderResponseModifier.h; sourceTree = ""; }; - F746B8A0D89C293CD78D1EE71CD25FF1 /* LookinEventHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinEventHandler.h; path = Src/Main/Shared/LookinEventHandler.h; sourceTree = ""; }; - F74FD66E160DEA3B30F3C017DE8ED1BA /* LookinAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttribute.h; path = Src/Main/Shared/LookinAttribute.h; sourceTree = ""; }; - F81A89C6E769F9B774524A9FE4BA70B5 /* UIColor+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+LookinServer.h"; path = "Src/Main/Server/Category/UIColor+LookinServer.h"; sourceTree = ""; }; - F98B3E6FF4A7A436AEB00C4FE95820A2 /* LKS_CustomAttrSetterManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_CustomAttrSetterManager.h; path = Src/Main/Server/Others/LKS_CustomAttrSetterManager.h; sourceTree = ""; }; - F9B85917A028A675DFE95B885791EDFC /* LookinWeakContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinWeakContainer.m; path = Src/Main/Shared/LookinWeakContainer.m; sourceTree = ""; }; - FA1B344071044AFFAABF1077219DEC22 /* UIImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/Core/UIImageView+WebCache.m"; sourceTree = ""; }; - FA2246CD5BC5C3E37CEC58BCA4848181 /* NSSet+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSSet+Lookin.h"; path = "Src/Main/Shared/Category/NSSet+Lookin.h"; sourceTree = ""; }; - FAA44D6FF1A44EB319965DB5E0CC5F73 /* UIView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCache.m"; path = "SDWebImage/Core/UIView+WebCache.m"; sourceTree = ""; }; - FAB9874FA4C241C24657D3A825C00C66 /* LKS_AttrGroupsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_AttrGroupsMaker.h; path = Src/Main/Server/Others/LKS_AttrGroupsMaker.h; sourceTree = ""; }; - FAF1C0B2DCF27A6785AA511B6C9290B9 /* MJRefreshAutoNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoNormalFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h; sourceTree = ""; }; - FB260AFEB0CD406D8CDEDE623A1369CF /* LKS_CustomAttrModificationHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomAttrModificationHandler.m; path = Src/Main/Server/Connection/RequestHandler/LKS_CustomAttrModificationHandler.m; sourceTree = ""; }; - FBE4C2596FA0518DD6CED29332B75B5B /* DZNEmptyDataSet-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DZNEmptyDataSet-umbrella.h"; sourceTree = ""; }; - FC8B5F084763484BB92BA1D312960E45 /* UIButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+WebCache.m"; path = "SDWebImage/Core/UIButton+WebCache.m"; sourceTree = ""; }; - FD1216744C111B10EA2988454A525213 /* LookinAttributeModification.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinAttributeModification.m; path = Src/Main/Shared/LookinAttributeModification.m; sourceTree = ""; }; - FDD0D2A5CBDCDA5BDF9600C731F95B24 /* MJRefreshBackFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackFooter.h; path = MJRefresh/Base/MJRefreshBackFooter.h; sourceTree = ""; }; - FEBDC1C9F54DE3E90674A96F19B3458A /* LookinServerDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinServerDefines.h; path = Src/Main/Server/Others/LookinServerDefines.h; sourceTree = ""; }; - FEE404F0AEA8371C4FCFE3F576AA5835 /* NSArray+Lookin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+Lookin.h"; path = "Src/Main/Shared/Category/NSArray+Lookin.h"; sourceTree = ""; }; - FF266D90F27C22E50821C68FB0B959D8 /* LKS_ObjectRegistry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_ObjectRegistry.h; path = Src/Main/Server/Others/LKS_ObjectRegistry.h; sourceTree = ""; }; - FF5518BA3449B11DB02406C2A9A9AA75 /* SDImageCoderHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCoderHelper.h; path = SDWebImage/Core/SDImageCoderHelper.h; sourceTree = ""; }; - FFD58163B84A00F8FD88E21AE9F6DF12 /* SDWeakProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWeakProxy.m; path = SDWebImage/Private/SDWeakProxy.m; sourceTree = ""; }; + E4A5839D54BEE8A98756D5288A3E5050 /* NSBezierPath+SDRoundedCorners.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBezierPath+SDRoundedCorners.h"; path = "SDWebImage/Private/NSBezierPath+SDRoundedCorners.h"; sourceTree = ""; }; + E4BFFACAA945CC17167910BF3C319571 /* SDAssociatedObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDAssociatedObject.h; path = SDWebImage/Private/SDAssociatedObject.h; sourceTree = ""; }; + E4F1989DBFF7A3D94A0CF758DF35B3F6 /* HWPresentingVCAnimatedTransitioning.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPresentingVCAnimatedTransitioning.h; path = Sources/Animator/HWPresentingVCAnimatedTransitioning.h; sourceTree = ""; }; + E6CAC4483459A4704E779D629644670B /* HWPanModalContentView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalContentView.h; path = Sources/View/PanModal/HWPanModalContentView.h; sourceTree = ""; }; + E6FEAED2BC2A577A78A12FA14FC3BB6B /* LookinAttributesGroup.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttributesGroup.h; path = Src/Main/Shared/LookinAttributesGroup.h; sourceTree = ""; }; + E7485AA213719656370219B55A0AAE3C /* MJRefreshBackStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackStateFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m; sourceTree = ""; }; + E75295D3FB5952A7B3A8B497D502A68D /* ResourceBundle-MJExtension-MJExtension-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MJExtension-MJExtension-Info.plist"; sourceTree = ""; }; + E81450568229FA708143E74A7A580F89 /* JXCategoryCollectionView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryCollectionView.m; path = Sources/Common/JXCategoryCollectionView.m; sourceTree = ""; }; + E847BE3D7FA245C62A989A8A4F90542A /* UITableView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITableView+LookinServer.h"; path = "Src/Main/Server/Category/UITableView+LookinServer.h"; sourceTree = ""; }; + E8B2553B72F322F7DC0ED38BB760DDC6 /* UIButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+WebCache.m"; path = "SDWebImage/Core/UIButton+WebCache.m"; sourceTree = ""; }; + E8C71212CAB0DCBF4059538A93053A4A /* UIViewController+PanModalDefault.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+PanModalDefault.h"; path = "Sources/Presentable/UIViewController+PanModalDefault.h"; sourceTree = ""; }; + E948F26A10F663204E24603E8527A7F5 /* JXCategoryListContainerRTLCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryListContainerRTLCell.h; path = Sources/Common/JXCategoryListContainerRTLCell.h; sourceTree = ""; }; + E9FA8ED817E86A0F4415B8E73B62DCF8 /* SDImageGraphics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageGraphics.m; path = SDWebImage/Core/SDImageGraphics.m; sourceTree = ""; }; + EA3E73CFAE53223D9EC3DE4B0794DB06 /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; + EA759F283932CC196A3C378E0037B993 /* UIColor+JXAdd.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+JXAdd.m"; path = "Sources/Common/UIColor+JXAdd.m"; sourceTree = ""; }; + EB461C49F04DBE8D8B709BDAA4911ADC /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; + EB54379A72A5DCC64A2C9D42F05AE928 /* LookinServerDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinServerDefines.h; path = Src/Main/Server/Others/LookinServerDefines.h; sourceTree = ""; }; + EBEEA0239556FEF194877FD307A4ADD6 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; + EC37DBDA721D0EFF5AB018086BE1B195 /* HWPanModal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModal.h; path = Sources/HWPanModal.h; sourceTree = ""; }; + EC4CFDD75B85C12B1C1393BEA03A165C /* MBProgressHUD.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.debug.xcconfig; sourceTree = ""; }; + ECA7ED760D61427E9195A2805DB71798 /* UIView+HW_Frame.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+HW_Frame.m"; path = "Sources/Category/UIView+HW_Frame.m"; sourceTree = ""; }; + ED2A7F3394578B0F6BEA7FBFFE1E2291 /* MJRefreshBackStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackStateFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h; sourceTree = ""; }; + ED332DDCE634104C42A2AF8F698EDFB2 /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; + ED87146FC94850F3891F867B1931F652 /* AFAutoPurgingImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFAutoPurgingImageCache.m; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.m"; sourceTree = ""; }; + EDA0AA2D50C091E5400CDFDEC4B5B802 /* LKS_MultiplatformAdapter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_MultiplatformAdapter.h; path = Src/Main/Server/Others/LKS_MultiplatformAdapter.h; sourceTree = ""; }; + EDA5337EF8951852F4AA839734BF6786 /* HWPanModalAnimator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPanModalAnimator.m; path = Sources/Animator/HWPanModalAnimator.m; sourceTree = ""; }; + EDCA67FC2B94130DF2B6CE9E65BC9944 /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; + EE827BC4171898B142EBDE3C763AFC7F /* SDWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImage.h; path = WebImage/SDWebImage.h; sourceTree = ""; }; + EE9E5D3590E1EC14CD269A8B340CE3F0 /* SDImageCachesManagerOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCachesManagerOperation.m; path = SDWebImage/Private/SDImageCachesManagerOperation.m; sourceTree = ""; }; + EEB5224BF1CABA409B3D3760EDDAEA0A /* LYEmptyView */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = LYEmptyView; path = LYEmptyView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EF1815C1F114106321929B2F631067E5 /* SDImageIOAnimatedCoderInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageIOAnimatedCoderInternal.h; path = SDWebImage/Private/SDImageIOAnimatedCoderInternal.h; sourceTree = ""; }; + EF2876A2D62001FE741FE92492A10CFF /* JXCategoryIndicatorImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JXCategoryIndicatorImageView.h; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorImageView.h; sourceTree = ""; }; + EF62C88D7041DEBD26117AF61789D8AB /* HWPanModalPresentationUpdateProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPresentationUpdateProtocol.h; path = Sources/Presentable/HWPanModalPresentationUpdateProtocol.h; sourceTree = ""; }; + EF7183977EF6286C16A64DBC3D765320 /* HWPanModalHeight.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalHeight.h; path = Sources/Presentable/HWPanModalHeight.h; sourceTree = ""; }; + EFC3A24D1CE615DA957AE8C5AC47E5D7 /* SDWebImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageManager.m; path = SDWebImage/Core/SDWebImageManager.m; sourceTree = ""; }; + F00B3F2B17BB2816232EB507B7AC9018 /* SDWebImageCompat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCompat.m; path = SDWebImage/Core/SDWebImageCompat.m; sourceTree = ""; }; + F09D5DAEE3CD3FFE1B213DFEF893E818 /* JXCategoryView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JXCategoryView-prefix.pch"; sourceTree = ""; }; + F139F3BFF4ABD0678E7947E118F47774 /* UIImageView+HighlightedWebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+HighlightedWebCache.m"; path = "SDWebImage/Core/UIImageView+HighlightedWebCache.m"; sourceTree = ""; }; + F157AC2A50D3773392D42322F67E0EB0 /* LSTPopView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LSTPopView-Info.plist"; sourceTree = ""; }; + F1CF9E4569F5B94286E175AF9D675C11 /* SDInternalMacros.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDInternalMacros.m; path = SDWebImage/Private/SDInternalMacros.m; sourceTree = ""; }; + F1FB9919B7B8171A6A8679BDDA407F68 /* LKS_HierarchyDisplayItemsMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_HierarchyDisplayItemsMaker.h; path = Src/Main/Server/Others/LKS_HierarchyDisplayItemsMaker.h; sourceTree = ""; }; + F287F335FB60871C584FAC1904FF4181 /* SDDeviceHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDDeviceHelper.h; path = SDWebImage/Private/SDDeviceHelper.h; sourceTree = ""; }; + F32705CBE56ACF430653A1C459F5351E /* LookinAttrIdentifiers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinAttrIdentifiers.h; path = Src/Main/Shared/LookinAttrIdentifiers.h; sourceTree = ""; }; + F32DF0242A37C60B9E8BEDC175125BB2 /* MJRefreshBackFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackFooter.h; path = MJRefresh/Base/MJRefreshBackFooter.h; sourceTree = ""; }; + F363F53534ED7FE5A4BB0A1E1863D5E7 /* LKS_CustomAttrSetterManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LKS_CustomAttrSetterManager.m; path = Src/Main/Server/Others/LKS_CustomAttrSetterManager.m; sourceTree = ""; }; + F3BAE7C9BD506017B4C0D7BBB9100900 /* JXCategoryTitleVerticalZoomCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryTitleVerticalZoomCell.m; path = Sources/VerticalZoomTitle/JXCategoryTitleVerticalZoomCell.m; sourceTree = ""; }; + F4F901625B3879AD34FA2A0373208F59 /* LookinHierarchyInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinHierarchyInfo.m; path = Src/Main/Shared/LookinHierarchyInfo.m; sourceTree = ""; }; + F5B865CFCA1FF1600CB766B9BC34B8D9 /* LookinCustomAttrModification.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinCustomAttrModification.h; path = Src/Main/Shared/LookinCustomAttrModification.h; sourceTree = ""; }; + F5D8EBF4698D8B331794EA6F9BF47665 /* HWVisualEffectView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWVisualEffectView.m; path = Sources/View/HWVisualEffectView.m; sourceTree = ""; }; + F5EB73BE761C595601603CE39EC8D850 /* HWPageSheetPresentingAnimation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = HWPageSheetPresentingAnimation.m; path = Sources/Animator/PresentingVCAnimation/HWPageSheetPresentingAnimation.m; sourceTree = ""; }; + F64D04ACE9EB0341E57129D44479C065 /* MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefresh.h; path = MJRefresh/MJRefresh.h; sourceTree = ""; }; + F68616E55705601CBE5D9437AD83B340 /* JXCategoryView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = JXCategoryView.debug.xcconfig; sourceTree = ""; }; + F6CDCEC9BF52B36734600241EB9CC345 /* UIViewController+Presentation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+Presentation.m"; path = "Sources/Presentable/UIViewController+Presentation.m"; sourceTree = ""; }; + F762DC35806D05FE8346CE64A0357D9A /* JXPagingView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "JXPagingView-Info.plist"; sourceTree = ""; }; + F764EB4004D4A21398D072493BD19D56 /* HWPanModalPanGestureDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWPanModalPanGestureDelegate.h; path = Sources/Presentable/HWPanModalPanGestureDelegate.h; sourceTree = ""; }; + F8CCC7FB49429A8093BC8191C6474D58 /* UIView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCache.m"; path = "SDWebImage/Core/UIView+WebCache.m"; sourceTree = ""; }; + F8CEEFBE4317D04F4FD181E44C90A119 /* MJRefreshStateHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateHeader.h; path = MJRefresh/Custom/Header/MJRefreshStateHeader.h; sourceTree = ""; }; + F947DB2E34F4112ED83356B8AA944880 /* SDDeviceHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDeviceHelper.m; path = SDWebImage/Private/SDDeviceHelper.m; sourceTree = ""; }; + F9AA00EC509DE2C0E25E749F629EF1F6 /* UIViewController+LayoutHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+LayoutHelper.m"; path = "Sources/Presentable/UIViewController+LayoutHelper.m"; sourceTree = ""; }; + F9F30602CBEA307F110682B47DBF3B59 /* JXCategoryIndicatorCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorCell.m; path = Sources/Indicator/JXCategoryIndicatorCell.m; sourceTree = ""; }; + F9FBE6B4C01D1445DBFC466AEA64E5D8 /* JXCategoryIndicatorBallView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorBallView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorBallView.m; sourceTree = ""; }; + FA5C6E28985540EE03804DDC4277D459 /* LYEmptyViewHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LYEmptyViewHeader.h; path = LYEmptyView/LYEmptyViewHeader.h; sourceTree = ""; }; + FAA3871C50E5746944D1C3FA3E4736CE /* SDDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDDiskCache.m; path = SDWebImage/Core/SDDiskCache.m; sourceTree = ""; }; + FAA5F2D71B90788C908800A94534AA92 /* FLAnimatedImage */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FLAnimatedImage; path = FLAnimatedImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FB1FCAC52ADC49B2B3A81FFCCD3D56EE /* UIImage+GIF.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+GIF.h"; path = "SDWebImage/Core/UIImage+GIF.h"; sourceTree = ""; }; + FB614FC70886C761E2BA7E9C7E7F2D88 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; sourceTree = ""; }; + FB718B97DF8D94DCF736C973F8184652 /* UIImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/Core/UIImageView+WebCache.m"; sourceTree = ""; }; + FB84DF0F5016EBAF04FE5FE9F22081C0 /* SDWebImage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-umbrella.h"; sourceTree = ""; }; + FC8583F4233091326F271A4C13185F5B /* HWBackgroundConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWBackgroundConfig.h; path = Sources/View/HWBackgroundConfig.h; sourceTree = ""; }; + FCA4EBF34C88159600AC127D3548346D /* UITextView+LookinServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextView+LookinServer.h"; path = "Src/Main/Server/Category/UITextView+LookinServer.h"; sourceTree = ""; }; + FCBCC9D408AF4A848CBB9CEE3327E256 /* HWShoppingCartPresentingAnimation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HWShoppingCartPresentingAnimation.h; path = Sources/Animator/PresentingVCAnimation/HWShoppingCartPresentingAnimation.h; sourceTree = ""; }; + FCBD8DFA94436F5E62F1AA0F1AD2F2FA /* LookinStaticAsyncUpdateTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LookinStaticAsyncUpdateTask.m; path = Src/Main/Shared/LookinStaticAsyncUpdateTask.m; sourceTree = ""; }; + FD3C0DF69EC6CFA1DD8299F62B1A84FB /* SDWebImageOptionsProcessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOptionsProcessor.h; path = SDWebImage/Core/SDWebImageOptionsProcessor.h; sourceTree = ""; }; + FD61DA71A7253ED59D65D424C86E2C50 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; + FD7C0DEE68BC5E8256170F72FCC61847 /* JXCategoryIndicatorDotLineView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JXCategoryIndicatorDotLineView.m; path = Sources/Indicator/IndicatorViews/JXCategoryIndicatorDotLineView.m; sourceTree = ""; }; + FD937703BB1091324CC7A54FB95A5217 /* MJRefreshBackGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackGifFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m; sourceTree = ""; }; + FDCCFFDED68135F2816CA2167E15CF64 /* LookinHierarchyFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LookinHierarchyFile.h; path = Src/Main/Shared/LookinHierarchyFile.h; sourceTree = ""; }; + FEA159570B75D1C95DC0E0B5836BACFF /* LKS_HierarchyDetailsHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = LKS_HierarchyDetailsHandler.h; path = Src/Main/Server/Connection/RequestHandler/LKS_HierarchyDetailsHandler.h; sourceTree = ""; }; + FED4C87CAD14B9336A225C943B75263C /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; + FED91C88820F2942B3A007C5E5D17ACB /* UIColor+LookinServer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+LookinServer.m"; path = "Src/Main/Server/Category/UIColor+LookinServer.m"; sourceTree = ""; }; + FEE19DBCD45615CC389DD7223D3C447A /* SDImageCoderHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCoderHelper.m; path = SDWebImage/Core/SDImageCoderHelper.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 0DE7FCDD6C04EC4E1E9ECB00A0604FB7 /* Frameworks */ = { + 04785C72D7E967FCB78D8F7E7635973B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0DCF6770445D0657900721EC9917ECFB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -1146,6 +1648,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2A4C89A05153A8C37E3B9ACF170A9EB8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EFCAC311A0285F51E8B1B0F7416D7D8 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2D2D1D550E12F4C0C9C30D5A3CD01C4E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 37145BAEB1B97BA7ADD7D6C3E86E99BD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1163,10 +1680,43 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 68405B5F41E04D755317E63849131904 /* Frameworks */ = { + 481273BD538BE69936DB3D2C8EB1E61B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 8B47B7F220A2B9E121EFF5A28B477972 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 58A39759A11D8C551E18D1323674BF34 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D07985CF518269347F3FD5FE6D22609 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6328134103EDE3EF1EA3866C0B5CCA07 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F1A04C26FAF235FD6B0AF30E7ACD5DD5 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6B8E82384925B650051F0C1846383E41 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6E39FC1043D864A0759387AEED07D7AC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B03761E468C3B0F1BFEB2401CF2D5245 /* Foundation.framework in Frameworks */, + A0ADDB3C7DF96DF0E6BC53086778A103 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1179,6 +1729,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 98BB4909B1035551DF579C13A59BAA4D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 47C6C10BB05445BCB8CBCA4DADE7E933 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9E666AF8497E0DE090335A642D5B84EC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1187,18 +1745,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - A12778F5B92D79BB1CB466B6E7808C73 /* Frameworks */ = { + AE750D3363286EC4504AB9516776E757 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - AC60AAEBCF4A484AB8DAD9EBCA30DBD7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1EE04FF3866D1CDDBEFEBA7F795824AD /* Foundation.framework in Frameworks */, + 431023914A5D2653ABAE7AB54880C9AC /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1220,6 +1771,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D267C6F8AD649543C397BCAAADB7F148 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D2CBEBF5F1DA6766A833CCD0BF02B5B /* CoreGraphics.framework in Frameworks */, + DBB7D12AC159E50D059772E4B6CF1D2F /* Foundation.framework in Frameworks */, + FB6E014B34F33B89E5060DA1F00168A5 /* ImageIO.framework in Frameworks */, + FDD4C4D4F03502D5CB0B8763009A0948 /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; E672724427269716049B769344D7C3DC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1229,268 +1791,406 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F4019BF639D68EFAB596EA1BD86C37CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 004BCCE6E90EA8F999F5DD21EFC4736A /* Support Files */ = { + 070A9E270BA37B1A5AAC97680E006F46 /* LSTPopView */ = { isa = PBXGroup; children = ( - 0CE9804DA47B24CF925450C7924EF999 /* Masonry.modulemap */, - E321D3F90B0E3A7E45F64EB551639098 /* Masonry-dummy.m */, - BE6604D8C889F73372398B103D4FF327 /* Masonry-Info.plist */, - D8E5E1F0B039F76947E77470F619AB22 /* Masonry-prefix.pch */, - 31C3AFC445B760812F9E6924ABB9CC15 /* Masonry-umbrella.h */, - B9AC91A4E70DD8F8592A5811E8617578 /* Masonry.debug.xcconfig */, - F53F6F5B0D7E0FF60505964233E5C608 /* Masonry.release.xcconfig */, + EC737F9C95A0D5999B811C9A1D937DBC /* Code */, + 9A6094CFD16104AD70583A90D874C249 /* Support Files */, + ); + name = LSTPopView; + path = LSTPopView; + sourceTree = ""; + }; + 0B3501DF96788E261B37AA47988480FF /* Resources */ = { + isa = PBXGroup; + children = ( + A0497973DD4190C4C37CC950C86C6F2B /* PrivacyInfo.xcprivacy */, + ); + name = Resources; + sourceTree = ""; + }; + 102054A1E3292F59C346E38466BC61C8 /* Resources */ = { + isa = PBXGroup; + children = ( + 0FFF1AB10AC30C72DB3B2F106B23E5B3 /* PrivacyInfo.xcprivacy */, + ); + name = Resources; + sourceTree = ""; + }; + 184D0B412C8826DE321973718A83EAD0 /* Support Files */ = { + isa = PBXGroup; + children = ( + 91BC18AA2869958B15FBD2C2367C5DFC /* AFNetworking.modulemap */, + 18106F0763EC023048DB3F77457B9596 /* AFNetworking-dummy.m */, + 541552D5AA99C6DF3406BD050E1467DB /* AFNetworking-Info.plist */, + EDCA67FC2B94130DF2B6CE9E65BC9944 /* AFNetworking-prefix.pch */, + 83E8510A179E756198B5FC915A27736E /* AFNetworking-umbrella.h */, + 88D479C435BAEE51B8F3BBF87F8D3CC9 /* AFNetworking.debug.xcconfig */, + 57B2E23309380B0E15F50C277205AC0D /* AFNetworking.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/Masonry"; + path = "../Target Support Files/AFNetworking"; sourceTree = ""; }; - 055E201C6FE65C14750CE007D95094C3 /* DZNEmptyDataSet */ = { + 1C6C79318C220E5B8848BEC84F0BF1D4 /* Support Files */ = { isa = PBXGroup; children = ( - D6E369F88941EA9A46AF58BC88CC0720 /* UIScrollView+EmptyDataSet.h */, - 1C3AD08A39781246EBAC23F5B8A9BDD3 /* UIScrollView+EmptyDataSet.m */, - 6CE3F18721CC834AA1D80F2A9F218CA5 /* Support Files */, - ); - name = DZNEmptyDataSet; - path = DZNEmptyDataSet; - sourceTree = ""; - }; - 139D61AB9CCEA3CD3FE43AE8F0DFA14F /* Support Files */ = { - isa = PBXGroup; - children = ( - 79803C4DAA3D0FB997F7A51AB226B9D7 /* ResourceBundle-SDWebImage-SDWebImage-Info.plist */, - 504A6EFB974AF03849BCBDD8A6C0A198 /* SDWebImage.modulemap */, - EA4BA3056A1FE6B47E97AA549D4B9423 /* SDWebImage-dummy.m */, - 107E924936A407875330C174B34260AC /* SDWebImage-Info.plist */, - 25391D44BC144DD932559C9E9069347F /* SDWebImage-prefix.pch */, - 037A3F50C10BD2A3B9D2C3743608A737 /* SDWebImage-umbrella.h */, - 5998234B9DD3C83BCD1DE88EDDEA5DF6 /* SDWebImage.debug.xcconfig */, - 0C31E11F6B40D55EB650013FAC1B59C0 /* SDWebImage.release.xcconfig */, + 85C4F1C66A75633558DC8F8AE824BC70 /* LYEmptyView.modulemap */, + 2F19C07EBC4D3E8EF1AD6C474E7F24FE /* LYEmptyView-dummy.m */, + 7DCA3ADE9B99025CE2B42367695E1E68 /* LYEmptyView-Info.plist */, + 517EACA3BDCA2E1CB5B954656D4B9F02 /* LYEmptyView-prefix.pch */, + C00601FB0A8CFBE203150BAEC58E95FC /* LYEmptyView-umbrella.h */, + 5048CCD1406058B50480C383463B3C39 /* LYEmptyView.debug.xcconfig */, + E00B4B67B95B1D4B1001EF45F23EF0C4 /* LYEmptyView.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/SDWebImage"; + path = "../Target Support Files/LYEmptyView"; sourceTree = ""; }; - 1C8A19406FF58E9BA6BC427CA02E9857 /* Products */ = { + 2397706FC09C7D8BAD347D387C455173 /* MBProgressHUD */ = { isa = PBXGroup; children = ( - A4FA15D44DF6BAC7550EDEED10862AA3 /* AFNetworking */, - 5DA4577FE3BC4A03751108FFED07B385 /* DZNEmptyDataSet */, - 25664483ABF4DC8EC03E7472AA04333B /* LookinServer */, - 1FFED36A657123030ABB700256D73F15 /* Masonry */, - 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD */, - 2B276B0A79173A1D6E83C9B4FB9A4A57 /* MJExtension */, - 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */, - E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */, - 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */, - 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */, - DCA062FD08AC9694D8D781B3492421C5 /* Pods-keyBoard */, - B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */, - CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */, + 5DC759BB8D0141E0F064F3BCA7197315 /* MBProgressHUD.h */, + 347DA9A1002297848F6BF9D97BB1F302 /* MBProgressHUD.m */, + 4E1FCFC15AFF6ACA076B1D8B295CDE1D /* Support Files */, ); - name = Products; + name = MBProgressHUD; + path = MBProgressHUD; sourceTree = ""; }; - 1DF4B2EDEE04858C6D572415F9FFA5F7 /* Core */ = { + 23E095E4ABDFCF286D5B6E1FB3668170 /* MJRefresh */ = { isa = PBXGroup; children = ( - F2817892F9F21CF8BF9F8F35D58385AD /* NSBezierPath+SDRoundedCorners.h */, - 8BAD239072CC7DFB1FD50FE4374085D1 /* NSBezierPath+SDRoundedCorners.m */, - 1110127348EF0DD2FF03A68A13D86895 /* NSButton+WebCache.h */, - 613A0EC29C46AFB409483355C45FE1C7 /* NSButton+WebCache.m */, - 7DBD5C23623A08CDD875999AA28A1F8D /* NSData+ImageContentType.h */, - 17422A39378973466DCE06FB6ADA832E /* NSData+ImageContentType.m */, - CC47954DDA2CCCD6E92132955A0DE728 /* NSImage+Compatibility.h */, - 5B993C5AF69BCC11CB58D180BE7475BE /* NSImage+Compatibility.m */, - 2BA061B3651D9243CBD96694626B95C1 /* SDAnimatedImage.h */, - 8CD27E7A66F8B685B7056B181A0D4D46 /* SDAnimatedImage.m */, - 9A522D0661C437F2B97B12A18A3478A1 /* SDAnimatedImagePlayer.h */, - 6D30CE312289056E4C5788AB47438FED /* SDAnimatedImagePlayer.m */, - 33E548EC20D55A1581EF030D8F590720 /* SDAnimatedImageRep.h */, - 8A299BC446CAAFD89DBF55F51B07F0F4 /* SDAnimatedImageRep.m */, - DB89640D4CA100127D613D0379809B5A /* SDAnimatedImageView.h */, - 6B21CBEE99C5014F0E0F66C420497FCD /* SDAnimatedImageView.m */, - 241065D9A03A30BC61C328A01C40E560 /* SDAnimatedImageView+WebCache.h */, - 48A9A2DE85C1D87BCD354418BAF78749 /* SDAnimatedImageView+WebCache.m */, - B9EF838DEDDB795D85E2F065BD697452 /* SDAssociatedObject.h */, - 3D7966DEA2CA0101B9FC2C01A1A2909B /* SDAssociatedObject.m */, - BDD492D9CC4757F16B776F8B08A1A49F /* SDAsyncBlockOperation.h */, - E70D2DE5FE013503515AE432AE16071A /* SDAsyncBlockOperation.m */, - 19F3928D9276C0125AA1EBDB31A470E1 /* SDCallbackQueue.h */, - 13D448A155C957ECCF95DC54FBE28569 /* SDCallbackQueue.m */, - F4DCF85783AA9A1B3A613F5BAC3C0FEC /* SDDeviceHelper.h */, - 4D2D491E6C287C5C66C4EF6B165E85BD /* SDDeviceHelper.m */, - 5F52BB443191BF5EA87C6419E4BAFFD5 /* SDDiskCache.h */, - D6C233C8BB873C737FFE3E1DFBC2A186 /* SDDiskCache.m */, - 25AADAD73C32FC4E150A4A19780980C4 /* SDDisplayLink.h */, - F14968FDB67455000B5A2C9A77C64B07 /* SDDisplayLink.m */, - 599EA7E2BEEE9D88C43DF182C6A874D1 /* SDFileAttributeHelper.h */, - 4223ACF818570B18B88D6B2884075BF1 /* SDFileAttributeHelper.m */, - 4E7FA66C9DDB6507631DF1F179557C4A /* SDGraphicsImageRenderer.h */, - 9843F03B02D2521214C5C5583A9BBDA3 /* SDGraphicsImageRenderer.m */, - BF679E0482D915265B5050368ABBB701 /* SDImageAPNGCoder.h */, - F6908A3C9CC8A527E2C3CB20A2C51560 /* SDImageAPNGCoder.m */, - 5E0CFDE214ACE5F071E4BEEF63BDDCD6 /* SDImageAssetManager.h */, - 1CA256AA8704AE9F135214714BAFF153 /* SDImageAssetManager.m */, - 93FB055BA93E62482AD7154A938F761A /* SDImageAWebPCoder.h */, - 0AF433E9D2C6355E77FFBE3AC3CB5B3A /* SDImageAWebPCoder.m */, - 34206822AA40B77DF3E1B3B5D326158F /* SDImageCache.h */, - 3D6CF72BA8B7618D0238AD641B57FE35 /* SDImageCache.m */, - 1F43D293502C6A280429EF2DEFA6C0E6 /* SDImageCacheConfig.h */, - 4770EEEC71445F1C55A5C71E32517009 /* SDImageCacheConfig.m */, - 3CA1F0AA7C906C09D35E1B3B781EB6E0 /* SDImageCacheDefine.h */, - C839ECCA7B6B8EF19AFC3658241117C8 /* SDImageCacheDefine.m */, - 99F9CF6DCFC4C32DE7AC87FA68FD05DA /* SDImageCachesManager.h */, - A3CC467742888B5DE59CC393D50BA540 /* SDImageCachesManager.m */, - AB362641176A92218B886FD83548F6C2 /* SDImageCachesManagerOperation.h */, - A1B6FEE442B47E03714BC3FB94670DCC /* SDImageCachesManagerOperation.m */, - 2FE87671299E95720DB52DD3375B566E /* SDImageCoder.h */, - 12F12865FFC70E396EDFB92C4A7F13D7 /* SDImageCoder.m */, - FF5518BA3449B11DB02406C2A9A9AA75 /* SDImageCoderHelper.h */, - A57C810A36EA495CAFAEDAD83C19A651 /* SDImageCoderHelper.m */, - 89023F2C23C8826F172885D263CC29D2 /* SDImageCodersManager.h */, - 97041A2525062E71B923CEBB11179389 /* SDImageCodersManager.m */, - 1FC42F03931384EE2605E5C1FF575608 /* SDImageFrame.h */, - B6F3F601094A8014DC41447620116D80 /* SDImageFrame.m */, - 148FDB67C55B5854E979447E82AFD54E /* SDImageFramePool.h */, - 131863AC3A27979CE5BF1B35EB9C1CED /* SDImageFramePool.m */, - 8F0FAF8AA7D9999CB7B6AC14DC9F613F /* SDImageGIFCoder.h */, - E5514D264E4855320B70B7010325576C /* SDImageGIFCoder.m */, - 89485243816A18F41367AE862167C061 /* SDImageGraphics.h */, - ED6C24AA261BA4AFA4E02DA1EFA44065 /* SDImageGraphics.m */, - 67A65AF14731E6A6CF631892AB163C2D /* SDImageHEICCoder.h */, - 9D9C32EDDDB1CA2666760FDE90B64590 /* SDImageHEICCoder.m */, - BF86BA22A3F81C27DE4346E22477D2CD /* SDImageIOAnimatedCoder.h */, - 5C0CAD4F0394CDAF40054888E02EB093 /* SDImageIOAnimatedCoder.m */, - 9662C23EC2FEA41BE91046E19A928D8C /* SDImageIOAnimatedCoderInternal.h */, - B00A278D1C0A05DD872C02CEFE3B53AC /* SDImageIOCoder.h */, - E1E6BDC6A27A05429814F2520B890A63 /* SDImageIOCoder.m */, - 97003D4D841CDDF5214C70A6CC7425DF /* SDImageLoader.h */, - 2254BB0E1CAB331C712E8819CE1CEBA9 /* SDImageLoader.m */, - 9964200935BD2352FD5DAD8C2AC9FE07 /* SDImageLoadersManager.h */, - D601D33EE8BB8396FF4AED582379432E /* SDImageLoadersManager.m */, - BD3AE781F5CE5DD3063848F6F78DD40B /* SDImageTransformer.h */, - DF57705B90AB01302C42302B6BB038DD /* SDImageTransformer.m */, - 8F715C3F41E2D739BCA20A8ED2E487A1 /* SDInternalMacros.h */, - DE9EB519F0B4BF7D539877F733F7BCAF /* SDInternalMacros.m */, - 24998A1052F45827E4FFAFAF7FA1542E /* SDMemoryCache.h */, - 59D0E9B54F4868B1B1BDE17140B78250 /* SDMemoryCache.m */, - 79462E533AFF776B12B799A128AA5EE8 /* SDmetamacros.h */, - EF15AFFA76ECFCE490107F1DEB31BD62 /* SDWeakProxy.h */, - FFD58163B84A00F8FD88E21AE9F6DF12 /* SDWeakProxy.m */, - 5248A2EBBCEB19A0BBFA557B594E2DEA /* SDWebImage.h */, - DF2FF7F81EC1FE20B9F8B3879085D4FA /* SDWebImageCacheKeyFilter.h */, - 960792D55E0D95EDBE31A27683F9FEEF /* SDWebImageCacheKeyFilter.m */, - 794882B4F91B9E9B55DD3DF40E04DA22 /* SDWebImageCacheSerializer.h */, - 42189E436FCC0F9F0BAA536F3BF84910 /* SDWebImageCacheSerializer.m */, - CBCBBB0099A9339A1A8ABBEDF291AF92 /* SDWebImageCompat.h */, - 299CDB086FE0568EE14EAB79D7B74437 /* SDWebImageCompat.m */, - 01E24F0E64AEC0E54DBDB063CE89097A /* SDWebImageDefine.h */, - 0370FDB753906B18C1B9AFB8BE7D213C /* SDWebImageDefine.m */, - 9C6609EE1C9372D5E3C70AF9861CE95D /* SDWebImageDownloader.h */, - 94E4D004CAC99A7D4B7144E86418C29C /* SDWebImageDownloader.m */, - 99418F0A943BD9FF46795740F7385472 /* SDWebImageDownloaderConfig.h */, - 2A5A249D6ED704F9FEE1FFBC9B61426F /* SDWebImageDownloaderConfig.m */, - 15EEB72FE94B15511A9B077601BFC002 /* SDWebImageDownloaderDecryptor.h */, - F226E8137EFBE0F2C4ADF98335CAA02A /* SDWebImageDownloaderDecryptor.m */, - 929BD46DB08827C3FD713BC0E928C239 /* SDWebImageDownloaderOperation.h */, - 0C5C306F08907FB9E1301EA07220C6EB /* SDWebImageDownloaderOperation.m */, - ED216C76AB8BA24D783B6A22E1E01C97 /* SDWebImageDownloaderRequestModifier.h */, - 2AEE1DAEE2CD1BAB6DBCBC50916263A4 /* SDWebImageDownloaderRequestModifier.m */, - F6B25A4160A5D48C609C6C2B58E46DE9 /* SDWebImageDownloaderResponseModifier.h */, - 15D08EB14955AB2B841A5E9E16D8D4AE /* SDWebImageDownloaderResponseModifier.m */, - EE96F8DD901EEB1A8375B055EDF7DBBE /* SDWebImageError.h */, - CE89275D8F89A11FB2761E0461236313 /* SDWebImageError.m */, - B6D81E3EC47029DCA820DF6AA652C734 /* SDWebImageIndicator.h */, - 54354678DA42B275327F1EABDD57F9BD /* SDWebImageIndicator.m */, - 5C7AE763582816CA9E57C0D78A7D1A49 /* SDWebImageManager.h */, - 036896A95CE28AB066292A03BAD2BFFA /* SDWebImageManager.m */, - 0BF41BBB1EBC1FE4F91BE320D947ED64 /* SDWebImageOperation.h */, - EFBFF769FFEA0B2F71A0E5EDE7DCDDF3 /* SDWebImageOperation.m */, - C0AED8CDD333F60946EF309E2D789249 /* SDWebImageOptionsProcessor.h */, - AE4708C50A24F74BB9721BF97FDD4782 /* SDWebImageOptionsProcessor.m */, - 5E83988FA8D9C00FAEEA94EE0633C2C5 /* SDWebImagePrefetcher.h */, - CDE77633CA7FA3526B2AA79AB5F21A42 /* SDWebImagePrefetcher.m */, - 3BF9DE6E63B2A31CC1EADA84D3E42E7A /* SDWebImageTransition.h */, - 4819E2A59EFDCF27B3C3DDB40C7B2D13 /* SDWebImageTransition.m */, - 9E3D65B846C5EFBA9201404CD8BDC1DA /* SDWebImageTransitionInternal.h */, - 615CFF22184D20B3B6107165A49D6FEF /* UIButton+WebCache.h */, - FC8B5F084763484BB92BA1D312960E45 /* UIButton+WebCache.m */, - D6A9452B8FC36F44EC5608AB04827703 /* UIColor+SDHexString.h */, - F299DB132C67105BBC5A78FBCB87FCF2 /* UIColor+SDHexString.m */, - 7B54AFD2BD6CA59B1C3B03B1146FE77F /* UIImage+ExtendedCacheData.h */, - 71BB52034FF7403843EE79E4975D6D70 /* UIImage+ExtendedCacheData.m */, - 2A67F3F63FB3C05544B8F66F7ED89E74 /* UIImage+ForceDecode.h */, - BB09D1C81119E88D019FD33037BC5587 /* UIImage+ForceDecode.m */, - 2DFD54923DA02EA135A1A1E2F56CBDE1 /* UIImage+GIF.h */, - 3D64DD7369F8D81EDC16FC3539F46D73 /* UIImage+GIF.m */, - 80FED7368916E2D1EE8E2B7F26A2618F /* UIImage+MemoryCacheCost.h */, - F66C529D67E3A61B55DFF40E581048ED /* UIImage+MemoryCacheCost.m */, - E614E7E1FA6658E0B9CF44C05D4E6811 /* UIImage+Metadata.h */, - 0FD3FF7FA5E997D3DDAB5C272F8734A6 /* UIImage+Metadata.m */, - C59B65D3E951B3FDACD866C4564C0214 /* UIImage+MultiFormat.h */, - 7CBB9E2731CD9B8F896AD9F7398CD3F6 /* UIImage+MultiFormat.m */, - AA8F3F4E9CF14305D8C83582492FEA87 /* UIImage+Transform.h */, - DD9F495B1E192CA5A7EA012DC8524457 /* UIImage+Transform.m */, - 3996B697C00897DAFE1DFD73DAA4E114 /* UIImageView+HighlightedWebCache.h */, - F0BE45EAE3F2E6B703C484173BD9CDAD /* UIImageView+HighlightedWebCache.m */, - 9DFECBD4586BE9AE288AFFA5027A9A24 /* UIImageView+WebCache.h */, - FA1B344071044AFFAABF1077219DEC22 /* UIImageView+WebCache.m */, - 98B6A3897B6D415F51E7F65FD9A20296 /* UIView+WebCache.h */, - FAA44D6FF1A44EB319965DB5E0CC5F73 /* UIView+WebCache.m */, - C9154FA9EFF76FE4C993ADDBEB9A5EE4 /* UIView+WebCacheOperation.h */, - 8AE06F501FB1F02940458122AC396D62 /* UIView+WebCacheOperation.m */, - 832592FA01CF620F64F9CED4966CEA99 /* UIView+WebCacheState.h */, - 96D5456A17DF66E262562E8208ADEFF0 /* UIView+WebCacheState.m */, - F364D65121D8297BD4970B4E36B87837 /* Resources */, + F64D04ACE9EB0341E57129D44479C065 /* MJRefresh.h */, + DE7E60B5B6A0850596F935D95CAFE167 /* MJRefreshAutoFooter.h */, + 14CF605A6E1A867AA3131733CCE53D99 /* MJRefreshAutoFooter.m */, + 7CE9A594E8A127B7273A7D82E1882497 /* MJRefreshAutoGifFooter.h */, + BC7F3F9323470C634DC0D469E7C13B10 /* MJRefreshAutoGifFooter.m */, + 77973C87CC9649629EBEE249DCC355F5 /* MJRefreshAutoNormalFooter.h */, + 6021531912761F1BDBFE14A61784B26D /* MJRefreshAutoNormalFooter.m */, + 8C065D632F2F749CBD48B178A68B1631 /* MJRefreshAutoStateFooter.h */, + 8CF1445CC744306AE4ECBA85DFD6DB27 /* MJRefreshAutoStateFooter.m */, + F32DF0242A37C60B9E8BEDC175125BB2 /* MJRefreshBackFooter.h */, + A7EA79586CBF531A23E8B00CFA7B82C7 /* MJRefreshBackFooter.m */, + BBA58A99F7E528A8D41BD96706230160 /* MJRefreshBackGifFooter.h */, + FD937703BB1091324CC7A54FB95A5217 /* MJRefreshBackGifFooter.m */, + E45A9679E38D826E316675D8F368F69C /* MJRefreshBackNormalFooter.h */, + A64A22A853C13E4375B73E01D1D90CB1 /* MJRefreshBackNormalFooter.m */, + ED2A7F3394578B0F6BEA7FBFFE1E2291 /* MJRefreshBackStateFooter.h */, + E7485AA213719656370219B55A0AAE3C /* MJRefreshBackStateFooter.m */, + 5E9C6ED309FB0F6481FF6639AA9C417B /* MJRefreshComponent.h */, + 6C9E32D40F89FB7470530B4F8AAB6162 /* MJRefreshComponent.m */, + 2B4792E0E693278C27DB918B70E58272 /* MJRefreshConfig.h */, + 3C71B9877A51B54673C7FFC0C3276863 /* MJRefreshConfig.m */, + 63A3BD4651AA1DDCB216ABB7FBC3A69E /* MJRefreshConst.h */, + 8638AEC16F5A3F7D05EF0F7C39544261 /* MJRefreshConst.m */, + 800ECE845D6F36BE51A284DFCAE27307 /* MJRefreshFooter.h */, + 0260C833576479A14C0F759F9D161479 /* MJRefreshFooter.m */, + 7718D3A1CB256B2263AD76B8EFDC9B86 /* MJRefreshGifHeader.h */, + B6242B29A00A9DBC6FF1CD09266BBF54 /* MJRefreshGifHeader.m */, + 16308A5AF08E401B61B68CCD953A0528 /* MJRefreshHeader.h */, + 66E849825D4B5783372753D6820DE97F /* MJRefreshHeader.m */, + D411D25D78A2F9E3CF17B20443ED9F40 /* MJRefreshNormalHeader.h */, + 61D65BB6AAD351E64F3FE46FACDEED4F /* MJRefreshNormalHeader.m */, + 83340409B38BF2A20F089A4B919FC02F /* MJRefreshNormalTrailer.h */, + 6DE6908A836615F946533A6FEE623373 /* MJRefreshNormalTrailer.m */, + F8CEEFBE4317D04F4FD181E44C90A119 /* MJRefreshStateHeader.h */, + 3259CC7D8EE4331CC9B8A86DA09EA5B3 /* MJRefreshStateHeader.m */, + AB1D54171867DC3B104DAE8C6D30F644 /* MJRefreshStateTrailer.h */, + 29792A8AE7CB7444FE7BA20424B814AD /* MJRefreshStateTrailer.m */, + 572433DB55AF2085E2E4D419FCE37679 /* MJRefreshTrailer.h */, + 5C64D6AC35DE27CAD74CA154541AF1C9 /* MJRefreshTrailer.m */, + 412FD8B68949345873B82E2D0C864C85 /* NSBundle+MJRefresh.h */, + 9ECA4FF1A4B2A73F055139B44105081C /* NSBundle+MJRefresh.m */, + 70021D526E8906DE61E9D2D0F92A78C3 /* UICollectionViewLayout+MJRefresh.h */, + BE1A1849BD6BB4B796D54DCBEF79FB7A /* UICollectionViewLayout+MJRefresh.m */, + 304FA88F8B2636C2DD7FA535D2BD617D /* UIScrollView+MJExtension.h */, + B8F1319B150BB3DBD94BEB4C80F6F296 /* UIScrollView+MJExtension.m */, + DE0511947F57D1CF3F274B6414AE449B /* UIScrollView+MJRefresh.h */, + 6B94BD4B7CE09D63E43117EFC4B15D0D /* UIScrollView+MJRefresh.m */, + 38C2193309DE8B485EA6F0495C08B115 /* UIView+MJExtension.h */, + 60696FE70F42B1A0CD7B0614C2A2F16C /* UIView+MJExtension.m */, + 27463477E43B49707581CF13A6E099B2 /* Resources */, + 28E2A9A1CEAC3F154F646A51F0227786 /* Support Files */, + ); + name = MJRefresh; + path = MJRefresh; + sourceTree = ""; + }; + 27463477E43B49707581CF13A6E099B2 /* Resources */ = { + isa = PBXGroup; + children = ( + 083F5143D12F213638EF9FE439F1CEFA /* MJRefresh.bundle */, + 20674A80959A90C9F9E51DBDC8807D93 /* PrivacyInfo.xcprivacy */, + ); + name = Resources; + sourceTree = ""; + }; + 276C8F966392FC7A9273EA1CF3239640 /* HWPanModal */ = { + isa = PBXGroup; + children = ( + FC8583F4233091326F271A4C13185F5B /* HWBackgroundConfig.h */, + 3F0DA836C065C821DDDE100A36B1C087 /* HWBackgroundConfig.m */, + 0F1705DF1CC5E82194523F85FE871354 /* HWDimmedView.h */, + 9230BE776665C8EB51C8889631B1B31B /* HWDimmedView.m */, + 1EC115C953943E0027F6AD5AFEE41A30 /* HWPageSheetPresentingAnimation.h */, + F5EB73BE761C595601603CE39EC8D850 /* HWPageSheetPresentingAnimation.m */, + 94CE97E5A9659D6EE58C83DCB52F73D5 /* HWPanContainerView.h */, + 453FB14441528B4AE2CF3592D5874C54 /* HWPanContainerView.m */, + 4A15AB0AB6FCF1589E2A6CEDC3CF0B95 /* HWPanIndicatorView.h */, + 77E6EFEE426EA2068D5FE2B73740D659 /* HWPanIndicatorView.m */, + EC37DBDA721D0EFF5AB018086BE1B195 /* HWPanModal.h */, + CF7B4B9CB0EF762A12884D6FE337E068 /* HWPanModalAnimator.h */, + EDA5337EF8951852F4AA839734BF6786 /* HWPanModalAnimator.m */, + 091DAAA7597B1233173C3BB1DC8D1D79 /* HWPanModalContainerView.h */, + 0BED1E57A7780D7944D806EF7FB48648 /* HWPanModalContainerView.m */, + E6CAC4483459A4704E779D629644670B /* HWPanModalContentView.h */, + 9E31AD6314EC8102DE4FC6291C0FE66F /* HWPanModalContentView.m */, + EF7183977EF6286C16A64DBC3D765320 /* HWPanModalHeight.h */, + BCDE5AFCF524DCA9CD59B6F4A4738325 /* HWPanModalIndicatorProtocol.h */, + 47A97040129EEE8B96AEEA0A9B73DA45 /* HWPanModalInteractiveAnimator.h */, + 74751305705DEA03873DFA2AF4DDC9B7 /* HWPanModalInteractiveAnimator.m */, + F764EB4004D4A21398D072493BD19D56 /* HWPanModalPanGestureDelegate.h */, + 3A10B1AFB4B6959F4A11AB1B1BC4A437 /* HWPanModalPresentable.h */, + C644FF26241C14C759578567892EF00D /* HWPanModalPresentableHandler.h */, + 0FC2E352D2D0DD942A9B4488E3654AB0 /* HWPanModalPresentableHandler.m */, + DB48FEC8123075E04395CF34F6F8227D /* HWPanModalPresentationAnimator.h */, + 831897EBD9EF72C4D55D02DE399C410A /* HWPanModalPresentationAnimator.m */, + 87888E540A812F012C68F804E8F5AE7B /* HWPanModalPresentationController.h */, + 1F9506DDA8FBAA7420E9B8137BFCFDFA /* HWPanModalPresentationController.m */, + 4EBFFAE4CE0471C78DB70755CFCC7609 /* HWPanModalPresentationDelegate.h */, + 1724C0944D7BC65545806EE9EDED203D /* HWPanModalPresentationDelegate.m */, + EF62C88D7041DEBD26117AF61789D8AB /* HWPanModalPresentationUpdateProtocol.h */, + DE4F66BD16AF47C58F5E08D62D7916E3 /* HWPanModalPresenterProtocol.h */, + 568F43CF567335FABEC4825ED4776B19 /* HWPanModalShadow.h */, + 513C1A2EE22268DD51EB02AE24E3B579 /* HWPanModalShadow.m */, + E4F1989DBFF7A3D94A0CF758DF35B3F6 /* HWPresentingVCAnimatedTransitioning.h */, + FCBCC9D408AF4A848CBB9CEE3327E256 /* HWShoppingCartPresentingAnimation.h */, + C5D725B550FCED60C80870F1B120D3B4 /* HWShoppingCartPresentingAnimation.m */, + 7E270235979252FF388A0C6D1E54966D /* HWVisualEffectView.h */, + F5D8EBF4698D8B331794EA6F9BF47665 /* HWVisualEffectView.m */, + 05D708E8F9065868500ABC98E789B739 /* KeyValueObserver.h */, + A2350DF4D8FE6C892E64B8C644667527 /* KeyValueObserver.m */, + 7BDFAC11D184E7F4498FC12FE0AFDCFC /* UIScrollView+Helper.h */, + 330AFA4D280CBB2EE073DCC942489EAB /* UIScrollView+Helper.m */, + 2B0B272843C604B68C602DEE1AD3605F /* UIView+HW_Frame.h */, + ECA7ED760D61427E9195A2805DB71798 /* UIView+HW_Frame.m */, + 2DC211B96CB1A7D40B3203E4778066C9 /* UIViewController+LayoutHelper.h */, + F9AA00EC509DE2C0E25E749F629EF1F6 /* UIViewController+LayoutHelper.m */, + E8C71212CAB0DCBF4059538A93053A4A /* UIViewController+PanModalDefault.h */, + B95FDE5F86C6AC76E24A82E181084256 /* UIViewController+PanModalDefault.m */, + 82F6D1678A37FB68B3455162AB8BDAA2 /* UIViewController+PanModalPresenter.h */, + 2A1E2D85798C902C2A1E1B714EF78587 /* UIViewController+PanModalPresenter.m */, + DB3B6BBCBC04C438F099DE5DEC15C188 /* UIViewController+Presentation.h */, + F6CDCEC9BF52B36734600241EB9CC345 /* UIViewController+Presentation.m */, + F9D546C8B0F4E1C342B53CD786B328AB /* Support Files */, + ); + name = HWPanModal; + path = HWPanModal; + sourceTree = ""; + }; + 288FC03C5D2C78A45B56AFFEE5C2C9F7 /* LSTTimer */ = { + isa = PBXGroup; + children = ( + 68AAA13D71385283DB69A35327BC2F47 /* LSTTimer.h */, + CE5782C68BCDC8C49DD74B206B3FFFF1 /* LSTTimer.m */, + EDCE25045C1BBF6ECB7211723055D0DB /* Support Files */, + ); + name = LSTTimer; + path = LSTTimer; + sourceTree = ""; + }; + 28E2A9A1CEAC3F154F646A51F0227786 /* Support Files */ = { + isa = PBXGroup; + children = ( + ABAC9F2093F2EF164CB968D710D261F5 /* MJRefresh.modulemap */, + 741E2A603352D4102F1DAFBB68C69122 /* MJRefresh-dummy.m */, + 04996832466C0B682760DEB660586A88 /* MJRefresh-Info.plist */, + 81D115D4A9C927BEBA7B66F114F7B4EC /* MJRefresh-prefix.pch */, + 6A2E7581F1DA07EBD6D2568091FCCB71 /* MJRefresh-umbrella.h */, + 7895C7C58218B5F79C76FA1B5A55E669 /* MJRefresh.debug.xcconfig */, + A324C5885C8FB2DC65900A0EE79A0E45 /* MJRefresh.release.xcconfig */, + 9897B379E415C6537D86A30137A8D274 /* ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/MJRefresh"; + sourceTree = ""; + }; + 2F8EF5B81FDAABB39353996747C04D04 /* Core */ = { + isa = PBXGroup; + children = ( + E4A5839D54BEE8A98756D5288A3E5050 /* NSBezierPath+SDRoundedCorners.h */, + 34F0487226F5EBEBA3C6D3E1743C5260 /* NSBezierPath+SDRoundedCorners.m */, + CE2B5265F3721FD7EAE15556CCDB1151 /* NSButton+WebCache.h */, + 53155231B4EB5B29274A0546D6F39B91 /* NSButton+WebCache.m */, + 00449113F3BDDB46E11CEE02CF1F29A1 /* NSData+ImageContentType.h */, + 928339E7523C1267D5DF15E548454A5E /* NSData+ImageContentType.m */, + B09C6285E70223CDED72989080A8442A /* NSImage+Compatibility.h */, + 23763927ED025640A4CAA94867A3D823 /* NSImage+Compatibility.m */, + A1411B1EA7A3C51DB2072BF40B4D5A60 /* SDAnimatedImage.h */, + BDB258BF0BE17AFC3BFB4FB942403B82 /* SDAnimatedImage.m */, + 6C1E503B34448DC968FB5BDFADFAE70F /* SDAnimatedImagePlayer.h */, + 8A5D6AD5CB7122607D6E477D373A31E2 /* SDAnimatedImagePlayer.m */, + 674659ECD497CB56B02FD385F68621CA /* SDAnimatedImageRep.h */, + C94F3031AB6C5451E9610DBD24FE9029 /* SDAnimatedImageRep.m */, + 37977014CE5B8A9E93F1EC56C3AC6D52 /* SDAnimatedImageView.h */, + 883434364AD74D3F77868A0CF2FB7A09 /* SDAnimatedImageView.m */, + B705DD8FCD54B3AFD61B70C82828ACE4 /* SDAnimatedImageView+WebCache.h */, + A2C2A9B920BB92B872BA2AC2EA086220 /* SDAnimatedImageView+WebCache.m */, + E4BFFACAA945CC17167910BF3C319571 /* SDAssociatedObject.h */, + 321334B98147E6E64FCE056E3717FEE0 /* SDAssociatedObject.m */, + 026BB0AEDD69539DEC39191EE0C5214B /* SDAsyncBlockOperation.h */, + 2A03E8820B42DFF0FCE849CB64302CAF /* SDAsyncBlockOperation.m */, + 402736588AC9D07AA589F2943BAE3C89 /* SDCallbackQueue.h */, + 7BD134826FCB54429F667B8DBF296710 /* SDCallbackQueue.m */, + F287F335FB60871C584FAC1904FF4181 /* SDDeviceHelper.h */, + F947DB2E34F4112ED83356B8AA944880 /* SDDeviceHelper.m */, + A464713D364DCC51BD1C744435EF31A3 /* SDDiskCache.h */, + FAA3871C50E5746944D1C3FA3E4736CE /* SDDiskCache.m */, + B5F6ED51FA52849CB3D9D44DD45396E2 /* SDDisplayLink.h */, + 1679E08A4A241FB86455E71FDFB20D9F /* SDDisplayLink.m */, + 0ED5656E5971882A3EA314E222EBC2C5 /* SDFileAttributeHelper.h */, + 72CEA2C3193763834CD0E25D8DB88F2D /* SDFileAttributeHelper.m */, + D444527057532BACBF8EC98BE62D3E03 /* SDGraphicsImageRenderer.h */, + 46F71F9F19999F6D4F186847FA3CC8F7 /* SDGraphicsImageRenderer.m */, + 3501E850F701BA678364B4AFBF1C8417 /* SDImageAPNGCoder.h */, + 07274C755D75F4A07C925D1DDE5FA529 /* SDImageAPNGCoder.m */, + 9F5507B4A6BD90BF5F74B1AAC009AD90 /* SDImageAssetManager.h */, + 87B2A7EE05A20B3EDDFE045A6B7911E5 /* SDImageAssetManager.m */, + BF3C6AEB909F4472F8D8E4E21B25B716 /* SDImageAWebPCoder.h */, + BC30CFC7778FEADF9DCBF0A4ABA1769C /* SDImageAWebPCoder.m */, + DEEA81C89F22AF300ABFA4E5550B7B06 /* SDImageCache.h */, + 77715D6F65035CFA25715F00E4915BA5 /* SDImageCache.m */, + E368F7BC820788B717CC047A744E4326 /* SDImageCacheConfig.h */, + C3D9450A4AAE9542E6A1A0473B7DF812 /* SDImageCacheConfig.m */, + B2C2A4CA80B5FE7CB8927FAEE4CAF5F4 /* SDImageCacheDefine.h */, + C74EA9D59FFCBE16D0C0E5B7B2D53516 /* SDImageCacheDefine.m */, + 839CCD719F79C7FBC2909C72822FB470 /* SDImageCachesManager.h */, + DFE214BE294126C1B4FFE49DDADA7AEE /* SDImageCachesManager.m */, + 6A41E1A305241C5A627FAD06CB90A275 /* SDImageCachesManagerOperation.h */, + EE9E5D3590E1EC14CD269A8B340CE3F0 /* SDImageCachesManagerOperation.m */, + 5EF3B546633CC3DB26A173DE519AC3D7 /* SDImageCoder.h */, + 2E79D80C613F4B57826DA627018BB1C5 /* SDImageCoder.m */, + A3E40CB9D351DF0E70C7A452071E82E1 /* SDImageCoderHelper.h */, + FEE19DBCD45615CC389DD7223D3C447A /* SDImageCoderHelper.m */, + 0BC7EB117F009B160822B3FFCCC63F2A /* SDImageCodersManager.h */, + 03700B93F7A3FF6F3675D80E5DB1C1C7 /* SDImageCodersManager.m */, + 6D8BE2762FA18EF88A5BAD861C739B02 /* SDImageFrame.h */, + 452754C8CDFE17EC42C563B4B6E1F69A /* SDImageFrame.m */, + 449CCE39A5A9EA789B9A284113D1025E /* SDImageFramePool.h */, + BF31B533FDEE0B0DA7ED824B4F336534 /* SDImageFramePool.m */, + 9C0E279B5FFB9696801CC86ACF92805A /* SDImageGIFCoder.h */, + 763CF36C11B6092D9D5485AC2363F205 /* SDImageGIFCoder.m */, + 5EA970CCF2164DC59ECEE9DE06B1BCBA /* SDImageGraphics.h */, + E9FA8ED817E86A0F4415B8E73B62DCF8 /* SDImageGraphics.m */, + 55488AFE93BF97340EF80D0D6C1E2CA0 /* SDImageHEICCoder.h */, + 1CA6A325AACF7253FFEB9D258746335D /* SDImageHEICCoder.m */, + B75E67C2319B8FDBF4D6263203A06D6B /* SDImageIOAnimatedCoder.h */, + B92B905C66437721BB933FEDA5B00CB4 /* SDImageIOAnimatedCoder.m */, + EF1815C1F114106321929B2F631067E5 /* SDImageIOAnimatedCoderInternal.h */, + E4718E4C19C181FBAEBD080580F8C026 /* SDImageIOCoder.h */, + 04094D9F916F0B3E8A409CF5EEC45FCC /* SDImageIOCoder.m */, + C8ED101794ADA1876F4FFCBD1F79D622 /* SDImageLoader.h */, + B9E1D06297B630EA32D1369915C0CB97 /* SDImageLoader.m */, + 7C1F5F86210D3FB1EF59D8665E7C4A77 /* SDImageLoadersManager.h */, + 2E585503EB164F6C036C85B124140368 /* SDImageLoadersManager.m */, + 6EAD8B1C822E0F2BAB884329D798190B /* SDImageTransformer.h */, + C45DF4498F0949CD4F02FA86BFE50D93 /* SDImageTransformer.m */, + 962D7794EB805E6D2F4F5F0B58218401 /* SDInternalMacros.h */, + F1CF9E4569F5B94286E175AF9D675C11 /* SDInternalMacros.m */, + 256D50D68BFC3FD314552D1D0BC2044D /* SDMemoryCache.h */, + C202F1C5D8455CDDCAE965BD7BAAFC3B /* SDMemoryCache.m */, + 98B3D67E4B164109B9B94A959496BA25 /* SDmetamacros.h */, + A92BC89EBEE6C3CE964CA994B506EA43 /* SDWeakProxy.h */, + 98901829A364C7B4F13375AEB6AA0FBE /* SDWeakProxy.m */, + EE827BC4171898B142EBDE3C763AFC7F /* SDWebImage.h */, + B4F7FC0CFCBE2143A4999C2F356D2B47 /* SDWebImageCacheKeyFilter.h */, + C909F8904D301FB96965DD62CE4E2CA7 /* SDWebImageCacheKeyFilter.m */, + BD430BA3E5DB115A0F8BF9D6110923AE /* SDWebImageCacheSerializer.h */, + 0D6771046C7CF97C82B7D303F2AFD49E /* SDWebImageCacheSerializer.m */, + B87895ABF5221A865DF2D53247763F89 /* SDWebImageCompat.h */, + F00B3F2B17BB2816232EB507B7AC9018 /* SDWebImageCompat.m */, + 3313EDBDBF7A4CA0DC32526D9ED0B496 /* SDWebImageDefine.h */, + AEEC6C323BA320F8FE0EFED607BC9994 /* SDWebImageDefine.m */, + 96AEDA915084E949F39F28D248C2FB43 /* SDWebImageDownloader.h */, + B453C947A0F7F0133F2F98F9E8EF1E43 /* SDWebImageDownloader.m */, + CBD58A6BE5B4D23DDB42D3D26A87CAEA /* SDWebImageDownloaderConfig.h */, + 6650E50E5FAFFD61FC973E5A0D5C8398 /* SDWebImageDownloaderConfig.m */, + 3ED4F75E10F9C3D76FF139C89BBB8154 /* SDWebImageDownloaderDecryptor.h */, + E38A10934CB29F9B2C75A0785209FA84 /* SDWebImageDownloaderDecryptor.m */, + 304D443FD07AF14BA7F1628D80971669 /* SDWebImageDownloaderOperation.h */, + 35B67A3C0E25A19B996355E03ED4A3CD /* SDWebImageDownloaderOperation.m */, + B2CE10A014B3B7826BFF751346CE7495 /* SDWebImageDownloaderRequestModifier.h */, + 607560CCA2D3766D85B5AEE557812D0E /* SDWebImageDownloaderRequestModifier.m */, + 6F1245D39980C8CC23C4FFA557C72FA3 /* SDWebImageDownloaderResponseModifier.h */, + 4BC98580A0BA844CDD661F01812A35C7 /* SDWebImageDownloaderResponseModifier.m */, + 16465B6B7358098E137335C9985BBBBC /* SDWebImageError.h */, + A4F1299F85FD74B081B5C5F85EF530B7 /* SDWebImageError.m */, + E0DD4370E4AF2D75716AE1B5D67EABEB /* SDWebImageIndicator.h */, + A56060BC793E00F370FD0DF3B4157376 /* SDWebImageIndicator.m */, + 253C2858A52DB3FD4BE13D65D2B6C2A6 /* SDWebImageManager.h */, + EFC3A24D1CE615DA957AE8C5AC47E5D7 /* SDWebImageManager.m */, + 949A8C57291DF7D8139F90AD367DB80C /* SDWebImageOperation.h */, + 0A70A9B1B9D076F21A4C704EAC69B3E9 /* SDWebImageOperation.m */, + FD3C0DF69EC6CFA1DD8299F62B1A84FB /* SDWebImageOptionsProcessor.h */, + 1B82CFD6AD23DAB70352983FFFA8DBBE /* SDWebImageOptionsProcessor.m */, + 6099FBA2A3EE3D602B49D82E19FA5875 /* SDWebImagePrefetcher.h */, + 9AA439B2B87976D37C23F7DCCE897F8C /* SDWebImagePrefetcher.m */, + 59CF9D4B8C92110B4BC1E1792E4AAEA5 /* SDWebImageTransition.h */, + A4B49E8FCEA2AFEE938A133ECC269CF2 /* SDWebImageTransition.m */, + ACD18D412C592E0FB706C10554E5283E /* SDWebImageTransitionInternal.h */, + 731A2E2A09E554B786F7BD8D9285D1CC /* UIButton+WebCache.h */, + E8B2553B72F322F7DC0ED38BB760DDC6 /* UIButton+WebCache.m */, + DC85B08C4C82F12C3AA7970FE44E1D9F /* UIColor+SDHexString.h */, + 343C42E325F84441C510AF8DEE739ADF /* UIColor+SDHexString.m */, + 8D2F3BF5EE9E269F816330AC6BF6745F /* UIImage+ExtendedCacheData.h */, + A7A348B5BB8CB7A444F827000C95DAE5 /* UIImage+ExtendedCacheData.m */, + 317AEF64C0405ADA2DB47569A6D72FC4 /* UIImage+ForceDecode.h */, + CF91BA63B659D0E10C9E123EBEAB8FA3 /* UIImage+ForceDecode.m */, + FB1FCAC52ADC49B2B3A81FFCCD3D56EE /* UIImage+GIF.h */, + 7A2AEB4C3E4F6147F107DF9376FA7264 /* UIImage+GIF.m */, + 0055AF44029FABEF5E29D1BC1B86CC15 /* UIImage+MemoryCacheCost.h */, + 0451FF8513ABCE79BA473B450192579B /* UIImage+MemoryCacheCost.m */, + 429004AF40A48DE835234068590E6A94 /* UIImage+Metadata.h */, + 5E5C516541F7C7AC40E990C05307FEEF /* UIImage+Metadata.m */, + 517D8EDC9F4BA34E4E4060247125B56D /* UIImage+MultiFormat.h */, + 373258A2F6DFCE8ADD1C1D42DE5EF5D3 /* UIImage+MultiFormat.m */, + A39050EBA53940D0CE63B52BF031BE6C /* UIImage+Transform.h */, + 0EBF81CE72AA8B4B06F1BC37CFA7B96A /* UIImage+Transform.m */, + 855BA7199BD9AC7B4687AF3F66E21279 /* UIImageView+HighlightedWebCache.h */, + F139F3BFF4ABD0678E7947E118F47774 /* UIImageView+HighlightedWebCache.m */, + 0B5075BB968E268BB5D61B393C333DB4 /* UIImageView+WebCache.h */, + FB718B97DF8D94DCF736C973F8184652 /* UIImageView+WebCache.m */, + 36BEAD7507B8644D14D46C852A6EF20B /* UIView+WebCache.h */, + F8CCC7FB49429A8093BC8191C6474D58 /* UIView+WebCache.m */, + CF6ABA6691731EEA533F56170FB03C5C /* UIView+WebCacheOperation.h */, + 43901AAA2BB40AE5F534540676833E30 /* UIView+WebCacheOperation.m */, + 919C930C4E0162377E3C95D0F6F11177 /* UIView+WebCacheState.h */, + 8E4925A54FF503F963785651A98856BD /* UIView+WebCacheState.m */, + 0B3501DF96788E261B37AA47988480FF /* Resources */, ); name = Core; sourceTree = ""; }; - 278BA3F4B18D03DAFFA7B31C7D8082C1 /* NSURLSession */ = { + 3FB59ED98513C1B8FA6DBF40283EB341 /* Serialization */ = { isa = PBXGroup; children = ( - E5F4E4918198D7216ABDC0BE4C9BFCE9 /* AFCompatibilityMacros.h */, - 8A3DF7C8B0CA95D284475EF487EC6944 /* AFHTTPSessionManager.h */, - 8CABC6887E9E2AF4A62642A0C780B4B3 /* AFHTTPSessionManager.m */, - 35618C07738616EC64E35AB9084E01C6 /* AFURLSessionManager.h */, - A6A924083322C61BD2DC82A438F46687 /* AFURLSessionManager.m */, + 4228538168305A12A3465600D6FA372A /* AFURLRequestSerialization.h */, + DE378B71C4559C86FA84F1AB2F15BD03 /* AFURLRequestSerialization.m */, + B5A6B26A93BDE64568CF7AF44D709974 /* AFURLResponseSerialization.h */, + 1DD3D7BBD826081D1399FCDA65D59838 /* AFURLResponseSerialization.m */, ); - name = NSURLSession; - sourceTree = ""; - }; - 3A0A951B4CD76B39B843EF2102500514 /* AFNetworking */ = { - isa = PBXGroup; - children = ( - 743C4A42055B7373FB20F646193D0919 /* AFNetworking.h */, - 278BA3F4B18D03DAFFA7B31C7D8082C1 /* NSURLSession */, - F8863687E232B36E6A3336B80CEF9AEF /* Reachability */, - 42D550893AB4C7DEACCB0BA2BD275931 /* Security */, - A5DEA61008E4B3C548059441B307E57A /* Serialization */, - EAF375AA4ECFCEFB8A42837BED2CA767 /* Support Files */, - 4DFD5EFE1D39A89202C706E005AEAC6C /* UIKit */, - ); - name = AFNetworking; - path = AFNetworking; - sourceTree = ""; - }; - 3C8938BD791B748D62E0594E21A8F606 /* Pods */ = { - isa = PBXGroup; - children = ( - 3A0A951B4CD76B39B843EF2102500514 /* AFNetworking */, - 632F5BB47DEA8EC3D22F645F32B611D0 /* Bugly */, - 055E201C6FE65C14750CE007D95094C3 /* DZNEmptyDataSet */, - 482C57567033D15CB5B58A3A51D16047 /* LookinServer */, - 49A74F626BD81F04B89DC8F68C0C8423 /* Masonry */, - EE64A145CDD38964AF4945D376B599A2 /* MBProgressHUD */, - E11E673B56635EAB5EC9773B8D724830 /* MJExtension */, - A369C1279A7423AC4561A1711312F059 /* MJRefresh */, - C5610FA28BEC5D4814F24C959B9C82BB /* SDWebImage */, - ); - name = Pods; + name = Serialization; sourceTree = ""; }; 4098ED899C8DF8E013F9F260ECFAA236 /* Pods-keyBoard */ = { @@ -1510,15 +2210,6 @@ path = "Target Support Files/Pods-keyBoard"; sourceTree = ""; }; - 42D550893AB4C7DEACCB0BA2BD275931 /* Security */ = { - isa = PBXGroup; - children = ( - 3F61B84FD6B8249C85FCBF56257E34C6 /* AFSecurityPolicy.h */, - 34294BB6B51E74AFE5298D85D957E2F6 /* AFSecurityPolicy.m */, - ); - name = Security; - sourceTree = ""; - }; 47B776543D6613BCB6FB72308F863018 /* Pods-CustomKeyboard */ = { isa = PBXGroup; children = ( @@ -1535,271 +2226,558 @@ path = "Target Support Files/Pods-CustomKeyboard"; sourceTree = ""; }; - 482C57567033D15CB5B58A3A51D16047 /* LookinServer */ = { + 4C9B1F2E52EB330FD3C540E9E187C896 /* JXCategoryView */ = { isa = PBXGroup; children = ( - FB435B3C1ABA904B9D4AEBB59855C935 /* Core */, - 73B1383B55A4637636F1D1641B1B4B2C /* Support Files */, + 72B1B153E1909E0A9DFA6E6097FD363D /* JXCategoryBaseCell.h */, + 6FD544A644986722B86F15A292995457 /* JXCategoryBaseCell.m */, + 7D7A76984F1E3BB7440B31DF8D5447F0 /* JXCategoryBaseCellModel.h */, + 897530E070833B039DC2821D0B63B137 /* JXCategoryBaseCellModel.m */, + 45E71D8592674E85D7D5DA4831A592BE /* JXCategoryBaseView.h */, + 39D939E1825294C23871CD06F0A1E6A2 /* JXCategoryBaseView.m */, + 051A66FC7C22537DD150BA86539EC9D4 /* JXCategoryCollectionView.h */, + E81450568229FA708143E74A7A580F89 /* JXCategoryCollectionView.m */, + 8B890DAD1E942EF3DB7BF5C23113C1B6 /* JXCategoryDotCell.h */, + 87D7822F88C7B9608DF7E50878B7970B /* JXCategoryDotCell.m */, + 931669FB7F8BA540208B2F23E13B2F19 /* JXCategoryDotCellModel.h */, + 3AF0216318F4C1EBD4207012E5E70EB1 /* JXCategoryDotCellModel.m */, + 8EFBD2E7A88C44123D980C42CB8702A4 /* JXCategoryDotView.h */, + C86FEA7FA982FA034501F7AB37760D49 /* JXCategoryDotView.m */, + 1C9E2AC9C9AE14EBBFDCDBBA925613E4 /* JXCategoryFactory.h */, + B82D0099E75E96FE5ACCF5B647388551 /* JXCategoryFactory.m */, + 9234E8779322D7F9722AF6E18FF9F6F3 /* JXCategoryImageCell.h */, + 8067C53E08CA3787D9D5C3551F86EF9D /* JXCategoryImageCell.m */, + D51E4D4230E01D5F3D9340BDF320C3E1 /* JXCategoryImageCellModel.h */, + 570A4EA50A989D93BDAC90837E4F3637 /* JXCategoryImageCellModel.m */, + 31C9A23E37AE09BB9DC1BC766BD3A6AA /* JXCategoryImageView.h */, + 5CB6F43E2EFE165260D66B0BFF9A8831 /* JXCategoryImageView.m */, + 5EE479D553AE99C7C893E8B21299B3AC /* JXCategoryIndicatorBackgroundView.h */, + D68722AFBA338282E0B3C89AFE0F83AC /* JXCategoryIndicatorBackgroundView.m */, + 2A4AC508097EE18B75D5D75FDA7CF5C1 /* JXCategoryIndicatorBallView.h */, + F9FBE6B4C01D1445DBFC466AEA64E5D8 /* JXCategoryIndicatorBallView.m */, + 913F72595D3AEFAFE006FD96A54FD8DA /* JXCategoryIndicatorCell.h */, + F9F30602CBEA307F110682B47DBF3B59 /* JXCategoryIndicatorCell.m */, + 5EFCD05B81004D2C239BFBEBEE4DC3D5 /* JXCategoryIndicatorCellModel.h */, + 7E73D1DD407F0535009A207AB317F8B7 /* JXCategoryIndicatorCellModel.m */, + 37C2A3B1C753D4547646108720BF5321 /* JXCategoryIndicatorComponentView.h */, + 1D490F15AED6B55BCD64F4D5193A9375 /* JXCategoryIndicatorComponentView.m */, + C398AC4FA166ECBDBFA37681D3C108CC /* JXCategoryIndicatorDotLineView.h */, + FD7C0DEE68BC5E8256170F72FCC61847 /* JXCategoryIndicatorDotLineView.m */, + EF2876A2D62001FE741FE92492A10CFF /* JXCategoryIndicatorImageView.h */, + B3443BE7FBE80A857A146093C743D9BF /* JXCategoryIndicatorImageView.m */, + A527D460219BC25D3D8E05E8A68C23C9 /* JXCategoryIndicatorLineView.h */, + B49F76B93F72D361782D7DA99B65ADC9 /* JXCategoryIndicatorLineView.m */, + 30E03A823CD994C7C3DEA8D91B90C5DE /* JXCategoryIndicatorParamsModel.h */, + 1936EF3FEE34E513D746BA5037CDEE80 /* JXCategoryIndicatorParamsModel.m */, + 92A35222DEEC452079F1343331C6E154 /* JXCategoryIndicatorProtocol.h */, + D25C8F67455D872A48F4797213321EA4 /* JXCategoryIndicatorRainbowLineView.h */, + 021930E01F482BDF2DEAAA2AF9FDCF18 /* JXCategoryIndicatorRainbowLineView.m */, + 5B766998FBEAD558A15F06134D5A9335 /* JXCategoryIndicatorTriangleView.h */, + C31C4A7197700436AFBAB631C088A6AE /* JXCategoryIndicatorTriangleView.m */, + 2DFC8007FA865661CA9E295ADD1014BA /* JXCategoryIndicatorView.h */, + 1817B2506E6D89DAFA8176C4A51738C0 /* JXCategoryIndicatorView.m */, + E948F26A10F663204E24603E8527A7F5 /* JXCategoryListContainerRTLCell.h */, + 96D1E2DE4F6F4EB00BD41C7ABD504109 /* JXCategoryListContainerRTLCell.m */, + D9CF33220A4EDFF59077DE1F83605414 /* JXCategoryListContainerView.h */, + C63CFE9D73B31D9EBEF51E32F9AC7286 /* JXCategoryListContainerView.m */, + A23AD7EF4A12F64EAAFE5154D8DC5843 /* JXCategoryNumberCell.h */, + 7B51D3C0C65114DF44F6DDB3ED9C4E4E /* JXCategoryNumberCell.m */, + 292BBC0398F56F3818017A7314541B45 /* JXCategoryNumberCellModel.h */, + 5633AC0E53EEE3085AFE9CB101E6C0CF /* JXCategoryNumberCellModel.m */, + 7B8734ED62BE39C69073D2C32183C6FC /* JXCategoryNumberView.h */, + D5119B7CF0FE429CF0E185983E72F98F /* JXCategoryNumberView.m */, + 0CF1A36FA548FCE3A4F7DA66625E9583 /* JXCategoryTitleCell.h */, + B49837A2AA042F710F43F143A929D49F /* JXCategoryTitleCell.m */, + E01ADBA325921AF74B0FBD58F7BB5032 /* JXCategoryTitleCellModel.h */, + B70A750F053AB9B0B60CBF456ED577A9 /* JXCategoryTitleCellModel.m */, + 524557CADCF9674C470A7B1764594AEC /* JXCategoryTitleImageCell.h */, + 5EADC8693C7692FBBE4CE165F51B28E9 /* JXCategoryTitleImageCell.m */, + 3B812F8DDDC6CC3E3ACDB1D17716E70C /* JXCategoryTitleImageCellModel.h */, + B28192DA39251C0AC1C30AE245A9A547 /* JXCategoryTitleImageCellModel.m */, + 9E91A12C513A640E68663D4ED668C0FC /* JXCategoryTitleImageView.h */, + 9EC4E80691EA4009AB067722DA72E4D5 /* JXCategoryTitleImageView.m */, + 25475D081A3343232AD119F5F5A5F24A /* JXCategoryTitleVerticalZoomCell.h */, + F3BAE7C9BD506017B4C0D7BBB9100900 /* JXCategoryTitleVerticalZoomCell.m */, + C4D51AE584C5960F5C6B60C866377741 /* JXCategoryTitleVerticalZoomCellModel.h */, + 230B07768E56A05E48373DAA2EAC05DE /* JXCategoryTitleVerticalZoomCellModel.m */, + 996C55702A2E4E7B3785C0C5454598C9 /* JXCategoryTitleVerticalZoomView.h */, + 43BA7B9A75BE654B8242649314595C2D /* JXCategoryTitleVerticalZoomView.m */, + 5105F32D29B4C0D80B780EE2DF6D2898 /* JXCategoryTitleView.h */, + 8FEE8F6EEF601125225DCB1FEACED91C /* JXCategoryTitleView.m */, + 892976CDE28E9BEF86BFABB5F84E72F6 /* JXCategoryView.h */, + 8FF761C99D422AE106C31A4A7AE469C7 /* JXCategoryViewAnimator.h */, + 95BCF1B96C9A492409E9634BC63A400B /* JXCategoryViewAnimator.m */, + B4750EDA171CA7EB95AFE62489A712EF /* JXCategoryViewDefines.h */, + 22A80188C121A76950A88A3321260BFD /* RTLManager.h */, + 9A3BA26DC995AB016051D522F5691C91 /* RTLManager.m */, + 3D72A1C48CB238B4D5F50BA925DEDEAE /* UIColor+JXAdd.h */, + EA759F283932CC196A3C378E0037B993 /* UIColor+JXAdd.m */, + 5FEA93EEEC74A71E4D426F48D7F850F2 /* Resources */, + F4552932065591EFBCEA1E5854647226 /* Support Files */, ); - name = LookinServer; - path = LookinServer; + name = JXCategoryView; + path = JXCategoryView; sourceTree = ""; }; - 49A74F626BD81F04B89DC8F68C0C8423 /* Masonry */ = { + 4D01249FF2A98F37C991C38E6B67067C /* JXPagingView */ = { isa = PBXGroup; children = ( - F68B2B4FABAF7DB3BFD45E81B3302EEE /* MASCompositeConstraint.h */, - ABFE70D35403EBB3D3B8E84170698E30 /* MASCompositeConstraint.m */, - B36A499BB6A9A389E077337779129B95 /* MASConstraint.h */, - F57A932DBB8EE96EEDB42899B11A3E40 /* MASConstraint.m */, - 7BA0DD426F8305DA317D708459ABA12F /* MASConstraint+Private.h */, - 63B2D397715E1B3990E46DFCAE0A73D5 /* MASConstraintMaker.h */, - 3D891833337A0E2AFA0DBB31899C747F /* MASConstraintMaker.m */, - 82B53F06F74B4F928AF69994EDA63D71 /* MASLayoutConstraint.h */, - 5AE5F5B6D6DAD0B45FC2D30EE6FBEE81 /* MASLayoutConstraint.m */, - B069597AD0812CBF01ACDD3CE4B6F843 /* Masonry.h */, - 21628153BCD0325102EB502FB5AEDF0F /* MASUtilities.h */, - EA5E2A6BFD8D228A6FF7C7C749D642DB /* MASViewAttribute.h */, - 07F0D69559BBD9895C4D0BD66F33AC55 /* MASViewAttribute.m */, - 2FD6A0DEDE4E0A17B8A614C8D15158DD /* MASViewConstraint.h */, - BBC10C6127599FC7CD74CA6E613C44DB /* MASViewConstraint.m */, - 7D45408149C7FF7C3CD91B6DDBFB7448 /* NSArray+MASAdditions.h */, - A054792401E8F9F7BEA8441F9C1DA7C7 /* NSArray+MASAdditions.m */, - E1C46B6B074DF2D170E6F2ACB5E8C8BA /* NSArray+MASShorthandAdditions.h */, - 1A62C9B59CFA9D74EE95F526BE485EC8 /* NSLayoutConstraint+MASDebugAdditions.h */, - 96E64D1052C3FD60EB6BBB8A95EE1349 /* NSLayoutConstraint+MASDebugAdditions.m */, - 6289794567935CA3DC8B5C49AEA74043 /* View+MASAdditions.h */, - 59AE847A100A8834951E42690C982455 /* View+MASAdditions.m */, - 31E7ED25B098BFBF30E180BFC0E2174B /* View+MASShorthandAdditions.h */, - B4D76F7EB1CE870804724BC071C5ACB3 /* ViewController+MASAdditions.h */, - 904AEE3BB6B326E7E1CFD8B0A34306AB /* ViewController+MASAdditions.m */, - 004BCCE6E90EA8F999F5DD21EFC4736A /* Support Files */, + B4640B79F6E1B39F4E2822274BC61D23 /* Pager */, + DB5A3B2FEE3BD7A679B91E83BA32906B /* Support Files */, ); - name = Masonry; - path = Masonry; + name = JXPagingView; + path = JXPagingView; sourceTree = ""; }; - 4DFD5EFE1D39A89202C706E005AEAC6C /* UIKit */ = { + 4E1FCFC15AFF6ACA076B1D8B295CDE1D /* Support Files */ = { isa = PBXGroup; children = ( - A565D25677F6FEEAD298666682CDA4B2 /* AFAutoPurgingImageCache.h */, - 3C0293D25B82D4CCF17D52B025BDDA03 /* AFAutoPurgingImageCache.m */, - D3C9902E0E2D0A78C2A349E20322FC80 /* AFImageDownloader.h */, - A67D546CB537E231FE83AA071A555BB7 /* AFImageDownloader.m */, - 245FCAB926AF197B8F4E931DD8477D4A /* AFNetworkActivityIndicatorManager.h */, - 3DD65B80E7AA07416BB8F502F3C3A438 /* AFNetworkActivityIndicatorManager.m */, - F53768EF8D38709F253FC1C181B05162 /* UIActivityIndicatorView+AFNetworking.h */, - 15E423D2DE3EB3895273EDB5BC21FDE9 /* UIActivityIndicatorView+AFNetworking.m */, - 35182E600B80DDDFBA4A4B90FAA71EFD /* UIButton+AFNetworking.h */, - 2D93B5DFF8656FC20174F5CDCB325540 /* UIButton+AFNetworking.m */, - 319E8C485C3E5DB2BFBF15AA61E5ABA9 /* UIImageView+AFNetworking.h */, - 4D125D803F381B689272DFC8613DDA9A /* UIImageView+AFNetworking.m */, - E727648E6DB0C84B6B5C85D16CF9D6AC /* UIKit+AFNetworking.h */, - 219886C4AF0E20C3CD4D4061CAAE8767 /* UIProgressView+AFNetworking.h */, - 2D3B8DD288273B0C3AFDD2F366BB894B /* UIProgressView+AFNetworking.m */, - 32556CF656ADFF88DE99F135C7BE2EB7 /* UIRefreshControl+AFNetworking.h */, - 9228BFB339DE3C8FD5163C974AB7DE89 /* UIRefreshControl+AFNetworking.m */, - 8E466B1532DEF5F8A8FE002C3882E69E /* WKWebView+AFNetworking.h */, - 0426BF3118E242E4EA8BB1145A2A6F60 /* WKWebView+AFNetworking.m */, - ); - name = UIKit; - sourceTree = ""; - }; - 632F5BB47DEA8EC3D22F645F32B611D0 /* Bugly */ = { - isa = PBXGroup; - children = ( - DB6A5FFB077AA72411EB46B8A77A31B0 /* Frameworks */, - A6678288D73D0E7B53AB75DF84AA65D4 /* Support Files */, - ); - name = Bugly; - path = Bugly; - sourceTree = ""; - }; - 6CE3F18721CC834AA1D80F2A9F218CA5 /* Support Files */ = { - isa = PBXGroup; - children = ( - 2625A6F485FAAFFDD766C135FDF8F796 /* DZNEmptyDataSet.modulemap */, - 52CE89D1B7CAF7D6D1E509FE1267800A /* DZNEmptyDataSet-dummy.m */, - 20C240076DD8D1DC14E751DAFAE98662 /* DZNEmptyDataSet-Info.plist */, - 26E9B5584E3E3AA9E7AF8978192DF06B /* DZNEmptyDataSet-prefix.pch */, - FBE4C2596FA0518DD6CED29332B75B5B /* DZNEmptyDataSet-umbrella.h */, - 61A50E7751555885AEB4247687F5DF05 /* DZNEmptyDataSet.debug.xcconfig */, - 52832E51BDED300B58102A301664AD5A /* DZNEmptyDataSet.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/DZNEmptyDataSet"; - sourceTree = ""; - }; - 717E6458BD53164643C1A5869C11B538 /* iOS */ = { - isa = PBXGroup; - children = ( - 86A260983254EF2D214865E91D3787B2 /* CoreGraphics.framework */, - 3964617E5C241BE3E12D8F1D88607841 /* Foundation.framework */, - CFBDDF0554D720E199E1094AAEC3D171 /* ImageIO.framework */, - D673941813D9CA4EFFC6C32109054DC5 /* QuartzCore.framework */, - E1DF8BF780A4AD9606856AB857CA1D86 /* UIKit.framework */, - ); - name = iOS; - sourceTree = ""; - }; - 73B1383B55A4637636F1D1641B1B4B2C /* Support Files */ = { - isa = PBXGroup; - children = ( - 3CF065C3DEDD146A59230103D73E1A55 /* LookinServer.modulemap */, - C4BB81E05861A9C00B09F3A39D27B164 /* LookinServer-dummy.m */, - 2CFE5CE900A783BD5709EEF033BA8475 /* LookinServer-Info.plist */, - 400DE9B9180EAE02FE3ADA6DB9EFD64F /* LookinServer-prefix.pch */, - B1A8FD671105727BDE389DF6E59E7187 /* LookinServer-umbrella.h */, - 9641B4F4D8DDE2072CB32BF4C9C2882A /* LookinServer.debug.xcconfig */, - 2DAD93B79D27664FE05E862A2C992A45 /* LookinServer.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/LookinServer"; - sourceTree = ""; - }; - 85416DF4AE2111F696182FA844F2611A /* Support Files */ = { - isa = PBXGroup; - children = ( - 61E1874601B077A6F69725D9EF8827B1 /* MBProgressHUD.modulemap */, - 16C85770D72E9770C476992A31B3655F /* MBProgressHUD-dummy.m */, - D3412473E790C600A01CFF5127EA049C /* MBProgressHUD-Info.plist */, - 6A6FA79B39689AE1D69FBABCD4BB8F7B /* MBProgressHUD-prefix.pch */, - D219431FF998A6D0FA270965A4CDE56D /* MBProgressHUD-umbrella.h */, - 2940A878AE956B2190BA5A68D63DC5AD /* MBProgressHUD.debug.xcconfig */, - 71C7BAB63ED44B881A65C001AA682ADB /* MBProgressHUD.release.xcconfig */, + 3C530EFDCDFFC732A409BADBE3F0D068 /* MBProgressHUD.modulemap */, + D30B8333D334528105E28100C243348D /* MBProgressHUD-dummy.m */, + A16556ABD8D8BADE087CDC162140E59B /* MBProgressHUD-Info.plist */, + 98768C46376F54DFEB58CDD9F278AC71 /* MBProgressHUD-prefix.pch */, + A8AF8342462E3EDE8E3D40F840DFA00C /* MBProgressHUD-umbrella.h */, + EC4CFDD75B85C12B1C1393BEA03A165C /* MBProgressHUD.debug.xcconfig */, + AC0C26DBF6F4D6A9D8C1BF55FE14DABA /* MBProgressHUD.release.xcconfig */, ); name = "Support Files"; path = "../Target Support Files/MBProgressHUD"; sourceTree = ""; }; - 8AB9F15B6060B4A24C4EA01AC9540849 /* Support Files */ = { + 579E4939EC6AC009496870BECBDEC208 /* Reachability */ = { isa = PBXGroup; children = ( - 0AC3ECEAAABFC0FEDCE3E1B814F1A7E5 /* MJRefresh.modulemap */, - 4D47A5312A106ED050240FD5A4E84CE4 /* MJRefresh-dummy.m */, - D226F4D7ADA4D7570E831057BF0F25E7 /* MJRefresh-Info.plist */, - 650740D8E20A30E70F588321BC583BBC /* MJRefresh-prefix.pch */, - 2065E7BBA3909607E34531E7D59623FF /* MJRefresh-umbrella.h */, - D2BBA8DCCC9E2658211368C22BE1B033 /* MJRefresh.debug.xcconfig */, - 45EDC4788D38048F75B7F3CD0BEF1783 /* MJRefresh.release.xcconfig */, - 51D6AF1225DCDC66E13DAA2BCB6B1DCF /* ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist */, + 9C0082C9FF6875DA300AE3D8453DCB62 /* AFNetworkReachabilityManager.h */, + C75FCCDECEB6A92A56B67E27033473B6 /* AFNetworkReachabilityManager.m */, ); - name = "Support Files"; - path = "../Target Support Files/MJRefresh"; + name = Reachability; sourceTree = ""; }; - 9F62E2D2D42206A4CD335DDB26C286FF /* Support Files */ = { + 5FEA21AFA94BB3973C15EEFD1CA50FFA /* LookinServer */ = { isa = PBXGroup; children = ( - DE365B0506D97BB22271ACD3BE9D48CC /* MJExtension.modulemap */, - 2A7BA44CD5FDF42B32263B5F4259A024 /* MJExtension-dummy.m */, - 5CAEE17C08505E0DF4A1EF22D4CAD064 /* MJExtension-Info.plist */, - 964A9667953DC95C883D7E82FD74B649 /* MJExtension-prefix.pch */, - 808621872AB88E6448666731EB043018 /* MJExtension-umbrella.h */, - 57BCCC946B3042A20D0C8F15D69FF943 /* MJExtension.debug.xcconfig */, - 3E2A55F2F78E11DEDCF2FA119B3E1912 /* MJExtension.release.xcconfig */, - 0BDAABEB54032920AAEBA43908724F60 /* ResourceBundle-MJExtension-MJExtension-Info.plist */, + 8083A32807E86242A863314EF6818E55 /* Core */, + 831477AC631FF14EDA7861CA75B58087 /* Support Files */, + ); + name = LookinServer; + path = LookinServer; + sourceTree = ""; + }; + 5FEA93EEEC74A71E4D426F48D7F850F2 /* Resources */ = { + isa = PBXGroup; + children = ( + 7AC0215893BDD3C5E126FCE996097AB4 /* PrivacyInfo.xcprivacy */, + ); + name = Resources; + sourceTree = ""; + }; + 619A9868F13BC15F5FC65525C1D9E2CF /* DZNEmptyDataSet */ = { + isa = PBXGroup; + children = ( + 2945888F89AB6D3ECBBEDD6E09D1B949 /* UIScrollView+EmptyDataSet.h */, + 45FCB10C5ADD911EC17F1E6BAAFE9892 /* UIScrollView+EmptyDataSet.m */, + 6243689E5C76660F684D23A4B8790B3A /* Support Files */, + ); + name = DZNEmptyDataSet; + path = DZNEmptyDataSet; + sourceTree = ""; + }; + 6243689E5C76660F684D23A4B8790B3A /* Support Files */ = { + isa = PBXGroup; + children = ( + 406C8D3FB686F0A24482B5EC0964787A /* DZNEmptyDataSet.modulemap */, + B8322800FD1F06BC2FEA3A9EEA874E20 /* DZNEmptyDataSet-dummy.m */, + 2B53DEB14A9698F954D95E54715C1911 /* DZNEmptyDataSet-Info.plist */, + 7A307E6A261D750F85B7C9C1575036E4 /* DZNEmptyDataSet-prefix.pch */, + 6523AFC889399B6B25C08CCBEEE2F0B6 /* DZNEmptyDataSet-umbrella.h */, + 48E1ED2BAC3C5C1B077AAB67F3325D4E /* DZNEmptyDataSet.debug.xcconfig */, + 5CB726B6B5C83EAABA9AC89E76D45643 /* DZNEmptyDataSet.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/DZNEmptyDataSet"; + sourceTree = ""; + }; + 6D1FBB10825D24E335F04D97066D9C66 /* NSURLSession */ = { + isa = PBXGroup; + children = ( + 060133813AFA51D11B917CB91A3D4950 /* AFCompatibilityMacros.h */, + FB614FC70886C761E2BA7E9C7E7F2D88 /* AFHTTPSessionManager.h */, + A11C415AC80BAC0B06685E1F8AC7C7C8 /* AFHTTPSessionManager.m */, + 1612A7E2EB4D912BD038AFA9FAE11CFD /* AFURLSessionManager.h */, + EA3E73CFAE53223D9EC3DE4B0794DB06 /* AFURLSessionManager.m */, + ); + name = NSURLSession; + sourceTree = ""; + }; + 7DD842DFF9E829253FACA707DA5ADAAB /* FLAnimatedImage */ = { + isa = PBXGroup; + children = ( + E386525610DF7AB4E84ED0202969AB8E /* FLAnimatedImage.h */, + D1046C4A0F4D596969B881D83BCC0FA1 /* FLAnimatedImage.m */, + 18EAC20398B46C2C580B542618314D9E /* FLAnimatedImageView.h */, + 148EEB030F62D4D33B4C03AE45AD6C08 /* FLAnimatedImageView.m */, + CABD2BCBA14C84A63E7608CED87846A3 /* Support Files */, + ); + name = FLAnimatedImage; + path = FLAnimatedImage; + sourceTree = ""; + }; + 8082051853063B4647901F5178837B33 /* Support Files */ = { + isa = PBXGroup; + children = ( + A14754CFA2BACA27D3CA6DD44F6D8F10 /* ResourceBundle-SDWebImage-SDWebImage-Info.plist */, + 5978BDDC6A977C5D014B3D0CC0294043 /* SDWebImage.modulemap */, + 61C0CC288A628CFA871D599D497E2A8E /* SDWebImage-dummy.m */, + 9FB49DC67A435D7D63695F113C3D398C /* SDWebImage-Info.plist */, + AF5F1AB306D02EC6A5F39878FAE8BEA1 /* SDWebImage-prefix.pch */, + FB84DF0F5016EBAF04FE5FE9F22081C0 /* SDWebImage-umbrella.h */, + 93B896E371962B657B3B85C108092214 /* SDWebImage.debug.xcconfig */, + 81F7F63875295940D9A950DB7D2EBDE7 /* SDWebImage.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/SDWebImage"; + sourceTree = ""; + }; + 8083A32807E86242A863314EF6818E55 /* Core */ = { + isa = PBXGroup; + children = ( + 768785318FEB9536A4DAAD47BD76396B /* CALayer+Lookin.h */, + 657631264951C7514A1788B1C6316E7F /* CALayer+Lookin.m */, + 77DEC7B6CE458C6AAB89A25A3E05BA4B /* CALayer+LookinServer.h */, + 798B3DCD95877B6C7D997E0652FB6E9A /* CALayer+LookinServer.m */, + 8BE10EB8B74E3D1DE4172EF863BC22F8 /* Color+Lookin.h */, + 4B2681504ECC11F7B0563ECF0A1FDDFA /* Color+Lookin.m */, + 8679B55EBC5DC660D8E798D1B986FC22 /* Image+Lookin.h */, + C6553D3214536278C24D990CC36267F3 /* Image+Lookin.m */, + 313050E8524ED89E2B2CF8F5C1CC7633 /* LKS_AttrGroupsMaker.h */, + 00AE10F23D2B898E9F45884FD9904B2F /* LKS_AttrGroupsMaker.m */, + ADF656282B85E6C974597F555BDE3F21 /* LKS_AttrModificationPatchHandler.h */, + DEFCE7D8BFD813860A380F7F5B5EB401 /* LKS_AttrModificationPatchHandler.m */, + 769C3408F11A51A90B589A6DBB334C55 /* LKS_ConnectionManager.h */, + DA49453EBB9C905AD701D17F18479113 /* LKS_ConnectionManager.m */, + 52FF07E10C8C0B816653B6836CCFFD04 /* LKS_CustomAttrGroupsMaker.h */, + AB2B98D8DC3605842D8528F53C1896A2 /* LKS_CustomAttrGroupsMaker.m */, + 1EFF4D34DD5391DCE7D206B11306BCE5 /* LKS_CustomAttrModificationHandler.h */, + D00729EFDA62359B2F2AA1EF43FADFD9 /* LKS_CustomAttrModificationHandler.m */, + A0925E96742E33F78D548F10A7C0475D /* LKS_CustomAttrSetterManager.h */, + F363F53534ED7FE5A4BB0A1E1863D5E7 /* LKS_CustomAttrSetterManager.m */, + 98935AEC9F6608D5CCBFEF667B9F658A /* LKS_CustomDisplayItemsMaker.h */, + C19EBB7B5E5A5B4CB83F93B794EA02A1 /* LKS_CustomDisplayItemsMaker.m */, + 51AB8F5FA4517AC80D7763B2894462EB /* LKS_EventHandlerMaker.h */, + CD6BC672271DF551FD22D8BABC528CA6 /* LKS_EventHandlerMaker.m */, + 9C47102257C212ED978684D39466579B /* LKS_ExportManager.h */, + 207535A186296DE018201ED1B7DDD076 /* LKS_ExportManager.m */, + AA7E9357D1D22FB737AEE89305734112 /* LKS_GestureTargetActionsSearcher.h */, + C81473AB6162F68681F317D8EC207A4C /* LKS_GestureTargetActionsSearcher.m */, + 3CA454A209E71894BC9366B10B95D086 /* LKS_Helper.h */, + 4D2B4D757199E020DE43661B60EB2819 /* LKS_Helper.m */, + FEA159570B75D1C95DC0E0B5836BACFF /* LKS_HierarchyDetailsHandler.h */, + 0719BBC5095E9B709A7485C347010514 /* LKS_HierarchyDetailsHandler.m */, + F1FB9919B7B8171A6A8679BDDA407F68 /* LKS_HierarchyDisplayItemsMaker.h */, + 00B27A1456536538B2E7220C71AA3F4F /* LKS_HierarchyDisplayItemsMaker.m */, + 8B8796E86BD11BC29D00EED72E50AE91 /* LKS_InbuiltAttrModificationHandler.h */, + A1DAAC915F745C515E0BF4D613B5CB1C /* LKS_InbuiltAttrModificationHandler.m */, + EDA0AA2D50C091E5400CDFDEC4B5B802 /* LKS_MultiplatformAdapter.h */, + 957B3209BD81CDA1C8049B3245F6946E /* LKS_MultiplatformAdapter.m */, + DBFA6FCFCE1CB3F169BDBDCE936950B5 /* LKS_ObjectRegistry.h */, + CB5214881D82D6C122FB4D3B471F9D93 /* LKS_ObjectRegistry.m */, + AFBA747DBA20D4BACF78CA8DE98ADF94 /* LKS_RequestHandler.h */, + DF017A36F518C19E10298190FD8A84C4 /* LKS_RequestHandler.m */, + 52AF8374431A1EA8420BA1E29139131E /* LKS_TraceManager.h */, + C7F42FC60A06A5673FA7DE53298188E2 /* LKS_TraceManager.m */, + A4CFB2BE169777F50B29077639FCFEC4 /* LKSConfigManager.h */, + 32E665F5EEABCF137D52CE4A3889C9F0 /* LKSConfigManager.m */, + 07C3DB4C7661755654D296A929BE2CE7 /* Lookin_PTChannel.h */, + 862D8BDF52FBE8FCF3A562F5A62C802E /* Lookin_PTChannel.m */, + 8B523AAA92DB90BD5B95092AF6B85BFB /* Lookin_PTPrivate.h */, + 3E05D85B85A84A7D628539AD042EC841 /* Lookin_PTProtocol.h */, + 4B6F5F5F32C55F6B9F4E87EC57A0A074 /* Lookin_PTProtocol.m */, + 210B700E8324769F741C26126E6B1F4A /* Lookin_PTUSBHub.h */, + B1850D4E22F95780586FA04DA695C24C /* Lookin_PTUSBHub.m */, + 3D8A828331C79742A41F54C2050C90A8 /* LookinAppInfo.h */, + DF85367F662269F3652AFC693AA2B00F /* LookinAppInfo.m */, + 903EBE6439B30182644FFF066DE11129 /* LookinAttribute.h */, + B267D6EC269C7ADF7A4202363528E8C2 /* LookinAttribute.m */, + B915A35174E3017D6DC61C0A3E31050E /* LookinAttributeModification.h */, + 39592D3DD29808CC34F5BDE8FFAD64E6 /* LookinAttributeModification.m */, + E6FEAED2BC2A577A78A12FA14FC3BB6B /* LookinAttributesGroup.h */, + D0B1EDD790AB62D80A6CA23D5272938B /* LookinAttributesGroup.m */, + CAE21A3C562355122DA705E505CCA673 /* LookinAttributesSection.h */, + 4F8D39C76EB84B28054B453882C78E41 /* LookinAttributesSection.m */, + F32705CBE56ACF430653A1C459F5351E /* LookinAttrIdentifiers.h */, + 9D4F497397BEDE35BC05F6C2B6D33577 /* LookinAttrIdentifiers.m */, + C9E1D6C567F43B4A9410AC83170573DE /* LookinAttrType.h */, + 97DE751E0ED3939932D72FB39C5A934A /* LookinAutoLayoutConstraint.h */, + 38F21B02ED02115E613C152CE563BD5A /* LookinAutoLayoutConstraint.m */, + 99712B41FFAFC24C5F649A94D8DD7FFE /* LookinCodingValueType.h */, + 10DBEAC7DAAC95D5A947ACA061058C0B /* LookinConnectionAttachment.h */, + 9C75F181A3E07F7E7B4B017B48488393 /* LookinConnectionAttachment.m */, + D9BB987ADE61FFDF3C240961F2EB4DDB /* LookinConnectionResponseAttachment.h */, + B2B7D0FDFC6ECF60B59728E60160431B /* LookinConnectionResponseAttachment.m */, + F5B865CFCA1FF1600CB766B9BC34B8D9 /* LookinCustomAttrModification.h */, + 7E445C787AA09C1E3A771E4C7DBCE2CA /* LookinCustomAttrModification.m */, + 3DDFB85C3FF1851267A20FACB64B4497 /* LookinCustomDisplayItemInfo.h */, + 44B0B0F109E74E6F92B6497967BCE536 /* LookinCustomDisplayItemInfo.m */, + 6AB6F2617132C99A6B5CB953305CCA89 /* LookinDashboardBlueprint.h */, + 73A2C1D7BD2A650246BEE1A00F6D836C /* LookinDashboardBlueprint.m */, + 7DD55E3EFF5073BEBD483D293C40A0D6 /* LookinDefines.h */, + 6EE8AE5699FC4ACD4283D4626ACDF742 /* LookinDisplayItem.h */, + AE19AE8E2478EF2E39C49272A1998EFE /* LookinDisplayItem.m */, + 407D327724ADF96791DFD9B922AA254A /* LookinDisplayItemDetail.h */, + 15D6A20A536D39FB4F4DE78CEC3512CE /* LookinDisplayItemDetail.m */, + 05EE9449F14265ADB3100E60632AB642 /* LookinEventHandler.h */, + D4CFF1EB3CBDD5217E39DD58BD101359 /* LookinEventHandler.m */, + FDCCFFDED68135F2816CA2167E15CF64 /* LookinHierarchyFile.h */, + 3A1C13D0C9F5E8ED93D0398C379507C1 /* LookinHierarchyFile.m */, + 26469EA2BF7F49FCDA80695277950B2B /* LookinHierarchyInfo.h */, + F4F901625B3879AD34FA2A0373208F59 /* LookinHierarchyInfo.m */, + 00C9A4038FA1CE3381055E02DAAEC90E /* LookinIvarTrace.h */, + 6148399DD529311A930CEF2A2AC2FBD4 /* LookinIvarTrace.m */, + 371A20C759D3E78183B0BC7EA626FA2D /* LookinObject.h */, + CFC8ED8D34DD2679124911EB0F515607 /* LookinObject.m */, + E23048DA7D038B179D12173BA0F800DB /* LookinServer.h */, + EB54379A72A5DCC64A2C9D42F05AE928 /* LookinServerDefines.h */, + 09799A44FC43F3184E20B590CC73FFC7 /* LookinStaticAsyncUpdateTask.h */, + FCBD8DFA94436F5E62F1AA0F1AD2F2FA /* LookinStaticAsyncUpdateTask.m */, + 17A16F153D08C8BBF15070C730EC0C3A /* LookinTuple.h */, + B5157027D16B7E61C1D5AB091D10458E /* LookinTuple.m */, + B0922492568B0DD6D1F92C0E3B3A53A1 /* LookinWeakContainer.h */, + 60F9066C601EE11D24D22C170F05AF13 /* LookinWeakContainer.m */, + 852A42FAC0EA5F64033033841A03891A /* NSArray+Lookin.h */, + 4AAF4EE016C54A7F264F9B8FBB0853C8 /* NSArray+Lookin.m */, + 4A2BDE1ACE119E645C72F92B4CCAECF4 /* NSObject+Lookin.h */, + B6575913AB2C7FDA723D279165349FF6 /* NSObject+Lookin.m */, + 3A9477BE731926B610D9B847EF5B7347 /* NSObject+LookinServer.h */, + A566FD7AC8F85BE1E72F6DF11FEA6338 /* NSObject+LookinServer.m */, + C1D06F4343D9C630BC102E7BCD9CECCF /* NSSet+Lookin.h */, + E312EC8FB74A492C6D5A647700644AC4 /* NSSet+Lookin.m */, + 92670C1E3C13D6C6157E7AFB4347DB17 /* NSString+Lookin.h */, + C9A08CB30EFC3A6CB342354C253BE4D8 /* NSString+Lookin.m */, + 70D52E1253BDF6EF05A1C5C1D46734EA /* Peertalk.h */, + C41AE199679E3EEC03FA1272FE103027 /* UIBlurEffect+LookinServer.h */, + B041D1C998D0894DB89A31049CC1B872 /* UIBlurEffect+LookinServer.m */, + A810CCF3953514350B557ABBEEBE5FF6 /* UIColor+LookinServer.h */, + FED91C88820F2942B3A007C5E5D17ACB /* UIColor+LookinServer.m */, + 60195DBDE404C5ECBC4E710D0F5E50E7 /* UIImage+LookinServer.h */, + 20C453B83E1025092DAD587080018B43 /* UIImage+LookinServer.m */, + 310DC522C0637DDB20D8D38412CB4153 /* UIImageView+LookinServer.h */, + DA0C012CAB8552E7EA8382B0E5D6B738 /* UIImageView+LookinServer.m */, + D5909A44E1AC01893309CADDDBC4E50C /* UILabel+LookinServer.h */, + 6BD526972490CFC41EE7106FF8E272CC /* UILabel+LookinServer.m */, + E847BE3D7FA245C62A989A8A4F90542A /* UITableView+LookinServer.h */, + B77422F87DF00923771B3EF8E6C0A9BF /* UITableView+LookinServer.m */, + 5D2F2FDA20E8BC9884D1E9ED05D83DDF /* UITextField+LookinServer.h */, + C64A52A00F5D8A13BA6BD40D1834BF56 /* UITextField+LookinServer.m */, + FCA4EBF34C88159600AC127D3548346D /* UITextView+LookinServer.h */, + 1D8DC297A0249D2FB0109542F14B89AB /* UITextView+LookinServer.m */, + DC7496C927F9E881D19A203C207B5417 /* UIView+LookinServer.h */, + 76AEEFCD2262D6843C63EB46FD6663BB /* UIView+LookinServer.m */, + 4C7F47A09BE728487DF546FE00CA555E /* UIViewController+LookinServer.h */, + 8A9BFDE06B11541EA7E87336A09C3816 /* UIViewController+LookinServer.m */, + 9ABEB6B0A44AC8BCBC6CB1A8A8A9A0FF /* UIVisualEffectView+LookinServer.h */, + A7DF910F689AA8FEAD1EF63DDDFCB780 /* UIVisualEffectView+LookinServer.m */, + ); + name = Core; + sourceTree = ""; + }; + 831477AC631FF14EDA7861CA75B58087 /* Support Files */ = { + isa = PBXGroup; + children = ( + 0DEA9604C374890EC86557DA00C054E0 /* LookinServer.modulemap */, + 6D00FB0A2824B0B4E8A345D97C52AA3B /* LookinServer-dummy.m */, + 06878A6718B46A5E825D03CB581CD8B2 /* LookinServer-Info.plist */, + 5C847B3748FF7761203F8DDBD028D651 /* LookinServer-prefix.pch */, + 469576EF612EDF18C057B4FB1E423192 /* LookinServer-umbrella.h */, + 7376537428F41B571A3D20FF9175747F /* LookinServer.debug.xcconfig */, + 438B056E0DAE53D40DB4894FF36879AF /* LookinServer.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/LookinServer"; + sourceTree = ""; + }; + 83B95F67C4195EA01B02C929A0C06C54 /* Support Files */ = { + isa = PBXGroup; + children = ( + 616DFB551B9EEC8F4D98DBDC3C2543CA /* MJExtension.modulemap */, + 43E163147E40F868F458CD979D77C4E4 /* MJExtension-dummy.m */, + 23B693321C3E2CA46CF401E48AE2795D /* MJExtension-Info.plist */, + 4531FCCC5DE7D00D6F827809F7CD4289 /* MJExtension-prefix.pch */, + 2713EAAF042877733E01E359F3224ABF /* MJExtension-umbrella.h */, + 954035BEFF37A926FB7C25E5508CD25D /* MJExtension.debug.xcconfig */, + 7B582290DB93C466A4DA695035B6DA2E /* MJExtension.release.xcconfig */, + E75295D3FB5952A7B3A8B497D502A68D /* ResourceBundle-MJExtension-MJExtension-Info.plist */, ); name = "Support Files"; path = "../Target Support Files/MJExtension"; sourceTree = ""; }; - A369C1279A7423AC4561A1711312F059 /* MJRefresh */ = { + 8B3672DA9A8B9E29E7BA1D933AD6F3B2 /* Bugly */ = { isa = PBXGroup; children = ( - A53791C99F3E8789C928D8471E4310AC /* MJRefresh.h */, - A417B5FC83ECB57A121FCD14A6DD23D3 /* MJRefreshAutoFooter.h */, - D404BDF65C17843DC41C1611EAAA22EB /* MJRefreshAutoFooter.m */, - C79FFC2722DEE9A1F54D8DBDD3CB2A2C /* MJRefreshAutoGifFooter.h */, - 6E49D88BA109001AA94CB4B1CBCC6353 /* MJRefreshAutoGifFooter.m */, - FAF1C0B2DCF27A6785AA511B6C9290B9 /* MJRefreshAutoNormalFooter.h */, - 79E1EEF42DE5E1954630A63B8A5E02B6 /* MJRefreshAutoNormalFooter.m */, - 80F9F8B5249F11798A805DF46C09F2CA /* MJRefreshAutoStateFooter.h */, - 9450EAE5D947C741A2403ADD203E1875 /* MJRefreshAutoStateFooter.m */, - FDD0D2A5CBDCDA5BDF9600C731F95B24 /* MJRefreshBackFooter.h */, - AB22EEA7E251269666B0DD8D3FCD0892 /* MJRefreshBackFooter.m */, - 2CC603030F93055E51FF99944B356CB6 /* MJRefreshBackGifFooter.h */, - 948E1E3EDCE53B021791B9169CCC28BD /* MJRefreshBackGifFooter.m */, - B70FF2E3C927A22C388C16FE8C3F56DB /* MJRefreshBackNormalFooter.h */, - 426AEC2F7F358DEDB66C3F2D15F925A4 /* MJRefreshBackNormalFooter.m */, - 58AA57BAA26D8C03E401EEFD3C78271F /* MJRefreshBackStateFooter.h */, - 0E24EFDE111F674B782A0DB6E26DA6D2 /* MJRefreshBackStateFooter.m */, - 383AEE356898B114D8DD079C51566FF2 /* MJRefreshComponent.h */, - EF2661A0DF69E1828AB8D83F666F4FBC /* MJRefreshComponent.m */, - B985D3DA018E1C8C3AC44ADE702B404B /* MJRefreshConfig.h */, - 4C9BF32317317006604613DB6B7E6531 /* MJRefreshConfig.m */, - B9E85A8129A4E7BFE16B2262D78F1DCC /* MJRefreshConst.h */, - 9324A882B3ED55B3EF9D92D946555583 /* MJRefreshConst.m */, - 120B89B8756AC54266917A34CDCADBB2 /* MJRefreshFooter.h */, - A4E4BD7B01B4DA8E6A41CD86E6AB6B44 /* MJRefreshFooter.m */, - E7FE66EE9C43A4BD03E9F354FADF7098 /* MJRefreshGifHeader.h */, - 0F0234E8EBBDCA694F549267CF8444C2 /* MJRefreshGifHeader.m */, - D5509360DE46CF0B8D64058FE9FD45E8 /* MJRefreshHeader.h */, - 5989AAAB35D0B7EF697456F3897FACEC /* MJRefreshHeader.m */, - 5932D997195DFCB258D366D038A56978 /* MJRefreshNormalHeader.h */, - 854F1B8C164960BB0D2721562BD6E7E5 /* MJRefreshNormalHeader.m */, - A8E1E4CE0CD5AF60097B9523ED2201F8 /* MJRefreshNormalTrailer.h */, - E25013592494E49EB3F378AA4A68FB7A /* MJRefreshNormalTrailer.m */, - E0E79E8251323154CB271295CCD93D0A /* MJRefreshStateHeader.h */, - D3A9927A87E21A8976D18DC44FE50014 /* MJRefreshStateHeader.m */, - 3DDB2F652BC38BC05396DCC9F34040CD /* MJRefreshStateTrailer.h */, - 6A2C339DB0F9EF94544BE6FCDA59F50F /* MJRefreshStateTrailer.m */, - E603FC069FE0FF9249D8A7348F6E7795 /* MJRefreshTrailer.h */, - ABCA85AD5553CAA4C58A12223211E18E /* MJRefreshTrailer.m */, - 1E12075C58652877783AAD26D8A6ED78 /* NSBundle+MJRefresh.h */, - 8E6B85BD26EE974026A447B476B2932B /* NSBundle+MJRefresh.m */, - EE4B0CFE38831013E2F465F169783700 /* UICollectionViewLayout+MJRefresh.h */, - B7D4D5B8A3207BDAE71FAE9F1B443CBF /* UICollectionViewLayout+MJRefresh.m */, - B640B3AD2FE955C7A51E5B1F84A61189 /* UIScrollView+MJExtension.h */, - F61E20013C3B1EBDF05023CF2525C38C /* UIScrollView+MJExtension.m */, - AEB9B57AEEA7BDF0C696120F4B110F33 /* UIScrollView+MJRefresh.h */, - 0236FAD4E41045C8223B36E40BDEDF2C /* UIScrollView+MJRefresh.m */, - 61AA277CF1084D31AAA460D8C1A9BE4E /* UIView+MJExtension.h */, - 45DC3F40C3A1FA5B5920DED3DF89557C /* UIView+MJExtension.m */, - FD75246711B9ACD8C080F9752A75506E /* Resources */, - 8AB9F15B6060B4A24C4EA01AC9540849 /* Support Files */, + BD3E878C18624C95338F2E281FA906B8 /* Frameworks */, + C910B48399196A5E00BB083DA443CDA1 /* Support Files */, ); - name = MJRefresh; - path = MJRefresh; + name = Bugly; + path = Bugly; sourceTree = ""; }; - A5DEA61008E4B3C548059441B307E57A /* Serialization */ = { + 9A6094CFD16104AD70583A90D874C249 /* Support Files */ = { isa = PBXGroup; children = ( - CA67A34B63E36E76FF453D2ABD613A39 /* AFURLRequestSerialization.h */, - 5C457050D64C2C7287BDFC768D33C9AE /* AFURLRequestSerialization.m */, - F3D6C729EB2C2561DF46F90B1EE029B4 /* AFURLResponseSerialization.h */, - 05D83C1EC3DD8D27EE1C07CFDE18D72E /* AFURLResponseSerialization.m */, - ); - name = Serialization; - sourceTree = ""; - }; - A6678288D73D0E7B53AB75DF84AA65D4 /* Support Files */ = { - isa = PBXGroup; - children = ( - 18DB01964CBE026F2E6511875E1A98E2 /* Bugly.debug.xcconfig */, - 8C9727D0D56A9017D437CA50176F0474 /* Bugly.release.xcconfig */, + 2795C0F083BB71E948BE56DAFC73957B /* LSTPopView.modulemap */, + C98FF255A58DDF6F211BD72458B9C3D0 /* LSTPopView-dummy.m */, + F157AC2A50D3773392D42322F67E0EB0 /* LSTPopView-Info.plist */, + DA08E928976E65BC11D71562A0E4FBA2 /* LSTPopView-prefix.pch */, + D7C0280DF79D384D6CBED6E080E02BB8 /* LSTPopView-umbrella.h */, + 163DD1C8E32A767AC162D451FB47DECB /* LSTPopView.debug.xcconfig */, + 6BD04BB450562622E215B33554778CC3 /* LSTPopView.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/Bugly"; + path = "../Target Support Files/LSTPopView"; + sourceTree = ""; + }; + 9F5BA1D45C5B890529791B582CDD92E6 /* MJExtension */ = { + isa = PBXGroup; + children = ( + 13AC6B7EC0E45B7BC751451206C8C575 /* MJExtension.h */, + 65CCB6F10EC6B284E771B999975CE0B0 /* MJExtensionConst.h */, + 2D0DE149DDBAC4B5DCFA0C2217970015 /* MJExtensionConst.m */, + 99650956C6DC18187951AE72D50E44A2 /* MJFoundation.h */, + BCF14CEE3203A4E740B9A9FD66CCABA4 /* MJFoundation.m */, + AB379411892DE9D6AC2BA478DD047B45 /* MJProperty.h */, + 9D7E307063029FFE21DDCDC0455FA473 /* MJProperty.m */, + 05A7B005509B15E31ECEED7DFEEB1EDB /* MJPropertyKey.h */, + 57A3558C23C0EFA92D7C80FBF8A6332A /* MJPropertyKey.m */, + A0329494F5B3BBF4A9C54DD83622388B /* MJPropertyType.h */, + 073DE0C455B2CE33A0FBA3C6ECF4F8CF /* MJPropertyType.m */, + DEDA7D852A16AEB2E4133F8138BB40A3 /* NSObject+MJClass.h */, + 6D149C2EB765D348E439D96EC2A80A04 /* NSObject+MJClass.m */, + DD2F0E472487CBFBA5CA4F3C62C1BB0B /* NSObject+MJCoding.h */, + 0249A8711339B6CD1E26258C064677E9 /* NSObject+MJCoding.m */, + 1B41D364B66F85CF33EB15116929CF48 /* NSObject+MJKeyValue.h */, + 0C7575113B17F46DF34D3C118CB31308 /* NSObject+MJKeyValue.m */, + 0C6F8F3E8953AADD74838D4A882F45A1 /* NSObject+MJProperty.h */, + D44C8E719DA4251716FDA4B2519C022D /* NSObject+MJProperty.m */, + 12702606A08588ACD81E031A777BAB70 /* NSString+MJExtension.h */, + 15C39377834B42681C3BF6A5471C5F78 /* NSString+MJExtension.m */, + 102054A1E3292F59C346E38466BC61C8 /* Resources */, + 83B95F67C4195EA01B02C929A0C06C54 /* Support Files */, + ); + name = MJExtension; + path = MJExtension; + sourceTree = ""; + }; + A06A903601EA30E66A3EFB3445AE0486 /* Support Files */ = { + isa = PBXGroup; + children = ( + 0A7D8AD4481BE4F0D7389A1662CCA111 /* Masonry.modulemap */, + 07001E763AE097A75E1AFBEB80197373 /* Masonry-dummy.m */, + BD3BC591D3DAF10375616FB7F294F926 /* Masonry-Info.plist */, + BD243AB5EB0FB2763BBC742A8BCF80DD /* Masonry-prefix.pch */, + 128CF11122A7C2009F733361122E39A1 /* Masonry-umbrella.h */, + A603B071469D044FB92322560F131681 /* Masonry.debug.xcconfig */, + 4A4AE7A504C340AE8EE98F70C318D63C /* Masonry.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Masonry"; + sourceTree = ""; + }; + A55E2B2247987FBEC60B3A5F75016BFF /* iOS */ = { + isa = PBXGroup; + children = ( + 638488B4F5FF9C67F848A841B1A34765 /* CoreGraphics.framework */, + 9D41AAC213895165C450F5576DE42CB2 /* Foundation.framework */, + 77F4C0466DFC43C56F1D982F88EF74A0 /* ImageIO.framework */, + BDEE6097B6411333154FEF90A280E3E4 /* QuartzCore.framework */, + 9F5B3C0CF01454E7AC9226E88FDFBAE6 /* UIKit.framework */, + ); + name = iOS; + sourceTree = ""; + }; + A5CE40587B1D0DEFF98742773A62CA50 /* Security */ = { + isa = PBXGroup; + children = ( + 4C354F545C0CC91C4033DC0D648B3819 /* AFSecurityPolicy.h */, + 4883D2BC668CDDE38C319AC414885077 /* AFSecurityPolicy.m */, + ); + name = Security; + sourceTree = ""; + }; + A989CAE17245D9B811F7FFC909DD86CA /* LYEmptyView */ = { + isa = PBXGroup; + children = ( + B5885DEE0FCB371101A605FDA3D3F35C /* LYEmptyBaseView.h */, + 1D0C4CB17BF463D490AE3400293A0D47 /* LYEmptyBaseView.m */, + 374CEB5E4CAC5B1889E4B3A57B47546E /* LYEmptyView.h */, + 39267406AD82F75ABB872A20BE14F010 /* LYEmptyView.m */, + FA5C6E28985540EE03804DDC4277D459 /* LYEmptyViewHeader.h */, + 7A5F8A5650078BFF9587944F0042AE79 /* UIView+Empty.h */, + A34A186C33DB71F8C4ACB6E0705472D0 /* UIView+Empty.m */, + 0CA8B3EFCD9E73829676C70CE3E88BE0 /* UIView+LYExtension.h */, + 0B4EEA7B77703F45AB157AC651CEF4EA /* UIView+LYExtension.m */, + 1C6C79318C220E5B8848BEC84F0BF1D4 /* Support Files */, + ); + name = LYEmptyView; + path = LYEmptyView; + sourceTree = ""; + }; + B4640B79F6E1B39F4E2822274BC61D23 /* Pager */ = { + isa = PBXGroup; + children = ( + 57460121EED43E41D624C46A92FE9E08 /* JXPagerListContainerView.h */, + E0742EB318197474CB672E4520705ACC /* JXPagerListContainerView.m */, + 3B250EFB659FBBBBA5D680859085344D /* JXPagerListRefreshView.h */, + 659E098AEC86E789470E344EB23EC1DD /* JXPagerListRefreshView.m */, + D564B14F434E85E8016FF192E33548A8 /* JXPagerMainTableView.h */, + 9C2DAB09AC8F3AD6E82FDC5DB2562CB4 /* JXPagerMainTableView.m */, + 7B167FA26CB7B8DC98E1A68B1B44BA8A /* JXPagerSmoothView.h */, + CF46C0579CB3C54966C0F025487DB215 /* JXPagerSmoothView.m */, + 8310CCDF3085A9EE32455CB865148664 /* JXPagerView.h */, + 044A47D1E36901CA79D51CC72EA995C9 /* JXPagerView.m */, + F671FF7CE184FC6A84ADEF036DEA2F7D /* Resources */, + ); + name = Pager; sourceTree = ""; }; B94D7768568A9992200DB461E8CF687F /* Frameworks */ = { isa = PBXGroup; children = ( - 717E6458BD53164643C1A5869C11B538 /* iOS */, + A55E2B2247987FBEC60B3A5F75016BFF /* iOS */, ); name = Frameworks; sourceTree = ""; }; - C5610FA28BEC5D4814F24C959B9C82BB /* SDWebImage */ = { + BD3E878C18624C95338F2E281FA906B8 /* Frameworks */ = { isa = PBXGroup; children = ( - 1DF4B2EDEE04858C6D572415F9FFA5F7 /* Core */, - 139D61AB9CCEA3CD3FE43AE8F0DFA14F /* Support Files */, + 634119E1E65F912498A262851F72517B /* Bugly.framework */, ); - name = SDWebImage; - path = SDWebImage; + name = Frameworks; + sourceTree = ""; + }; + C910B48399196A5E00BB083DA443CDA1 /* Support Files */ = { + isa = PBXGroup; + children = ( + 3DF983F1377AD739C3DF33AE51632FCF /* Bugly.debug.xcconfig */, + 0AD4477B34BC6EAF1A362183974F34DC /* Bugly.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Bugly"; + sourceTree = ""; + }; + CABD2BCBA14C84A63E7608CED87846A3 /* Support Files */ = { + isa = PBXGroup; + children = ( + B6ED434773EE7ECEDAB93E7A62107F73 /* FLAnimatedImage.modulemap */, + 2CCD2F6CD21BCE8D4DC6CE0FB91B91CB /* FLAnimatedImage-dummy.m */, + 64D49E5BC4A3E2ECFAA63B66E38A6F8D /* FLAnimatedImage-Info.plist */, + 353BBBDE951248D62CFDF267ACFAD0A7 /* FLAnimatedImage-prefix.pch */, + 7FAB126742756E8C628ED27AEC1B9567 /* FLAnimatedImage-umbrella.h */, + 2CB55990BE7673BB5930FB77BB2A2C33 /* FLAnimatedImage.debug.xcconfig */, + D5BBA19EC013D7414BE28B29DCA7518D /* FLAnimatedImage.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FLAnimatedImage"; sourceTree = ""; }; CF1408CF629C7361332E53B88F7BD30C = { @@ -1807,89 +2785,212 @@ children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, B94D7768568A9992200DB461E8CF687F /* Frameworks */, - 3C8938BD791B748D62E0594E21A8F606 /* Pods */, - 1C8A19406FF58E9BA6BC427CA02E9857 /* Products */, + E3282B046A353048174B1E513DFF9A4E /* Pods */, + D3828787C1DCC6E76B71C947B6C876AE /* Products */, F7ED90CD818DD0484BF7DB0E1E3B9AB2 /* Targets Support Files */, ); sourceTree = ""; }; - D98E67C1E6047B33AD3281F951D96C7F /* Resources */ = { + D3828787C1DCC6E76B71C947B6C876AE /* Products */ = { isa = PBXGroup; children = ( - F320516E3A699EEF56C411E9C2DA9C29 /* PrivacyInfo.xcprivacy */, + A4FA15D44DF6BAC7550EDEED10862AA3 /* AFNetworking */, + 5DA4577FE3BC4A03751108FFED07B385 /* DZNEmptyDataSet */, + FAA5F2D71B90788C908800A94534AA92 /* FLAnimatedImage */, + 7819923046C4F6B199F8D45E9F7BA6B0 /* HWPanModal */, + C3A46B03C308EEEB11F2A62BA5D2E8BE /* JXCategoryView */, + BB4F011171FCB76B1AEBE390F843E930 /* JXCategoryView-JXCategoryView */, + 2F4A1CCB21DB7EA5A2ACEB11E374FBCA /* JXPagingView */, + E03F152E95B6924D2486511337D24503 /* JXPagingView-JXPagerView */, + 25664483ABF4DC8EC03E7472AA04333B /* LookinServer */, + 399102B94B534EB49EE0E5512D150CA8 /* LSTPopView */, + DE19C7D984CBC535E4768F5543458A1E /* LSTTimer */, + EEB5224BF1CABA409B3D3760EDDAEA0A /* LYEmptyView */, + 1FFED36A657123030ABB700256D73F15 /* Masonry */, + 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD */, + 2B276B0A79173A1D6E83C9B4FB9A4A57 /* MJExtension */, + 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */, + E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */, + 7E3097CFEFDA621E9FB0E62009FF87FC /* MJRefresh-MJRefresh.Privacy */, + 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */, + DCA062FD08AC9694D8D781B3492421C5 /* Pods-keyBoard */, + B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */, + CF1281E58AA1045D4B7F33FC56691C42 /* SDWebImage-SDWebImage */, ); - name = Resources; + name = Products; sourceTree = ""; }; - DB6A5FFB077AA72411EB46B8A77A31B0 /* Frameworks */ = { + D453386A36746D9803EFAF894ED288F7 /* SDWebImage */ = { isa = PBXGroup; children = ( - 70E91E9355FAF7D2A8CA2A2112F06A60 /* Bugly.framework */, + 2F8EF5B81FDAABB39353996747C04D04 /* Core */, + 8082051853063B4647901F5178837B33 /* Support Files */, ); - name = Frameworks; + name = SDWebImage; + path = SDWebImage; sourceTree = ""; }; - E11E673B56635EAB5EC9773B8D724830 /* MJExtension */ = { + DB5A3B2FEE3BD7A679B91E83BA32906B /* Support Files */ = { isa = PBXGroup; children = ( - B486D1944AF55BFAF5E8F8CDE6F8EB79 /* MJExtension.h */, - C342060C11E55E0DDCC3A84C8C1FBC35 /* MJExtensionConst.h */, - BCE109BED042388EE5FB3949ADA18281 /* MJExtensionConst.m */, - D9B1F5912311585292CF1DB19B5FF418 /* MJFoundation.h */, - 47E596E1EB48CB4E8DE37CC0D5122787 /* MJFoundation.m */, - BB20479CEB729CCB614B58BD2EFB3BB7 /* MJProperty.h */, - DF383723C6CD6F7B6FCFE6C752DF50AF /* MJProperty.m */, - D197698AA79A94AD39EC006BBB9D3481 /* MJPropertyKey.h */, - 3F39E9FDE611BCC2A514A77F1EB63E8B /* MJPropertyKey.m */, - 04549DFA210F3D3C27211535994000B3 /* MJPropertyType.h */, - D15A23E7684648249EA4D7C312BACC22 /* MJPropertyType.m */, - 96163189CC5AFA5E4E23D6B0B3EADFF7 /* NSObject+MJClass.h */, - 049541DC9203D75878CAF900D458CC34 /* NSObject+MJClass.m */, - CC6EC6E349C4E8476F9617E9150D43FE /* NSObject+MJCoding.h */, - 45F43707DFF3E5A8EFA1404F7259F5DF /* NSObject+MJCoding.m */, - 5210B0534D834B2EF86FDFCE90B73F2D /* NSObject+MJKeyValue.h */, - 2EEEDD3CF0530751FD80AFB402DAB153 /* NSObject+MJKeyValue.m */, - 364231170128CA2CD3F9589FE34C2FAE /* NSObject+MJProperty.h */, - 336D23D3AF9B2B8FD356A62D7B4A2A05 /* NSObject+MJProperty.m */, - AF4D3A8A4AF29616DFF2E40A94DA00AE /* NSString+MJExtension.h */, - A3A3B77B219A105E2636BBFACE42D7A8 /* NSString+MJExtension.m */, - D98E67C1E6047B33AD3281F951D96C7F /* Resources */, - 9F62E2D2D42206A4CD335DDB26C286FF /* Support Files */, - ); - name = MJExtension; - path = MJExtension; - sourceTree = ""; - }; - EAF375AA4ECFCEFB8A42837BED2CA767 /* Support Files */ = { - isa = PBXGroup; - children = ( - 00E5C0F46BD576A82A38738DB780C7D9 /* AFNetworking.modulemap */, - 83A4CDCDF549B87D4E437ED8A4615D91 /* AFNetworking-dummy.m */, - 23D7D1DC3E63FD87D87BE6C2EB198360 /* AFNetworking-Info.plist */, - 7D5B144E69C677553A95B3CCA57BC43C /* AFNetworking-prefix.pch */, - 0696D0619ACA95D8E9E7EFDC0CD595D2 /* AFNetworking-umbrella.h */, - 5104591E28208BB976FFAD3D7AFA2F58 /* AFNetworking.debug.xcconfig */, - C6F66997EF28E05B21EB7F13B379645A /* AFNetworking.release.xcconfig */, + 56F54F2E70EF1B4C4CD6CC49471EBF8F /* JXPagingView.modulemap */, + 10AACE3BDEFABB8B9E709942B03E5595 /* JXPagingView-dummy.m */, + F762DC35806D05FE8346CE64A0357D9A /* JXPagingView-Info.plist */, + A9BB84448AE1154A6E3D359329D6E5D8 /* JXPagingView-prefix.pch */, + B4319C3394898C8897D6580DAC5A5124 /* JXPagingView-umbrella.h */, + 39D7BCC784A30383722D127896FE591E /* JXPagingView.debug.xcconfig */, + D3FD4542A2D174FC95524833AB672073 /* JXPagingView.release.xcconfig */, + 2F04E40EC66FE8A57ECA4BC540959E1D /* ResourceBundle-JXPagerView-JXPagingView-Info.plist */, ); name = "Support Files"; - path = "../Target Support Files/AFNetworking"; + path = "../Target Support Files/JXPagingView"; sourceTree = ""; }; - EE64A145CDD38964AF4945D376B599A2 /* MBProgressHUD */ = { + E3282B046A353048174B1E513DFF9A4E /* Pods */ = { isa = PBXGroup; children = ( - 2D069519EE909290F7C452231691CA88 /* MBProgressHUD.h */, - 8A6D5DE8BC7E18B47355B8494A426209 /* MBProgressHUD.m */, - 85416DF4AE2111F696182FA844F2611A /* Support Files */, + F50E68E76DBF5D25ABBDA080A797818B /* AFNetworking */, + 8B3672DA9A8B9E29E7BA1D933AD6F3B2 /* Bugly */, + 619A9868F13BC15F5FC65525C1D9E2CF /* DZNEmptyDataSet */, + 7DD842DFF9E829253FACA707DA5ADAAB /* FLAnimatedImage */, + 276C8F966392FC7A9273EA1CF3239640 /* HWPanModal */, + 4C9B1F2E52EB330FD3C540E9E187C896 /* JXCategoryView */, + 4D01249FF2A98F37C991C38E6B67067C /* JXPagingView */, + 5FEA21AFA94BB3973C15EEFD1CA50FFA /* LookinServer */, + 070A9E270BA37B1A5AAC97680E006F46 /* LSTPopView */, + 288FC03C5D2C78A45B56AFFEE5C2C9F7 /* LSTTimer */, + A989CAE17245D9B811F7FFC909DD86CA /* LYEmptyView */, + EE105AE032C43766E8A0D667D3647744 /* Masonry */, + 2397706FC09C7D8BAD347D387C455173 /* MBProgressHUD */, + 9F5BA1D45C5B890529791B582CDD92E6 /* MJExtension */, + 23E095E4ABDFCF286D5B6E1FB3668170 /* MJRefresh */, + D453386A36746D9803EFAF894ED288F7 /* SDWebImage */, ); - name = MBProgressHUD; - path = MBProgressHUD; + name = Pods; sourceTree = ""; }; - F364D65121D8297BD4970B4E36B87837 /* Resources */ = { + E56FC4F1AC3134805F24F088D231587A /* UIKit */ = { isa = PBXGroup; children = ( - B9232C2E4F4A27C4FBD3F8EA3E351AF5 /* PrivacyInfo.xcprivacy */, + C3DBF2503619D6F278D203DBF5D29B4E /* AFAutoPurgingImageCache.h */, + ED87146FC94850F3891F867B1931F652 /* AFAutoPurgingImageCache.m */, + 36CBA5AB35EE7DE7B4A5CDBAC4BE20A8 /* AFImageDownloader.h */, + 41B61F60FDADCD1988F2A5F1B93F6FB0 /* AFImageDownloader.m */, + A198AAC0BC41558B9FC61F89E90D900F /* AFNetworkActivityIndicatorManager.h */, + 6516BB90D0CA47F75712B356350A9FC1 /* AFNetworkActivityIndicatorManager.m */, + DCB771163568003A2EA8F4B1A606B9ED /* UIActivityIndicatorView+AFNetworking.h */, + BF141C03BAA67847DFB6B6DFF0D1CBFC /* UIActivityIndicatorView+AFNetworking.m */, + D7F6132E07FDE40130D6C51920456A21 /* UIButton+AFNetworking.h */, + BF0EE7E880EA65C279154531EF91F5E8 /* UIButton+AFNetworking.m */, + ED332DDCE634104C42A2AF8F698EDFB2 /* UIImageView+AFNetworking.h */, + B628043D13CE1145E17714D58AB2A687 /* UIImageView+AFNetworking.m */, + CBB2B3782C3C4626F075A8900436D09D /* UIKit+AFNetworking.h */, + EB461C49F04DBE8D8B709BDAA4911ADC /* UIProgressView+AFNetworking.h */, + 5B758502F7753329D591359BA2747831 /* UIProgressView+AFNetworking.m */, + 48A816CF0BA23EA39A514E31ED98C5D3 /* UIRefreshControl+AFNetworking.h */, + 80E9CB1F62E65A837FF5E47B2FC3ECA1 /* UIRefreshControl+AFNetworking.m */, + B052BF123A39C5CF4B531584A2A83BED /* WKWebView+AFNetworking.h */, + A1C4717F035C7128013EA7E000DAC18A /* WKWebView+AFNetworking.m */, + ); + name = UIKit; + sourceTree = ""; + }; + EC737F9C95A0D5999B811C9A1D937DBC /* Code */ = { + isa = PBXGroup; + children = ( + DB7D4CE7BA063A9CA415CD86C8825985 /* LSTPopView.h */, + 633C3F66E9BA0FD7538C55D5287ED77E /* LSTPopView.m */, + 7D7595F0F8BE4F40C64D68F0D491C6C6 /* LSTPopViewProtocol.h */, + 6757029D58C1BFD772BCC87D14A52E39 /* UIView+LSTPV.h */, + 1B1E80842E43848FFB0F162AFF96E774 /* UIView+LSTPV.m */, + ); + name = Code; + sourceTree = ""; + }; + EDCE25045C1BBF6ECB7211723055D0DB /* Support Files */ = { + isa = PBXGroup; + children = ( + 6331F4B8E0F66A8F7B8028B33CF71268 /* LSTTimer.modulemap */, + A3211D6272FC8FFC9717C01969D328F7 /* LSTTimer-dummy.m */, + B74E719F2E64B3E186B6F4B672482329 /* LSTTimer-Info.plist */, + 7D6E9AC32A60E19ACB08AED4E4CD31A3 /* LSTTimer-prefix.pch */, + 88F65BAED091224357C1ABFEA1C484FA /* LSTTimer-umbrella.h */, + 6CE98E2FC8B92A0E98F20755C88122A4 /* LSTTimer.debug.xcconfig */, + 73EBDE260791BF4440027F8601391D8B /* LSTTimer.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/LSTTimer"; + sourceTree = ""; + }; + EE105AE032C43766E8A0D667D3647744 /* Masonry */ = { + isa = PBXGroup; + children = ( + AE4CC2528765A45B472AD5B813D01119 /* MASCompositeConstraint.h */, + 70CD4567ACE296214EA982091E2B8F90 /* MASCompositeConstraint.m */, + FD61DA71A7253ED59D65D424C86E2C50 /* MASConstraint.h */, + 23B6D3BC0C4291E4CB154E7F35862BCB /* MASConstraint.m */, + AC368BF52013B3AE323DC35D782A044B /* MASConstraint+Private.h */, + 404BBFC3B5A2ADAEF4E188881B357111 /* MASConstraintMaker.h */, + 673C80521DE4F20FDE3E9A82E6EBEC53 /* MASConstraintMaker.m */, + 2A98EB9CE425ECC87D9747E4EAC3DB0C /* MASLayoutConstraint.h */, + 7DEDD90DB6CF7DD05B6B753765E65AAD /* MASLayoutConstraint.m */, + 1E2CD23DF8D29ECCE7278412B1BFFFA2 /* Masonry.h */, + 1BFABBA210FF6BEF09CABCCBE8AE590F /* MASUtilities.h */, + 7083FA062632CC52050FC4EB53D64E3A /* MASViewAttribute.h */, + B9CA9F01554205BFBACCA553143C8676 /* MASViewAttribute.m */, + 6EB329DC3D8A252CA69C19DAF330A784 /* MASViewConstraint.h */, + 0CE35A6903D3E473ACA2703E7286A28E /* MASViewConstraint.m */, + 05FF40C91ADEB302CBF4314535A1A6E7 /* NSArray+MASAdditions.h */, + 3E34DAE4904CE87FBB70688EA36DF9D3 /* NSArray+MASAdditions.m */, + 986324EA3CC9A3BDF0E5C7B1763862EE /* NSArray+MASShorthandAdditions.h */, + BE9E061AE26F933A7BBEFF3D94E9B32D /* NSLayoutConstraint+MASDebugAdditions.h */, + D8B8A062E76BF87D54F581F6428D4E28 /* NSLayoutConstraint+MASDebugAdditions.m */, + 8B8AB8065F8811289957B59E9EBA6B47 /* View+MASAdditions.h */, + 1069EA3A85D1A1A87FE087B0FE402436 /* View+MASAdditions.m */, + EBEEA0239556FEF194877FD307A4ADD6 /* View+MASShorthandAdditions.h */, + FED4C87CAD14B9336A225C943B75263C /* ViewController+MASAdditions.h */, + DB1B5D6DA097974C176F91F3853055EC /* ViewController+MASAdditions.m */, + A06A903601EA30E66A3EFB3445AE0486 /* Support Files */, + ); + name = Masonry; + path = Masonry; + sourceTree = ""; + }; + F4552932065591EFBCEA1E5854647226 /* Support Files */ = { + isa = PBXGroup; + children = ( + 526BF014AFB62CD2E2E5312B573388BC /* JXCategoryView.modulemap */, + D98B4BEA4820634A8F01172731FF97B7 /* JXCategoryView-dummy.m */, + A01B197EE310DCCE265AA065FA12EF38 /* JXCategoryView-Info.plist */, + F09D5DAEE3CD3FFE1B213DFEF893E818 /* JXCategoryView-prefix.pch */, + AC3EF9D4544217A0B4E13DA6B530C974 /* JXCategoryView-umbrella.h */, + F68616E55705601CBE5D9437AD83B340 /* JXCategoryView.debug.xcconfig */, + DF80C06856CA889ADB8807594055C7DF /* JXCategoryView.release.xcconfig */, + AAA2247A63D832BDB9097AE7D635F20C /* ResourceBundle-JXCategoryView-JXCategoryView-Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/JXCategoryView"; + sourceTree = ""; + }; + F50E68E76DBF5D25ABBDA080A797818B /* AFNetworking */ = { + isa = PBXGroup; + children = ( + 860D7179002683A0368E532B751FC40E /* AFNetworking.h */, + 6D1FBB10825D24E335F04D97066D9C66 /* NSURLSession */, + 579E4939EC6AC009496870BECBDEC208 /* Reachability */, + A5CE40587B1D0DEFF98742773A62CA50 /* Security */, + 3FB59ED98513C1B8FA6DBF40283EB341 /* Serialization */, + 184D0B412C8826DE321973718A83EAD0 /* Support Files */, + E56FC4F1AC3134805F24F088D231587A /* UIKit */, + ); + name = AFNetworking; + path = AFNetworking; + sourceTree = ""; + }; + F671FF7CE184FC6A84ADEF036DEA2F7D /* Resources */ = { + isa = PBXGroup; + children = ( + 7EC4505824D228FB201DC90A544C01B3 /* PrivacyInfo.xcprivacy */, ); name = Resources; sourceTree = ""; @@ -1903,164 +3004,19 @@ name = "Targets Support Files"; sourceTree = ""; }; - F8863687E232B36E6A3336B80CEF9AEF /* Reachability */ = { + F9D546C8B0F4E1C342B53CD786B328AB /* Support Files */ = { isa = PBXGroup; children = ( - 62E02B7B42A91CD6887912774FAE6528 /* AFNetworkReachabilityManager.h */, - 0D18C326A9F4C285AD294832344E63FF /* AFNetworkReachabilityManager.m */, + 59720B9654BC9C6EC9F2FF79FB3FEB5A /* HWPanModal.modulemap */, + 0AE235E52EF7BBF7348F9B4CAB71F7D8 /* HWPanModal-dummy.m */, + CDE56910104E914C73DC565FDFEABE34 /* HWPanModal-Info.plist */, + 4F973225F70967D6C01DF18ABCACA3C4 /* HWPanModal-prefix.pch */, + 1EFF4EEBD779C7DB39B6B044205385FA /* HWPanModal-umbrella.h */, + 4201C2CD51C00E5AC0EC45DC41B32695 /* HWPanModal.debug.xcconfig */, + CA665BB1B8AEA701C3C1A72312BFE105 /* HWPanModal.release.xcconfig */, ); - name = Reachability; - sourceTree = ""; - }; - FB435B3C1ABA904B9D4AEBB59855C935 /* Core */ = { - isa = PBXGroup; - children = ( - E857EC016B703D1261AC73360907C980 /* CALayer+Lookin.h */, - 3BBF905BC343AA0D52B6BC0B1E5B22E9 /* CALayer+Lookin.m */, - 26476CAEC54A4CE04264494F816DFD2C /* CALayer+LookinServer.h */, - A99D2B8B886EDA66D95608FD72CE97AF /* CALayer+LookinServer.m */, - 4FD8426A1028406F5A9C4E27D5C9E76C /* Color+Lookin.h */, - 9278559A57D46FAC97B2480A76E574BE /* Color+Lookin.m */, - 2039E8AAF8AAC77E31E425C61871263D /* Image+Lookin.h */, - 19CD19C5B1822DA77E4C7C9F454FD5D5 /* Image+Lookin.m */, - FAB9874FA4C241C24657D3A825C00C66 /* LKS_AttrGroupsMaker.h */, - EA281F7D07872BD2CB3C821E84CCC544 /* LKS_AttrGroupsMaker.m */, - 477B43B19C3181419CE0D39929320355 /* LKS_AttrModificationPatchHandler.h */, - 79EEB00E9ED2C742987150EA5E0B1341 /* LKS_AttrModificationPatchHandler.m */, - 613D22FE29FDFD98F1BA3415B19FB040 /* LKS_ConnectionManager.h */, - 5ABD1279233951A8EAE905C43AD033A4 /* LKS_ConnectionManager.m */, - 9D58792A3DBAB3667630D1FF53DDFB8D /* LKS_CustomAttrGroupsMaker.h */, - 667106A3B29FC2624F444E79272C8235 /* LKS_CustomAttrGroupsMaker.m */, - 834B6D6A1ACFBDDF049322F2ED0C17DE /* LKS_CustomAttrModificationHandler.h */, - FB260AFEB0CD406D8CDEDE623A1369CF /* LKS_CustomAttrModificationHandler.m */, - F98B3E6FF4A7A436AEB00C4FE95820A2 /* LKS_CustomAttrSetterManager.h */, - 1D74E044AA7CFE331B6C3B53D98B1022 /* LKS_CustomAttrSetterManager.m */, - 6F10AABF341F29547C8D1C780B3F8861 /* LKS_CustomDisplayItemsMaker.h */, - C08BFCAD6B6021A9C9686DA64A6CF1AE /* LKS_CustomDisplayItemsMaker.m */, - DE6C055C722C44DA0E562F93906DCD34 /* LKS_EventHandlerMaker.h */, - 7CB82C5681E372AE74735E8F3B7211E5 /* LKS_EventHandlerMaker.m */, - DECAD058B2FE8CD24CC1022B0A1523AB /* LKS_ExportManager.h */, - A306B5D1B1BD0232E2121BA1E0EA27F9 /* LKS_ExportManager.m */, - 7E82EAB687527F885E79D9835727B3F8 /* LKS_GestureTargetActionsSearcher.h */, - 9F1EE18C1314EB74EEB6B6392E8EFB08 /* LKS_GestureTargetActionsSearcher.m */, - 567AA7AB9514E985494C554A1802C03B /* LKS_Helper.h */, - 371FD070C447028E0DC76F07BB442FC4 /* LKS_Helper.m */, - 5E355B215CED31C4C6EF33EEB9E95B38 /* LKS_HierarchyDetailsHandler.h */, - 94310BE9068195ADA7842BD0A9A7F782 /* LKS_HierarchyDetailsHandler.m */, - 52FBF3084E82AF80B1B017FB5240AF4F /* LKS_HierarchyDisplayItemsMaker.h */, - 3E2B86406A2B5383183DAE9ABBBB3893 /* LKS_HierarchyDisplayItemsMaker.m */, - E91E93486D40A052515660F00B079B5A /* LKS_InbuiltAttrModificationHandler.h */, - 37559870F51779045F8C7A57C1303E2D /* LKS_InbuiltAttrModificationHandler.m */, - 0075507DF323DF510CA1115DE2B33C98 /* LKS_MultiplatformAdapter.h */, - 31C69A4489CC7299F114CDEAFBE0DE3C /* LKS_MultiplatformAdapter.m */, - FF266D90F27C22E50821C68FB0B959D8 /* LKS_ObjectRegistry.h */, - 30361FA11468C74A598363E37D30E56C /* LKS_ObjectRegistry.m */, - E4000AF0B9EEE3F891ADD766B1967BD3 /* LKS_RequestHandler.h */, - 68C023D8DAEB5C5E7F36F7020DDBFE63 /* LKS_RequestHandler.m */, - 46771EF8828C8A7519CEFD7A8DF062BE /* LKS_TraceManager.h */, - A3868E0511721B009DE0A628C978E4AF /* LKS_TraceManager.m */, - 6FD83C0A67C6DD93C76CB6563151D889 /* LKSConfigManager.h */, - 4B2A98ADD6BF259F1E366B570C576632 /* LKSConfigManager.m */, - 341D877992B274AC6FD93AB03542E561 /* Lookin_PTChannel.h */, - 93AFD572FFECC065D5DF0E8764C35B66 /* Lookin_PTChannel.m */, - 0D703CF356A8E2B3B3665722366223A5 /* Lookin_PTPrivate.h */, - 1550F0B5EA5360BFA35606256AB6EF51 /* Lookin_PTProtocol.h */, - 84E9E0A3D552DFF9EC45D14794237342 /* Lookin_PTProtocol.m */, - 4211A99A6EE6255E875FA46E987F2128 /* Lookin_PTUSBHub.h */, - 9C8E3573AF9C6E24E9DFBDDB57A91B44 /* Lookin_PTUSBHub.m */, - 2F6981AC25702BE9417B498391042242 /* LookinAppInfo.h */, - DE5E3242D0D245F39B1349B5C4819144 /* LookinAppInfo.m */, - F74FD66E160DEA3B30F3C017DE8ED1BA /* LookinAttribute.h */, - 7FCB45CBC3B45614560DA456506F73F1 /* LookinAttribute.m */, - 06660480BC631DCE06583A85704487AB /* LookinAttributeModification.h */, - FD1216744C111B10EA2988454A525213 /* LookinAttributeModification.m */, - 1948F2AFCD4F7087CA46FB78E5A05ABD /* LookinAttributesGroup.h */, - 594BEBF4113035634E37CC4FC2A11D62 /* LookinAttributesGroup.m */, - 40B6DD67F49B0103232B5D6B727392FA /* LookinAttributesSection.h */, - EF6193F470BF021CAED5E3E0DC4F602E /* LookinAttributesSection.m */, - 94CD4DB147D9FC14A9FB75335D8AAAF6 /* LookinAttrIdentifiers.h */, - 75E99E8BA24E841D85C9E942E3654D62 /* LookinAttrIdentifiers.m */, - B12DF9FA146221C01FCE0D22DDBDC890 /* LookinAttrType.h */, - 0301A3F865A2919DCD43EE9D0DC363A5 /* LookinAutoLayoutConstraint.h */, - 528C15198BF77FCE909FB6A717EA8C53 /* LookinAutoLayoutConstraint.m */, - A7178BC144BA120067B45EC042E2D156 /* LookinCodingValueType.h */, - 5212AF1887982114A494FF962BEF5A35 /* LookinConnectionAttachment.h */, - A6EB4E3885146B9E8EBACA05C540E733 /* LookinConnectionAttachment.m */, - 9BF2F8A5A2E35CC31448E86BCF471F49 /* LookinConnectionResponseAttachment.h */, - 3B6B095661E36C4E8A066559D4D5AF33 /* LookinConnectionResponseAttachment.m */, - 2F154763B55BC95D1F3E0C64970B8D48 /* LookinCustomAttrModification.h */, - 4730B0C65CA50BE6D828887D7CC8EB9F /* LookinCustomAttrModification.m */, - D4D2347D4EFB2E5610773AF965AA8399 /* LookinCustomDisplayItemInfo.h */, - 1C5B4FB13625B33C4ABB17DDEF05C782 /* LookinCustomDisplayItemInfo.m */, - 713E37659AD7D79DA6664C3D3ECF01F7 /* LookinDashboardBlueprint.h */, - 290A1387E4C301A25D8613FBB0DCEC6A /* LookinDashboardBlueprint.m */, - 6E6089EEBB83334AD3EFA96BE408F86D /* LookinDefines.h */, - 7597119135479FEF90DC7CA9DDBF03A6 /* LookinDisplayItem.h */, - E9ED096883562D4C47E188D0E5CB3065 /* LookinDisplayItem.m */, - A1BB512E1904C9AC07E6CEBA4DE525DB /* LookinDisplayItemDetail.h */, - DC3E4B841669D08E886FD8D7A86C654E /* LookinDisplayItemDetail.m */, - F746B8A0D89C293CD78D1EE71CD25FF1 /* LookinEventHandler.h */, - 189A631A2ED6331F0A226846AD73B1E4 /* LookinEventHandler.m */, - 6DAD9E82D42212E9D52E28737BC21479 /* LookinHierarchyFile.h */, - EFD8B43671F8A160934DA73D3C45B4C0 /* LookinHierarchyFile.m */, - 9C9BCDBD08949F0C3053B9F87567E0B2 /* LookinHierarchyInfo.h */, - 56A3EB69345768D61D52161327AE66C8 /* LookinHierarchyInfo.m */, - E05CD820CF8075CB902341061803D784 /* LookinIvarTrace.h */, - 872090FEDB94946E441D4F936A1357C0 /* LookinIvarTrace.m */, - E70A8D54BBD1266CC7CAFB4BD5CE317B /* LookinObject.h */, - A3048EE57AEE9C3B5FDB98C9E7DF4BB9 /* LookinObject.m */, - 30A10CFE082F8338A031688B47CDED17 /* LookinServer.h */, - FEBDC1C9F54DE3E90674A96F19B3458A /* LookinServerDefines.h */, - D23D41020809113858D4CA46059797CF /* LookinStaticAsyncUpdateTask.h */, - 7DDE67F73A61A7328413374AFFA92E85 /* LookinStaticAsyncUpdateTask.m */, - E785CD9E03330FEEAB8EA2F65DA92853 /* LookinTuple.h */, - D03549B19B7C1700178CF12088FCE44C /* LookinTuple.m */, - 785DDFE2F3C7BA8AEDE2278087F506EB /* LookinWeakContainer.h */, - F9B85917A028A675DFE95B885791EDFC /* LookinWeakContainer.m */, - FEE404F0AEA8371C4FCFE3F576AA5835 /* NSArray+Lookin.h */, - 49A24CBDEFCE6B22E2D355C6D04AC9B4 /* NSArray+Lookin.m */, - 9F2C6DE995A9BCF5E418479898442088 /* NSObject+Lookin.h */, - BA48F14A970C2FE9AE9B9A3F4EF27D84 /* NSObject+Lookin.m */, - 87D20D63606C6DC8B53F345069126C44 /* NSObject+LookinServer.h */, - E66FFAE76E02A3342AF857261F059F70 /* NSObject+LookinServer.m */, - FA2246CD5BC5C3E37CEC58BCA4848181 /* NSSet+Lookin.h */, - 3E5219BC7E7BF5C405E48CC237D2EDC2 /* NSSet+Lookin.m */, - 52EF359F996014A062F3A2945F10438A /* NSString+Lookin.h */, - 3ED91326A0371ACE08A353BC67F60F6B /* NSString+Lookin.m */, - ED81CDC30BE2F7BBA09422B3CD1BDF85 /* Peertalk.h */, - 220B8AB16FBD2158AB55D35E9376D13A /* UIBlurEffect+LookinServer.h */, - D950E8533947A1D8B1CABC80463AFF52 /* UIBlurEffect+LookinServer.m */, - F81A89C6E769F9B774524A9FE4BA70B5 /* UIColor+LookinServer.h */, - 1D4236904A41DC2950754F5BE583BD4A /* UIColor+LookinServer.m */, - 241D729CBB4E30C3E09474F7F34CB9FA /* UIImage+LookinServer.h */, - F2087695EC0958A50E2C65A5D2E03159 /* UIImage+LookinServer.m */, - 6CAEA0BC49D62C0D220FA986A5391EEC /* UIImageView+LookinServer.h */, - A6B89FBB0AA4A7BD7E16AFF20A519DC2 /* UIImageView+LookinServer.m */, - ECA6154AE35962F20A086F5A3633C0CC /* UILabel+LookinServer.h */, - C23D52958B18447DC5C865BB12951C58 /* UILabel+LookinServer.m */, - CAE0A8B09C0AF83117C6BC9602D5D41F /* UITableView+LookinServer.h */, - 7584B9C7664B986D7C6582FD3280C473 /* UITableView+LookinServer.m */, - AB70C7432DDB8346C9DB4A27C7C7AEEB /* UITextField+LookinServer.h */, - CEC88A03608F444860F81FB5EB689938 /* UITextField+LookinServer.m */, - E9FADEFBF123E3EB09754AA63F0510E1 /* UITextView+LookinServer.h */, - D54A6D034409C4B729B7DBA2D502B89D /* UITextView+LookinServer.m */, - 12119FD9C09B77E5C8A003238C89E88A /* UIView+LookinServer.h */, - E3ADFF983A9B025AF718C3D24404E480 /* UIView+LookinServer.m */, - 2567115C715DFD2B942FF9386C729778 /* UIViewController+LookinServer.h */, - 5AF7E49BBE304E0327E319036BE5671B /* UIViewController+LookinServer.m */, - 594925FC6BBDEA3002D153F167630F93 /* UIVisualEffectView+LookinServer.h */, - 2731C084E8B9BB6A54629DDFEBD14EA1 /* UIVisualEffectView+LookinServer.m */, - ); - name = Core; - sourceTree = ""; - }; - FD75246711B9ACD8C080F9752A75506E /* Resources */ = { - isa = PBXGroup; - children = ( - 352F463EFB3454F98E285A844376EC28 /* MJRefresh.bundle */, - A6057C23DD0D9C9A5559F8F0DC47A97D /* PrivacyInfo.xcprivacy */, - ); - name = Resources; + name = "Support Files"; + path = "../Target Support Files/HWPanModal"; sourceTree = ""; }; /* End PBXGroup section */ @@ -2117,6 +3073,27 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 195AA888551D84C490CBCAED7AE25EBE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 7BC817F176759B34FDC3C9A3BDE900BF /* LYEmptyBaseView.h in Headers */, + EF51279C724969A99FF5EF85F832FC00 /* LYEmptyView.h in Headers */, + F2892F71762EC5410EE733B862712BB3 /* LYEmptyView-umbrella.h in Headers */, + 9C6A760E54D2281BBE39A443C0F78D55 /* LYEmptyViewHeader.h in Headers */, + 1ED0D560CC57BCED931C26E643B2A96A /* UIView+Empty.h in Headers */, + 9F8A77D8902C98115735987BA80BD5C9 /* UIView+LYExtension.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1BBE9495F3D97388AE8F965FB5CA16AD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C2405D23D1A7428F65C7D740476ABA2 /* Pods-keyBoard-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 22C4F6C2D1258108CF5B6E74F03D0EB2 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2313,14 +3290,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5E9A96655812158910B2D46F18F4983F /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 891AB9476B659A3490DCE45A52A8D132 /* Pods-keyBoard-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 5F83BB683AB24A3D1254696689952DDF /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2329,6 +3298,130 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7A48625CF583F169B2CE65398246355A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D380F9C945002DBF2E7D64983ABDC890 /* JXPagerListContainerView.h in Headers */, + 20D5706AD3ED295B4FBACD8825DC3A1E /* JXPagerListRefreshView.h in Headers */, + E77175BDAE33AADF66766B28AA710247 /* JXPagerMainTableView.h in Headers */, + CA9AFE3460622CC65F75A2DDE845F6E9 /* JXPagerSmoothView.h in Headers */, + 85ED10431A6C01970A3DAD8A8C9BF25F /* JXPagerView.h in Headers */, + 3CE13969772F4180701A575FAB98E978 /* JXPagingView-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 80AAB619EDBB0EBDBBC84368EED44AA3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2EC1750C894F036194B90CFD26072B0C /* FLAnimatedImage.h in Headers */, + F600BB873FD4764BAA9E02826F804486 /* FLAnimatedImage-umbrella.h in Headers */, + 01D2F1D0ABE13AAB2CDC0C25E378E964 /* FLAnimatedImageView.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84D76E7A37ACD9AD8CE52211102311F6 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 713D162A627185DA38847832AB5BDA44 /* LSTPopView.h in Headers */, + DDB268F1408C6AA5860C768310E9B9D6 /* LSTPopView-umbrella.h in Headers */, + D121163078CA9BBE54A83BD73EF784CF /* LSTPopViewProtocol.h in Headers */, + 3E982309E295BB31C065D62750D0F1FD /* UIView+LSTPV.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 93691E22DE50657D0D08BA5D05234F57 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A643679AC9795083558C6D8E33AF6151 /* JXCategoryBaseCell.h in Headers */, + C74589E03918328E4D27EFCBF6C4A0B8 /* JXCategoryBaseCellModel.h in Headers */, + 88197D535BEBB0F4B71F106AE300631D /* JXCategoryBaseView.h in Headers */, + 780EDF2615923E89C179EB5A60D2DA41 /* JXCategoryCollectionView.h in Headers */, + 2EC7BA321016EC71EA595E4BAF0B7E8B /* JXCategoryDotCell.h in Headers */, + 22C38AE7AB145224FF646303AFED11D2 /* JXCategoryDotCellModel.h in Headers */, + 6B9D333C18DDBF4E7CC889F7FDE05EEA /* JXCategoryDotView.h in Headers */, + 4C8C34A09D61A3881DFB1A544A2CA2A5 /* JXCategoryFactory.h in Headers */, + 7D1E98BE9558F6E5E29B0E81EC526A90 /* JXCategoryImageCell.h in Headers */, + B0F512045830FAB66AE7526E35501800 /* JXCategoryImageCellModel.h in Headers */, + 55910DBCDF99E39955BE01EAD8251081 /* JXCategoryImageView.h in Headers */, + BD7E02AB6057AD5A6AC513C34D508135 /* JXCategoryIndicatorBackgroundView.h in Headers */, + ECC6BC85943DB873215826A344A462FD /* JXCategoryIndicatorBallView.h in Headers */, + 5CAB535753B28B463140F421E9B00136 /* JXCategoryIndicatorCell.h in Headers */, + 6BE86A0FFB0D69C6098CC75E1FB4E8B5 /* JXCategoryIndicatorCellModel.h in Headers */, + 168889E3E897E6D6102A2AA7F7C47496 /* JXCategoryIndicatorComponentView.h in Headers */, + BCEEAFC24178DE5AABACC74245CE1739 /* JXCategoryIndicatorDotLineView.h in Headers */, + C8685678D1B020F87365D022216FFE29 /* JXCategoryIndicatorImageView.h in Headers */, + E2DF1B379D9444D40D78320E90B1DC07 /* JXCategoryIndicatorLineView.h in Headers */, + E52DCE394A6E02B6BA11FA64624F68F3 /* JXCategoryIndicatorParamsModel.h in Headers */, + 1399CD097E164E2C7A6882F0C8FFA525 /* JXCategoryIndicatorProtocol.h in Headers */, + 0AA1842830C770B1E299BAC977E813D9 /* JXCategoryIndicatorRainbowLineView.h in Headers */, + 546DE9D8142C6D8554E083C6FD65D0BE /* JXCategoryIndicatorTriangleView.h in Headers */, + F1ABB5428A1CCF2EAC42A4C3B388F25D /* JXCategoryIndicatorView.h in Headers */, + 11AD210D385F977383AFB974D3CDEF53 /* JXCategoryListContainerRTLCell.h in Headers */, + 6F75FDB9BE37C9A8473F97B1696B5D09 /* JXCategoryListContainerView.h in Headers */, + 31FA8264AA5553AB85039530B1FB8C4B /* JXCategoryNumberCell.h in Headers */, + BFD8EC99CD8DA66E3C6C0B3EE8CC4859 /* JXCategoryNumberCellModel.h in Headers */, + 1C1BC9F0555B36914FF5278D30152DE6 /* JXCategoryNumberView.h in Headers */, + 4424E7517B86FE622BCD3D5040FC579C /* JXCategoryTitleCell.h in Headers */, + C07F8A334C739FD38D9CB5C5239D683F /* JXCategoryTitleCellModel.h in Headers */, + 70D30BC7134E3C8006BF0B6A4B438057 /* JXCategoryTitleImageCell.h in Headers */, + 1F778CA18D1F4A50D9F15280B25D10EB /* JXCategoryTitleImageCellModel.h in Headers */, + 874CE8F3650D220092077846A46598E6 /* JXCategoryTitleImageView.h in Headers */, + 1DC161351EBD409CC622E826340E4FD8 /* JXCategoryTitleVerticalZoomCell.h in Headers */, + 17341EDF872432C3966B77976F3E0470 /* JXCategoryTitleVerticalZoomCellModel.h in Headers */, + 52E60EE26D065DB63D272298AC8867DF /* JXCategoryTitleVerticalZoomView.h in Headers */, + 88889F5DA04EB4FA08125742B5E522DA /* JXCategoryTitleView.h in Headers */, + 5EE53074B8A35D48AB76CAF38C88A37A /* JXCategoryView.h in Headers */, + B948DCB652CEF1509FBE410D85844A53 /* JXCategoryView-umbrella.h in Headers */, + 4281CC31F4D4EAE690F999C778F17E5B /* JXCategoryViewAnimator.h in Headers */, + A1BFCC1BC5107F5F72BDBDB98E12559C /* JXCategoryViewDefines.h in Headers */, + CEC9EF043F69710AC29940EB4E1E2B19 /* RTLManager.h in Headers */, + F458385338076D8734DD74BE4A94B33F /* UIColor+JXAdd.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A903C05DE36F05DE8EA13A2F4A3D52E8 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCCBFE0D3914D33369C19AC135AB54AA /* HWBackgroundConfig.h in Headers */, + 76C8C631DF9AC2F667369EEA0CE46522 /* HWDimmedView.h in Headers */, + 7276688DEA6FB95D4DEB7F3D019C3958 /* HWPageSheetPresentingAnimation.h in Headers */, + EDB9E11998290348E4DFB5140D678942 /* HWPanContainerView.h in Headers */, + FF106518AFECA24E74B1D649E4F9AC70 /* HWPanIndicatorView.h in Headers */, + 0A7342FACEBA0077F1B06178940883DB /* HWPanModal.h in Headers */, + C04D578067F77AAB6717D32712CC39A2 /* HWPanModal-umbrella.h in Headers */, + D737D93725B0E072027AB6DA9C4DDDEC /* HWPanModalAnimator.h in Headers */, + 36B3F095DFFC8D2AF2C0A8C523173927 /* HWPanModalContainerView.h in Headers */, + 4DD9F4BAA95C3527A660D3AAD055CF1E /* HWPanModalContentView.h in Headers */, + 12EC136F97CCCDD8C3765925FABA52CD /* HWPanModalHeight.h in Headers */, + 3127F22BF0A5465D472669272D586BDC /* HWPanModalIndicatorProtocol.h in Headers */, + 3CA9E838F014DC32CFCF6AD36F5D7E58 /* HWPanModalInteractiveAnimator.h in Headers */, + 5106193FDEA44A08AAAAB9B8A227CBE9 /* HWPanModalPanGestureDelegate.h in Headers */, + C9A72F0A93329C42B77395B0F6CEA26C /* HWPanModalPresentable.h in Headers */, + 1DB724891F1F6468BDB333369F667F39 /* HWPanModalPresentableHandler.h in Headers */, + E97B2C62D3EE772504A939BEE7D6B459 /* HWPanModalPresentationAnimator.h in Headers */, + B8CA1F338C44C633916650FD85DA5A30 /* HWPanModalPresentationController.h in Headers */, + E4773572BED239AA7D618F1C05BAF51E /* HWPanModalPresentationDelegate.h in Headers */, + 9BBBDC6BB6583BCAA75242231B62B530 /* HWPanModalPresentationUpdateProtocol.h in Headers */, + 03623FBDBE9F6B422E9A5C6EAD321A58 /* HWPanModalPresenterProtocol.h in Headers */, + 3679603CE8336E00A0BFAA39E10A92D0 /* HWPanModalShadow.h in Headers */, + CF7005F2C42AC2E2DD6D437D52C7048B /* HWPresentingVCAnimatedTransitioning.h in Headers */, + 2D0E2E3CDCB12399497B4F31D4C20E3E /* HWShoppingCartPresentingAnimation.h in Headers */, + 4503182D5F8EF2F02609862026D2D455 /* HWVisualEffectView.h in Headers */, + D3615499AFE4D2A8EC2E773F4D8A82B2 /* KeyValueObserver.h in Headers */, + 4334CCEA5B7EA16A4EF26702D287CB07 /* UIScrollView+Helper.h in Headers */, + 76019F9FDD44B8F79261AD55C8728164 /* UIView+HW_Frame.h in Headers */, + 353C1D03325B8F3E65F985DA29245F18 /* UIViewController+LayoutHelper.h in Headers */, + B987864019E987FE32AB26A9CF2C8E12 /* UIViewController+PanModalDefault.h in Headers */, + 7FA48BF8B9F73775654E75CEB5363FF4 /* UIViewController+PanModalPresenter.h in Headers */, + 6D637D02F5EE50D21C8548061956C898 /* UIViewController+Presentation.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B5D73FBBE3085418AA04A3B4B8D080B8 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2364,6 +3457,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FFA880310EDC0CF0A2515E0ED18689B0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + EC6671997676ABEBC34F2BE6C01266B1 /* LSTTimer.h in Headers */, + CA543D086B4C8E314FB43F0B78147FE9 /* LSTTimer-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -2385,33 +3487,75 @@ productReference = A4FA15D44DF6BAC7550EDEED10862AA3 /* AFNetworking */; productType = "com.apple.product-type.framework"; }; - 18BD026D2210082A239FC15D072FD5BF /* Pods-keyBoard */ = { + 16704C6B67439DA959DB043702C75A7A /* JXPagingView-JXPagerView */ = { isa = PBXNativeTarget; - buildConfigurationList = 3FA2BE14A4014E20D1803ECC0CEB5A7F /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */; + buildConfigurationList = 404863FC7F43060AAE7C6FA66F917915 /* Build configuration list for PBXNativeTarget "JXPagingView-JXPagerView" */; buildPhases = ( - 5E9A96655812158910B2D46F18F4983F /* Headers */, - 87D36E846DA0820C15C53178D809C27F /* Sources */, - AC60AAEBCF4A484AB8DAD9EBCA30DBD7 /* Frameworks */, - B3CE18BE6ADF72F2E31CF5989ACEA7C5 /* Resources */, + 5E3F655370D8F2DAABC53D59D069B3A1 /* Sources */, + 2D2D1D550E12F4C0C9C30D5A3CD01C4E /* Frameworks */, + 860DF70163CE0C8308216A41597A40DF /* Resources */, ); buildRules = ( ); dependencies = ( - 69F880D20E49FF278D9D99F0FC359C80 /* PBXTargetDependency */, - 071F326A1012E3F537E82D4600D6099B /* PBXTargetDependency */, - 3CC71AA09CD8D91F7CAC51C8C0C3D8A8 /* PBXTargetDependency */, - D4796534CC93D6F34DDBB3E449125A23 /* PBXTargetDependency */, - 575EFC27A8B3BE6F6EF85229FA04A8F6 /* PBXTargetDependency */, - 8343E87E690EAE8ED5D426D9B97081C7 /* PBXTargetDependency */, - 4CEDC3503EBC64FA8AD4BB751A1257E2 /* PBXTargetDependency */, - EF01B3D5C4798C26DB6A90866EE03225 /* PBXTargetDependency */, - 09B11A1954CF8173776EC7F7B6571224 /* PBXTargetDependency */, + ); + name = "JXPagingView-JXPagerView"; + productName = JXPagerView; + productReference = E03F152E95B6924D2486511337D24503 /* JXPagingView-JXPagerView */; + productType = "com.apple.product-type.bundle"; + }; + 18BD026D2210082A239FC15D072FD5BF /* Pods-keyBoard */ = { + isa = PBXNativeTarget; + buildConfigurationList = 48C48CA74E925091D509EAE661A5D87D /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */; + buildPhases = ( + 1BBE9495F3D97388AE8F965FB5CA16AD /* Headers */, + E3AA8B53287F6ACBF2F2800146C6ECD0 /* Sources */, + 2A4C89A05153A8C37E3B9ACF170A9EB8 /* Frameworks */, + 2B9BFC6488F4ABCC9916C35510BB7D7C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D431884F2F2835EF4FDB44219ADAA88B /* PBXTargetDependency */, + 3067995C8EDFEF1A63CA85F6D091AD0B /* PBXTargetDependency */, + E7B53C78EB3FA9751B3C978B6CB97980 /* PBXTargetDependency */, + D6DB70831F359F7235B8C97A50300DDF /* PBXTargetDependency */, + C0EEAAE6B64FC5B6DFCE16644E06B2CA /* PBXTargetDependency */, + CE8F85B0B6965EE090F12CB8B384E2A3 /* PBXTargetDependency */, + BB84628766B4F66DF4DC34732901F40E /* PBXTargetDependency */, + 90059A9ED4F8080EA23A70C0EB5FE47E /* PBXTargetDependency */, + 7D1F8A3DE88EF01CF89EF4750D0835BC /* PBXTargetDependency */, + F750881392263D81A5BB4E131005A44E /* PBXTargetDependency */, + 28BE8BB7BD4C9C6AB673350A1570FA84 /* PBXTargetDependency */, + FE3D9C468529CF310D88B6383BEFBFDD /* PBXTargetDependency */, + 9403290AE1B7249ADE1ED8950739EE94 /* PBXTargetDependency */, + 22268E07F0FDFC08F0EE9D82FF083DD6 /* PBXTargetDependency */, + ABAA3F7B666DBB2B8C2E114433F7A89D /* PBXTargetDependency */, + D2B74321DDAF41730531D5172D454257 /* PBXTargetDependency */, ); name = "Pods-keyBoard"; productName = Pods_keyBoard; productReference = DCA062FD08AC9694D8D781B3492421C5 /* Pods-keyBoard */; productType = "com.apple.product-type.framework"; }; + 31DCABABCA873FBA7A92FEB47D71ED8E /* HWPanModal */ = { + isa = PBXNativeTarget; + buildConfigurationList = D47A0ADD8E3841C9330561C3E1664BB3 /* Build configuration list for PBXNativeTarget "HWPanModal" */; + buildPhases = ( + A903C05DE36F05DE8EA13A2F4A3D52E8 /* Headers */, + 3EA749E8A97310551F543948A8C92475 /* Sources */, + 6328134103EDE3EF1EA3866C0B5CCA07 /* Frameworks */, + 27B1683E18D5081CF470BC9A233C7D28 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HWPanModal; + productName = HWPanModal; + productReference = 7819923046C4F6B199F8D45E9F7BA6B0 /* HWPanModal */; + productType = "com.apple.product-type.framework"; + }; 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */ = { isa = PBXNativeTarget; buildConfigurationList = 2F9E94B5F79E365095CB33D3D3FCA6A2 /* Build configuration list for PBXNativeTarget "SDWebImage" */; @@ -2424,13 +3568,49 @@ buildRules = ( ); dependencies = ( - EE61A46DF554B3E5C29DB10DCBB3618A /* PBXTargetDependency */, + D37914A752321FFCFF48251614F3D1B6 /* PBXTargetDependency */, ); name = SDWebImage; productName = SDWebImage; productReference = B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */; productType = "com.apple.product-type.framework"; }; + 4A8E8992707D01510894596DB9BCCA00 /* FLAnimatedImage */ = { + isa = PBXNativeTarget; + buildConfigurationList = F06E4A04DE8430EB36B85704972503A5 /* Build configuration list for PBXNativeTarget "FLAnimatedImage" */; + buildPhases = ( + 80AAB619EDBB0EBDBBC84368EED44AA3 /* Headers */, + FCCB6EDD1337F2C5115636BA7E258EDF /* Sources */, + D267C6F8AD649543C397BCAAADB7F148 /* Frameworks */, + 9EF83CC96C715675FF7A15F96027E83F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FLAnimatedImage; + productName = FLAnimatedImage; + productReference = FAA5F2D71B90788C908800A94534AA92 /* FLAnimatedImage */; + productType = "com.apple.product-type.framework"; + }; + 4AA4C7BB776C55F3421BA137B643DD64 /* LYEmptyView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 511C0840C50AF349D9A51E73BA56D28D /* Build configuration list for PBXNativeTarget "LYEmptyView" */; + buildPhases = ( + 195AA888551D84C490CBCAED7AE25EBE /* Headers */, + E8A558A3C629ABA805E9D912FCCBCD2F /* Sources */, + 98BB4909B1035551DF579C13A59BAA4D /* Frameworks */, + 311EF2CB460B544059B769919A899ECA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LYEmptyView; + productName = LYEmptyView; + productReference = EEB5224BF1CABA409B3D3760EDDAEA0A /* LYEmptyView */; + productType = "com.apple.product-type.framework"; + }; 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */ = { isa = PBXNativeTarget; buildConfigurationList = 547AC2DDC5CDD1783E0827EEA7D453E1 /* Build configuration list for PBXNativeTarget "MJExtension" */; @@ -2443,7 +3623,7 @@ buildRules = ( ); dependencies = ( - 578B4FEE3B5BBEBE31FFA9C174A0B42C /* PBXTargetDependency */, + 1D289FBB39D9730B46C50BB58E35DEDD /* PBXTargetDependency */, ); name = MJExtension; productName = MJExtension; @@ -2468,6 +3648,24 @@ productReference = 1FFED36A657123030ABB700256D73F15 /* Masonry */; productType = "com.apple.product-type.framework"; }; + 5A2609DB0612F95A3450D2E02CA850A0 /* LSTTimer */ = { + isa = PBXNativeTarget; + buildConfigurationList = C43E72A521778768A4BFF773BB3A3E73 /* Build configuration list for PBXNativeTarget "LSTTimer" */; + buildPhases = ( + FFA880310EDC0CF0A2515E0ED18689B0 /* Headers */, + 960664E0DAFB6A287268BB843AE03C4D /* Sources */, + 58A39759A11D8C551E18D1323674BF34 /* Frameworks */, + 3E9DF1CA7088EFD9A83405BFA3BA49AB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LSTTimer; + productName = LSTTimer; + productReference = DE19C7D984CBC535E4768F5543458A1E /* LSTTimer */; + productType = "com.apple.product-type.framework"; + }; 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */ = { isa = PBXNativeTarget; buildConfigurationList = E7624967EDC883D80ED3DA81C495736B /* Build configuration list for PBXNativeTarget "LookinServer" */; @@ -2498,7 +3696,7 @@ buildRules = ( ); dependencies = ( - 5D247EA99693B7B23340BCC7FCB64DA1 /* PBXTargetDependency */, + 4B67FE65673F595E9C8A068417DA514D /* PBXTargetDependency */, ); name = MJRefresh; productName = MJRefresh; @@ -2523,13 +3721,51 @@ productReference = 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD */; productType = "com.apple.product-type.framework"; }; + 8B7D23DD98E41BAE91418E9E85F191D6 /* LSTPopView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 91696E961FC8FD5A148C3EBCD7606569 /* Build configuration list for PBXNativeTarget "LSTPopView" */; + buildPhases = ( + 84D76E7A37ACD9AD8CE52211102311F6 /* Headers */, + FC9E2C7570932C200785305216E8FD25 /* Sources */, + 6E39FC1043D864A0759387AEED07D7AC /* Frameworks */, + 2505A007E2B6A35CF29F55A3EBF40EAD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 88EAB6CB023EDFC5B53D2E9C22425E3A /* PBXTargetDependency */, + ); + name = LSTPopView; + productName = LSTPopView; + productReference = 399102B94B534EB49EE0E5512D150CA8 /* LSTPopView */; + productType = "com.apple.product-type.framework"; + }; + 8BEAFAA726C1965864B79B4B441AA513 /* JXCategoryView */ = { + isa = PBXNativeTarget; + buildConfigurationList = DB4C55F70CF73736D3687A2E620AC793 /* Build configuration list for PBXNativeTarget "JXCategoryView" */; + buildPhases = ( + 93691E22DE50657D0D08BA5D05234F57 /* Headers */, + 8F5978DBE3D91F845AFFF79059502540 /* Sources */, + 481273BD538BE69936DB3D2C8EB1E61B /* Frameworks */, + D6BF70856976374C62C62EF42CD1B449 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 840E5121538D55EE93FDAA52D266DA70 /* PBXTargetDependency */, + ); + name = JXCategoryView; + productName = JXCategoryView; + productReference = C3A46B03C308EEEB11F2A62BA5D2E8BE /* JXCategoryView */; + productType = "com.apple.product-type.framework"; + }; 94CFBA7D633ECA58DF85C327B035E6A3 /* SDWebImage-SDWebImage */ = { isa = PBXNativeTarget; - buildConfigurationList = E1B78FF12090122B97AE1A33AD172B8C /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */; + buildConfigurationList = FB913463BEC55EE719AD5BC32990DB46 /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */; buildPhases = ( - AD25BCFFC542199E6A56D85CF9FB3D3B /* Sources */, - 68405B5F41E04D755317E63849131904 /* Frameworks */, - E40003F128ACA565E0AF6D7254C64D86 /* Resources */, + A3408CB3584697A2B6167BD69AA21B2F /* Sources */, + 0DCF6770445D0657900721EC9917ECFB /* Frameworks */, + 0F4454263AF02A68EA280CFD2F6F0009 /* Resources */, ); buildRules = ( ); @@ -2542,11 +3778,11 @@ }; B26054DF1DEA11585A231AF6D1D80D5E /* MJRefresh-MJRefresh.Privacy */ = { isa = PBXNativeTarget; - buildConfigurationList = 0B91AB5AF396DEF5CC076D126E4738A7 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */; + buildConfigurationList = BA6D8ED14C9A066F526869BBA7BFA2F0 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */; buildPhases = ( - 8986B9155B9BA0DA7D02654B069F0887 /* Sources */, - 0DE7FCDD6C04EC4E1E9ECB00A0604FB7 /* Frameworks */, - 021D9F4B66A6BEEC09A45D59909CBDE6 /* Resources */, + 25D101E1E3D7EB40B6BF4B0D063D4CFB /* Sources */, + 04785C72D7E967FCB78D8F7E7635973B /* Frameworks */, + BD0C56EEEF7BFD5736E628E5DAEDE627 /* Resources */, ); buildRules = ( ); @@ -2559,11 +3795,11 @@ }; B32AF3F43989CBA171BB1FB3957A4509 /* MJExtension-MJExtension */ = { isa = PBXNativeTarget; - buildConfigurationList = 95B0FCBEC38B41A89EDFDA2284E4CF2F /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */; + buildConfigurationList = 97AAB185F08FD001A3F3B9102E506695 /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */; buildPhases = ( - D5A57C43D4D146DC812EB6C4160745DD /* Sources */, - A12778F5B92D79BB1CB466B6E7808C73 /* Frameworks */, - D4B34D2916BE13E436CD1FF18F0BC0CB /* Resources */, + 4B87B289E4FC9DF2FE22A240DAB0E3AD /* Sources */, + 6B8E82384925B650051F0C1846383E41 /* Frameworks */, + 3D2CFD627094E91914BED90AC6A972BE /* Resources */, ); buildRules = ( ); @@ -2574,6 +3810,25 @@ productReference = 43EAAD2AB7E6B407E80E95F643F93D22 /* MJExtension-MJExtension */; productType = "com.apple.product-type.bundle"; }; + C4E1020AF425614337737213AA26DBD5 /* JXPagingView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 773A22765B846DE10CADF4D2E77FE841 /* Build configuration list for PBXNativeTarget "JXPagingView" */; + buildPhases = ( + 7A48625CF583F169B2CE65398246355A /* Headers */, + 9F03A6C166C310270FB3F4AFE9D7573D /* Sources */, + AE750D3363286EC4504AB9516776E757 /* Frameworks */, + 5C89912961D7B3B99680563233DBEA04 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CFAD2B6D6431A495BD1CA533779A67B0 /* PBXTargetDependency */, + ); + name = JXPagingView; + productName = JXPagingView; + productReference = 2F4A1CCB21DB7EA5A2ACEB11E374FBCA /* JXPagingView */; + productType = "com.apple.product-type.framework"; + }; D9B2DB11933DB55A80A118934E6680AB /* Pods-CustomKeyboard */ = { isa = PBXNativeTarget; buildConfigurationList = B1224CED7ED3E4B356E8F429D6C62F7E /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */; @@ -2586,17 +3841,34 @@ buildRules = ( ); dependencies = ( - 33AF3D0CC306E3DD56CCD4562DC58ABA /* PBXTargetDependency */, - 6D842140C98E51FF8C3EC4AC689EC108 /* PBXTargetDependency */, - AEC4F62BB393A387D98BB39E07E54A5E /* PBXTargetDependency */, - BD5EEFF9A8B5208454EE5C08E29DEC6F /* PBXTargetDependency */, - 32CDD4F647C6AFB9D8EF74E8A88163CD /* PBXTargetDependency */, + 516A94BC5E451EEB51F643D23D85E82C /* PBXTargetDependency */, + B5024FC019BD8A112152FB369A67EAFA /* PBXTargetDependency */, + 285B72F62A1DE2E9A5E2E4D45F15828C /* PBXTargetDependency */, + 3B6CA3026290428D105D8C0E16BC28C0 /* PBXTargetDependency */, + 418F39BD767B7F3EBD3B862DC77F178A /* PBXTargetDependency */, ); name = "Pods-CustomKeyboard"; productName = Pods_CustomKeyboard; productReference = 0B4AAC15A428CDC2A62AF9CC27BEA609 /* Pods-CustomKeyboard */; productType = "com.apple.product-type.framework"; }; + E79E29F55A2453370D27112480FCF6A2 /* JXCategoryView-JXCategoryView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 931B4A41B3614242C4D8813983B29AE7 /* Build configuration list for PBXNativeTarget "JXCategoryView-JXCategoryView" */; + buildPhases = ( + E7FC7BB552A8FE956E421E3474419D5D /* Sources */, + F4019BF639D68EFAB596EA1BD86C37CB /* Frameworks */, + 1461F55480D564BB754551A6E8B059D2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "JXCategoryView-JXCategoryView"; + productName = JXCategoryView; + productReference = BB4F011171FCB76B1AEBE390F843E930 /* JXCategoryView-JXCategoryView */; + productType = "com.apple.product-type.bundle"; + }; F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */ = { isa = PBXNativeTarget; buildConfigurationList = 1CF7CA11A791652D6975B2EDE2FC6719 /* Build configuration list for PBXNativeTarget "DZNEmptyDataSet" */; @@ -2635,14 +3907,23 @@ mainGroup = CF1408CF629C7361332E53B88F7BD30C; minimizedProjectReferenceProxies = 0; preferredProjectObjectVersion = 77; - productRefGroup = 1C8A19406FF58E9BA6BC427CA02E9857 /* Products */; + productRefGroup = D3828787C1DCC6E76B71C947B6C876AE /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */, 4A68CFD979D413A619DF631BB121D98F /* Bugly */, F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */, + 4A8E8992707D01510894596DB9BCCA00 /* FLAnimatedImage */, + 31DCABABCA873FBA7A92FEB47D71ED8E /* HWPanModal */, + 8BEAFAA726C1965864B79B4B441AA513 /* JXCategoryView */, + E79E29F55A2453370D27112480FCF6A2 /* JXCategoryView-JXCategoryView */, + C4E1020AF425614337737213AA26DBD5 /* JXPagingView */, + 16704C6B67439DA959DB043702C75A7A /* JXPagingView-JXPagerView */, 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */, + 8B7D23DD98E41BAE91418E9E85F191D6 /* LSTPopView */, + 5A2609DB0612F95A3450D2E02CA850A0 /* LSTTimer */, + 4AA4C7BB776C55F3421BA137B643DD64 /* LYEmptyView */, 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */, 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */, 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */, @@ -2658,11 +3939,19 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 021D9F4B66A6BEEC09A45D59909CBDE6 /* Resources */ = { + 0F4454263AF02A68EA280CFD2F6F0009 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - BBD85F9E0E25710317253841091C391F /* PrivacyInfo.xcprivacy in Resources */, + 7DFACBAC8324FE3F177FA465E0006A9C /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1461F55480D564BB754551A6E8B059D2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7D4B5D7A593F4436B57347FD2A5072B4 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2674,6 +3963,49 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2505A007E2B6A35CF29F55A3EBF40EAD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 27B1683E18D5081CF470BC9A233C7D28 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2B9BFC6488F4ABCC9916C35510BB7D7C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 311EF2CB460B544059B769919A899ECA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D2CFD627094E91914BED90AC6A972BE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B2E706AF15CBC9BBDA6B180AA008345E /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E9DF1CA7088EFD9A83405BFA3BA49AB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 44B3C0D7DDF289331B7732E9D87126DB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -2691,6 +4023,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5C89912961D7B3B99680563233DBEA04 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 91AFF41167C616A131F2E24563B8DDD8 /* JXPagingView-JXPagerView in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 860DF70163CE0C8308216A41597A40DF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 27CE2AFFB3219A5D3717045970929C80 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8DF763B35C7183D33FE173339E261549 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -2705,18 +4053,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - B3CE18BE6ADF72F2E31CF5989ACEA7C5 /* Resources */ = { + 9EF83CC96C715675FF7A15F96027E83F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - D4B34D2916BE13E436CD1FF18F0BC0CB /* Resources */ = { + BD0C56EEEF7BFD5736E628E5DAEDE627 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2FEE980BEE23B8E0C7EBB70445EC8C9A /* PrivacyInfo.xcprivacy in Resources */, + 1F2863645F3DEAC57B592AFFB45D5E77 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2727,11 +4075,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E40003F128ACA565E0AF6D7254C64D86 /* Resources */ = { + D6BF70856976374C62C62EF42CD1B449 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - EBC9AA5D4A55F79BB5CBF6CC92719FAF /* PrivacyInfo.xcprivacy in Resources */, + A1C02A0C13BE4A139BC38BBE20217FA2 /* JXCategoryView-JXCategoryView in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2866,15 +4214,52 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 87D36E846DA0820C15C53178D809C27F /* Sources */ = { + 25D101E1E3D7EB40B6BF4B0D063D4CFB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9DE398BDF0CD7F38181F2F751AC18CB2 /* Pods-keyBoard-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8986B9155B9BA0DA7D02654B069F0887 /* Sources */ = { + 3EA749E8A97310551F543948A8C92475 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6E4DE8085E69AD1DDB49B059DCE286DB /* HWBackgroundConfig.m in Sources */, + 9D859B99561C389C0F494428F66F1871 /* HWDimmedView.m in Sources */, + A760FF1452F08B787F0997D91F4A2C98 /* HWPageSheetPresentingAnimation.m in Sources */, + FC32143CA2A916F032F2B569313315AA /* HWPanContainerView.m in Sources */, + F47EBDD360E642A0499A767BC7C17B4B /* HWPanIndicatorView.m in Sources */, + E1B4145C5201DB66B65520B36849067C /* HWPanModal-dummy.m in Sources */, + 80EBFDD01E84CE4E8AE5BAE9CB3C7C1D /* HWPanModalAnimator.m in Sources */, + 73B19D03C7B7DF1C944544165F742D82 /* HWPanModalContainerView.m in Sources */, + 79534562F85AA71041043B395DE14AD0 /* HWPanModalContentView.m in Sources */, + 381E0DBE152CA0D9C66310CB77A20A83 /* HWPanModalInteractiveAnimator.m in Sources */, + FEE3D901B4A4638F9E00935144E982B3 /* HWPanModalPresentableHandler.m in Sources */, + 541AD3B0F5EA216EE730ECC6E8B84C31 /* HWPanModalPresentationAnimator.m in Sources */, + 1D3DCD05B685A7CAF291C25D922B1831 /* HWPanModalPresentationController.m in Sources */, + 3BD85ED8999015326D93D8EEADCCF910 /* HWPanModalPresentationDelegate.m in Sources */, + E7520DAA65004368C61453B8A2740295 /* HWPanModalShadow.m in Sources */, + 0005259AEE76604A26E43EA994475B68 /* HWShoppingCartPresentingAnimation.m in Sources */, + F6A34F74BE7FE816114D7F3902296AF2 /* HWVisualEffectView.m in Sources */, + 4ACC15DF96D179E48E4276AE3C540C7C /* KeyValueObserver.m in Sources */, + 728107C8D8479AADE986F4EC23233DC3 /* UIScrollView+Helper.m in Sources */, + 7053A9EB6335BEAC9EFDF2D5320E6E2A /* UIView+HW_Frame.m in Sources */, + 22F19B23471EE7840581A348EB735BD1 /* UIViewController+LayoutHelper.m in Sources */, + F3DA1005917E252B306712DAAA287FB0 /* UIViewController+PanModalDefault.m in Sources */, + BD2F6B06ADB5136DA881D1B918367125 /* UIViewController+PanModalPresenter.m in Sources */, + B01F27CEAE1971DEC56A8811FE669EB6 /* UIViewController+Presentation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B87B289E4FC9DF2FE22A240DAB0E3AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5E3F655370D8F2DAABC53D59D069B3A1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -2953,6 +4338,76 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8F5978DBE3D91F845AFFF79059502540 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9E7FD4501C2EF7FBF3379D21E46DB07B /* JXCategoryBaseCell.m in Sources */, + 940CD731A431894B0EE4E3283E6F352F /* JXCategoryBaseCellModel.m in Sources */, + 620A0FFFDE5AEF215E28135566106BA4 /* JXCategoryBaseView.m in Sources */, + BE7F6E08A9BDA2EF6FA625EB5CD685EC /* JXCategoryCollectionView.m in Sources */, + E038F02D08E33A673A360ED34648A027 /* JXCategoryDotCell.m in Sources */, + D31558927DE3F62D1BB1FC416E6F237D /* JXCategoryDotCellModel.m in Sources */, + 20FBBC12322412237D48D3695D98E043 /* JXCategoryDotView.m in Sources */, + EC9B8D81AEAF11E16149869246F7D4C1 /* JXCategoryFactory.m in Sources */, + F847E3C26E5AC43CD73364AD3DF49AFE /* JXCategoryImageCell.m in Sources */, + CE2AF36EBB17CDA2652CBADD4A7ABF82 /* JXCategoryImageCellModel.m in Sources */, + 266352AA446DAE8C9502E83810C174D9 /* JXCategoryImageView.m in Sources */, + 6630C0B541E50903F9AD81FD847CFE7A /* JXCategoryIndicatorBackgroundView.m in Sources */, + 6BF5DB46D42D8B9D536C870EC77BF4A3 /* JXCategoryIndicatorBallView.m in Sources */, + 1C0FA6017CAD67C1A80FFA70024FC6FD /* JXCategoryIndicatorCell.m in Sources */, + 2EDA227454079ED3F6371BF34AFD4735 /* JXCategoryIndicatorCellModel.m in Sources */, + 579DDC4FE78455D88E0350C3268D96C4 /* JXCategoryIndicatorComponentView.m in Sources */, + C922BFFF717515E5878910DF4078CE1E /* JXCategoryIndicatorDotLineView.m in Sources */, + D93EA925FC24665584B3653514A56706 /* JXCategoryIndicatorImageView.m in Sources */, + 3B62431BEF820E7FC779F344AB2A1D17 /* JXCategoryIndicatorLineView.m in Sources */, + 8128D2BD3AC890F75E7AD243AA104C13 /* JXCategoryIndicatorParamsModel.m in Sources */, + 0C312924F0A07471A1D04AD15D32BF3A /* JXCategoryIndicatorRainbowLineView.m in Sources */, + D08901EA319887BE6D694F8333BE8D1F /* JXCategoryIndicatorTriangleView.m in Sources */, + AF17C7BD3344504E243E234004B4593E /* JXCategoryIndicatorView.m in Sources */, + F43396B5CB23638E5509B3ED61AE6192 /* JXCategoryListContainerRTLCell.m in Sources */, + D0E37358C3DCF2A8A572C4F38BB0569B /* JXCategoryListContainerView.m in Sources */, + C22BFD04EAB76981E7F112D57A1F5E79 /* JXCategoryNumberCell.m in Sources */, + E4B688B8A0D07AFB883A52250CA874A1 /* JXCategoryNumberCellModel.m in Sources */, + 020FEDA58170EE1ABDF9E268D373CF4F /* JXCategoryNumberView.m in Sources */, + 79701CF51014A7C02D810F9DAEFE6D79 /* JXCategoryTitleCell.m in Sources */, + 4ECE7F80A917130DE4045E25D741EAF9 /* JXCategoryTitleCellModel.m in Sources */, + 8FF4E9A492CA258F45C0BC51F6F69650 /* JXCategoryTitleImageCell.m in Sources */, + AD395F6BD7F53258A431E9479D07C6AF /* JXCategoryTitleImageCellModel.m in Sources */, + 91BEBD471C408E6C72763AFB6926242B /* JXCategoryTitleImageView.m in Sources */, + 93E2C24501FAE3C3B886B9879786EF22 /* JXCategoryTitleVerticalZoomCell.m in Sources */, + E42D6EF120A5C17DA2F6FD6473CE7E7A /* JXCategoryTitleVerticalZoomCellModel.m in Sources */, + EEF0BF7E53148EB20BED242061BDC5ED /* JXCategoryTitleVerticalZoomView.m in Sources */, + A325C7E5098EB5641EF49D279EA9EF03 /* JXCategoryTitleView.m in Sources */, + 8B990235A0006E1F9C1E6F68AD81F77C /* JXCategoryView-dummy.m in Sources */, + 2395CE03CE80FC5F9A7F61C48270618B /* JXCategoryViewAnimator.m in Sources */, + 2175B894008D948C762468307BA677B8 /* RTLManager.m in Sources */, + 96C1D55B3436C158B4CBB4E3D0AE53EE /* UIColor+JXAdd.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 960664E0DAFB6A287268BB843AE03C4D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 21232E67D630EBF8EA4CB3322B359F0D /* LSTTimer.m in Sources */, + 9C623DECA454522DB641AA29C86F6387 /* LSTTimer-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9F03A6C166C310270FB3F4AFE9D7573D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E0DB14976CA6F6E604FD5E4EDF3378E7 /* JXPagerListContainerView.m in Sources */, + 6C76DB1B99B98C951F687DE80FE6F463 /* JXPagerListRefreshView.m in Sources */, + 0D6EFFD314E70C1E547970D8CEF11131 /* JXPagerMainTableView.m in Sources */, + 6204F3E4E75772BB6CAB13CD53D9D93E /* JXPagerSmoothView.m in Sources */, + EE101918DFCDC1D6728BF910DB5AF29A /* JXPagerView.m in Sources */, + 05EEA40D460AB9A5A6E8D33AAAEF801E /* JXPagingView-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; A29E3C9E62E3E86A20CAE1E7632313FC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2962,7 +4417,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - AD25BCFFC542199E6A56D85CF9FB3D3B /* Sources */ = { + A3408CB3584697A2B6167BD69AA21B2F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -2992,13 +4447,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - D5A57C43D4D146DC812EB6C4160745DD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; DA0B6A6F9B3EDF226BF081DAC7E777E7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3049,6 +4497,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E3AA8B53287F6ACBF2F2800146C6ECD0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 58852265A6A355CDF8D25BCD71F54F3D /* Pods-keyBoard-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7FC7BB552A8FE956E421E3474419D5D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8A558A3C629ABA805E9D912FCCBCD2F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7D1C6E10B8E0F98E19048BB416A39A0D /* LYEmptyBaseView.m in Sources */, + 2210A1E405AB21104E7AF86D05C8AD39 /* LYEmptyView.m in Sources */, + A59F64C74CB407EBC0385F026FC7234A /* LYEmptyView-dummy.m in Sources */, + 0E97928FD3B4476EDC015E83A8E2CAA3 /* UIView+Empty.m in Sources */, + 743BBA00940EF6877AE1D5014755D0D6 /* UIView+LYExtension.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; E8CCE3C7763C30E81A067AE9AC1B8915 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3057,117 +4532,324 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FC9E2C7570932C200785305216E8FD25 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3111CEA93C868CA68CBD351C934FEB80 /* LSTPopView.m in Sources */, + A0B7A3B941134AA95A20F5A85165CC72 /* LSTPopView-dummy.m in Sources */, + BE4F0DF600FBF07E812D262B293CF76C /* UIView+LSTPV.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FCCB6EDD1337F2C5115636BA7E258EDF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AD01931D200C49153984E27CBCEFE9D1 /* FLAnimatedImage.m in Sources */, + C16483526F6C6287240A75EDCB7E2F2F /* FLAnimatedImage-dummy.m in Sources */, + FD3AF10F8723DABEE406D25592B5F562 /* FLAnimatedImageView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 071F326A1012E3F537E82D4600D6099B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Bugly; - target = 4A68CFD979D413A619DF631BB121D98F /* Bugly */; - targetProxy = C85024A705A5032AA3907BF36C187CEA /* PBXContainerItemProxy */; - }; - 09B11A1954CF8173776EC7F7B6571224 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SDWebImage; - target = 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */; - targetProxy = F295793354A8BF65125212DAE1C81DF5 /* PBXContainerItemProxy */; - }; - 32CDD4F647C6AFB9D8EF74E8A88163CD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Masonry; - target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; - targetProxy = 551922F754B651AFCAAB56605458A1A4 /* PBXContainerItemProxy */; - }; - 33AF3D0CC306E3DD56CCD4562DC58ABA /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = AFNetworking; - target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; - targetProxy = F34B1D580EA71604D4CC7C4C5807E366 /* PBXContainerItemProxy */; - }; - 3CC71AA09CD8D91F7CAC51C8C0C3D8A8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = DZNEmptyDataSet; - target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */; - targetProxy = D8B3BBDA3C526A079F33D20BFE81FDA0 /* PBXContainerItemProxy */; - }; - 4CEDC3503EBC64FA8AD4BB751A1257E2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MJRefresh; - target = 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */; - targetProxy = 6610EBAD645971628D6E656F2A7FB551 /* PBXContainerItemProxy */; - }; - 575EFC27A8B3BE6F6EF85229FA04A8F6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MBProgressHUD; - target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; - targetProxy = F9524D7CD6D352CCF289944EBCA3B3FB /* PBXContainerItemProxy */; - }; - 578B4FEE3B5BBEBE31FFA9C174A0B42C /* PBXTargetDependency */ = { + 1D289FBB39D9730B46C50BB58E35DEDD /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "MJExtension-MJExtension"; target = B32AF3F43989CBA171BB1FB3957A4509 /* MJExtension-MJExtension */; - targetProxy = F4000FEC7CADA56B75E5CC31E64EC891 /* PBXContainerItemProxy */; + targetProxy = C30FB24BD734A3779E20934DB3D4D9C8 /* PBXContainerItemProxy */; }; - 5D247EA99693B7B23340BCC7FCB64DA1 /* PBXTargetDependency */ = { + 22268E07F0FDFC08F0EE9D82FF083DD6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "MJRefresh-MJRefresh.Privacy"; - target = B26054DF1DEA11585A231AF6D1D80D5E /* MJRefresh-MJRefresh.Privacy */; - targetProxy = BBBA8C59A31486B3AE2F16C6A4AAAB66 /* PBXContainerItemProxy */; + name = MJRefresh; + target = 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */; + targetProxy = B0121AEB150BEE5708989CCC69A51E6E /* PBXContainerItemProxy */; }; - 69F880D20E49FF278D9D99F0FC359C80 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = AFNetworking; - target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; - targetProxy = 17AC289E8A24B84DB147B7977008DB53 /* PBXContainerItemProxy */; - }; - 6D842140C98E51FF8C3EC4AC689EC108 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = DZNEmptyDataSet; - target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */; - targetProxy = B0F47C29852712CF2F2C1E658ECD1809 /* PBXContainerItemProxy */; - }; - 8343E87E690EAE8ED5D426D9B97081C7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MJExtension; - target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; - targetProxy = 17A6BBBD906DDCB7334A02B16B07B4DB /* PBXContainerItemProxy */; - }; - AEC4F62BB393A387D98BB39E07E54A5E /* PBXTargetDependency */ = { + 285B72F62A1DE2E9A5E2E4D45F15828C /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = MBProgressHUD; target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; - targetProxy = A311284721E0C3165FAA791C3EE6961E /* PBXContainerItemProxy */; + targetProxy = 70663BD3E4659CFF0C7EF0B56DBC9C78 /* PBXContainerItemProxy */; }; - BD5EEFF9A8B5208454EE5C08E29DEC6F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MJExtension; - target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; - targetProxy = AD74DB90134D3DB33FAC2C873C0764E9 /* PBXContainerItemProxy */; - }; - D4796534CC93D6F34DDBB3E449125A23 /* PBXTargetDependency */ = { + 28BE8BB7BD4C9C6AB673350A1570FA84 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = LookinServer; target = 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */; - targetProxy = 7D22DC5F48A287865357EE41131C6668 /* PBXContainerItemProxy */; + targetProxy = 71C3BF8323A3B89C42C815297FB1B486 /* PBXContainerItemProxy */; }; - EE61A46DF554B3E5C29DB10DCBB3618A /* PBXTargetDependency */ = { + 3067995C8EDFEF1A63CA85F6D091AD0B /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "SDWebImage-SDWebImage"; - target = 94CFBA7D633ECA58DF85C327B035E6A3 /* SDWebImage-SDWebImage */; - targetProxy = 8C2E663FC9840B2B7BABEF079AD58862 /* PBXContainerItemProxy */; + name = Bugly; + target = 4A68CFD979D413A619DF631BB121D98F /* Bugly */; + targetProxy = 02FAAF39D5DC83544D9E66B036B176EA /* PBXContainerItemProxy */; }; - EF01B3D5C4798C26DB6A90866EE03225 /* PBXTargetDependency */ = { + 3B6CA3026290428D105D8C0E16BC28C0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MJExtension; + target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; + targetProxy = 492374464B2EEB82B866DBC203FB6CF9 /* PBXContainerItemProxy */; + }; + 418F39BD767B7F3EBD3B862DC77F178A /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Masonry; target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; - targetProxy = 1CC061C6A0CA52E13056E44543CDE4BD /* PBXContainerItemProxy */; + targetProxy = F24DDDDEE9FC26F48E2EA84062015B72 /* PBXContainerItemProxy */; + }; + 4B67FE65673F595E9C8A068417DA514D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "MJRefresh-MJRefresh.Privacy"; + target = B26054DF1DEA11585A231AF6D1D80D5E /* MJRefresh-MJRefresh.Privacy */; + targetProxy = A2D6E99D61C37E2D571D73F75FCFE0B4 /* PBXContainerItemProxy */; + }; + 516A94BC5E451EEB51F643D23D85E82C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AFNetworking; + target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; + targetProxy = C548A30C8E9A6CD52D6655421F9E80B2 /* PBXContainerItemProxy */; + }; + 7D1F8A3DE88EF01CF89EF4750D0835BC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = LSTTimer; + target = 5A2609DB0612F95A3450D2E02CA850A0 /* LSTTimer */; + targetProxy = A3A1467D883FED3ABCAC49113A737098 /* PBXContainerItemProxy */; + }; + 840E5121538D55EE93FDAA52D266DA70 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "JXCategoryView-JXCategoryView"; + target = E79E29F55A2453370D27112480FCF6A2 /* JXCategoryView-JXCategoryView */; + targetProxy = BAEC79AAEBBDF2BA3087612B7E05FD8E /* PBXContainerItemProxy */; + }; + 88EAB6CB023EDFC5B53D2E9C22425E3A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = LSTTimer; + target = 5A2609DB0612F95A3450D2E02CA850A0 /* LSTTimer */; + targetProxy = 9D62F9D7E8B03E6D53909480991C8AEA /* PBXContainerItemProxy */; + }; + 90059A9ED4F8080EA23A70C0EB5FE47E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = LSTPopView; + target = 8B7D23DD98E41BAE91418E9E85F191D6 /* LSTPopView */; + targetProxy = D9630B9E5DE60DCADFA9106CF013D735 /* PBXContainerItemProxy */; + }; + 9403290AE1B7249ADE1ED8950739EE94 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MJExtension; + target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */; + targetProxy = 4F853CA6F77CC1808AF5BAF0CCAB86C0 /* PBXContainerItemProxy */; + }; + ABAA3F7B666DBB2B8C2E114433F7A89D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Masonry; + target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; + targetProxy = F518DC696627DF925BE789501947DBC7 /* PBXContainerItemProxy */; + }; + B5024FC019BD8A112152FB369A67EAFA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = DZNEmptyDataSet; + target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */; + targetProxy = F02666E823668E7F6E705B610204BBE2 /* PBXContainerItemProxy */; + }; + BB84628766B4F66DF4DC34732901F40E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = JXPagingView; + target = C4E1020AF425614337737213AA26DBD5 /* JXPagingView */; + targetProxy = CEFF12BAC2DF7A2FB2A16265805F8779 /* PBXContainerItemProxy */; + }; + C0EEAAE6B64FC5B6DFCE16644E06B2CA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = HWPanModal; + target = 31DCABABCA873FBA7A92FEB47D71ED8E /* HWPanModal */; + targetProxy = DB09B1B3C4EF493AB0763F0795077728 /* PBXContainerItemProxy */; + }; + CE8F85B0B6965EE090F12CB8B384E2A3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = JXCategoryView; + target = 8BEAFAA726C1965864B79B4B441AA513 /* JXCategoryView */; + targetProxy = 0AC2AD8EAFB742F27A3D34C64E40AFC6 /* PBXContainerItemProxy */; + }; + CFAD2B6D6431A495BD1CA533779A67B0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "JXPagingView-JXPagerView"; + target = 16704C6B67439DA959DB043702C75A7A /* JXPagingView-JXPagerView */; + targetProxy = 4B52CF33FA25735578A3E44A4CD0C61E /* PBXContainerItemProxy */; + }; + D2B74321DDAF41730531D5172D454257 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SDWebImage; + target = 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */; + targetProxy = 6C532ADBCD9DB30208C8082362062867 /* PBXContainerItemProxy */; + }; + D37914A752321FFCFF48251614F3D1B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "SDWebImage-SDWebImage"; + target = 94CFBA7D633ECA58DF85C327B035E6A3 /* SDWebImage-SDWebImage */; + targetProxy = 6B502CE29B8265D64E66B68DA64E8BAF /* PBXContainerItemProxy */; + }; + D431884F2F2835EF4FDB44219ADAA88B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AFNetworking; + target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */; + targetProxy = 586A5F02457EAA9AECE8CFCC7EDC4A36 /* PBXContainerItemProxy */; + }; + D6DB70831F359F7235B8C97A50300DDF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FLAnimatedImage; + target = 4A8E8992707D01510894596DB9BCCA00 /* FLAnimatedImage */; + targetProxy = FD339A2CF804D4CD1FADE6633BE4DB45 /* PBXContainerItemProxy */; + }; + E7B53C78EB3FA9751B3C978B6CB97980 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = DZNEmptyDataSet; + target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */; + targetProxy = D031B103E98AAB5CEC13491B24F6A82E /* PBXContainerItemProxy */; + }; + F750881392263D81A5BB4E131005A44E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = LYEmptyView; + target = 4AA4C7BB776C55F3421BA137B643DD64 /* LYEmptyView */; + targetProxy = 080FDB8CF401316D3CCD779F38297489 /* PBXContainerItemProxy */; + }; + FE3D9C468529CF310D88B6383BEFBFDD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MBProgressHUD; + target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; + targetProxy = 6C0462143C24DADCF6D346CFCCF1F2DF /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 024C9A3B861ABA20A2346A6A466EB015 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F68616E55705601CBE5D9437AD83B340 /* JXCategoryView.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/JXCategoryView"; + IBSC_MODULE = JXCategoryView; + INFOPLIST_FILE = "Target Support Files/JXCategoryView/ResourceBundle-JXCategoryView-JXCategoryView-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = JXCategoryView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 083F4B327F32BA42082C93DA3678A905 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 35BFA337F4E1FDE67C773A82CCDFD6DA /* Pods-keyBoard.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0BAEB6F6833BF585A150B8AD74FDBC03 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6CE98E2FC8B92A0E98F20755C88122A4 /* LSTTimer.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/LSTTimer/LSTTimer-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LSTTimer/LSTTimer-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/LSTTimer/LSTTimer.modulemap"; + PRODUCT_MODULE_NAME = LSTTimer; + PRODUCT_NAME = LSTTimer; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0FF9630F4FA55B5D0AE7A67F275961B4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A324C5885C8FB2DC65900A0EE79A0E45 /* MJRefresh.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJRefresh"; + IBSC_MODULE = MJRefresh; + INFOPLIST_FILE = "Target Support Files/MJRefresh/ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_NAME = MJRefresh.Privacy; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 124345EDBC5F34B7AF5C60B83C477235 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 81F7F63875295940D9A950DB7D2EBDE7 /* SDWebImage.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SDWebImage"; + IBSC_MODULE = SDWebImage; + INFOPLIST_FILE = "Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = SDWebImage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; 1A69165A21A7A1CC42A38CF8ADE98215 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2DAD93B79D27664FE05E862A2C992A45 /* LookinServer.release.xcconfig */; + baseConfigurationReference = 438B056E0DAE53D40DB4894FF36879AF /* LookinServer.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3242,9 +4924,43 @@ }; name = Release; }; + 26A0DE2A2C5EEB5AB1D9315AE03103A7 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 954035BEFF37A926FB7C25E5508CD25D /* MJExtension.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJExtension"; + IBSC_MODULE = MJExtension; + INFOPLIST_FILE = "Target Support Files/MJExtension/ResourceBundle-MJExtension-MJExtension-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_NAME = MJExtension; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 2B066301F5B1D4BFFD95FEB2D9535180 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D3FD4542A2D174FC95524833AB672073 /* JXPagingView.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/JXPagingView"; + IBSC_MODULE = JXPagingView; + INFOPLIST_FILE = "Target Support Files/JXPagingView/ResourceBundle-JXPagerView-JXPagingView-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = JXPagerView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; 2D1085CA7BD144CABF012FC10C6C9120 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B9AC91A4E70DD8F8592A5811E8617578 /* Masonry.debug.xcconfig */; + baseConfigurationReference = A603B071469D044FB92322560F131681 /* Masonry.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3281,7 +4997,7 @@ }; 35044A57510DB3F4E442A9C16E980E4A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 61A50E7751555885AEB4247687F5DF05 /* DZNEmptyDataSet.debug.xcconfig */; + baseConfigurationReference = 48E1ED2BAC3C5C1B077AAB67F3325D4E /* DZNEmptyDataSet.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3316,9 +5032,46 @@ }; name = Debug; }; - 427CF48FABE82C6FC8208160FDF4A9CE /* Debug */ = { + 3565929B4632DC589BC25FDD7CE29119 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 57BCCC946B3042A20D0C8F15D69FF943 /* MJExtension.debug.xcconfig */; + baseConfigurationReference = 5048CCD1406058B50480C383463B3C39 /* LYEmptyView.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/LYEmptyView/LYEmptyView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LYEmptyView/LYEmptyView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/LYEmptyView/LYEmptyView.modulemap"; + PRODUCT_MODULE_NAME = LYEmptyView; + PRODUCT_NAME = LYEmptyView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 40403C5D9FB335BD8C765DF3FE61B9E5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7B582290DB93C466A4DA695035B6DA2E /* MJExtension.release.xcconfig */; buildSettings = { CODE_SIGNING_ALLOWED = NO; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJExtension"; @@ -3331,11 +5084,28 @@ TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = bundle; }; - name = Debug; + name = Release; + }; + 44E4190BC3FB54D917C88AC4FC84B935 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DF80C06856CA889ADB8807594055C7DF /* JXCategoryView.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/JXCategoryView"; + IBSC_MODULE = JXCategoryView; + INFOPLIST_FILE = "Target Support Files/JXCategoryView/ResourceBundle-JXCategoryView-JXCategoryView-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = JXCategoryView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; }; 49CEA33268972C89BF290FCBF8F9DFC0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 52832E51BDED300B58102A301664AD5A /* DZNEmptyDataSet.release.xcconfig */; + baseConfigurationReference = 5CB726B6B5C83EAABA9AC89E76D45643 /* DZNEmptyDataSet.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3371,26 +5141,9 @@ }; name = Release; }; - 50BA0438712A00B9F9ECCE17AD68D287 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5998234B9DD3C83BCD1DE88EDDEA5DF6 /* SDWebImage.debug.xcconfig */; - buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SDWebImage"; - IBSC_MODULE = SDWebImage; - INFOPLIST_FILE = "Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - PRODUCT_NAME = SDWebImage; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; 51753BD6FE635BB9421BCA4C05F63C6A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 45EDC4788D38048F75B7F3CD0BEF1783 /* MJRefresh.release.xcconfig */; + baseConfigurationReference = A324C5885C8FB2DC65900A0EE79A0E45 /* MJRefresh.release.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3427,26 +5180,85 @@ }; name = Release; }; - 532B03D3A70665C5D6CA2E785045C97B /* Release */ = { + 571314BC8A84B1CED724D0AFB1CED826 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3E2A55F2F78E11DEDCF2FA119B3E1912 /* MJExtension.release.xcconfig */; + baseConfigurationReference = DF80C06856CA889ADB8807594055C7DF /* JXCategoryView.release.xcconfig */; buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJExtension"; - IBSC_MODULE = MJExtension; - INFOPLIST_FILE = "Target Support Files/MJExtension/ResourceBundle-MJExtension-MJExtension-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - PRODUCT_NAME = MJExtension; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/JXCategoryView/JXCategoryView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/JXCategoryView/JXCategoryView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/JXCategoryView/JXCategoryView.modulemap"; + PRODUCT_MODULE_NAME = JXCategoryView; + PRODUCT_NAME = JXCategoryView; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 5FA85455B8129B5351F63A65BE01DE60 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E00B4B67B95B1D4B1001EF45F23EF0C4 /* LYEmptyView.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/LYEmptyView/LYEmptyView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LYEmptyView/LYEmptyView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/LYEmptyView/LYEmptyView.modulemap"; + PRODUCT_MODULE_NAME = LYEmptyView; + PRODUCT_NAME = LYEmptyView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; 614F7847ADAD2F1EEC9E48FAEC955108 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D2BBA8DCCC9E2658211368C22BE1B033 /* MJRefresh.debug.xcconfig */; + baseConfigurationReference = 7895C7C58218B5F79C76FA1B5A55E669 /* MJRefresh.debug.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3484,7 +5296,7 @@ }; 618AB008538F74AAF983C04297207BB6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9641B4F4D8DDE2072CB32BF4C9C2882A /* LookinServer.debug.xcconfig */; + baseConfigurationReference = 7376537428F41B571A3D20FF9175747F /* LookinServer.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3518,6 +5330,99 @@ }; name = Debug; }; + 63708B35D08B13BC40AB51386020974A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CA665BB1B8AEA701C3C1A72312BFE105 /* HWPanModal.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/HWPanModal/HWPanModal-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/HWPanModal/HWPanModal-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/HWPanModal/HWPanModal.modulemap"; + PRODUCT_MODULE_NAME = HWPanModal; + PRODUCT_NAME = HWPanModal; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 64F655C37D34116A6844DB785A318D16 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 39D7BCC784A30383722D127896FE591E /* JXPagingView.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/JXPagingView"; + IBSC_MODULE = JXPagingView; + INFOPLIST_FILE = "Target Support Files/JXPagingView/ResourceBundle-JXPagerView-JXPagingView-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = JXPagerView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 67BAB382C3420CD62CB414CAA4D8A5B1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D5BBA19EC013D7414BE28B29DCA7518D /* FLAnimatedImage.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/FLAnimatedImage/FLAnimatedImage-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/FLAnimatedImage/FLAnimatedImage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/FLAnimatedImage/FLAnimatedImage.modulemap"; + PRODUCT_MODULE_NAME = FLAnimatedImage; + PRODUCT_NAME = FLAnimatedImage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; 7BB5AE2225500DE9658B6277FED45BCD /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.debug.xcconfig */; @@ -3557,6 +5462,44 @@ }; name = Debug; }; + 869A260EDB31DBC8F1FD513756A77A93 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 39D7BCC784A30383722D127896FE591E /* JXPagingView.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/JXPagingView/JXPagingView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/JXPagingView/JXPagingView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/JXPagingView/JXPagingView.modulemap"; + PRODUCT_MODULE_NAME = JXPagingView; + PRODUCT_NAME = JXPagingView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3623,20 +5566,120 @@ }; name = Debug; }; - 9C1EE0C94CDE25779693BCA7261B5989 /* Release */ = { + 8EAC2F834160F0D756B3363236E0940A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C31E11F6B40D55EB650013FAC1B59C0 /* SDWebImage.release.xcconfig */; + baseConfigurationReference = D3FD4542A2D174FC95524833AB672073 /* JXPagingView.release.xcconfig */; buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SDWebImage"; - IBSC_MODULE = SDWebImage; - INFOPLIST_FILE = "Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - PRODUCT_NAME = SDWebImage; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/JXPagingView/JXPagingView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/JXPagingView/JXPagingView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/JXPagingView/JXPagingView.modulemap"; + PRODUCT_MODULE_NAME = JXPagingView; + PRODUCT_NAME = JXPagingView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 8F481C1C1CF7C89F42A9EFE335DEA2BC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6BD04BB450562622E215B33554778CC3 /* LSTPopView.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/LSTPopView/LSTPopView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LSTPopView/LSTPopView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/LSTPopView/LSTPopView.modulemap"; + PRODUCT_MODULE_NAME = LSTPopView; + PRODUCT_NAME = LSTPopView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 9B8AB2F5A292514588D0A1ECFA2D15C4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6E8FF241173D596A21D4D4B7D86A810 /* Pods-keyBoard.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; @@ -3704,7 +5747,7 @@ }; 9E9FB1E032B56896F9380263D45A0F9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3E2A55F2F78E11DEDCF2FA119B3E1912 /* MJExtension.release.xcconfig */; + baseConfigurationReference = 7B582290DB93C466A4DA695035B6DA2E /* MJExtension.release.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3743,7 +5786,7 @@ }; 9F519E5162C0E51D10B7E999E2FD0125 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C31E11F6B40D55EB650013FAC1B59C0 /* SDWebImage.release.xcconfig */; + baseConfigurationReference = 81F7F63875295940D9A950DB7D2EBDE7 /* SDWebImage.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3779,9 +5822,46 @@ }; name = Release; }; + A04019026E1B09655264B132BF5345A4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F68616E55705601CBE5D9437AD83B340 /* JXCategoryView.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/JXCategoryView/JXCategoryView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/JXCategoryView/JXCategoryView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/JXCategoryView/JXCategoryView.modulemap"; + PRODUCT_MODULE_NAME = JXCategoryView; + PRODUCT_NAME = JXCategoryView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; B04295D726C1883ADA40A304483D7E33 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5998234B9DD3C83BCD1DE88EDDEA5DF6 /* SDWebImage.debug.xcconfig */; + baseConfigurationReference = 93B896E371962B657B3B85C108092214 /* SDWebImage.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3818,7 +5898,7 @@ }; B26FBB655ABB114E4C0D589843814D6C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8C9727D0D56A9017D437CA50176F0474 /* Bugly.release.xcconfig */; + baseConfigurationReference = 0AD4477B34BC6EAF1A362183974F34DC /* Bugly.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -3834,29 +5914,10 @@ }; name = Release; }; - B83818605FEB0030D2B6D7FF64325A19 /* Debug */ = { + B429B9740B8EB5894C5BF953D9590A46 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D2BBA8DCCC9E2658211368C22BE1B033 /* MJRefresh.debug.xcconfig */; + baseConfigurationReference = 2CB55990BE7673BB5930FB77BB2A2C33 /* FLAnimatedImage.debug.xcconfig */; buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJRefresh"; - IBSC_MODULE = MJRefresh; - INFOPLIST_FILE = "Target Support Files/MJRefresh/ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - PRODUCT_NAME = MJRefresh.Privacy; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - BA12DA04ADC510F02AC04E3CFF37D769 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A6E8FF241173D596A21D4D4B7D86A810 /* Pods-keyBoard.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -3867,33 +5928,32 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; - INFOPLIST_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/FLAnimatedImage/FLAnimatedImage-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/FLAnimatedImage/FLAnimatedImage-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/FLAnimatedImage/FLAnimatedImage.modulemap"; + PRODUCT_MODULE_NAME = FLAnimatedImage; + PRODUCT_NAME = FLAnimatedImage; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; BCD70A0BB22D0C72BAF7207A7D4F44BD /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2940A878AE956B2190BA5A68D63DC5AD /* MBProgressHUD.debug.xcconfig */; + baseConfigurationReference = EC4CFDD75B85C12B1C1393BEA03A165C /* MBProgressHUD.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3928,9 +5988,84 @@ }; name = Debug; }; + BD1821022C3B758BEA9CB5616F987BC7 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 73EBDE260791BF4440027F8601391D8B /* LSTTimer.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/LSTTimer/LSTTimer-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LSTTimer/LSTTimer-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/LSTTimer/LSTTimer.modulemap"; + PRODUCT_MODULE_NAME = LSTTimer; + PRODUCT_NAME = LSTTimer; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + BDD02D9903A09C2C9D362C7536416CFB /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4201C2CD51C00E5AC0EC45DC41B32695 /* HWPanModal.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/HWPanModal/HWPanModal-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/HWPanModal/HWPanModal-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/HWPanModal/HWPanModal.modulemap"; + PRODUCT_MODULE_NAME = HWPanModal; + PRODUCT_NAME = HWPanModal; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; BE0CDEB7BE0A402663AFCC2111742430 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 71C7BAB63ED44B881A65C001AA682ADB /* MBProgressHUD.release.xcconfig */; + baseConfigurationReference = AC0C26DBF6F4D6A9D8C1BF55FE14DABA /* MBProgressHUD.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -3968,7 +6103,7 @@ }; CBAFED52B4B51F600FAF2141BA449F2E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18DB01964CBE026F2E6511875E1A98E2 /* Bugly.debug.xcconfig */; + baseConfigurationReference = 3DF983F1377AD739C3DF33AE51632FCF /* Bugly.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -3983,48 +6118,9 @@ }; name = Debug; }; - CCA3AD40EAA35CF032C0E1F404CCF9A1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 35BFA337F4E1FDE67C773A82CCDFD6DA /* Pods-keyBoard.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - INFOPLIST_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-keyBoard/Pods-keyBoard.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; CEE7FEC0A1B23DE7053203A448EEB294 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5104591E28208BB976FFAD3D7AFA2F58 /* AFNetworking.debug.xcconfig */; + baseConfigurationReference = 88D479C435BAEE51B8F3BBF87F8D3CC9 /* AFNetworking.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4061,7 +6157,7 @@ }; D0AB0AEF4014B926FCD853D3AE0A370A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F53F6F5B0D7E0FF60505964233E5C608 /* Masonry.release.xcconfig */; + baseConfigurationReference = 4A4AE7A504C340AE8EE98F70C318D63C /* Masonry.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4097,9 +6193,43 @@ }; name = Release; }; + D82E0E1859E0296A83015DC35BE95E81 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7895C7C58218B5F79C76FA1B5A55E669 /* MJRefresh.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJRefresh"; + IBSC_MODULE = MJRefresh; + INFOPLIST_FILE = "Target Support Files/MJRefresh/ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_NAME = MJRefresh.Privacy; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + D9D1855EA0BF7C903F0263AEDAADE1E7 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 93B896E371962B657B3B85C108092214 /* SDWebImage.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/SDWebImage"; + IBSC_MODULE = SDWebImage; + INFOPLIST_FILE = "Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + PRODUCT_NAME = SDWebImage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; DA533AA9B577872DAFB44EF2CF26C49A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C6F66997EF28E05B21EB7F13B379645A /* AFNetworking.release.xcconfig */; + baseConfigurationReference = 57B2E23309380B0E15F50C277205AC0D /* AFNetworking.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -4137,7 +6267,7 @@ }; EC66105EE15F9DC9B6F20F58FB67957D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 57BCCC946B3042A20D0C8F15D69FF943 /* MJExtension.debug.xcconfig */; + baseConfigurationReference = 954035BEFF37A926FB7C25E5508CD25D /* MJExtension.debug.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -4173,35 +6303,46 @@ }; name = Debug; }; - FE5AD58E2A362D4BD062D63BEF049BC0 /* Release */ = { + F48613BDFA945AC2A18363244F54E67C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 45EDC4788D38048F75B7F3CD0BEF1783 /* MJRefresh.release.xcconfig */; + baseConfigurationReference = 163DD1C8E32A767AC162D451FB47DECB /* LSTPopView.debug.xcconfig */; buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MJRefresh"; - IBSC_MODULE = MJRefresh; - INFOPLIST_FILE = "Target Support Files/MJRefresh/ResourceBundle-MJRefresh.Privacy-MJRefresh-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - PRODUCT_NAME = MJRefresh.Privacy; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/LSTPopView/LSTPopView-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/LSTPopView/LSTPopView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/LSTPopView/LSTPopView.modulemap"; + PRODUCT_MODULE_NAME = LSTPopView; + PRODUCT_NAME = LSTPopView; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 0B91AB5AF396DEF5CC076D126E4738A7 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B83818605FEB0030D2B6D7FF64325A19 /* Debug */, - FE5AD58E2A362D4BD062D63BEF049BC0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 1CF7CA11A791652D6975B2EDE2FC6719 /* Build configuration list for PBXNativeTarget "DZNEmptyDataSet" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -4229,11 +6370,11 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 3FA2BE14A4014E20D1803ECC0CEB5A7F /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */ = { + 404863FC7F43060AAE7C6FA66F917915 /* Build configuration list for PBXNativeTarget "JXPagingView-JXPagerView" */ = { isa = XCConfigurationList; buildConfigurations = ( - CCA3AD40EAA35CF032C0E1F404CCF9A1 /* Debug */, - BA12DA04ADC510F02AC04E3CFF37D769 /* Release */, + 64F655C37D34116A6844DB785A318D16 /* Debug */, + 2B066301F5B1D4BFFD95FEB2D9535180 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4247,6 +6388,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 48C48CA74E925091D509EAE661A5D87D /* Build configuration list for PBXNativeTarget "Pods-keyBoard" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 083F4B327F32BA42082C93DA3678A905 /* Debug */, + 9B8AB2F5A292514588D0A1ECFA2D15C4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 511C0840C50AF349D9A51E73BA56D28D /* Build configuration list for PBXNativeTarget "LYEmptyView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3565929B4632DC589BC25FDD7CE29119 /* Debug */, + 5FA85455B8129B5351F63A65BE01DE60 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 547AC2DDC5CDD1783E0827EEA7D453E1 /* Build configuration list for PBXNativeTarget "MJExtension" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -4256,6 +6415,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 773A22765B846DE10CADF4D2E77FE841 /* Build configuration list for PBXNativeTarget "JXPagingView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 869A260EDB31DBC8F1FD513756A77A93 /* Debug */, + 8EAC2F834160F0D756B3363236E0940A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 7CEB2E47380AD51987AA02ECD4DFBCD9 /* Build configuration list for PBXNativeTarget "AFNetworking" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -4265,6 +6433,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 91696E961FC8FD5A148C3EBCD7606569 /* Build configuration list for PBXNativeTarget "LSTPopView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F48613BDFA945AC2A18363244F54E67C /* Debug */, + 8F481C1C1CF7C89F42A9EFE335DEA2BC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 931B4A41B3614242C4D8813983B29AE7 /* Build configuration list for PBXNativeTarget "JXCategoryView-JXCategoryView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 024C9A3B861ABA20A2346A6A466EB015 /* Debug */, + 44E4190BC3FB54D917C88AC4FC84B935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 945C0F2B41CBADE68A142120AE9A4AF3 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -4274,11 +6460,11 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 95B0FCBEC38B41A89EDFDA2284E4CF2F /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */ = { + 97AAB185F08FD001A3F3B9102E506695 /* Build configuration list for PBXNativeTarget "MJExtension-MJExtension" */ = { isa = XCConfigurationList; buildConfigurations = ( - 427CF48FABE82C6FC8208160FDF4A9CE /* Debug */, - 532B03D3A70665C5D6CA2E785045C97B /* Release */, + 26A0DE2A2C5EEB5AB1D9315AE03103A7 /* Debug */, + 40403C5D9FB335BD8C765DF3FE61B9E5 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4310,11 +6496,38 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - E1B78FF12090122B97AE1A33AD172B8C /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */ = { + BA6D8ED14C9A066F526869BBA7BFA2F0 /* Build configuration list for PBXNativeTarget "MJRefresh-MJRefresh.Privacy" */ = { isa = XCConfigurationList; buildConfigurations = ( - 50BA0438712A00B9F9ECCE17AD68D287 /* Debug */, - 9C1EE0C94CDE25779693BCA7261B5989 /* Release */, + D82E0E1859E0296A83015DC35BE95E81 /* Debug */, + 0FF9630F4FA55B5D0AE7A67F275961B4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C43E72A521778768A4BFF773BB3A3E73 /* Build configuration list for PBXNativeTarget "LSTTimer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0BAEB6F6833BF585A150B8AD74FDBC03 /* Debug */, + BD1821022C3B758BEA9CB5616F987BC7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D47A0ADD8E3841C9330561C3E1664BB3 /* Build configuration list for PBXNativeTarget "HWPanModal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BDD02D9903A09C2C9D362C7536416CFB /* Debug */, + 63708B35D08B13BC40AB51386020974A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DB4C55F70CF73736D3687A2E620AC793 /* Build configuration list for PBXNativeTarget "JXCategoryView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A04019026E1B09655264B132BF5345A4 /* Debug */, + 571314BC8A84B1CED724D0AFB1CED826 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4328,6 +6541,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F06E4A04DE8430EB36B85704972503A5 /* Build configuration list for PBXNativeTarget "FLAnimatedImage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B429B9740B8EB5894C5BF953D9590A46 /* Debug */, + 67BAB382C3420CD62CB414CAA4D8A5B1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FB913463BEC55EE719AD5BC32990DB46 /* Build configuration list for PBXNativeTarget "SDWebImage-SDWebImage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D9D1855EA0BF7C903F0263AEDAADE1E7 /* Debug */, + 124345EDBC5F34B7AF5C60B83C477235 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/FLAnimatedImage.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/FLAnimatedImage.xcscheme new file mode 100644 index 0000000..6851dd8 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/FLAnimatedImage.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/HWPanModal.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/HWPanModal.xcscheme new file mode 100644 index 0000000..d82a391 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/HWPanModal.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXCategoryView-JXCategoryView.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXCategoryView-JXCategoryView.xcscheme new file mode 100644 index 0000000..177a116 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXCategoryView-JXCategoryView.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXCategoryView.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXCategoryView.xcscheme new file mode 100644 index 0000000..375271a --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXCategoryView.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXPagingView-JXPagerView.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXPagingView-JXPagerView.xcscheme new file mode 100644 index 0000000..d4e7bad --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXPagingView-JXPagerView.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXPagingView.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXPagingView.xcscheme new file mode 100644 index 0000000..0d1b64d --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/JXPagingView.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LSTPopView.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LSTPopView.xcscheme new file mode 100644 index 0000000..d643155 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LSTPopView.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LSTTimer.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LSTTimer.xcscheme new file mode 100644 index 0000000..72d6d1f --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LSTTimer.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LYEmptyView.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LYEmptyView.xcscheme new file mode 100644 index 0000000..0994b8d --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/LYEmptyView.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-Info.plist b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-Info.plist new file mode 100644 index 0000000..d6405e6 --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.17 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-dummy.m b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-dummy.m new file mode 100644 index 0000000..343e6b0 --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FLAnimatedImage : NSObject +@end +@implementation PodsDummy_FLAnimatedImage +@end diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-prefix.pch b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-umbrella.h b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-umbrella.h new file mode 100644 index 0000000..3ae0cae --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FLAnimatedImage.h" +#import "FLAnimatedImageView.h" + +FOUNDATION_EXPORT double FLAnimatedImageVersionNumber; +FOUNDATION_EXPORT const unsigned char FLAnimatedImageVersionString[]; + diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.debug.xcconfig b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.debug.xcconfig new file mode 100644 index 0000000..d55c041 --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.debug.xcconfig @@ -0,0 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "ImageIO" -framework "QuartzCore" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FLAnimatedImage +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.modulemap b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.modulemap new file mode 100644 index 0000000..0c6f2e3 --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.modulemap @@ -0,0 +1,6 @@ +framework module FLAnimatedImage { + umbrella header "FLAnimatedImage-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.release.xcconfig b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.release.xcconfig new file mode 100644 index 0000000..d55c041 --- /dev/null +++ b/Pods/Target Support Files/FLAnimatedImage/FLAnimatedImage.release.xcconfig @@ -0,0 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "ImageIO" -framework "QuartzCore" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FLAnimatedImage +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal-Info.plist b/Pods/Target Support Files/HWPanModal/HWPanModal-Info.plist new file mode 100644 index 0000000..5687afa --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.9.9 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal-dummy.m b/Pods/Target Support Files/HWPanModal/HWPanModal-dummy.m new file mode 100644 index 0000000..9e46cd7 --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_HWPanModal : NSObject +@end +@implementation PodsDummy_HWPanModal +@end diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal-prefix.pch b/Pods/Target Support Files/HWPanModal/HWPanModal-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal-umbrella.h b/Pods/Target Support Files/HWPanModal/HWPanModal-umbrella.h new file mode 100644 index 0000000..993527a --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal-umbrella.h @@ -0,0 +1,47 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "HWPanModalAnimator.h" +#import "HWPanModalInteractiveAnimator.h" +#import "HWPanModalPresentationAnimator.h" +#import "HWPresentingVCAnimatedTransitioning.h" +#import "HWPageSheetPresentingAnimation.h" +#import "HWShoppingCartPresentingAnimation.h" +#import "UIScrollView+Helper.h" +#import "UIView+HW_Frame.h" +#import "HWPanModalPresentationController.h" +#import "HWPanModalPresentationDelegate.h" +#import "HWPanModal.h" +#import "KeyValueObserver.h" +#import "HWPanModalPresentableHandler.h" +#import "HWPanModalHeight.h" +#import "HWPanModalPanGestureDelegate.h" +#import "HWPanModalPresentable.h" +#import "HWPanModalPresentationUpdateProtocol.h" +#import "UIViewController+LayoutHelper.h" +#import "UIViewController+PanModalDefault.h" +#import "UIViewController+Presentation.h" +#import "HWPanModalPresenterProtocol.h" +#import "UIViewController+PanModalPresenter.h" +#import "HWBackgroundConfig.h" +#import "HWDimmedView.h" +#import "HWPanContainerView.h" +#import "HWPanIndicatorView.h" +#import "HWPanModalIndicatorProtocol.h" +#import "HWPanModalShadow.h" +#import "HWVisualEffectView.h" +#import "HWPanModalContainerView.h" +#import "HWPanModalContentView.h" + +FOUNDATION_EXPORT double HWPanModalVersionNumber; +FOUNDATION_EXPORT const unsigned char HWPanModalVersionString[]; + diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal.debug.xcconfig b/Pods/Target Support Files/HWPanModal/HWPanModal.debug.xcconfig new file mode 100644 index 0000000..23faa61 --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/HWPanModal +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal.modulemap b/Pods/Target Support Files/HWPanModal/HWPanModal.modulemap new file mode 100644 index 0000000..a329887 --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal.modulemap @@ -0,0 +1,6 @@ +framework module HWPanModal { + umbrella header "HWPanModal-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/HWPanModal/HWPanModal.release.xcconfig b/Pods/Target Support Files/HWPanModal/HWPanModal.release.xcconfig new file mode 100644 index 0000000..23faa61 --- /dev/null +++ b/Pods/Target Support Files/HWPanModal/HWPanModal.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/HWPanModal +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView-Info.plist b/Pods/Target Support Files/JXCategoryView/JXCategoryView-Info.plist new file mode 100644 index 0000000..66116d5 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.6.8 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView-dummy.m b/Pods/Target Support Files/JXCategoryView/JXCategoryView-dummy.m new file mode 100644 index 0000000..c2b08cd --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_JXCategoryView : NSObject +@end +@implementation PodsDummy_JXCategoryView +@end diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView-prefix.pch b/Pods/Target Support Files/JXCategoryView/JXCategoryView-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView-umbrella.h b/Pods/Target Support Files/JXCategoryView/JXCategoryView-umbrella.h new file mode 100644 index 0000000..db80d54 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView-umbrella.h @@ -0,0 +1,59 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "JXCategoryView.h" +#import "JXCategoryBaseCell.h" +#import "JXCategoryBaseCellModel.h" +#import "JXCategoryBaseView.h" +#import "JXCategoryCollectionView.h" +#import "JXCategoryFactory.h" +#import "JXCategoryIndicatorParamsModel.h" +#import "JXCategoryIndicatorProtocol.h" +#import "JXCategoryListContainerRTLCell.h" +#import "JXCategoryListContainerView.h" +#import "JXCategoryViewAnimator.h" +#import "JXCategoryViewDefines.h" +#import "UIColor+JXAdd.h" +#import "JXCategoryDotCell.h" +#import "JXCategoryDotCellModel.h" +#import "JXCategoryDotView.h" +#import "JXCategoryImageCell.h" +#import "JXCategoryImageCellModel.h" +#import "JXCategoryImageView.h" +#import "JXCategoryIndicatorBackgroundView.h" +#import "JXCategoryIndicatorBallView.h" +#import "JXCategoryIndicatorComponentView.h" +#import "JXCategoryIndicatorDotLineView.h" +#import "JXCategoryIndicatorImageView.h" +#import "JXCategoryIndicatorLineView.h" +#import "JXCategoryIndicatorRainbowLineView.h" +#import "JXCategoryIndicatorTriangleView.h" +#import "JXCategoryIndicatorCell.h" +#import "JXCategoryIndicatorCellModel.h" +#import "JXCategoryIndicatorView.h" +#import "JXCategoryNumberCell.h" +#import "JXCategoryNumberCellModel.h" +#import "JXCategoryNumberView.h" +#import "RTLManager.h" +#import "JXCategoryTitleCell.h" +#import "JXCategoryTitleCellModel.h" +#import "JXCategoryTitleView.h" +#import "JXCategoryTitleImageCell.h" +#import "JXCategoryTitleImageCellModel.h" +#import "JXCategoryTitleImageView.h" +#import "JXCategoryTitleVerticalZoomCell.h" +#import "JXCategoryTitleVerticalZoomCellModel.h" +#import "JXCategoryTitleVerticalZoomView.h" + +FOUNDATION_EXPORT double JXCategoryViewVersionNumber; +FOUNDATION_EXPORT const unsigned char JXCategoryViewVersionString[]; + diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView.debug.xcconfig b/Pods/Target Support Files/JXCategoryView/JXCategoryView.debug.xcconfig new file mode 100644 index 0000000..4256a18 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/JXCategoryView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView.modulemap b/Pods/Target Support Files/JXCategoryView/JXCategoryView.modulemap new file mode 100644 index 0000000..fec3cc8 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView.modulemap @@ -0,0 +1,6 @@ +framework module JXCategoryView { + umbrella header "JXCategoryView-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/JXCategoryView/JXCategoryView.release.xcconfig b/Pods/Target Support Files/JXCategoryView/JXCategoryView.release.xcconfig new file mode 100644 index 0000000..4256a18 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/JXCategoryView.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/JXCategoryView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/JXCategoryView/ResourceBundle-JXCategoryView-JXCategoryView-Info.plist b/Pods/Target Support Files/JXCategoryView/ResourceBundle-JXCategoryView-JXCategoryView-Info.plist new file mode 100644 index 0000000..644e001 --- /dev/null +++ b/Pods/Target Support Files/JXCategoryView/ResourceBundle-JXCategoryView-JXCategoryView-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.6.8 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView-Info.plist b/Pods/Target Support Files/JXPagingView/JXPagingView-Info.plist new file mode 100644 index 0000000..08ba171 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.1.3 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView-dummy.m b/Pods/Target Support Files/JXPagingView/JXPagingView-dummy.m new file mode 100644 index 0000000..6a26959 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_JXPagingView : NSObject +@end +@implementation PodsDummy_JXPagingView +@end diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView-prefix.pch b/Pods/Target Support Files/JXPagingView/JXPagingView-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView-umbrella.h b/Pods/Target Support Files/JXPagingView/JXPagingView-umbrella.h new file mode 100644 index 0000000..67650f6 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "JXPagerListContainerView.h" +#import "JXPagerListRefreshView.h" +#import "JXPagerMainTableView.h" +#import "JXPagerSmoothView.h" +#import "JXPagerView.h" + +FOUNDATION_EXPORT double JXPagingViewVersionNumber; +FOUNDATION_EXPORT const unsigned char JXPagingViewVersionString[]; + diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView.debug.xcconfig b/Pods/Target Support Files/JXPagingView/JXPagingView.debug.xcconfig new file mode 100644 index 0000000..eefa6a8 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/JXPagingView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView.modulemap b/Pods/Target Support Files/JXPagingView/JXPagingView.modulemap new file mode 100644 index 0000000..5702dc0 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView.modulemap @@ -0,0 +1,6 @@ +framework module JXPagingView { + umbrella header "JXPagingView-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/JXPagingView/JXPagingView.release.xcconfig b/Pods/Target Support Files/JXPagingView/JXPagingView.release.xcconfig new file mode 100644 index 0000000..eefa6a8 --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/JXPagingView.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/JXPagingView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/JXPagingView/ResourceBundle-JXPagerView-JXPagingView-Info.plist b/Pods/Target Support Files/JXPagingView/ResourceBundle-JXPagerView-JXPagingView-Info.plist new file mode 100644 index 0000000..5b5034b --- /dev/null +++ b/Pods/Target Support Files/JXPagingView/ResourceBundle-JXPagerView-JXPagingView-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 2.1.3 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView-Info.plist b/Pods/Target Support Files/LSTPopView/LSTPopView-Info.plist new file mode 100644 index 0000000..5bfaa83 --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.3.10 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView-dummy.m b/Pods/Target Support Files/LSTPopView/LSTPopView-dummy.m new file mode 100644 index 0000000..a929a5e --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_LSTPopView : NSObject +@end +@implementation PodsDummy_LSTPopView +@end diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView-prefix.pch b/Pods/Target Support Files/LSTPopView/LSTPopView-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView-umbrella.h b/Pods/Target Support Files/LSTPopView/LSTPopView-umbrella.h new file mode 100644 index 0000000..cd628a0 --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "LSTPopView.h" +#import "LSTPopViewProtocol.h" +#import "UIView+LSTPV.h" + +FOUNDATION_EXPORT double LSTPopViewVersionNumber; +FOUNDATION_EXPORT const unsigned char LSTPopViewVersionString[]; + diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView.debug.xcconfig b/Pods/Target Support Files/LSTPopView/LSTPopView.debug.xcconfig new file mode 100644 index 0000000..7c97e36 --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "LSTTimer" -framework "UIKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/LSTPopView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView.modulemap b/Pods/Target Support Files/LSTPopView/LSTPopView.modulemap new file mode 100644 index 0000000..3140061 --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView.modulemap @@ -0,0 +1,6 @@ +framework module LSTPopView { + umbrella header "LSTPopView-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/LSTPopView/LSTPopView.release.xcconfig b/Pods/Target Support Files/LSTPopView/LSTPopView.release.xcconfig new file mode 100644 index 0000000..7c97e36 --- /dev/null +++ b/Pods/Target Support Files/LSTPopView/LSTPopView.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "LSTTimer" -framework "UIKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/LSTPopView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer-Info.plist b/Pods/Target Support Files/LSTTimer/LSTTimer-Info.plist new file mode 100644 index 0000000..8de3c32 --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.2.10 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer-dummy.m b/Pods/Target Support Files/LSTTimer/LSTTimer-dummy.m new file mode 100644 index 0000000..5101afd --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_LSTTimer : NSObject +@end +@implementation PodsDummy_LSTTimer +@end diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer-prefix.pch b/Pods/Target Support Files/LSTTimer/LSTTimer-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer-umbrella.h b/Pods/Target Support Files/LSTTimer/LSTTimer-umbrella.h new file mode 100644 index 0000000..54b8f60 --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "LSTTimer.h" + +FOUNDATION_EXPORT double LSTTimerVersionNumber; +FOUNDATION_EXPORT const unsigned char LSTTimerVersionString[]; + diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer.debug.xcconfig b/Pods/Target Support Files/LSTTimer/LSTTimer.debug.xcconfig new file mode 100644 index 0000000..5cd41e5 --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/LSTTimer +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer.modulemap b/Pods/Target Support Files/LSTTimer/LSTTimer.modulemap new file mode 100644 index 0000000..183e011 --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer.modulemap @@ -0,0 +1,6 @@ +framework module LSTTimer { + umbrella header "LSTTimer-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/LSTTimer/LSTTimer.release.xcconfig b/Pods/Target Support Files/LSTTimer/LSTTimer.release.xcconfig new file mode 100644 index 0000000..5cd41e5 --- /dev/null +++ b/Pods/Target Support Files/LSTTimer/LSTTimer.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/LSTTimer +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView-Info.plist b/Pods/Target Support Files/LYEmptyView/LYEmptyView-Info.plist new file mode 100644 index 0000000..77bb479 --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.3.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView-dummy.m b/Pods/Target Support Files/LYEmptyView/LYEmptyView-dummy.m new file mode 100644 index 0000000..5a0e24f --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_LYEmptyView : NSObject +@end +@implementation PodsDummy_LYEmptyView +@end diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView-prefix.pch b/Pods/Target Support Files/LYEmptyView/LYEmptyView-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView-umbrella.h b/Pods/Target Support Files/LYEmptyView/LYEmptyView-umbrella.h new file mode 100644 index 0000000..13a8301 --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "LYEmptyBaseView.h" +#import "LYEmptyView.h" +#import "LYEmptyViewHeader.h" +#import "UIView+Empty.h" +#import "UIView+LYExtension.h" + +FOUNDATION_EXPORT double LYEmptyViewVersionNumber; +FOUNDATION_EXPORT const unsigned char LYEmptyViewVersionString[]; + diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView.debug.xcconfig b/Pods/Target Support Files/LYEmptyView/LYEmptyView.debug.xcconfig new file mode 100644 index 0000000..83c7092 --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/LYEmptyView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView.modulemap b/Pods/Target Support Files/LYEmptyView/LYEmptyView.modulemap new file mode 100644 index 0000000..7bc3100 --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView.modulemap @@ -0,0 +1,6 @@ +framework module LYEmptyView { + umbrella header "LYEmptyView-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/LYEmptyView/LYEmptyView.release.xcconfig b/Pods/Target Support Files/LYEmptyView/LYEmptyView.release.xcconfig new file mode 100644 index 0000000..83c7092 --- /dev/null +++ b/Pods/Target Support Files/LYEmptyView/LYEmptyView.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/LYEmptyView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown index d4f13b3..811fe3a 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.markdown @@ -37,6 +37,177 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## FLAnimatedImage + +The MIT License (MIT) + +Copyright (c) 2014-2016 Flipboard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## HWPanModal + +MIT License + +Copyright (c) 2019 Heath Wang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## JXCategoryView + +MIT License + +Copyright (c) 2018 暴走的鑫鑫 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## JXPagingView + +MIT License + +Copyright (c) 2018 暴走的鑫鑫 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## LSTPopView + +Copyright (c) 2020 490790096@qq.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## LSTTimer + +Copyright (c) 2020 490790096@qq.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## LYEmptyView + +MIT License + +Copyright (c) 2017 yang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + ## LookinServer MIT License diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.plist b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.plist index 009ba4e..6b69ac6 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.plist +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-acknowledgements.plist @@ -60,6 +60,219 @@ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI Type PSGroupSpecifier
+ + FooterText + The MIT License (MIT) + +Copyright (c) 2014-2016 Flipboard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + FLAnimatedImage + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2019 Heath Wang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + HWPanModal + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2018 暴走的鑫鑫 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + JXCategoryView + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2018 暴走的鑫鑫 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + JXPagingView + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2020 490790096@qq.com <LoSenTrad@163.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + LSTPopView + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2020 490790096@qq.com <LoSenTrad@163.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + LSTTimer + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2017 yang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + LYEmptyView + Type + PSGroupSpecifier + FooterText MIT License diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-input-files.xcfilelist b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-input-files.xcfilelist index fd18c4b..34d8e4e 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-input-files.xcfilelist +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-input-files.xcfilelist @@ -1,6 +1,13 @@ ${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh ${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework ${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework +${BUILT_PRODUCTS_DIR}/FLAnimatedImage/FLAnimatedImage.framework +${BUILT_PRODUCTS_DIR}/HWPanModal/HWPanModal.framework +${BUILT_PRODUCTS_DIR}/JXCategoryView/JXCategoryView.framework +${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework +${BUILT_PRODUCTS_DIR}/LSTPopView/LSTPopView.framework +${BUILT_PRODUCTS_DIR}/LSTTimer/LSTTimer.framework +${BUILT_PRODUCTS_DIR}/LYEmptyView/LYEmptyView.framework ${BUILT_PRODUCTS_DIR}/LookinServer/LookinServer.framework ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework ${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-output-files.xcfilelist b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-output-files.xcfilelist index 9d28c83..9d68623 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-output-files.xcfilelist +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Debug-output-files.xcfilelist @@ -1,5 +1,12 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLAnimatedImage.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HWPanModal.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXCategoryView.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXPagingView.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LSTPopView.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LSTTimer.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LYEmptyView.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LookinServer.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-input-files.xcfilelist b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-input-files.xcfilelist index 1b381a7..b977d53 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-input-files.xcfilelist +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-input-files.xcfilelist @@ -1,6 +1,13 @@ ${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh ${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework ${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework +${BUILT_PRODUCTS_DIR}/FLAnimatedImage/FLAnimatedImage.framework +${BUILT_PRODUCTS_DIR}/HWPanModal/HWPanModal.framework +${BUILT_PRODUCTS_DIR}/JXCategoryView/JXCategoryView.framework +${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework +${BUILT_PRODUCTS_DIR}/LSTPopView/LSTPopView.framework +${BUILT_PRODUCTS_DIR}/LSTTimer/LSTTimer.framework +${BUILT_PRODUCTS_DIR}/LYEmptyView/LYEmptyView.framework ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework ${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-output-files.xcfilelist b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-output-files.xcfilelist index 80f5e3c..f4eb712 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-output-files.xcfilelist +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-Release-output-files.xcfilelist @@ -1,5 +1,12 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLAnimatedImage.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HWPanModal.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXCategoryView.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXPagingView.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LSTPopView.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LSTTimer.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LYEmptyView.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh index 39e15c2..66535f4 100755 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh @@ -178,6 +178,13 @@ code_sign_if_enabled() { if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework" install_framework "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework" + install_framework "${BUILT_PRODUCTS_DIR}/FLAnimatedImage/FLAnimatedImage.framework" + install_framework "${BUILT_PRODUCTS_DIR}/HWPanModal/HWPanModal.framework" + install_framework "${BUILT_PRODUCTS_DIR}/JXCategoryView/JXCategoryView.framework" + install_framework "${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework" + install_framework "${BUILT_PRODUCTS_DIR}/LSTPopView/LSTPopView.framework" + install_framework "${BUILT_PRODUCTS_DIR}/LSTTimer/LSTTimer.framework" + install_framework "${BUILT_PRODUCTS_DIR}/LYEmptyView/LYEmptyView.framework" install_framework "${BUILT_PRODUCTS_DIR}/LookinServer/LookinServer.framework" install_framework "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework" @@ -188,6 +195,13 @@ fi if [[ "$CONFIGURATION" == "Release" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework" install_framework "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework" + install_framework "${BUILT_PRODUCTS_DIR}/FLAnimatedImage/FLAnimatedImage.framework" + install_framework "${BUILT_PRODUCTS_DIR}/HWPanModal/HWPanModal.framework" + install_framework "${BUILT_PRODUCTS_DIR}/JXCategoryView/JXCategoryView.framework" + install_framework "${BUILT_PRODUCTS_DIR}/JXPagingView/JXPagingView.framework" + install_framework "${BUILT_PRODUCTS_DIR}/LSTPopView/LSTPopView.framework" + install_framework "${BUILT_PRODUCTS_DIR}/LSTTimer/LSTTimer.framework" + install_framework "${BUILT_PRODUCTS_DIR}/LYEmptyView/LYEmptyView.framework" install_framework "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.debug.xcconfig b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.debug.xcconfig index cb9a079..96285cf 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.debug.xcconfig +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.debug.xcconfig @@ -1,10 +1,10 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage" "${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal" "${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer/LookinServer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage/FLAnimatedImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal/HWPanModal.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView/JXCategoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView/JXPagingView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView/LSTPopView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer/LSTTimer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView/LYEmptyView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer/LookinServer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "LookinServer" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "UIKit" -OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" +OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "FLAnimatedImage" -framework "Foundation" -framework "HWPanModal" -framework "ImageIO" -framework "JXCategoryView" -framework "JXPagingView" -framework "LSTPopView" -framework "LSTTimer" -framework "LYEmptyView" -framework "LookinServer" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "UIKit" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal" "-F${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView" "-F${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "-F${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView" "-F${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "-F${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView" "-F${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig index 8547576..c13eb51 100644 --- a/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig +++ b/Pods/Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig @@ -1,10 +1,10 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_ROOT}/Bugly" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage" "${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal" "${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_ROOT}/Bugly" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage/FLAnimatedImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal/HWPanModal.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView/JXCategoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView/JXPagingView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView/LSTPopView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer/LSTTimer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView/LYEmptyView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "AFNetworking" -framework "Bugly" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/Bugly" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "AFNetworking" -framework "Bugly" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "FLAnimatedImage" -framework "Foundation" -framework "HWPanModal" -framework "ImageIO" -framework "JXCategoryView" -framework "JXPagingView" -framework "LSTPopView" -framework "LSTTimer" -framework "LYEmptyView" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/Bugly" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/FLAnimatedImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/HWPanModal" "-F${PODS_CONFIGURATION_BUILD_DIR}/JXCategoryView" "-F${PODS_CONFIGURATION_BUILD_DIR}/JXPagingView" "-F${PODS_CONFIGURATION_BUILD_DIR}/LSTPopView" "-F${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "-F${PODS_CONFIGURATION_BUILD_DIR}/LYEmptyView" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/Shared/KBConfig.h b/Shared/KBConfig.h index 8a79c94..35a90bb 100644 --- a/Shared/KBConfig.h +++ b/Shared/KBConfig.h @@ -8,6 +8,11 @@ #ifndef KBConfig_h #define KBConfig_h +// UIKit is needed for CGFloat and UIScreen used by size-adaptation helpers +#if __OBJC__ +#import +#endif + // 基础baseUrl #ifndef KB_BASE_URL #define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/" @@ -15,7 +20,7 @@ // Universal Links 通用链接 #ifndef KB_UL_BASE -#define KB_UL_BASE @"https://your.domain/ul" +#define KB_UL_BASE @"https://app.tknb.net/ul" #endif #define KB_UL_LOGIN KB_UL_BASE @"/login" @@ -37,8 +42,38 @@ #define KB_KEYBOARD_EXTENSION_BUNDLE_ID @"com.loveKey.nyx.CustomKeyboard" #endif +// --- 应用自定义 Scheme --- +// 主 App 在 Info.plist 中注册的 URL Scheme,用于从键盘扩展唤起容器 App。 +// 注意:AppDelegate 中对 scheme 做了小写化比较(kbkeyboardappextension),iOS 对大小写不敏感; +// 这里统一通过宏引用,避免出现与 App 端不一致的字符串。 +#ifndef KB_APP_SCHEME +#define KB_APP_SCHEME @"kbkeyboardAppExtension" +#endif + +// --- 尺寸适配(以 375 设计稿为基准) --- +// 用法:传入设计稿上的数值,返回按当前屏幕宽度缩放后的值。 +// 例如:CGFloat padding = KBFit(16); +#ifndef KB_DESIGN_WIDTH +#define KB_DESIGN_WIDTH 375.0 +#endif + +#if __OBJC__ +static inline CGFloat KBScreenWidth(void) { + return [UIScreen mainScreen].bounds.size.width; +} + +static inline CGFloat KBScaleFactor(void) { + return KBScreenWidth() / (CGFloat)KB_DESIGN_WIDTH; +} + +static inline CGFloat KBFit(CGFloat designValue) { + return designValue * KBScaleFactor(); +} +#endif + // --- 常用宏 --- // 弱引用 self(在 block 中避免循环引用):使用处直接写 KBWeakSelf; #ifndef KBWeakSelf #define KBWeakSelf __weak __typeof(self) weakSelf = self; #endif + diff --git a/Shared/KBSkinManager.h b/Shared/KBSkinManager.h new file mode 100644 index 0000000..b82350a --- /dev/null +++ b/Shared/KBSkinManager.h @@ -0,0 +1,58 @@ +// +// KBSkinManager.h +// App & Keyboard Extension shared skin/theme manager. +// +// Stores a lightweight theme (colors, identifiers) to shared keychain so +// both targets see the same current skin. Cross-process updates are delivered +// via Darwin notification. Intended for immediate reflection in extension. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const KBSkinDidChangeNotification; // in-process +extern NSString * const KBDarwinSkinChanged; // cross-process + +/// Simple theme model (colors only; assets can be added later via App Group) +@interface KBSkinTheme : NSObject +@property (nonatomic, copy) NSString *skinId; // e.g. "mint" +@property (nonatomic, copy) NSString *name; // display name +@property (nonatomic, strong) UIColor *keyboardBackground; +@property (nonatomic, strong) UIColor *keyBackground; +@property (nonatomic, strong) UIColor *keyTextColor; +@property (nonatomic, strong) UIColor *keyHighlightBackground; // selected/highlighted +@property (nonatomic, strong) UIColor *accentColor; // function view accents +/// 可选:键盘背景图片的 PNG/JPEG 数据(若存在,优先显示图片) +@property (nonatomic, strong, nullable) NSData *backgroundImageData; +@end + +/// Shared skin manager (Keychain Sharing based) +@interface KBSkinManager : NSObject + ++ (instancetype)shared; + +@property (atomic, strong, readonly) KBSkinTheme *current; // never nil (fallback to default) + +/// Save theme from JSON dictionary (keys: id, name, background, key_bg, key_text, key_highlight, accent) +- (BOOL)applyThemeFromJSON:(NSDictionary *)json; + +/// Save explicit theme +- (BOOL)applyTheme:(KBSkinTheme *)theme; + +/// Reset to default theme +- (void)resetToDefault; + +/// 直接应用图片皮肤(使用 JPEG/PNG 数据)。建议大小 < 512KB。 +- (BOOL)applyImageSkinWithData:(NSData *)imageData skinId:(NSString *)skinId name:(NSString *)name; + +/// 当前背景图片(若存在) +- (nullable UIImage *)currentBackgroundImage; + +/// Parse a hex color string like "#RRGGBB"/"#RRGGBBAA" ++ (UIColor *)colorFromHexString:(NSString *)hex defaultColor:(UIColor *)fallback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Shared/KBSkinManager.m b/Shared/KBSkinManager.m new file mode 100644 index 0000000..6497ff4 --- /dev/null +++ b/Shared/KBSkinManager.m @@ -0,0 +1,214 @@ +// +// KBSkinManager.m +// + +#import "KBSkinManager.h" +#import +#import "KBConfig.h" + +NSString * const KBSkinDidChangeNotification = @"KBSkinDidChangeNotification"; +NSString * const KBDarwinSkinChanged = @"com.loveKey.nyx.skin.changed"; + +static NSString * const kKBSkinService = @"com.loveKey.nyx.skin"; // Keychain service +static NSString * const kKBSkinAccount = @"current"; // Keychain account + +@implementation KBSkinTheme + ++ (BOOL)supportsSecureCoding { return YES; } + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.skinId forKey:@"skinId"]; + [coder encodeObject:self.name forKey:@"name"]; + [coder encodeObject:self.keyboardBackground forKey:@"keyboardBackground"]; + [coder encodeObject:self.keyBackground forKey:@"keyBackground"]; + [coder encodeObject:self.keyTextColor forKey:@"keyTextColor"]; + [coder encodeObject:self.keyHighlightBackground forKey:@"keyHighlightBackground"]; + [coder encodeObject:self.accentColor forKey:@"accentColor"]; + if (self.backgroundImageData) { + [coder encodeObject:self.backgroundImageData forKey:@"backgroundImageData"]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + if (self = [super init]) { + _skinId = [coder decodeObjectOfClass:NSString.class forKey:@"skinId"] ?: @"default"; + _name = [coder decodeObjectOfClass:NSString.class forKey:@"name"] ?: @"Default"; + _keyboardBackground = [coder decodeObjectOfClass:UIColor.class forKey:@"keyboardBackground"] ?: [UIColor colorWithWhite:0.95 alpha:1.0]; + _keyBackground = [coder decodeObjectOfClass:UIColor.class forKey:@"keyBackground"] ?: UIColor.whiteColor; + _keyTextColor = [coder decodeObjectOfClass:UIColor.class forKey:@"keyTextColor"] ?: UIColor.blackColor; + _keyHighlightBackground = [coder decodeObjectOfClass:UIColor.class forKey:@"keyHighlightBackground"] ?: [UIColor colorWithWhite:0.85 alpha:1.0]; + _accentColor = [coder decodeObjectOfClass:UIColor.class forKey:@"accentColor"] ?: [UIColor colorWithRed:0.77 green:0.93 blue:0.82 alpha:1.0]; + _backgroundImageData = [coder decodeObjectOfClass:NSData.class forKey:@"backgroundImageData"]; + } + return self; +} + +@end + +@interface KBSkinManager () +@property (atomic, strong, readwrite) KBSkinTheme *current; +@end + +@implementation KBSkinManager + ++ (instancetype)shared { + static KBSkinManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBSkinManager new]; }); + return m; +} + +- (instancetype)init { + if (self = [super init]) { + _current = [self p_loadFromKeychain] ?: [self.class defaultTheme]; + // Observe Darwin notification for cross-process updates + CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), + (__bridge const void *)(self), + KBSkinDarwinCallback, + (__bridge CFStringRef)KBDarwinSkinChanged, + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); + } + return self; +} + +static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { + KBSkinManager *self = (__bridge KBSkinManager *)observer; + [self p_reloadFromKeychainAndBroadcast:YES]; +} + +- (void)dealloc { + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (__bridge CFStringRef)KBDarwinSkinChanged, NULL); +} + +#pragma mark - Public + +- (BOOL)applyThemeFromJSON:(NSDictionary *)json { + if (json.count == 0) return NO; + KBSkinTheme *t = [KBSkinTheme new]; + t.skinId = [json[@"id"] isKindOfClass:NSString.class] ? json[@"id"] : @"custom"; + t.name = [json[@"name"] isKindOfClass:NSString.class] ? json[@"name"] : t.skinId; + t.keyboardBackground = [self.class colorFromHexString:json[@"background"] defaultColor:[self.class defaultTheme].keyboardBackground]; + t.keyBackground = [self.class colorFromHexString:json[@"key_bg"] defaultColor:[self.class defaultTheme].keyBackground]; + t.keyTextColor = [self.class colorFromHexString:json[@"key_text"] defaultColor:[self.class defaultTheme].keyTextColor]; + t.keyHighlightBackground = [self.class colorFromHexString:json[@"key_highlight"] defaultColor:[self.class defaultTheme].keyHighlightBackground]; + t.accentColor = [self.class colorFromHexString:json[@"accent"] defaultColor:[self.class defaultTheme].accentColor]; + return [self applyTheme:t]; +} + +- (BOOL)applyTheme:(KBSkinTheme *)theme { + if (!theme) return NO; + if ([self p_saveToKeychain:theme]) { + self.current = theme; + [[NSNotificationCenter defaultCenter] postNotificationName:KBSkinDidChangeNotification object:nil]; + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)KBDarwinSkinChanged, NULL, NULL, true); + return YES; + } + return NO; +} + +- (void)resetToDefault { + [self applyTheme:[self.class defaultTheme]]; +} + +- (BOOL)applyImageSkinWithData:(NSData *)imageData skinId:(NSString *)skinId name:(NSString *)name { + if (imageData.length == 0) return NO; + // 构造新主题,继承当前配色作为按键/强调色的默认值 + KBSkinTheme *base = self.current ?: [self.class defaultTheme]; + KBSkinTheme *t = [KBSkinTheme new]; + t.skinId = skinId ?: @"image"; + t.name = name ?: t.skinId; + t.keyboardBackground = base.keyboardBackground ?: [self.class defaultTheme].keyboardBackground; + t.keyBackground = base.keyBackground ?: [self.class defaultTheme].keyBackground; + t.keyTextColor = base.keyTextColor ?: [self.class defaultTheme].keyTextColor; + t.keyHighlightBackground = base.keyHighlightBackground ?: [self.class defaultTheme].keyHighlightBackground; + t.accentColor = base.accentColor ?: [self.class defaultTheme].accentColor; + t.backgroundImageData = imageData; + return [self applyTheme:t]; +} + +- (UIImage *)currentBackgroundImage { + NSData *d = self.current.backgroundImageData; + if (d.length == 0) return nil; + return [UIImage imageWithData:d scale:[UIScreen mainScreen].scale] ?: nil; +} + ++ (UIColor *)colorFromHexString:(NSString *)hex defaultColor:(UIColor *)fallback { + if (![hex isKindOfClass:NSString.class] || hex.length == 0) return fallback; + NSString *s = [[hex stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] lowercaseString]; + if ([s hasPrefix:@"#"]) s = [s substringFromIndex:1]; + unsigned long long v = 0; NSScanner *scanner = [NSScanner scannerWithString:s]; + if (![scanner scanHexLongLong:&v]) return fallback; + if (s.length == 6) { // RRGGBB + CGFloat r = ((v >> 16) & 0xFF) / 255.0; + CGFloat g = ((v >> 8) & 0xFF) / 255.0; + CGFloat b = (v & 0xFF) / 255.0; + return [UIColor colorWithRed:r green:g blue:b alpha:1.0]; + } else if (s.length == 8) { // RRGGBBAA + CGFloat r = ((v >> 24) & 0xFF) / 255.0; + CGFloat g = ((v >> 16) & 0xFF) / 255.0; + CGFloat b = ((v >> 8) & 0xFF) / 255.0; + CGFloat a = (v & 0xFF) / 255.0; + return [UIColor colorWithRed:r green:g blue:b alpha:a]; + } + return fallback; +} + +#pragma mark - Defaults + ++ (KBSkinTheme *)defaultTheme { + KBSkinTheme *t = [KBSkinTheme new]; + t.skinId = @"default"; + t.name = @"Default"; + t.keyboardBackground = [UIColor colorWithWhite:0.95 alpha:1.0]; + t.keyBackground = UIColor.whiteColor; + t.keyTextColor = UIColor.blackColor; + t.keyHighlightBackground = [UIColor colorWithWhite:0.85 alpha:1.0]; + t.accentColor = [UIColor colorWithRed:0.77 green:0.93 blue:0.82 alpha:1.0]; + t.backgroundImageData = nil; + return t; +} + +#pragma mark - Keychain + +- (NSMutableDictionary *)baseKCQuery { + NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService: kKBSkinService, + (__bridge id)kSecAttrAccount: kKBSkinAccount } mutableCopy]; + q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; + return q; +} + +- (BOOL)p_saveToKeychain:(KBSkinTheme *)theme { + NSError *err = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:theme requiringSecureCoding:YES error:&err]; + if (err || data.length == 0) return NO; + NSMutableDictionary *q = [self baseKCQuery]; + SecItemDelete((__bridge CFDictionaryRef)q); + q[(__bridge id)kSecValueData] = data; + q[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + OSStatus st = SecItemAdd((__bridge CFDictionaryRef)q, NULL); + return (st == errSecSuccess); +} + +- (KBSkinTheme *)p_loadFromKeychain { + NSMutableDictionary *q = [self baseKCQuery]; + q[(__bridge id)kSecReturnData] = @YES; + q[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + CFTypeRef dataRef = NULL; OSStatus st = SecItemCopyMatching((__bridge CFDictionaryRef)q, &dataRef); + if (st != errSecSuccess || !dataRef) return nil; + NSData *data = (__bridge_transfer NSData *)dataRef; + if (data.length == 0) return nil; + @try { + KBSkinTheme *t = [NSKeyedUnarchiver unarchivedObjectOfClass:KBSkinTheme.class fromData:data error:NULL]; + return t; + } @catch (__unused NSException *e) { return nil; } +} + +- (void)p_reloadFromKeychainAndBroadcast:(BOOL)broadcast { + KBSkinTheme *t = [self p_loadFromKeychain] ?: [self.class defaultTheme]; + self.current = t; + if (broadcast) { + [[NSNotificationCenter defaultCenter] postNotificationName:KBSkinDidChangeNotification object:nil]; + } +} + +@end diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index e49e609..3a4de1b 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -8,6 +8,73 @@ /* Begin PBXBuildFile section */ 043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EAE12EAF940F0089C901 /* KBPermissionViewController.m */; }; + 0459D1B42EBA284C00F2D189 /* KBSkinCenterVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */; }; + 0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; }; + 0459D1B82EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; }; + 0477BD952EBAFF4E0055D639 /* KBURLOpenBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BD932EBAFF4E0055D639 /* KBURLOpenBridge.m */; }; + 0477BDF02EBB76E30055D639 /* HomeSheetVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */; }; + 0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */; }; + 0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF62EBC63A80055D639 /* KBTestVC.m */; }; + 0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF92EBC66340055D639 /* HomeHeadView.m */; }; + 0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDFC2EBC6A170055D639 /* HomeHotVC.m */; }; + 0477BE002EBC6A330055D639 /* HomeRankVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDFF2EBC6A330055D639 /* HomeRankVC.m */; }; + 0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BE032EBC83130055D639 /* HomeMainVC.m */; }; + 0477BEA22EBCF0000055D639 /* KBTopImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BEA12EBCF0000055D639 /* KBTopImageButton.m */; }; + 047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650C2EBC8A840035E841 /* KBPanModalView.m */; }; + 047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */; }; + 047C652D2EBCAAAC0035E841 /* crab_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C651F2EBCAAAC0035E841 /* crab_selected.png */; }; + 047C652E2EBCAAAC0035E841 /* crab.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C651E2EBCAAAC0035E841 /* crab.png */; }; + 047C652F2EBCAAAC0035E841 /* arrow_down.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C651A2EBCAAAC0035E841 /* arrow_down.png */; }; + 047C65302EBCAAAC0035E841 /* football.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65212EBCAAAC0035E841 /* football.png */; }; + 047C65312EBCAAAC0035E841 /* city.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65122EBCAAAC0035E841 /* city.png */; }; + 047C65322EBCAAAC0035E841 /* apple_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65192EBCAAAC0035E841 /* apple_selected.png */; }; + 047C65332EBCAAAC0035E841 /* carrot.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C651C2EBCAAAC0035E841 /* carrot.png */; }; + 047C65342EBCAAAC0035E841 /* lobster.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65262EBCAAAC0035E841 /* lobster.png */; }; + 047C65352EBCAAAC0035E841 /* lufei.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 047C65282EBCAAAC0035E841 /* lufei.jpg */; }; + 047C65362EBCAAAC0035E841 /* river.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65152EBCAAAC0035E841 /* river.png */; }; + 047C65372EBCAAAC0035E841 /* watermelon_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C652A2EBCAAAC0035E841 /* watermelon_selected.png */; }; + 047C65382EBCAAAC0035E841 /* JXCategoryView.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65242EBCAAAC0035E841 /* JXCategoryView.png */; }; + 047C65392EBCAAAC0035E841 /* JXCategoryViewStructure.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65252EBCAAAC0035E841 /* JXCategoryViewStructure.png */; }; + 047C653A2EBCAAAC0035E841 /* arrow_up.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C651B2EBCAAAC0035E841 /* arrow_up.png */; }; + 047C653B2EBCAAAC0035E841 /* boat.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65112EBCAAAC0035E841 /* boat.png */; }; + 047C653C2EBCAAAC0035E841 /* grape_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65232EBCAAAC0035E841 /* grape_selected.png */; }; + 047C653D2EBCAAAC0035E841 /* lobster_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65272EBCAAAC0035E841 /* lobster_selected.png */; }; + 047C653E2EBCAAAC0035E841 /* light.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65132EBCAAAC0035E841 /* light.png */; }; + 047C653F2EBCAAAC0035E841 /* seaWave.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65162EBCAAAC0035E841 /* seaWave.png */; }; + 047C65402EBCAAAC0035E841 /* watermelon.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65292EBCAAAC0035E841 /* watermelon.png */; }; + 047C65412EBCAAAC0035E841 /* lotus.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65142EBCAAAC0035E841 /* lotus.png */; }; + 047C65422EBCAAAC0035E841 /* grape.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65222EBCAAAC0035E841 /* grape.png */; }; + 047C65432EBCAAAC0035E841 /* filter.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65202EBCAAAC0035E841 /* filter.png */; }; + 047C65442EBCAAAC0035E841 /* apple.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C65182EBCAAAC0035E841 /* apple.png */; }; + 047C65452EBCAAAC0035E841 /* carrot_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 047C651D2EBCAAAC0035E841 /* carrot_selected.png */; }; + 047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C654F2EBCBA9E0035E841 /* KBShopVC.m */; }; + 047C65532EBCBAC60035E841 /* KBCommunityVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C65522EBCBAC60035E841 /* KBCommunityVC.m */; }; + 047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C65572EBCC06D0035E841 /* HomeRankCardCell.m */; }; + 047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C655B2EBCD08E0035E841 /* UIView+KBShadow.m */; }; + 047C655E2EBCD5B20035E841 /* UIImage+KBColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C655D2EBCD5B20035E841 /* UIImage+KBColor.m */; }; + 048908BC2EBE1FCB00FABA60 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908BB2EBE1FCB00FABA60 /* BaseViewController.m */; }; + 048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908C22EBE32B800FABA60 /* KBSearchVC.m */; }; + 048908CC2EBE373500FABA60 /* KBSearchBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908C52EBE373500FABA60 /* KBSearchBarView.m */; }; + 048908CD2EBE373500FABA60 /* KBSearchSectionHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908C72EBE373500FABA60 /* KBSearchSectionHeader.m */; }; + 048908CE2EBE373500FABA60 /* KBSkinCardCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908C92EBE373500FABA60 /* KBSkinCardCell.m */; }; + 048908CF2EBE373500FABA60 /* KBTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908CB2EBE373500FABA60 /* KBTagCell.m */; }; + 048908D22EBF611D00FABA60 /* KBHistoryMoreCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908D12EBF611D00FABA60 /* KBHistoryMoreCell.m */; }; + 048908DA2EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908D82EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m */; }; + 048908DD2EBF67EB00FABA60 /* KBSearchResultVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908DC2EBF67EB00FABA60 /* KBSearchResultVC.m */; }; + 048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908DF2EBF73DC00FABA60 /* MySkinVC.m */; }; + 048908E32EBF760000FABA60 /* MySkinCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908E22EBF760000FABA60 /* MySkinCell.m */; }; + 048908E32EBF821700FABA60 /* KBSkinDetailVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908E22EBF821700FABA60 /* KBSkinDetailVC.m */; }; + 048908E62EBF841B00FABA60 /* KBSkinDetailTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908E52EBF841B00FABA60 /* KBSkinDetailTagCell.m */; }; + 048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908E82EBF843000FABA60 /* KBSkinDetailHeaderCell.m */; }; + 048908EC2EBF849300FABA60 /* KBSkinTagsContainerCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908EB2EBF849300FABA60 /* KBSkinTagsContainerCell.m */; }; + 048908EF2EBF861800FABA60 /* KBSkinSectionTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908EE2EBF861800FABA60 /* KBSkinSectionTitleCell.m */; }; + 048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908F12EC047FD00FABA60 /* KBShopHeadView.m */; }; + 048908F52EC0496400FABA60 /* KBShopItemVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908F42EC0496400FABA60 /* KBShopItemVC.m */; }; + 048908FE2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */; }; + 048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048909F12EC0AAAA00FABA60 /* KBCategoryTitleCell.m */; }; + 048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */; }; + 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */; }; + 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */; }; 04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; }; 04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */; }; 04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */; }; @@ -59,6 +126,8 @@ A1B2C4202EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */; }; A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */; }; A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2D7012EB8C00100000001 /* KBLangTestVC.m */; }; + A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0022EBC7AAA00000001 /* KBTopThreeView.m */; }; + A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0042EBC7AAA00000001 /* HomeHotCell.m */; }; ECC9EE02174D86E8D792472F /* Pods_keyBoard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 967065BB5230E43F293B3AF9 /* Pods_keyBoard.framework */; }; /* End PBXBuildFile section */ @@ -87,6 +156,114 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0459D1B22EBA284C00F2D189 /* KBSkinCenterVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinCenterVC.h; sourceTree = ""; }; + 0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinCenterVC.m; sourceTree = ""; }; + 0459D1B52EBA287900F2D189 /* KBSkinManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinManager.h; sourceTree = ""; }; + 0459D1B62EBA287900F2D189 /* KBSkinManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinManager.m; sourceTree = ""; }; + 0477BD922EBAFF4E0055D639 /* KBURLOpenBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBURLOpenBridge.h; sourceTree = ""; }; + 0477BD932EBAFF4E0055D639 /* KBURLOpenBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBURLOpenBridge.m; sourceTree = ""; }; + 0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeSheetVC.h; sourceTree = ""; }; + 0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeSheetVC.m; sourceTree = ""; }; + 0477BDF12EBB7B850055D639 /* KBDirectionIndicatorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBDirectionIndicatorView.h; sourceTree = ""; }; + 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBDirectionIndicatorView.m; sourceTree = ""; }; + 0477BDF52EBC63A80055D639 /* KBTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTestVC.h; sourceTree = ""; }; + 0477BDF62EBC63A80055D639 /* KBTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTestVC.m; sourceTree = ""; }; + 0477BDF82EBC66340055D639 /* HomeHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHeadView.h; sourceTree = ""; }; + 0477BDF92EBC66340055D639 /* HomeHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHeadView.m; sourceTree = ""; }; + 0477BDFB2EBC6A170055D639 /* HomeHotVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHotVC.h; sourceTree = ""; }; + 0477BDFC2EBC6A170055D639 /* HomeHotVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHotVC.m; sourceTree = ""; }; + 0477BDFE2EBC6A330055D639 /* HomeRankVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankVC.h; sourceTree = ""; }; + 0477BDFF2EBC6A330055D639 /* HomeRankVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeRankVC.m; sourceTree = ""; }; + 0477BE022EBC83130055D639 /* HomeMainVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeMainVC.h; sourceTree = ""; }; + 0477BE032EBC83130055D639 /* HomeMainVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeMainVC.m; sourceTree = ""; }; + 0477BEA02EBCF0000055D639 /* KBTopImageButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTopImageButton.h; sourceTree = ""; }; + 0477BEA12EBCF0000055D639 /* KBTopImageButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTopImageButton.m; sourceTree = ""; }; + 047C650B2EBC8A840035E841 /* KBPanModalView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPanModalView.h; sourceTree = ""; }; + 047C650C2EBC8A840035E841 /* KBPanModalView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPanModalView.m; sourceTree = ""; }; + 047C650E2EBCA8DD0035E841 /* HomeRankContentVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankContentVC.h; sourceTree = ""; }; + 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeRankContentVC.m; sourceTree = ""; }; + 047C65112EBCAAAC0035E841 /* boat.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = boat.png; sourceTree = ""; }; + 047C65122EBCAAAC0035E841 /* city.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = city.png; sourceTree = ""; }; + 047C65132EBCAAAC0035E841 /* light.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = light.png; sourceTree = ""; }; + 047C65142EBCAAAC0035E841 /* lotus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lotus.png; sourceTree = ""; }; + 047C65152EBCAAAC0035E841 /* river.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = river.png; sourceTree = ""; }; + 047C65162EBCAAAC0035E841 /* seaWave.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = seaWave.png; sourceTree = ""; }; + 047C65182EBCAAAC0035E841 /* apple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = apple.png; sourceTree = ""; }; + 047C65192EBCAAAC0035E841 /* apple_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = apple_selected.png; sourceTree = ""; }; + 047C651A2EBCAAAC0035E841 /* arrow_down.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = arrow_down.png; sourceTree = ""; }; + 047C651B2EBCAAAC0035E841 /* arrow_up.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = arrow_up.png; sourceTree = ""; }; + 047C651C2EBCAAAC0035E841 /* carrot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = carrot.png; sourceTree = ""; }; + 047C651D2EBCAAAC0035E841 /* carrot_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = carrot_selected.png; sourceTree = ""; }; + 047C651E2EBCAAAC0035E841 /* crab.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = crab.png; sourceTree = ""; }; + 047C651F2EBCAAAC0035E841 /* crab_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = crab_selected.png; sourceTree = ""; }; + 047C65202EBCAAAC0035E841 /* filter.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = filter.png; sourceTree = ""; }; + 047C65212EBCAAAC0035E841 /* football.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = football.png; sourceTree = ""; }; + 047C65222EBCAAAC0035E841 /* grape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = grape.png; sourceTree = ""; }; + 047C65232EBCAAAC0035E841 /* grape_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = grape_selected.png; sourceTree = ""; }; + 047C65242EBCAAAC0035E841 /* JXCategoryView.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = JXCategoryView.png; sourceTree = ""; }; + 047C65252EBCAAAC0035E841 /* JXCategoryViewStructure.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = JXCategoryViewStructure.png; sourceTree = ""; }; + 047C65262EBCAAAC0035E841 /* lobster.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lobster.png; sourceTree = ""; }; + 047C65272EBCAAAC0035E841 /* lobster_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lobster_selected.png; sourceTree = ""; }; + 047C65282EBCAAAC0035E841 /* lufei.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = lufei.jpg; sourceTree = ""; }; + 047C65292EBCAAAC0035E841 /* watermelon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = watermelon.png; sourceTree = ""; }; + 047C652A2EBCAAAC0035E841 /* watermelon_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = watermelon_selected.png; sourceTree = ""; }; + 047C654E2EBCBA9E0035E841 /* KBShopVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopVC.h; sourceTree = ""; }; + 047C654F2EBCBA9E0035E841 /* KBShopVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopVC.m; sourceTree = ""; }; + 047C65512EBCBAC60035E841 /* KBCommunityVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCommunityVC.h; sourceTree = ""; }; + 047C65522EBCBAC60035E841 /* KBCommunityVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCommunityVC.m; sourceTree = ""; }; + 047C65562EBCC06D0035E841 /* HomeRankCardCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankCardCell.h; sourceTree = ""; }; + 047C65572EBCC06D0035E841 /* HomeRankCardCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeRankCardCell.m; sourceTree = ""; }; + 047C655A2EBCD08E0035E841 /* UIView+KBShadow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+KBShadow.h"; sourceTree = ""; }; + 047C655B2EBCD08E0035E841 /* UIView+KBShadow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+KBShadow.m"; sourceTree = ""; }; + 047C655C2EBCD5B20035E841 /* UIImage+KBColor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+KBColor.h"; sourceTree = ""; }; + 047C655D2EBCD5B20035E841 /* UIImage+KBColor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+KBColor.m"; sourceTree = ""; }; + 048908BA2EBE1FCB00FABA60 /* BaseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseViewController.h; sourceTree = ""; }; + 048908BB2EBE1FCB00FABA60 /* BaseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseViewController.m; sourceTree = ""; }; + 048908C12EBE32B800FABA60 /* KBSearchVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchVC.h; sourceTree = ""; }; + 048908C22EBE32B800FABA60 /* KBSearchVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchVC.m; sourceTree = ""; }; + 048908C42EBE373500FABA60 /* KBSearchBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchBarView.h; sourceTree = ""; }; + 048908C52EBE373500FABA60 /* KBSearchBarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchBarView.m; sourceTree = ""; }; + 048908C62EBE373500FABA60 /* KBSearchSectionHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchSectionHeader.h; sourceTree = ""; }; + 048908C72EBE373500FABA60 /* KBSearchSectionHeader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchSectionHeader.m; sourceTree = ""; }; + 048908C82EBE373500FABA60 /* KBSkinCardCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinCardCell.h; sourceTree = ""; }; + 048908C92EBE373500FABA60 /* KBSkinCardCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinCardCell.m; sourceTree = ""; }; + 048908CA2EBE373500FABA60 /* KBTagCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTagCell.h; sourceTree = ""; }; + 048908CB2EBE373500FABA60 /* KBTagCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTagCell.m; sourceTree = ""; }; + 048908D02EBF611D00FABA60 /* KBHistoryMoreCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBHistoryMoreCell.h; sourceTree = ""; }; + 048908D12EBF611D00FABA60 /* KBHistoryMoreCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBHistoryMoreCell.m; sourceTree = ""; }; + 048908D72EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UICollectionViewLeftAlignedLayout.h; sourceTree = ""; }; + 048908D82EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UICollectionViewLeftAlignedLayout.m; sourceTree = ""; }; + 048908DB2EBF67EB00FABA60 /* KBSearchResultVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchResultVC.h; sourceTree = ""; }; + 048908DC2EBF67EB00FABA60 /* KBSearchResultVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchResultVC.m; sourceTree = ""; }; + 048908DE2EBF73DC00FABA60 /* MySkinVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MySkinVC.h; sourceTree = ""; }; + 048908DF2EBF73DC00FABA60 /* MySkinVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MySkinVC.m; sourceTree = ""; }; + 048908E12EBF760000FABA60 /* MySkinCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MySkinCell.h; sourceTree = ""; }; + 048908E12EBF821700FABA60 /* KBSkinDetailVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinDetailVC.h; sourceTree = ""; }; + 048908E22EBF760000FABA60 /* MySkinCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MySkinCell.m; sourceTree = ""; }; + 048908E22EBF821700FABA60 /* KBSkinDetailVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinDetailVC.m; sourceTree = ""; }; + 048908E42EBF841B00FABA60 /* KBSkinDetailTagCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinDetailTagCell.h; sourceTree = ""; }; + 048908E52EBF841B00FABA60 /* KBSkinDetailTagCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinDetailTagCell.m; sourceTree = ""; }; + 048908E72EBF843000FABA60 /* KBSkinDetailHeaderCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinDetailHeaderCell.h; sourceTree = ""; }; + 048908E82EBF843000FABA60 /* KBSkinDetailHeaderCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinDetailHeaderCell.m; sourceTree = ""; }; + 048908EA2EBF849300FABA60 /* KBSkinTagsContainerCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinTagsContainerCell.h; sourceTree = ""; }; + 048908EB2EBF849300FABA60 /* KBSkinTagsContainerCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinTagsContainerCell.m; sourceTree = ""; }; + 048908ED2EBF861800FABA60 /* KBSkinSectionTitleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinSectionTitleCell.h; sourceTree = ""; }; + 048908EE2EBF861800FABA60 /* KBSkinSectionTitleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinSectionTitleCell.m; sourceTree = ""; }; + 048908F02EC047FD00FABA60 /* KBShopHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopHeadView.h; sourceTree = ""; }; + 048908F12EC047FD00FABA60 /* KBShopHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopHeadView.m; sourceTree = ""; }; + 048908F32EC0496400FABA60 /* KBShopItemVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopItemVC.h; sourceTree = ""; }; + 048908F42EC0496400FABA60 /* KBShopItemVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopItemVC.m; sourceTree = ""; }; + 048908FC2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+KBEmptyView.h"; sourceTree = ""; }; + 048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+KBEmptyView.m"; sourceTree = ""; }; + 048909F02EC0AAAA00FABA60 /* KBCategoryTitleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleCell.h; sourceTree = ""; }; + 048909F12EC0AAAA00FABA60 /* KBCategoryTitleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleCell.m; sourceTree = ""; }; + 048909F22EC0AAAA00FABA60 /* KBCategoryTitleView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleView.h; sourceTree = ""; }; + 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleView.m; sourceTree = ""; }; + 04890A002EC0BBBB00FABA60 /* KBCategoryTitleImageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageCell.h; sourceTree = ""; }; + 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageCell.m; sourceTree = ""; }; + 04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageView.h; sourceTree = ""; }; + 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageView.m; sourceTree = ""; }; + 04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; sourceTree = ""; }; 04A9FE102EB4D0D20020DB6D /* KBFullAccessManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFullAccessManager.h; sourceTree = ""; }; 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFullAccessManager.m; sourceTree = ""; }; 04A9FE142EB873C80020DB6D /* UIViewController+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Extension.h"; sourceTree = ""; }; @@ -184,6 +361,10 @@ A1B2C4232EB4B7A100000001 /* KBKeyboardPermissionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyboardPermissionManager.h; sourceTree = ""; }; A1B2D7002EB8C00100000001 /* KBLangTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLangTestVC.h; sourceTree = ""; }; A1B2D7012EB8C00100000001 /* KBLangTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLangTestVC.m; sourceTree = ""; }; + A1B2E0012EBC7AAA00000001 /* KBTopThreeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTopThreeView.h; sourceTree = ""; }; + A1B2E0022EBC7AAA00000001 /* KBTopThreeView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTopThreeView.m; sourceTree = ""; }; + A1B2E0032EBC7AAA00000001 /* HomeHotCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHotCell.h; sourceTree = ""; }; + A1B2E0042EBC7AAA00000001 /* HomeHotCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHotCell.m; sourceTree = ""; }; B12EC429812407B9F0E67565 /* Pods-CustomKeyboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CustomKeyboard.release.xcconfig"; path = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.release.xcconfig"; sourceTree = ""; }; B8CA018AB878499327504AAD /* Pods-CustomKeyboard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CustomKeyboard.debug.xcconfig"; path = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.debug.xcconfig"; sourceTree = ""; }; F67DDBD716E4E616D8CC2C9C /* Pods-keyBoard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-keyBoard.debug.xcconfig"; path = "Target Support Files/Pods-keyBoard/Pods-keyBoard.debug.xcconfig"; sourceTree = ""; }; @@ -209,6 +390,231 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0477BD942EBAFF4E0055D639 /* Utils */ = { + isa = PBXGroup; + children = ( + 0477BD922EBAFF4E0055D639 /* KBURLOpenBridge.h */, + 0477BD932EBAFF4E0055D639 /* KBURLOpenBridge.m */, + ); + path = Utils; + sourceTree = ""; + }; + 0477BE012EBC6D420055D639 /* FunctionTest */ = { + isa = PBXGroup; + children = ( + 0477BDF52EBC63A80055D639 /* KBTestVC.h */, + 0477BDF62EBC63A80055D639 /* KBTestVC.m */, + A1B2D7002EB8C00100000001 /* KBLangTestVC.h */, + A1B2D7012EB8C00100000001 /* KBLangTestVC.m */, + 0459D1B22EBA284C00F2D189 /* KBSkinCenterVC.h */, + 0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */, + ); + path = FunctionTest; + sourceTree = ""; + }; + 047C65172EBCAAAC0035E841 /* Indicator */ = { + isa = PBXGroup; + children = ( + 047C65112EBCAAAC0035E841 /* boat.png */, + 047C65122EBCAAAC0035E841 /* city.png */, + 047C65132EBCAAAC0035E841 /* light.png */, + 047C65142EBCAAAC0035E841 /* lotus.png */, + 047C65152EBCAAAC0035E841 /* river.png */, + 047C65162EBCAAAC0035E841 /* seaWave.png */, + ); + path = Indicator; + sourceTree = ""; + }; + 047C652B2EBCAAAC0035E841 /* Images */ = { + isa = PBXGroup; + children = ( + 047C65172EBCAAAC0035E841 /* Indicator */, + 047C65182EBCAAAC0035E841 /* apple.png */, + 047C65192EBCAAAC0035E841 /* apple_selected.png */, + 047C651A2EBCAAAC0035E841 /* arrow_down.png */, + 047C651B2EBCAAAC0035E841 /* arrow_up.png */, + 047C651C2EBCAAAC0035E841 /* carrot.png */, + 047C651D2EBCAAAC0035E841 /* carrot_selected.png */, + 047C651E2EBCAAAC0035E841 /* crab.png */, + 047C651F2EBCAAAC0035E841 /* crab_selected.png */, + 047C65202EBCAAAC0035E841 /* filter.png */, + 047C65212EBCAAAC0035E841 /* football.png */, + 047C65222EBCAAAC0035E841 /* grape.png */, + 047C65232EBCAAAC0035E841 /* grape_selected.png */, + 047C65242EBCAAAC0035E841 /* JXCategoryView.png */, + 047C65252EBCAAAC0035E841 /* JXCategoryViewStructure.png */, + 047C65262EBCAAAC0035E841 /* lobster.png */, + 047C65272EBCAAAC0035E841 /* lobster_selected.png */, + 047C65282EBCAAAC0035E841 /* lufei.jpg */, + 047C65292EBCAAAC0035E841 /* watermelon.png */, + 047C652A2EBCAAAC0035E841 /* watermelon_selected.png */, + ); + path = Images; + sourceTree = ""; + }; + 047C652C2EBCAAAC0035E841 /* Resource */ = { + isa = PBXGroup; + children = ( + 047C652B2EBCAAAC0035E841 /* Images */, + ); + path = Resource; + sourceTree = ""; + }; + 047C65462EBCBA880035E841 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 047C65472EBCBA880035E841 /* V */ = { + isa = PBXGroup; + children = ( + ); + path = V; + sourceTree = ""; + }; + 047C65482EBCBA880035E841 /* VC */ = { + isa = PBXGroup; + children = ( + 047C65512EBCBAC60035E841 /* KBCommunityVC.h */, + 047C65522EBCBAC60035E841 /* KBCommunityVC.m */, + ); + path = VC; + sourceTree = ""; + }; + 047C65492EBCBA880035E841 /* Community */ = { + isa = PBXGroup; + children = ( + 047C65462EBCBA880035E841 /* M */, + 047C65472EBCBA880035E841 /* V */, + 047C65482EBCBA880035E841 /* VC */, + ); + path = Community; + sourceTree = ""; + }; + 047C654A2EBCBA880035E841 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 047C654B2EBCBA880035E841 /* V */ = { + isa = PBXGroup; + children = ( + 048908F02EC047FD00FABA60 /* KBShopHeadView.h */, + 048908F12EC047FD00FABA60 /* KBShopHeadView.m */, + 048909F02EC0AAAA00FABA60 /* KBCategoryTitleCell.h */, + 048909F12EC0AAAA00FABA60 /* KBCategoryTitleCell.m */, + 048909F22EC0AAAA00FABA60 /* KBCategoryTitleView.h */, + 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */, + 04890A002EC0BBBB00FABA60 /* KBCategoryTitleImageCell.h */, + 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */, + 04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */, + 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */, + ); + path = V; + sourceTree = ""; + }; + 047C654C2EBCBA880035E841 /* VC */ = { + isa = PBXGroup; + children = ( + 047C654E2EBCBA9E0035E841 /* KBShopVC.h */, + 047C654F2EBCBA9E0035E841 /* KBShopVC.m */, + 048908F32EC0496400FABA60 /* KBShopItemVC.h */, + 048908F42EC0496400FABA60 /* KBShopItemVC.m */, + ); + path = VC; + sourceTree = ""; + }; + 047C654D2EBCBA880035E841 /* Shop */ = { + isa = PBXGroup; + children = ( + 047C654A2EBCBA880035E841 /* M */, + 047C654B2EBCBA880035E841 /* V */, + 047C654C2EBCBA880035E841 /* VC */, + ); + path = Shop; + sourceTree = ""; + }; + 048908B82EBDC11200FABA60 /* V */ = { + isa = PBXGroup; + children = ( + ); + path = V; + sourceTree = ""; + }; + 048908B92EBDC11200FABA60 /* Common */ = { + isa = PBXGroup; + children = ( + 048908B82EBDC11200FABA60 /* V */, + ); + path = Common; + sourceTree = ""; + }; + 048908BD2EBE329D00FABA60 /* M */ = { + isa = PBXGroup; + children = ( + ); + path = M; + sourceTree = ""; + }; + 048908BE2EBE329D00FABA60 /* V */ = { + isa = PBXGroup; + children = ( + 048908C42EBE373500FABA60 /* KBSearchBarView.h */, + 048908C52EBE373500FABA60 /* KBSearchBarView.m */, + 048908C62EBE373500FABA60 /* KBSearchSectionHeader.h */, + 048908C72EBE373500FABA60 /* KBSearchSectionHeader.m */, + 048908C82EBE373500FABA60 /* KBSkinCardCell.h */, + 048908C92EBE373500FABA60 /* KBSkinCardCell.m */, + 048908D02EBF611D00FABA60 /* KBHistoryMoreCell.h */, + 048908D12EBF611D00FABA60 /* KBHistoryMoreCell.m */, + 048908CA2EBE373500FABA60 /* KBTagCell.h */, + 048908CB2EBE373500FABA60 /* KBTagCell.m */, + ); + path = V; + sourceTree = ""; + }; + 048908BF2EBE329D00FABA60 /* VC */ = { + isa = PBXGroup; + children = ( + 048908C12EBE32B800FABA60 /* KBSearchVC.h */, + 048908C22EBE32B800FABA60 /* KBSearchVC.m */, + 048908DB2EBF67EB00FABA60 /* KBSearchResultVC.h */, + 048908DC2EBF67EB00FABA60 /* KBSearchResultVC.m */, + ); + path = VC; + sourceTree = ""; + }; + 048908C02EBE329D00FABA60 /* Search */ = { + isa = PBXGroup; + children = ( + 048908BD2EBE329D00FABA60 /* M */, + 048908BE2EBE329D00FABA60 /* V */, + 048908BF2EBE329D00FABA60 /* VC */, + ); + path = Search; + sourceTree = ""; + }; + 048908D32EBF618E00FABA60 /* Vender */ = { + isa = PBXGroup; + children = ( + 048908D92EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout */, + ); + path = Vender; + sourceTree = ""; + }; + 048908D92EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout */ = { + isa = PBXGroup; + children = ( + 048908D72EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.h */, + 048908D82EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m */, + ); + path = UICollectionViewLeftAlignedLayout; + sourceTree = ""; + }; 04A9FE122EB4D0D20020DB6D /* Manager */ = { isa = PBXGroup; children = ( @@ -249,6 +655,7 @@ 04C6EAD72EAF870B0089C901 /* CustomKeyboard */ = { isa = PBXGroup; children = ( + 0477BD942EBAFF4E0055D639 /* Utils */, 04A9FE122EB4D0D20020DB6D /* Manager */, 04FC95662EB0546C007BD342 /* Model */, 04C6EADA2EAF8C7B0089C901 /* View */, @@ -266,6 +673,7 @@ children = ( 04C6EADB2EAF8CEB0089C901 /* KBToolBar.h */, 04C6EADC2EAF8CEB0089C901 /* KBToolBar.m */, + 04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */, 04FC95682EB05497007BD342 /* KBKeyButton.h */, 04FC95692EB05497007BD342 /* KBKeyButton.m */, 04FC956B2EB054B7007BD342 /* KBKeyboardView.h */, @@ -316,6 +724,20 @@ 04FC95B42EB1E3B1007BD342 /* V */ = { isa = PBXGroup; children = ( + 0477BDF12EBB7B850055D639 /* KBDirectionIndicatorView.h */, + 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */, + 0477BDF82EBC66340055D639 /* HomeHeadView.h */, + 0477BDF92EBC66340055D639 /* HomeHeadView.m */, + 0477BEA02EBCF0000055D639 /* KBTopImageButton.h */, + 0477BEA12EBCF0000055D639 /* KBTopImageButton.m */, + A1B2E0012EBC7AAA00000001 /* KBTopThreeView.h */, + A1B2E0022EBC7AAA00000001 /* KBTopThreeView.m */, + A1B2E0032EBC7AAA00000001 /* HomeHotCell.h */, + A1B2E0042EBC7AAA00000001 /* HomeHotCell.m */, + 047C650B2EBC8A840035E841 /* KBPanModalView.h */, + 047C650C2EBC8A840035E841 /* KBPanModalView.m */, + 047C65562EBCC06D0035E841 /* HomeRankCardCell.h */, + 047C65572EBCC06D0035E841 /* HomeRankCardCell.m */, ); path = V; sourceTree = ""; @@ -325,8 +747,17 @@ children = ( 04FC95CD2EB1E7A1007BD342 /* HomeVC.h */, 04FC95CE2EB1E7A1007BD342 /* HomeVC.m */, - A1B2D7002EB8C00100000001 /* KBLangTestVC.h */, - A1B2D7012EB8C00100000001 /* KBLangTestVC.m */, + 0477BE022EBC83130055D639 /* HomeMainVC.h */, + 0477BE032EBC83130055D639 /* HomeMainVC.m */, + 0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */, + 0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */, + 0477BDFB2EBC6A170055D639 /* HomeHotVC.h */, + 0477BDFC2EBC6A170055D639 /* HomeHotVC.m */, + 0477BDFE2EBC6A330055D639 /* HomeRankVC.h */, + 0477BDFF2EBC6A330055D639 /* HomeRankVC.m */, + 047C650E2EBCA8DD0035E841 /* HomeRankContentVC.h */, + 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */, + 0477BE012EBC6D420055D639 /* FunctionTest */, ); path = VC; sourceTree = ""; @@ -382,6 +813,16 @@ 04FC95BC2EB1E3B1007BD342 /* V */ = { isa = PBXGroup; children = ( + 048908E12EBF760000FABA60 /* MySkinCell.h */, + 048908E22EBF760000FABA60 /* MySkinCell.m */, + 048908E42EBF841B00FABA60 /* KBSkinDetailTagCell.h */, + 048908E52EBF841B00FABA60 /* KBSkinDetailTagCell.m */, + 048908E72EBF843000FABA60 /* KBSkinDetailHeaderCell.h */, + 048908E82EBF843000FABA60 /* KBSkinDetailHeaderCell.m */, + 048908EA2EBF849300FABA60 /* KBSkinTagsContainerCell.h */, + 048908EB2EBF849300FABA60 /* KBSkinTagsContainerCell.m */, + 048908ED2EBF861800FABA60 /* KBSkinSectionTitleCell.h */, + 048908EE2EBF861800FABA60 /* KBSkinSectionTitleCell.m */, ); path = V; sourceTree = ""; @@ -391,6 +832,10 @@ children = ( 04FC95D02EB1E7AE007BD342 /* MyVC.h */, 04FC95D12EB1E7AE007BD342 /* MyVC.m */, + 048908DE2EBF73DC00FABA60 /* MySkinVC.h */, + 048908DF2EBF73DC00FABA60 /* MySkinVC.m */, + 048908E12EBF821700FABA60 /* KBSkinDetailVC.h */, + 048908E22EBF821700FABA60 /* KBSkinDetailVC.m */, ); path = VC; sourceTree = ""; @@ -408,6 +853,14 @@ 04FC95BF2EB1E3B1007BD342 /* Class */ = { isa = PBXGroup; children = ( + 048908D32EBF618E00FABA60 /* Vender */, + 048908C02EBE329D00FABA60 /* Search */, + 048908B92EBDC11200FABA60 /* Common */, + 04FC95B62EB1E3B1007BD342 /* Home */, + 047C654D2EBCBA880035E841 /* Shop */, + 047C65492EBCBA880035E841 /* Community */, + 04FC95BE2EB1E3B1007BD342 /* Me */, + 047C652C2EBCAAAC0035E841 /* Resource */, 04FC95EE2EB3399D007BD342 /* Manager */, 04FC95ED2EB33611007BD342 /* Login */, 04FC95E82EB23B67007BD342 /* Network */, @@ -415,8 +868,6 @@ 04FC95E12EB20AD1007BD342 /* Guard */, 04FC95C62EB1E4AB007BD342 /* Base */, 04FC95BA2EB1E3B1007BD342 /* Main */, - 04FC95B62EB1E3B1007BD342 /* Home */, - 04FC95BE2EB1E3B1007BD342 /* Me */, ); path = Class; sourceTree = ""; @@ -435,6 +886,8 @@ 04FC95D42EB1EA16007BD342 /* BaseCell.m */, 04FC95D52EB1EA16007BD342 /* BaseTableView.h */, 04FC95D62EB1EA16007BD342 /* BaseTableView.m */, + 048908FC2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.h */, + 048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */, ); path = V; sourceTree = ""; @@ -446,6 +899,8 @@ 04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */, 04FC95CA2EB1E780007BD342 /* BaseTabBarController.h */, 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */, + 048908BA2EBE1FCB00FABA60 /* BaseViewController.h */, + 048908BB2EBE1FCB00FABA60 /* BaseViewController.m */, ); path = VC; sourceTree = ""; @@ -512,6 +967,10 @@ 04FC97082EB31B14007BD342 /* KBHUD.m */, 04A9FE142EB873C80020DB6D /* UIViewController+Extension.h */, 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */, + 047C655A2EBCD08E0035E841 /* UIView+KBShadow.h */, + 047C655B2EBCD08E0035E841 /* UIView+KBShadow.m */, + 047C655C2EBCD5B20035E841 /* UIImage+KBColor.h */, + 047C655D2EBCD5B20035E841 /* UIImage+KBColor.m */, ); path = Categories; sourceTree = ""; @@ -580,6 +1039,8 @@ A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */, 04A9FE182EB892460020DB6D /* KBLocalizationManager.h */, 04A9FE192EB892460020DB6D /* KBLocalizationManager.m */, + 0459D1B52EBA287900F2D189 /* KBSkinManager.h */, + 0459D1B62EBA287900F2D189 /* KBSkinManager.m */, ); path = Shared; sourceTree = ""; @@ -729,6 +1190,31 @@ buildActionMask = 2147483647; files = ( 04C6EABA2EAF86530089C901 /* Assets.xcassets in Resources */, + 047C652D2EBCAAAC0035E841 /* crab_selected.png in Resources */, + 047C652E2EBCAAAC0035E841 /* crab.png in Resources */, + 047C652F2EBCAAAC0035E841 /* arrow_down.png in Resources */, + 047C65302EBCAAAC0035E841 /* football.png in Resources */, + 047C65312EBCAAAC0035E841 /* city.png in Resources */, + 047C65322EBCAAAC0035E841 /* apple_selected.png in Resources */, + 047C65332EBCAAAC0035E841 /* carrot.png in Resources */, + 047C65342EBCAAAC0035E841 /* lobster.png in Resources */, + 047C65352EBCAAAC0035E841 /* lufei.jpg in Resources */, + 047C65362EBCAAAC0035E841 /* river.png in Resources */, + 047C65372EBCAAAC0035E841 /* watermelon_selected.png in Resources */, + 047C65382EBCAAAC0035E841 /* JXCategoryView.png in Resources */, + 047C65392EBCAAAC0035E841 /* JXCategoryViewStructure.png in Resources */, + 047C653A2EBCAAAC0035E841 /* arrow_up.png in Resources */, + 047C653B2EBCAAAC0035E841 /* boat.png in Resources */, + 047C653C2EBCAAAC0035E841 /* grape_selected.png in Resources */, + 047C653D2EBCAAAC0035E841 /* lobster_selected.png in Resources */, + 047C653E2EBCAAAC0035E841 /* light.png in Resources */, + 047C653F2EBCAAAC0035E841 /* seaWave.png in Resources */, + 047C65402EBCAAAC0035E841 /* watermelon.png in Resources */, + 047C65412EBCAAAC0035E841 /* lotus.png in Resources */, + 047C65422EBCAAAC0035E841 /* grape.png in Resources */, + 047C65432EBCAAAC0035E841 /* filter.png in Resources */, + 047C65442EBCAAAC0035E841 /* apple.png in Resources */, + 047C65452EBCAAAC0035E841 /* carrot_selected.png in Resources */, 04A9FE212EB893F10020DB6D /* Localizable.strings in Resources */, 04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */, 04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */, @@ -815,6 +1301,7 @@ 04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */, 04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */, 04C6EAD82EAF870B0089C901 /* KeyboardViewController.m in Sources */, + 0459D1B82EBA287900F2D189 /* KBSkinManager.m in Sources */, 04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */, A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */, 04A9FE1A2EB892460020DB6D /* KBLocalizationManager.m in Sources */, @@ -828,6 +1315,7 @@ A1B2C4002EB4A0A100000003 /* KBAuthManager.m in Sources */, 04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */, A1B2C4202EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */, + 0477BD952EBAFF4E0055D639 /* KBURLOpenBridge.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -835,33 +1323,75 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */, + 048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */, + 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */, + 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */, 04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */, 04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */, + 047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */, + 0477BE002EBC6A330055D639 /* HomeRankVC.m in Sources */, + 047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */, 043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */, 04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */, 04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */, 04FC95F12EB339A7007BD342 /* LoginViewController.m in Sources */, + 048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */, 04FC96142EB34E00007BD342 /* KBLoginSheetViewController.m in Sources */, 04A9FE1B2EB892460020DB6D /* KBLocalizationManager.m in Sources */, + 048908BC2EBE1FCB00FABA60 /* BaseViewController.m in Sources */, 04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */, + 048908EF2EBF861800FABA60 /* KBSkinSectionTitleCell.m in Sources */, + 048908E32EBF821700FABA60 /* KBSkinDetailVC.m in Sources */, + 0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */, + 048908D22EBF611D00FABA60 /* KBHistoryMoreCell.m in Sources */, 04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */, + 0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */, 04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */, + 048908DD2EBF67EB00FABA60 /* KBSearchResultVC.m in Sources */, + 047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */, + 047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */, + 048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */, + 047C655E2EBCD5B20035E841 /* UIImage+KBColor.m in Sources */, 04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */, 04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */, + 048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */, + 048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */, + 048908EC2EBF849300FABA60 /* KBSkinTagsContainerCell.m in Sources */, + 0477BDF02EBB76E30055D639 /* HomeSheetVC.m in Sources */, + 048908E62EBF841B00FABA60 /* KBSkinDetailTagCell.m in Sources */, 04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */, + 0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */, 04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */, 04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */, 04FC97092EB31B14007BD342 /* KBHUD.m in Sources */, 04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */, + 048908FE2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m in Sources */, 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */, 04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */, A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */, + 048908DA2EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m in Sources */, 04C6EABF2EAF86530089C901 /* main.m in Sources */, 04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */, + 047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */, + 0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */, + 0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */, + 048908CC2EBE373500FABA60 /* KBSearchBarView.m in Sources */, + 048908CD2EBE373500FABA60 /* KBSearchSectionHeader.m in Sources */, + 048908CE2EBE373500FABA60 /* KBSkinCardCell.m in Sources */, + 048908CF2EBE373500FABA60 /* KBTagCell.m in Sources */, + 0477BEA22EBCF0000055D639 /* KBTopImageButton.m in Sources */, + A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */, + A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */, + 0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */, + 048908F52EC0496400FABA60 /* KBShopItemVC.m in Sources */, 04FC95F42EB339C1007BD342 /* AppleSignInManager.m in Sources */, 04C6EAC12EAF86530089C901 /* ViewController.m in Sources */, A1B2C4002EB4A0A100000004 /* KBAuthManager.m in Sources */, + 047C65532EBCBAC60035E841 /* KBCommunityVC.m in Sources */, A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */, + 0459D1B42EBA284C00F2D189 /* KBSkinCenterVC.m in Sources */, + 048908E32EBF760000FABA60 /* MySkinCell.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -989,11 +1519,12 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = keyBoard/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "YOLO输入法"; - INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.loveKey.nyx.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboard\n );\n}"; + INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.loveKey.nyx.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboardAppExtension\n );\n}"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UIUserInterfaceStyle = Light; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1032,11 +1563,12 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = keyBoard/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "YOLO输入法"; - INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.loveKey.nyx.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboard\n );\n}"; + INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.loveKey.nyx.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboardAppExtension\n );\n}"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UIUserInterfaceStyle = Light; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/keyBoard.xcodeproj/xcshareddata/xcschemes/keyBoard.xcscheme b/keyBoard.xcodeproj/xcshareddata/xcschemes/keyBoard.xcscheme index 4b87720..5988250 100644 --- a/keyBoard.xcodeproj/xcshareddata/xcschemes/keyBoard.xcscheme +++ b/keyBoard.xcodeproj/xcshareddata/xcschemes/keyBoard.xcscheme @@ -1,7 +1,7 @@ + version = "1.3"> @@ -27,8 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - + + @@ -87,4 +87,3 @@ revealArchiveInOrganizer = "YES"> - diff --git a/keyBoard/AppDelegate.m b/keyBoard/AppDelegate.m index 31b7514..1d9511b 100644 --- a/keyBoard/AppDelegate.m +++ b/keyBoard/AppDelegate.m @@ -61,10 +61,25 @@ static NSString * const kKBKeyboardExtensionBundleId = @"com.loveKey.nyx.CustomK #pragma mark - Deep Link +- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler { + if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { + NSURL *url = userActivity.webpageURL; + if (!url) return NO; + NSString *host = url.host.lowercaseString ?: @""; + if ([host hasSuffix:@"app.tknb.net"]) { + NSString *path = url.path.lowercaseString ?: @""; + if ([path hasPrefix:@"/ul/settings"]) { [self kb_openAppSettings]; return YES; } + if ([path hasPrefix:@"/ul/login"]) { [self kb_presentLoginSheetIfNeeded]; return YES; } + } + } + return NO; +} + // iOS 9+ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { if (!url) return NO; - if ([[url.scheme lowercaseString] isEqualToString:@"kbkeyboard"]) { + // 注意:已对 scheme 做了小写化,比较值也应为小写 + if ([[url.scheme lowercaseString] isEqualToString:@"kbkeyboardappextension"]) { NSString *urlHost = url.host ?: @""; NSString *host = [urlHost lowercaseString]; if ([host isEqualToString:@"login"]) { // kbkeyboard://login diff --git a/keyBoard/Assets.xcassets/Home/Contents.json b/keyBoard/Assets.xcassets/Home/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/Contents.json new file mode 100644 index 0000000..97751b0 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "get_ppd_btn@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "get_ppd_btn@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/get_ppd_btn@2x.png b/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/get_ppd_btn@2x.png new file mode 100644 index 0000000..75ccc0e Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/get_ppd_btn@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/get_ppd_btn@3x.png b/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/get_ppd_btn@3x.png new file mode 100644 index 0000000..b995a30 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/get_ppd_btn.imageset/get_ppd_btn@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/Contents.json new file mode 100644 index 0000000..10a98fd --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hoem_love_key@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hoem_love_key@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/hoem_love_key@2x.png b/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/hoem_love_key@2x.png new file mode 100644 index 0000000..4f1f2e1 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/hoem_love_key@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/hoem_love_key@3x.png b/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/hoem_love_key@3x.png new file mode 100644 index 0000000..a76dd63 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/hoem_love_key.imageset/hoem_love_key@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/Contents.json new file mode 100644 index 0000000..5c5e11f --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_ai_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_ai_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/home_ai_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/home_ai_icon@2x.png new file mode 100644 index 0000000..e334153 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/home_ai_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/home_ai_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/home_ai_icon@3x.png new file mode 100644 index 0000000..1a4867e Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_ai_icon.imageset/home_ai_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/Contents.json new file mode 100644 index 0000000..d3f2079 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "home_bar_underline.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_bar_underline 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_bar_underline 2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline 1.png b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline 1.png new file mode 100644 index 0000000..3658ff5 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline 1.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline 2.png b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline 2.png new file mode 100644 index 0000000..3658ff5 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline 2.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline.png b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline.png new file mode 100644 index 0000000..3658ff5 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_bar_underline.imageset/home_bar_underline.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/Contents.json new file mode 100644 index 0000000..d357bcc --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_bg_image 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_bg_image 2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/home_bg_image 1.png b/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/home_bg_image 1.png new file mode 100644 index 0000000..52a267f Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/home_bg_image 1.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/home_bg_image 2.png b/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/home_bg_image 2.png new file mode 100644 index 0000000..52a267f Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_bg_image.imageset/home_bg_image 2.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/Contents.json new file mode 100644 index 0000000..f7f7caa --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_chat_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_chat_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/home_chat_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/home_chat_icon@2x.png new file mode 100644 index 0000000..09dd0b9 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/home_chat_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/home_chat_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/home_chat_icon@3x.png new file mode 100644 index 0000000..762cf2d Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_chat_icon.imageset/home_chat_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_down_arrow.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_down_arrow.imageset/Contents.json new file mode 100644 index 0000000..d5f9251 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_down_arrow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "home_down_arrow.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_down_arrow.imageset/home_down_arrow.png b/keyBoard/Assets.xcassets/Home/home_down_arrow.imageset/home_down_arrow.png new file mode 100644 index 0000000..60c653c Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_down_arrow.imageset/home_down_arrow.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/Contents.json new file mode 100644 index 0000000..37c6f7c --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_emotion_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_emotion_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/home_emotion_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/home_emotion_icon@2x.png new file mode 100644 index 0000000..511516c Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/home_emotion_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/home_emotion_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/home_emotion_icon@3x.png new file mode 100644 index 0000000..ed641e9 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_emotion_icon.imageset/home_emotion_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/Contents.json new file mode 100644 index 0000000..9411071 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_hg_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_hg_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/home_hg_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/home_hg_icon@2x.png new file mode 100644 index 0000000..1cb0e2b Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/home_hg_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/home_hg_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/home_hg_icon@3x.png new file mode 100644 index 0000000..1c68189 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_hg_icon.imageset/home_hg_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/Contents.json new file mode 100644 index 0000000..94cd72b --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_item_normal@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_item_normal@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/home_item_normal@2x.png b/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/home_item_normal@2x.png new file mode 100644 index 0000000..542f6f4 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/home_item_normal@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/home_item_normal@3x.png b/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/home_item_normal@3x.png new file mode 100644 index 0000000..2910a80 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_item_normal.imageset/home_item_normal@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/Contents.json new file mode 100644 index 0000000..55dcdc2 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_item_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_item_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/home_item_selected@2x.png b/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/home_item_selected@2x.png new file mode 100644 index 0000000..e647e4e Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/home_item_selected@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/home_item_selected@3x.png b/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/home_item_selected@3x.png new file mode 100644 index 0000000..b868e13 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_item_selected.imageset/home_item_selected@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/Contents.json new file mode 100644 index 0000000..a1613b4 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_keyboard_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_keyboard_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/home_keyboard_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/home_keyboard_icon@2x.png new file mode 100644 index 0000000..7b21e24 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/home_keyboard_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/home_keyboard_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/home_keyboard_icon@3x.png new file mode 100644 index 0000000..91ae8fa Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_keyboard_icon.imageset/home_keyboard_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_left_bg.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_left_bg.imageset/Contents.json new file mode 100644 index 0000000..9a26c26 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_left_bg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "home_left_bg.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_left_bg.imageset/home_left_bg.png b/keyBoard/Assets.xcassets/Home/home_left_bg.imageset/home_left_bg.png new file mode 100644 index 0000000..9d3ddc8 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_left_bg.imageset/home_left_bg.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/Contents.json new file mode 100644 index 0000000..f018f56 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_person_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_person_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/home_person_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/home_person_icon@2x.png new file mode 100644 index 0000000..2481ac6 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/home_person_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/home_person_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/home_person_icon@3x.png new file mode 100644 index 0000000..89cfb46 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_person_icon.imageset/home_person_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/Contents.json new file mode 100644 index 0000000..dfad0fe --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_rank_1@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_rank_1@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/home_rank_1@2x.png b/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/home_rank_1@2x.png new file mode 100644 index 0000000..c47599a Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/home_rank_1@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/home_rank_1@3x.png b/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/home_rank_1@3x.png new file mode 100644 index 0000000..6016a35 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_rank_1.imageset/home_rank_1@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/Contents.json new file mode 100644 index 0000000..90ba1f8 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_rank_2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_rank_2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/home_rank_2@2x.png b/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/home_rank_2@2x.png new file mode 100644 index 0000000..68a37c1 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/home_rank_2@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/home_rank_2@3x.png b/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/home_rank_2@3x.png new file mode 100644 index 0000000..f8b8958 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_rank_2.imageset/home_rank_2@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/Contents.json new file mode 100644 index 0000000..2548fdc --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_rank_3@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_rank_3@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/home_rank_3@2x.png b/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/home_rank_3@2x.png new file mode 100644 index 0000000..d9530bd Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/home_rank_3@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/home_rank_3@3x.png b/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/home_rank_3@3x.png new file mode 100644 index 0000000..267bfff Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_rank_3.imageset/home_rank_3@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_right_bg.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_right_bg.imageset/Contents.json new file mode 100644 index 0000000..88d79a3 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_right_bg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "home_right_bg.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_right_bg.imageset/home_right_bg.png b/keyBoard/Assets.xcassets/Home/home_right_bg.imageset/home_right_bg.png new file mode 100644 index 0000000..4972b28 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_right_bg.imageset/home_right_bg.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/Contents.json new file mode 100644 index 0000000..9a363b0 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "home_topvip_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "home_topvip_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/home_topvip_icon@2x.png b/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/home_topvip_icon@2x.png new file mode 100644 index 0000000..e5b93d6 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/home_topvip_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/home_topvip_icon@3x.png b/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/home_topvip_icon@3x.png new file mode 100644 index 0000000..fd556ee Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_topvip_icon.imageset/home_topvip_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Home/home_up_arrow.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/home_up_arrow.imageset/Contents.json new file mode 100644 index 0000000..9e7d2e1 --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/home_up_arrow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "home_up_arrow.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/home_up_arrow.imageset/home_up_arrow.png b/keyBoard/Assets.xcassets/Home/home_up_arrow.imageset/home_up_arrow.png new file mode 100644 index 0000000..6076766 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/home_up_arrow.imageset/home_up_arrow.png differ diff --git a/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/Contents.json new file mode 100644 index 0000000..4494def --- /dev/null +++ b/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "recharge_now_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "recharge_now_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/recharge_now_icon@2x.png b/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/recharge_now_icon@2x.png new file mode 100644 index 0000000..f525fe2 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/recharge_now_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/recharge_now_icon@3x.png b/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/recharge_now_icon@3x.png new file mode 100644 index 0000000..b244847 Binary files /dev/null and b/keyBoard/Assets.xcassets/Home/recharge_now_icon.imageset/recharge_now_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/Contents.json b/keyBoard/Assets.xcassets/Tabbar/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/Contents.json new file mode 100644 index 0000000..7af5406 --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_home@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_home@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/tab_home@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/tab_home@2x.png new file mode 100644 index 0000000..54341f2 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/tab_home@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/tab_home@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/tab_home@3x.png new file mode 100644 index 0000000..ab6b987 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_home.imageset/tab_home@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/Contents.json new file mode 100644 index 0000000..ebc818b --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_home_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_home_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/tab_home_selected@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/tab_home_selected@2x.png new file mode 100644 index 0000000..fa0f28d Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/tab_home_selected@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/tab_home_selected@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/tab_home_selected@3x.png new file mode 100644 index 0000000..1579dad Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_home_selected.imageset/tab_home_selected@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/Contents.json new file mode 100644 index 0000000..46617d7 --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_my@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_my@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/tab_my@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/tab_my@2x.png new file mode 100644 index 0000000..c769634 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/tab_my@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/tab_my@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/tab_my@3x.png new file mode 100644 index 0000000..9f9d55a Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_my.imageset/tab_my@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/Contents.json new file mode 100644 index 0000000..96d8332 --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_my_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_my_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/tab_my_selected@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/tab_my_selected@2x.png new file mode 100644 index 0000000..9afd604 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/tab_my_selected@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/tab_my_selected@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/tab_my_selected@3x.png new file mode 100644 index 0000000..79483e3 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_my_selected.imageset/tab_my_selected@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/Contents.json new file mode 100644 index 0000000..94e016f --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_shequ@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_shequ@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/tab_shequ@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/tab_shequ@2x.png new file mode 100644 index 0000000..1298c86 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/tab_shequ@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/tab_shequ@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/tab_shequ@3x.png new file mode 100644 index 0000000..78f9d1b Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shequ.imageset/tab_shequ@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/Contents.json new file mode 100644 index 0000000..e509d9b --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_shequ_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_shequ_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/tab_shequ_selected@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/tab_shequ_selected@2x.png new file mode 100644 index 0000000..6177181 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/tab_shequ_selected@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/tab_shequ_selected@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/tab_shequ_selected@3x.png new file mode 100644 index 0000000..f0c0a08 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shequ_selected.imageset/tab_shequ_selected@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/Contents.json new file mode 100644 index 0000000..b5f1900 --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_shop@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_shop@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/tab_shop@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/tab_shop@2x.png new file mode 100644 index 0000000..4836fee Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/tab_shop@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/tab_shop@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/tab_shop@3x.png new file mode 100644 index 0000000..a980981 Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shop.imageset/tab_shop@3x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/Contents.json b/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/Contents.json new file mode 100644 index 0000000..52f0b4a --- /dev/null +++ b/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tab_shop_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "tab_shop_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/tab_shop_selected@2x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/tab_shop_selected@2x.png new file mode 100644 index 0000000..4478dca Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/tab_shop_selected@2x.png differ diff --git a/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/tab_shop_selected@3x.png b/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/tab_shop_selected@3x.png new file mode 100644 index 0000000..baa22ac Binary files /dev/null and b/keyBoard/Assets.xcassets/Tabbar/tab_shop_selected.imageset/tab_shop_selected@3x.png differ diff --git a/keyBoard/Class/Base/V/BaseTableView.h b/keyBoard/Class/Base/V/BaseTableView.h index 9395838..b6777a7 100644 --- a/keyBoard/Class/Base/V/BaseTableView.h +++ b/keyBoard/Class/Base/V/BaseTableView.h @@ -40,6 +40,22 @@ typedef void(^KBEmptyAction)(void); /// 触发刷新空数据视图(若集成了 DZNEmptyDataSet 则调用其 reloadEmptyDataSet) - (void)kb_reloadEmptyDataSet; +/// 使用 LYEmptyView 在表格页快速挂载一套统一样式的空态视图(与 DZNEmptyDataSet 二选一) +/// 注意:调用该方法会自动关闭本类内置的 DZNEmptyDataSet(useEmptyDataSet = NO),避免冲突。 +/// - Parameters: +/// - image: 占位图(可空) +/// - title: 标题(默认“暂无数据”) +/// - detail: 描述(可空) +/// - buttonTitle: 按钮标题(可空,传空则不展示按钮) +/// - tapHandler: 点击空白区域回调(可空) +/// - buttonHandler: 按钮点击回调(可空) +- (void)kb_makeDefaultEmptyViewWithImage:(nullable UIImage *)image + title:(nullable NSString *)title + detail:(nullable NSString *)detail + buttonTitle:(nullable NSString *)buttonTitle + tapHandler:(nullable KBEmptyAction)tapHandler + buttonHandler:(nullable KBEmptyAction)buttonHandler; + @end NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Base/V/BaseTableView.m b/keyBoard/Class/Base/V/BaseTableView.m index 0d743e3..ff1e49f 100644 --- a/keyBoard/Class/Base/V/BaseTableView.m +++ b/keyBoard/Class/Base/V/BaseTableView.m @@ -13,6 +13,15 @@ #define KB_HAS_DZN 0 #endif +// 可选引入:LYEmptyView(通过 Pod 集成),用于空态视图的“自动显隐+属性配置”方案 +#if __has_include() +#import +#import +#define KB_HAS_LY 1 +#else +#define KB_HAS_LY 0 +#endif + @interface BaseTableView () #if KB_HAS_DZN @@ -127,4 +136,66 @@ #endif +// MARK: - LYEmptyView 快速挂载(与 DZN 二选一) +- (void)kb_makeDefaultEmptyViewWithImage:(UIImage *)image + title:(NSString *)title + detail:(NSString *)detail + buttonTitle:(NSString *)buttonTitle + tapHandler:(KBEmptyAction)tapHandler + buttonHandler:(KBEmptyAction)buttonHandler { +#if KB_HAS_LY + // 关闭 DZN,避免两套空态叠加 + self.useEmptyDataSet = NO; + + // 默认文案 + NSString *t = title ?: @"暂无数据"; + + LYEmptyView *ev = nil; + if (buttonTitle.length > 0) { + // 带按钮(优先 block 方式) + __weak typeof(self) weakSelf = self; + ev = [LYEmptyView emptyActionViewWithImage:image + titleStr:t + detailStr:detail ?: @"" + btnTitleStr:buttonTitle + btnClickBlock:^{ if (buttonHandler) buttonHandler(); [weakSelf setNeedsLayout]; }]; + } else { + // 无按钮 + ev = [LYEmptyView emptyViewWithImage:image titleStr:t detailStr:detail ?: @""]; + } + + // 点击空白区域 + if (tapHandler) { + ev.tapEmptyViewBlock = ^{ tapHandler(); }; + } + + // 统一样式(可按需微调) + ev.emptyViewIsCompleteCoverSuperView = NO; // 不全屏覆盖,按内容大小布局 + ev.ignoreContentInset = YES; // 忽略 inset,避免导航/安全区影响 + ev.contentViewOffset = -10; // 轻微上移 + ev.subViewMargin = 14; // 子控件间距 + ev.titleLabFont = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + ev.titleLabTextColor = [UIColor colorWithWhite:0.45 alpha:1.0]; + ev.detailLabFont = [UIFont systemFontOfSize:14]; + ev.detailLabTextColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + ev.detailLabLineSpacing = 3; + ev.detailLabMaxLines = 2; + ev.actionBtnFont = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + ev.actionBtnCornerRadius = 6; + ev.actionBtnBorderWidth = 1; + ev.actionBtnBorderColor = [UIColor colorWithWhite:0.88 alpha:1.0]; + ev.actionBtnTitleColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + ev.actionBtnBackGroundColor = [UIColor whiteColor]; + ev.actionBtnHorizontalMargin = 20; // 自动宽度:文字 + padding*2 + + // 自动显隐交由控制层(网络请求) + ev.autoShowEmptyView = NO; + + self.ly_emptyView = (LYEmptyView *)ev; +#else + // 未集成 LYEmptyView 时不做任何处理,保持兼容 + (void)image; (void)title; (void)detail; (void)buttonTitle; (void)tapHandler; (void)buttonHandler; +#endif +} + @end diff --git a/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h new file mode 100644 index 0000000..c1b15ae --- /dev/null +++ b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.h @@ -0,0 +1,40 @@ +// +// UIScrollView+KBEmptyView.h +// keyBoard +// +// 统一封装基于 LYEmptyView 的空态视图挂载方法,适用于 UITableView/UICollectionView。 +// 注意:仅在对应页面已通过 CocoaPods 集成 LYEmptyView 时生效。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^KBEmptyAction)(void); + +@interface UIScrollView (KBEmptyView) + +/// 快速挂载一套统一样式的空态视图(LYEmptyView) +/// - Parameters: +/// - image: 占位图(可空) +/// - title: 标题(默认“暂无数据”) +/// - detail: 描述(可空) +/// - buttonTitle: 按钮标题(可空,传空则不显示按钮) +/// - tapHandler: 点击空白区域回调(可空) +/// - buttonHandler: 按钮点击回调(可空) +- (void)kb_makeDefaultEmptyViewWithImage:(nullable UIImage *)image + title:(nullable NSString *)title + detail:(nullable NSString *)detail + buttonTitle:(nullable NSString *)buttonTitle + tapHandler:(nullable KBEmptyAction)tapHandler + buttonHandler:(nullable KBEmptyAction)buttonHandler; + +/// 便捷加载态控制:关闭自动显隐后,配合网络请求手动控制显示/隐藏 +- (void)kb_setLYAutoShowEnabled:(BOOL)enabled; // YES=自动显隐;NO=手动 +- (void)kb_beginLoadingForEmpty; // 请求开始:临时隐藏 empty +- (void)kb_endLoadingForEmpty; // 请求结束:根据数据源显示/隐藏(需确保先 reloadData) + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m new file mode 100644 index 0000000..3c75ad2 --- /dev/null +++ b/keyBoard/Class/Base/V/UIScrollView+KBEmptyView.m @@ -0,0 +1,90 @@ +// +// UIScrollView+KBEmptyView.m +// keyBoard +// + +#import "UIScrollView+KBEmptyView.h" + +#if __has_include() +#import +#import +#define KB_HAS_LY 1 +#else +#define KB_HAS_LY 0 +#endif + +@implementation UIScrollView (KBEmptyView) + +- (void)kb_makeDefaultEmptyViewWithImage:(UIImage *)image + title:(NSString *)title + detail:(NSString *)detail + buttonTitle:(NSString *)buttonTitle + tapHandler:(KBEmptyAction)tapHandler + buttonHandler:(KBEmptyAction)buttonHandler { +#if KB_HAS_LY + NSString *t = title ?: @"暂无数据"; + LYEmptyView *ev = nil; + + if (buttonTitle.length > 0) { + __weak typeof(self) weakSelf = self; + ev = [LYEmptyView emptyActionViewWithImage:image + titleStr:t + detailStr:detail ?: @"" + btnTitleStr:buttonTitle + btnClickBlock:^{ if (buttonHandler) buttonHandler(); [weakSelf setNeedsLayout]; }]; + } else { + ev = [LYEmptyView emptyViewWithImage:image titleStr:t detailStr:detail ?: @""]; + } + + if (tapHandler) { ev.tapEmptyViewBlock = ^{ tapHandler(); }; } + + // 统一样式 + ev.emptyViewIsCompleteCoverSuperView = NO; + ev.ignoreContentInset = YES; + ev.contentViewOffset = -10; + ev.subViewMargin = 14; + ev.titleLabFont = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + ev.titleLabTextColor = [UIColor colorWithWhite:0.45 alpha:1.0]; + ev.detailLabFont = [UIFont systemFontOfSize:14]; + ev.detailLabTextColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + ev.detailLabLineSpacing = 3; + ev.detailLabMaxLines = 2; + ev.actionBtnFont = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + ev.actionBtnCornerRadius = 6; + ev.actionBtnBorderWidth = 1; + ev.actionBtnBorderColor = [UIColor colorWithWhite:0.88 alpha:1.0]; + ev.actionBtnTitleColor = [UIColor colorWithRed:0.22 green:0.49 blue:0.96 alpha:1.0]; + ev.actionBtnBackGroundColor = [UIColor whiteColor]; + ev.actionBtnHorizontalMargin = 20; + + // 默认关闭自动显隐,交给调用方用 begin/end 控制 + ev.autoShowEmptyView = NO; + + self.ly_emptyView = ev; +#else + (void)image; (void)title; (void)detail; (void)buttonTitle; (void)tapHandler; (void)buttonHandler; +#endif +} + +- (void)kb_setLYAutoShowEnabled:(BOOL)enabled { +#if KB_HAS_LY + self.ly_emptyView.autoShowEmptyView = enabled; +#else + (void)enabled; +#endif +} + +- (void)kb_beginLoadingForEmpty { +#if KB_HAS_LY + [self ly_startLoading]; +#endif +} + +- (void)kb_endLoadingForEmpty { +#if KB_HAS_LY + [self ly_endLoading]; +#endif +} + +@end + diff --git a/keyBoard/Class/Base/VC/BaseTabBarController.m b/keyBoard/Class/Base/VC/BaseTabBarController.m index 68bd70b..b24d801 100644 --- a/keyBoard/Class/Base/VC/BaseTabBarController.m +++ b/keyBoard/Class/Base/VC/BaseTabBarController.m @@ -7,7 +7,11 @@ #import "BaseTabBarController.h" #import "HomeVC.h" +#import "HomeMainVC.h" #import "MyVC.h" +#import "KBShopVC.h" +#import "KBCommunityVC.h" + #import "BaseNavigationController.h" #import "KBAuthManager.h" @interface BaseTabBarController () @@ -18,20 +22,88 @@ - (void)viewDidLoad { [super viewDidLoad]; - // Setup two tabs: Home & My, each embedded in BaseNavigationController - HomeVC *home = [[HomeVC alloc] init]; + + [self setupTabbarAppearance]; + + // 组装 4 个 Tab:首页 / 商城 / 社区 / 我的 + // 图标位于 Assets.xcassets/Tabbar 下:tab_home/tab_home_selected 等 + + // 首页 + HomeMainVC *home = [[HomeMainVC alloc] init]; home.title = @"首页"; BaseNavigationController *navHome = [[BaseNavigationController alloc] initWithRootViewController:home]; - navHome.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"首页" image:nil selectedImage:nil]; + navHome.tabBarItem = [self tabItemWithTitle:@"首页" + image:@"tab_home" + selectedImg:@"tab_home_selected"]; + // 商城 + KBShopVC *shop = [[KBShopVC alloc] init]; + shop.title = @"商城"; + BaseNavigationController *navShop = [[BaseNavigationController alloc] initWithRootViewController:shop]; + navShop.tabBarItem = [self tabItemWithTitle:@"商城" + image:@"tab_shop" + selectedImg:@"tab_shop_selected"]; + + // 社区 + KBCommunityVC *community = [[KBCommunityVC alloc] init]; + community.title = @"社区"; + BaseNavigationController *navCommunity = [[BaseNavigationController alloc] initWithRootViewController:community]; + navCommunity.tabBarItem = [self tabItemWithTitle:@"社区" + image:@"tab_shequ" + selectedImg:@"tab_shequ_selected"]; + + // 我的 MyVC *my = [[MyVC alloc] init]; my.title = @"我的"; BaseNavigationController *navMy = [[BaseNavigationController alloc] initWithRootViewController:my]; - navMy.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"我的" image:nil selectedImage:nil]; + navMy.tabBarItem = [self tabItemWithTitle:@"我的" + image:@"tab_my" + selectedImg:@"tab_my_selected"]; - self.viewControllers = @[navHome, navMy]; + self.viewControllers = @[navHome, navShop, navCommunity, navMy]; - [[KBAuthManager shared] saveAccessToken:@"TEST" refreshToken:nil expiryDate:[NSDate dateWithTimeIntervalSinceNow:3600] userIdentifier:nil]; + // 测试储存Token + /*[[KBAuthManager shared] saveAccessToken:@"TEST" refreshToken:nil expiryDate:[NSDate dateWithTimeIntervalSinceNow:3600] userIdentifier:nil]*/; +} + +- (void)setupTabbarAppearance{ + // 让 TabBar 不透明,子控制器 view 不再延伸到 TabBar 下 + self.tabBar.translucent = NO; + if (@available(iOS 15.0, *)) { + UITabBarAppearance *a = [UITabBarAppearance new]; + [a configureWithOpaqueBackground]; + a.backgroundColor = [UIColor whiteColor]; + // 设置选中标题为黑色(iOS 15+ 需通过 appearance) + NSDictionary *selAttr = @{ NSForegroundColorAttributeName : [UIColor blackColor] }; + a.stackedLayoutAppearance.selected.titleTextAttributes = selAttr; + a.inlineLayoutAppearance.selected.titleTextAttributes = selAttr; + a.compactInlineLayoutAppearance.selected.titleTextAttributes = selAttr; + self.tabBar.standardAppearance = a; + self.tabBar.scrollEdgeAppearance = a; + } else if (@available(iOS 13.0, *)) { + UITabBarAppearance *a = [UITabBarAppearance new]; + [a configureWithOpaqueBackground]; + a.backgroundColor = [UIColor whiteColor]; + NSDictionary *selAttr = @{ NSForegroundColorAttributeName : [UIColor blackColor] }; + a.stackedLayoutAppearance.selected.titleTextAttributes = selAttr; + a.inlineLayoutAppearance.selected.titleTextAttributes = selAttr; + a.compactInlineLayoutAppearance.selected.titleTextAttributes = selAttr; + self.tabBar.standardAppearance = a; + self.tabBar.tintColor = [UIColor blackColor]; + } else { + // 老系统用 tintColor/appearance 做回退 + self.tabBar.tintColor = [UIColor blackColor]; + [[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]} + forState:UIControlStateSelected]; + } +} + +// 统一构造 TabBarItem,原图渲染,避免被系统 Tint 着色 +- (UITabBarItem *)tabItemWithTitle:(NSString *)title image:(NSString *)imageName selectedImg:(NSString *)selectedName { + UIImage *img = [[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + UIImage *sel = [[UIImage imageNamed:selectedName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:title image:img selectedImage:sel]; + return item; } /* diff --git a/keyBoard/Class/Base/VC/BaseViewController.h b/keyBoard/Class/Base/VC/BaseViewController.h new file mode 100644 index 0000000..3b32969 --- /dev/null +++ b/keyBoard/Class/Base/VC/BaseViewController.h @@ -0,0 +1,16 @@ +// +// BaseViewController.h +// keyBoard +// +// Created by Mac on 2025/11/7. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BaseViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Base/VC/BaseViewController.m b/keyBoard/Class/Base/VC/BaseViewController.m new file mode 100644 index 0000000..e736182 --- /dev/null +++ b/keyBoard/Class/Base/VC/BaseViewController.m @@ -0,0 +1,32 @@ +// +// BaseViewController.m +// keyBoard +// +// Created by Mac on 2025/11/7. +// + +#import "BaseViewController.h" + +@interface BaseViewController () + +@end + +@implementation BaseViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.view.backgroundColor = [UIColor whiteColor]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/keyBoard/Class/Categories/UIImage+KBColor.h b/keyBoard/Class/Categories/UIImage+KBColor.h new file mode 100644 index 0000000..3ffc4c1 --- /dev/null +++ b/keyBoard/Class/Categories/UIImage+KBColor.h @@ -0,0 +1,42 @@ +// +// UIImage+KBColor.h +// keyBoard +// +// 颜色/渐变 生成图片工具 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, KBGradientDirection) { + KBGradientDirectionLeftToRight = 0, // 左 → 右 + KBGradientDirectionTopToBottom, // 上 → 下 + KBGradientDirectionLeftTopToRightBottom,// 左上 → 右下 + KBGradientDirectionLeftBottomToRightTop // 左下 → 右上 +}; + +@interface UIImage (KBColor) + +/// 用纯色生成图片 ++ (UIImage *)kb_imageWithColor:(UIColor *)color size:(CGSize)size; + +/// 用纯色生成圆角图片 ++ (UIImage *)kb_imageWithColor:(UIColor *)color size:(CGSize)size cornerRadius:(CGFloat)cornerRadius; + +/// 生成渐变图片(默认均匀分布) ++ (UIImage *)kb_gradientImageWithColors:(NSArray *)colors + size:(CGSize)size + direction:(KBGradientDirection)direction; + +/// 生成渐变图片(可指定 locations 与圆角) ++ (UIImage *)kb_gradientImageWithColors:(NSArray *)colors + locations:(NSArray * _Nullable)locations + size:(CGSize)size + direction:(KBGradientDirection)direction + cornerRadius:(CGFloat)cornerRadius; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Categories/UIImage+KBColor.m b/keyBoard/Class/Categories/UIImage+KBColor.m new file mode 100644 index 0000000..c13145c --- /dev/null +++ b/keyBoard/Class/Categories/UIImage+KBColor.m @@ -0,0 +1,86 @@ +// +// UIImage+KBColor.m +// keyBoard +// +// 颜色/渐变 生成图片工具 +// + +#import "UIImage+KBColor.h" + +@implementation UIImage (KBColor) + ++ (UIImage *)kb_imageWithColor:(UIColor *)color size:(CGSize)size { + return [self kb_imageWithColor:color size:size cornerRadius:0]; +} + ++ (UIImage *)kb_imageWithColor:(UIColor *)color size:(CGSize)size cornerRadius:(CGFloat)cornerRadius { + if (size.width <= 0 || size.height <= 0 || !color) { return nil; } + CGRect rect = (CGRect){CGPointZero, size}; + UIGraphicsBeginImageContextWithOptions(size, NO, 0); // 0 => 使用设备 scale + CGContextRef ctx = UIGraphicsGetCurrentContext(); + if (cornerRadius > 0) { + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; + [path addClip]; + } + CGContextSetFillColorWithColor(ctx, color.CGColor); + CGContextFillRect(ctx, rect); + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return img; +} + ++ (UIImage *)kb_gradientImageWithColors:(NSArray *)colors + size:(CGSize)size + direction:(KBGradientDirection)direction { + return [self kb_gradientImageWithColors:colors locations:nil size:size direction:direction cornerRadius:0]; +} + ++ (UIImage *)kb_gradientImageWithColors:(NSArray *)colors + locations:(NSArray * _Nullable)locations + size:(CGSize)size + direction:(KBGradientDirection)direction + cornerRadius:(CGFloat)cornerRadius { + if (colors.count == 0 || size.width <= 0 || size.height <= 0) { return nil; } + // 构造渐变层 + CAGradientLayer *layer = [CAGradientLayer layer]; + layer.frame = (CGRect){CGPointZero, size}; + NSMutableArray *cgColors = [NSMutableArray arrayWithCapacity:colors.count]; + for (UIColor *c in colors) { [cgColors addObject:(id)c.CGColor]; } + layer.colors = cgColors; + if (locations.count == colors.count) { layer.locations = locations; } + + // 方向 -> 起止点 + switch (direction) { + case KBGradientDirectionLeftToRight: + layer.startPoint = CGPointMake(0, 0.5); + layer.endPoint = CGPointMake(1, 0.5); + break; + case KBGradientDirectionTopToBottom: + layer.startPoint = CGPointMake(0.5, 0); + layer.endPoint = CGPointMake(0.5, 1); + break; + case KBGradientDirectionLeftTopToRightBottom: + layer.startPoint = CGPointMake(0, 0); + layer.endPoint = CGPointMake(1, 1); + break; + case KBGradientDirectionLeftBottomToRightTop: + layer.startPoint = CGPointMake(0, 1); + layer.endPoint = CGPointMake(1, 0); + break; + } + + if (cornerRadius > 0) { + layer.cornerRadius = cornerRadius; + layer.masksToBounds = YES; + } + + UIGraphicsBeginImageContextWithOptions(size, NO, 0); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + [layer renderInContext:ctx]; + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return img; +} + +@end + diff --git a/keyBoard/Class/Categories/UIView+KBShadow.h b/keyBoard/Class/Categories/UIView+KBShadow.h new file mode 100644 index 0000000..76c93d3 --- /dev/null +++ b/keyBoard/Class/Categories/UIView+KBShadow.h @@ -0,0 +1,34 @@ +// +// UIView+KBShadow.h +// keyBoard +// +// 基础阴影封装:一行设置卡片阴影,支持圆角与路径缓存 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (KBShadow) + +/// 便捷方法:设置卡片阴影(常用黑色、透明度0.15、半径10、偏移(0,6))并记录圆角和内边距,用于后续更新路径 +- (void)kb_setCardShadowWithCornerRadius:(CGFloat)cornerRadius insets:(UIEdgeInsets)insets; + +/// 自定义阴影参数;同时记录 cornerRadius 与 insets,供 `kb_updateShadowPath` 使用 +- (void)kb_setShadowWithColor:(UIColor *)color + opacity:(float)opacity + radius:(CGFloat)radius + offset:(CGSize)offset + cornerRadius:(CGFloat)cornerRadius + insets:(UIEdgeInsets)insets; + +/// 在 `layoutSubviews` 等尺寸变化后调用,按记录的 cornerRadius 与 insets 更新 shadowPath +- (void)kb_updateShadowPath; + +/// 移除阴影(清理 shadowPath) +- (void)kb_removeShadow; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Categories/UIView+KBShadow.m b/keyBoard/Class/Categories/UIView+KBShadow.m new file mode 100644 index 0000000..1f66546 --- /dev/null +++ b/keyBoard/Class/Categories/UIView+KBShadow.m @@ -0,0 +1,65 @@ +// +// UIView+KBShadow.m +// keyBoard +// +// + +#import "UIView+KBShadow.h" +#import + +static const void *kKBShadowInsetsKey = &kKBShadowInsetsKey; +static const void *kKBShadowCornerRadiusKey = &kKBShadowCornerRadiusKey; + +@implementation UIView (KBShadow) + +- (void)kb_setCardShadowWithCornerRadius:(CGFloat)cornerRadius insets:(UIEdgeInsets)insets { + [self kb_setShadowWithColor:[UIColor blackColor] + opacity:0.15f + radius:10.0 + offset:CGSizeMake(0, 6) + cornerRadius:cornerRadius + insets:insets]; +} + +- (void)kb_setShadowWithColor:(UIColor *)color + opacity:(float)opacity + radius:(CGFloat)radius + offset:(CGSize)offset + cornerRadius:(CGFloat)cornerRadius + insets:(UIEdgeInsets)insets { + CALayer *layer = self.layer; + layer.masksToBounds = NO; // 需要让阴影显示在边界外 + layer.shadowColor = color.CGColor; + layer.shadowOpacity = opacity; + layer.shadowRadius = radius; + layer.shadowOffset = offset; + + // 记录参数,供尺寸变化后更新路径 + objc_setAssociatedObject(self, kKBShadowInsetsKey, [NSValue valueWithUIEdgeInsets:insets], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(self, kKBShadowCornerRadiusKey, @(cornerRadius), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // 初次也设置一次路径(避免首次 layout 之前看不到阴影) + [self kb_updateShadowPath]; +} + +- (void)kb_updateShadowPath { + NSValue *insetsVal = objc_getAssociatedObject(self, kKBShadowInsetsKey); + NSNumber *cornerVal = objc_getAssociatedObject(self, kKBShadowCornerRadiusKey); + if (!insetsVal || !cornerVal) return; + UIEdgeInsets insets = [insetsVal UIEdgeInsetsValue]; + CGFloat corner = (CGFloat)[cornerVal doubleValue]; + CGRect rect = UIEdgeInsetsInsetRect(self.bounds, insets); + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:corner]; + self.layer.shadowPath = path.CGPath; +} + +- (void)kb_removeShadow { + CALayer *layer = self.layer; + layer.shadowOpacity = 0; + layer.shadowPath = nil; + objc_setAssociatedObject(self, kKBShadowInsetsKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(self, kKBShadowCornerRadiusKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +@end + diff --git a/keyBoard/Class/Community/VC/KBCommunityVC.h b/keyBoard/Class/Community/VC/KBCommunityVC.h new file mode 100644 index 0000000..3b47be3 --- /dev/null +++ b/keyBoard/Class/Community/VC/KBCommunityVC.h @@ -0,0 +1,16 @@ +// +// KBCommunityVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBCommunityVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Community/VC/KBCommunityVC.m b/keyBoard/Class/Community/VC/KBCommunityVC.m new file mode 100644 index 0000000..8819311 --- /dev/null +++ b/keyBoard/Class/Community/VC/KBCommunityVC.m @@ -0,0 +1,31 @@ +// +// KBCommunityVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "KBCommunityVC.h" + +@interface KBCommunityVC () + +@end + +@implementation KBCommunityVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/keyBoard/Class/Home/V/HomeHeadView.h b/keyBoard/Class/Home/V/HomeHeadView.h new file mode 100644 index 0000000..19390a1 --- /dev/null +++ b/keyBoard/Class/Home/V/HomeHeadView.h @@ -0,0 +1,23 @@ +// +// HomeHeadView.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeHeadView : UIView + +/// 点击底部购买按钮回调 +@property (nonatomic, copy) void (^onTapBuy)(void); + +/// 配置4个功能按钮标题与图片(可选) +/// 若 images 为空会使用一个渐变占位图 +- (void)configureFeatureTitles:(NSArray *)titles images:(NSArray * _Nullable)images; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/V/HomeHeadView.m b/keyBoard/Class/Home/V/HomeHeadView.m new file mode 100644 index 0000000..a97db12 --- /dev/null +++ b/keyBoard/Class/Home/V/HomeHeadView.m @@ -0,0 +1,243 @@ +// +// HomeHeadView.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "HomeHeadView.h" +#import "UIImage+KBColor.h" +#import "KBTopImageButton.h" + + +@interface HomeHeadView() +@property (nonatomic, strong) UIImageView *loveKeyImageView; + +// 顶部会员卡图片 +@property (nonatomic, strong) UIImageView *vipImageView; +// 主/副标题 +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *subTitleLabel; +// 中部四个功能按钮容器 +@property (nonatomic, strong) UIView *featuresContainer; +@property (nonatomic, strong) NSArray *featureButtons; +// 底部购买按钮 +@property (nonatomic, strong) UIButton *buyButton; + +@end + +@implementation HomeHeadView + +- (instancetype)initWithFrame:(CGRect)frame{ + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor clearColor]; + [self setupViews]; + [self setupConstraints]; + [self defaultData]; + } + return self; +} + +#pragma mark - Layout +- (void)layoutSubviews { + [super layoutSubviews]; +} + +#pragma mark - UI +- (void)setupViews { +// [self addSubview:self.loveKeyImageView]; + [self addSubview:self.vipImageView]; + [self addSubview:self.titleLabel]; + [self addSubview:self.subTitleLabel]; + [self addSubview:self.featuresContainer]; + [self addSubview:self.buyButton]; +} + +- (void)setupConstraints { + // 顶部图 + [self.vipImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.mas_top).offset(2); + make.centerX.equalTo(self); + make.width.mas_equalTo(217); + make.height.mas_equalTo(166); + }]; + +// [self.loveKeyImageView mas_makeConstraints:^(MASConstraintMaker *make) { +// make.top.equalTo(self.vipImageView.mas_centerY).offset(0); +// make.right.equalTo(self).offset(-16); +// make.width.mas_equalTo(335); +// make.height.mas_equalTo(117); +// }]; + + // 主标题 + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.vipImageView.mas_bottom).offset(28); + make.centerX.equalTo(self); + make.left.greaterThanOrEqualTo(self.mas_left).offset(16); + make.right.lessThanOrEqualTo(self.mas_right).offset(-16); + make.height.mas_equalTo(26); + }]; + + // 副标题 + [self.subTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(3); + make.centerX.equalTo(self.titleLabel); + make.left.greaterThanOrEqualTo(self.mas_left).offset(16); + make.right.lessThanOrEqualTo(self.mas_right).offset(-16); + make.height.mas_equalTo(20); + }]; + + // 功能按钮容器 + [self.featuresContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.subTitleLabel.mas_bottom).offset(16); + make.left.equalTo(self.mas_left).offset(16); + make.right.equalTo(self.mas_right).offset(-16); + make.height.mas_equalTo(80); + }]; + + // 四个按钮等宽分布 + KBTopImageButton *b0 = self.featureButtons[0]; + KBTopImageButton *b1 = self.featureButtons[1]; + KBTopImageButton *b2 = self.featureButtons[2]; + KBTopImageButton *b3 = self.featureButtons[3]; + + [b0 mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.bottom.equalTo(self.featuresContainer); + }]; + [b1 mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(b0.mas_right); + make.top.bottom.equalTo(b0); + make.width.equalTo(b0); + }]; + [b2 mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(b1.mas_right); + make.top.bottom.equalTo(b0); + make.width.equalTo(b0); + }]; + [b3 mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(b2.mas_right); + make.top.bottom.right.equalTo(self.featuresContainer); + make.width.equalTo(b0); + }]; + + // 购买按钮 + [self.buyButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(62); + make.right.equalTo(self.mas_right).offset(-62); + make.bottom.equalTo(self.mas_bottom).offset(0); + make.height.mas_equalTo(56); + }]; +} + +- (void)defaultData { + // 默认文案(使用英文,便于与示例图一致) + self.titleLabel.text = @"Become A Member Of Love Key"; + self.subTitleLabel.text = @"Unlock All Functions"; + + NSArray *titles = @[@"Wireless Sub-ai\nDialogue", + @"Personalized\nKeyboard", + @"Chat\nPersona", + @"Emotional\nCounseling"]; + NSArray *images = @[[UIImage imageNamed:@"home_ai_icon"], + [UIImage imageNamed:@"home_keyboard_icon"], + [UIImage imageNamed:@"home_chat_icon"], + [UIImage imageNamed:@"home_emotion_icon"]]; + [self configureFeatureTitles:titles images:images]; +} + +#pragma mark - Public +- (void)configureFeatureTitles:(NSArray *)titles images:(NSArray *)images { + // 设置四个按钮标题与占位图片(如未传图片则生成渐变圆角占位) + NSInteger count = MIN(4, titles.count); + for (NSInteger i = 0; i < 4; i++) { + KBTopImageButton *btn = self.featureButtons[i]; + if (i < count) { + btn.textLabel.text = titles[i]; + } + UIImage *img = (i < images.count) ? images[i] : nil; + btn.iconView.image = img; + } +} + +#pragma mark - Actions +- (void)onTapBuyAction { + if (self.onTapBuy) { self.onTapBuy(); } +} + +#pragma mark - Lazy +- (UIImageView *)vipImageView{ + if (!_vipImageView) { + _vipImageView = [[UIImageView alloc] init]; + _vipImageView.image = [UIImage imageNamed:@"home_topvip_icon"]; + _vipImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _vipImageView; +} +- (UIImageView *)loveKeyImageView{ + if (!_loveKeyImageView) { + _loveKeyImageView = [[UIImageView alloc] init]; + _loveKeyImageView.image = [UIImage imageNamed:@"hoem_love_key"]; + _loveKeyImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _loveKeyImageView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightBold]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UILabel *)subTitleLabel { + if (!_subTitleLabel) { + _subTitleLabel = [[UILabel alloc] init]; + _subTitleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightRegular]; + _subTitleLabel.textColor = self.titleLabel.textColor; + _subTitleLabel.textAlignment = NSTextAlignmentCenter; + } + return _subTitleLabel; +} + +- (UIView *)featuresContainer { + if (!_featuresContainer) { + _featuresContainer = [[UIView alloc] init]; + // 不显式背景,保留父视图背景;如需调试可设置颜色 + // _featuresContainer.backgroundColor = [UIColor colorWithWhite:0 alpha:0.02]; + + // 创建4个功能按钮(懒加载一并放到数组) + NSMutableArray *arr = [NSMutableArray arrayWithCapacity:4]; + for (int i = 0; i < 4; i++) { + KBTopImageButton *btn = [[KBTopImageButton alloc] init]; + btn.iconSize = CGSizeMake(54, 44); + btn.spacing = 0; + [self.featuresContainer addSubview:btn]; + [arr addObject:btn]; + } + _featureButtons = [arr copy]; + } + return _featuresContainer; +} + +- (NSArray *)featureButtons { + // 只读访问,实际由 featuresContainer 的懒加载创建 + if (!_featureButtons) { (void)self.featuresContainer; } + return _featureButtons; +} + +- (UIButton *)buyButton { + if (!_buyButton) { + _buyButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_buyButton setTitle:@"Recharge Now" forState:UIControlStateNormal]; + [_buyButton setTitleColor:[UIColor colorWithHex:0x1B1F1A] forState:UIControlStateNormal]; + _buyButton.titleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; + [_buyButton setBackgroundImage:[UIImage imageNamed:@"recharge_now_icon"] forState:UIControlStateNormal]; + [_buyButton addTarget:self action:@selector(onTapBuyAction) forControlEvents:UIControlEventTouchUpInside]; + } + return _buyButton; +} + +@end diff --git a/keyBoard/Class/Home/V/HomeHotCell.h b/keyBoard/Class/Home/V/HomeHotCell.h new file mode 100644 index 0000000..8884126 --- /dev/null +++ b/keyBoard/Class/Home/V/HomeHotCell.h @@ -0,0 +1,20 @@ +// +// HomeHotCell.h +// keyBoard +// +// 自定义 cell:左侧序号与圆形头像,占位标题/副标题,右侧加入按钮。 +// + +#import "BaseCell.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeHotCell : BaseCell + +/// 配置数据 +- (void)configWithRank:(NSInteger)rank title:(NSString *)title subtitle:(NSString *)sub joined:(BOOL)joined; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Home/V/HomeHotCell.m b/keyBoard/Class/Home/V/HomeHotCell.m new file mode 100644 index 0000000..f09890f --- /dev/null +++ b/keyBoard/Class/Home/V/HomeHotCell.m @@ -0,0 +1,151 @@ +// +// HomeHotCell.m +// keyBoard +// + +#import "HomeHotCell.h" + +@interface HomeHotCell() +// 左侧序号 +@property (nonatomic, strong) UILabel *rankLabel; +@property (nonatomic, strong) UIView *yuanView; +// 左侧圆形头像占位 +@property (nonatomic, strong) UIView *avatarView; +// 标题 +@property (nonatomic, strong) UILabel *titleLabel; +// 副标题 +@property (nonatomic, strong) UILabel *subLabel; +// 右侧加入按钮(或已加入勾选) +@property (nonatomic, strong) UIButton *actionButton; +@end + +@implementation HomeHotCell + +- (void)setupUI { + [super setupUI]; + + // 添加控件 + [self.contentView addSubview:self.yuanView]; + [self.contentView addSubview:self.rankLabel]; + [self.contentView addSubview:self.avatarView]; + [self.contentView addSubview:self.titleLabel]; + [self.contentView addSubview:self.subLabel]; + [self.contentView addSubview:self.actionButton]; + + // 布局(使用 Masonry) + [self.rankLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(16); + make.centerY.equalTo(self.contentView); + }]; + [self.yuanView mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.rankLabel).offset(2); + make.bottom.equalTo(self.rankLabel).offset(-3); + make.width.height.mas_equalTo(6); + }]; + + [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.rankLabel.mas_right).offset(12); + make.centerY.equalTo(self.contentView); + make.width.height.mas_equalTo(56); + }]; + + [self.actionButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contentView); + make.right.equalTo(self.contentView).offset(-16); + make.width.mas_equalTo(56); + make.height.mas_equalTo(38); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.avatarView.mas_right).offset(12); + make.top.equalTo(self.avatarView.mas_top).offset(-2); + make.right.lessThanOrEqualTo(self.actionButton.mas_left).offset(-12); + }]; + + [self.subLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.titleLabel); + make.right.equalTo(self.titleLabel); + make.bottom.equalTo(self.avatarView.mas_bottom).offset(2); + }]; +} + +- (void)configWithRank:(NSInteger)rank title:(NSString *)title subtitle:(NSString *)sub joined:(BOOL)joined { + self.rankLabel.text = [NSString stringWithFormat:@"%ld", (long)rank]; + self.titleLabel.text = title ?: @""; + self.subLabel.text = sub ?: @""; + + if (joined) { + // 已加入状态:灰背景、打勾 + [self.actionButton setTitle:@"✓" forState:UIControlStateNormal]; + [self.actionButton setTitleColor:[UIColor colorWithWhite:0.45 alpha:1] forState:UIControlStateNormal]; + self.actionButton.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1]; + } else { + // 可加入状态:绿色加号 + [self.actionButton setTitle:@"+" forState:UIControlStateNormal]; + [self.actionButton setTitleColor:[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] forState:UIControlStateNormal]; + self.actionButton.backgroundColor = [UIColor colorWithRed:0.88 green:0.97 blue:0.93 alpha:1.0]; + } +} + +#pragma mark - Lazy + +- (UILabel *)rankLabel { + if (!_rankLabel) { + _rankLabel = [[UILabel alloc] init]; + _rankLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _rankLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + } + return _rankLabel; +} + +- (UIView *)avatarView { + if (!_avatarView) { + _avatarView = [[UIView alloc] init]; + _avatarView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1]; + _avatarView.layer.cornerRadius = 28; + _avatarView.layer.masksToBounds = YES; + } + return _avatarView; +} + +- (UIView *)yuanView { + if (!_yuanView) { + _yuanView = [[UIView alloc] init]; + _yuanView.backgroundColor = [UIColor colorWithHex:0x26D3AA]; + _yuanView.layer.cornerRadius = 3; + _yuanView.layer.masksToBounds = YES; + } + return _yuanView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + } + return _titleLabel; +} + +- (UILabel *)subLabel { + if (!_subLabel) { + _subLabel = [[UILabel alloc] init]; + _subLabel.font = [UIFont systemFontOfSize:12]; + _subLabel.textColor = [UIColor colorWithHex:0x9A9A9A]; + _subLabel.numberOfLines = 2; + } + return _subLabel; +} + +- (UIButton *)actionButton { + if (!_actionButton) { + _actionButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _actionButton.layer.cornerRadius = 12; + _actionButton.layer.masksToBounds = YES; + _actionButton.titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightBold]; + } + return _actionButton; +} + +@end + diff --git a/keyBoard/Class/Home/V/HomeRankCardCell.h b/keyBoard/Class/Home/V/HomeRankCardCell.h new file mode 100644 index 0000000..547f084 --- /dev/null +++ b/keyBoard/Class/Home/V/HomeRankCardCell.h @@ -0,0 +1,27 @@ +// +// HomeRankCardCell.h +// keyBoard +// +// Created by Codex on 2025/11/06. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 首页排行榜卡片 Cell(两列) +@interface HomeRankCardCell : UICollectionViewCell + +/// 点击加号/勾选按钮回调 +@property (nonatomic, copy, nullable) void (^onTapAction)(void); + +/// 统一配置数据 +- (void)configureWithTitle:(NSString *)title + desc:(NSString *)desc + people:(NSString *)people + added:(BOOL)added; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Home/V/HomeRankCardCell.m b/keyBoard/Class/Home/V/HomeRankCardCell.m new file mode 100644 index 0000000..cd62dd5 --- /dev/null +++ b/keyBoard/Class/Home/V/HomeRankCardCell.m @@ -0,0 +1,202 @@ +// +// HomeRankCardCell.m +// keyBoard +// +// Created by Codex on 2025/11/06. +// + +@import UIKit; +#import "HomeRankCardCell.h" +#import "UIView+KBShadow.h" + +@interface HomeRankCardCell () +@property (nonatomic, strong) UIView *shadowView; // 阴影容器(不裁剪) +@property (nonatomic, strong) UIView *cardView; // 白色圆角卡片 +@property (nonatomic, strong) UIView *badgeCircle; // 顶部圆形描边 +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *descLabel; +@property (nonatomic, strong) UILabel *peopleLabel; +@property (nonatomic, strong) UIButton *actionBtn; // 加号/勾选按钮 +@property (nonatomic, assign) BOOL added; +@end + +@implementation HomeRankCardCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = UIColor.clearColor; + [self setupUI]; + [self setupConstraints]; + } + return self; +} + +- (void)setupUI { + // 使用懒加载属性,保证首次访问时创建 + [self.contentView addSubview:self.shadowView]; + [self.shadowView addSubview:self.cardView]; + [self.contentView addSubview:self.badgeCircle]; + [self.cardView addSubview:self.titleLabel]; + [self.cardView addSubview:self.descLabel]; + [self.cardView addSubview:self.peopleLabel]; + [self.cardView addSubview:self.actionBtn]; + + // 统一阴影封装:在阴影容器上添加卡片阴影,阴影路径根据卡片左右 8pt 内边距进行收缩 + [self.shadowView kb_setCardShadowWithCornerRadius:18.0 insets:UIEdgeInsetsMake(0, 8, 0, 8)]; +} + +- (void)setupConstraints { + // Masonry 约束 + [self.shadowView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.equalTo(self.contentView); + make.top.equalTo(self.contentView.mas_top).offset(68 * 0.5); // 给圆环留空间 + }]; + + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.shadowView).insets(UIEdgeInsetsMake(0, 8, 0, 8)); + }]; + + [self.badgeCircle mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.cardView); + make.centerY.equalTo(self.shadowView.mas_top); + make.width.height.mas_equalTo(68); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.badgeCircle.mas_bottom).offset(13); + make.left.equalTo(self.cardView.mas_left).offset(18); + make.right.equalTo(self.cardView.mas_right).offset(-18); + make.height.mas_equalTo(23); + }]; + + [self.descLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(12); + make.left.equalTo(self.cardView.mas_left).offset(18); + make.right.equalTo(self.cardView.mas_right).offset(-18); + }]; + + [self.peopleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.descLabel.mas_bottom).offset(8); + make.left.equalTo(self.cardView.mas_left).offset(18); + make.right.equalTo(self.cardView.mas_right).offset(-18); + }]; + + [self.actionBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.cardView.mas_left).offset(18); + make.right.equalTo(self.cardView.mas_right).offset(-18); + make.bottom.equalTo(self.cardView.mas_bottom).offset(-12); + make.height.mas_equalTo(32); + }]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + // 阴影路径需在尺寸确定后更新(封装方法会基于记录参数自动计算) + [self.shadowView kb_updateShadowPath]; + + _badgeCircle.layer.cornerRadius = 34; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + self.onTapAction = nil; +} + +- (void)tapAction { + if (self.onTapAction) self.onTapAction(); +} + +- (void)configureWithTitle:(NSString *)title desc:(NSString *)desc people:(NSString *)people added:(BOOL)added { + self.added = added; + self.titleLabel.text = title ?: @""; + self.descLabel.text = desc ?: @""; + self.peopleLabel.text = people ?: @""; + + if (added) { + // 已添加:灰底、对勾 + self.actionBtn.backgroundColor = [UIColor colorWithWhite:0.93 alpha:1.0]; + [self.actionBtn setTitle:@"✓" forState:UIControlStateNormal]; + [self.actionBtn setTitleColor:[UIColor colorWithWhite:0.55 alpha:1.0] forState:UIControlStateNormal]; + } else { + // 未添加:黑底、加号 + self.actionBtn.backgroundColor = [UIColor blackColor]; + [self.actionBtn setTitle:@"+" forState:UIControlStateNormal]; + [self.actionBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + } +} + +#pragma mark - Lazy UI + +- (UIView *)shadowView { + if (!_shadowView) { + _shadowView = [UIView new]; + _shadowView.backgroundColor = UIColor.clearColor; + } + return _shadowView; +} + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [UIView new]; + _cardView.backgroundColor = UIColor.whiteColor; + _cardView.layer.cornerRadius = 18.0; + _cardView.layer.masksToBounds = YES; + } + return _cardView; +} + +- (UIView *)badgeCircle { + if (!_badgeCircle) { + _badgeCircle = [UIView new]; + _badgeCircle.backgroundColor = UIColor.whiteColor; + _badgeCircle.layer.borderColor = [UIColor colorWithRed:0.78 green:0.90 blue:0.20 alpha:1.0].CGColor; + _badgeCircle.layer.borderWidth = 3.0; + } + return _badgeCircle; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + _titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UILabel *)descLabel { + if (!_descLabel) { + _descLabel = [UILabel new]; + _descLabel.textColor = [UIColor colorWithHex:0x9A9A9A]; + _descLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightRegular]; + _descLabel.textAlignment = NSTextAlignmentCenter; + _descLabel.numberOfLines = 2; + } + return _descLabel; +} + +- (UILabel *)peopleLabel { + if (!_peopleLabel) { + _peopleLabel = [UILabel new]; + _peopleLabel.textColor = [UIColor colorWithHex:0x02BEAC]; + _peopleLabel.font = [UIFont systemFontOfSize:10 weight:UIFontWeightRegular]; + _peopleLabel.textAlignment = NSTextAlignmentCenter; + _peopleLabel.numberOfLines = 2; + } + return _peopleLabel; +} + +- (UIButton *)actionBtn { + if (!_actionBtn) { + _actionBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + _actionBtn.layer.cornerRadius = 4.0; + _actionBtn.layer.masksToBounds = YES; + [_actionBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + _actionBtn.titleLabel.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold]; + [_actionBtn addTarget:self action:@selector(tapAction) forControlEvents:UIControlEventTouchUpInside]; + } + return _actionBtn; +} + +@end diff --git a/keyBoard/Class/Home/V/KBDirectionIndicatorView.h b/keyBoard/Class/Home/V/KBDirectionIndicatorView.h new file mode 100644 index 0000000..7495077 --- /dev/null +++ b/keyBoard/Class/Home/V/KBDirectionIndicatorView.h @@ -0,0 +1,17 @@ +// +// KBDirectionIndicatorView.h +// keyBoard +// +// Created by Mac on 2025/11/5. +// HomeSheetVC 三角指示器 + +#import +#import +#import +NS_ASSUME_NONNULL_BEGIN + +@interface KBDirectionIndicatorView : UIView +- (void)applyPresentationState:(PresentationState)state; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/V/KBDirectionIndicatorView.m b/keyBoard/Class/Home/V/KBDirectionIndicatorView.m new file mode 100644 index 0000000..103631e --- /dev/null +++ b/keyBoard/Class/Home/V/KBDirectionIndicatorView.m @@ -0,0 +1,66 @@ +// +// KBDirectionIndicatorView.m +// keyBoard +// +// Created by Mac on 2025/11/5. +// + +#import "KBDirectionIndicatorView.h" +#import "UIView+HW_Frame.h" + +@interface KBDirectionIndicatorView () +@property (nonatomic, strong) UIView *leftView; +@property (nonatomic, strong) UIView *rightView; +@end + +@implementation KBDirectionIndicatorView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.backgroundColor = UIColor.clearColor; + _leftView = [UIView new]; + _rightView = [UIView new]; + _leftView.backgroundColor = _rightView.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1]; + [self addSubview:_leftView]; + [self addSubview:_rightView]; + } + return self; +} + +- (CGSize)indicatorSize { return CGSizeMake(34, 13); } + +- (void)setupSubviews { + CGSize size = [self indicatorSize]; + self.hw_size = size; + CGFloat h = 5, c = h/2.0; + _leftView.frame = CGRectMake(0, 0, size.width/2 + c, h); + _rightView.frame = CGRectMake(size.width/2 - c, 0, size.width/2 + c, h); + _leftView.hw_centerY = _rightView.hw_centerY = self.hw_height/2.0; + _leftView.layer.cornerRadius = MIN(_leftView.hw_width, _leftView.hw_height)/2; + _rightView.layer.cornerRadius = MIN(_rightView.hw_width, _rightView.hw_height)/2; +} + +// 默认库会在很多时机传 HWIndicatorStateNormal,这里忽略,不改变我们基于状态的朝向 +- (void)didChangeToState:(HWIndicatorState)state { + // no-op 或者根据需要做轻微弹性动画 +} + +- (void)applyPresentationState:(PresentationState)state { + CGFloat angle = (CGFloat)(20.0 * M_PI / 180.0); + void (^animate)(void) = ^{ + switch (state) { + case PresentationStateShort: // 最低:指向上(∧) + self.leftView.transform = CGAffineTransformMakeRotation(-angle); + self.rightView.transform = CGAffineTransformMakeRotation(angle); + break; + case PresentationStateLong: // 最高:指向下(∨) + default: + self.leftView.transform = CGAffineTransformMakeRotation(angle); + self.rightView.transform = CGAffineTransformMakeRotation(-angle); + break; + } + }; + [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionCurveEaseOut animations:animate completion:nil]; +} +@end diff --git a/keyBoard/Class/Home/V/KBPanModalView.h b/keyBoard/Class/Home/V/KBPanModalView.h new file mode 100644 index 0000000..e902fce --- /dev/null +++ b/keyBoard/Class/Home/V/KBPanModalView.h @@ -0,0 +1,19 @@ +// +// KBPanModalView.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import +#import + +#import "HWPanModalContentView.h" +NS_ASSUME_NONNULL_BEGIN + +@interface KBPanModalView : HWPanModalContentView +@property (nonatomic, assign) CGFloat minHeight; // 例如 150 +@property (nonatomic, assign) CGFloat topInset; // 例如 100 +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/V/KBPanModalView.m b/keyBoard/Class/Home/V/KBPanModalView.m new file mode 100644 index 0000000..e516c17 --- /dev/null +++ b/keyBoard/Class/Home/V/KBPanModalView.m @@ -0,0 +1,484 @@ +// +// KBPanModalView.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "KBPanModalView.h" +#import "KBDirectionIndicatorView.h" +// 子控制器 +#import "HomeHotVC.h" +#import "HomeRankVC.h" +@interface KBPanModalView() +@property (nonatomic, strong) KBDirectionIndicatorView *indicator; +// 顶部切换按钮与指示条 +@property (nonatomic, strong) UIView *topBar; +@property (nonatomic, strong) UIView *bigWhiteContentView; +@property (nonatomic, strong) UIView *secWhiteContentView; +/// 皇冠👑 +@property (nonatomic, strong) UIImageView *hgImageView; +/// 人 +@property (nonatomic, strong) UIImageView *personImageView; + + +@property (nonatomic, strong) UIImageView *leftBgImageView; +@property (nonatomic, strong) UIImageView *rightBgImageView; + + +@property (nonatomic, strong) UIButton *hotButton; +@property (nonatomic, strong) UIButton *rankButton; +@property (nonatomic, strong) UIImageView *underlineImageView; // 选中下划线 +/// 顶部拖拽方向图标(初始向上,展开至顶部后向下) +@property (nonatomic, strong) UIImageView *dragArrowImageView; + +// 承载子控制器内容 +// 注意:父类 HWPanModalContentView 内部已有名为 `containerView` 的属性(类型为 HWPanModalContainerView), +// 不能同名,否则会导致运行时通过该属性访问到我们自己的 UIView,从而在库里调用 +// `currentPresentationState` 时崩溃(- [UIView currentPresentationState] unrecognized selector)。 +// 因此这里将承载子内容的视图命名为 contentContainerView。 +@property (nonatomic, strong) UIView *contentContainerView; +@property (nonatomic, strong) UIViewController *currentChild; +@property (nonatomic, strong) HomeHotVC *hotVC; +@property (nonatomic, strong) HomeRankVC *rankVC; +@property (nonatomic, assign) NSInteger currentIndex; + +@end +@implementation KBPanModalView + +- (instancetype)initWithFrame:(CGRect)frame{ + if (self = [super initWithFrame:frame]) { + // 该背景色会被 HWPanModal 用来设置容器的 _contentView 背景色 + // 参考 Pods/HWPanModal/Sources/View/PanModal/HWPanModalContainerView.m: adjustPanContainerBackgroundColor + // 想要改变外层白色底(截图中 _contentView)的颜色,只需改这里即可 +// self.backgroundColor = [UIColor colorWithHex:0xE8FFF4]; // 柔和的绿色 + self.backgroundColor = [UIColor clearColor]; +// HWBackgroundConfig *config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault]; +// config.backgroundAlpha = 0; +// [self.hw_dimmedView reloadConfig:config]; + + + + // 顶部按钮 + 容器 + [self setupTopButtonsAndContainer]; + // 默认展示“热门” + [self switchToIndex:0 animated:NO]; + } + return self; +} + +- (HWBackgroundConfig *)backgroundConfig { + HWBackgroundConfig *config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault]; + config.backgroundAlpha = 0; + config.blurTintColor = [UIColor clearColor]; + return config; +} + +- (UIView *)customIndicatorView { + if (!_indicator) _indicator = [KBDirectionIndicatorView new]; + return _indicator; +} + +// 弹窗展示动画完成:根据当前展示状态设置一次箭头图 +- (void)panModalTransitionDidFinish { + [self kb_updateDragArrowForState:self.hw_presentationState]; +} + +- (void)didChangeTransitionToState:(PresentationState)state { + // 每次状态切换完成后刷新顶部箭头 + [self kb_updateDragArrowForState:state]; +} + +- (PanModalHeight)shortFormHeight { + return PanModalHeightMake(PanModalHeightTypeMaxTopInset, self.minHeight); +} + +- (PanModalHeight)longFormHeight { + return PanModalHeightMake(PanModalHeightTypeMaxTopInset, self.topInset ?: 100); +} + +- (PresentationState)originPresentationState { + return PresentationStateShort; // 初始就以最小高度展示 +} + +- (BOOL)anchorModalToLongForm { + return YES; // 到 long 后不再继续往上拖 +} + +- (BOOL)allowsPullDownWhenShortState { + return NO; // 在 short 状态禁止继续往下拉(锁住最小高度) +} + +- (CGFloat)topOffset{ + return 0.001; +} + +/// 允许时间穿透 +- (BOOL)allowsTouchEventsPassingThroughTransitionView { + return YES; +} + +-(BOOL)shouldAutoSetPanScrollContentInset{ + return NO; +} + + +- (UIScrollView *)panScrollable { + if (self.currentIndex == 0) { + return self.hotVC.tableView; + } + return self.rankVC.collectionView; +} + +// 可选:完全不允许拖拽关闭(避免被拉到底消失) +- (BOOL)allowsDragToDismiss { + return NO; +} +// +//- (BOOL)showDragIndicator{ +// return NO; +//} +// +// 点背景不关闭 +- (BOOL)allowsTapBackgroundToDismiss { + return NO; +} + +// 出现时不做上推动画(瞬时到位)开了下拉动画有问题 +//- (NSTimeInterval)transitionDuration { +// return 0; +//} + +//// 可选:关闭触觉反馈,避免出现时的轻微震动 +//- (BOOL)isHapticFeedbackEnabled { +// return NO; +//} + + +#pragma mark - UI + +- (void)setupTopButtonsAndContainer { + + // 添加最大的白色容器 + [self addSubview:self.bigWhiteContentView]; + + [self.bigWhiteContentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self).inset(0); + make.top.equalTo(self).offset(40); + make.bottom.equalTo(self); + }]; + + [self.bigWhiteContentView addSubview:self.secWhiteContentView]; + [self.secWhiteContentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self).inset(0); + make.top.equalTo(self.bigWhiteContentView).offset(40); + make.bottom.equalTo(self.bigWhiteContentView); + }]; + + [self.secWhiteContentView addSubview:self.leftBgImageView]; + [self.secWhiteContentView addSubview:self.rightBgImageView]; + + [self.leftBgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.equalTo(self.secWhiteContentView); +// make.bottom.equalTo(self.secWhiteContentView); + }]; + [self.rightBgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.equalTo(self.secWhiteContentView); +// make.bottom.equalTo(self.secWhiteContentView); + }]; + + + // 顶部栏 + [self.secWhiteContentView addSubview:self.topBar]; + [self.secWhiteContentView addSubview:self.contentContainerView]; + // 顶部拖拽方向箭头(放在顶部栏之上) + [self addSubview:self.dragArrowImageView]; + + // 调整层级:将人物与皇冠图放到左右背景图的后面(z 轴更低) + [self.secWhiteContentView insertSubview:self.personImageView belowSubview:self.leftBgImageView]; + [self.secWhiteContentView insertSubview:self.hgImageView belowSubview:self.rightBgImageView]; + + // 固定各层 zPosition,避免插入顺序导致的偶发层级问题(背景 < 人/皇冠 < 磨砂 < 顶部栏) + self.leftBgImageView.layer.zPosition = 0; + self.rightBgImageView.layer.zPosition = 0; + self.personImageView.layer.zPosition = 1; + self.hgImageView.layer.zPosition = 1; + self.topBar.layer.zPosition = 3; + +// [self.topBar addSubview:self.leftImageView]; +// [self.topBar addSubview:self.rightImageView]; + + + + // 两个按钮 + self.hotButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.hotButton setTitle:@"Ranking List" forState:UIControlStateNormal]; + [self.hotButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal]; + [self.hotButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; + self.hotButton.titleLabel.font = [UIFont boldSystemFontOfSize:16]; + self.hotButton.tag = 0; + [self.hotButton addTarget:self action:@selector(onTapTopButton:) forControlEvents:UIControlEventTouchUpInside]; + [self.topBar addSubview:self.hotButton]; + + self.rankButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.rankButton setTitle:@"Persona circle" forState:UIControlStateNormal]; + [self.rankButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal]; + [self.rankButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; + self.rankButton.titleLabel.font = [UIFont boldSystemFontOfSize:16]; + self.rankButton.tag = 1; + [self.rankButton addTarget:self action:@selector(onTapTopButton:) forControlEvents:UIControlEventTouchUpInside]; + [self.topBar addSubview:self.rankButton]; + + // 下划线(跟随选中按钮) + [self.topBar addSubview:self.underlineImageView]; + + // Masonry 约束 + CGFloat topPadding = 12; // 与顶部小指示器留点空间 + [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.secWhiteContentView); + make.top.equalTo(self.secWhiteContentView).offset(topPadding); + make.height.mas_equalTo(54); + }]; + + // 将箭头放在顶部栏上方,居中显示 + [self.dragArrowImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.topBar); + make.bottom.equalTo(self.topBar.mas_top).offset(-20); + make.width.mas_equalTo(18); + make.height.mas_equalTo(18); + }]; + + [self.hotButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.topBar).offset(3); + make.left.equalTo(self.topBar); + }]; + [self.rankButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.hotButton); + make.right.equalTo(self.topBar); + make.left.equalTo(self.hotButton.mas_right); + make.width.equalTo(self.hotButton); + }]; + + // 初始先放在“热门”下方,宽度稍小于按钮文字 + [self.underlineImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(5); + make.bottom.equalTo(self.topBar.mas_bottom).offset(-14); + make.centerX.equalTo(self.hotButton).offset(-0); + make.width.mas_equalTo(78); + }]; + + [self.contentContainerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.topBar.mas_bottom).offset(8); + make.left.right.equalTo(self.secWhiteContentView).inset(20); + make.bottom.equalTo(self.secWhiteContentView); + }]; + + [self.personImageView mas_makeConstraints:^(MASConstraintMaker *make) { + // 仍按页面整体的左右边距定位,保持与改层级前的视觉一致 + make.left.equalTo(self).offset(46); + make.bottom.equalTo(self.topBar.mas_top).offset(11); + make.width.mas_equalTo(53); + make.height.mas_equalTo(81); + }]; + + [self.hgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self).offset(-38); + make.bottom.equalTo(self.topBar.mas_top).offset(16); + make.width.mas_equalTo(82); + make.height.mas_equalTo(66); + }]; + +} + +#pragma mark - Action + +- (void)onTapTopButton:(UIButton *)sender { + [self switchToIndex:sender.tag animated:false]; +// [self hw_panModalSetNeedsLayoutUpdate]; +} + +#pragma mark - Switch Child + +- (void)switchToIndex:(NSInteger)index animated:(BOOL)animated { + self.currentIndex = index; + UIViewController *target = (index == 0) ? self.hotVC : self.rankVC; + if (!target) { + if (index == 0) { + self.hotVC = [HomeHotVC new]; + target = self.hotVC; + } else { + self.rankVC = [HomeRankVC new]; + target = self.rankVC; + } + } + + if (self.currentChild == target) { + // 已经是目标 + [self updateButtonStateForIndex:index animated:animated]; + return; + } + + // 移除当前 + if (self.currentChild) { + [self.currentChild willMoveToParentViewController:nil]; + [self.currentChild.view removeFromSuperview]; + [self.currentChild removeFromParentViewController]; + } + + // 添加目标 +// [self addChildViewController:target]; + [self.contentContainerView addSubview:target.view]; + [target.view mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.right.equalTo(self.contentContainerView); + make.bottom.equalTo(self.contentContainerView).offset(-KB_TABBAR_HEIGHT); + }]; +// [target didMoveToParentViewController:self]; + self.currentChild = target; + [self updateButtonStateForIndex:index animated:animated]; +} + +- (void)updateButtonStateForIndex:(NSInteger)index animated:(BOOL)animated { + self.hotButton.selected = (index == 0); + self.rankButton.selected = (index == 1); + + UIButton *btn = (index == 0) ? self.hotButton : self.rankButton; + // 更新下划线位置 + [self.underlineImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(5); + make.bottom.equalTo(self.topBar.mas_bottom).offset(-15); + make.centerX.equalTo(btn).offset(index == 0 ? -6 : -11); + make.width.mas_equalTo(78); + }]; + if (index == 0) { + self.leftBgImageView.hidden = NO; + self.rightBgImageView.hidden = YES; + self.personImageView.hidden = YES; + self.hgImageView.hidden = NO; + } else { + self.leftBgImageView.hidden = YES; + self.rightBgImageView.hidden = NO; + self.personImageView.hidden = NO; + self.hgImageView.hidden = YES; + } + + // 确认层级:把可见的装饰图放到当前背景图后面 + UIView *visibleBg = self.rightBgImageView.hidden ? self.leftBgImageView : self.rightBgImageView; + if (!self.hgImageView.hidden) { + [self.secWhiteContentView insertSubview:self.hgImageView belowSubview:visibleBg]; + } + if (!self.personImageView.hidden) { + [self.secWhiteContentView insertSubview:self.personImageView belowSubview:visibleBg]; + } + + if (animated) { + [UIView animateWithDuration:0.25 animations:^{ + [self.topBar layoutIfNeeded]; + }]; + } else { + [self.topBar layoutIfNeeded]; + } +} + +- (UIView *)bigWhiteContentView{ + if (!_bigWhiteContentView) { + _bigWhiteContentView = [[UIView alloc] init]; + _bigWhiteContentView.backgroundColor = [UIColor whiteColor]; + _bigWhiteContentView.layer.cornerRadius = 40; + // 不裁剪子视图,避免顶部装饰图越界部分被截断 + _bigWhiteContentView.layer.masksToBounds = NO; // 等同于 clipsToBounds = NO + } + return _bigWhiteContentView; +} + +- (UIView *)secWhiteContentView{ + if (!_secWhiteContentView) { + _secWhiteContentView = [[UIView alloc] init]; + } + return _secWhiteContentView; +} + +- (UIImageView *)hgImageView{ + if (!_hgImageView) { + _hgImageView = [[UIImageView alloc] init]; + _hgImageView.image = [UIImage imageNamed:@"home_hg_icon"]; + _hgImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _hgImageView; +} + +- (UIImageView *)personImageView{ + if (!_personImageView) { + _personImageView = [[UIImageView alloc] init]; + _personImageView.image = [UIImage imageNamed:@"home_person_icon"]; + _personImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _personImageView; +} + + +- (UIView *)topBar{ + if (!_topBar) { + _topBar = [[UIView alloc] init]; + } + return _topBar; +} + +- (UIView *)contentContainerView{ + if (!_contentContainerView) { + _contentContainerView = [[UIView alloc] init]; + } + return _contentContainerView; +} + +- (UIImageView *)underlineImageView{ + if (!_underlineImageView) { + _underlineImageView = [[UIImageView alloc] init]; + _underlineImageView.image = [UIImage imageNamed:@"home_bar_underline"]; + } + return _underlineImageView; +} + +// 顶部拖拽方向箭头 +- (UIImageView *)dragArrowImageView { + if (!_dragArrowImageView) { + _dragArrowImageView = [[UIImageView alloc] init]; + _dragArrowImageView.contentMode = UIViewContentModeScaleAspectFit; + // 初始在 Short 状态,显示向上的箭头 + _dragArrowImageView.image = [UIImage imageNamed:@"home_up_arrow"]; + } + return _dragArrowImageView; +} + +// 根据弹窗展示状态切换箭头图 +- (void)kb_updateDragArrowForState:(PresentationState)state { + NSString *imgName = (state == PresentationStateMedium) ? @"home_down_arrow" : @"home_up_arrow"; + UIImage *img = [UIImage imageNamed:imgName]; + if (img && self.dragArrowImageView.image != img) { + // 柔和切换,避免频繁拖拽时突兀 + [UIView transitionWithView:self.dragArrowImageView + duration:0.18 + options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionBeginFromCurrentState + animations:^{ + self.dragArrowImageView.image = img; + } completion:nil]; + } +} + + +- (UIImageView *)leftBgImageView{ + if (!_leftBgImageView) { + _leftBgImageView = [[UIImageView alloc] init]; + _leftBgImageView.image = [UIImage imageNamed:@"home_left_bg"]; + } + return _leftBgImageView; +} + +- (UIImageView *)rightBgImageView{ + if (!_rightBgImageView) { + _rightBgImageView = [[UIImageView alloc] init]; + _rightBgImageView.image = [UIImage imageNamed:@"home_right_bg"]; + } + return _rightBgImageView; +} + +@end diff --git a/keyBoard/Class/Home/V/KBTopImageButton.h b/keyBoard/Class/Home/V/KBTopImageButton.h new file mode 100644 index 0000000..e1307da --- /dev/null +++ b/keyBoard/Class/Home/V/KBTopImageButton.h @@ -0,0 +1,25 @@ +// +// KBTopImageButton.h +// keyBoard +// +// 上图下文按钮:支持自定义图标尺寸与上下间距 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBTopImageButton : UIControl +/// 图标视图 +@property (nonatomic, strong, readonly) UIImageView *iconView; +/// 文本标签 +@property (nonatomic, strong, readonly) UILabel *textLabel; +/// 图片与文字之间的间距,默认 6 +@property (nonatomic, assign) CGFloat spacing; +/// 图标尺寸,默认 44x44 +@property (nonatomic, assign) CGSize iconSize; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Home/V/KBTopImageButton.m b/keyBoard/Class/Home/V/KBTopImageButton.m new file mode 100644 index 0000000..9cc985f --- /dev/null +++ b/keyBoard/Class/Home/V/KBTopImageButton.m @@ -0,0 +1,61 @@ +// +// KBTopImageButton.m +// keyBoard +// +// 上图下文按钮:图片在上、文字在下,内部简单布局,适合图标型功能入口 +// + +#import "KBTopImageButton.h" +#import "UIColor+Extension.h" + +@interface KBTopImageButton() +@property (nonatomic, strong) UIImageView *iconView; +@property (nonatomic, strong) UILabel *textLabel; +@end + +@implementation KBTopImageButton + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + _spacing = 6; + _iconSize = CGSizeMake(44, 44); + + _iconView = [[UIImageView alloc] init]; + _iconView.contentMode = UIViewContentModeScaleAspectFit; + [self addSubview:_iconView]; + + _textLabel = [[UILabel alloc] init]; + _textLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightSemibold]; + _textLabel.textColor = [UIColor colorWithHex:0x2B2B2B]; + _textLabel.textAlignment = NSTextAlignmentCenter; + _textLabel.numberOfLines = 2; + [self addSubview:_textLabel]; + } + return self; +} + +- (CGSize)intrinsicContentSize { + CGFloat width = MAX(_iconSize.width, 60); + return CGSizeMake(width, _iconSize.height + _spacing + 34); +} + +- (void)layoutSubviews { + [super layoutSubviews]; + CGFloat W = CGRectGetWidth(self.bounds); + CGFloat H = CGRectGetHeight(self.bounds); + CGSize iconS = self.iconSize; + CGFloat ix = (W - iconS.width) * 0.5; + self.iconView.frame = CGRectMake(ix, 0, iconS.width, iconS.height); + + CGFloat labelTop = CGRectGetMaxY(self.iconView.frame) + self.spacing; + CGFloat lh = MAX(0, H - labelTop); + self.textLabel.frame = CGRectMake(0, labelTop, W, lh); +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + self.alpha = highlighted ? 0.6 : 1.0; +} + +@end + diff --git a/keyBoard/Class/Home/V/KBTopThreeView.h b/keyBoard/Class/Home/V/KBTopThreeView.h new file mode 100644 index 0000000..1b0b882 --- /dev/null +++ b/keyBoard/Class/Home/V/KBTopThreeView.h @@ -0,0 +1,21 @@ +// +// KBTopThreeView.h +// keyBoard +// +// 顶部前三名展示视图:内部横向三栏,样式参考设计图。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 用于 HomeHot 顶部展示前三名的视图 +@interface KBTopThreeView : UIView + +/// 配置三项内容(数组元素可传 @{ @"title":NSString, @"rank":@(1/2/3) }) +- (void)configWithItems:(NSArray *)items; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Home/V/KBTopThreeView.m b/keyBoard/Class/Home/V/KBTopThreeView.m new file mode 100644 index 0000000..be5fe95 --- /dev/null +++ b/keyBoard/Class/Home/V/KBTopThreeView.m @@ -0,0 +1,262 @@ +// +// KBTopThreeView.m +// keyBoard +// + +#import "KBTopThreeView.h" + +@interface KBTopThreeCardView : UIView +/// 头像占位(圆形描边) +@property (nonatomic, strong) UIView *avatarCircleView; +/// 彩条卡片背景 +@property (nonatomic, strong) UIImageView *cardImageView; +/// 标题 +@property (nonatomic, strong) UILabel *titleLabel; + +/// 渲染 +- (void)renderWithTitle:(NSString *)title rank:(NSInteger)rank; +@end + +@implementation KBTopThreeCardView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + // 卡片 + [self addSubview:self.cardImageView]; + // 头像圆圈 + [self addSubview:self.avatarCircleView]; + [self.cardImageView addSubview:self.titleLabel]; + + // 布局 + [self.avatarCircleView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self); + make.centerX.equalTo(self); + make.width.height.mas_equalTo(68); + }]; + + [self.cardImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.avatarCircleView.mas_bottom).offset(-34); // 顶部悬浮重叠 + make.left.right.equalTo(self); + make.height.mas_equalTo(KBFit(158)); + }]; + + + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.cardImageView); + make.top.equalTo(self.cardImageView).offset(84); + }]; + +} + +- (void)renderWithTitle:(NSString *)title rank:(NSInteger)rank { + self.titleLabel.text = title.length ? title : @""; + + // 不同名次数的配色 + UIColor *theme; + UIImage *image; + switch (rank) { + case 1: + { + theme = [UIColor colorWithRed:1.00 green:0.86 blue:0.43 alpha:1.0]; + image = [UIImage imageNamed:@"home_rank_1"]; + } + break; // 金 + case 2: { + theme = [UIColor colorWithRed:0.68 green:0.80 blue:1.00 alpha:1.0]; + image = [UIImage imageNamed:@"home_rank_2"]; + } + break; // 蓝 + default: { + theme = [UIColor colorWithRed:1.00 green:0.78 blue:0.63 alpha:1.0]; + image = [UIImage imageNamed:@"home_rank_3"]; + + } break; // 橙 + } + self.cardImageView.image = image; + // 加号按钮移至 KBTopThreeView,由其统一控制样式与布局 + + // 圆圈描边 + self.avatarCircleView.layer.borderColor = [UIColor colorWithRed:0.83 green:0.95 blue:0.27 alpha:1.0].CGColor; +} + +#pragma mark - Lazy + +- (UIView *)avatarCircleView { + if (!_avatarCircleView) { + _avatarCircleView = [[UIView alloc] init]; + _avatarCircleView.backgroundColor = [UIColor whiteColor]; + _avatarCircleView.layer.cornerRadius = 34; + _avatarCircleView.layer.borderWidth = 2.0; + _avatarCircleView.layer.borderColor = [UIColor colorWithWhite:0.9 alpha:1].CGColor; + // 可在此加入头像 UIImageView + } + return _avatarCircleView; +} + +- (UIImageView *)cardImageView { + if (!_cardImageView) { + _cardImageView = [[UIImageView alloc] init]; + } + return _cardImageView; +} + + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.textColor = [UIColor colorWithWhite:0.1 alpha:1]; + _titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +// 此类不再持有 plusButton + +@end + + +@interface KBTopThreeView() +@property (nonatomic, strong) KBTopThreeCardView *leftCard; +@property (nonatomic, strong) KBTopThreeCardView *centerCard; +@property (nonatomic, strong) KBTopThreeCardView *rightCard; +/// 统一的底部加号按钮(移出卡片,放到 KBTopThreeView) +@property (nonatomic, strong) UIButton *plusButton; +/// 左右卡片底部也有 plus 按钮 +@property (nonatomic, strong) UIButton *leftPlusButton; +@property (nonatomic, strong) UIButton *rightPlusButton; +@end + +@implementation KBTopThreeView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor whiteColor]; + [self setupUI]; + } + return self; +} + +- (void)setupUI { + [self addSubview:self.leftCard]; + [self addSubview:self.centerCard]; + [self addSubview:self.rightCard]; + [self addSubview:self.plusButton]; + [self addSubview:self.leftPlusButton]; + [self addSubview:self.rightPlusButton]; + + // 横向均分布局 + [self.centerCard mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self).offset(8); + make.width.mas_equalTo(KBFit(96)); + make.height.mas_equalTo(KBFit(180)); + }]; + // 第二、三名比第一名矮一点:顶部向下偏移 + CGFloat sideTopDelta = 12.0; // 侧边两张比中间低 12pt(可按设计调整) + [self.leftCard mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.centerCard).offset(sideTopDelta); + make.right.equalTo(self.centerCard.mas_left).offset(-8); + make.width.equalTo(self.centerCard); + // 与中间卡片底部对齐,通过高度差体现“更矮” + make.height.equalTo(self.centerCard); + }]; + [self.rightCard mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.centerCard).offset(sideTopDelta); + make.left.equalTo(self.centerCard.mas_right).offset(8); + make.width.equalTo(self.centerCard); + make.height.equalTo(self.centerCard); + }]; + + // 用 plusButton 来“撑起”本视图,且底部对齐 + [self.plusButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.centerCard.mas_bottom).offset(12); + make.centerX.equalTo(self); // 或改为 equalTo(self.centerCard) 以严格与中卡居中 + make.width.mas_equalTo(60); + make.height.mas_equalTo(28); + make.bottom.equalTo(self).offset(-8); + }]; + + // 左右 plus 按钮,同样底部对齐,用它们一起撑起视图 + [self.leftPlusButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.leftCard.mas_bottom).offset(12); + make.centerX.equalTo(self.leftCard); + make.width.height.equalTo(self.plusButton); + make.bottom.equalTo(self).offset(-8); + }]; + [self.rightPlusButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.rightCard.mas_bottom).offset(12); + make.centerX.equalTo(self.rightCard); + make.width.height.equalTo(self.plusButton); + make.bottom.equalTo(self).offset(-8); + }]; +} + +- (void)configWithItems:(NSArray *)items { + // items 顺序任意,这里按 rank 分配:1 放中间,2 左,3 右 + NSString *t1 = @"", *t2 = @"", *t3 = @""; + for (NSDictionary *d in items) { + NSInteger r = [d[@"rank"] integerValue]; + NSString *title = d[@"title"] ?: @""; + if (r == 1) t1 = title; + else if (r == 2) t2 = title; + else if (r == 3) t3 = title; + } + [self.centerCard renderWithTitle:t1 rank:1]; + [self.leftCard renderWithTitle:t2 rank:2]; + [self.rightCard renderWithTitle:t3 rank:3]; +} + +#pragma mark - Lazy +- (KBTopThreeCardView *)leftCard { if (!_leftCard) _leftCard = [KBTopThreeCardView new]; return _leftCard; } +- (KBTopThreeCardView *)centerCard { if (!_centerCard) _centerCard = [KBTopThreeCardView new]; return _centerCard; } +- (KBTopThreeCardView *)rightCard { if (!_rightCard) _rightCard = [KBTopThreeCardView new]; return _rightCard; } + +- (UIButton *)plusButton { + if (!_plusButton) { + _plusButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_plusButton setTitle:@"+" forState:UIControlStateNormal]; + [_plusButton setTitleColor:[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] forState:UIControlStateNormal]; + _plusButton.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _plusButton.layer.cornerRadius = 14.0; + _plusButton.layer.masksToBounds = YES; + // 默认浅色背景,可按需要在外层配置 + _plusButton.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + } + return _plusButton; +} + +- (UIButton *)leftPlusButton { + if (!_leftPlusButton) { + _leftPlusButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_leftPlusButton setTitle:@"+" forState:UIControlStateNormal]; + [_leftPlusButton setTitleColor:[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] forState:UIControlStateNormal]; + _leftPlusButton.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _leftPlusButton.layer.cornerRadius = 14.0; + _leftPlusButton.layer.masksToBounds = YES; + _leftPlusButton.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + } + return _leftPlusButton; +} + +- (UIButton *)rightPlusButton { + if (!_rightPlusButton) { + _rightPlusButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_rightPlusButton setTitle:@"+" forState:UIControlStateNormal]; + [_rightPlusButton setTitleColor:[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] forState:UIControlStateNormal]; + _rightPlusButton.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _rightPlusButton.layer.cornerRadius = 14.0; + _rightPlusButton.layer.masksToBounds = YES; + _rightPlusButton.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + } + return _rightPlusButton; +} + +@end diff --git a/keyBoard/Class/Home/VC/KBLangTestVC.h b/keyBoard/Class/Home/VC/FunctionTest/KBLangTestVC.h similarity index 100% rename from keyBoard/Class/Home/VC/KBLangTestVC.h rename to keyBoard/Class/Home/VC/FunctionTest/KBLangTestVC.h diff --git a/keyBoard/Class/Home/VC/KBLangTestVC.m b/keyBoard/Class/Home/VC/FunctionTest/KBLangTestVC.m similarity index 100% rename from keyBoard/Class/Home/VC/KBLangTestVC.m rename to keyBoard/Class/Home/VC/FunctionTest/KBLangTestVC.m diff --git a/keyBoard/Class/Home/VC/FunctionTest/KBSkinCenterVC.h b/keyBoard/Class/Home/VC/FunctionTest/KBSkinCenterVC.h new file mode 100644 index 0000000..6c8ecc2 --- /dev/null +++ b/keyBoard/Class/Home/VC/FunctionTest/KBSkinCenterVC.h @@ -0,0 +1,11 @@ +// +// KBSkinCenterVC.h +// 简单的皮肤中心:展示两款示例皮肤,点击“下载并应用”后立即同步到键盘扩展。 +// + +#import + +@interface KBSkinCenterVC : UIViewController + +@end + diff --git a/keyBoard/Class/Home/VC/FunctionTest/KBSkinCenterVC.m b/keyBoard/Class/Home/VC/FunctionTest/KBSkinCenterVC.m new file mode 100644 index 0000000..5a097bd --- /dev/null +++ b/keyBoard/Class/Home/VC/FunctionTest/KBSkinCenterVC.m @@ -0,0 +1,132 @@ +// +// KBSkinCenterVC.m +// + +#import "KBSkinCenterVC.h" +#import "Masonry.h" +#import "KBNetworkManager.h" +#import "KBSkinManager.h" +#import "KBHUD.h" + +@interface KBSkinCell : UITableViewCell +@property (nonatomic, strong) UIButton *applyBtn; +@end + +@implementation KBSkinCell +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.selectionStyle = UITableViewCellSelectionStyleNone; + _applyBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [_applyBtn setTitle:@"下载并应用" forState:UIControlStateNormal]; + _applyBtn.layer.cornerRadius = 6; _applyBtn.layer.borderWidth = 1; + _applyBtn.layer.borderColor = [UIColor colorWithWhite:0.85 alpha:1].CGColor; + [self.contentView addSubview:_applyBtn]; + [_applyBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.contentView).offset(-16); + make.centerY.equalTo(self.contentView); + make.width.mas_equalTo(110); + make.height.mas_equalTo(34); + }]; + } + return self; +} +@end + +@interface KBSkinCenterVC () +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, copy) NSArray *skins; // id, name, img(url relative to KB_BASE_URL) +@end + +@implementation KBSkinCenterVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.title = @"皮肤中心"; + self.view.backgroundColor = [UIColor whiteColor]; + // 绝对 URL 的测试皮肤图片(无需 KB_BASE_URL)。 + // 说明:使用 picsum.photos 的固定 id,稳定可直接访问。 + self.skins = @[ + @{ @"id": @"aurora", @"name": @"极光", @"img": @"https://picsum.photos/id/1018/1600/900.jpg" }, + @{ @"id": @"alps", @"name": @"雪山", @"img": @"https://picsum.photos/id/1016/1600/900.jpg" }, + @{ @"id": @"lake", @"name": @"湖面", @"img": @"https://picsum.photos/id/1039/1600/900.jpg" }, + ]; + + self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.tableView.delegate = self; self.tableView.dataSource = self; + [self.view addSubview:self.tableView]; +} + +#pragma mark - UITableView + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.skins.count; } + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *cid = @"skin.cell"; + KBSkinCell *cell = [tableView dequeueReusableCellWithIdentifier:cid]; + if (!cell) { cell = [[KBSkinCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cid]; } + NSDictionary *skin = self.skins[indexPath.row]; + cell.textLabel.text = skin[@"name"]; cell.detailTextLabel.text = skin[@"id"]; + [cell.applyBtn removeTarget:nil action:NULL forControlEvents:UIControlEventTouchUpInside]; + [cell.applyBtn addTarget:self action:@selector(onApplyBtn:) forControlEvents:UIControlEventTouchUpInside]; + cell.applyBtn.tag = indexPath.row; + return cell; +} + +- (void)onApplyBtn:(UIButton *)sender { + NSInteger idx = sender.tag; + if (idx < 0 || idx >= self.skins.count) return; + NSDictionary *skin = self.skins[idx]; + NSString *path = skin[@"img"] ?: @""; // 相对 KB_BASE_URL + + // 下载图片数据(非 JSON 将以 NSData 返回) + [[KBNetworkManager shared] GET:path parameters:nil headers:nil completion:^(id jsonOrData, NSURLResponse *response, NSError *error) { + NSData *data = ([jsonOrData isKindOfClass:NSData.class] ? (NSData *)jsonOrData : nil); + // 尝试压缩尺寸,避免 Keychain 过大:将宽度限制到 1500px + if (data && data.length > 0) { + UIImage *img = [UIImage imageWithData:data]; + if (img) { + CGFloat maxW = 1500.0; + if (img.size.width > maxW) { + CGFloat scale = maxW / img.size.width; + CGSize newSize = CGSizeMake(maxW, floor(img.size.height * scale)); + UIGraphicsBeginImageContextWithOptions(newSize, YES, 1.0); + [img drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; + UIImage *resized = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + img = resized ?: img; + } + data = UIImageJPEGRepresentation(img, 0.85) ?: data; // 压成 JPEG + } + } + dispatch_async(dispatch_get_main_queue(), ^{ + NSData *payload = data; + if (payload.length == 0) { + // 兜底:生成一张简单渐变图片 + CGSize size = CGSizeMake(1200, 600); + UIGraphicsBeginImageContextWithOptions(size, YES, 1.0); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + UIColor *c1 = [UIColor colorWithRed:0.76 green:0.91 blue:0.86 alpha:1]; + UIColor *c2 = [UIColor colorWithRed:0.93 green:0.97 blue:0.91 alpha:1]; + if ([skin[@"id"] hasPrefix:@"dark"]) { + c1 = [UIColor colorWithRed:0.1 green:0.12 blue:0.16 alpha:1]; + c2 = [UIColor colorWithRed:0.22 green:0.24 blue:0.28 alpha:1]; + } + CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); + NSArray *colors = @[(__bridge id)c1.CGColor, (__bridge id)c2.CGColor]; + CGFloat locs[] = {0,1}; + CGGradientRef grad = CGGradientCreateWithColors(space, (__bridge CFArrayRef)colors, locs); + CGContextDrawLinearGradient(ctx, grad, CGPointZero, CGPointMake(size.width, size.height), 0); + CGGradientRelease(grad); CGColorSpaceRelease(space); + UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + payload = UIImageJPEGRepresentation(img, 0.9); + } + BOOL ok = (payload.length > 0) ? [[KBSkinManager shared] applyImageSkinWithData:payload skinId:skin[@"id"] name:skin[@"name"]] : NO; + [KBHUD showInfo:(ok ? @"已应用,切到键盘查看" : @"应用失败")]; + }); + }]; +} + +@end diff --git a/keyBoard/Class/Home/VC/FunctionTest/KBTestVC.h b/keyBoard/Class/Home/VC/FunctionTest/KBTestVC.h new file mode 100644 index 0000000..d6e38ef --- /dev/null +++ b/keyBoard/Class/Home/VC/FunctionTest/KBTestVC.h @@ -0,0 +1,16 @@ +// +// KBTestVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBTestVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/FunctionTest/KBTestVC.m b/keyBoard/Class/Home/VC/FunctionTest/KBTestVC.m new file mode 100644 index 0000000..dc9b451 --- /dev/null +++ b/keyBoard/Class/Home/VC/FunctionTest/KBTestVC.m @@ -0,0 +1,94 @@ +// +// KBTestVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "KBTestVC.h" +#import "KBGuideVC.h" +#import "KBLangTestVC.h" +@interface KBTestVC () +@property (nonatomic, strong) UITextView *textView; // 作为表头,保持原有键盘测试 +@property (nonatomic, strong) BaseTableView *tableView; // 首页列表 +@property (nonatomic, copy) NSArray *items; // 简单数据源 +@end + +@implementation KBTestVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + + CGFloat width = [UIScreen mainScreen].bounds.size.width; + UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 220)]; + CGRect frame = CGRectMake(16, 16, width - 32, 188); + self.textView = [[UITextView alloc] initWithFrame:frame]; + self.textView.text = KBLocalized(@"home_input_placeholder"); + self.textView.layer.borderColor = [UIColor blackColor].CGColor; + self.textView.layer.borderWidth = 0.5; + [header addSubview:self.textView]; + + // 列表 + self.tableView = [[BaseTableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; + self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.tableView.delegate = self; + self.tableView.dataSource = self; + self.tableView.tableHeaderView = header; + [self.view addSubview:self.tableView]; + + self.items = @[ KBLocalized(@"home_item_lang_test"), KBLocalized(@"home_item_keyboard_permission"), @"皮肤中心" ]; + + dispatch_async(dispatch_get_main_queue(), ^{ [self.textView becomeFirstResponder]; }); + + [[KBNetworkManager shared] GET:@"app/config" parameters:nil headers:nil completion:^(id _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) { + NSLog(@"===="); + }]; +} + +- (void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + self.title = KBLocalized(@"home_title"); + self.items = @[ KBLocalized(@"home_item_lang_test"), KBLocalized(@"home_item_keyboard_permission"), @"皮肤中心" ]; + [self.tableView reloadData]; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ +// KBGuideVC *vc = [[KBGuideVC alloc] init]; +// [self.navigationController pushViewController:vc animated:true]; +// [KBHUD showInfo:@"加载中..."]; +// [KBHUD show]; +// [KBHUD showAllowTapToDismiss:true]; +} + +#pragma mark - UITableViewDataSource +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.items.count; } +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *cellId = @"home.cell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; + if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; } + cell.textLabel.text = self.items[indexPath.row]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + return cell; +} + +#pragma mark - UITableViewDelegate +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (indexPath.row == 0) { + // 多语言测试页 + KBLangTestVC *vc = [KBLangTestVC new]; + [self.navigationController pushViewController:vc animated:YES]; + } else if (indexPath.row == 1) { + // 键盘权限引导页 + KBGuideVC *vc = [KBGuideVC new]; + [self.navigationController pushViewController:vc animated:YES]; + } else if (indexPath.row == 2) { + // 皮肤中心 + UIViewController *vc = [NSClassFromString(@"KBSkinCenterVC") new]; + if (vc) { [self.navigationController pushViewController:vc animated:YES]; } + } +} +@end diff --git a/keyBoard/Class/Home/VC/HomeHotVC.h b/keyBoard/Class/Home/VC/HomeHotVC.h new file mode 100644 index 0000000..37b2ab3 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeHotVC.h @@ -0,0 +1,17 @@ +// +// HomeHotVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeHotVC : BaseViewController +// 列表 +@property (nonatomic, strong) BaseTableView *tableView; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/HomeHotVC.m b/keyBoard/Class/Home/VC/HomeHotVC.m new file mode 100644 index 0000000..1a8e47d --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeHotVC.m @@ -0,0 +1,110 @@ +// +// HomeHotVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "HomeHotVC.h" +// 视图 +#import "KBTopThreeView.h" +#import "HomeHotCell.h" +#import "HomeRankVC.h" +#import "KBSearchVC.h" + +#import +@interface HomeHotVC () + +// 顶部前三名视图 +@property (nonatomic, strong) KBTopThreeView *topThreeView; + +@property (nonatomic, strong) NSArray *dataSource; // 简单模拟数据 + +@end + +@interface HomeHotVC () + +@end + +@implementation HomeHotVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // 构建数据(演示) + self.dataSource = @[ + @{@"rank":@4, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@NO}, + @{@"rank":@5, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@YES}, + @{@"rank":@6, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@NO}, + @{@"rank":@7, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@NO} + ]; + + // 搭建 UI + [self.view addSubview:self.tableView]; + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; + + // 顶部前三名作为 tableHeaderView(注意:tableHeaderView 需设定明确高度) + CGFloat headerH = 280.0; + self.topThreeView = [[KBTopThreeView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, headerH)]; + // 示例配置:三个条目的标题 + [self.topThreeView configWithItems:@[ + @{@"title":@"High EQ", @"rank":@1}, + @{@"title":@"Flirt Girls", @"rank":@2}, + @{@"title":@"Humorous", @"rank":@3} + ]]; + self.tableView.tableHeaderView = self.topThreeView; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.dataSource.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + HomeHotCell *cell = [tableView dequeueReusableCellWithIdentifier:HomeHotCell.reuseId forIndexPath:indexPath]; + NSDictionary *item = self.dataSource[indexPath.row]; + // 配置 cell + [cell configWithRank:[item[@"rank"] integerValue] + title:item[@"title"] + subtitle:item[@"sub"] + joined:[item[@"joined"] boolValue]]; + return cell; +} + +#pragma mark - UITableViewDelegate + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 84.0; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +// KBSearchVC *vc = [[KBSearchVC alloc] init]; +// [self.navigationController pushViewController:vc animated:true]; +// UINavigationController *nav = KB_CURRENT_NAV; +// [nav pushViewController:vc animated:true]; + NSLog(@"==="); + +} + +#pragma mark - Lazy + +- (BaseTableView *)tableView { + if (!_tableView) { + // 使用 BaseTableView,统一默认配置 + _tableView = [[BaseTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.dataSource = self; + _tableView.delegate = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 设计为卡片式,去掉系统分割线 + _tableView.showsVerticalScrollIndicator = NO; + _tableView.contentInset = UIEdgeInsetsMake(8, 0, KB_SafeAreaBottom(), 0); + [_tableView registerClass:HomeHotCell.class forCellReuseIdentifier:HomeHotCell.reuseId]; + } + return _tableView; +} + + + +@end diff --git a/keyBoard/Class/Home/VC/HomeMainVC.h b/keyBoard/Class/Home/VC/HomeMainVC.h new file mode 100644 index 0000000..fb78ed1 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeMainVC.h @@ -0,0 +1,16 @@ +// +// HomeMainVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeMainVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/HomeMainVC.m b/keyBoard/Class/Home/VC/HomeMainVC.m new file mode 100644 index 0000000..4a266b6 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeMainVC.m @@ -0,0 +1,64 @@ +// +// HomeMainVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "HomeMainVC.h" +#import "HomeHeadView.h" +#import "KBPanModalView.h" + +@interface HomeMainVC () +@property (nonatomic, strong) HomeHeadView *headView; +@property (nonatomic, strong) KBPanModalView *simplePanModalView; + +@end + +@implementation HomeMainVC + +- (void)viewDidLoad { + [super viewDidLoad]; + + UIImageView *bgImageView = [[UIImageView alloc] init]; + bgImageView.image = [UIImage imageNamed:@"home_bg_image"]; + [self.view addSubview:bgImageView]; + [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; +// CGFloat topV = (500); + + [self.view addSubview:self.headView]; + [self setupMas]; + // 创建sheetVC + self.simplePanModalView = [[KBPanModalView alloc] init]; + // 使用宏,避免误写成函数指针判断导致恒为 true + if (KB_DEVICE_HAS_NOTCH) { + self.simplePanModalView.minHeight = 473 - 44 + KB_NAV_TOTAL_HEIGHT; + }else{ + self.simplePanModalView.minHeight = 473 - 44 + KB_NAV_TOTAL_HEIGHT; +// + } + self.simplePanModalView.topInset = 100; + [self.simplePanModalView presentInView:self.view]; +} + +- (void)setupMas{ + [self.headView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT); + make.height.mas_equalTo(473 - 44); + }]; +} + + +#pragma mark - lazy +- (HomeHeadView *)headView{ + if (!_headView) { + _headView = [[HomeHeadView alloc] init]; + } + return _headView; +} + + +@end diff --git a/keyBoard/Class/Home/VC/HomeRankContentVC.h b/keyBoard/Class/Home/VC/HomeRankContentVC.h new file mode 100644 index 0000000..23553b5 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeRankContentVC.h @@ -0,0 +1,18 @@ +// +// HomeRankContentVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import +#import "JXCategoryListContainerView.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeRankContentVC : UIViewController +@property (nonatomic, strong) UICollectionView *collectionView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/HomeRankContentVC.m b/keyBoard/Class/Home/VC/HomeRankContentVC.m new file mode 100644 index 0000000..43bf2f8 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeRankContentVC.m @@ -0,0 +1,111 @@ +// +// HomeRankContentVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +@import UIKit; +#import "HomeRankContentVC.h" + +// 自定义卡片 Cell +#import "HomeRankCardCell.h" + +@interface HomeRankContentVC () +@property (nonatomic, strong) NSArray *dataSource; // 简单模拟数据 +@end + +@implementation HomeRankContentVC + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.view.backgroundColor = COLOR_WITH_RGB(246/255.0, 253/255.0, 249/255.0, 1.0); // 淡绿色背景 + + // 数据 + self.dataSource = @[ + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(NO)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(YES)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(NO)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(YES)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(NO)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(YES)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(NO)}, + @{@"title":@"High EQ", @"desc":@"Be Neither Too Close\nNor Too Distant...", @"people":@"Two Million People\nHave Used It", @"added":@(YES)} + ]; + + + [self.view addSubview:self.collectionView]; + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; +} + +- (UICollectionView *)collectionView{ + if (!_collectionView) { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.sectionInset = UIEdgeInsetsMake(16, 16, 16, 16); + layout.minimumLineSpacing = 24; + layout.minimumInteritemSpacing = 16; + + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionView.backgroundColor = [UIColor clearColor]; +// _collectionView.alwaysBounceVertical = YES; + _collectionView.bounces = false; + _collectionView.dataSource = self; + _collectionView.delegate = self; + [_collectionView registerClass:[HomeRankCardCell class] forCellWithReuseIdentifier:@"HomeRankCardCell"]; +// self.collectionView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _collectionView; +} + + +#pragma mark - UICollectionViewDataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.dataSource.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + HomeRankCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"HomeRankCardCell" forIndexPath:indexPath]; + NSDictionary *d = self.dataSource[indexPath.item]; + BOOL added = [d[@"added"] boolValue]; + [cell configureWithTitle:d[@"title"] + desc:d[@"desc"] + people:d[@"people"] + added:added]; + __weak typeof(self) weakSelf = self; + cell.onTapAction = ^{ + // 切换添加/已添加状态并刷新该项 + NSMutableArray *m = [weakSelf.dataSource mutableCopy]; + NSMutableDictionary *md = [m[indexPath.item] mutableCopy]; + BOOL cur = [md[@"added"] boolValue]; + md[@"added"] = @(!cur); + m[indexPath.item] = md; + weakSelf.dataSource = [m copy]; + [weakSelf.collectionView reloadItemsAtIndexPaths:@[indexPath]]; + }; + return cell; +} + +#pragma mark - UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + CGFloat totalHInset = 16 + 16; // section i/l/r + CGFloat spacing = 16; // interitem spacing + CGFloat w = collectionView.bounds.size.width - totalHInset; // not including section insets yet + // Two columns → each width = (width - spacing - lr insets)/2 + CGFloat cellWidth = (w - spacing) / 2.0; + // 固定高度,接近示意图比例 + CGFloat cellHeight = 234.0; + return CGSizeMake(floor(cellWidth), cellHeight); +} + + +#pragma mark - JXCategoryListContentViewDelegate +- (UIView *)listView { + return self.view; +} + +@end diff --git a/keyBoard/Class/Home/VC/HomeRankVC.h b/keyBoard/Class/Home/VC/HomeRankVC.h new file mode 100644 index 0000000..c9a3963 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeRankVC.h @@ -0,0 +1,18 @@ +// +// HomeRankVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import +#import "JXCategoryView.h" +#import "JXCategoryListContainerView.h" +NS_ASSUME_NONNULL_BEGIN + +@interface HomeRankVC : BaseViewController +// 列表 +@property (nonatomic, strong) UICollectionView *collectionView; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/HomeRankVC.m b/keyBoard/Class/Home/VC/HomeRankVC.m new file mode 100644 index 0000000..19733bb --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeRankVC.m @@ -0,0 +1,179 @@ +// +// HomeRankVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "HomeRankVC.h" +#import "HomeRankContentVC.h" +#import "KBCategoryTitleImageView.h" + +@interface HomeRankVC () +@property (nonatomic, strong) NSArray *titles; +@property (nonatomic, strong) JXCategoryTitleImageView *myCategoryView; +@property (nonatomic, strong) JXCategoryListContainerView *listContainerView; +@property (nonatomic, assign) JXCategoryTitleImageType currentType; + +@end + +@implementation HomeRankVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.titles = @[@"螃蟹啊斯柯达积分卡", @"小龙虾", @"苹果", @"胡萝卜", @"葡萄", @"西瓜"]; + [self.view addSubview:self.myCategoryView]; + [self.view addSubview:self.listContainerView]; + self.listContainerView.scrollView.scrollEnabled = false; + NSArray *imageNames = @[@"home_item_normal", @"home_item_normal", @"home_item_normal", @"home_item_normal", @"home_item_normal", @"home_item_normal"]; + NSArray *selectedImageNames = @[@"home_item_selected", @"home_item_selected", @"home_item_selected", @"home_item_selected", @"home_item_selected", @"home_item_selected"]; + + self.myCategoryView.titles = self.titles; +// self.myCategoryView.titleColorGradientEnabled = YES; + self.myCategoryView.imageInfoArray = imageNames; + self.myCategoryView.cellBackgroundSelectedColor = [UIColor blackColor]; + self.myCategoryView.cellBackgroundUnselectedColor = [UIColor colorWithHex:0xEAF8F4]; + self.myCategoryView.titleColor = [UIColor colorWithHex:0x1B1F1A]; + self.myCategoryView.titleSelectedColor = [UIColor whiteColor]; + self.myCategoryView.titleFont = [UIFont systemFontOfSize:12]; + // 关闭各种“放大”效果,保持选中与未选中宽度一致 + self.myCategoryView.titleLabelZoomEnabled = NO; // 关闭文字缩放 + self.myCategoryView.titleLabelZoomScale = 1.0; + self.myCategoryView.cellWidthZoomEnabled = NO; // 关闭cell宽度缩放 + self.myCategoryView.cellWidthZoomScale = 1.0; + + self.myCategoryView.selectedImageInfoArray = selectedImageNames; + self.myCategoryView.loadImageBlock = ^(UIImageView *imageView, id info) { + NSString *imageName = info; + imageView.image = [UIImage imageNamed:imageName]; + }; + self.myCategoryView.imageZoomEnabled = false; + self.myCategoryView.imageZoomScale = 1.3; + self.myCategoryView.averageCellSpacingEnabled = NO; + + self.myCategoryView.cellBackgroundColorGradientEnabled = true; + self.myCategoryView.cellWidthIncrement = 20; +// JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init]; +// lineView.indicatorWidth = 20; +// self.myCategoryView.indicators = @[lineView]; +// JXCategoryIndicatorLineView *indicatorlineView = [[JXCategoryIndicatorLineView alloc]init]; +// indicatorlineView.indicatorHeight = 30; +// indicatorlineView.indicatorColor = UIColor.blackColor; +// indicatorlineView.verticalMargin = 10; +// indicatorlineView.indicatorWidthIncrement = 20; +// indicatorlineView.indicatorCornerRadius = 4; +// UIImage *bgImage = [UIImage kb_imageWithColor:[UIColor blackColor] size:CGSizeMake(30, 30)]; +//// UIImage *bgImage = [UIImage imageNamed:@"get_ppd_btn"]; +// UIImageView *imageV = [[UIImageView alloc]initWithImage:bgImage]; +// imageV.frame = indicatorlineView.bounds; +// imageV.contentMode = UIViewContentModeScaleToFill; +// [indicatorlineView addSubview:imageV]; +// self.myCategoryView.indicators = @[indicatorlineView]; +// [self configCategoryViewWithType:JXCategoryTitleImageType_LeftImage]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + self.myCategoryView.frame = CGRectMake(0, 0, self.view.bounds.size.width, [self preferredCategoryViewHeight]); + self.listContainerView.frame = CGRectMake(0, [self preferredCategoryViewHeight], self.view.bounds.size.width, self.view.bounds.size.height - [self preferredCategoryViewHeight]); +} + +//- (JXCategoryBaseView *)preferredCategoryView { +// return [[JXCategoryBaseView alloc] init]; +//} + +- (CGFloat)preferredCategoryViewHeight { + return 30; +} + +- (void)configCategoryViewWithType:(JXCategoryTitleImageType)imageType { + self.currentType = imageType; + if ((NSInteger)imageType == 100) { + NSMutableArray *types = [NSMutableArray array]; + for (int i = 0; i < self.titles.count; i++) { + if (i == 2) { + [types addObject:@(JXCategoryTitleImageType_OnlyImage)]; + }else if (i == 4) { + [types addObject:@(JXCategoryTitleImageType_LeftImage)]; + }else { + [types addObject:@(JXCategoryTitleImageType_OnlyTitle)]; + } + } + self.myCategoryView.imageTypes = types; + }else { + NSMutableArray *types = [NSMutableArray array]; + for (int i = 0; i < self.titles.count; i++) { + [types addObject:@(imageType)]; + } + self.myCategoryView.imageTypes = types; + } + [self.myCategoryView reloadData]; +} + +// 分页菜单视图 +- (JXCategoryTitleImageView *)myCategoryView { + if (!_myCategoryView) { + // Use our subclass so cells get a 4pt rounded background locally + _myCategoryView = (JXCategoryTitleImageView *)[[KBCategoryTitleImageView alloc] init]; + _myCategoryView.delegate = self; + + // !!!: 将列表容器视图关联到 categoryView + _myCategoryView.listContainer = self.listContainerView; + } + return _myCategoryView; +} + +// 列表容器视图 +- (JXCategoryListContainerView *)listContainerView { + if (!_listContainerView) { + _listContainerView = [[JXCategoryListContainerView alloc] initWithType:JXCategoryListContainerType_ScrollView delegate:self]; + } + return _listContainerView; +} + +#pragma mark - JXCategoryViewDelegate + +// 点击选中或者滚动选中都会调用该方法。适用于只关心选中事件,不关心具体是点击还是滚动选中的。 +- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index { + NSLog(@"%@", NSStringFromSelector(_cmd)); + // 拿到当前显示的列表 VC(已创建/显示过的会记录在 validListDict 中) + id list = self.listContainerView.validListDict[@(index)]; + if ([list isKindOfClass:[HomeRankContentVC class]]) { + HomeRankContentVC *currentVC = (HomeRankContentVC *)list; + // 如需拿到对应的 collectionView,可以在这里同步一下 + self.collectionView = currentVC.collectionView; + // TODO: 在这里对 currentVC 做需要的操作 + } + // 侧滑手势处理 + self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0); +} + +// 滚动选中的情况才会调用该方法 +- (void)categoryView:(JXCategoryBaseView *)categoryView didScrollSelectedItemAtIndex:(NSInteger)index { + NSLog(@"%@", NSStringFromSelector(_cmd)); +} + +#pragma mark - JXCategoryListContainerViewDelegate + +// 返回列表的数量 +- (NSInteger)numberOfListsInlistContainerView:(JXCategoryListContainerView *)listContainerView { + return self.titles.count; +} + +// 返回各个列表菜单下的实例,该实例需要遵守并实现 协议 +- (id)listContainerView:(JXCategoryListContainerView *)listContainerView initListForIndex:(NSInteger)index { + HomeRankContentVC *list = [[HomeRankContentVC alloc] init]; + self.collectionView = list.collectionView; + return list; +} + + +#pragma mark - TitleImageSettingViewControllerDelegate + +- (void)titleImageSettingVCDidSelectedImageType:(JXCategoryTitleImageType)imageType { + [self configCategoryViewWithType:imageType]; +} + +@end diff --git a/keyBoard/Class/Home/VC/HomeSheetVC.h b/keyBoard/Class/Home/VC/HomeSheetVC.h new file mode 100644 index 0000000..6f90c1b --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeSheetVC.h @@ -0,0 +1,18 @@ +// +// HomeSheetVC.h +// keyBoard +// +// Created by Mac on 2025/11/5. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeSheetVC : UIViewController +@property (nonatomic, assign) CGFloat minHeight; // 例如 150 +@property (nonatomic, assign) CGFloat topInset; // 例如 100 +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VC/HomeSheetVC.m b/keyBoard/Class/Home/VC/HomeSheetVC.m new file mode 100644 index 0000000..8279b77 --- /dev/null +++ b/keyBoard/Class/Home/VC/HomeSheetVC.m @@ -0,0 +1,271 @@ +// +// HomeSheetVC.m +// keyBoard +// +// Created by Mac on 2025/11/5. +// + +#import "HomeSheetVC.h" +#import "KBDirectionIndicatorView.h" +// 子控制器 +#import "HomeHotVC.h" +#import "HomeRankVC.h" + +@interface HomeSheetVC () +@property (nonatomic, strong) KBDirectionIndicatorView *indicator; + +// 顶部切换按钮与指示条 +@property (nonatomic, strong) UIView *topBar; +@property (nonatomic, strong) UIButton *hotButton; +@property (nonatomic, strong) UIButton *rankButton; +@property (nonatomic, strong) UIView *underlineView; // 选中下划线 + +// 承载子控制器内容 +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) UIViewController *currentChild; +@property (nonatomic, strong) HomeHotVC *hotVC; +@property (nonatomic, strong) HomeRankVC *rankVC; +@end + +@implementation HomeSheetVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.view.backgroundColor = [UIColor redColor]; + HWBackgroundConfig *config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault]; + config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault]; + config.backgroundAlpha = 0.001; + [self.hw_dimmedView reloadConfig:config]; + + // 顶部按钮 + 容器 + [self setupTopButtonsAndContainer]; + // 默认展示“热门” + [self switchToIndex:0 animated:NO]; +} + +- (UIView *)customIndicatorView { + if (!_indicator) _indicator = [KBDirectionIndicatorView new]; + return _indicator; +} + +- (void)panModalTransitionDidFinish { + // 初次展示后按当前状态设定一次朝向 + [self.indicator applyPresentationState:self.hw_presentationState]; + // 避免出现内容随弹窗上移的“位移动画”观感: + // 顶部栏在展示动画期间先隐藏,待完成后淡入 + if (self.topBar && self.topBar.alpha < 1.0) { + [UIView animateWithDuration:0.18 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.topBar.alpha = 1.0; + } completion:nil]; + } +} + +- (void)didChangeTransitionToState:(PresentationState)state { +// // 每次状态切换完成后刷新朝向 +// [self.indicator applyPresentationState:state]; +} + +- (PanModalHeight)shortFormHeight { + return PanModalHeightMake(PanModalHeightTypeContent, self.minHeight ?: 300); +} + +- (PanModalHeight)longFormHeight { + return PanModalHeightMake(PanModalHeightTypeMaxTopInset, self.topInset ?: 100); +} + +- (PresentationState)originPresentationState { + return PresentationStateShort; // 初始就以最小高度展示 +} + +- (BOOL)anchorModalToLongForm { + return YES; // 到 long 后不再继续往上拖 +} + +- (BOOL)allowsPullDownWhenShortState { + return NO; // 在 short 状态禁止继续往下拉(锁住最小高度) +} + +/// 允许时间穿透 +- (BOOL)allowsTouchEventsPassingThroughTransitionView { + return YES; +} + +-(BOOL)shouldAutoSetPanScrollContentInset{ + return NO; +} + + +- (UIScrollView *)panScrollable { + return self.hotVC.tableView; +} + +// 可选:完全不允许拖拽关闭(避免被拉到底消失) +- (BOOL)allowsDragToDismiss { + return NO; +} +// +//- (BOOL)showDragIndicator{ +// return NO; +//} +// +// 点背景不关闭 +- (BOOL)allowsTapBackgroundToDismiss { + return NO; +} + +// 出现时不做上推动画(瞬时到位)开了下拉动画有问题 +//- (NSTimeInterval)transitionDuration { +// return 0; +//} + +//// 可选:关闭触觉反馈,避免出现时的轻微震动 +//- (BOOL)isHapticFeedbackEnabled { +// return NO; +//} + + +#pragma mark - UI + +- (void)setupTopButtonsAndContainer { + // 顶部栏 + self.topBar = [[UIView alloc] init]; + self.topBar.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + [self.view addSubview:self.topBar]; + // 首次展示时先隐藏,待转场完成后再淡入,避免“自底向上滑入”的错觉 + self.topBar.alpha = 0.0; + + // 两个按钮 + self.hotButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.hotButton setTitle:@"热门" forState:UIControlStateNormal]; + [self.hotButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal]; + [self.hotButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; + self.hotButton.titleLabel.font = [UIFont boldSystemFontOfSize:16]; + self.hotButton.tag = 0; + [self.hotButton addTarget:self action:@selector(onTapTopButton:) forControlEvents:UIControlEventTouchUpInside]; + [self.topBar addSubview:self.hotButton]; + + self.rankButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.rankButton setTitle:@"排行" forState:UIControlStateNormal]; + [self.rankButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal]; + [self.rankButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; + self.rankButton.titleLabel.font = [UIFont boldSystemFontOfSize:16]; + self.rankButton.tag = 1; + [self.rankButton addTarget:self action:@selector(onTapTopButton:) forControlEvents:UIControlEventTouchUpInside]; + [self.topBar addSubview:self.rankButton]; + + // 下划线(跟随选中按钮) + self.underlineView = [[UIView alloc] init]; + self.underlineView.backgroundColor = [UIColor blackColor]; + self.underlineView.layer.cornerRadius = 1.0; + [self.topBar addSubview:self.underlineView]; + + // 容器视图 + self.containerView = [[UIView alloc] init]; + self.containerView.backgroundColor = [UIColor whiteColor]; + self.containerView.clipsToBounds = YES; + [self.view addSubview:self.containerView]; + + // Masonry 约束 + CGFloat topPadding = 12; // 与顶部小指示器留点空间 + [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.view).offset(topPadding); + make.height.mas_equalTo(44); + }]; + + [self.hotButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(self.topBar); + make.left.equalTo(self.topBar); + }]; + [self.rankButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(self.topBar); + make.right.equalTo(self.topBar); + make.left.equalTo(self.hotButton.mas_right); + make.width.equalTo(self.hotButton); + }]; + + // 初始先放在“热门”下方,宽度稍小于按钮文字 + [self.underlineView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(2); + make.bottom.equalTo(self.topBar.mas_bottom).offset(-2); + make.centerX.equalTo(self.hotButton); + make.width.mas_equalTo(24); + }]; + + [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.topBar.mas_bottom).offset(8); + make.left.right.bottom.equalTo(self.view); + }]; +} + +#pragma mark - Action + +- (void)onTapTopButton:(UIButton *)sender { + [self switchToIndex:sender.tag animated:YES]; + [self hw_panModalSetNeedsLayoutUpdate]; +} + +#pragma mark - Switch Child + +- (void)switchToIndex:(NSInteger)index animated:(BOOL)animated { + UIViewController *target = (index == 0) ? self.hotVC : self.rankVC; + if (!target) { + if (index == 0) { + self.hotVC = [HomeHotVC new]; + target = self.hotVC; + } else { + self.rankVC = [HomeRankVC new]; + target = self.rankVC; + } + } + + if (self.currentChild == target) { + // 已经是目标 + [self updateButtonStateForIndex:index animated:animated]; + return; + } + + // 移除当前 + if (self.currentChild) { + [self.currentChild willMoveToParentViewController:nil]; + [self.currentChild.view removeFromSuperview]; + [self.currentChild removeFromParentViewController]; + } + + // 添加目标 + [self addChildViewController:target]; + [self.containerView addSubview:target.view]; + target.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1]; + [target.view mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.containerView); + }]; + [target didMoveToParentViewController:self]; + self.currentChild = target; + + [self updateButtonStateForIndex:index animated:animated]; +} + +- (void)updateButtonStateForIndex:(NSInteger)index animated:(BOOL)animated { + self.hotButton.selected = (index == 0); + self.rankButton.selected = (index == 1); + + UIButton *btn = (index == 0) ? self.hotButton : self.rankButton; + // 更新下划线位置 + [self.underlineView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(2); + make.bottom.equalTo(self.topBar.mas_bottom).offset(-2); + make.centerX.equalTo(btn); + make.width.mas_equalTo(24); + }]; + + if (animated) { + [UIView animateWithDuration:0.25 animations:^{ + [self.topBar layoutIfNeeded]; + }]; + } else { + [self.topBar layoutIfNeeded]; + } +} + +@end diff --git a/keyBoard/Class/Home/VC/HomeVC.m b/keyBoard/Class/Home/VC/HomeVC.m index 346f4b4..d6badcb 100644 --- a/keyBoard/Class/Home/VC/HomeVC.m +++ b/keyBoard/Class/Home/VC/HomeVC.m @@ -6,96 +6,56 @@ // #import "HomeVC.h" -#import "KBGuideVC.h" -#import "KBLangTestVC.h" +#import "HomeHeadView.h" +#import "HomeSheetVC.h" + +@interface HomeVC () +@property (nonatomic, strong) HomeHeadView *headView; -@interface HomeVC () -@property (nonatomic, strong) UITextView *textView; // 作为表头,保持原有键盘测试 -@property (nonatomic, strong) BaseTableView *tableView; // 首页列表 -@property (nonatomic, copy) NSArray *items; // 简单数据源 @end @implementation HomeVC - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor whiteColor]; + self.view.backgroundColor = [UIColor yellowColor]; + CGFloat topV = (500); - CGFloat width = [UIScreen mainScreen].bounds.size.width; - UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 220)]; - CGRect frame = CGRectMake(16, 16, width - 32, 188); - self.textView = [[UITextView alloc] initWithFrame:frame]; - self.textView.text = KBLocalized(@"home_input_placeholder"); - self.textView.layer.borderColor = [UIColor blackColor].CGColor; - self.textView.layer.borderWidth = 0.5; - [header addSubview:self.textView]; + [self.view addSubview:self.headView]; + [self setupMas:topV]; + // 创建sheetVC + HomeSheetVC *vc = [[HomeSheetVC alloc] init]; + // 使用宏,避免误写成函数指针判断导致恒为 true +// if (KB_DEVICE_HAS_NOTCH) { +// vc.minHeight = KB_SCREEN_HEIGHT - topV - 34; +// }else{ + vc.minHeight = KB_SCREEN_HEIGHT - topV; +// +// } + vc.topInset = 100; + [self presentPanModal:vc]; +} - // 列表 - self.tableView = [[BaseTableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; - self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.tableView.delegate = self; - self.tableView.dataSource = self; - self.tableView.tableHeaderView = header; - [self.view addSubview:self.tableView]; - - self.items = @[ KBLocalized(@"home_item_lang_test"), KBLocalized(@"home_item_keyboard_permission") ]; - - dispatch_async(dispatch_get_main_queue(), ^{ [self.textView becomeFirstResponder]; }); - - [[KBNetworkManager shared] GET:@"app/config" parameters:nil headers:nil completion:^(id _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) { - NSLog(@"===="); +- (void)setupMas:(CGFloat)headViewTopV{ + [self.headView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.view); + make.height.mas_equalTo(headViewTopV); }]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; - self.title = KBLocalized(@"home_title"); - self.items = @[ KBLocalized(@"home_item_lang_test"), KBLocalized(@"home_item_keyboard_permission") ]; - [self.tableView reloadData]; + } -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ -// KBGuideVC *vc = [[KBGuideVC alloc] init]; -// [self.navigationController pushViewController:vc animated:true]; -// [KBHUD showInfo:@"加载中..."]; -// [KBHUD show]; -// [KBHUD showAllowTapToDismiss:true]; -} -#pragma mark - UITableViewDataSource -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.items.count; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *cellId = @"home.cell"; - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; - if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; } - cell.textLabel.text = self.items[indexPath.row]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - return cell; -} - -#pragma mark - UITableViewDelegate -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - if (indexPath.row == 0) { - // 多语言测试页 - KBLangTestVC *vc = [KBLangTestVC new]; - [self.navigationController pushViewController:vc animated:YES]; - } else if (indexPath.row == 1) { - // 键盘权限引导页 - KBGuideVC *vc = [KBGuideVC new]; - [self.navigationController pushViewController:vc animated:YES]; +#pragma mark - lazy +- (HomeHeadView *)headView{ + if (!_headView) { + _headView = [[HomeHeadView alloc] init]; } + return _headView; } -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ - @end diff --git a/keyBoard/Class/Me/V/KBSkinDetailHeaderCell.h b/keyBoard/Class/Me/V/KBSkinDetailHeaderCell.h new file mode 100644 index 0000000..20cb401 --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinDetailHeaderCell.h @@ -0,0 +1,19 @@ +// +// KBSkinDetailHeaderCell.h +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSkinDetailHeaderCell : UICollectionViewCell +@property (nonatomic, strong) UIImageView *coverView; // 顶部大图 +@property (nonatomic, strong) UILabel *leftLabel; // 下方左侧文案(#1B1F1A) +@property (nonatomic, strong) UILabel *rightLabel; // 下方右侧文案(#02BEAC) +- (void)configWithTitle:(NSString *)title right:(NSString *)right; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/V/KBSkinDetailHeaderCell.m b/keyBoard/Class/Me/V/KBSkinDetailHeaderCell.m new file mode 100644 index 0000000..0950ccd --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinDetailHeaderCell.m @@ -0,0 +1,75 @@ +// +// KBSkinDetailHeaderCell.m +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import "KBSkinDetailHeaderCell.h" + +@implementation KBSkinDetailHeaderCell +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor whiteColor]; + self.contentView.layer.cornerRadius = 12; + self.contentView.layer.masksToBounds = YES; + + [self.contentView addSubview:self.coverView]; + [self.contentView addSubview:self.leftLabel]; + [self.contentView addSubview:self.rightLabel]; + + // 上图,16:9 比例;下方左右文案 + [self.coverView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.right.equalTo(self.contentView); + // 高度按照宽度等比(接近截图比例) + make.height.equalTo(self.contentView.mas_width).multipliedBy(0.58); + }]; + [self.leftLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(12); + make.top.equalTo(self.coverView.mas_bottom).offset(10); + }]; + [self.rightLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.contentView).offset(-12); + make.centerY.equalTo(self.leftLabel); + }]; + } + return self; +} + +- (void)configWithTitle:(NSString *)title right:(NSString *)right { + // 演示:标题/下载量文案 + self.leftLabel.text = title.length ? title : @"Dopamine"; + self.rightLabel.text = right.length ? right : @"Download: 1 Million"; + // 本示例不做网络图,直接用占位背景色 + self.coverView.backgroundColor = [UIColor colorWithWhite:0.94 alpha:1.0]; +} + +#pragma mark - Lazy +- (UIImageView *)coverView { + if (!_coverView) { + _coverView = [[UIImageView alloc] init]; + _coverView.contentMode = UIViewContentModeScaleAspectFill; + _coverView.clipsToBounds = YES; + } + return _coverView; +} +- (UILabel *)leftLabel { + if (!_leftLabel) { + _leftLabel = [UILabel new]; + _leftLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + _leftLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _leftLabel.text = @"Dopamine"; + } + return _leftLabel; +} +- (UILabel *)rightLabel { + if (!_rightLabel) { + _rightLabel = [UILabel new]; + _rightLabel.textColor = [UIColor colorWithHex:0x02BEAC]; + _rightLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; + _rightLabel.textAlignment = NSTextAlignmentRight; + _rightLabel.text = @"Download: 1 Million"; + } + return _rightLabel; +} +@end diff --git a/keyBoard/Class/Me/V/KBSkinDetailTagCell.h b/keyBoard/Class/Me/V/KBSkinDetailTagCell.h new file mode 100644 index 0000000..b2be094 --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinDetailTagCell.h @@ -0,0 +1,18 @@ +// +// KBSkinDetailTagCell.h +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSkinDetailTagCell : UICollectionViewCell +- (void)config:(NSString *)text; +/// 根据文案计算自适应宽度(外部布局用) ++ (CGSize)sizeForText:(NSString *)text; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/V/KBSkinDetailTagCell.m b/keyBoard/Class/Me/V/KBSkinDetailTagCell.m new file mode 100644 index 0000000..63ee5fd --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinDetailTagCell.m @@ -0,0 +1,48 @@ +// +// KBSkinDetailTagCell.m +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import "KBSkinDetailTagCell.h" +@interface KBSkinDetailTagCell () +@property (nonatomic, strong) UILabel *titleLabel; +@end +@implementation KBSkinDetailTagCell +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + self.contentView.layer.cornerRadius = 16; + self.contentView.layer.masksToBounds = YES; + [self.contentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentView).insets(UIEdgeInsetsMake(6, 12, 6, 12)); + }]; + } + return self; +} + +- (void)config:(NSString *)text { + self.titleLabel.text = text ?: @""; +} + ++ (CGSize)sizeForText:(NSString *)text { + if (text.length == 0) { return CGSizeMake(40, 32); } + CGSize s = [text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]}]; + // 两侧内边距 12 + 12,高度固定 32 + return CGSizeMake(ceil(s.width) + 24, 32); +} + +#pragma mark - Lazy + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + } + return _titleLabel; +} + +@end diff --git a/keyBoard/Class/Me/V/KBSkinSectionTitleCell.h b/keyBoard/Class/Me/V/KBSkinSectionTitleCell.h new file mode 100644 index 0000000..c7e6cb8 --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinSectionTitleCell.h @@ -0,0 +1,17 @@ +// +// KBSkinSectionTitleCell.h +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +/// MARK: - 区块标题 cell +@interface KBSkinSectionTitleCell : UICollectionViewCell +@property (nonatomic, strong) UILabel *titleLabel; +- (void)config:(NSString *)title; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/V/KBSkinSectionTitleCell.m b/keyBoard/Class/Me/V/KBSkinSectionTitleCell.m new file mode 100644 index 0000000..397cbaf --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinSectionTitleCell.m @@ -0,0 +1,36 @@ +// +// KBSkinSectionTitleCell.m +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import "KBSkinSectionTitleCell.h" + +@implementation KBSkinSectionTitleCell +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor whiteColor]; + [self.contentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(16); + make.centerY.equalTo(self.contentView); + }]; + } + return self; +} + +- (void)config:(NSString *)title { + self.titleLabel.text = title ?: @"Recommended Skin"; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + _titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _titleLabel.text = @"Recommended Skin"; + } + return _titleLabel; +} +@end diff --git a/keyBoard/Class/Me/V/KBSkinTagsContainerCell.h b/keyBoard/Class/Me/V/KBSkinTagsContainerCell.h new file mode 100644 index 0000000..3cf4f72 --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinTagsContainerCell.h @@ -0,0 +1,20 @@ +// +// KBSkinTagsContainerCell.h +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSkinTagsContainerCell : UICollectionViewCell +@property (nonatomic, strong) UICollectionView *tagsView; // 内部标签列表 +@property (nonatomic, copy) NSArray *tags; // 标签文案 +- (void)configWithTags:(NSArray *)tags; +/// 根据给定宽度,计算该容器需要的高度(用于外部 sizeForItem) ++ (CGFloat)heightForTags:(NSArray *)tags width:(CGFloat)width; +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/V/KBSkinTagsContainerCell.m b/keyBoard/Class/Me/V/KBSkinTagsContainerCell.m new file mode 100644 index 0000000..e23ba59 --- /dev/null +++ b/keyBoard/Class/Me/V/KBSkinTagsContainerCell.m @@ -0,0 +1,91 @@ +// +// KBSkinTagsContainerCell.m +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import "KBSkinTagsContainerCell.h" +#import "KBSkinDetailTagCell.h" +#import "UICollectionViewLeftAlignedLayout.h" +static NSString * const kInnerTagCellId = @"kInnerTagCellId"; + +@implementation KBSkinTagsContainerCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor whiteColor]; + [self.contentView addSubview:self.tagsView]; + [self.tagsView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentView); + }]; + } + return self; +} + +- (void)configWithTags:(NSArray *)tags { + self.tags = tags; + [self.tagsView reloadData]; +} + +#pragma mark - UICollectionView + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.tags.count; +} +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + KBSkinDetailTagCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kInnerTagCellId forIndexPath:indexPath]; + [cell config:self.tags[indexPath.item]]; + return cell; +} +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + // 根据文案自适应宽度,高度固定 32 + return [KBSkinDetailTagCell sizeForText:self.tags[indexPath.item]]; +} + +#pragma mark - Height Helper + ++ (CGFloat)heightForTags:(NSArray *)tags width:(CGFloat)width { + if (tags.count == 0) { return 0; } + // 计算在给定宽度下的自动换行高度(与内部布局保持一致:行间距 8,item 间距 8,sectionInsets = {0,16,0,16}) + CGFloat leftRight = 16 * 2; // 外部 VC 会给整体 sectionInset=16,这里额外留一点安全边距 + CGFloat maxWidth = width - leftRight; + CGFloat x = 0; + CGFloat rows = 1; + for (NSString *t in tags) { + CGSize s = [KBSkinDetailTagCell sizeForText:t]; + CGFloat iw = ceil(s.width); + if (x == 0) { + x = iw; + } else { + // item 间距 8 + if (x + 8 + iw > maxWidth) { // 换行 + rows += 1; + x = iw; + } else { + x += 8 + iw; + } + } + } + // 行高固定 32;行间距 8;上下额外增加 8 视觉留白 + return rows * 32 + (rows - 1) * 8 + 16; +} + +#pragma mark - Lazy +- (UICollectionView *)tagsView { + if (!_tagsView) { + UICollectionViewLeftAlignedLayout *layout = [UICollectionViewLeftAlignedLayout new]; + layout.minimumInteritemSpacing = 8; + layout.minimumLineSpacing = 8; + layout.sectionInset = UIEdgeInsetsMake(8, 0, 8, 16); + + _tagsView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _tagsView.backgroundColor = [UIColor whiteColor]; + _tagsView.dataSource = self; + _tagsView.delegate = self; + [_tagsView registerClass:KBSkinDetailTagCell.class forCellWithReuseIdentifier:kInnerTagCellId]; + _tagsView.scrollEnabled = NO; // 由外层滚动 + } + return _tagsView; +} +@end diff --git a/keyBoard/Class/Me/V/MySkinCell.h b/keyBoard/Class/Me/V/MySkinCell.h new file mode 100644 index 0000000..e8d1359 --- /dev/null +++ b/keyBoard/Class/Me/V/MySkinCell.h @@ -0,0 +1,25 @@ +// +// MySkinCell.h +// keyBoard +// +// 我的皮肤 - 列表 cell。编辑态显示选择圆点。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MySkinCell : UICollectionViewCell +/// 是否处于编辑态(显示左上角选择圆点) +@property (nonatomic, assign, getter=isEditing) BOOL editing; + +/// 配置显示内容(演示仅传标题与占位图) +- (void)configWithTitle:(NSString *)title image:(nullable UIImage *)image; + +/// 根据选中状态刷新打勾样式(供外部在 select/deselect 时调用) +- (void)updateSelected:(BOOL)selected; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Me/V/MySkinCell.m b/keyBoard/Class/Me/V/MySkinCell.m new file mode 100644 index 0000000..7f91fec --- /dev/null +++ b/keyBoard/Class/Me/V/MySkinCell.m @@ -0,0 +1,186 @@ +// +// MySkinCell.m +// keyBoard +// + +#import "MySkinCell.h" +#import +#import "UIColor+Extension.h" + +// 左上角小圆点 + 对勾视图(无需切图,用 CAShapeLayer 绘制) +@interface KBSelectDotView : UIView +@property (nonatomic, assign) BOOL selectedState; // 选中状态 +- (void)applySelected:(BOOL)selected; // 刷新外观 +@end + +@implementation KBSelectDotView { + CAShapeLayer *_circleLayer; // 圆形背景 + CAShapeLayer *_checkLayer; // 白色对勾 +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = UIColor.clearColor; + + _circleLayer = [CAShapeLayer layer]; + _circleLayer.fillColor = [UIColor colorWithWhite:0 alpha:0.51].CGColor; // 默认未选中:#000000 51% + [self.layer addSublayer:_circleLayer]; + + _checkLayer = [CAShapeLayer layer]; + _checkLayer.strokeColor = UIColor.whiteColor.CGColor; // 对勾白色 + _checkLayer.fillColor = UIColor.clearColor.CGColor; + _checkLayer.lineWidth = 2.0; + _checkLayer.lineCap = kCALineCapRound; + _checkLayer.lineJoin = kCALineJoinRound; + _checkLayer.hidden = YES; // 未选中时隐藏 + [self.layer addSublayer:_checkLayer]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + CGFloat size = MIN(self.bounds.size.width, self.bounds.size.height); + CGRect r = CGRectMake((self.bounds.size.width - size) * 0.5, + (self.bounds.size.height - size) * 0.5, + size, size); + UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:r]; + _circleLayer.path = circle.CGPath; + + // 对勾路径(相对 size) + CGFloat s = size; + CGPoint p1 = CGPointMake(CGRectGetMinX(r) + s * 0.26, CGRectGetMinY(r) + s * 0.55); + CGPoint p2 = CGPointMake(CGRectGetMinX(r) + s * 0.43, CGRectGetMinY(r) + s * 0.72); + CGPoint p3 = CGPointMake(CGRectGetMinX(r) + s * 0.76, CGRectGetMinY(r) + s * 0.28); + UIBezierPath *check = [UIBezierPath bezierPath]; + [check moveToPoint:p1]; + [check addLineToPoint:p2]; + [check addLineToPoint:p3]; + _checkLayer.path = check.CGPath; +} + +- (void)applySelected:(BOOL)selected { + self.selectedState = selected; + UIColor *fill = selected ? [UIColor colorWithHex:0x02BEAC] : [UIColor colorWithWhite:0 alpha:0.51]; + _circleLayer.fillColor = fill.CGColor; // 选中改为 #02BEAC + _checkLayer.hidden = !selected; // 选中显示白对勾 +} +@end + +@interface MySkinCell () +@property (nonatomic, strong) UIView *cardView; // 卡片容器(圆角) +@property (nonatomic, strong) UIImageView *coverView; // 预览图 +@property (nonatomic, strong) UILabel *titleLabel; // 标题 + +@property (nonatomic, strong) KBSelectDotView *markView; // 左上角勾选图标(自绘) +@end + +@implementation MySkinCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor whiteColor]; + + [self.contentView addSubview:self.cardView]; + [self.cardView addSubview:self.coverView]; + [self.cardView addSubview:self.titleLabel]; + [self.contentView addSubview:self.markView]; + + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentView); + }]; + [self.coverView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.right.equalTo(self.cardView); + make.height.equalTo(self.cardView.mas_width).multipliedBy(0.66); // 接近截图比例 + }]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.cardView).offset(12); + make.right.equalTo(self.cardView).offset(-12); + make.top.equalTo(self.coverView.mas_bottom).offset(10); + }]; + [self.markView mas_makeConstraints:^(MASConstraintMaker *make) { + // 直接相对 contentView,避免受 cardView/masksToBounds 等影响 + make.left.equalTo(self.contentView).offset(8); + make.top.equalTo(self.contentView).offset(8); + make.width.height.mas_equalTo(15); // 设计要求:直径 15px + }]; + + self.markView.hidden = YES; // 默认非编辑态隐藏 + } + return self; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + self.editing = NO; + [self updateSelected:NO]; +} + +- (void)setSelected:(BOOL)selected { + [super setSelected:selected]; + // 统一在系统选中态变更时同步小圆点 + [self updateSelected:selected]; +} + +- (void)configWithTitle:(NSString *)title image:(UIImage *)image { + self.titleLabel.text = title.length ? title : @"Dopamine"; + // 简化:展示本地占位色 + self.coverView.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; +} + +- (void)setEditing:(BOOL)editing { + _editing = editing; + self.markView.hidden = !editing; + if (editing) { [self.markView applySelected:self.isSelected]; } +} + +- (void)updateSelected:(BOOL)selected { + if (!self.isEditing) { + self.markView.hidden = YES; + return; + } + self.markView.hidden = NO; + [self.markView applySelected:selected]; +} + +#pragma mark - Lazy + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [UIView new]; + _cardView.backgroundColor = [UIColor colorWithWhite:0.97 alpha:1.0]; + _cardView.layer.cornerRadius = 12; + _cardView.layer.masksToBounds = YES; + } + return _cardView; +} + +- (UIImageView *)coverView { + if (!_coverView) { + _coverView = [[UIImageView alloc] init]; + _coverView.contentMode = UIViewContentModeScaleAspectFill; + _coverView.clipsToBounds = YES; + } + return _coverView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + _titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightSemibold]; + _titleLabel.textColor = [UIColor colorWithHex:0x333333]; + _titleLabel.text = @"Dopamine"; + } + return _titleLabel; +} + +- (KBSelectDotView *)markView { + if (!_markView) { + _markView = [[KBSelectDotView alloc] init]; + _markView.userInteractionEnabled = NO; // 只作展示 + _markView.layer.zPosition = 10; // 置顶,确保不被图片遮挡 + } + return _markView; +} + +@end diff --git a/keyBoard/Class/Me/VC/KBSkinDetailVC.h b/keyBoard/Class/Me/VC/KBSkinDetailVC.h new file mode 100644 index 0000000..addd4c6 --- /dev/null +++ b/keyBoard/Class/Me/VC/KBSkinDetailVC.h @@ -0,0 +1,16 @@ +// +// KBSkinDetailVC.h +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSkinDetailVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/VC/KBSkinDetailVC.m b/keyBoard/Class/Me/VC/KBSkinDetailVC.m new file mode 100644 index 0000000..10e002b --- /dev/null +++ b/keyBoard/Class/Me/VC/KBSkinDetailVC.m @@ -0,0 +1,159 @@ +// +// KBSkinDetailVC.m +// keyBoard + +#import "KBSkinDetailVC.h" +#import +#import "UIColor+Extension.h" +#import "UICollectionViewLeftAlignedLayout.h" +#import "KBSkinDetailHeaderCell.h" +#import "KBSkinTagsContainerCell.h" +#import "KBSkinCardCell.h" // 已有的 皮肤卡片 cell(用作 2 列网格) +#import "KBSkinSectionTitleCell.h" + +static NSString * const kHeaderCellId = @"kHeaderCellId"; +static NSString * const kTagsContainerCellId = @"kTagsContainerCellId"; +static NSString * const kSectionTitleCellId = @"kSectionTitleCellId"; +static NSString * const kGridCellId = @"kGridCellId"; // 直接复用 KBSkinCardCell + +typedef NS_ENUM(NSInteger, KBSkinDetailSection) { + KBSkinDetailSectionHeader = 0, + KBSkinDetailSectionTags, + KBSkinDetailSectionTitle, + KBSkinDetailSectionGrid, + KBSkinDetailSectionCount +}; + +@interface KBSkinDetailVC () +@property (nonatomic, strong) UICollectionView *collectionView; // 主列表 +@property (nonatomic, copy) NSArray *tags; // 标签数据 +@property (nonatomic, copy) NSArray *gridData; // 底部网格数据 +@end + +@implementation KBSkinDetailVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + // 简单数据(演示) + self.tags = @[ @"Cute", @"Fresh", @"Cute", @"Fresh", @"Cute", @"Fresh" ]; + self.gridData = @[ + @{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" }, + @{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" }, + @{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" }, + ]; + + [self.view addSubview:self.collectionView]; + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; +} + +#pragma mark - UICollectionView DataSource + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return KBSkinDetailSectionCount; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + switch (section) { + case KBSkinDetailSectionHeader: return 1; // 顶部大卡片 + case KBSkinDetailSectionTags: return 1; // 标签容器 + case KBSkinDetailSectionTitle: return 1; // 标题 + case KBSkinDetailSectionGrid: return self.gridData.count; // 2 列网格 + } + return 0; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + switch (indexPath.section) { + case KBSkinDetailSectionHeader: { + KBSkinDetailHeaderCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kHeaderCellId forIndexPath:indexPath]; + [cell configWithTitle:@"Dopamine" right:@"Download: 1 Million"]; + return cell; + } + case KBSkinDetailSectionTags: { + KBSkinTagsContainerCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kTagsContainerCellId forIndexPath:indexPath]; + [cell configWithTags:self.tags]; + return cell; + } + case KBSkinDetailSectionTitle: { + KBSkinSectionTitleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kSectionTitleCellId forIndexPath:indexPath]; + [cell config:@"Recommended Skin"]; + return cell; + } + case KBSkinDetailSectionGrid: { + KBSkinCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kGridCellId forIndexPath:indexPath]; + NSDictionary *d = self.gridData[indexPath.item]; + [cell configWithTitle:d[@"title"] imageURL:nil price:@"20"]; + return cell; + } + } + return [UICollectionViewCell new]; +} + +#pragma mark - UICollectionView DelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + CGFloat W = collectionView.bounds.size.width; + CGFloat insetLR = 16.0; + CGFloat contentW = W - insetLR * 2; + switch (indexPath.section) { + case KBSkinDetailSectionHeader: { + // 高度 = 图片 0.58W + 文案与上下留白(≈56) + CGFloat h = contentW * 0.58 + 56; + return CGSizeMake(contentW, h); + } + case KBSkinDetailSectionTags: { + CGFloat h = [KBSkinTagsContainerCell heightForTags:self.tags width:W]; + return CGSizeMake(contentW, h); + } + case KBSkinDetailSectionTitle: { + return CGSizeMake(contentW, 44); + } + case KBSkinDetailSectionGrid: { + // 2 列 + CGFloat spacing = 12.0; + CGFloat itemW = floor((contentW - spacing) / 2.0); + CGFloat itemH = itemW * 0.75 + 56; // 参考 KBSkinCardCell 内部布局 + return CGSizeMake(itemW, itemH); + } + } + return CGSizeZero; +} + +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(12, 16, 12, 16); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 12.0; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + // 网格区需要这个间距,其它区也保持统一 + return 12.0; +} + +#pragma mark - Lazy + +- (UICollectionView *)collectionView { + if (!_collectionView) { + UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new]; + layout.scrollDirection = UICollectionViewScrollDirectionVertical; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionView.backgroundColor = [UIColor whiteColor]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + + // 注册 cell + [_collectionView registerClass:KBSkinDetailHeaderCell.class forCellWithReuseIdentifier:kHeaderCellId]; + [_collectionView registerClass:KBSkinTagsContainerCell.class forCellWithReuseIdentifier:kTagsContainerCellId]; + [_collectionView registerClass:KBSkinSectionTitleCell.class forCellWithReuseIdentifier:kSectionTitleCellId]; + [_collectionView registerClass:KBSkinCardCell.class forCellWithReuseIdentifier:kGridCellId]; + } + return _collectionView; +} + +@end diff --git a/keyBoard/Class/Me/VC/MySkinVC.h b/keyBoard/Class/Me/VC/MySkinVC.h new file mode 100644 index 0000000..7f80dd8 --- /dev/null +++ b/keyBoard/Class/Me/VC/MySkinVC.h @@ -0,0 +1,16 @@ +// +// MySkinVC.h +// keyBoard +// +// Created by Mac on 2025/11/8. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MySkinVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/VC/MySkinVC.m b/keyBoard/Class/Me/VC/MySkinVC.m new file mode 100644 index 0000000..b700196 --- /dev/null +++ b/keyBoard/Class/Me/VC/MySkinVC.m @@ -0,0 +1,289 @@ +// +// MySkinVC.m +// keyBoard +// + +#import "MySkinVC.h" +#import +#import "UIColor+Extension.h" +#import +#import "UIScrollView+KBEmptyView.h" // 统一空态封装(LYEmptyView) + +#import "MySkinCell.h" + +static NSString * const kMySkinCellId = @"kMySkinCellId"; + +@interface MySkinVC () +@property (nonatomic, strong) UICollectionView *collectionView; // 列表 +@property (nonatomic, strong) UIView *bottomView; // 底部操作条 +@property (nonatomic, strong) UILabel *selectedLabel; // 已选择数量 +@property (nonatomic, strong) UIButton *deleteButton; // 删除 + +@property (nonatomic, strong) NSMutableArray *data; // 简单数据源 +@property (nonatomic, assign) NSInteger loadCount; // 刷新计数(用于演示空/有数据切换) +@property (nonatomic, assign, getter=isEditingMode) BOOL editingMode; // 是否编辑态 +@end + +@implementation MySkinVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + self.title = @"My Skin"; // 标题 + + // 右上角 Editor/Cancel + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Editor" style:UIBarButtonItemStylePlain target:self action:@selector(onToggleEdit)]; + + // 数据源初始化为空(演示空态 + 下拉刷新) + self.data = [NSMutableArray array]; + + // 视图 + [self.view addSubview:self.collectionView]; + [self.view addSubview:self.bottomView]; + + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop); + make.left.right.equalTo(self.view); + make.bottom.equalTo(self.view.mas_bottom); // 底部被 bottomView 覆盖即可 + }]; + + [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom); + make.height.mas_equalTo(64); + }]; + + // 空态视图(LYEmptyView)统一样式 + 重试按钮 + __weak typeof(self) weakSelf = self; + [self.collectionView kb_makeDefaultEmptyViewWithImage:nil + title:@"暂无皮肤" + detail:@"下拉刷新试试" + buttonTitle:@"重试" + tapHandler:nil + buttonHandler:^{ [weakSelf.collectionView.mj_header beginRefreshing]; }]; + [self.collectionView kb_setLYAutoShowEnabled:NO]; // 采用手动控制显隐 + + // 立即按当前数据源状态显示一次空态(首屏就应展示空视图) + [self.collectionView kb_endLoadingForEmpty]; + + // 下拉刷新(演示网络加载 + 空态切换) + self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(fetchData)]; + + // 首次进入自动刷新 + [self.collectionView.mj_header beginRefreshing]; + + // 初始:非编辑态,隐藏底部 + self.bottomView.hidden = YES; +} + +#pragma mark - Data + +- (void)fetchData { + // 模拟网络延迟 1.0s + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + self.loadCount += 1; + + // 交替返回:奇数次空数据,偶数次有数据(演示空态/非空切换) + [self.data removeAllObjects]; + if (self.loadCount % 2 == 0) { + for (int i = 0; i < 8; i++) { + [self.data addObject:@{ @"title": @"Dopamine" }]; + } + } + + [self.collectionView reloadData]; + [self.collectionView kb_endLoadingForEmpty]; // 根据数据源显示/隐藏 emptyView + [self.collectionView.mj_header endRefreshing]; + }); +} + +#pragma mark - Actions + +- (void)onToggleEdit { + self.editingMode = !self.editingMode; + + // 更新顶部按钮 + self.navigationItem.rightBarButtonItem.title = self.isEditingMode ? @"Cancel" : @"Editor"; + + // 控制底部栏显隐 + self.bottomView.hidden = !self.isEditingMode; + + // 列表进入/退出多选 + self.collectionView.allowsMultipleSelection = self.isEditingMode; + // 直接刷新可见 cell,确保切换后立刻出现/隐藏 markView + for (UICollectionViewCell *c in self.collectionView.visibleCells) { + if (![c isKindOfClass:MySkinCell.class]) continue; + MySkinCell *cell = (MySkinCell *)c; + cell.editing = self.isEditingMode; + NSIndexPath *ip = [self.collectionView indexPathForCell:cell]; + BOOL selected = [[self.collectionView indexPathsForSelectedItems] containsObject:ip]; + [cell updateSelected:selected]; + } + // 再做一次 reload 保守刷新(防止 offscreen cell) + [self.collectionView reloadData]; + + // 清空选择并刷新底部文案 + for (NSIndexPath *ip in [self.collectionView indexPathsForSelectedItems]) { + [self.collectionView deselectItemAtIndexPath:ip animated:NO]; + } + [self updateBottomUI]; +} + +- (void)onDelete { + // 根据选中项删除 + NSArray *selected = [[self.collectionView indexPathsForSelectedItems] sortedArrayUsingSelector:@selector(compare:)]; + if (selected.count == 0) return; + + // 批量更新,先改数据,再删 UI + [self.collectionView performBatchUpdates:^{ + NSMutableIndexSet *set = [NSMutableIndexSet indexSet]; + for (NSIndexPath *ip in selected) { [set addIndex:ip.item]; } + [self.data removeObjectsAtIndexes:set]; + [self.collectionView deleteItemsAtIndexPaths:selected]; + } completion:^(BOOL finished) { + [self updateBottomUI]; + // 根据当前数据源显隐空视图(删除到 0 条时应显示空态) + [self.collectionView kb_endLoadingForEmpty]; + }]; +} + +- (void)updateBottomUI { + NSInteger count = self.collectionView.indexPathsForSelectedItems.count; + self.selectedLabel.text = [NSString stringWithFormat:@"Selected: %ld Skins", (long)count]; + + BOOL enable = count > 0; + self.deleteButton.enabled = enable; + if (enable) { + self.deleteButton.backgroundColor = [UIColor colorWithHex:0x02BEAC]; + [self.deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + self.deleteButton.layer.borderColor = [UIColor colorWithHex:0x02BEAC].CGColor; + } else { + self.deleteButton.backgroundColor = [UIColor colorWithHex:0xF2F2F2]; + [self.deleteButton setTitleColor:[UIColor colorWithHex:0xC8C8C8] forState:UIControlStateNormal]; + self.deleteButton.layer.borderColor = [UIColor colorWithHex:0xE6E6E6].CGColor; + } +} + +#pragma mark - UICollectionView + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.data.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + MySkinCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kMySkinCellId forIndexPath:indexPath]; + NSDictionary *d = self.data[indexPath.item]; + [cell configWithTitle:d[@"title"] image:nil]; + cell.editing = self.isEditingMode; // 控制是否显示选择圆点 + // 同步选中状态(复用时) + BOOL selected = [[collectionView indexPathsForSelectedItems] containsObject:indexPath]; + [cell updateSelected:selected]; + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + if (!self.isEditingMode) { + // 非编辑态:可在此进入详情,当前示例不处理 + [collectionView deselectItemAtIndexPath:indexPath animated:YES]; + return; + } + MySkinCell *cell = (MySkinCell *)[collectionView cellForItemAtIndexPath:indexPath]; + [cell updateSelected:YES]; + [self updateBottomUI]; +} + +- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath { + if (!self.isEditingMode) return; + MySkinCell *cell = (MySkinCell *)[collectionView cellForItemAtIndexPath:indexPath]; + [cell updateSelected:NO]; + [self updateBottomUI]; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if (![cell isKindOfClass:MySkinCell.class]) return; + MySkinCell *c = (MySkinCell *)cell; + c.editing = self.isEditingMode; // 保证滚动出现的新 cell 同步编辑态 + BOOL selected = [[collectionView indexPathsForSelectedItems] containsObject:indexPath]; + [c updateSelected:selected]; +} + +#pragma mark - Lazy + +- (UICollectionView *)collectionView { + if (!_collectionView) { + UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new]; + CGFloat inset = 16; + CGFloat spacing = 12; + CGFloat W = UIScreen.mainScreen.bounds.size.width; + CGFloat itemW = floor((W - inset * 2 - spacing) / 2.0); + CGFloat itemH = itemW * 0.82f; // 接近截图比例 + layout.itemSize = CGSizeMake(itemW, itemH); + layout.minimumInteritemSpacing = spacing; + layout.minimumLineSpacing = spacing; + layout.sectionInset = UIEdgeInsetsMake(12, inset, 12, inset); + + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionView.backgroundColor = [UIColor whiteColor]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + _collectionView.allowsMultipleSelection = NO; // 初始 + [_collectionView registerClass:MySkinCell.class forCellWithReuseIdentifier:kMySkinCellId]; + } + return _collectionView; +} + +- (UIView *)bottomView { + if (!_bottomView) { + _bottomView = [UIView new]; + _bottomView.backgroundColor = [UIColor whiteColor]; + _bottomView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.06].CGColor; + _bottomView.layer.shadowOpacity = 1; + _bottomView.layer.shadowOffset = CGSizeMake(0, -2); + + [_bottomView addSubview:self.selectedLabel]; + [_bottomView addSubview:self.deleteButton]; + + [self.selectedLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(_bottomView).offset(16); + make.centerY.equalTo(_bottomView); + }]; + [self.deleteButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(_bottomView).offset(-16); + make.centerY.equalTo(_bottomView); + make.width.mas_equalTo(92); + make.height.mas_equalTo(36); + }]; + } + return _bottomView; +} + +- (UILabel *)selectedLabel { + if (!_selectedLabel) { + _selectedLabel = [UILabel new]; + _selectedLabel.textColor = [UIColor colorWithHex:0x666666]; + _selectedLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + _selectedLabel.text = @"Selected: 0 Skins"; + } + return _selectedLabel; +} + +- (UIButton *)deleteButton { + if (!_deleteButton) { + _deleteButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_deleteButton setTitle:@"Delete" forState:UIControlStateNormal]; + _deleteButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _deleteButton.layer.cornerRadius = 18; + _deleteButton.layer.borderWidth = 1; + _deleteButton.clipsToBounds = YES; + [_deleteButton addTarget:self action:@selector(onDelete) forControlEvents:UIControlEventTouchUpInside]; + // 初始禁用态样式 + _deleteButton.enabled = NO; + _deleteButton.backgroundColor = [UIColor colorWithHex:0xF2F2F2]; + [_deleteButton setTitleColor:[UIColor colorWithHex:0xC8C8C8] forState:UIControlStateNormal]; + _deleteButton.layer.borderColor = [UIColor colorWithHex:0xE6E6E6].CGColor; + } + return _deleteButton; +} + +@end diff --git a/keyBoard/Class/Me/VC/MyVC.m b/keyBoard/Class/Me/VC/MyVC.m index b98e244..d977520 100644 --- a/keyBoard/Class/Me/VC/MyVC.m +++ b/keyBoard/Class/Me/VC/MyVC.m @@ -6,6 +6,8 @@ // #import "MyVC.h" +#import "MySkinVC.h" +#import "KBSkinDetailVC.h" @interface MyVC () @@ -27,7 +29,10 @@ } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ - [KBHUD show]; + MySkinVC *vc = [[MySkinVC alloc] init]; +// KBSkinDetailVC *vc = [[KBSkinDetailVC alloc] init]; + + [self.navigationController pushViewController:vc animated:true]; } /* diff --git a/keyBoard/Class/Resource/Images/Indicator/boat.png b/keyBoard/Class/Resource/Images/Indicator/boat.png new file mode 100644 index 0000000..f080599 Binary files /dev/null and b/keyBoard/Class/Resource/Images/Indicator/boat.png differ diff --git a/keyBoard/Class/Resource/Images/Indicator/city.png b/keyBoard/Class/Resource/Images/Indicator/city.png new file mode 100644 index 0000000..b8f55d6 Binary files /dev/null and b/keyBoard/Class/Resource/Images/Indicator/city.png differ diff --git a/keyBoard/Class/Resource/Images/Indicator/light.png b/keyBoard/Class/Resource/Images/Indicator/light.png new file mode 100644 index 0000000..7e17ac8 Binary files /dev/null and b/keyBoard/Class/Resource/Images/Indicator/light.png differ diff --git a/keyBoard/Class/Resource/Images/Indicator/lotus.png b/keyBoard/Class/Resource/Images/Indicator/lotus.png new file mode 100644 index 0000000..0e33fde Binary files /dev/null and b/keyBoard/Class/Resource/Images/Indicator/lotus.png differ diff --git a/keyBoard/Class/Resource/Images/Indicator/river.png b/keyBoard/Class/Resource/Images/Indicator/river.png new file mode 100644 index 0000000..3e0ca5e Binary files /dev/null and b/keyBoard/Class/Resource/Images/Indicator/river.png differ diff --git a/keyBoard/Class/Resource/Images/Indicator/seaWave.png b/keyBoard/Class/Resource/Images/Indicator/seaWave.png new file mode 100644 index 0000000..761e689 Binary files /dev/null and b/keyBoard/Class/Resource/Images/Indicator/seaWave.png differ diff --git a/keyBoard/Class/Resource/Images/JXCategoryView.png b/keyBoard/Class/Resource/Images/JXCategoryView.png new file mode 100644 index 0000000..ffee709 Binary files /dev/null and b/keyBoard/Class/Resource/Images/JXCategoryView.png differ diff --git a/keyBoard/Class/Resource/Images/JXCategoryViewStructure.png b/keyBoard/Class/Resource/Images/JXCategoryViewStructure.png new file mode 100644 index 0000000..a6351e7 Binary files /dev/null and b/keyBoard/Class/Resource/Images/JXCategoryViewStructure.png differ diff --git a/keyBoard/Class/Resource/Images/apple.png b/keyBoard/Class/Resource/Images/apple.png new file mode 100644 index 0000000..f5644a4 Binary files /dev/null and b/keyBoard/Class/Resource/Images/apple.png differ diff --git a/keyBoard/Class/Resource/Images/apple_selected.png b/keyBoard/Class/Resource/Images/apple_selected.png new file mode 100644 index 0000000..4b9ab90 Binary files /dev/null and b/keyBoard/Class/Resource/Images/apple_selected.png differ diff --git a/keyBoard/Class/Resource/Images/arrow_down.png b/keyBoard/Class/Resource/Images/arrow_down.png new file mode 100644 index 0000000..38d129c Binary files /dev/null and b/keyBoard/Class/Resource/Images/arrow_down.png differ diff --git a/keyBoard/Class/Resource/Images/arrow_up.png b/keyBoard/Class/Resource/Images/arrow_up.png new file mode 100644 index 0000000..33c503e Binary files /dev/null and b/keyBoard/Class/Resource/Images/arrow_up.png differ diff --git a/keyBoard/Class/Resource/Images/carrot.png b/keyBoard/Class/Resource/Images/carrot.png new file mode 100644 index 0000000..0ec6b23 Binary files /dev/null and b/keyBoard/Class/Resource/Images/carrot.png differ diff --git a/keyBoard/Class/Resource/Images/carrot_selected.png b/keyBoard/Class/Resource/Images/carrot_selected.png new file mode 100644 index 0000000..b4dcb64 Binary files /dev/null and b/keyBoard/Class/Resource/Images/carrot_selected.png differ diff --git a/keyBoard/Class/Resource/Images/crab.png b/keyBoard/Class/Resource/Images/crab.png new file mode 100644 index 0000000..b689ecb Binary files /dev/null and b/keyBoard/Class/Resource/Images/crab.png differ diff --git a/keyBoard/Class/Resource/Images/crab_selected.png b/keyBoard/Class/Resource/Images/crab_selected.png new file mode 100644 index 0000000..8a91fb3 Binary files /dev/null and b/keyBoard/Class/Resource/Images/crab_selected.png differ diff --git a/keyBoard/Class/Resource/Images/filter.png b/keyBoard/Class/Resource/Images/filter.png new file mode 100644 index 0000000..8e425bb Binary files /dev/null and b/keyBoard/Class/Resource/Images/filter.png differ diff --git a/keyBoard/Class/Resource/Images/football.png b/keyBoard/Class/Resource/Images/football.png new file mode 100644 index 0000000..843a032 Binary files /dev/null and b/keyBoard/Class/Resource/Images/football.png differ diff --git a/keyBoard/Class/Resource/Images/grape.png b/keyBoard/Class/Resource/Images/grape.png new file mode 100644 index 0000000..08719a6 Binary files /dev/null and b/keyBoard/Class/Resource/Images/grape.png differ diff --git a/keyBoard/Class/Resource/Images/grape_selected.png b/keyBoard/Class/Resource/Images/grape_selected.png new file mode 100644 index 0000000..fe393d6 Binary files /dev/null and b/keyBoard/Class/Resource/Images/grape_selected.png differ diff --git a/keyBoard/Class/Resource/Images/lobster.png b/keyBoard/Class/Resource/Images/lobster.png new file mode 100644 index 0000000..5c6b342 Binary files /dev/null and b/keyBoard/Class/Resource/Images/lobster.png differ diff --git a/keyBoard/Class/Resource/Images/lobster_selected.png b/keyBoard/Class/Resource/Images/lobster_selected.png new file mode 100644 index 0000000..efaa832 Binary files /dev/null and b/keyBoard/Class/Resource/Images/lobster_selected.png differ diff --git a/keyBoard/Class/Resource/Images/lufei.jpg b/keyBoard/Class/Resource/Images/lufei.jpg new file mode 100644 index 0000000..83b417e Binary files /dev/null and b/keyBoard/Class/Resource/Images/lufei.jpg differ diff --git a/keyBoard/Class/Resource/Images/watermelon.png b/keyBoard/Class/Resource/Images/watermelon.png new file mode 100644 index 0000000..cb3f2bd Binary files /dev/null and b/keyBoard/Class/Resource/Images/watermelon.png differ diff --git a/keyBoard/Class/Resource/Images/watermelon_selected.png b/keyBoard/Class/Resource/Images/watermelon_selected.png new file mode 100644 index 0000000..7c77dbf Binary files /dev/null and b/keyBoard/Class/Resource/Images/watermelon_selected.png differ diff --git a/keyBoard/Class/Search/V/KBHistoryMoreCell.h b/keyBoard/Class/Search/V/KBHistoryMoreCell.h new file mode 100644 index 0000000..95ce74c --- /dev/null +++ b/keyBoard/Class/Search/V/KBHistoryMoreCell.h @@ -0,0 +1,18 @@ +// +// KBHistoryMoreCell.h +// keyBoard +// +// 历史记录第二行尾部的“展开更多”按钮 cell(向下箭头)。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBHistoryMoreCell : UICollectionViewCell +/// 固定尺寸建议(高度与标签一致 32) ++ (CGSize)fixedSize; +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Search/V/KBHistoryMoreCell.m b/keyBoard/Class/Search/V/KBHistoryMoreCell.m new file mode 100644 index 0000000..938f653 --- /dev/null +++ b/keyBoard/Class/Search/V/KBHistoryMoreCell.m @@ -0,0 +1,56 @@ +// +// KBHistoryMoreCell.m +// keyBoard +// + +#import "KBHistoryMoreCell.h" + +@interface KBHistoryMoreCell () +@property (nonatomic, strong) UIView *bgView; +@property (nonatomic, strong) UIImageView *iconView; +@end + +@implementation KBHistoryMoreCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor clearColor]; + [self.contentView addSubview:self.bgView]; + [self.bgView addSubview:self.iconView]; + + [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentView); + }]; + [self.iconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self.bgView); + make.width.height.mas_equalTo(14); + }]; + } + return self; +} + ++ (CGSize)fixedSize { return CGSizeMake(32, 32); } + +#pragma mark - Lazy + +- (UIView *)bgView { + if (!_bgView) { + _bgView = [[UIView alloc] init]; + _bgView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + _bgView.layer.cornerRadius = 16; + _bgView.layer.masksToBounds = YES; + } + return _bgView; +} + +- (UIImageView *)iconView { + if (!_iconView) { + _iconView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"chevron.down"]]; + _iconView.tintColor = [UIColor colorWithHex:0x9A9A9A]; + _iconView.contentMode = UIViewContentModeScaleAspectFit; + } + return _iconView; +} + +@end + diff --git a/keyBoard/Class/Search/V/KBSearchBarView.h b/keyBoard/Class/Search/V/KBSearchBarView.h new file mode 100644 index 0000000..da1750e --- /dev/null +++ b/keyBoard/Class/Search/V/KBSearchBarView.h @@ -0,0 +1,31 @@ +// +// KBSearchBarView.h +// keyBoard +// +// 顶部搜索栏,独立封装的 View。 +// - 左侧圆角输入框,右侧搜索按钮 +// - 通过 block 将搜索事件回传给 VC +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSearchBarView : UIView + +/// 输入框 +@property (nonatomic, strong, readonly) UITextField *textField; + +/// 点击键盘 return 或右侧按钮时回调 +@property (nonatomic, copy) void(^onSearch)(NSString *keyword); + +/// 占位文字,默认“Themes” +@property (nonatomic, copy) NSString *placeholder; + +/// 外部可设置关键字 +- (void)updateKeyword:(NSString *)keyword; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Search/V/KBSearchBarView.m b/keyBoard/Class/Search/V/KBSearchBarView.m new file mode 100644 index 0000000..92256c0 --- /dev/null +++ b/keyBoard/Class/Search/V/KBSearchBarView.m @@ -0,0 +1,125 @@ +// +// KBSearchBarView.m +// keyBoard +// +// 顶部搜索栏封装。 +// + +#import "KBSearchBarView.h" + +@interface KBSearchBarView () +@property (nonatomic, strong) UIView *bgView; // 圆角背景 +@property (nonatomic, strong, readwrite) UITextField *textField; // 输入框 +@property (nonatomic, strong) UIButton *searchButton; // 右侧搜索按钮 +@end + +@implementation KBSearchBarView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + // 添加子视图 + [self addSubview:self.bgView]; + [self.bgView addSubview:self.textField]; + [self.bgView addSubview:self.searchButton]; + + // layout - Masonry + [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); // 高度由外部容器决定 + }]; + + [self.searchButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.bgView); + make.right.equalTo(self.bgView).offset(-8); + make.width.mas_equalTo(84); + make.height.mas_equalTo(32); + }]; + + [self.textField mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.bgView).offset(12); + make.centerY.equalTo(self.bgView); + make.right.equalTo(self.searchButton.mas_left).offset(-8); + make.height.mas_equalTo(30); + }]; + + self.bgView.layer.borderWidth = 1; + self.bgView.layer.borderColor = [UIColor colorWithHex:0xE6E6E6].CGColor; +} + +#pragma mark - Action + +- (void)searchButtonTapped { + NSString *kw = self.textField.text ?: @""; + if (self.onSearch) { self.onSearch(kw); } +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + [textField resignFirstResponder]; + if (self.onSearch) { self.onSearch(textField.text ?: @""); } + return YES; +} + +- (void)updateKeyword:(NSString *)keyword { + self.textField.text = keyword ?: @""; +} + +#pragma mark - Lazy + +- (UIView *)bgView { + if (!_bgView) { + _bgView = [[UIView alloc] init]; + // 淡灰色背景 + 圆角 + _bgView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + _bgView.layer.cornerRadius = 20; + _bgView.layer.masksToBounds = YES; + } + return _bgView; +} + +- (UITextField *)textField { + if (!_textField) { + _textField = [[UITextField alloc] init]; + _textField.delegate = self; + _textField.font = [UIFont systemFontOfSize:15]; + _textField.textColor = [UIColor colorWithHex:0x1B1F1A]; + _textField.clearButtonMode = UITextFieldViewModeWhileEditing; + _textField.returnKeyType = UIReturnKeySearch; + _textField.placeholder = @"Themes"; // 默认占位 + + // 左侧占位图标 + UIView *pad = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 8)]; + _textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 6, 1)]; + _textField.leftViewMode = UITextFieldViewModeAlways; + (void)pad; // 保留变量避免未使用告警 + } + return _textField; +} + +- (UIButton *)searchButton { + if (!_searchButton) { + _searchButton = [UIButton buttonWithType:UIButtonTypeSystem]; + _searchButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [_searchButton setTitle:@"Search" forState:UIControlStateNormal]; + // 绿色样式 + [_searchButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _searchButton.backgroundColor = [UIColor colorWithRed:0.15 green:0.72 blue:0.62 alpha:1.0]; + _searchButton.layer.cornerRadius = 16; + _searchButton.layer.masksToBounds = YES; + [_searchButton addTarget:self action:@selector(searchButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _searchButton; +} + +#pragma mark - Public + +- (void)setPlaceholder:(NSString *)placeholder { + _placeholder = [placeholder copy]; + self.textField.placeholder = placeholder; +} + +@end diff --git a/keyBoard/Class/Search/V/KBSearchSectionHeader.h b/keyBoard/Class/Search/V/KBSearchSectionHeader.h new file mode 100644 index 0000000..4faea23 --- /dev/null +++ b/keyBoard/Class/Search/V/KBSearchSectionHeader.h @@ -0,0 +1,29 @@ +// +// KBSearchSectionHeader.h +// keyBoard +// +// 通用区头:左侧标题,右侧可选垃圾桶按钮。 +// 用于“历史搜索”和“推荐皮肤”两个 section。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSearchSectionHeader : UICollectionReusableView + +/// 标题 +@property (nonatomic, strong, readonly) UILabel *titleLabel; +/// 右侧垃圾桶按钮(仅历史搜索使用) +@property (nonatomic, strong, readonly) UIButton *trashButton; + +/// 配置标题与是否显示垃圾桶 +- (void)configWithTitle:(NSString *)title showTrash:(BOOL)showTrash; + +/// 清除按钮点击回调 +@property (nonatomic, copy) void(^onTapTrash)(void); + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Search/V/KBSearchSectionHeader.m b/keyBoard/Class/Search/V/KBSearchSectionHeader.m new file mode 100644 index 0000000..792f27f --- /dev/null +++ b/keyBoard/Class/Search/V/KBSearchSectionHeader.m @@ -0,0 +1,72 @@ +// +// KBSearchSectionHeader.m +// keyBoard +// + +#import "KBSearchSectionHeader.h" + +@interface KBSearchSectionHeader () +@property (nonatomic, strong, readwrite) UILabel *titleLabel; +@property (nonatomic, strong, readwrite) UIButton *trashButton; +@end + +@implementation KBSearchSectionHeader + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + self.backgroundColor = [UIColor whiteColor]; + + [self addSubview:self.titleLabel]; + [self addSubview:self.trashButton]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(16); + make.centerY.equalTo(self); + make.right.lessThanOrEqualTo(self.trashButton.mas_left).offset(-8); + }]; + + [self.trashButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self); + make.right.equalTo(self).offset(-16); + make.width.height.mas_equalTo(24); + }]; +} + +- (void)tapTrash { + if (self.onTapTrash) { self.onTapTrash(); } +} + +- (void)configWithTitle:(NSString *)title showTrash:(BOOL)showTrash { + self.titleLabel.text = title; + self.trashButton.hidden = !showTrash; +} + +#pragma mark - Lazy + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + } + return _titleLabel; +} + +- (UIButton *)trashButton { + if (!_trashButton) { + _trashButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_trashButton setImage:[UIImage systemImageNamed:@"trash"] forState:UIControlStateNormal]; + _trashButton.tintColor = [UIColor colorWithHex:0x9A9A9A]; + [_trashButton addTarget:self action:@selector(tapTrash) forControlEvents:UIControlEventTouchUpInside]; + } + return _trashButton; +} + +@end + diff --git a/keyBoard/Class/Search/V/KBSkinCardCell.h b/keyBoard/Class/Search/V/KBSkinCardCell.h new file mode 100644 index 0000000..f475e35 --- /dev/null +++ b/keyBoard/Class/Search/V/KBSkinCardCell.h @@ -0,0 +1,17 @@ +// +// KBSkinCardCell.h +// keyBoard +// +// 推荐皮肤 - 简单卡片 cell。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBSkinCardCell : UICollectionViewCell +- (void)configWithTitle:(NSString *)title imageURL:(nullable NSString *)url price:(NSString *)price; +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Search/V/KBSkinCardCell.m b/keyBoard/Class/Search/V/KBSkinCardCell.m new file mode 100644 index 0000000..c1238b3 --- /dev/null +++ b/keyBoard/Class/Search/V/KBSkinCardCell.m @@ -0,0 +1,86 @@ +// +// KBSkinCardCell.m +// keyBoard +// + +#import "KBSkinCardCell.h" + +@interface KBSkinCardCell () +@property (nonatomic, strong) UIImageView *coverView; // 封面 +@property (nonatomic, strong) UILabel *titleLabel; // 标题 +@property (nonatomic, strong) UILabel *priceLabel; // 价格 +@end + +@implementation KBSkinCardCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor whiteColor]; + self.contentView.layer.cornerRadius = 12; + self.contentView.layer.masksToBounds = YES; + self.contentView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.06].CGColor; + self.contentView.layer.shadowOpacity = 1; + self.contentView.layer.shadowOffset = CGSizeMake(0, 2); + + [self.contentView addSubview:self.coverView]; + [self.contentView addSubview:self.titleLabel]; + [self.contentView addSubview:self.priceLabel]; + + [self.coverView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.right.equalTo(self.contentView); + make.height.equalTo(self.contentView.mas_width).multipliedBy(0.75); // 4:3 + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(12); + make.right.equalTo(self.contentView).offset(-12); + make.top.equalTo(self.coverView.mas_bottom).offset(8); + }]; + + [self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.titleLabel); + make.bottom.equalTo(self.contentView).offset(-10); + }]; + } + return self; +} + +- (void)configWithTitle:(NSString *)title imageURL:(NSString *)url price:(NSString *)price { + self.titleLabel.text = title.length ? title : @"Dopamine"; + self.priceLabel.text = price.length ? price : @"20"; + // 简化:本地展示占位色,无网络图 + self.coverView.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; +} + +#pragma mark - Lazy + +- (UIImageView *)coverView { + if (!_coverView) { + _coverView = [[UIImageView alloc] init]; + _coverView.contentMode = UIViewContentModeScaleAspectFill; + _coverView.clipsToBounds = YES; + _coverView.backgroundColor = [UIColor colorWithWhite:0.94 alpha:1.0]; + } + return _coverView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + } + return _titleLabel; +} + +- (UILabel *)priceLabel { + if (!_priceLabel) { + _priceLabel = [[UILabel alloc] init]; + _priceLabel.font = [UIFont systemFontOfSize:14]; + _priceLabel.textColor = [UIColor colorWithRed:0.15 green:0.72 blue:0.62 alpha:1.0]; + } + return _priceLabel; +} + +@end + diff --git a/keyBoard/Class/Search/V/KBTagCell.h b/keyBoard/Class/Search/V/KBTagCell.h new file mode 100644 index 0000000..372b864 --- /dev/null +++ b/keyBoard/Class/Search/V/KBTagCell.h @@ -0,0 +1,19 @@ +// +// KBTagCell.h +// keyBoard +// +// 历史搜索 - 标签样式 cell。 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBTagCell : UICollectionViewCell +- (void)config:(NSString *)text; +/// 根据文案计算自适应宽度(外部布局用) ++ (CGSize)sizeForText:(NSString *)text; +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Search/V/KBTagCell.m b/keyBoard/Class/Search/V/KBTagCell.m new file mode 100644 index 0000000..2838baf --- /dev/null +++ b/keyBoard/Class/Search/V/KBTagCell.m @@ -0,0 +1,50 @@ +// +// KBTagCell.m +// keyBoard +// + +#import "KBTagCell.h" + +@interface KBTagCell () +@property (nonatomic, strong) UILabel *titleLabel; +@end + +@implementation KBTagCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; + self.contentView.layer.cornerRadius = 16; + self.contentView.layer.masksToBounds = YES; + [self.contentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentView).insets(UIEdgeInsetsMake(6, 12, 6, 12)); + }]; + } + return self; +} + +- (void)config:(NSString *)text { + self.titleLabel.text = text ?: @""; +} + ++ (CGSize)sizeForText:(NSString *)text { + if (text.length == 0) { return CGSizeMake(40, 32); } + CGSize s = [text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]}]; + // 两侧内边距 12 + 12,高度固定 32 + return CGSizeMake(ceil(s.width) + 24, 32); +} + +#pragma mark - Lazy + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14]; + _titleLabel.textColor = [UIColor colorWithHex:0x1B1F1A]; + } + return _titleLabel; +} + +@end + diff --git a/keyBoard/Class/Search/VC/KBSearchResultVC.h b/keyBoard/Class/Search/VC/KBSearchResultVC.h new file mode 100644 index 0000000..e2da78c --- /dev/null +++ b/keyBoard/Class/Search/VC/KBSearchResultVC.h @@ -0,0 +1,21 @@ +// +// KBSearchResultVC.h +// keyBoard +// +// 搜索结果页:顶部搜索框 + 下方网格列表 +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 简单的搜索结果页,供外部 push 使用 +@interface KBSearchResultVC : UIViewController + +/// 可选:进入页面时默认关键字 +@property (nonatomic, copy, nullable) NSString *defaultKeyword; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/keyBoard/Class/Search/VC/KBSearchResultVC.m b/keyBoard/Class/Search/VC/KBSearchResultVC.m new file mode 100644 index 0000000..fbec781 --- /dev/null +++ b/keyBoard/Class/Search/VC/KBSearchResultVC.m @@ -0,0 +1,219 @@ +// +// KBSearchResultVC.m +// keyBoard +// + +#import "KBSearchResultVC.h" +#import "KBSearchBarView.h" +#import "KBSkinCardCell.h" + +static NSString * const kResultCellId = @"KBSkinCardCell"; + +@interface KBSearchResultVC () + +// 顶部自定义栏:返回按钮 + 搜索栏 +@property (nonatomic, strong) UIView *topBar; +@property (nonatomic, strong) UIButton *backButton; +@property (nonatomic, strong) KBSearchBarView *searchBarView; + +// 结果列表 +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout; + +// 数据源(示例数据,实际项目中由网络返回) +@property (nonatomic, strong) NSMutableArray *resultItems; // @{title, price} + +@end + +@implementation KBSearchResultVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + // 添加子视图 + [self.view addSubview:self.topBar]; + [self.topBar addSubview:self.backButton]; + [self.topBar addSubview:self.searchBarView]; + [self.view addSubview:self.collectionView]; + + // Masonry 布局:顶部自定义栏(无导航栏) + [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view.mas_top).offset(KB_STATUSBAR_HEIGHT + 8); + make.left.right.equalTo(self.view); + make.height.mas_equalTo(44); + }]; + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.topBar).offset(12); + make.centerY.equalTo(self.topBar); + make.width.mas_equalTo(28); + make.height.mas_equalTo(36); + }]; + [self.searchBarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.backButton); + make.left.equalTo(self.backButton.mas_right).offset(12); + make.width.mas_equalTo(315); + make.height.mas_equalTo(36); + make.right.lessThanOrEqualTo(self.topBar).offset(-16); + }]; + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.topBar.mas_bottom).offset(12); + make.left.right.bottom.equalTo(self.view); + }]; + + // 默认关键字(如果有) + if (self.defaultKeyword.length > 0) { + [self.searchBarView updateKeyword:self.defaultKeyword]; + [self performSearch:self.defaultKeyword]; + } else { + // 填充一些示例数据 + [self loadMockData]; + } +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + // 隐藏系统导航栏 + [self.navigationController setNavigationBarHidden:YES animated:animated]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + if (self.isMovingFromParentViewController || self.isBeingDismissed) { + [self.navigationController setNavigationBarHidden:NO animated:animated]; + } +} + +#pragma mark - Private + +/// 执行搜索(示例:本地生成一些数据) +- (void)performSearch:(NSString *)keyword { + // 这里可以发起网络请求;演示中生成 10 条假数据 + [self.resultItems removeAllObjects]; + for (int i = 0; i < 10; i++) { + [self.resultItems addObject:@{ @"title": @"Dopamine", @"price": @"20" }]; + } + [self.collectionView reloadData]; +} + +/// 示例数据 +- (void)loadMockData { + [self.resultItems removeAllObjects]; + for (int i = 0; i < 12; i++) { + [self.resultItems addObject:@{ @"title": @"Dopamine", @"price": @"20" }]; + } + [self.collectionView reloadData]; +} + +#pragma mark - UICollectionViewDataSource + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 1; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.resultItems.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + KBSkinCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kResultCellId forIndexPath:indexPath]; + NSDictionary *it = self.resultItems[indexPath.item]; + [cell configWithTitle:it[@"title"] imageURL:nil price:it[@"price"]]; + return cell; +} + +#pragma mark - UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + // 两列布局 + CGFloat width = collectionView.bounds.size.width; + CGFloat inset = 16; // 左右间距 + CGFloat spacing = 12; // 列间距 + CGFloat w = floor((width - inset * 2 - spacing) / 2.0); + CGFloat h = w * 0.75 + 8 + 20 + 10 + 6 + 8; // 与 KBSkinCardCell 估算一致 + return CGSizeMake(w, h); +} + +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(8, 16, 20, 16); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return 12; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 16; +} + +#pragma mark - Lazy + +- (KBSearchBarView *)searchBarView { + if (!_searchBarView) { + _searchBarView = [[KBSearchBarView alloc] init]; + _searchBarView.placeholder = @"Themes"; + __weak typeof(self) weakSelf = self; + _searchBarView.onSearch = ^(NSString * _Nonnull keyword) { + [weakSelf performSearch:keyword]; + }; + } + return _searchBarView; +} + +- (UIView *)topBar { + if (!_topBar) { + _topBar = [[UIView alloc] init]; + _topBar.backgroundColor = [UIColor whiteColor]; + } + return _topBar; +} + +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeSystem]; + UIImage *img = nil; + if (@available(iOS 13.0, *)) { + img = [UIImage systemImageNamed:@"chevron.left"]; + } + if (img) { + [_backButton setImage:img forState:UIControlStateNormal]; + } else { + [_backButton setTitle:@"<" forState:UIControlStateNormal]; + _backButton.titleLabel.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold]; + } + [_backButton setTintColor:[UIColor blackColor]]; + [_backButton addTarget:self action:@selector(onTapBack) forControlEvents:UIControlEventTouchUpInside]; + } + return _backButton; +} + +- (void)onTapBack { [self.navigationController popViewControllerAnimated:YES]; } + +- (UICollectionViewFlowLayout *)flowLayout { + if (!_flowLayout) { + _flowLayout = [[UICollectionViewFlowLayout alloc] init]; + _flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; + } + return _flowLayout; +} + +- (UICollectionView *)collectionView { + if (!_collectionView) { + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.flowLayout]; + _collectionView.backgroundColor = [UIColor whiteColor]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + // 注册结果卡片 cell + [_collectionView registerClass:KBSkinCardCell.class forCellWithReuseIdentifier:kResultCellId]; + } + return _collectionView; +} + +- (NSMutableArray *)resultItems { + if (!_resultItems) { + _resultItems = [NSMutableArray array]; + } + return _resultItems; +} + +@end diff --git a/keyBoard/Class/Search/VC/KBSearchVC.h b/keyBoard/Class/Search/VC/KBSearchVC.h new file mode 100644 index 0000000..149f133 --- /dev/null +++ b/keyBoard/Class/Search/VC/KBSearchVC.h @@ -0,0 +1,21 @@ +// +// KBSearchVC.h +// keyBoard +// +// Created by Mac on 2025/11/7. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 搜索页:顶部搜索视图 + 底部集合列表 +/// 说明: +/// - 顶部搜索栏封装为单独 View(KBSearchBarView) +/// - 底部使用 `UICollectionView` 展示:历史搜索(标签流式)/ 推荐皮肤(两列卡片) +/// - 当历史记录为空时,不展示“历史搜索”标题与右侧垃圾桶 +@interface KBSearchVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Search/VC/KBSearchVC.m b/keyBoard/Class/Search/VC/KBSearchVC.m new file mode 100644 index 0000000..bb6c52b --- /dev/null +++ b/keyBoard/Class/Search/VC/KBSearchVC.m @@ -0,0 +1,429 @@ +// +// KBSearchVC.m +// keyBoard +// +// Created by Mac on 2025/11/7. +// + +#import "KBSearchVC.h" +#import "KBSearchBarView.h" +#import "KBSearchSectionHeader.h" +#import "KBTagCell.h" +#import "KBSkinCardCell.h" +#import "KBHistoryMoreCell.h" +#import "KBSearchResultVC.h" +#import "UICollectionViewLeftAlignedLayout.h" + + +static NSString * const kTagCellId = @"KBTagCell"; +static NSString * const kSkinCellId = @"KBSkinCardCell"; +static NSString * const kHeaderId = @"KBSearchSectionHeader"; +static NSString * const kMoreCellId = @"KBHistoryMoreCell"; +static NSString * const kMoreToken = @"__KB_MORE__"; // 用于内部计算的占位标识 + +typedef NS_ENUM(NSInteger, KBSearchSection) { + KBSearchSectionHistory = 0, + KBSearchSectionRecommend = 1, +}; + +@interface KBSearchVC () +// 自定义顶部区域:返回按钮 + 搜索栏 +@property (nonatomic, strong) UIView *topBar; +@property (nonatomic, strong) UIButton *backButton; +@property (nonatomic, strong) KBSearchBarView *searchBarView; +// 列表 +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) UICollectionViewLeftAlignedLayout *flowLayout; + +// 数据 +@property (nonatomic, strong) NSMutableArray *historyWords; // 历史搜索 +@property (nonatomic, strong) NSArray *recommendItems; // 推荐数据(title/price) +@property (nonatomic, assign) BOOL historyExpanded; // 是否展开所有历史 +@property (nonatomic, assign) CGFloat lastCollectionWidth; // 记录宽度变化,用于重新计算 +@end + +@implementation KBSearchVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + // UI + [self.view addSubview:self.topBar]; + [self.topBar addSubview:self.backButton]; + [self.topBar addSubview:self.searchBarView]; + [self.view addSubview:self.collectionView]; + + // 布局 - Masonry(无导航栏) + [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view.mas_top).offset(KB_STATUSBAR_HEIGHT + 8); + make.left.right.equalTo(self.view); + make.height.mas_equalTo(44); // 容器高度 + }]; + + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.topBar).offset(12); + make.centerY.equalTo(self.topBar); + make.width.mas_equalTo(28); + make.height.mas_equalTo(36); + }]; + + [self.searchBarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.backButton); + make.left.equalTo(self.backButton.mas_right).offset(12); + make.width.mas_equalTo(315); + make.height.mas_equalTo(36); + make.right.lessThanOrEqualTo(self.topBar).offset(-16); + }]; + + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.topBar.mas_bottom).offset(12); + make.left.right.bottom.equalTo(self.view); + }]; + + // 初始化测试数据 + self.historyWords = [@[@"果冻橙", @"芒果", @"有机水果卷心菜", @"水果萝卜", @"熟冻帝王蟹", @"赣南脐橙"] mutableCopy]; + self.recommendItems = @[ + @{@"title":@"Dopamine", @"price":@"20"}, + @{@"title":@"Dopamine", @"price":@"20"}, + @{@"title":@"Dopamine", @"price":@"20"}, + @{@"title":@"Dopamine", @"price":@"20"}, + @{@"title":@"Dopamine", @"price":@"20"}, + @{@"title":@"Dopamine", @"price":@"20"}, + ]; + + [self.collectionView reloadData]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + CGFloat w = self.collectionView.bounds.size.width; + if (w > 0 && fabs(w - self.lastCollectionWidth) > 0.5) { + self.lastCollectionWidth = w; + [self.collectionView reloadData]; + } +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + // 隐藏系统导航栏,使用自定义返回按钮 + [self.navigationController setNavigationBarHidden:YES animated:animated]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + // 仅在返回上一级时恢复导航栏;push 到下一级(同样隐藏导航栏)不做处理,避免闪烁 + if (self.isMovingFromParentViewController || self.isBeingDismissed) { + [self.navigationController setNavigationBarHidden:NO animated:animated]; + } +} + +#pragma mark - Private + +/// 执行搜索:将关键字置顶到历史(去重、忽略大小写/前后空格) +- (void)performSearch:(NSString *)kw { + NSString *trim = [kw stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (trim.length == 0) { return; } + // 忽略大小写去重(把所有等同项移除) + for (NSInteger i = (NSInteger)self.historyWords.count - 1; i >= 0; i--) { + NSString *old = self.historyWords[i]; + if ([old caseInsensitiveCompare:trim] == NSOrderedSame) { + [self.historyWords removeObjectAtIndex:i]; + } + } + // 插入最前 + [self.historyWords insertObject:trim atIndex:0]; + [self.collectionView reloadData]; +} + +/// 打开搜索结果页,把关键字传过去 +- (void)openResultForKeyword:(NSString *)kw { + NSString *trim = [kw stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (trim.length == 0) { return; } + KBSearchResultVC *vc = [[KBSearchResultVC alloc] init]; + vc.defaultKeyword = trim; + [self.navigationController pushViewController:vc animated:YES]; +} + +/// 计算“最多两行展示”的历史数据,若超出则在第二行尾部添加一个“更多”按钮(向下箭头)。 +- (NSArray *)currentDisplayHistory { + if (self.historyExpanded) { return self.historyWords; } + if (self.collectionView.bounds.size.width <= 0) { return self.historyWords; } + + CGFloat width = self.collectionView.bounds.size.width; + UIEdgeInsets inset = UIEdgeInsetsMake(8, 16, 12, 16); + CGFloat available = width - inset.left - inset.right; + CGFloat itemSpacing = 8.0; // 与代理中保持一致 + + NSMutableArray *display = [NSMutableArray array]; + NSInteger line = 1; + CGFloat lineUsed = 0.0; // 当前行已占宽度 + // 记录当前第2行每个 item 的宽度与在 display 中的下标,便于回退 + NSMutableArray *lineWidths = [NSMutableArray array]; + NSMutableArray *lineIndexes = [NSMutableArray array]; + + for (NSInteger i = 0; i < self.historyWords.count; i++) { + NSString *text = self.historyWords[i]; + CGSize sz = [KBTagCell sizeForText:text]; + CGFloat w = sz.width; + CGFloat need = (lineUsed == 0 ? w : (lineUsed + itemSpacing + w)); + + if (need <= available) { + // 放得下,加入当前行 + [display addObject:text]; + if (line == 2) { + [lineWidths addObject:@(w)]; + [lineIndexes addObject:@(display.count - 1)]; + } + lineUsed = need; + continue; + } + + // 放不下,需要换行或截断 + if (line == 1) { + // 换到第 2 行 + line = 2; + lineUsed = 0.0; + [lineWidths removeAllObjects]; + [lineIndexes removeAllObjects]; + + // 直接把该元素作为第 2 行的第一个 + if (w <= available) { + [display addObject:text]; + [lineWidths addObject:@(w)]; + [lineIndexes addObject:@(display.count - 1)]; + lineUsed = w; + continue; + } else { + // 极端情况:单个标签就超过一行可用宽,直接用“更多”按钮占位 + [display addObject:kMoreToken]; + return display; + } + } + + // 已在第 2 行且再次超出,说明超过两行。需要在第二行末尾放“更多”按钮。 + CGSize moreSize = [KBHistoryMoreCell fixedSize]; + CGFloat moreNeed = (lineUsed == 0 ? moreSize.width : (lineUsed + itemSpacing + moreSize.width)); + if (moreNeed <= available) { + [display addObject:kMoreToken]; + return display; + } + + // 放不下“更多”,从当前行尾部回退一个标签,直到能放下“更多”。 + while (lineIndexes.count > 0) { + NSNumber *lastIndexNum = lineIndexes.lastObject; // display 中的下标 + NSNumber *lastWidthNum = lineWidths.lastObject; + [display removeObjectAtIndex:lastIndexNum.integerValue]; + [lineIndexes removeLastObject]; + [lineWidths removeLastObject]; + + // 重新计算当前行已占宽 + lineUsed = 0.0; + for (NSInteger k = 0; k < lineWidths.count; k++) { + CGFloat iw = lineWidths[k].doubleValue; + lineUsed = (k == 0 ? iw : (lineUsed + itemSpacing + iw)); + } + // 加入更多后是否能放得下 + moreNeed = (lineUsed == 0 ? moreSize.width : (lineUsed + itemSpacing + moreSize.width)); + if (moreNeed <= available) { + [display addObject:kMoreToken]; + return display; + } + } + + // 如果全部移除仍放不下,则第二行只显示“更多” + [display addObject:kMoreToken]; + return display; + } + + // 循环结束:数据未超过两行,无需“更多” + return display; +} + +/// 清空历史 +- (void)clearHistory { + [self.historyWords removeAllObjects]; + [self.collectionView reloadData]; +} + +#pragma mark - UICollectionViewDataSource + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 2; // 历史 + 推荐 +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + if (section == KBSearchSectionHistory) { + NSArray *list = [self currentDisplayHistory]; + return list.count; // 历史最多两行;可能包含“更多”占位 + } + return self.recommendItems.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.section == KBSearchSectionHistory) { + NSArray *list = [self currentDisplayHistory]; + NSString *text = list[indexPath.item]; + if ([text isEqualToString:kMoreToken]) { + KBHistoryMoreCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kMoreCellId forIndexPath:indexPath]; + return cell; + } else { + KBTagCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kTagCellId forIndexPath:indexPath]; + [cell config:text]; + return cell; + } + } + KBSkinCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kSkinCellId forIndexPath:indexPath]; + NSDictionary *it = self.recommendItems[indexPath.item]; + [cell configWithTitle:it[@"title"] imageURL:nil price:it[@"price"]]; + return cell; +} + +- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { + if (kind == UICollectionElementKindSectionHeader) { + KBSearchSectionHeader *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:kHeaderId forIndexPath:indexPath]; + if (indexPath.section == KBSearchSectionHistory) { + // 当没有历史时,外部通过 sizeForHeader 返回 0,这里仍设置但不会显示 + [header configWithTitle:@"Historical Search" showTrash:self.historyWords.count > 0]; + __weak typeof(self) weakSelf = self; + header.onTapTrash = ^{ [weakSelf clearHistory]; }; + } else { + [header configWithTitle:@"Recommended Skin" showTrash:NO]; + } + return header; + } + return [UICollectionReusableView new]; +} + +#pragma mark - UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + CGFloat width = collectionView.bounds.size.width; + if (indexPath.section == KBSearchSectionHistory) { + NSArray *list = [self currentDisplayHistory]; + NSString *t = list[indexPath.item]; + if ([t isEqualToString:kMoreToken]) { + return [KBHistoryMoreCell fixedSize]; + } + return [KBTagCell sizeForText:t]; + } + // 两列卡片 + CGFloat inset = 16; // 左右间距 + CGFloat spacing = 12; // 列间距 + CGFloat w = floor((width - inset*2 - spacing) / 2.0); + // 高度:封面 0.75w + 标题 + 价格 + 边距,近似定高 + CGFloat h = w*0.75 + 8 + 20 + 10 + 6 + 8; // 估算 + return CGSizeMake(w, h); +} + +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + if (section == KBSearchSectionHistory) { + return UIEdgeInsetsMake(8, 16, 12, 16); + } + return UIEdgeInsetsMake(8, 16, 20, 16); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return section == KBSearchSectionHistory ? 8 : 12; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return section == KBSearchSectionHistory ? 8 : 16; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { + // 当历史记录为空时,header 高度为 0,从而不显示标题与垃圾桶 + if (section == KBSearchSectionHistory) { + return self.historyWords.count == 0 ? CGSizeZero : CGSizeMake(collectionView.bounds.size.width, 40); + } + return CGSizeMake(collectionView.bounds.size.width, 40); +} + +#pragma mark - UICollectionViewDelegate + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.section == KBSearchSectionHistory) { + NSArray *list = [self currentDisplayHistory]; + NSString *kw = list[indexPath.item]; + if ([kw isEqualToString:kMoreToken]) { + // 展开所有历史 + self.historyExpanded = YES; + [self.collectionView reloadData]; + } else { + [self.searchBarView updateKeyword:kw]; + [self performSearch:kw]; + [self openResultForKeyword:kw]; + } + } +} + +#pragma mark - Lazy + +- (KBSearchBarView *)searchBarView { + if (!_searchBarView) { + _searchBarView = [[KBSearchBarView alloc] init]; + _searchBarView.placeholder = @"Themes"; + __weak typeof(self) weakSelf = self; + _searchBarView.onSearch = ^(NSString * _Nonnull keyword) { + // 置顶到历史 + 打开结果页 + [weakSelf performSearch:keyword]; + [weakSelf openResultForKeyword:keyword]; + }; + } + return _searchBarView; +} + +- (UIView *)topBar { + if (!_topBar) { + _topBar = [[UIView alloc] init]; + _topBar.backgroundColor = [UIColor whiteColor]; + } + return _topBar; +} + +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeSystem]; + UIImage *img = nil; + if (@available(iOS 13.0, *)) { + img = [UIImage systemImageNamed:@"chevron.left"]; + } + if (img) { + [_backButton setImage:img forState:UIControlStateNormal]; + } else { + [_backButton setTitle:@"<" forState:UIControlStateNormal]; + _backButton.titleLabel.font = [UIFont systemFontOfSize:22 weight:UIFontWeightSemibold]; + } + [_backButton setTintColor:[UIColor blackColor]]; + [_backButton addTarget:self action:@selector(onTapBack) forControlEvents:UIControlEventTouchUpInside]; + } + return _backButton; +} + +- (void)onTapBack { [self.navigationController popViewControllerAnimated:YES]; } + +- (UICollectionViewLeftAlignedLayout *)flowLayout { + if (!_flowLayout) { + _flowLayout = [[UICollectionViewLeftAlignedLayout alloc] init]; + _flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; + _flowLayout.sectionHeadersPinToVisibleBounds = NO; + } + return _flowLayout; +} + +- (UICollectionView *)collectionView { + if (!_collectionView) { + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.flowLayout]; + _collectionView.backgroundColor = [UIColor whiteColor]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + // 注册 cell & header + [_collectionView registerClass:KBTagCell.class forCellWithReuseIdentifier:kTagCellId]; + [_collectionView registerClass:KBSkinCardCell.class forCellWithReuseIdentifier:kSkinCellId]; + [_collectionView registerClass:KBHistoryMoreCell.class forCellWithReuseIdentifier:kMoreCellId]; + [_collectionView registerClass:KBSearchSectionHeader.class forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kHeaderId]; + } + return _collectionView; +} + +@end diff --git a/keyBoard/Class/Shared/KBConfig.h b/keyBoard/Class/Shared/KBConfig.h index b9cc820..88ccf09 100644 --- a/keyBoard/Class/Shared/KBConfig.h +++ b/keyBoard/Class/Shared/KBConfig.h @@ -31,3 +31,31 @@ #ifndef KB_KEYCHAIN_ACCESS_GROUP #define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.loveKey.nyx.shared" #endif + +// --- 设备特性:是否为带刘海机型(iPhone X 及以后异形屏)--- +// 说明:在 iPhone 12 等机型底部会有 34px 安全区,这里通过安全区来判断是否为“刘海屏”。 +// 注意:使用到 UIKit,这里自行引入,避免依赖 PCH 的包含顺序。 +#import +static inline BOOL KBDeviceHasNotchRuntime(void) { + if (@available(iOS 11.0, *)) { + UIWindow *window = nil; + if (@available(iOS 13.0, *)) { + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { + UIWindowScene *ws = (UIWindowScene *)scene; + for (UIWindow *w in ws.windows) { if (w.isKeyWindow) { window = w; break; } } + if (window) { break; } + } + } + if (!window) { window = UIApplication.sharedApplication.windows.firstObject; } + } else { + window = UIApplication.sharedApplication.keyWindow; + } + return window.safeAreaInsets.bottom > 0.0; + } + return NO; +} + +#ifndef KB_DEVICE_HAS_NOTCH +#define KB_DEVICE_HAS_NOTCH (KBDeviceHasNotchRuntime()) +#endif diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleCell.h b/keyBoard/Class/Shop/V/KBCategoryTitleCell.h new file mode 100644 index 0000000..1d38eb5 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleCell.h @@ -0,0 +1,14 @@ +// +// KBCategoryTitleCell.h +// keyBoard +// +// Custom title cell to show a smaller pill background for unselected state +// without modifying the third-party JXCategoryView sources. +// + +#import + +@interface KBCategoryTitleCell : JXCategoryTitleCell + +@end + diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleCell.m b/keyBoard/Class/Shop/V/KBCategoryTitleCell.m new file mode 100644 index 0000000..451e9ff --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleCell.m @@ -0,0 +1,56 @@ +// +// KBCategoryTitleCell.m +// keyBoard +// +// A JXCategoryTitleCell subclass that renders a 20pt-high rounded pill +// as the cell background. The pill is gray when unselected and clear when +// selected (so the indicator can show the white+border style). +// + +#import "KBCategoryTitleCell.h" +#import + +@interface KBCategoryTitleCell () +@property (nonatomic, strong) UIView *kb_pillBackgroundView; +@end + +@implementation KBCategoryTitleCell + +- (void)initializeViews { + [super initializeViews]; + self.kb_pillBackgroundView = [[UIView alloc] initWithFrame:CGRectZero]; + self.kb_pillBackgroundView.userInteractionEnabled = NO; + // 放在最底层,避免遮挡标题 + [self.contentView insertSubview:self.kb_pillBackgroundView atIndex:0]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + // 固定圆角块高度 20pt,使之更接近设计稿 + CGFloat pillHeight = 30.0; + CGFloat vPadding = MAX(0.0, (self.contentView.bounds.size.height - pillHeight)/2.0); + CGRect frame = CGRectInset(self.contentView.bounds, 0, vPadding); + self.kb_pillBackgroundView.frame = frame; + self.kb_pillBackgroundView.layer.cornerRadius = CGRectGetHeight(frame)/2.0; + self.kb_pillBackgroundView.layer.masksToBounds = YES; +} + +- (void)reloadData:(JXCategoryBaseCellModel *)cellModel { + [super reloadData:cellModel]; + // 使用父类的模型即可,里面已经包含了 cell 背景色渐变能力 + JXCategoryTitleCellModel *model = (JXCategoryTitleCellModel *)cellModel; + // 取消父类对 contentView 背景色的设置,由我们自己的 pill 来渲染 + self.contentView.backgroundColor = [UIColor clearColor]; + if (model.isCellBackgroundColorGradientEnabled) { + // 未选中:灰色椭圆;选中:透明(由指示器负责白底+描边) + if (model.isSelected) { + self.kb_pillBackgroundView.backgroundColor = [UIColor clearColor]; + } else { + self.kb_pillBackgroundView.backgroundColor = model.cellBackgroundUnselectedColor; + } + } else { + self.kb_pillBackgroundView.backgroundColor = [UIColor clearColor]; + } +} + +@end diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleImageCell.h b/keyBoard/Class/Shop/V/KBCategoryTitleImageCell.h new file mode 100644 index 0000000..6e48cc7 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleImageCell.h @@ -0,0 +1,14 @@ +// +// KBCategoryTitleImageCell.h +// keyBoard +// +// A JXCategoryTitleImageCell subclass that rounds the cell's contentView +// without changing the third-party JXCategoryView source code. +// + +#import + +@interface KBCategoryTitleImageCell : JXCategoryTitleImageCell + +@end + diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleImageCell.m b/keyBoard/Class/Shop/V/KBCategoryTitleImageCell.m new file mode 100644 index 0000000..a604c1d --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleImageCell.m @@ -0,0 +1,28 @@ +// +// KBCategoryTitleImageCell.m +// keyBoard +// +// Sets `contentView.layer.cornerRadius = 4` for title+image cells, so the +// background color that JXCategoryView applies is shown as a rounded rect. +// + +#import "KBCategoryTitleImageCell.h" + +@implementation KBCategoryTitleImageCell + +- (void)initializeViews { + [super initializeViews]; + // Round the cell background once; keep clipping within the rounded rect. + self.contentView.layer.cornerRadius = 4.0; + self.contentView.layer.masksToBounds = YES; +} + +// Defensive: if layout changes reset layer (some frameworks tweak layers in layout) +- (void)layoutSubviews { + [super layoutSubviews]; + self.contentView.layer.cornerRadius = 4.0; + self.contentView.layer.masksToBounds = YES; +} + +@end + diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleImageView.h b/keyBoard/Class/Shop/V/KBCategoryTitleImageView.h new file mode 100644 index 0000000..13e783c --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleImageView.h @@ -0,0 +1,14 @@ +// +// KBCategoryTitleImageView.h +// keyBoard +// +// Registers KBCategoryTitleImageCell so we can round cells locally +// without touching the JXCategoryView pod. +// + +#import + +@interface KBCategoryTitleImageView : JXCategoryTitleImageView + +@end + diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleImageView.m b/keyBoard/Class/Shop/V/KBCategoryTitleImageView.m new file mode 100644 index 0000000..720a977 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleImageView.m @@ -0,0 +1,18 @@ +// +// KBCategoryTitleImageView.m +// keyBoard +// +// Use our rounded KBCategoryTitleImageCell for this view instance. +// + +#import "KBCategoryTitleImageView.h" +#import "KBCategoryTitleImageCell.h" + +@implementation KBCategoryTitleImageView + +- (Class)preferredCellClass { + return [KBCategoryTitleImageCell class]; +} + +@end + diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleView.h b/keyBoard/Class/Shop/V/KBCategoryTitleView.h new file mode 100644 index 0000000..06552c0 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleView.h @@ -0,0 +1,13 @@ +// +// KBCategoryTitleView.h +// keyBoard +// +// A JXCategoryTitleView subclass that uses KBCategoryTitleCell. +// + +#import + +@interface KBCategoryTitleView : JXCategoryTitleView + +@end + diff --git a/keyBoard/Class/Shop/V/KBCategoryTitleView.m b/keyBoard/Class/Shop/V/KBCategoryTitleView.m new file mode 100644 index 0000000..b7f3d52 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBCategoryTitleView.m @@ -0,0 +1,32 @@ +// +// KBCategoryTitleView.m +// keyBoard +// +// Swap in KBCategoryTitleCell to add a custom unselected pill background. +// + +#import "KBCategoryTitleView.h" +#import "KBCategoryTitleCell.h" +#import +#import + +@implementation KBCategoryTitleView + +- (Class)preferredCellClass { + return [KBCategoryTitleCell class]; +} + +// 关闭左右滑动时的颜色/背景渐变(保持状态不变) +- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel + rightCellModel:(JXCategoryBaseCellModel *)rightCellModel + ratio:(CGFloat)ratio { + // 不调用 super,避免 JXCategoryIndicatorView/JXCategoryTitleView 内部的渐变计算 + JXCategoryTitleCellModel *left = (JXCategoryTitleCellModel *)leftCellModel; + JXCategoryTitleCellModel *right = (JXCategoryTitleCellModel *)rightCellModel; + + // 固定颜色:选中用选中色,未选中用普通色 + left.titleCurrentColor = left.isSelected ? left.titleSelectedColor : left.titleNormalColor; + right.titleCurrentColor = right.isSelected ? right.titleSelectedColor : right.titleNormalColor; +} + +@end diff --git a/keyBoard/Class/Shop/V/KBShopHeadView.h b/keyBoard/Class/Shop/V/KBShopHeadView.h new file mode 100644 index 0000000..d6d1276 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBShopHeadView.h @@ -0,0 +1,16 @@ +// +// KBShopHeadView.h +// keyBoard +// +// Created by Mac on 2025/11/9. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBShopHeadView : UIView + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Shop/V/KBShopHeadView.m b/keyBoard/Class/Shop/V/KBShopHeadView.m new file mode 100644 index 0000000..95e0909 --- /dev/null +++ b/keyBoard/Class/Shop/V/KBShopHeadView.m @@ -0,0 +1,20 @@ +// +// KBShopHeadView.m +// keyBoard +// +// Created by Mac on 2025/11/9. +// + +#import "KBShopHeadView.h" + +@implementation KBShopHeadView + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + +@end diff --git a/keyBoard/Class/Shop/VC/KBShopItemVC.h b/keyBoard/Class/Shop/VC/KBShopItemVC.h new file mode 100644 index 0000000..cf5e84c --- /dev/null +++ b/keyBoard/Class/Shop/VC/KBShopItemVC.h @@ -0,0 +1,26 @@ +// +// KBShopItemVC.h +// keyBoard +// +// Created by Mac on 2025/11/9. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBShopItemVC : UIViewController +/// 列表:使用 UICollectionView 展示两列皮肤卡片 +@property (nonatomic, strong) UICollectionView *collectionView; +/// 数据源:简单字符串作为标题(演示用) +@property (nonatomic, strong) NSMutableArray *dataSource; +/// 是否需要上拉加载更多 +@property (nonatomic, assign) BOOL isNeedFooter; +/// 是否需要下拉刷新 +@property (nonatomic, assign) BOOL isNeedHeader; +/// 首次是否已刷新过(避免重复触发) +@property (nonatomic, assign) BOOL isHeaderRefreshed; // 默认为 YES +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Shop/VC/KBShopItemVC.m b/keyBoard/Class/Shop/VC/KBShopItemVC.m new file mode 100644 index 0000000..55e252f --- /dev/null +++ b/keyBoard/Class/Shop/VC/KBShopItemVC.m @@ -0,0 +1,145 @@ +// +// KBShopItemVC.m +// keyBoard +// +// Created by Mac on 2025/11/9. +// + +#import "KBShopItemVC.h" +#import +#import +#import "KBSkinCardCell.h" + +@interface KBShopItemVC () +@property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView); +@end + +@implementation KBShopItemVC + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + // 懒加载 collectionView,并添加到视图 + [self.view addSubview:self.collectionView]; + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); // mas 布局:铺满 + }]; + + // 刷新组件(演示:2 秒后结束) + __weak typeof(self) weakSelf = self; + if (self.isNeedHeader) { + self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [weakSelf.collectionView.mj_header endRefreshing]; + }); + }]; + } + if (self.isNeedFooter) { + self.collectionView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [weakSelf.dataSource addObject:@"加载更多成功"]; // 模拟新增一条 + [weakSelf.collectionView reloadData]; + [weakSelf.collectionView.mj_footer endRefreshing]; + }); + }]; + } + + if (@available(iOS 11.0, *)) { + self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + + [self beginFirstRefresh]; +} + +#pragma mark - 刷新控制 + +// 首次进入自动触发一次刷新(如果需要) +- (void)beginFirstRefresh { + if (!self.isHeaderRefreshed) { + [self beginRefreshImmediately]; + } +} + +- (void)beginRefreshImmediately { + if (self.isNeedHeader) { + [self.collectionView.mj_header beginRefreshing]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + self.isHeaderRefreshed = YES; + [self.collectionView reloadData]; + [self.collectionView.mj_header endRefreshing]; + }); + } else { + self.isHeaderRefreshed = YES; + [self.collectionView reloadData]; + } +} + +#pragma mark - UICollectionView DataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + if (!self.isHeaderRefreshed) return 0; + return self.dataSource.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + KBSkinCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"KBSkinCardCell" forIndexPath:indexPath]; + NSString *title = (indexPath.item < self.dataSource.count) ? self.dataSource[indexPath.item] : @"Dopamine"; + [cell configWithTitle:title imageURL:nil price:@"20"]; // 价格写死 20(演示) + return cell; +} + +#pragma mark - UICollectionView DelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + // 两列布局:左右 16 间距,中间列间距 12 + CGFloat insetLR = 16.0; + CGFloat spacing = 12.0; + CGFloat contentW = collectionView.bounds.size.width - insetLR * 2; + CGFloat itemW = floor((contentW - spacing) / 2.0); + CGFloat itemH = itemW * 0.75 + 56; // KBSkinCardCell 内部高度估算 + return CGSizeMake(itemW, itemH); +} + +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(12, 16, 12, 16); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 12.0; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return 12.0; +} + +#pragma mark - UIScrollView Delegate(转发给分页容器) +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + !self.scrollCallback ?: self.scrollCallback(scrollView); +} + +#pragma mark - JXPagingViewListViewDelegate +- (UIView *)listView { return self.view; } +- (UIScrollView *)listScrollView { return self.collectionView; } +- (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback { self.scrollCallback = callback; } +- (void)listWillAppear { NSLog(@"%@:%@", self.title, NSStringFromSelector(_cmd)); } +- (void)listDidAppear { NSLog(@"%@:%@", self.title, NSStringFromSelector(_cmd)); } +- (void)listWillDisappear { NSLog(@"%@:%@", self.title, NSStringFromSelector(_cmd)); } +- (void)listDidDisappear { NSLog(@"%@:%@", self.title, NSStringFromSelector(_cmd)); } + +#pragma mark - Lazy +- (UICollectionView *)collectionView { + if (!_collectionView) { + UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new]; + layout.scrollDirection = UICollectionViewScrollDirectionVertical; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionView.backgroundColor = [UIColor whiteColor]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + // 注册皮肤卡片 cell + [_collectionView registerClass:KBSkinCardCell.class forCellWithReuseIdentifier:@"KBSkinCardCell"]; // 复用标识 + } + return _collectionView; +} + +@end diff --git a/keyBoard/Class/Shop/VC/KBShopVC.h b/keyBoard/Class/Shop/VC/KBShopVC.h new file mode 100644 index 0000000..52a1580 --- /dev/null +++ b/keyBoard/Class/Shop/VC/KBShopVC.h @@ -0,0 +1,16 @@ +// +// KBShopVC.h +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBShopVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Shop/VC/KBShopVC.m b/keyBoard/Class/Shop/VC/KBShopVC.m new file mode 100644 index 0000000..526cd1e --- /dev/null +++ b/keyBoard/Class/Shop/VC/KBShopVC.m @@ -0,0 +1,208 @@ +// +// KBShopVC.m +// keyBoard +// +// Created by Mac on 2025/11/6. +// + +#import "KBShopVC.h" +#import "JXPagerView.h" +#import "KBShopHeadView.h" +#import +#import "KBCategoryTitleView.h" +#import +#import +#import "KBShopItemVC.h" + +static const CGFloat JXTableHeaderViewHeight = (323); +static const CGFloat JXheightForHeaderInSection = 50; + +@interface KBShopVC () +@property (nonatomic, strong) UIView *naviBGView; + +@property (nonatomic, strong) JXPagerView *pagerView; +@property (nonatomic, strong) KBShopHeadView *userHeaderView; +@property (nonatomic, assign) BOOL isNeedFooter; +@property (nonatomic, assign) BOOL isNeedHeader; +- (JXPagerView *)preferredPagingView; + +@property (nonatomic, strong) JXCategoryTitleView *categoryView; +@property (nonatomic, strong) NSArray *titles; +@end + +@implementation KBShopVC + +- (void)viewDidLoad { + [super viewDidLoad]; +// [self setupUI]; + +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + [self.navigationController setNavigationBarHidden:YES animated:YES]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + [self.navigationController setNavigationBarHidden:NO animated:NO]; +} + +- (void)setupUI{ + + + self.automaticallyAdjustsScrollViewInsets = NO; + self.view.backgroundColor = [UIColor whiteColor]; + self.navigationController.navigationBar.translucent = false; + self.edgesForExtendedLayout = UIRectEdgeNone; + _titles = @[@"能力", @"爱好", @"队友",@"能力2", @"爱好2", @"队友2",@"能力", @"爱好", @"队友",@"能力2", @"爱好2", @"队友2"]; + + _userHeaderView = [[KBShopHeadView alloc] init]; + _categoryView = (JXCategoryTitleView *)[[KBCategoryTitleView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, JXheightForHeaderInSection)]; + self.categoryView.titles = self.titles; + self.categoryView.backgroundColor = [UIColor whiteColor]; + self.categoryView.delegate = self; + self.categoryView.titleSelectedColor = [UIColor colorWithHex:0x1B1F1A]; + self.categoryView.titleColor = [UIColor colorWithHex:0x9F9F9F]; + // 左右滑动时不要文字渐变色 + self.categoryView.titleColorGradientEnabled = NO; + // 不需要文字放大效果 + self.categoryView.cellWidthZoomEnabled = NO; + self.categoryView.cellWidthZoomScale = 1.0; + self.categoryView.contentScrollViewClickTransitionAnimationEnabled = NO; + // Unselected items need a rounded gray background like the screenshot. + // JXCategoryTitleView supports cell background colors via JXCategoryIndicatorView. + self.categoryView.cellBackgroundColorGradientEnabled = YES; + self.categoryView.cellBackgroundUnselectedColor = [UIColor colorWithHex:0xEFEFEF]; + self.categoryView.cellBackgroundSelectedColor = [UIColor whiteColor]; + // Make the pills look compact + self.categoryView.cellWidthIncrement = 20; // horizontal padding for each item + self.categoryView.cellSpacing = 12; // spacing between items + self.categoryView.contentEdgeInsetLeft = 16; + self.categoryView.contentEdgeInsetRight = 16; + self.categoryView.averageCellSpacingEnabled = NO; + + JXCategoryIndicatorBackgroundView *backgroundView = [[JXCategoryIndicatorBackgroundView alloc] init]; + backgroundView.indicatorHeight = 30; + backgroundView.indicatorCornerRadius = JXCategoryViewAutomaticDimension; + backgroundView.indicatorColor = [UIColor whiteColor]; // keep selected fill white + backgroundView.layer.borderColor = [UIColor colorWithHex:0x02BEAC].CGColor; + backgroundView.layer.borderWidth = 1; + backgroundView.indicatorWidthIncrement = 0; // 指示器宽度不额外加宽 + // 点击切换时不需要左右滚动动画,直接跳转到目标位置 + backgroundView.scrollEnabled = NO; + backgroundView.scrollAnimationDuration = 0; + self.categoryView.indicators = @[backgroundView]; + + _pagerView = [self preferredPagingView]; + self.pagerView.mainTableView.gestureDelegate = self; + [self.view addSubview:self.pagerView]; +// self.pagerView.listContainerView.scrollView.scrollEnabled = false; + + + self.categoryView.listContainer = (id)self.pagerView.listContainerView; + + //导航栏隐藏的情况,处理扣边返回,下面的代码要加上 +// [self.pagerView.listContainerView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer]; +// [self.pagerView.mainTableView.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer]; + + __weak typeof(self)weakSelf = self; + self.pagerView.mainTableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + self.categoryView.titles = @[@"高级能力", @"高级爱好", @"高级队友"]; + self.categoryView.defaultSelectedIndex = 0; + [self.categoryView reloadData]; + [self.pagerView reloadData]; + [weakSelf.pagerView.mainTableView.mj_header endRefreshing]; + }); + }]; + + self.pagerView.pinSectionHeaderVerticalOffset = KB_NAV_TOTAL_HEIGHT; + + self.naviBGView = [[UIView alloc] init]; + self.naviBGView.alpha = 0; + self.naviBGView.backgroundColor = [UIColor whiteColor]; + self.naviBGView.frame = CGRectMake(0, 0, KB_SCREEN_WIDTH, KB_NAV_TOTAL_HEIGHT); + [self.view addSubview:self.naviBGView]; + UILabel *naviTitleLabel = [[UILabel alloc] init]; + naviTitleLabel.text = @"导航栏隐藏"; + naviTitleLabel.textAlignment = NSTextAlignmentCenter; + naviTitleLabel.frame = CGRectMake(0, KB_STATUSBAR_HEIGHT, self.view.bounds.size.width, 44); + [self.naviBGView addSubview:naviTitleLabel]; +} + +- (JXPagerView *)preferredPagingView { + return [[JXPagerView alloc] initWithDelegate:self]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + self.pagerView.frame = self.view.bounds; +} + +#pragma mark - JXPagerViewDelegate + +- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView { + return self.userHeaderView; +} + +- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView { + return KBFit(JXTableHeaderViewHeight); +} + +- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { + return JXheightForHeaderInSection; +} + +- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { + return self.categoryView; +} + +- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView { + //和categoryView的item数量一致 + return self.categoryView.titles.count; +} + +- (id)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index { + KBShopItemVC *list = [[KBShopItemVC alloc] init]; + list.title = self.titles[index]; + list.isNeedHeader = self.isNeedHeader; + list.isNeedFooter = self.isNeedFooter; + if (index == 0) { + list.dataSource = @[@"橡胶火箭", @"橡胶火箭炮", @"橡胶机关枪", @"橡胶子弹", @"橡胶攻城炮", @"橡胶象枪", @"橡胶象枪乱打", @"橡胶灰熊铳", @"橡胶雷神象枪", @"橡胶猿王枪", @"橡胶犀·榴弹炮", @"橡胶大蛇炮", @"橡胶火箭", @"橡胶火箭炮", @"橡胶机关枪", @"橡胶子弹", @"橡胶攻城炮", @"橡胶象枪", @"橡胶象枪乱打", @"橡胶灰熊铳", @"橡胶雷神象枪", @"橡胶猿王枪", @"橡胶犀·榴弹炮", @"橡胶大蛇炮"].mutableCopy; + }else if (index == 1) { + list.dataSource = @[@"吃烤肉", @"吃鸡腿肉", @"吃牛肉", @"各种肉"].mutableCopy; + }else { + list.dataSource = @[@"【剑士】罗罗诺亚·索隆", @"【航海士】娜美", @"【狙击手】乌索普", @"【厨师】香吉士", @"【船医】托尼托尼·乔巴", @"【船匠】 弗兰奇", @"【音乐家】布鲁克", @"【考古学家】妮可·罗宾"].mutableCopy; + } + return list; +} + +#pragma mark - JXCategoryViewDelegate + +- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index { + self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0); +} + +#pragma mark - JXPagerMainTableViewGestureDelegate + +- (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + //禁止categoryView左右滑动的时候,上下和左右都可以滚动 + if (otherGestureRecognizer == self.categoryView.collectionView.panGestureRecognizer) { + return NO; + } + return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]; +} + + +- (void)pagerView:(JXPagerView *)pagerView mainTableViewDidScroll:(UIScrollView *)scrollView { + CGFloat thresholdDistance = JXTableHeaderViewHeight; + CGFloat percent = scrollView.contentOffset.y/thresholdDistance; + percent = MAX(0, MIN(1, percent)); + self.naviBGView.alpha = percent; +} + +@end diff --git a/keyBoard/Class/Vender/UICollectionViewLeftAlignedLayout/UICollectionViewLeftAlignedLayout.h b/keyBoard/Class/Vender/UICollectionViewLeftAlignedLayout/UICollectionViewLeftAlignedLayout.h new file mode 100644 index 0000000..b51c8d3 --- /dev/null +++ b/keyBoard/Class/Vender/UICollectionViewLeftAlignedLayout/UICollectionViewLeftAlignedLayout.h @@ -0,0 +1,39 @@ +// Copyright (c) 2014-2023 Giovanni Lodi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +/** + * Simple UICollectionViewFlowLayout that aligns the cells to the left rather than justify them + * + * Based on http://stackoverflow.com/questions/13017257/how-do-you-determine-spacing-between-cells-in-uicollectionview-flowlayout + */ + +#import + +@interface UICollectionViewLeftAlignedLayout : UICollectionViewFlowLayout + +@end + +/** + * Just a convenience protocol to keep things consistent. + * Someone could find it confusing for a delegate object to conform to UICollectionViewDelegateFlowLayout + * while using UICollectionViewLeftAlignedLayout. + */ +@protocol UICollectionViewDelegateLeftAlignedLayout + +@end diff --git a/keyBoard/Class/Vender/UICollectionViewLeftAlignedLayout/UICollectionViewLeftAlignedLayout.m b/keyBoard/Class/Vender/UICollectionViewLeftAlignedLayout/UICollectionViewLeftAlignedLayout.m new file mode 100644 index 0000000..a234789 --- /dev/null +++ b/keyBoard/Class/Vender/UICollectionViewLeftAlignedLayout/UICollectionViewLeftAlignedLayout.m @@ -0,0 +1,116 @@ +// Copyright (c) 2014-2023 Giovanni Lodi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#import "UICollectionViewLeftAlignedLayout.h" + +@interface UICollectionViewLayoutAttributes (LeftAligned) + +- (void)leftAlignFrameWithSectionInset:(UIEdgeInsets)sectionInset; + +@end + +@implementation UICollectionViewLayoutAttributes (LeftAligned) + +- (void)leftAlignFrameWithSectionInset:(UIEdgeInsets)sectionInset +{ + CGRect frame = self.frame; + frame.origin.x = sectionInset.left; + self.frame = frame; +} + +@end + +#pragma mark - + +@implementation UICollectionViewLeftAlignedLayout + +#pragma mark - UICollectionViewLayout + +- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { + NSArray *originalAttributes = [super layoutAttributesForElementsInRect:rect]; + NSMutableArray *updatedAttributes = [NSMutableArray arrayWithArray:originalAttributes]; + for (UICollectionViewLayoutAttributes *attributes in originalAttributes) { + if (!attributes.representedElementKind) { + NSUInteger index = [updatedAttributes indexOfObject:attributes]; + updatedAttributes[index] = [self layoutAttributesForItemAtIndexPath:attributes.indexPath]; + } + } + + return updatedAttributes; +} + +- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewLayoutAttributes* currentItemAttributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy]; + UIEdgeInsets sectionInset = [self evaluatedSectionInsetForItemAtIndex:indexPath.section]; + + BOOL isFirstItemInSection = indexPath.item == 0; + CGFloat layoutWidth = CGRectGetWidth(self.collectionView.frame) - sectionInset.left - sectionInset.right; + + if (isFirstItemInSection) { + [currentItemAttributes leftAlignFrameWithSectionInset:sectionInset]; + return currentItemAttributes; + } + + NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section]; + CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame; + CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width; + CGRect currentFrame = currentItemAttributes.frame; + CGRect strecthedCurrentFrame = CGRectMake(sectionInset.left, + currentFrame.origin.y, + layoutWidth, + currentFrame.size.height); + // if the current frame, once left aligned to the left and stretched to the full collection view + // width intersects the previous frame then they are on the same line + BOOL isFirstItemInRow = !CGRectIntersectsRect(previousFrame, strecthedCurrentFrame); + + if (isFirstItemInRow) { + // make sure the first item on a line is left aligned + [currentItemAttributes leftAlignFrameWithSectionInset:sectionInset]; + return currentItemAttributes; + } + + CGRect frame = currentItemAttributes.frame; + frame.origin.x = previousFrameRightPoint + [self evaluatedMinimumInteritemSpacingForSectionAtIndex:indexPath.section]; + currentItemAttributes.frame = frame; + return currentItemAttributes; +} + +- (CGFloat)evaluatedMinimumInteritemSpacingForSectionAtIndex:(NSInteger)sectionIndex +{ + if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)]) { + id delegate = (id)self.collectionView.delegate; + + return [delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:sectionIndex]; + } else { + return self.minimumInteritemSpacing; + } +} + +- (UIEdgeInsets)evaluatedSectionInsetForItemAtIndex:(NSInteger)index +{ + if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) { + id delegate = (id)self.collectionView.delegate; + + return [delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:index]; + } else { + return self.sectionInset; + } +} + +@end diff --git a/keyBoard/Info.plist b/keyBoard/Info.plist index 0bbab3d..c798311 100644 --- a/keyBoard/Info.plist +++ b/keyBoard/Info.plist @@ -5,11 +5,13 @@ CFBundleURLTypes + CFBundleTypeRole + Editor CFBundleURLName com.loveKey.nyx.keyboard CFBundleURLSchemes - kbkeyboard + kbkeyboardAppExtension diff --git a/keyBoard/KeyBoardPrefixHeader.pch b/keyBoard/KeyBoardPrefixHeader.pch index b8caeb7..7a7c720 100644 --- a/keyBoard/KeyBoardPrefixHeader.pch +++ b/keyBoard/KeyBoardPrefixHeader.pch @@ -25,17 +25,23 @@ /// 项目 +#import "UIView+KBShadow.h" +#import "UIImage+KBColor.h" +#import "UIColor+Extension.h" + #import "UIViewController+Extension.h" #import "BaseNavigationController.h" #import "BaseTableView.h" #import "BaseCell.h" +#import "BaseViewController.h" + #import "KBLocalizationManager.h" // 全局多语言封装 //-----------------------------------------------宏定义全局----------------------------------------------------------/ // 通用链接(Universal Links)统一配置 // 仅需修改这里的域名/前缀,工程内所有使用 UL 的地方都会同步。 -#define KB_UL_BASE @"https://your.domain/ul" // 替换为你的真实域名与前缀路径 +#define KB_UL_BASE @"https://app.tknb.net/ul" // 与 Associated Domains 一致 #define KB_UL_LOGIN KB_UL_BASE @"/login" #define KB_UL_SETTINGS KB_UL_BASE @"/settings" @@ -49,6 +55,9 @@ #define KB_NAVBAR_BASE_HEIGHT 44.0 #define KB_TABBAR_BASE_HEIGHT 49.0 +#define COLOR_WITH_RGB(R,G,B,A) [UIColor colorWithRed:R green:G blue:B alpha:A] + + // 当前 KeyWindow(iOS 13 场景化兼容) static inline UIWindow *KB_KeyWindow(void) { UIWindow *window = nil; @@ -99,4 +108,77 @@ static inline CGFloat KB_StatusBarHeight(void) { #define KB_IS_IPHONEX_SERIES (KB_SafeAreaBottom() > 0.0) + + +// --- 设备特性:是否为带刘海机型(iPhone X 及以后异形屏)--- +// 说明:在 iPhone 12 等机型底部会有 34px 安全区,这里通过安全区来判断是否为“刘海屏”。 +// 注意:使用到 UIKit,这里自行引入,避免依赖 PCH 的包含顺序。 +#import +static inline BOOL KBDeviceHasNotchRuntime(void) { + if (@available(iOS 11.0, *)) { + UIWindow *window = nil; + if (@available(iOS 13.0, *)) { + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { + UIWindowScene *ws = (UIWindowScene *)scene; + for (UIWindow *w in ws.windows) { if (w.isKeyWindow) { window = w; break; } } + if (window) { break; } + } + } + if (!window) { window = UIApplication.sharedApplication.windows.firstObject; } + } else { + window = UIApplication.sharedApplication.keyWindow; + } + return window.safeAreaInsets.bottom > 0.0; + } + return NO; +} + +#ifndef KB_DEVICE_HAS_NOTCH +#define KB_DEVICE_HAS_NOTCH (KBDeviceHasNotchRuntime()) +#endif + +// --- 获取当前可用的 UINavigationController --- +// 说明: +// 1. 优先取最顶层可见 VC(见 UIViewController+Extension),再解析其所在的导航容器; +// 2. 兼容被 UITabBarController 包裹、直接为 UINavigationController、或普通 VC 嵌套等场景; +// 3. 若无法获取,返回 nil。 +static inline __kindof UINavigationController *KB_CurrentNavigationController(void) { + UIViewController *top = [UIViewController kb_topMostViewController]; + if (!top) { + UIWindow *w = KB_KeyWindow(); + top = w.rootViewController; + } + if (!top) return nil; + + // 直接就是导航控制器 + if ([top isKindOfClass:[UINavigationController class]]) { + return (UINavigationController *)top; + } + // 顶层是 TabBar,取选中的子控制器 + if ([top isKindOfClass:[UITabBarController class]]) { + UITabBarController *tab = (UITabBarController *)top; + UIViewController *sel = tab.selectedViewController ?: tab.viewControllers.firstObject; + if ([sel isKindOfClass:[UINavigationController class]]) return (UINavigationController *)sel; + return sel.navigationController ?: nil; + } + // 普通 VC,取其所属导航 + if (top.navigationController) return top.navigationController; + + // 兜底:尝试从 root 解析 + UIViewController *root = KB_KeyWindow().rootViewController; + if ([root isKindOfClass:[UINavigationController class]]) return (UINavigationController *)root; + if ([root isKindOfClass:[UITabBarController class]]) { + UIViewController *sel = ((UITabBarController *)root).selectedViewController; + if ([sel isKindOfClass:[UINavigationController class]]) return (UINavigationController *)sel; + return sel.navigationController ?: nil; + } + return nil; +} + +// 简便宏:直接当做属性来用,例如:`[KB_CURRENT_NAV pushViewController:vc animated:YES];` +#ifndef KB_CURRENT_NAV +#define KB_CURRENT_NAV (KB_CurrentNavigationController()) +#endif + #endif /* KeyBoardPrefixHeader_pch */ diff --git a/keyBoard/Shared/KBConfig.h b/keyBoard/Shared/KBConfig.h index b9cc820..88ccf09 100644 --- a/keyBoard/Shared/KBConfig.h +++ b/keyBoard/Shared/KBConfig.h @@ -31,3 +31,31 @@ #ifndef KB_KEYCHAIN_ACCESS_GROUP #define KB_KEYCHAIN_ACCESS_GROUP @"TN6HHV45BB.com.loveKey.nyx.shared" #endif + +// --- 设备特性:是否为带刘海机型(iPhone X 及以后异形屏)--- +// 说明:在 iPhone 12 等机型底部会有 34px 安全区,这里通过安全区来判断是否为“刘海屏”。 +// 注意:使用到 UIKit,这里自行引入,避免依赖 PCH 的包含顺序。 +#import +static inline BOOL KBDeviceHasNotchRuntime(void) { + if (@available(iOS 11.0, *)) { + UIWindow *window = nil; + if (@available(iOS 13.0, *)) { + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { + UIWindowScene *ws = (UIWindowScene *)scene; + for (UIWindow *w in ws.windows) { if (w.isKeyWindow) { window = w; break; } } + if (window) { break; } + } + } + if (!window) { window = UIApplication.sharedApplication.windows.firstObject; } + } else { + window = UIApplication.sharedApplication.keyWindow; + } + return window.safeAreaInsets.bottom > 0.0; + } + return NO; +} + +#ifndef KB_DEVICE_HAS_NOTCH +#define KB_DEVICE_HAS_NOTCH (KBDeviceHasNotchRuntime()) +#endif diff --git a/keyBoard/keyBoard.entitlements b/keyBoard/keyBoard.entitlements index 34d0a44..eabbbc8 100644 --- a/keyBoard/keyBoard.entitlements +++ b/keyBoard/keyBoard.entitlements @@ -6,6 +6,10 @@ Default + com.apple.developer.associated-domains + + applinks:app.tknb.net + keychain-access-groups $(AppIdentifierPrefix)com.loveKey.nyx.shared